#ifndef BLINKER_HTTP_AIR202_H #define BLINKER_HTTP_AIR202_H #if ARDUINO >= 100 #include <Arduino.h> #else #include <WProgram.h> #endif // #include "Adapters/BlinkerSerialM QTT.h" #include "../Blinker/BlinkerATMaster.h" #include "../Blinker/BlinkerConfig.h" #include "../Blinker/BlinkerDebug.h" #include "../Blinker/BlinkerStream.h" #include "../Blinker/BlinkerUtility.h" // #if defined(ESP32) // #include <HardwareSerial.h> // HardwareSerial *HSerial_HTTP; // #else // #include <SoftwareSerial.h> // SoftwareSerial *SSerial_HTTP; // #endif #define BLINKER_HTTP_AIR202_DEFAULT_TIMEOUT 5000UL #define BLINKER_HTTP_AIR202_DATA_BUFFER_SIZE 1024 enum air202_http_status_t { air202_init, air202_init_success, air202_ver_check, air202_ver_check_success, air202_cgtt, air202_cgtt_resp, air202_cgtt_success, air202_spbar_1, air202_spbar_1_success, air202_spbar_2, air202_spbar_2_success, air202_http_init, air202_http_init_success, air202_http_init_failed, air202_http_para_set, air202_http_para_set_success, air202_http_para_set_failed, air202_http_start, air202_http_start_success, air202_http_start_failed, air202_http_data_set, air202_http_data_set_success, air202_http_data_set_failed, air202_http_data_post, air202_http_data_post_success, air202_http_data_post_failed, air202_http_upload_success, air202_http_upload_failed, air202_http_read_response, air202_http_read_success, air202_http_read_failed, air202_http_read_paylaod, air202_http_end, air202_http_end_failed, air202_http_end_success }; enum air202_status_sap_t { air202_sap_cgtt_state_ver_check, air202_sap_cgtt_state_ver_check_success, air202_sap_cgtt_state, air202_sap_cgtt_state_resp, air202_sap_cgtt_state_success, air202_sap_sapbar_pdp_REQ, air202_sap_sapbar_pdp_success, air202_sap_sapbar_pdp_failed, air202_sap_sapbar_apn_REQ, air202_sap_sapbar_apn_success, air202_sap_sapbar_apn_failed, air202_sap_sapbar_save_REQ, air202_sap_sapbar_save_success, air202_sap_sapbar_save_failed, air202_sap_sapbar_fresh_REQ, air202_sap_sapbar_fresh_success, air202_sap_sapbar_fresh_failed, }; class BlinkerHTTPAIR202 { public : BlinkerHTTPAIR202(Stream& s, bool isHardware, blinker_callback_t func) { stream = &s; isHWS = isHardware; listenFunc = func; } ~BlinkerHTTPAIR202() { flush(); } void streamPrint(const String & s) { // stream->flush(); BLINKER_LOG_ALL(s); stream->println(s); } int checkCGTT() { uint32_t http_time = millis(); air202_http_status_t http_status = air202_init; streamPrint(BLINKER_CMD_AT); while(millis() - http_time < _httpTimeout) { if (available()) { if (strcmp(streamData, BLINKER_CMD_OK) == 0) { BLINKER_LOG_ALL(BLINKER_F("air202_init_success")); http_status = air202_init_success; break; } } } if (http_status != air202_init_success) return false; streamPrint(BLINKER_CMD_CGMMR_REQ); http_status = air202_ver_check; while(millis() - http_time < _httpTimeout) { if (available()) { if (strcmp(streamData, BLINKER_CMD_CGMMR_RESP) == 0) { BLINKER_LOG_ALL(BLINKER_F("air202_ver_check_success")); http_status = air202_ver_check_success; break; } } } if (http_status != air202_ver_check_success) return false; streamPrint(BLINKER_CMD_CGQTT_REQ); http_status = air202_cgtt; while(millis() - http_time < _httpTimeout) { if (available()) { _masterAT = new BlinkerMasterAT(); _masterAT->update(STRING_format(streamData)); if (_masterAT->getState() != AT_M_NONE && _masterAT->reqName() == BLINKER_CMD_CGATT && _masterAT->getParam(0).toInt() == 1) { BLINKER_LOG_ALL(BLINKER_F("air202_cgtt_resp")); http_status = air202_cgtt_resp; } free(_masterAT); break; } } if (http_status != air202_cgtt_resp) return false; while(millis() - http_time < _httpTimeout) { if (available()) { if (strcmp(streamData, BLINKER_CMD_OK) == 0) { BLINKER_LOG_ALL(BLINKER_F("air202_cgtt_success")); http_status = air202_cgtt_success; break; } } } if (http_status != air202_cgtt_success) return false; // stream->println(BLINKER_CMD_CGQTT_REQ); // http_status = air202_cgtt; } bool begin(String host, String uri) { _host = host; _uri = uri; } void setTimeout(uint16_t timeout) { _httpTimeout = timeout; } bool GET() { // streamPrint(STRING_format(BLINKER_CMD_MDISCONNECT_REQ)); // uint32_t mqtt_time = millis(); // uint8_t status_get = 0; // while(millis() - mqtt_time < _httpTimeout) // { // if (available()) // { // BLINKER_LOG_ALL(BLINKER_F("== disconnect available ==")); // if (strcmp(streamData, BLINKER_CMD_CONNACK_OK) == 0) // { // BLINKER_LOG_ALL(BLINKER_F("mqtt disconnect")); // // return true; // break; // } // } // } // streamPrint(STRING_format(BLINKER_CMD_MIPCLOSE_REQ)); // mqtt_time = millis(); // while(millis() - mqtt_time < _httpTimeout) // { // if (available()) // { // BLINKER_LOG_ALL(BLINKER_F("== disconnect available ==")); // if (strcmp(streamData, BLINKER_CMD_CONNACK_OK) == 0) // { // BLINKER_LOG_ALL(BLINKER_F("mqtt disconnect")); // // return true; // break; // } // } // } // streamPrint(STRING_format(BLINKER_CMD_CIPSHUT_REQ)); // mqtt_time = millis(); // while(millis() - mqtt_time < _httpTimeout) // { // if (available()) // { // BLINKER_LOG_ALL(BLINKER_F("== disconnect available ==")); // if (strcmp(streamData, BLINKER_CMD_CONNACK_OK) == 0) // { // BLINKER_LOG_ALL(BLINKER_F("mqtt disconnect")); // return true; // // break; // } // } // } streamPrint(BLINKER_CMD_HTTPINIT_REQ); uint32_t http_time = millis(); air202_http_status_t http_status = air202_http_init; while(millis() - http_time < _httpTimeout) { if (available()) { if (strcmp(streamData, BLINKER_CMD_OK) == 0) { BLINKER_LOG_ALL(BLINKER_F("air202_http_init_success")); http_status = air202_http_init_success; break; } } } if (http_status != air202_http_init_success) { BLINKER_LOG_ALL(BLINKER_F("air202_http_init_failed")); return false; } streamPrint(STRING_format(BLINKER_CMD_HTTPPARA_REQ) + "=\"CID\",1"); http_status = air202_http_para_set; http_time = millis(); while(millis() - http_time < _httpTimeout) { if (available()) { if (strcmp(streamData, BLINKER_CMD_OK) == 0) { BLINKER_LOG_ALL(BLINKER_F("air202_http_para_set_success 1")); http_status = air202_http_para_set_success; break; } } } if (http_status != air202_http_para_set_success) return false; streamPrint(STRING_format(BLINKER_CMD_HTTPPARA_REQ) + \ "=\"URL\",\"" + _host + _uri + "\""); http_status = air202_http_para_set; http_time = millis(); while(millis() - http_time < _httpTimeout*2) { if (available()) { if (strcmp(streamData, BLINKER_CMD_OK) == 0) { BLINKER_LOG_ALL(BLINKER_F("air202_http_para_set_success 2")); http_status = air202_http_para_set_success; break; } else if (strcmp(streamData, BLINKER_CMD_ERROR) == 0) { BLINKER_LOG_ALL(BLINKER_F("air202_http_para_set_failed 2")); // streamPrint("AT+CPOWD"); break; } } } // http_status = air202_http_para_set_success;// TBD if (http_status != air202_http_para_set_success) { // streamPrint(STRING_format(BLINKER_CMD_HTTPERM_REQ)); // streamPrint("AT+CPOWD"); return false; } streamPrint(STRING_format(BLINKER_CMD_HTTPACTION_REQ) + "=0"); http_status = air202_http_start; http_time = millis(); while(millis() - http_time < _httpTimeout) { if (available()) { if (strcmp(streamData, BLINKER_CMD_OK) == 0) { BLINKER_LOG_ALL(BLINKER_F("air202_http_start_success")); http_status = air202_http_start_success; break; } else if (strcmp(streamData, BLINKER_CMD_ERROR) == 0) { streamPrint(STRING_format(BLINKER_CMD_HTTPREAD_REQ)); ::delay(500); streamPrint(STRING_format(BLINKER_CMD_HTTPERM_REQ)); ::delay(500); break; } } } if (http_status != air202_http_start_success) { streamPrint(STRING_format(BLINKER_CMD_HTTPERM_REQ)); return false; } http_time = millis(); while(millis() - http_time < _httpTimeout*10) { if (available()) { _masterAT = new BlinkerMasterAT(); _masterAT->update(STRING_format(streamData)); if (_masterAT->getState() != AT_M_NONE && _masterAT->reqName() == BLINKER_CMD_HTTPACTION) { BLINKER_LOG_ALL(BLINKER_F("air202_http_upload_success")); http_status = air202_http_upload_success; free(_masterAT); break; } free(_masterAT); // break; } } // if (http_status != air202_http_upload_success) return false; streamPrint(STRING_format(BLINKER_CMD_HTTPREAD_REQ)); http_status = air202_http_read_response; http_time = millis(); while(millis() - http_time < _httpTimeout) { if (available()) { _masterAT = new BlinkerMasterAT(); _masterAT->update(STRING_format(streamData)); if (_masterAT->getState() != AT_M_NONE && _masterAT->reqName() == BLINKER_CMD_HTTPREAD) { BLINKER_LOG_ALL(BLINKER_F("air202_http_read_success")); http_status = air202_http_read_success; free(_masterAT); break; } free(_masterAT); // break; } } if (http_status != air202_http_read_success) return false; http_time = millis(); while(millis() - http_time < _httpTimeout) { if (available()) { if (strcmp(streamData, BLINKER_CMD_OK) != 0) { // payload = streamData; if (isFreshPayload) free(payload); isFreshPayload = true; // char data_buff[1024] = { '\0' }; payload = (char*)malloc((strlen(streamData) + 1)*sizeof(char)); strcpy(payload, streamData); BLINKER_LOG_ALL(BLINKER_F("payload: "), payload); } } } http_time = millis(); while(millis() - http_time < _httpTimeout) { if (available()) { if (strcmp(streamData, BLINKER_CMD_OK) == 0) { break; } } } streamPrint(STRING_format(BLINKER_CMD_HTTPERM_REQ)); http_status = air202_http_end; http_time = millis(); while(millis() - http_time < _httpTimeout) { if (available()) { if (strcmp(streamData, BLINKER_CMD_OK) == 0) { BLINKER_LOG_ALL(BLINKER_F("air202_http_end_success")); http_status = air202_http_end_success; return true; } } } if (http_status != air202_http_end_success) return false; } bool POST(String _msg, String _type, String _application) { uint32_t http_time = millis(); air202_http_status_t http_status = air202_http_init; streamPrint(BLINKER_CMD_HTTPINIT_REQ); while(millis() - http_time < _httpTimeout) { if (available()) { if (strcmp(streamData, BLINKER_CMD_OK) == 0) { BLINKER_LOG_ALL(BLINKER_F("air202_http_init_success")); http_status = air202_http_init_success; break; } } } if (http_status != air202_http_init_success) return false; streamPrint(STRING_format(BLINKER_CMD_HTTPPARA_REQ) + "=\"CID\",1"); http_status = air202_http_para_set; while(millis() - http_time < _httpTimeout) { if (available()) { if (strcmp(streamData, BLINKER_CMD_OK) == 0) { BLINKER_LOG_ALL(BLINKER_F("air202_http_para_set_success 1")); http_status = air202_http_para_set_success; break; } } } if (http_status != air202_http_para_set_success) return false; streamPrint(STRING_format(BLINKER_CMD_HTTPPARA_REQ) + \ "=\"URL\",\"" + _host + _uri + "\""); http_status = air202_http_para_set; http_time = millis(); while(millis() - http_time < _httpTimeout) { if (available()) { if (strcmp(streamData, BLINKER_CMD_OK) == 0) { BLINKER_LOG_ALL(BLINKER_F("air202_http_para_set_success 2")); http_status = air202_http_para_set_success; break; } } } if (http_status != air202_http_para_set_success) return false; // streamPrint(STRING_format(BLINKER_CMD_HTTPPARA_REQ) + \ // "=\"" + _type + "\",\"" + _application + "\""); // http_status = air202_http_para_set; // http_time = millis(); // while(millis() - http_time < _httpTimeout) // { // if (available()) // { // if (strcmp(streamData, BLINKER_CMD_OK) == 0) // { // BLINKER_LOG_ALL(BLINKER_F("air202_http_para_set_success 3")); // http_status = air202_http_para_set_success; // break; // } // } // } // if (http_status != air202_http_para_set_success) return false; // _msg.replace("\"", "\\22"); // _msg = "\"" + _msg + "\""; streamPrint(STRING_format(BLINKER_CMD_HTTPDATA_REQ) + \ "=" + _msg.length() + ",10000"); http_status = air202_http_data_set; http_time = millis(); while(millis() - http_time < _httpTimeout) { if (available()) { if (strcmp(streamData, BLINKER_CMD_DOWNLOAD) == 0) { BLINKER_LOG_ALL(BLINKER_F("air202_http_data_set_success")); http_status = air202_http_data_set_success; break; } } } if (http_status != air202_http_data_set_success) return false; streamPrint(_msg); http_status = air202_http_data_post; http_time = millis(); while(millis() - http_time < _httpTimeout) { if (available()) { if (strcmp(streamData, BLINKER_CMD_OK) == 0) { BLINKER_LOG_ALL(BLINKER_F("air202_http_data_post_success")); http_status = air202_http_data_post_success; break; } } } if (http_status != air202_http_data_post_success) return false; streamPrint(STRING_format(BLINKER_CMD_HTTPACTION_REQ) + "=1"); http_status = air202_http_start; http_time = millis(); while(millis() - http_time < _httpTimeout) { if (available()) { if (strcmp(streamData, BLINKER_CMD_OK) == 0) { BLINKER_LOG_ALL(BLINKER_F("air202_http_start_success")); http_status = air202_http_start_success; break; } } } if (http_status != air202_http_start_success) { streamPrint(STRING_format(BLINKER_CMD_HTTPERM_REQ)); return false; } http_time = millis(); while(millis() - http_time < _httpTimeout*2) { if (available()) { _masterAT = new BlinkerMasterAT(); _masterAT->update(STRING_format(streamData)); if (_masterAT->getState() != AT_M_NONE && _masterAT->reqName() == BLINKER_CMD_HTTPACTION) { BLINKER_LOG_ALL(BLINKER_F("air202_http_upload_success")); http_status = air202_http_upload_success; free(_masterAT); break; } free(_masterAT); // break; } } if (http_status != air202_http_upload_success) { streamPrint(STRING_format(BLINKER_CMD_HTTPERM_REQ)); return false; } streamPrint(STRING_format(BLINKER_CMD_HTTPREAD_REQ)); http_status = air202_http_read_response; http_time = millis(); while(millis() - http_time < _httpTimeout) { if (available()) { _masterAT = new BlinkerMasterAT(); _masterAT->update(STRING_format(streamData)); if (_masterAT->getState() != AT_M_NONE && _masterAT->reqName() == BLINKER_CMD_HTTPREAD) { BLINKER_LOG_ALL(BLINKER_F("air202_http_read_success, data len: "), _masterAT->getParam(0)); http_status = air202_http_read_success; free(_masterAT); break; } free(_masterAT); // break; } } if (http_status != air202_http_read_success) return false; http_time = millis(); while(millis() - http_time < _httpTimeout) { if (available()) { if (strcmp(streamData, BLINKER_CMD_OK) != 0) { // payload = streamData; if (isFreshPayload) free(payload); isFreshPayload = true; char data_buff[1024] = { '\0' }; payload = (char*)malloc((strlen(streamData) + 1)*sizeof(char)); strcpy(payload, streamData); BLINKER_LOG_ALL(BLINKER_F("payload: "), payload); } } } http_time = millis(); while(millis() - http_time < _httpTimeout) { if (available()) { if (strcmp(streamData, BLINKER_CMD_OK) == 0) { break; } } } streamPrint(STRING_format(BLINKER_CMD_HTTPERM_REQ)); http_status = air202_http_end; http_time = millis(); while(millis() - http_time < _httpTimeout) { if (available()) { if (strcmp(streamData, BLINKER_CMD_OK) == 0) { BLINKER_LOG_ALL(BLINKER_F("air202_http_end_success")); http_status = air202_http_end_success; break; } } } if (http_status != air202_http_end_success) return false; return true; } String getString() { return payload;//TBD } void flush() { if (isFreshPayload) free(payload); if (isFresh) free(streamData); } protected : class BlinkerMasterAT * _masterAT; Stream* stream; // String streamData; // char streamData[1024]; char* streamData; // String payload = ""; char* payload; bool isFreshPayload = false; bool isFresh = false; bool isHWS = false; String _host; String _uri; blinker_callback_t listenFunc = NULL; uint16_t _httpTimeout = BLINKER_HTTP_AIR202_DEFAULT_TIMEOUT; int timedRead() { int c; uint32_t _startMillis = millis(); do { c = stream->read(); if (c >= 0) return c; } while(millis() - _startMillis < 1000); return -1; } bool available() { yield(); if (!isHWS) { // #if defined(__AVR__) || defined(ESP8266) // if (!SSerial_HTTP->isListening()) // { // SSerial_HTTP->listen(); // ::delay(100); // } // #endif if (listenFunc) listenFunc(); } // char _data[BLINKER_HTTP_AIR202_DATA_BUFFER_SIZE];// = { '\0' }; // memset(_data, '\0', BLINKER_HTTP_AIR202_DATA_BUFFER_SIZE); // if (!isFresh) streamData = (char*)malloc(BLINKER_HTTP_AIR202_DATA_BUFFER_SIZE*sizeof(char)); // else memset(streamData, '\0', BLINKER_HTTP_AIR202_DATA_BUFFER_SIZE); if (stream->available()) { // strcpy(_data, stream->readStringUntil('\n').c_str()); String _data = stream->readStringUntil('\n'); BLINKER_LOG_ALL(BLINKER_F("handleSerial rs: "), _data, BLINKER_F(", len: "), _data.length()); // _data[strlen(_data) - 1] = '\0'; if (isFresh) { free(streamData); isFresh = false; } if (_data.length() <= 1) return false; streamData = (char*)malloc((_data.length() + 1)*sizeof(char)); strcpy(streamData, _data.c_str()); if (_data.length() > 0 && streamData[_data.length() - 1] == '\r') streamData[_data.length() - 1] = '\0'; isFresh = true; return true; // if (isFresh) free(streamData); // streamData = (char*)malloc(1*sizeof(char)); // // streamData = ""; // // memset(streamData, '\0', 1024); // // BLINKER_LOG_ALL(BLINKER_F("handleSerial rs: "), stream->readString()); // // strcpy(streamData, stream->readStringUntil('\n').c_str()); // // int16_t dNum = strlen(streamData); // // BLINKER_LOG_ALL(BLINKER_F("handleSerial rs: "), streamData, // // BLINKER_F(", dNum: "), dNum); // int16_t dNum = 0; // int c_d = timedRead(); // while (dNum < BLINKER_MAX_READ_SIZE && // c_d >=0 && c_d != '\n') // { // // if (c_d != '\r') // { // streamData[dNum] = (char)c_d; // dNum++; // streamData = (char*)realloc(streamData, (dNum+1)*sizeof(char)); // } // c_d = timedRead(); // } // // dNum++; // // // streamData = (char*)realloc(streamData, dNum*sizeof(char)); // // streamData[dNum-1] = '\0'; // // strcpy(streamData, stream->readStringUntil('\n').c_str()); // // int16_t dNum = strlen(streamData); // // streamData[dNum-1] = '\0'; // // stream->flush(); // // BLINKER_LOG_ALL(BLINKER_F("handleSerial: "), streamData, // // BLINKER_F(" , dNum: "), dNum); // // BLINKER_LOG_FreeHeap_ALL(); // if (dNum < BLINKER_MAX_READ_SIZE && dNum > 0) // { // // if (streamData[dNum - 1] == '\r') // streamData[dNum - 1] = '\0'; // BLINKER_LOG_ALL(BLINKER_F("handleSerial: "), streamData, // BLINKER_F(" , dNum: "), dNum); // isFresh = true; // return true; // } // else // { // return false; // } } else { return false; } } }; #endif