// Command handler for sync command static void ICACHE_FLASH_ATTR cmdSync(CmdPacket *cmd) { CmdRequest req; cmdRequest(&req, cmd); if(cmd->argc != 0 || cmd->value == 0) { cmdResponseStart(CMD_RESP_V, 0, 0); cmdResponseEnd(); return; } // clear callbacks table os_memset(callbacks, 0, sizeof(callbacks)); // register our callback with wifi subsystem if (!wifiCbAdded) { wifiAddStateChangeCb(cmdWifiCb); wifiCbAdded = true; } // send OK response cmdResponseStart(CMD_RESP_V, cmd->value, 0); cmdResponseEnd(); // save the MCU's callback and trigger an initial callback cmdAddCb("wifiCb", cmd->value); lastWifiStatus = 0xff; // set to invalid value so we immediately send status cb in all cases cmdWifiCb(wifiState); return; }
void ICACHE_FLASH_ATTR cmdMqttPublishedCb(MQTT_Client* client) { MqttCmdCb* cb = (MqttCmdCb*)client->user_data; DBG("MQTT: Published cb=%p\n", (void*)cb->publishedCb); cmdResponseStart(CMD_RESP_CB, cb->publishedCb, 0); cmdResponseEnd(); }
// Command handler for hostname command static void ICACHE_FLASH_ATTR cmdHostname(CmdPacket *cmd) { cmdResponseStart(CMD_RESP_V, 0, 0); cmdResponseBody((uint8_t*)&flashConfig.hostname, sizeof(&flashConfig.hostname)); cmdResponseEnd(); return; }
//puts the ESP to sleep static void ICACHE_FLASH_ATTR cmdSleep(CmdPacket *cmd) { // uint32_t sleepTime = 30000000; cmdResponseStart(CMD_RESP_V,espSleep(42),42); //should put this to sleep for 30s attach gpio16 to RST cmdResponseEnd(); return; }
void ICACHE_FLASH_ATTR cmdMqttDisconnectedCb(MQTT_Client* client) { if (blocked) return; MqttCmdCb* cb = (MqttCmdCb*)client->user_data; DBG("MQTT: Disconnected cb=%p\n", (void*)cb->disconnectedCb); cmdResponseStart(CMD_RESP_CB, cb->disconnectedCb, 0); cmdResponseEnd(); }
void ICACHE_FLASH_ATTR cmdMqttDataCb(MQTT_Client* client, const char* topic, uint32_t topic_len, const char* data, uint32_t data_len) { MqttCmdCb* cb = (MqttCmdCb*)client->user_data; DBG("MQTT: Data cb=%p topic=%s len=%u\n", (void*)cb->dataCb, topic, data_len); cmdResponseStart(CMD_RESP_CB, cb->dataCb, 2); cmdResponseBody(topic, topic_len); cmdResponseBody(data, data_len); cmdResponseEnd(); }
// Callback from wifi subsystem to notify us of status changes static void ICACHE_FLASH_ATTR cmdWifiCb(uint8_t wifiStatus) { if (wifiStatus != lastWifiStatus){ DBG("cmdWifiCb: wifiStatus=%d\n", wifiStatus); lastWifiStatus = wifiStatus; CmdCallback *wifiCb = cmdGetCbByName("wifiCb"); if ((uint32_t)wifiCb->callback != -1) { uint8_t status = wifiStatus == wifiGotIP ? 5 : 1; cmdResponseStart(CMD_RESP_CB, (uint32_t)wifiCb->callback, 1); cmdResponseBody((uint8_t*)&status, 1); cmdResponseEnd(); } } }
// Parse a packet and print info about it void ICACHE_FLASH_ATTR cmdParsePacket(uint8_t *buf, short len) { // minimum command length if (len < sizeof(CmdPacket)) return; // init pointers into buffer CmdPacket *packet = (CmdPacket*)buf; uint8_t *data_ptr = (uint8_t*)&packet->args; uint8_t *data_limit = data_ptr+len; DBG("cmdParsePacket: cmd=%d argc=%d value=%u\n", packet->cmd, packet->argc, packet->value ); #if 0 // print out arguments uint16_t argn = 0; uint16_t argc = packet->argc; while (data_ptr+2 < data_limit && argc--) { short l = *(uint16_t*)data_ptr; os_printf("cmdParsePacket: arg[%d] len=%d:", argn++, l); data_ptr += 2; while (data_ptr < data_limit && l--) { os_printf(" %02X", *data_ptr++); } os_printf("\n"); } #endif if (!cmdInSync && packet->cmd != CMD_SYNC) { // we have not received a sync, perhaps we reset? Tell MCU to do a sync cmdResponseStart(CMD_SYNC, 0, 0); cmdResponseEnd(); } else if (data_ptr <= data_limit) { cmdExec(commands, packet); } else { DBG("cmdParsePacket: packet length overrun, parsing arg %d\n", packet->argc); } }
// Receive HTTP response - this hacky function assumes that the full response is received in // one go. Sigh... static void ICACHE_FLASH_ATTR tcpclient_recv(void *arg, char *pdata, unsigned short len) { struct espconn *pCon = (struct espconn*)arg; RestClient *client = (RestClient *)pCon->reverse; // parse status line int pi = 0; int16_t code = -1; char statusCode[4] = "\0\0\0\0"; int statusLen = 0; bool inStatus = false; while (pi < len) { if (pdata[pi] == '\n') { // end of status line if (code == -1) code = 502; // BAD GATEWAY break; } else if (pdata[pi] == ' ') { if (inStatus) code = atoi(statusCode); inStatus = !inStatus; } else if (inStatus) { if (statusLen < 3) statusCode[statusLen] = pdata[pi]; statusLen++; } pi++; } // parse header, all this does is look for the end of the header bool currentLineIsBlank = false; while (pi < len) { if (pdata[pi] == '\n') { if (currentLineIsBlank) { // body is starting pi++; break; } currentLineIsBlank = true; } else if (pdata[pi] != '\r') { currentLineIsBlank = false; } pi++; } //if (pi < len && pdata[pi] == '\r') pi++; // hacky! // collect body and send it int body_len = len-pi; DBG("REST: status=%d, body=%d\n", code, body_len); if (pi == len) { cmdResponseStart(CMD_RESP_CB, client->resp_cb, 1); cmdResponseBody(&code, sizeof(code)); cmdResponseEnd(); } else { cmdResponseStart(CMD_RESP_CB, client->resp_cb, 2); cmdResponseBody(&code, sizeof(code)); cmdResponseBody(pdata+pi, body_len>100?100:body_len); cmdResponseEnd(); #if 0 os_printf("REST: body="); for (int j=pi; j<len; j++) os_printf(" %02x", pdata[j]); os_printf("\n"); #endif } //if(client->security) // espconn_secure_disconnect(client->pCon); //else espconn_disconnect(client->pCon); }
void ICACHE_FLASH_ATTR REST_Setup(CmdPacket *cmd) { CmdRequest req; uint32_t port, security; int32_t err = -1; // error code in case of failure // start parsing the command cmdRequest(&req, cmd); if(cmdGetArgc(&req) != 3) goto fail; err--; // get the hostname uint16_t len = cmdArgLen(&req); if (len > 128) goto fail; // safety check err--; uint8_t *rest_host = (uint8_t*)os_zalloc(len + 1); if (cmdPopArg(&req, rest_host, len)) goto fail; err--; rest_host[len] = 0; // get the port if (cmdPopArg(&req, (uint8_t*)&port, 2)) { os_free(rest_host); goto fail; } err--; // get the security mode if (cmdPopArg(&req, (uint8_t*)&security, 1)) { os_free(rest_host); goto fail; } err--; // clear connection structures the first time if (restNum == 0xff) { os_memset(restClient, 0, MAX_REST * sizeof(RestClient)); restNum = 0; } // allocate a connection structure RestClient *client = restClient + restNum; uint8_t clientNum = restNum; restNum = (restNum+1)%MAX_REST; // free any data structure that may be left from a previous connection if (client->header) os_free(client->header); if (client->content_type) os_free(client->content_type); if (client->user_agent) os_free(client->user_agent); if (client->data) os_free(client->data); if (client->pCon) { if (client->pCon->proto.tcp) os_free(client->pCon->proto.tcp); os_free(client->pCon); } os_memset(client, 0, sizeof(RestClient)); DBG("REST: setup #%d host=%s port=%ld security=%ld\n", clientNum, rest_host, port, security); client->resp_cb = cmd->value; client->host = (char *)rest_host; client->port = port; client->security = security; client->header = (char*)os_zalloc(4); client->header[0] = 0; client->content_type = (char*)os_zalloc(22); os_sprintf((char *)client->content_type, "x-www-form-urlencoded"); client->user_agent = (char*)os_zalloc(9); os_sprintf((char *)client->user_agent, "esp-link"); client->pCon = (struct espconn *)os_zalloc(sizeof(struct espconn)); client->pCon->proto.tcp = (esp_tcp *)os_zalloc(sizeof(esp_tcp)); client->pCon->type = ESPCONN_TCP; client->pCon->state = ESPCONN_NONE; client->pCon->proto.tcp->local_port = espconn_port(); client->pCon->proto.tcp->remote_port = client->port; client->pCon->reverse = client; cmdResponseStart(CMD_RESP_V, clientNum, 0); cmdResponseEnd(); return; fail: cmdResponseStart(CMD_RESP_V, err, 0); cmdResponseEnd(); return; }
// Command handler for time static void ICACHE_FLASH_ATTR cmdGetTime(CmdPacket *cmd) { cmdResponseStart(CMD_RESP_V, sntp_get_current_timestamp(), 0); cmdResponseEnd(); return; }
// Command handler for wifi status command static void ICACHE_FLASH_ATTR cmdWifiStatus(CmdPacket *cmd) { cmdResponseStart(CMD_RESP_V, wifiState, 0); cmdResponseEnd(); return; }