Здравствуйте, госпада. Столкнулся со странностью: Есть сервер, который прнимает GET-запросы. http://m-ark.kps-dev.com/restws/session/token/Authorization:Basic:cmVzdF91c3I6amd0aGZuamg= Ваш браузер должен, пройдя по этой ссылке получить некий код авторизации. Пробую отправить тот же GET-запрос через SIM900. Использую такую "конструкцию" в надежде получить тот же ответ от сервера: numdata=inet.httpGET("www.m-ark.kps-dev.com", 80, "/restws/session/token/Authorization:Basic:cmVzdF91c3I6amd0aGZuamg=", msg, 50); Но сервер отвечает ошибками 400 или 403. Связь с сервером есть, но запрос серверу не нравится. Что же не нравится Ардуине? Спасибо. Код прилагаю. Код (Text): #include "SIM900.h" #include <SoftwareSerial.h> #include "inetGSM.h" //#include "sms.h" //#include "call.h" //To change pins for Software Serial, use the two lines in GSM.cpp. //GSM Shield for Arduino //www.open-electronics.org //this code is based on the example of Arduino Labs. //Simple sketch to start a connection as client. InetGSM inet; //CallGSM call; //SMSGSM sms; char msg[50]; int numdata; char inSerial[50]; int i=0; boolean started=false; void setup() {digitalWrite(9, HIGH); //Serial connection. Serial.begin(9600); Serial.println("GSM Shield testing."); //Start configuration of shield with baudrate. //For http uses is raccomanded to use 4800 or slower. if (gsm.begin(2400)){ Serial.println("\nstatus=READY"); started=true; } else digitalWrite(9, HIGH); Serial.println("\nstatus=IDLE"); if(started){ //GPRS attach, put in order APN, username and password. //If no needed auth let them blank. if (inet.attachGPRS("internet.beeline.ru", "", "")) Serial.println("status=ATTACHED"); else digitalWrite(9, HIGH); Serial.println("status=ERROR"); delay(1000); //Read IP address. gsm.SimpleWriteln("AT+CIFSR"); delay(5000); //Read until serial buffer is emapty. gsm.WhileSimpleRead(); //TCP Client GET, send a GET request to the server and //save the reply. numdata=inet.httpGET("www.m-ark.kps-dev.com", 80, "/restws/session/token/Authorization: base: cmVzdF91c3I6amd0aGZuamg=", msg, 50); //Print the results. Serial.println("\nNumber of data received:"); Serial.println(numdata); Serial.println("\nData received:"); Serial.println(msg); } }; void loop() { //Read for new byte on serial hardware, //and write them on NewSoftSerial. serialhwread(); //Read for new byte on NewSoftSerial. serialswread(); }; void serialhwread(){ i=0; if (Serial.available() > 0){ while (Serial.available() > 0) { inSerial[i]=(Serial.read()); delay(10); i++; } inSerial[i]='\0'; if(!strcmp(inSerial,"/END")){ Serial.println("_"); inSerial[0]=0x1a; inSerial[1]='\0'; gsm.SimpleWriteln(inSerial); } //Send a saved AT command using serial port. if(!strcmp(inSerial,"TEST")){ Serial.println("SIGNAL QUALITY"); gsm.SimpleWriteln("AT+CSQ"); } //Read last message saved. if(!strcmp(inSerial,"MSG")){ Serial.println(msg); } else{ Serial.println(inSerial); gsm.SimpleWriteln(inSerial); } inSerial[0]='\0'; } } void serialswread(){ gsm.SimpleRead(); }
Мне и в браузере вернуло "Доступ запрещён" со статусом 403. Вероятно, нужны какие-то куки или иные заголовки, имеющиеся в Вашей сессии. (Проверьте, что покажет в другом браузере или через "приватное окно".) Или открыто для определённого диапазона IP.
Да, Fire Fox 37 отозвался ошибкой 403. А Yandex и Chome - прекрасно отвечают. Надо подумать над сервером. А кроме inet.httpGET, другие способы отправить get-запрос существуют?
Отправку запросов из Arduino я не изучал. При отладке своих Web-сервисов на низком уровне использую программу netcat (nc). Из браузеров если стабильно разный результат при пустой сессии -- причина может быть в заголовке UserAgent. Однако у меня и из Chrome не открылось. Сервер Вы сами писали? Предварительной авторизации с использованием Cookie точно нет? Если из "нового окна в режиме инкогнито" будет ошибка -- нехватает какой-то авторизации. Если нет -- у сервера какие-то нестандартные (на мой взгляд) требования к заголовкам (UserAgent или чему-то ещё). В общем, анализируйте успешно отправленный запрос с помощью Wireshark или встроенных средств браузера, сравнивайте с отклонёнными. Если причина только в UserAgent -- то хорошо (хотя использовать его для авторизации -- не лучший выбор). Если замешаны Cookie -- то сложнее: если просто скомпрометировать их на клиенте (в ардуине), они могут устареть на сервере. Могут участвовать и другие заголовки.
История получила продолжение: оказывает Ардуина не умеет слать заголовки (Header) в GET и POST-запросах и нужно на более низком уровне это реализовывать. Здесь об этом заметка http://stackoverflow.com/questions/...ing-arduino-and-gsm-shield-and-parse-rest-api Жаль у меня не получается даже комплирование пройти, что-то компилятору не нравтся. Кто может проверит этот код? Буду признателен, если подскажете, как пройти компилироване.
Иду по следу.... подскажите, как скачать вот эту библиотеку? Какие-то SVN... https://code.google.com/p/gsm-shield...hes/GSMSHIELD/ Это то, что поможет решить проблему.
SVN -- древняя система контроля версий (а code.google.com -- хостинг исходников, который скоро закроется ). На данный момент лучший способ скачать с code.google.com -- экспортировать на GitHub.com, они выставили кнопку на видном месте. Я экспортировал в свой аккаунт на Гитхабе (удивительно, но быть владельцем проекта на code.google.com для этого не потебовалось), теперь можете открыть проект там https://github.com/Kopilov/gsm-shield-arduino и нажать кнопку "Download ZIP" справа. Или скачать средствами Git Git (http://git-scm.com/) -- современная система контроля версий с продвинутыми возможностями. Если будете дальше заниматься программированием всерьёз (особенно в команде) -- рекомендую освоить, пригодится. Пара хороших руководств: http://githowto.com/ru http://www-cs-students.stanford.edu/~blynn/gitmagic/intl/ru/
Спасибо, но какие-то чудеса: мне нужен файл inetGSM.ccp он тут https://code.google.com/p/gsm-shiel...branches/CompatibleVerIDE100/inetGSM.cpp?r=71 с кодом вида: intInetGSM::httpPOST(constchar* server,int port,constchar* path,constchar* parameters,char* result,int resultlength) strcpy(_buffer,"POST "); strcat(_buffer,path); strcat(_buffer," HTTP/1.0\nHost: "); strcat(_buffer,server); //strcat(_buffer,"\n\rUser-Agent: Mozilla/4.0\n\rContent-Length: "); strcat(_buffer,"\nContent-Length: "); itoa(strlen(parameters),itoaBuffer,10); strcat(_buffer,itoaBuffer); strcat(_buffer,"\n\n"); strcat(_buffer,parameters); strcat(_buffer,"\n\n"); потому, что в примере именно в таком виде: strcat(_buffer," HTTP/1.0\nHost: "); пишется код. А в том, что вы и я качаем синтаксис в inetGSM.ccp для другой: int InetGSM::httpPOST(const char* server, int port, const char* path, const char* parameters, char* result, int resultlength) } } if(!connected) return 0; gsm.SimpleWrite("POST "); gsm.SimpleWrite(path); gsm.SimpleWrite(" HTTP/1.1\nHost: "); gsm.SimpleWrite(server); gsm.SimpleWrite("\n"); gsm.SimpleWrite("User-Agent: Arduino\n"); gsm.SimpleWrite("Content-Type: application/x-www-form-urlencoded\n");
Это ветка CompatibleVerIDE100, а в предыдущем посте Вы дали ссылку на GSMSHIELD (сравните URL) -- я её наружу и выставил. Можете выбрать желаемую ветку в веб-интерфейсе GitHub (выпадающий список слева у зелёной кнопки), можете скачать весь репозиторий (установить git, выполнить команду git clone https://github.com/Kopilov/gsm-shield-arduino) и потрошить локально.
Я полнейший чайник, не могу архивом скачать нормальным. Не могли бы его в отдельный архивчик вынести? Или мне на почту скинуть или сюда? Спасибо.
Уважаемый, какая-то мистика. Ну нету там CompatibleVerIDE100/ Ну не могу найти. Выручите, пожалуйста.
Да, действительно. И, что интересно, если нажать ссылку "branches" в code.google.com из вашего первого примера -- выводится один список веток (примерно такой же, какой экспортировался в Гитхаб), а если из второго -- то другой, всего две ветки (CompatibleVerIDE100 и CompatibleVer), хотя проект, вроде, этот же. Может, это какие-нибудь скрытые ветки. Code.google.com я никогда не использовал, его тонкостей не знаю. Содержимое ветки SIM900IDE022 прикрепил, на всякий случай вместе с репозиторием (каталог .git внутри).
Кажется я начинаю понимать суть. Серверу не нравится обращение к нему, это можно исправить переписав в библиотеке файл inetGSM.cpp параметры GET или POST- запросов. А если мы создаём новый вид запроса, например inet.NewhttpPost( ), тогда не забываем его прописать и в inetGSM.h , по аналогии с уже существующими там httpGET, httpPOST - запросам. Запрос должен понравиться серверу. В таком виде нужно с сервером изъясняться, в одной из стандартных библиотек. if(!connected) return 0; gsm.SimpleWrite("POST "); gsm.SimpleWrite(path); gsm.SimpleWrite(" HTTP/1.1\nHost: "); gsm.SimpleWrite(server); gsm.SimpleWrite("\n"); gsm.SimpleWrite("User-Agent: Arduino\n"); gsm.SimpleWrite("Content-Type: application/x-www-form-urlencoded\n"); Вопрос вот какой: есть ли какие-то тестовые серверы, для которых известны формы POST-запроса, где можно как раз потестить это самое обращение к серверу? Спасибо
Товарищ Копилов мне крупно помог. Теперь проблемка встала на этапе компилирования. Пишу такую строчку с POST-запросом: numdata=inet.httpPOST("www.mysite.com", 80, "/my ", "{"title":"temp38", "temperature": "38", "latitude":"44.39 ","longitude":"33.79", "device_id":"28"}",msg,50); Не хочет компилировать из-за параметров в { }. Выдаёт ошибку: This report would have more information with "Show verbose output during compilation" enabled in File > Preferences. Arduino: 1.0.6 (Windows NT (unknown)), Board: "Arduino Uno" GPRS_mar31a.ino: In function 'void setup()': GPRS_mar31a:58: error: expected `)' before 'title' заменяю параметры "{"title":"temp38", "temperature": "38", "latitude":"44.39 ","longitude":"33.79", "device_id":"28"}" на строчку из найденного примера (http://forum.arduino.cc/index.php?topic=223171.0) : "testas=asd" Получаю: numdata=inet.httpPOST("www.mysite.com", 80, "/my ", "testas=asd",msg,50); И всё компилируется! Так что компилятору не нравится в этих параметрах ? "{"title":"temp38", "temperature": "38", "latitude":"44.39 ","longitude":"33.79", "device_id":"28"}" Чешу репу...