LOCAL void network_connect_cb(void *arg) { HTTP_REQUEST *request; switch(mConnectionState) { case CS_GETINFO: request = &mInfoRequest; dhdebug("Send info request..."); break; case CS_REGISTER: request = &mRegisterRequest; dhdebug("Send register request..."); break; case CS_POLL: request = &mPollRequest; dhdebug("Send poll request..."); break; default: dhdebug("ASSERT: networkConnectCb wrong state %d", mConnectionState); } int res; if( (res = espconn_send(&mDHConnector, request->data, request->len)) != ESPCONN_OK) { mConnectionState = CS_DISCONNECT; dhesperrors_espconn_result("network_connect_cb failed:", res); espconn_disconnect(&mDHConnector); } else { dhstatistic_add_bytes_sent(request->len); } }
void ICACHE_FLASH_ATTR dhdebug_dump(const char *data, unsigned int len) { if(len == 0) return; const unsigned char byte_per_line = 16; char textbuf[byte_per_line + 1]; char hexbuf[byte_per_line * 3 + 1]; char address[9] = "00000000"; int pos = 0; dhdebug("Dump at 0x%X, length %u", (unsigned int)data, len); do { byteToHex((pos / 0x1000000) & 0xFF, &address[0]); byteToHex((pos / 0x10000) & 0xFF, &address[2]); byteToHex((pos / 0x100) & 0xFF, &address[4]); byteToHex(pos & 0xFF, &address[6]); unsigned int i; for(i = 0; i < byte_per_line; i++) { if(pos < len) { char c = data[pos++]; byteToHex(c, &hexbuf[i * 3]); hexbuf[i * 3 + 2] = ' '; if(c < 0x20 || c >= 0x7F) textbuf[i] = '.'; else textbuf[i] = c; textbuf[i + 1] = 0; } else { hexbuf[i * 3] = ' '; hexbuf[i * 3 + 1] = ' '; hexbuf[i * 3 + 2] = ' '; } hexbuf[i * 3 + 3] = 0; } dhdebug("%s: %s %s", address, hexbuf, textbuf); } while (pos < len); }
UP_STATUS ICACHE_FLASH_ATTR uploadable_page_finish() { if(mBuffer == NULL) return UP_STATUS_WRONG_CALL; os_timer_disarm(&mFlashingTimer); ETS_INTR_LOCK(); // Mark data with null terminated char. If data takes whole available space, // there is no need in null terminated char. // At this point buffer should have at lest 1 free byte, since buffer // reaches maximum size before, it had to be written to flash. // If nothing was written, just report ok. SpiFlashOpResult res = SPI_FLASH_RESULT_OK; if(mBufferPos) { mBuffer[mBufferPos] = 0; mBufferPos++; res = flash_data(); } else if(mFlashingSector > UPLOADABLE_PAGE_START_SECTOR && mFlashingSector <= UPLOADABLE_PAGE_END_SECTOR) { res = write_zero_byte(mFlashingSector); } mBufferPos = 0; os_free(mBuffer); mBuffer = NULL; // force to recalc page size mPageLength = 0; ETS_INTR_UNLOCK(); if(res != SPI_FLASH_RESULT_OK) { dhdebug("Error while finishing flash page"); return UP_STATUS_INTERNAL_ERROR; } dhdebug("Flashing page has finished successfully"); return UP_STATUS_OK; }
void ICACHE_FLASH_ATTR dhesperrors_wifi_state(const char *descrption, uint8 reason) { char *errdescr = 0; switch(reason) { case EVENT_STAMODE_CONNECTED: errdescr = "STAMODE_CONNECTED"; break; case EVENT_STAMODE_DISCONNECTED: errdescr = "STAMODE_DISCONNECTED"; break; case EVENT_STAMODE_AUTHMODE_CHANGE: errdescr = "STAMODE_AUTHMODE_CHANGE"; break; case EVENT_STAMODE_GOT_IP: errdescr = "STAMODE_GOT_IP"; break; case EVENT_SOFTAPMODE_STACONNECTED: errdescr = "SOFTAPMODE_STACONNECTED"; break; case EVENT_SOFTAPMODE_STADISCONNECTED: errdescr = "SOFTAPMODE_STADISCONNECTED"; break; case EVENT_MAX: errdescr = "EVENT_MAX"; break; } if(errdescr) dhdebug("%s %s", descrption, errdescr); else dhdebug("%s %d", descrption, reason); }
int ICACHE_FLASH_ATTR dhsender_queue_take(HTTP_REQUEST *out, unsigned int *is_notification) { if(mQueueTakePos < 0) return 0; ETS_INTR_LOCK(); DHSENDER_QUEUE item; os_memcpy(&item, &mQueue[mQueueTakePos], sizeof(DHSENDER_QUEUE)); if(mQueueTakePos >= mQueueMaxSize - 1) mQueueTakePos = 0; else mQueueTakePos++; if(mQueueAddPos == mQueueTakePos) mQueueTakePos = -1; mQueueSize--; ETS_INTR_UNLOCK(); if(mQueueSize < MEM_RECOVER_THRESHOLD && dhmem_isblock()) dhmem_unblock(); char buf[HTTP_REQUEST_MIN_ALLOWED_PAYLOAD]; if(dhsender_data_to_json(buf, sizeof(buf), item.notification_type == RNT_NOTIFICATION_GPIO, item.data_type, &item.data, item.data_len, item.pin) < 0) { snprintf(buf, sizeof(buf), "Failed to convert data to json"); item.type = RT_RESPONCE_ERROR; } *is_notification = 0; switch(item.type) { case RT_RESPONCE_OK: case RT_RESPONCE_ERROR: dhrequest_create_update(out, item.id, (item.type == RT_RESPONCE_OK) ? STATUS_OK : STATUS_ERROR, buf); break; case RT_NOTIFICATION: *is_notification = 1; switch(item.notification_type) { case RNT_NOTIFICATION_GPIO: dhrequest_create_notification(out, "gpio/int", buf); break; case RNT_NOTIFICATION_ADC: dhrequest_create_notification(out, "adc/int", buf); break; case RNT_NOTIFICATION_UART: dhrequest_create_notification(out, "uart/int", buf); break; case RNT_NOTIFICATION_ONEWIRE: dhrequest_create_notification(out, "onewire/master/int", buf); break; default: dhdebug("ERROR: Unknown notification type of request %d", item.notification_type); return 0; } break; default: dhdebug("ERROR: Unknown type of request %d", item.type); return 0; } return 1; }
LOCAL void ICACHE_FLASH_ATTR start_resolve_dh_server() { static ip_addr_t ip; const char *server = dhrequest_current_server(); char host[os_strlen(server) + 1]; const char *fr = server; while(*fr != ':') { fr++; if(*fr == 0) { fr = 0; break; } } if(fr) { fr++; if(*fr != '/') fr = 0; } if (fr) { while (*fr == '/') fr++; int i = 0; while (*fr != '/' && *fr != ':' && *fr != 0) host[i++] = *fr++; // read port if present int port = 0; if(*fr == ':') { unsigned char d; fr++; while ( (d = *fr - 0x30) < 10) { fr++; port = port*10 + d; if(port > 0xFFFF) break; } } if(port && port < 0xFFFF) mDHConnector.proto.tcp->remote_port = port; else if (os_strncmp(dhrequest_current_server(), "https", 5) == 0) mDHConnector.proto.tcp->remote_port = 443; // HTTPS default port else mDHConnector.proto.tcp->remote_port = 80; //HTTP default port host[i] = 0; dhdebug("Resolving %s", host); err_t r = espconn_gethostbyname(&mDHConnector, host, &ip, resolve_cb); if(r == ESPCONN_OK) { resolve_cb(host, &ip, NULL); } else if(r != ESPCONN_INPROGRESS) { dhesperrors_espconn_result("Resolving failed:", r); arm_repeat_timer(RETRY_CONNECTION_INTERVAL_MS); } } else { dhdebug("Can not find scheme in server url"); } }
LOCAL void parse_json(struct jsonparse_state *jparser) { int type; unsigned int id; char command[128] = ""; const char *params; int paramslen = 0; char timestamp[128] = ""; while ((type = jsonparse_next(jparser)) != JSON_TYPE_ERROR) { if (type == JSON_TYPE_PAIR_NAME) { if (jsonparse_strcmp_value(jparser, "serverTimestamp") == 0) { jsonparse_next(jparser); if (jsonparse_next(jparser) != JSON_TYPE_ERROR) { jsonparse_copy_value(jparser, timestamp, sizeof(timestamp)); dhdebug("Timestamp received %s", timestamp); dhrequest_update_poll(&mPollRequest, timestamp); } break; } else if (jsonparse_strcmp_value(jparser, "command") == 0) { jsonparse_next(jparser); if(jsonparse_next(jparser) != JSON_TYPE_ERROR) jsonparse_copy_value(jparser, command, sizeof(command)); } else if (jsonparse_strcmp_value(jparser, "id") == 0) { jsonparse_next(jparser); if(jsonparse_next(jparser) != JSON_TYPE_ERROR) id = jsonparse_get_value_as_ulong(jparser); } else if (jsonparse_strcmp_value(jparser, "parameters") == 0) { jsonparse_next(jparser); if(jsonparse_next(jparser) != JSON_TYPE_ERROR) { // there is an issue with extracting subjson with jparser->vstart or jparser_copy_value params = &jparser->json[jparser->pos - 1]; if(*params == '{') { int end = jparser->pos; while(end < jparser->len && jparser->json[end] != '}') { end++; } paramslen = end - jparser->pos + 2; } } } else if (jsonparse_strcmp_value(jparser, "timestamp") == 0) { jsonparse_next(jparser); if(jsonparse_next(jparser) != JSON_TYPE_ERROR) jsonparse_copy_value(jparser, timestamp, sizeof(timestamp)); } } } if (mConnectionState == CS_POLL) { if(timestamp[0]) { dhdebug("Timestamp received %s", timestamp); dhrequest_update_poll(&mPollRequest, timestamp); } mCommandCallback(id, command, params, paramslen); } }
LOCAL void ICACHE_FLASH_ATTR dhap_httpd_connect_cb(void *arg) { struct espconn *conn = arg; mConnected++; if(mConnected > MAX_CONNECTIONS) { espconn_disconnect(conn); dhdebug("Refuse connection, already %u connections", mConnected); return; } espconn_regist_recvcb(conn, dhap_httpd_recv_cb); espconn_regist_disconcb(conn, dhap_httpd_disconnect_cb); espconn_regist_sentcb(conn, dhap_httpd_sent_cb); dhdebug("Client connected"); }
void ICACHE_FLASH_ATTR dhsender_queue_init() { mQueueMaxSize = (system_get_free_heap_size() - MEMORY_RESERVER) / sizeof(DHSENDER_QUEUE); if(mQueueMaxSize > MAX_QUEUE_LENGTH) mQueueMaxSize = MAX_QUEUE_LENGTH; mQueue = (DHSENDER_QUEUE *)os_malloc(mQueueMaxSize * sizeof(DHSENDER_QUEUE)); if(mQueue == 0) { dhdebug("ERROR: can not allocate memory for queue"); } else { if(mQueueMaxSize < 10) dhdebug("Warning: queue is very shot - %u", mQueueMaxSize); else dhdebug("Queue created, size %u", mQueueMaxSize); } }
void ICACHE_FLASH_ATTR dhesperrors_espconn_result(const char *descrption, int reason) { char *errdescr = 0; switch(reason) { case ESPCONN_OK: errdescr = "No error"; break; case ESPCONN_MEM: errdescr = "Out of memory error"; break; case ESPCONN_TIMEOUT: errdescr = "Timeout"; break; case ESPCONN_RTE: errdescr = "Routing problem"; break; case ESPCONN_INPROGRESS: errdescr = "Operation in progress"; break; case ESPCONN_ABRT: errdescr = "Connection aborted"; break; case ESPCONN_RST: errdescr = "Connection reset"; break; case ESPCONN_CLSD: errdescr = "Connection closed"; break; case ESPCONN_CONN: errdescr = "Not connected"; break; case ESPCONN_ARG: errdescr = "Illegal argument"; break; case ESPCONN_ISCONN: errdescr = "Already connected"; break; case ESPCONN_HANDSHAKE: errdescr = "SSL handshake failed"; break; case ESPCONN_PROTO_MSG: errdescr = "SSL application invalid"; break; } if(errdescr) dhdebug("%s %s", descrption, errdescr); else dhdebug("%s %d", descrption, reason); }
LOCAL void set_state(CONNECTION_STATE state) { mConnectionState = state; if(state != CS_DISCONNECT) { if(dhmem_isblock()) { mNeedRecover = 1; return; } } switch(state) { case CS_DISCONNECT: start_resolve_dh_server(); break; case CS_GETINFO: case CS_REGISTER: case CS_POLL: { const sint8 cr = espconn_connect(&mDHConnector); if(cr == ESPCONN_ISCONN) return; if(cr != ESPCONN_OK) { dhesperrors_espconn_result("Connector espconn_connect failed:", cr); arm_repeat_timer(RETRY_CONNECTION_INTERVAL_MS); } break; } default: dhdebug("ASSERT: set_state wrong state %d", mConnectionState); } }
UP_STATUS ICACHE_FLASH_ATTR uploadable_page_begin() { ETS_INTR_LOCK(); if(mBuffer == NULL) { mBuffer = (char *)os_malloc(SPI_FLASH_SEC_SIZE); } mBufferPos = 0; mFlashingSector = UPLOADABLE_PAGE_START_SECTOR; ETS_INTR_UNLOCK(); if(mBuffer == NULL) { dhdebug("No memory to initialize page flashing"); return UP_STATUS_INTERNAL_ERROR; } reset_timer(); dhdebug("Page flashing is initialized"); return UP_STATUS_OK; }
int ICACHE_FLASH_ATTR dhsender_queue_add(REQUEST_TYPE type, REQUEST_NOTIFICATION_TYPE notification_type, REQUEST_DATA_TYPE data_type, unsigned int id, va_list ap) { ETS_INTR_LOCK(); if(mQueueAddPos == mQueueTakePos) { ETS_INTR_UNLOCK(); dhdebug("ERROR: no space for request"); return 0; } mQueue[mQueueAddPos].id = id; mQueue[mQueueAddPos].type = type; mQueue[mQueueAddPos].data_type = data_type; mQueue[mQueueAddPos].notification_type = notification_type; dhsender_data_parse_va(ap, &data_type, &mQueue[mQueueAddPos].data, &mQueue[mQueueAddPos].data_len, &mQueue[mQueueAddPos].pin); if(mQueueTakePos < 0) mQueueTakePos = mQueueAddPos; if(mQueueAddPos >= mQueueMaxSize - 1) mQueueAddPos = 0; else mQueueAddPos++; mQueueSize++; if(mQueueSize > RESERVE_FOR_RESPONCE) dhmem_block(); ETS_INTR_UNLOCK(); return 1; }
LOCAL UP_STATUS ICACHE_FLASH_ATTR flash_data() { if(mFlashingSector > UPLOADABLE_PAGE_END_SECTOR) { return UP_STATUS_OVERFLOW; } if((SPI_FLASH_SEC_SIZE - mBufferPos) > 0) { irom_read(&mBuffer[mBufferPos], (const char *) (mFlashingSector * SPI_FLASH_SEC_SIZE + mBufferPos + IROM_FLASH_BASE_ADDRESS), SPI_FLASH_SEC_SIZE - mBufferPos); mBufferPos = SPI_FLASH_SEC_SIZE; } if(irom_cmp(mBuffer, (const char *) (mFlashingSector * SPI_FLASH_SEC_SIZE + IROM_FLASH_BASE_ADDRESS), SPI_FLASH_SEC_SIZE) == 0) { mFlashingSector++; return UP_STATUS_OK; } SpiFlashOpResult res; res = spi_flash_erase_sector(mFlashingSector); if(res == SPI_FLASH_RESULT_OK) { dhdebug("Flashing page at address 0x%X", mFlashingSector * SPI_FLASH_SEC_SIZE); res = spi_flash_write(mFlashingSector * SPI_FLASH_SEC_SIZE, (uint32 *)mBuffer, SPI_FLASH_SEC_SIZE); } system_soft_wdt_feed(); if(res == SPI_FLASH_RESULT_OK) { mFlashingSector++; return UP_STATUS_OK; } return UP_STATUS_INTERNAL_ERROR; }
UP_STATUS ICACHE_FLASH_ATTR uploadable_page_put(const char *data, unsigned int data_len) { if(mBuffer == NULL) return UP_STATUS_WRONG_CALL; if(mFlashingSector > UPLOADABLE_PAGE_END_SECTOR) return UP_STATUS_OVERFLOW; reset_timer(); ETS_INTR_LOCK(); while(data_len) { uint32_t tocopy = (data_len > (SPI_FLASH_SEC_SIZE - mBufferPos)) ? (SPI_FLASH_SEC_SIZE - mBufferPos): data_len; os_memcpy(&mBuffer[mBufferPos], data, tocopy); mBufferPos += tocopy; data_len -= tocopy; data += tocopy; if(mBufferPos == SPI_FLASH_SEC_SIZE) { SpiFlashOpResult res = flash_data(); mBufferPos = 0; if(res != SPI_FLASH_RESULT_OK) { ETS_INTR_UNLOCK(); dhdebug("Error while writing page at 0x%X", mFlashingSector * SPI_FLASH_SEC_SIZE); return UP_STATUS_INTERNAL_ERROR; } } } ETS_INTR_UNLOCK(); return UP_STATUS_OK; }
LOCAL void network_recv_cb(void *arg, char *data, unsigned short len) { dhstatistic_add_bytes_received(len); const char *rc = find_http_responce_code(data, len); if (rc) { // HTTP if (*rc == '2') { // HTTP responce code 2xx - Success if (mConnectionState == CS_REGISTER) { dhdebug("Successfully register"); } else { char *content = (char *) os_strstr(data, (char *) "\r\n\r\n"); if (content) { int deep = 0; unsigned int pos = 0; unsigned int jsonstart = 0; while (pos < len) { if (data[pos] == '{') { if (deep == 0) jsonstart = pos; deep++; } else if (data[pos] == '}') { deep--; if (deep == 0) { struct jsonparse_state jparser; jsonparse_setup(&jparser, &data[jsonstart], pos - jsonstart); parse_json(&jparser); } } pos++; } } } } else { mConnectionState = CS_DISCONNECT; dhdebug("Connector HTTP response bad status %c%c%c", rc[0],rc[1],rc[2]); dhdebug(data); dhdebug("--------------------------------------"); dhstatistic_server_errors_count(); } } else { mConnectionState = CS_DISCONNECT; dhdebug("Connector HTTP magic number is wrong"); dhstatistic_server_errors_count(); } espconn_disconnect(&mDHConnector); }
LOCAL void ICACHE_FLASH_ATTR resolve_cb(const char *name, ip_addr_t *ip, void *arg) { if (ip == NULL) { dhdebug("Resolve %s failed. Trying again...", name); mConnectionState = CS_DISCONNECT; arm_repeat_timer(RETRY_CONNECTION_INTERVAL_MS); dhstatistic_inc_network_errors_count(); return; } unsigned char *bip = (unsigned char *) ip; dhdebug("Host %s ip: %d.%d.%d.%d, using port %d", name, bip[0], bip[1], bip[2], bip[3], mDHConnector.proto.tcp->remote_port); dhsender_init(ip, mDHConnector.proto.tcp->remote_port); dhconnector_init_connection(ip); if(mPollRequest.len) set_state(CS_POLL); else set_state(CS_GETINFO); }
LOCAL void ICACHE_FLASH_ATTR senderRecvCb(void *arg, char *data, unsigned short len) { dhstatistic_add_bytes_received(len); const char *rc = find_http_responce_code(data, len); if (rc) { // HTTP if (*rc == '2') { // HTTP responce code 2xx - Success mSenderTook = 0; dhdebug("Sender received OK"); } else { dhdebug("Sender HTTP response bad status %c%c%c", rc[0],rc[1],rc[2]); dhdebug_ram(data); dhdebug("--------------------------------------"); dhstatistic_server_errors_count(); } } else { dhdebug("Sender received wrong HTTP magic"); dhstatistic_server_errors_count(); } espconn_disconnect(&mDHSender); }
LOCAL void ICACHE_FLASH_ATTR wifi_state_cb(System_Event_t *event) { if(event->event == EVENT_STAMODE_GOT_IP) { if(event->event_info.got_ip.ip.addr != 0) { const unsigned char * const bip = (unsigned char *)&event->event_info.got_ip.ip; dhdebug("WiFi connected, ip: %d.%d.%d.%d", bip[0], bip[1], bip[2], bip[3]); mConnectionState = CS_DISCONNECT; arm_repeat_timer(DHREQUEST_PAUSE_MS); } else { dhdebug("ERROR: WiFi reports STAMODE_GOT_IP, but no actual ip found"); } } else if(event->event == EVENT_STAMODE_DISCONNECTED) { os_timer_disarm(&mRetryTimer); dhsender_stop_repeat(); dhesperrors_disconnect_reason("WiFi disconnected", event->event_info.disconnected.reason); dhstatistic_inc_wifi_lost_count(); } else { dhesperrors_wifi_state("WiFi event", event->event); } }
int ICACHE_FLASH_ATTR dhgpio_write(unsigned int set_mask, unsigned int unset_mask) { const unsigned int pins = set_mask | unset_mask; if((pins | DHGPIO_SUITABLE_PINS) != DHGPIO_SUITABLE_PINS) return 0; dhdebug("GPIO set high at 0x%X, set low at 0x%X", set_mask, unset_mask); dhgpio_prepare_pins(pins, 1); dhgpio_open_drain(0, pins); dhgpio_pull(0, pins); gpio_output_set(set_mask, unset_mask, pins, 0); return 1; }
void user_init(void) { int ever_saved; if(mSpecialMode) { system_set_os_print(0); dhsettings_init(&ever_saved); dhap_init(); } else { dhdebug("*****************************"); dhsettings_init(&ever_saved); if(ever_saved == 0) { // if first run on this chip uploadable_page_delete(); } dhsender_queue_init(); dhconnector_init(dhcommands_do); dhgpio_init(); webserver_init(); dhdebug("Initialization completed"); dhterminal_init(); } }
LOCAL void ICACHE_FLASH_ATTR decrementSenderTook() { if(mSenderTook) { if(mSenderTook == 1) { dhdebug("WARNING: Request is not delivered after %u attempts", DHSENDER_RETRY_COUNT); if(isCurrentNotification) dhstatistic_inc_notifications_dropped_count(); else dhstatistic_inc_responces_dropped_count(); } mSenderTook--; } }
void ICACHE_FLASH_ATTR dhsender_notification(REQUEST_NOTIFICATION_TYPE type, REQUEST_DATA_TYPE data_type, ...) { va_list ap; va_start(ap, data_type); dhstatistic_inc_notifications_count(); if(dhsender_queue_add(RT_NOTIFICATION, type, data_type, 0, ap)) { dhsender_next(NULL); } else { dhstatistic_inc_notifications_dropped_count(); dhdebug("ERROR: No memory for notification."); } va_end(ap); }
void ICACHE_FLASH_ATTR dhsender_response(CommandResultArgument cid, RESPONCE_STATUS status, REQUEST_DATA_TYPE data_type, ...) { va_list ap; va_start(ap, data_type); dhstatistic_inc_responces_count(); if(dhsender_queue_add(status == DHSTATUS_ERROR ? RT_RESPONCE_ERROR : RT_RESPONCE_OK, RNT_NOTIFICATION_NONE, data_type, cid.id, ap)) { dhsender_next(NULL); } else { dhstatistic_inc_responces_dropped_count(); dhdebug("ERROR: No memory for response."); } va_end(ap); }
void ICACHE_FLASH_ATTR dhap_httpd_init() { struct espconn *httpdConn = (struct espconn *)os_zalloc(sizeof(struct espconn )); esp_tcp *httpdTcp = (esp_tcp *)os_zalloc(sizeof(esp_tcp)); httpdConn->type = ESPCONN_TCP; httpdConn->state = ESPCONN_NONE; httpdTcp->local_port = HTTPD_PORT; httpdConn->proto.tcp = httpdTcp; espconn_regist_connectcb(httpdConn, dhap_httpd_connect_cb); espconn_regist_reconcb(httpdConn, dhap_httpd_reconnect_cb); sint8 res = espconn_accept(httpdConn); if(res) dhdebug("espconn_accept returned: %d", res); }
LOCAL void network_disconnect_cb(void *arg) { switch(mConnectionState) { case CS_DISCONNECT: arm_repeat_timer(RETRY_CONNECTION_INTERVAL_MS); break; case CS_GETINFO: set_state(CS_REGISTER); break; case CS_REGISTER: mConnectionState = CS_POLL; /* no break */ case CS_POLL: arm_repeat_timer(DHREQUEST_PAUSE_MS); break; default: dhdebug("ASSERT: networkDisconnectCb wrong state %d", mConnectionState); } }
LOCAL void ICACHE_FLASH_ATTR dhsender_next(void *arg) { if(mStopped) return; if(mSenderTook == 0) { if(dhsender_queue_take(&mSenderRequest, &isCurrentNotification)) mSenderTook = DHSENDER_RETRY_COUNT; else return; } sint8 cr = espconn_connect(&mDHSender); if(cr == ESPCONN_ISCONN) { return; } else if (cr != ESPCONN_OK) { dhesperrors_espconn_result("Sender espconn_connect failed:", cr); dhsender_arm_timer(RETRY_CONNECTION_INTERVAL_MS); } else { dhdebug("Sender start"); } }
DHI2C_STATUS ICACHE_FLASH_ATTR mpu6050_read(int sda, int scl, MPU6050_XYZ *acceleromter, MPU6050_XYZ *gyroscope, float *temparature) { char buf[16]; DHI2C_STATUS status; if(sda != MPU6050_NO_PIN && scl != MPU6050_NO_PIN) { if((status = dhi2c_init(sda, scl)) != DHI2C_OK) { dhdebug("mpu6050: failed to set up pins"); return status; } } buf[0] = 0x6B; // power up buf[1] = 0; // no sleep bit if((status = dhi2c_write(mAddress, buf, 2, 1)) != DHI2C_OK) { dhdebug("mpu6050: failed to power up"); return status; } buf[0] = 0x1C; // accelerometer configuration buf[1] = (1 << 4); // AFS_SEL = 2, range +-8 g if((status = dhi2c_write(mAddress, buf, 2, 1)) != DHI2C_OK) { dhdebug("mpu6050: failed to configure accelerometer"); return status; } buf[0] = 0x1B; // gyroscope configuration buf[1] = (1 << 4); // FS_SEL = 2, range +-1000 dps if((status = dhi2c_write(mAddress, buf, 2, 1)) != DHI2C_OK) { dhdebug("mpu6050: failed to configure gyroscope"); return status; } os_delay_us(50000); buf[0] = 0x3B; // get data if((status = dhi2c_write(mAddress, buf, 1, 0)) != DHI2C_OK) { dhdebug("mpu6050: failed to set read register"); return status; } if((status = dhi2c_read(mAddress, buf, 14)) != DHI2C_OK) { dhdebug("mpu6050: failed to read"); return status; } buf[14] = 0x6B; // power down buf[15] = 1 << 6; // sleep bit if((status = dhi2c_write(mAddress, &buf[14], 2, 1)) != DHI2C_OK) { dhdebug("mpu6050: failed to power up"); return status; } if(acceleromter) { acceleromter->X = signedInt16(buf, 0) * 8.0f * EARTH_GRAVITY_ACCELERATION / 32768.0f; acceleromter->Y = signedInt16(buf, 2) * 8.0f * EARTH_GRAVITY_ACCELERATION / 32768.0f; acceleromter->Z = signedInt16(buf, 4) * 8.0f * EARTH_GRAVITY_ACCELERATION / 32768.0f; } if(gyroscope) { gyroscope->X = signedInt16(buf, 8) * 1000.0f / 32768.0f; gyroscope->Y = signedInt16(buf, 10) * 1000.0f / 32768.0f; gyroscope->Z = signedInt16(buf, 12) * 1000.0f / 32768.0f; } if(temparature) *temparature = signedInt16(buf, 6) / 340.0f + 36.53f; return DHI2C_OK; }
LOCAL void ICACHE_FLASH_ATTR receive_post(const char *data, unsigned short len, char * internal, unsigned int internalsize) { const unsigned int POST_BUF_SIZE = 2048; const char content_length[] = "Content-Length:"; const char sp[] = "\r\n\r\n"; if(mPostBuf == 0) { mPostBuf = (char*)os_malloc(POST_BUF_SIZE); if(mPostBuf == 0) { check_send_res(espconn_send(mCurrentPost, internal, internalsize)); mCurrentPost = 0; return; } } if(len > POST_BUF_SIZE - mPostBufPos) { check_send_res(espconn_send(mCurrentPost, internal, internalsize)); mCurrentPost = 0; return; } os_memcpy(&mPostBuf[mPostBufPos], data, len); mPostBufPos += len; const int to = (int)mPostBufPos - sizeof(content_length) + 1; int i; unsigned int cont_len; for(i = 0; i < to; i++) { if(os_strncmp(&mPostBuf[i], content_length, sizeof(content_length) - 1) == 0) { i += sizeof(content_length) - 1; while(mPostBuf[i] == ' ') i++; if(strToUInt(&mPostBuf[i], &cont_len)) { for(; i < mPostBufPos; i++) { if(os_strncmp(&mPostBuf[i], sp, sizeof(sp) - 1) == 0) { i += sizeof(sp) - 1; if(cont_len <= mPostBufPos - i) { dhdebug("POST len %u/%u", cont_len, mPostBufPos - i); char *res = dhap_post_parse(&mPostBuf[i], mPostBufPos - i); unsigned int rlen; if(res) { res = dhap_pages_error(res, &rlen); } else { if(dhsettings_commit() == 0) { res = internal; rlen = internalsize; } else { res = dhap_pages_ok(&rlen); if(res == 0) { dhdebug("Generate OK page fail"); res = internal; rlen = internalsize; } else { dhdebug("Configuration was written. Will be rebooted in %d ms", RECONFIGURE_DELAY_MS); os_timer_disarm(&mReconfigureTimer); os_timer_setfn(&mReconfigureTimer, (os_timer_func_t *)system_reconfigure, NULL); os_timer_arm(&mReconfigureTimer, RECONFIGURE_DELAY_MS, 0); mConfigured = 1; } } } dhdebug("Parse post, send result %u bytes", rlen); check_send_res(espconn_send(mCurrentPost, res, rlen)); mCurrentPost = 0; } return; } } } return; } } }
LOCAL void ICACHE_FLASH_ATTR dhap_httpd_sent_cb(void *arg) { struct espconn *conn = arg; espconn_disconnect(conn); dhdebug("Data sent"); }