#include "project.h" #define URL_SIZE 256 #define TYPE_UNKNOWN 0 #define TYPE_GET 1 #define TYPE_POST 2 #define MAX_RECV_BUFFER_SIZE 1024 typedef struct http_state_struct { bool header_parsed_ok; bool error; bool overflow; uint8_t type; uint32_t bytes_recvd; uint32_t header_length; uint32_t content_length; uint32_t expected_length; char url[URL_SIZE]; char *recv_buffer; uint32_t recv_buffer_len; uint32_t recv_buffer_size; } http_state; static http_state static_state = { 0 }; #define LENGTH_ERR ((uint32_t) -1) void ICACHE_FLASH_ATTR webserver_send_reply (struct espconn *conn, int status, char *type, char *body, size_t body_len) { char header[256] = { 0 }; char *ptr = header; if (body && !body_len) body_len = os_strlen (body); switch (status) { case 200: ptr += os_sprintf (ptr, "HTTP/1.1 %d OK\r\nContent-Length: %d\r\nServer: InternetOfThingsThing/1.0\r\n", status, body ? body_len : 0); break; default: ptr += os_sprintf (ptr, "HTTP/1.1 %d BadRequest\r\nContent-Length: %d\r\nServer: InternetOfThingsThing/1.0\r\n", status, 0); break; } if (body && body_len) { if (type) ptr += os_sprintf (ptr, "Content-type: %s\r\nExpires: Fri, 10 Apr 2008 14:00:00 GMT\r\nPragma: no-cache\r\n", type); } ptr += os_sprintf (ptr, "Connection: close\r\n\r\n"); #ifdef SERVER_SSL_ENABLE espconn_secure_sent (conn, header, (uint32_t) ptr - header); if (body && body_len) espconn_secure_sent (conn, body, body_len); #else espconn_sent (conn, header, (uint32_t) (ptr - header)); if (body && body_len) espconn_sent (conn, body, body_len); #endif } static bool ICACHE_FLASH_ATTR webserver_get_header (char *buf, uint32_t length, char *match, char *ret, uint32_t ret_len) { uint32_t match_len = os_strlen (match); char *line_ptr; char *eol_ptr; uint32_t line_length; line_ptr = (char *) bounded_strstr (buf, length, match); if (!line_ptr) return false; line_length = (buf + length) - line_ptr; if (line_length <= match_len) return false; line_ptr += match_len; line_length -= match_len; eol_ptr = (char *) bounded_strstr (line_ptr, line_length, "\r\n"); if (!eol_ptr) return false; line_length = eol_ptr - line_ptr; if (line_length >= ret_len) return false; os_memcpy (ret, line_ptr, ret_len); ret[ret_len] = 0; return true; } static bool ICACHE_FLASH_ATTR webserver_parse_request (http_state * s, char *buf) { char *ptr = buf; char *eol_ptr; uint32_t line_length; eol_ptr = (char *) bounded_strstr (buf, s->header_length, "\r\n"); if (!eol_ptr) return false; line_length = eol_ptr - buf; if (line_length < 5) return false; if (!strncmp (ptr, "GET ", 4)) { s->type = TYPE_GET; ptr += 4; line_length -= 4; } else if (!strncmp (ptr, "POST ", 5)) { s->type = TYPE_POST; ptr += 5; line_length -= 5; } while (util_isspace (*ptr)) { ptr++; line_length--; if (!line_length) return false; } eol_ptr = ptr; /*Skip the protocol version */ while (!util_isspace (*eol_ptr)) { eol_ptr++; line_length--; if (!line_length) return false; } line_length = eol_ptr - ptr; if (line_length >= URL_SIZE) return false; os_memcpy (s->url, ptr, line_length); s->url[line_length] = 0; return true; } static bool ICACHE_FLASH_ATTR webserver_parse_header (http_state * s, char *buf, uint32_t length) { char *eoh_ptr; char tmp_buf[256]; char *ptr; s->header_parsed_ok = false; if (s->error) return false; eoh_ptr = (char *) bounded_strstr (buf, length, "\r\n\r\n"); if (!eoh_ptr) return false; eoh_ptr += 4; s->header_length = eoh_ptr - buf; if (!webserver_get_header (buf, s->header_length, "Content-Length: ", tmp_buf, sizeof (tmp_buf))) { s->content_length = 0; } else { s->content_length = atoi (tmp_buf); if (s->content_length < 0) return false; } if (!webserver_parse_request (s, buf)) { s->error++; return false; } s->header_parsed_ok = true; s->expected_length = s->content_length + s->header_length; os_printf ("wph:url:%s\n", s->url); os_printf ("wph:head:%u,data:%u,tot:%u\n", s->header_length, s->content_length, s->content_length + s->header_length); return true; } static void ICACHE_FLASH_ATTR webserver_state_reset (http_state * s) { os_printf ("wsr:\n"); if (s->recv_buffer) os_free (s->recv_buffer); memset (s, 0, sizeof (*s)); } static bool ICACHE_FLASH_ATTR webserver_append_data (http_state * s, char *data, uint32_t len) { uint32_t space; s->bytes_recvd += len; if (s->error) return false; if (!s->recv_buffer) { if (s->recv_buffer_size) { if (s->recv_buffer_size > MAX_RECV_BUFFER_SIZE) s->recv_buffer_size = MAX_RECV_BUFFER_SIZE; } else { s->recv_buffer_size = MAX_RECV_BUFFER_SIZE; } s->recv_buffer_len = 0; s->recv_buffer = (char *) os_zalloc (s->recv_buffer_size); if (!s->recv_buffer) { s->error++; return false; } os_printf ("wad:bs:%u,len:%u,add:%u\n", s->recv_buffer_size, s->recv_buffer_len, len); } space = s->recv_buffer_size - s->recv_buffer_len; if (len > space) { s->overflow++; space = len; } os_memcpy (s->recv_buffer, data, space); s->recv_buffer_len += space; return true; } static void ICACHE_FLASH_ATTR webserver_header (http_state * s) { } static void ICACHE_FLASH_ATTR webserver_req (struct espconn *conn, http_state * s) { os_printf ("Webserver req: %s\n", s->url); if (!os_strcmp (s->url, "/crash.html")) { webserver_send_reply (conn, 200, "text/html", "crashed into monitor", 0); crash (); } else if (!os_strcmp (s->url, "/upgrade.html")) { webserver_send_reply (conn, 200, "text/html", "triggered upgrade", 0); os_printf ("Upgrading\n"); upgrade (); } else if (!os_strcmp (s->url, "/gpio.html")) { gpio_page (conn); } else if (!os_strcmp (s->url, "/")) { gpio_colour_page (conn); } else { webserver_send_reply (conn, 404, "text/html", "Not Found", 0); } espconn_disconnect (conn); } static void ICACHE_FLASH_ATTR webserver_recv (void *arg, char *pusrdata, unsigned short data_len) { struct espconn *conn = arg; uint32_t len; http_state *s = &static_state; #if 0 if (doing_upgrade) { upgrade_recv (ptrespconn, pusrdata, data_len); free_recvbuffer (); return; } #endif os_printf ("len:%u\n", data_len); if (!s->header_parsed_ok) { if (!s->recv_buffer) { if (webserver_parse_header (s, pusrdata, data_len)) { webserver_header (s); s->recv_buffer_size = s->expected_length; } webserver_append_data (s, pusrdata, data_len); } else { webserver_append_data (s, pusrdata, data_len); webserver_parse_header (s, s->recv_buffer, s->recv_buffer_len); } } else { webserver_append_data (s, pusrdata, data_len); } if (s->error) return; if (s->bytes_recvd != s->expected_length) return; webserver_req (conn, s); } static ICACHE_FLASH_ATTR void webserver_recon (void *arg, sint8 err) { struct espconn *pesp_conn = arg; os_printf ("webserver's %d.%d.%d.%d:%d err %d reconnect\n", pesp_conn->proto.tcp->remote_ip[0], pesp_conn->proto.tcp->remote_ip[1], pesp_conn->proto.tcp->remote_ip[2], pesp_conn->proto.tcp->remote_ip[3], pesp_conn->proto.tcp->remote_port, err); } static ICACHE_FLASH_ATTR void webserver_discon (void *arg) { struct espconn *pesp_conn = arg; os_printf ("webserver's %d.%d.%d.%d:%d disconnect\n", pesp_conn->proto.tcp->remote_ip[0], pesp_conn->proto.tcp->remote_ip[1], pesp_conn->proto.tcp->remote_ip[2], pesp_conn->proto.tcp->remote_ip[3], pesp_conn->proto.tcp->remote_port); } static void ICACHE_FLASH_ATTR webserver_listen (void *arg) { struct espconn *pesp_conn = arg; webserver_state_reset (&static_state); espconn_regist_recvcb (pesp_conn, webserver_recv); espconn_regist_reconcb (pesp_conn, webserver_recon); espconn_regist_disconcb (pesp_conn, webserver_discon); } void ICACHE_FLASH_ATTR webserver_init (void) { static struct espconn esp_conn; static esp_tcp esptcp; esp_conn.type = ESPCONN_TCP; esp_conn.state = ESPCONN_NONE; esp_conn.proto.tcp = &esptcp; #ifdef HTTPS esp_conn.proto.tcp->local_port = 443; #else esp_conn.proto.tcp->local_port = 80; #endif espconn_regist_connectcb (&esp_conn, webserver_listen); #ifdef HTTPS espconn_secure_accept (&esp_conn); #else espconn_accept (&esp_conn); #endif } #if 0 /****************************************************************************** * Copyright 2013-2014 Espressif Systems (Wuxi) * * FileName: webserver.c * * Description: The web server mode configration. * Check your hardware connection with the host while use this mode. * Modification history: * 2014/3/12, v1.0 create this file. *******************************************************************************/ #include "ets_sys.h" #include "os_type.h" #include "osapi.h" #include "mem.h" #include "user_interface.h" #include "iot_version.h" #include "espconn.h" #include "json.h" #include "webserver.h" #include "upgrade.h" #if ESP_PLATFORM #include "esp_platform.h" #endif #if LIGHT_DEVICE #include "light.h" #endif static struct station_config *sta_conf; static struct softap_config *ap_conf; //static struct secrty_server_info *sec_server; //static struct upgrade_server_info *server; //struct lewei_login_info *login_info; static scaninfo *pscaninfo; extern u16 scannum; static uint32 PostCmdNeeRsp = 1; uint8 upgrade_lock = 0; static os_timer_t app_upgrade_10s; static os_timer_t upgrade_check_timer; /****************************************************************************** * FunctionName : device_get * Description : set up the device information parmer as a JSON format * Parameters : js_ctx -- A pointer to a JSON set up * Returns : result *******************************************************************************/ static int ICACHE_FLASH_ATTR device_get (struct jsontree_context *js_ctx) { const char *path = jsontree_path_name (js_ctx, js_ctx->depth - 1); if (os_strncmp (path, "manufacture", 11) == 0) { jsontree_write_string (js_ctx, "Espressif Systems"); } else if (os_strncmp (path, "product", 7) == 0) { #if SENSOR_DEVICE #if HUMITURE_SUB_DEVICE jsontree_write_string (js_ctx, "Humiture"); #elif FLAMMABLE_GAS_SUB_DEVICE jsontree_write_string (js_ctx, "Flammable Gas"); #endif #endif #if PLUG_DEVICE jsontree_write_string (js_ctx, "Plug"); #endif #if LIGHT_DEVICE jsontree_write_string (js_ctx, "Light"); #endif } return 0; } static struct jsontree_callback device_callback = JSONTREE_CALLBACK (device_get, NULL); /****************************************************************************** * FunctionName : userbin_get * Description : get up the user bin paramer as a JSON format * Parameters : js_ctx -- A pointer to a JSON set up * Returns : result *******************************************************************************/ static int ICACHE_FLASH_ATTR userbin_get (struct jsontree_context *js_ctx) { const char *path = jsontree_path_name (js_ctx, js_ctx->depth - 1); char string[32]; if (os_strncmp (path, "status", 8) == 0) { os_sprintf (string, "200"); } else if (os_strncmp (path, "user_bin", 8) == 0) { if (system_upgrade_userbin_check () == 0x00) { os_sprintf (string, "user1.bin"); } else if (system_upgrade_userbin_check () == 0x01) { os_sprintf (string, "user2.bin"); } else { return 0; } } jsontree_write_string (js_ctx, string); return 0; } static struct jsontree_callback userbin_callback = JSONTREE_CALLBACK (userbin_get, NULL); JSONTREE_OBJECT (userbin_tree, JSONTREE_PAIR ("status", &userbin_callback), JSONTREE_PAIR ("user_bin", &userbin_callback)); JSONTREE_OBJECT (userinfo_tree, JSONTREE_PAIR ("user_info", &userbin_tree)); /****************************************************************************** * FunctionName : version_get * Description : set up the device version paramer as a JSON format * Parameters : js_ctx -- A pointer to a JSON set up * Returns : result *******************************************************************************/ static int ICACHE_FLASH_ATTR version_get (struct jsontree_context *js_ctx) { const char *path = jsontree_path_name (js_ctx, js_ctx->depth - 1); char string[32]; if (os_strncmp (path, "hardware", 8) == 0) { #if SENSOR_DEVICE os_sprintf (string, "0.3"); #else os_sprintf (string, "0.1"); #endif } else if (os_strncmp (path, "sdk_version", 11) == 0) { os_sprintf (string, "%s", system_get_sdk_version ()); } else if (os_strncmp (path, "iot_version", 11) == 0) { os_sprintf (string, "%s%d.%d.%dt%d(%s)", VERSION_TYPE, IOT_VERSION_MAJOR, IOT_VERSION_MINOR, IOT_VERSION_REVISION, device_type, UPGRADE_FALG); } jsontree_write_string (js_ctx, string); return 0; } static struct jsontree_callback version_callback = JSONTREE_CALLBACK (version_get, NULL); JSONTREE_OBJECT (device_tree, JSONTREE_PAIR ("product", &device_callback), JSONTREE_PAIR ("manufacturer", &device_callback)); JSONTREE_OBJECT (version_tree, JSONTREE_PAIR ("hardware", &version_callback), JSONTREE_PAIR ("sdk_version", &version_callback), JSONTREE_PAIR ("iot_version", &version_callback),); JSONTREE_OBJECT (info_tree, JSONTREE_PAIR ("Version", &version_tree), JSONTREE_PAIR ("Device", &device_tree)); JSONTREE_OBJECT (INFOTree, JSONTREE_PAIR ("info", &info_tree)); static int ICACHE_FLASH_ATTR connect_status_get (struct jsontree_context *js_ctx) { const char *path = jsontree_path_name (js_ctx, js_ctx->depth - 1); if (os_strncmp (path, "status", 8) == 0) { jsontree_write_int (js_ctx, user_esp_platform_get_connect_status ()); } return 0; } static struct jsontree_callback connect_status_callback = JSONTREE_CALLBACK (connect_status_get, NULL); JSONTREE_OBJECT (status_sub_tree, JSONTREE_PAIR ("status", &connect_status_callback)); JSONTREE_OBJECT (connect_status_tree, JSONTREE_PAIR ("Status", &status_sub_tree)); JSONTREE_OBJECT (con_status_tree, JSONTREE_PAIR ("info", &connect_status_tree)); #if PLUG_DEVICE /****************************************************************************** * FunctionName : status_get * Description : set up the device status as a JSON format * Parameters : js_ctx -- A pointer to a JSON set up * Returns : result *******************************************************************************/ static int ICACHE_FLASH_ATTR status_get (struct jsontree_context *js_ctx) { if (user_plug_get_status () == 1) { jsontree_write_int (js_ctx, 1); } else { jsontree_write_int (js_ctx, 0); } return 0; } /****************************************************************************** * FunctionName : status_set * Description : parse the device status parmer as a JSON format * Parameters : js_ctx -- A pointer to a JSON set up * parser -- A pointer to a JSON parser state * Returns : result *******************************************************************************/ static int ICACHE_FLASH_ATTR status_set (struct jsontree_context *js_ctx, struct jsonparse_state *parser) { int type; while ((type = jsonparse_next (parser)) != 0) { if (type == JSON_TYPE_PAIR_NAME) { if (jsonparse_strcmp_value (parser, "status") == 0) { uint8 status; jsonparse_next (parser); jsonparse_next (parser); status = jsonparse_get_value_as_int (parser); user_plug_set_status (status); } } } return 0; } static struct jsontree_callback status_callback = JSONTREE_CALLBACK (status_get, status_set); JSONTREE_OBJECT (status_tree, JSONTREE_PAIR ("status", &status_callback)); JSONTREE_OBJECT (response_tree, JSONTREE_PAIR ("Response", &status_tree)); JSONTREE_OBJECT (StatusTree, JSONTREE_PAIR ("switch", &response_tree)); #endif #if LIGHT_DEVICE static int ICACHE_FLASH_ATTR light_status_get (struct jsontree_context *js_ctx) { const char *path = jsontree_path_name (js_ctx, js_ctx->depth - 1); if (os_strncmp (path, "red", 3) == 0) { jsontree_write_int (js_ctx, user_light_get_duty (LIGHT_RED)); } else if (os_strncmp (path, "green", 5) == 0) { jsontree_write_int (js_ctx, user_light_get_duty (LIGHT_GREEN)); } else if (os_strncmp (path, "blue", 4) == 0) { jsontree_write_int (js_ctx, user_light_get_duty (LIGHT_BLUE)); } else if (os_strncmp (path, "wwhite", 6) == 0) { if (PWM_CHANNEL > LIGHT_WARM_WHITE) { jsontree_write_int (js_ctx, user_light_get_duty (LIGHT_WARM_WHITE)); } else { jsontree_write_int (js_ctx, 0); } } else if (os_strncmp (path, "cwhite", 6) == 0) { if (PWM_CHANNEL > LIGHT_COLD_WHITE) { jsontree_write_int (js_ctx, user_light_get_duty (LIGHT_COLD_WHITE)); } else { jsontree_write_int (js_ctx, 0); } } else if (os_strncmp (path, "period", 6) == 0) { jsontree_write_int (js_ctx, user_light_get_period ()); } return 0; } static int ICACHE_FLASH_ATTR light_status_set (struct jsontree_context *js_ctx, struct jsonparse_state *parser) { int type; static uint32 r, g, b, cw, ww, period; period = 1000; cw = 0; ww = 0; extern uint8 light_sleep_flg; while ((type = jsonparse_next (parser)) != 0) { if (type == JSON_TYPE_PAIR_NAME) { if (jsonparse_strcmp_value (parser, "red") == 0) { uint32 status; jsonparse_next (parser); jsonparse_next (parser); status = jsonparse_get_value_as_int (parser); r = status; os_printf ("R: %d \n", status); //user_light_set_duty(status, LIGHT_RED); //light_set_aim_r( r); } else if (jsonparse_strcmp_value (parser, "green") == 0) { uint32 status; jsonparse_next (parser); jsonparse_next (parser); status = jsonparse_get_value_as_int (parser); g = status; os_printf ("G: %d \n", status); //user_light_set_duty(status, LIGHT_GREEN); //light_set_aim_g( g); } else if (jsonparse_strcmp_value (parser, "blue") == 0) { uint32 status; jsonparse_next (parser); jsonparse_next (parser); status = jsonparse_get_value_as_int (parser); b = status; os_printf ("B: %d \n", status); //user_light_set_duty(status, LIGHT_BLUE); //set_aim_b( b); } else if (jsonparse_strcmp_value (parser, "cwhite") == 0) { uint32 status; jsonparse_next (parser); jsonparse_next (parser); status = jsonparse_get_value_as_int (parser); cw = status; os_printf ("CW: %d \n", status); //user_light_set_duty(status, LIGHT_BLUE); //set_aim_b( b); } else if (jsonparse_strcmp_value (parser, "wwhite") == 0) { uint32 status; jsonparse_next (parser); jsonparse_next (parser); status = jsonparse_get_value_as_int (parser); ww = status; os_printf ("WW: %d \n", status); //user_light_set_duty(status, LIGHT_BLUE); //set_aim_b( b); } else if (jsonparse_strcmp_value (parser, "period") == 0) { uint32 status; jsonparse_next (parser); jsonparse_next (parser); status = jsonparse_get_value_as_int (parser); os_printf ("PERIOD: %d \n", status); period = status; //user_light_set_period(status); } else if (jsonparse_strcmp_value (parser, "response") == 0) { uint32 status; jsonparse_next (parser); jsonparse_next (parser); status = jsonparse_get_value_as_int (parser); os_printf ("rspneed: %d \n", status); PostCmdNeeRsp = status; } } } if ((r | g | b | ww | cw) == 0) { if (light_sleep_flg == 0) { } } else { if (light_sleep_flg == 1) { os_printf ("modem sleep en\r\n"); wifi_set_sleep_type (MODEM_SLEEP_T); light_sleep_flg = 0; } } light_set_aim (r, g, b, cw, ww, period); return 0; } static struct jsontree_callback light_callback = JSONTREE_CALLBACK (light_status_get, light_status_set); JSONTREE_OBJECT (rgb_tree, JSONTREE_PAIR ("red", &light_callback), JSONTREE_PAIR ("green", &light_callback), JSONTREE_PAIR ("blue", &light_callback), JSONTREE_PAIR ("cwhite", &light_callback), JSONTREE_PAIR ("wwhite", &light_callback),); JSONTREE_OBJECT (sta_tree, JSONTREE_PAIR ("period", &light_callback), JSONTREE_PAIR ("rgb", &rgb_tree)); JSONTREE_OBJECT (PwmTree, JSONTREE_PAIR ("light", &sta_tree)); #endif /****************************************************************************** * FunctionName : wifi_station_get * Description : set up the station paramer as a JSON format * Parameters : js_ctx -- A pointer to a JSON set up * Returns : result *******************************************************************************/ static int ICACHE_FLASH_ATTR wifi_station_get (struct jsontree_context *js_ctx) { const char *path = jsontree_path_name (js_ctx, js_ctx->depth - 1); struct ip_info ipconfig; uint8 buf[20]; os_bzero (buf, sizeof (buf)); wifi_station_get_config (sta_conf); wifi_get_ip_info (STATION_IF, &ipconfig); if (os_strncmp (path, "ssid", 4) == 0) { jsontree_write_string (js_ctx, sta_conf->ssid); } else if (os_strncmp (path, "password", 8) == 0) { jsontree_write_string (js_ctx, sta_conf->password); } else if (os_strncmp (path, "ip", 2) == 0) { os_sprintf (buf, IPSTR, IP2STR (&ipconfig.ip)); jsontree_write_string (js_ctx, buf); } else if (os_strncmp (path, "mask", 4) == 0) { os_sprintf (buf, IPSTR, IP2STR (&ipconfig.netmask)); jsontree_write_string (js_ctx, buf); } else if (os_strncmp (path, "gw", 2) == 0) { os_sprintf (buf, IPSTR, IP2STR (&ipconfig.gw)); jsontree_write_string (js_ctx, buf); } return 0; } /****************************************************************************** * FunctionName : wifi_station_set * Description : parse the station parmer as a JSON format * Parameters : js_ctx -- A pointer to a JSON set up * parser -- A pointer to a JSON parser state * Returns : result *******************************************************************************/ static int ICACHE_FLASH_ATTR wifi_station_set (struct jsontree_context *js_ctx, struct jsonparse_state *parser) { int type; uint8 station_tree; while ((type = jsonparse_next (parser)) != 0) { if (type == JSON_TYPE_PAIR_NAME) { char buffer[64]; os_bzero (buffer, 64); if (jsonparse_strcmp_value (parser, "Station") == 0) { station_tree = 1; } else if (jsonparse_strcmp_value (parser, "Softap") == 0) { station_tree = 0; } if (station_tree) { if (jsonparse_strcmp_value (parser, "ssid") == 0) { jsonparse_next (parser); jsonparse_next (parser); jsonparse_copy_value (parser, buffer, sizeof (buffer)); os_memcpy (sta_conf->ssid, buffer, os_strlen (buffer)); } else if (jsonparse_strcmp_value (parser, "password") == 0) { jsonparse_next (parser); jsonparse_next (parser); jsonparse_copy_value (parser, buffer, sizeof (buffer)); os_memcpy (sta_conf->password, buffer, os_strlen (buffer)); } #if ESP_PLATFORM else if (jsonparse_strcmp_value (parser, "token") == 0) { jsonparse_next (parser); jsonparse_next (parser); jsonparse_copy_value (parser, buffer, sizeof (buffer)); user_esp_platform_set_token (buffer); } #endif } } } return 0; } static struct jsontree_callback wifi_station_callback = JSONTREE_CALLBACK (wifi_station_get, wifi_station_set); JSONTREE_OBJECT (get_station_config_tree, JSONTREE_PAIR ("ssid", &wifi_station_callback), JSONTREE_PAIR ("password", &wifi_station_callback)); JSONTREE_OBJECT (set_station_config_tree, JSONTREE_PAIR ("ssid", &wifi_station_callback), JSONTREE_PAIR ("password", &wifi_station_callback), JSONTREE_PAIR ("token", &wifi_station_callback)); JSONTREE_OBJECT (ip_tree, JSONTREE_PAIR ("ip", &wifi_station_callback), JSONTREE_PAIR ("mask", &wifi_station_callback), JSONTREE_PAIR ("gw", &wifi_station_callback)); JSONTREE_OBJECT (get_station_tree, JSONTREE_PAIR ("Connect_Station", &get_station_config_tree), JSONTREE_PAIR ("Ipinfo_Station", &ip_tree)); JSONTREE_OBJECT (set_station_tree, JSONTREE_PAIR ("Connect_Station", &set_station_config_tree)); //JSONTREE_OBJECT(get_wifi_station_info_tree, // JSONTREE_PAIR("Station", &get_station_tree)); //JSONTREE_OBJECT(set_wifi_station_info_tree, // JSONTREE_PAIR("station", &set_station_tree)); /****************************************************************************** * FunctionName : wifi_softap_get * Description : set up the softap paramer as a JSON format * Parameters : js_ctx -- A pointer to a JSON set up * Returns : result *******************************************************************************/ static int ICACHE_FLASH_ATTR wifi_softap_get (struct jsontree_context *js_ctx) { const char *path = jsontree_path_name (js_ctx, js_ctx->depth - 1); struct ip_info ipconfig; uint8 buf[20]; os_bzero (buf, sizeof (buf)); wifi_softap_get_config (ap_conf); wifi_get_ip_info (SOFTAP_IF, &ipconfig); if (os_strncmp (path, "ssid", 4) == 0) { jsontree_write_string (js_ctx, ap_conf->ssid); } else if (os_strncmp (path, "password", 8) == 0) { jsontree_write_string (js_ctx, ap_conf->password); } else if (os_strncmp (path, "channel", 7) == 0) { jsontree_write_int (js_ctx, ap_conf->channel); } else if (os_strncmp (path, "authmode", 8) == 0) { switch (ap_conf->authmode) { case AUTH_OPEN: jsontree_write_string (js_ctx, "OPEN"); break; case AUTH_WEP: jsontree_write_string (js_ctx, "WEP"); break; case AUTH_WPA_PSK: jsontree_write_string (js_ctx, "WPAPSK"); break; case AUTH_WPA2_PSK: jsontree_write_string (js_ctx, "WPA2PSK"); break; case AUTH_WPA_WPA2_PSK: jsontree_write_string (js_ctx, "WPAPSK/WPA2PSK"); break; default: jsontree_write_int (js_ctx, ap_conf->authmode); break; } } else if (os_strncmp (path, "ip", 2) == 0) { os_sprintf (buf, IPSTR, IP2STR (&ipconfig.ip)); jsontree_write_string (js_ctx, buf); } else if (os_strncmp (path, "mask", 4) == 0) { os_sprintf (buf, IPSTR, IP2STR (&ipconfig.netmask)); jsontree_write_string (js_ctx, buf); } else if (os_strncmp (path, "gw", 2) == 0) { os_sprintf (buf, IPSTR, IP2STR (&ipconfig.gw)); jsontree_write_string (js_ctx, buf); } return 0; } /****************************************************************************** * FunctionName : wifi_softap_set * Description : parse the softap parmer as a JSON format * Parameters : js_ctx -- A pointer to a JSON set up * parser -- A pointer to a JSON parser state * Returns : result *******************************************************************************/ static int ICACHE_FLASH_ATTR wifi_softap_set (struct jsontree_context *js_ctx, struct jsonparse_state *parser) { int type; uint8 softap_tree; while ((type = jsonparse_next (parser)) != 0) { if (type == JSON_TYPE_PAIR_NAME) { char buffer[64]; os_bzero (buffer, 64); if (jsonparse_strcmp_value (parser, "Station") == 0) { softap_tree = 0; } else if (jsonparse_strcmp_value (parser, "Softap") == 0) { softap_tree = 1; } if (softap_tree) { if (jsonparse_strcmp_value (parser, "authmode") == 0) { jsonparse_next (parser); jsonparse_next (parser); jsonparse_copy_value (parser, buffer, sizeof (buffer)); // other mode will be supported later... if (os_strcmp (buffer, "OPEN") == 0) { ap_conf->authmode = AUTH_OPEN; } else if (os_strcmp (buffer, "WPAPSK") == 0) { ap_conf->authmode = AUTH_WPA_PSK; os_printf ("%d %s\n", ap_conf->authmode, buffer); } else if (os_strcmp (buffer, "WPA2PSK") == 0) { ap_conf->authmode = AUTH_WPA2_PSK; } else if (os_strcmp (buffer, "WPAPSK/WPA2PSK") == 0) { ap_conf->authmode = AUTH_WPA_WPA2_PSK; } else { ap_conf->authmode = AUTH_OPEN; return 0; } } if (jsonparse_strcmp_value (parser, "channel") == 0) { jsonparse_next (parser); jsonparse_next (parser); ap_conf->channel = jsonparse_get_value_as_int (parser); } else if (jsonparse_strcmp_value (parser, "ssid") == 0) { jsonparse_next (parser); jsonparse_next (parser); jsonparse_copy_value (parser, buffer, sizeof (buffer)); os_memcpy (ap_conf->ssid, buffer, os_strlen (buffer)); } else if (jsonparse_strcmp_value (parser, "password") == 0) { jsonparse_next (parser); jsonparse_next (parser); jsonparse_copy_value (parser, buffer, sizeof (buffer)); os_memcpy (ap_conf->password, buffer, os_strlen (buffer)); } } } } return 0; } static struct jsontree_callback wifi_softap_callback = JSONTREE_CALLBACK (wifi_softap_get, wifi_softap_set); JSONTREE_OBJECT (softap_config_tree, JSONTREE_PAIR ("authmode", &wifi_softap_callback), JSONTREE_PAIR ("channel", &wifi_softap_callback), JSONTREE_PAIR ("ssid", &wifi_softap_callback), JSONTREE_PAIR ("password", &wifi_softap_callback)); JSONTREE_OBJECT (softap_ip_tree, JSONTREE_PAIR ("ip", &wifi_softap_callback), JSONTREE_PAIR ("mask", &wifi_softap_callback), JSONTREE_PAIR ("gw", &wifi_softap_callback)); JSONTREE_OBJECT (get_softap_tree, JSONTREE_PAIR ("Connect_Softap", &softap_config_tree), JSONTREE_PAIR ("Ipinfo_Softap", &softap_ip_tree)); JSONTREE_OBJECT (set_softap_tree, JSONTREE_PAIR ("Ipinfo_Softap", &softap_config_tree)); JSONTREE_OBJECT (get_wifi_tree, JSONTREE_PAIR ("Station", &get_station_tree), JSONTREE_PAIR ("Softap", &get_softap_tree)); JSONTREE_OBJECT (set_wifi_tree, JSONTREE_PAIR ("Station", &set_station_tree), JSONTREE_PAIR ("Softap", &set_softap_tree)); JSONTREE_OBJECT (wifi_response_tree, JSONTREE_PAIR ("Response", &get_wifi_tree)); JSONTREE_OBJECT (wifi_request_tree, JSONTREE_PAIR ("Request", &set_wifi_tree)); JSONTREE_OBJECT (wifi_info_tree, JSONTREE_PAIR ("wifi", &wifi_response_tree)); JSONTREE_OBJECT (wifi_req_tree, JSONTREE_PAIR ("wifi", &wifi_request_tree)); /****************************************************************************** * FunctionName : scan_get * Description : set up the scan data as a JSON format * Parameters : js_ctx -- A pointer to a JSON set up * Returns : result *******************************************************************************/ static int ICACHE_FLASH_ATTR scan_get (struct jsontree_context *js_ctx) { const char *path = jsontree_path_name (js_ctx, js_ctx->depth - 1); // STAILQ_HEAD(, bss_info) *pbss = scanarg; static struct bss_info *bss; if (os_strncmp (path, "TotalPage", 9) == 0) { jsontree_write_int (js_ctx, pscaninfo->totalpage); } else if (os_strncmp (path, "PageNum", 7) == 0) { jsontree_write_int (js_ctx, pscaninfo->pagenum); } else if (os_strncmp (path, "bssid", 5) == 0) { bss = STAILQ_FIRST (pscaninfo->pbss); u8 buffer[32]; //if (bss != NULL){ os_memset (buffer, 0, sizeof (buffer)); os_sprintf (buffer, MACSTR, MAC2STR (bss->bssid)); jsontree_write_string (js_ctx, buffer); //} } else if (os_strncmp (path, "ssid", 4) == 0) { //if (bss != NULL) jsontree_write_string (js_ctx, bss->ssid); } else if (os_strncmp (path, "rssi", 4) == 0) { //if (bss != NULL) jsontree_write_int (js_ctx, -(bss->rssi)); } else if (os_strncmp (path, "channel", 7) == 0) { //if (bss != NULL) jsontree_write_int (js_ctx, bss->channel); } else if (os_strncmp (path, "authmode", 8) == 0) { //if (bss != NULL){ switch (bss->authmode) { case AUTH_OPEN: jsontree_write_string (js_ctx, "OPEN"); break; case AUTH_WEP: jsontree_write_string (js_ctx, "WEP"); break; case AUTH_WPA_PSK: jsontree_write_string (js_ctx, "WPAPSK"); break; case AUTH_WPA2_PSK: jsontree_write_string (js_ctx, "WPA2PSK"); break; case AUTH_WPA_WPA2_PSK: jsontree_write_string (js_ctx, "WPAPSK/WPA2PSK"); break; default: jsontree_write_int (js_ctx, bss->authmode); break; } STAILQ_REMOVE_HEAD (pscaninfo->pbss, next); os_free (bss); //} } return 0; } static struct jsontree_callback scan_callback = JSONTREE_CALLBACK (scan_get, NULL); JSONTREE_OBJECT (scaninfo_tree, JSONTREE_PAIR ("bssid", &scan_callback), JSONTREE_PAIR ("ssid", &scan_callback), JSONTREE_PAIR ("rssi", &scan_callback), JSONTREE_PAIR ("channel", &scan_callback), JSONTREE_PAIR ("authmode", &scan_callback)); JSONTREE_ARRAY (scanrslt_tree, JSONTREE_PAIR_ARRAY (&scaninfo_tree), JSONTREE_PAIR_ARRAY (&scaninfo_tree), JSONTREE_PAIR_ARRAY (&scaninfo_tree), JSONTREE_PAIR_ARRAY (&scaninfo_tree), JSONTREE_PAIR_ARRAY (&scaninfo_tree), JSONTREE_PAIR_ARRAY (&scaninfo_tree), JSONTREE_PAIR_ARRAY (&scaninfo_tree), JSONTREE_PAIR_ARRAY (&scaninfo_tree)); JSONTREE_OBJECT (scantree, JSONTREE_PAIR ("TotalPage", &scan_callback), JSONTREE_PAIR ("PageNum", &scan_callback), JSONTREE_PAIR ("ScanResult", &scanrslt_tree)); JSONTREE_OBJECT (scanres_tree, JSONTREE_PAIR ("Response", &scantree)); JSONTREE_OBJECT (scan_tree, JSONTREE_PAIR ("scan", &scanres_tree)); /****************************************************************************** * FunctionName : parse_url * Description : parse the received data from the server * Parameters : precv -- the received data * purl_frame -- the result of parsing the url * Returns : none *******************************************************************************/ static void ICACHE_FLASH_ATTR parse_url (char *precv, URL_Frame * purl_frame) { char *str = NULL; uint8 length = 0; char *pbuffer = NULL; char *pbufer = NULL; if (purl_frame == NULL || precv == NULL) { return; } pbuffer = (char *) os_strstr (precv, "Host:"); if (pbuffer != NULL) { length = pbuffer - precv; pbufer = (char *) os_zalloc (length + 1); pbuffer = pbufer; os_memcpy (pbuffer, precv, length); os_memset (purl_frame->pSelect, 0, URLSize); os_memset (purl_frame->pCommand, 0, URLSize); os_memset (purl_frame->pFilename, 0, URLSize); if (os_strncmp (pbuffer, "GET ", 4) == 0) { purl_frame->Type = GET; pbuffer += 4; } else if (os_strncmp (pbuffer, "POST ", 5) == 0) { purl_frame->Type = POST; pbuffer += 5; } pbuffer++; str = (char *) os_strstr (pbuffer, "?"); if (str != NULL) { length = str - pbuffer; os_memcpy (purl_frame->pSelect, pbuffer, length); str++; pbuffer = (char *) os_strstr (str, "="); if (pbuffer != NULL) { length = pbuffer - str; os_memcpy (purl_frame->pCommand, str, length); pbuffer++; str = (char *) os_strstr (pbuffer, "&"); if (str != NULL) { length = str - pbuffer; os_memcpy (purl_frame->pFilename, pbuffer, length); } else { str = (char *) os_strstr (pbuffer, " HTTP"); if (str != NULL) { length = str - pbuffer; os_memcpy (purl_frame->pFilename, pbuffer, length); } } } } os_free (pbufer); } else { return; } } static char *precvbuffer; static uint32 dat_sumlength = 0; static bool ICACHE_FLASH_ATTR save_data (char *precv, uint16 length) { bool flag = false; char length_buf[10] = { 0 }; char *ptemp = NULL; char *pdata = NULL; uint16 headlength = 0; static uint32 totallength = 0; ptemp = (char *) os_strstr (precv, "\r\n\r\n"); if (ptemp != NULL) { length -= ptemp - precv; length -= 4; totallength += length; headlength = ptemp - precv + 4; pdata = (char *) os_strstr (precv, "Content-Length: "); if (pdata != NULL) { pdata += 16; precvbuffer = (char *) os_strstr (pdata, "\r\n"); if (precvbuffer != NULL) { os_memcpy (length_buf, pdata, precvbuffer - pdata); dat_sumlength = atoi (length_buf); } } else { if (totallength != 0x00) { totallength = 0; dat_sumlength = 0; return false; } } if ((dat_sumlength + headlength) >= 1024) { precvbuffer = (char *) os_zalloc (headlength + 1); os_memcpy (precvbuffer, precv, headlength + 1); } else { precvbuffer = (char *) os_zalloc (dat_sumlength + headlength + 1); os_memcpy (precvbuffer, precv, os_strlen (precv)); } } else { if (precvbuffer != NULL) { totallength += length; os_memcpy (precvbuffer + os_strlen (precvbuffer), precv, length); } else { totallength = 0; dat_sumlength = 0; return false; } } if (totallength == dat_sumlength) { totallength = 0; dat_sumlength = 0; return true; } else { return false; } } static bool ICACHE_FLASH_ATTR check_data (char *precv, uint16 length) { //bool flag = true; char length_buf[10] = { 0 }; char *ptemp = NULL; char *pdata = NULL; char *tmp_precvbuffer; uint16 tmp_length = length; uint32 tmp_totallength = 0; ptemp = (char *) os_strstr (precv, "\r\n\r\n"); if (ptemp != NULL) { tmp_length -= ptemp - precv; tmp_length -= 4; tmp_totallength += tmp_length; pdata = (char *) os_strstr (precv, "Content-Length: "); if (pdata != NULL) { pdata += 16; tmp_precvbuffer = (char *) os_strstr (pdata, "\r\n"); if (tmp_precvbuffer != NULL) { os_memcpy (length_buf, pdata, tmp_precvbuffer - pdata); dat_sumlength = atoi (length_buf); os_printf ("A_dat:%u,tot:%u,lenght:%u\n", dat_sumlength, tmp_totallength, tmp_length); if (dat_sumlength != tmp_totallength) { return false; } } } } return true; } static os_timer_t *restart_10ms; static rst_parm *rstparm; /****************************************************************************** * FunctionName : restart_10ms_cb * Description : system restart or wifi reconnected after a certain time. * Parameters : arg -- Additional argument to pass to the function * Returns : none *******************************************************************************/ static void ICACHE_FLASH_ATTR restart_10ms_cb (void *arg) { if (rstparm != NULL && rstparm->pespconn != NULL) { switch (rstparm->parmtype) { case WIFI: //if (rstparm->pespconn->state == ESPCONN_CLOSE) { if (sta_conf->ssid[0] != 0x00) { wifi_station_set_config (sta_conf); wifi_station_disconnect (); wifi_station_connect (); user_esp_platform_check_ip (1); } if (ap_conf->ssid[0] != 0x00) { wifi_softap_set_config (ap_conf); system_restart (); } os_free (ap_conf); ap_conf = NULL; os_free (sta_conf); sta_conf = NULL; os_free (rstparm); rstparm = NULL; os_free (restart_10ms); restart_10ms = NULL; //} else { // os_timer_arm(restart_10ms, 10, 0); //} break; case DEEP_SLEEP: case REBOOT: if (rstparm->pespconn->state == ESPCONN_CLOSE) { wifi_set_opmode (STATION_MODE); if (rstparm->parmtype == DEEP_SLEEP) { #if SENSOR_DEVICE system_deep_sleep (SENSOR_DEEP_SLEEP_TIME); #endif } } else { os_timer_arm (restart_10ms, 10, 0); } break; default: break; } } } /****************************************************************************** * FunctionName : data_send * Description : processing the data as http format and send to the client or server * Parameters : arg -- argument to set for client or server * responseOK -- true or false * psend -- The send data * Returns : *******************************************************************************/ static void ICACHE_FLASH_ATTR data_send (void *arg, bool responseOK, char *psend) { uint16 length = 0; char *pbuf = NULL; char httphead[256]; struct espconn *ptrespconn = arg; os_memset (httphead, 0, 256); if (responseOK) { os_sprintf (httphead, "HTTP/1.0 200 OK\r\nContent-Length: %d\r\nServer: lwIP/1.4.0\r\n", psend ? os_strlen (psend) : 0); if (psend) { os_sprintf (httphead + os_strlen (httphead), "Content-type: application/json\r\nExpires: Fri, 10 Apr 2008 14:00:00 GMT\r\nPragma: no-cache\r\n\r\n"); length = os_strlen (httphead) + os_strlen (psend); pbuf = (char *) os_zalloc (length + 1); os_memcpy (pbuf, httphead, os_strlen (httphead)); os_memcpy (pbuf + os_strlen (httphead), psend, os_strlen (psend)); } else { os_sprintf (httphead + os_strlen (httphead), "\n"); length = os_strlen (httphead); } } else { os_sprintf (httphead, "HTTP/1.0 400 BadRequest\r\n\ Content-Length: 0\r\nServer: lwIP/1.4.0\r\n\n"); length = os_strlen (httphead); } if (psend) { #ifdef SERVER_SSL_ENABLE espconn_secure_sent (ptrespconn, pbuf, length); #else espconn_sent (ptrespconn, pbuf, length); #endif } else { #ifdef SERVER_SSL_ENABLE espconn_secure_sent (ptrespconn, httphead, length); #else espconn_sent (ptrespconn, httphead, length); #endif } if (pbuf) { os_free (pbuf); pbuf = NULL; } } /****************************************************************************** * FunctionName : json_send * Description : processing the data as json format and send to the client or server * Parameters : arg -- argument to set for client or server * ParmType -- json format type * Returns : none *******************************************************************************/ static void ICACHE_FLASH_ATTR json_send (void *arg, ParmType ParmType) { char *pbuf = NULL; pbuf = (char *) os_zalloc (jsonSize); struct espconn *ptrespconn = arg; switch (ParmType) { #if LIGHT_DEVICE case LIGHT_STATUS: json_ws_send ((struct jsontree_value *) &PwmTree, "light", pbuf); break; #endif #if PLUG_DEVICE case SWITCH_STATUS: json_ws_send ((struct jsontree_value *) &StatusTree, "switch", pbuf); break; #endif case INFOMATION: json_ws_send ((struct jsontree_value *) &INFOTree, "info", pbuf); break; case WIFI: json_ws_send ((struct jsontree_value *) &wifi_info_tree, "wifi", pbuf); break; case CONNECT_STATUS: json_ws_send ((struct jsontree_value *) &con_status_tree, "info", pbuf); break; case USER_BIN: json_ws_send ((struct jsontree_value *) &userinfo_tree, "user_info", pbuf); break; case SCAN: { u8 i = 0; u8 scancount = 0; struct bss_info *bss = NULL; bss = STAILQ_FIRST (pscaninfo->pbss); if (bss == NULL) { os_free (pscaninfo); pscaninfo = NULL; os_sprintf (pbuf, "{\n\"successful\": false,\n\"data\": null\n}"); } else { do { if (pscaninfo->page_sn == pscaninfo->pagenum) { pscaninfo->page_sn = 0; os_sprintf (pbuf, "{\n\"successful\": false,\n\"meessage\": \"repeated page\"\n}"); break; } scancount = scannum - (pscaninfo->pagenum - 1) * 8; if (scancount >= 8) { pscaninfo->data_cnt += 8; pscaninfo->page_sn = pscaninfo->pagenum; if (pscaninfo->data_cnt > scannum) { pscaninfo->data_cnt -= 8; os_sprintf (pbuf, "{\n\"successful\": false,\n\"meessage\": \"error page\"\n}"); break; } json_ws_send ((struct jsontree_value *) &scan_tree, "scan", pbuf); } else { pscaninfo->data_cnt += scancount; pscaninfo->page_sn = pscaninfo->pagenum; if (pscaninfo->data_cnt > scannum) { pscaninfo->data_cnt -= scancount; os_sprintf (pbuf, "{\n\"successful\": false,\n\"meessage\": \"error page\"\n}"); break; } char *ptrscanbuf = (char *) os_zalloc (jsonSize); char *pscanbuf = ptrscanbuf; os_sprintf (pscanbuf, ",\n\"ScanResult\": [\n"); pscanbuf += os_strlen (pscanbuf); for (i = 0; i < scancount; i++) { JSONTREE_OBJECT (page_tree, JSONTREE_PAIR ("page", &scaninfo_tree)); json_ws_send ((struct jsontree_value *) &page_tree, "page", pscanbuf); os_sprintf (pscanbuf + os_strlen (pscanbuf), ",\n"); pscanbuf += os_strlen (pscanbuf); } os_sprintf (pscanbuf - 2, "]\n"); JSONTREE_OBJECT (scantree, JSONTREE_PAIR ("TotalPage", &scan_callback), JSONTREE_PAIR ("PageNum", &scan_callback)); JSONTREE_OBJECT (scanres_tree, JSONTREE_PAIR ("Response", &scantree)); JSONTREE_OBJECT (scan_tree, JSONTREE_PAIR ("scan", &scanres_tree)); json_ws_send ((struct jsontree_value *) &scan_tree, "scan", pbuf); os_memcpy (pbuf + os_strlen (pbuf) - 4, ptrscanbuf, os_strlen (ptrscanbuf)); os_sprintf (pbuf + os_strlen (pbuf), "}\n}"); os_free (ptrscanbuf); } } while (0); } break; } default: break; } data_send (ptrespconn, true, pbuf); os_free (pbuf); pbuf = NULL; } /****************************************************************************** * FunctionName : response_send * Description : processing the send result * Parameters : arg -- argument to set for client or server * responseOK -- true or false * Returns : none *******************************************************************************/ static void ICACHE_FLASH_ATTR response_send (void *arg, bool responseOK) { struct espconn *ptrespconn = arg; data_send (ptrespconn, responseOK, NULL); } /****************************************************************************** * FunctionName : json_scan_cb * Description : processing the scan result * Parameters : arg -- Additional argument to pass to the callback function * status -- scan status * Returns : none *******************************************************************************/ static void ICACHE_FLASH_ATTR json_scan_cb (void *arg, STATUS status) { pscaninfo->pbss = arg; if (scannum % 8 == 0) { pscaninfo->totalpage = scannum / 8; } else { pscaninfo->totalpage = scannum / 8 + 1; } JSONTREE_OBJECT (totaltree, JSONTREE_PAIR ("TotalPage", &scan_callback)); JSONTREE_OBJECT (totalres_tree, JSONTREE_PAIR ("Response", &totaltree)); JSONTREE_OBJECT (total_tree, JSONTREE_PAIR ("total", &totalres_tree)); char *pbuf = NULL; pbuf = (char *) os_zalloc (jsonSize); json_ws_send ((struct jsontree_value *) &total_tree, "total", pbuf); data_send (pscaninfo->pespconn, true, pbuf); os_free (pbuf); } void ICACHE_FLASH_ATTR upgrade_check_func (void *arg) { struct espconn *ptrespconn = arg; os_timer_disarm (&upgrade_check_timer); if (system_upgrade_flag_check () == UPGRADE_FLAG_START) { response_send (ptrespconn, false); system_upgrade_deinit (); system_upgrade_flag_set (UPGRADE_FLAG_IDLE); upgrade_lock = 0; os_printf ("local upgrade failed\n"); } else if (system_upgrade_flag_check () == UPGRADE_FLAG_FINISH) { os_printf ("local upgrade success\n"); response_send (ptrespconn, true); upgrade_lock = 0; } else { } } /****************************************************************************** * FunctionName : upgrade_deinit * Description : disconnect the connection with the host * Parameters : bin -- server number * Returns : none *******************************************************************************/ void ICACHE_FLASH_ATTR static local_upgrade_deinit (void) { if (system_upgrade_flag_check () != UPGRADE_FLAG_START) { os_printf ("system upgrade deinit\n"); system_upgrade_deinit (); } } /****************************************************************************** * FunctionName : upgrade_download * Description : Processing the upgrade data from the host * Parameters : bin -- server number * pusrdata -- The upgrade data (or NULL when the connection has been closed!) * length -- The length of upgrade data * Returns : none *******************************************************************************/ static void ICACHE_FLASH_ATTR local_upgrade_download (void *arg, char *pusrdata, unsigned short length) { char *ptr = NULL; char *ptmp2 = NULL; char lengthbuffer[32]; static uint32 totallength = 0; static uint32 sumlength = 0; char A_buf[2] = { 0xE9, 0x03 }; char B_buf[2] = { 0xEA, 0x04 }; struct espconn *pespconn = arg; if (totallength == 0 && (ptr = (char *) os_strstr (pusrdata, "\r\n\r\n")) != NULL && (ptr = (char *) os_strstr (pusrdata, "Content-Length")) != NULL) { ptr = (char *) os_strstr (pusrdata, "Content-Length: "); if (ptr != NULL) { ptr += 16; ptmp2 = (char *) os_strstr (ptr, "\r\n"); if (ptmp2 != NULL) { os_memset (lengthbuffer, 0, sizeof (lengthbuffer)); os_memcpy (lengthbuffer, ptr, ptmp2 - ptr); sumlength = atoi (lengthbuffer); } else { os_printf ("sumlength failed\n"); } } else { os_printf ("Content-Length: failed\n"); } if (sumlength != 0) { system_upgrade_erase_flash (sumlength); } ptr = (char *) os_strstr (pusrdata, "\r\n\r\n"); length -= ptr - pusrdata; length -= 4; totallength += length; os_printf ("upgrade file download start.\n"); system_upgrade (ptr + 4, length); } else { totallength += length; system_upgrade (pusrdata, length); } if (totallength == sumlength) { os_printf ("upgrade file download finished.\n"); system_upgrade_flag_set (UPGRADE_FLAG_FINISH); totallength = 0; sumlength = 0; upgrade_check_func (pespconn); os_timer_disarm (&app_upgrade_10s); os_timer_setfn (&app_upgrade_10s, (os_timer_func_t *) local_upgrade_deinit, NULL); os_timer_arm (&app_upgrade_10s, 10, 0); } } /****************************************************************************** * FunctionName : webserver_recv * Description : Processing the received data from the server * Parameters : arg -- Additional argument to pass to the callback function * pusrdata -- The received data (or NULL when the connection has been closed!) * length -- The length of received data * Returns : none *******************************************************************************/ static void ICACHE_FLASH_ATTR webserver_recv (void *arg, char *pusrdata, unsigned short length) { URL_Frame *pURL_Frame = NULL; char *pParseBuffer = NULL; bool parse_flag = false; struct espconn *ptrespconn = arg; if (upgrade_lock == 0) { os_printf ("len:%u\n", length); if (check_data (pusrdata, length) == false) { os_printf ("goto\n"); goto _temp_exit; } parse_flag = save_data (pusrdata, length); if (parse_flag == false) { response_send (ptrespconn, false); } // os_printf(precvbuffer); pURL_Frame = (URL_Frame *) os_zalloc (sizeof (URL_Frame)); parse_url (precvbuffer, pURL_Frame); switch (pURL_Frame->Type) { case GET: os_printf ("We have a GET request.\n"); if (os_strcmp (pURL_Frame->pSelect, "client") == 0 && os_strcmp (pURL_Frame->pCommand, "command") == 0) { if (os_strcmp (pURL_Frame->pFilename, "info") == 0) { json_send (ptrespconn, INFOMATION); } if (os_strcmp (pURL_Frame->pFilename, "status") == 0) { json_send (ptrespconn, CONNECT_STATUS); } else if (os_strcmp (pURL_Frame->pFilename, "scan") == 0) { char *strstr = NULL; strstr = (char *) os_strstr (pusrdata, "&"); if (strstr == NULL) { if (pscaninfo == NULL) { pscaninfo = (scaninfo *) os_zalloc (sizeof (scaninfo)); } pscaninfo->pespconn = ptrespconn; pscaninfo->pagenum = 0; pscaninfo->page_sn = 0; pscaninfo->data_cnt = 0; wifi_station_scan (NULL, json_scan_cb); } else { strstr++; if (os_strncmp (strstr, "page", 4) == 0) { if (pscaninfo != NULL) { pscaninfo->pagenum = *(strstr + 5); pscaninfo->pagenum -= 0x30; if (pscaninfo->pagenum > pscaninfo->totalpage || pscaninfo->pagenum == 0) { response_send (ptrespconn, false); } else { json_send (ptrespconn, SCAN); } } else { response_send (ptrespconn, false); } } else { response_send (ptrespconn, false); } } } else { response_send (ptrespconn, false); } } else if (os_strcmp (pURL_Frame->pSelect, "config") == 0 && os_strcmp (pURL_Frame->pCommand, "command") == 0) { if (os_strcmp (pURL_Frame->pFilename, "wifi") == 0) { ap_conf = (struct softap_config *) os_zalloc (sizeof (struct softap_config)); sta_conf = (struct station_config *) os_zalloc (sizeof (struct station_config)); json_send (ptrespconn, WIFI); os_free (sta_conf); os_free (ap_conf); sta_conf = NULL; ap_conf = NULL; } #if PLUG_DEVICE else if (os_strcmp (pURL_Frame->pFilename, "switch") == 0) { json_send (ptrespconn, SWITCH_STATUS); } #endif #if LIGHT_DEVICE else if (os_strcmp (pURL_Frame->pFilename, "light") == 0) { json_send (ptrespconn, LIGHT_STATUS); } #endif else if (os_strcmp (pURL_Frame->pFilename, "reboot") == 0) { json_send (ptrespconn, REBOOT); } else { response_send (ptrespconn, false); } } else if (os_strcmp (pURL_Frame->pSelect, "upgrade") == 0 && os_strcmp (pURL_Frame->pCommand, "command") == 0) { if (os_strcmp (pURL_Frame->pFilename, "getuser") == 0) { json_send (ptrespconn, USER_BIN); } } else { response_send (ptrespconn, false); } break; case POST: os_printf ("We have a POST request.\n"); pParseBuffer = (char *) os_strstr (precvbuffer, "\r\n\r\n"); if (pParseBuffer == NULL) { break; } pParseBuffer += 4; if (os_strcmp (pURL_Frame->pSelect, "config") == 0 && os_strcmp (pURL_Frame->pCommand, "command") == 0) { #if SENSOR_DEVICE if (os_strcmp (pURL_Frame->pFilename, "sleep") == 0) { #else if (os_strcmp (pURL_Frame->pFilename, "reboot") == 0) { #endif if (pParseBuffer != NULL) { if (restart_10ms != NULL) { os_timer_disarm (restart_10ms); } if (rstparm == NULL) { rstparm = (rst_parm *) os_zalloc (sizeof (rst_parm)); } rstparm->pespconn = ptrespconn; #if SENSOR_DEVICE rstparm->parmtype = DEEP_SLEEP; #else rstparm->parmtype = REBOOT; #endif if (restart_10ms == NULL) { restart_10ms = (os_timer_t *) os_malloc (sizeof (os_timer_t)); } os_timer_setfn (restart_10ms, (os_timer_func_t *) restart_10ms_cb, NULL); os_timer_arm (restart_10ms, 10, 0); // delay 10ms, then do response_send (ptrespconn, true); } else { response_send (ptrespconn, false); } } else if (os_strcmp (pURL_Frame->pFilename, "wifi") == 0) { if (pParseBuffer != NULL) { struct jsontree_context js; user_esp_platform_set_connect_status (DEVICE_CONNECTING); if (restart_10ms != NULL) { os_timer_disarm (restart_10ms); } if (ap_conf == NULL) { ap_conf = (struct softap_config *) os_zalloc (sizeof (struct softap_config)); } if (sta_conf == NULL) { sta_conf = (struct station_config *) os_zalloc (sizeof (struct station_config)); } jsontree_setup (&js, (struct jsontree_value *) &wifi_req_tree, json_putchar); json_parse (&js, pParseBuffer); if (rstparm == NULL) { rstparm = (rst_parm *) os_zalloc (sizeof (rst_parm)); } rstparm->pespconn = ptrespconn; rstparm->parmtype = WIFI; if (sta_conf->ssid[0] != 0x00 || ap_conf->ssid[0] != 0x00) { ap_conf->ssid_hidden = 0; ap_conf->max_connection = 4; if (restart_10ms == NULL) { restart_10ms = (os_timer_t *) os_malloc (sizeof (os_timer_t)); } os_timer_disarm (restart_10ms); os_timer_setfn (restart_10ms, (os_timer_func_t *) restart_10ms_cb, NULL); os_timer_arm (restart_10ms, 10, 0); // delay 10ms, then do } else { os_free (ap_conf); os_free (sta_conf); os_free (rstparm); sta_conf = NULL; ap_conf = NULL; rstparm = NULL; } response_send (ptrespconn, true); } else { response_send (ptrespconn, false); } } #if PLUG_DEVICE else if (os_strcmp (pURL_Frame->pFilename, "switch") == 0) { if (pParseBuffer != NULL) { struct jsontree_context js; jsontree_setup (&js, (struct jsontree_value *) &StatusTree, json_putchar); json_parse (&js, pParseBuffer); response_send (ptrespconn, true); } else { response_send (ptrespconn, false); } } #endif #if LIGHT_DEVICE else if (os_strcmp (pURL_Frame->pFilename, "light") == 0) { if (pParseBuffer != NULL) { struct jsontree_context js; jsontree_setup (&js, (struct jsontree_value *) &PwmTree, json_putchar); json_parse (&js, pParseBuffer); os_printf ("rsp1:%u\n", PostCmdNeeRsp); if (PostCmdNeeRsp == 0) PostCmdNeeRsp = 1; else response_send (ptrespconn, true); } else { response_send (ptrespconn, false); } } else if (os_strcmp (pURL_Frame->pFilename, "reset") == 0) { response_send (ptrespconn, true); extern struct esp_platform_saved_param esp_param; esp_param.activeflag = 0; system_param_save_with_protect (ESP_PARAM_START_SEC, &esp_param, sizeof (esp_param)); system_restore (); system_restart (); } #endif else { response_send (ptrespconn, false); } } else if (os_strcmp (pURL_Frame->pSelect, "upgrade") == 0 && os_strcmp (pURL_Frame->pCommand, "command") == 0) { if (os_strcmp (pURL_Frame->pFilename, "start") == 0) { response_send (ptrespconn, true); os_printf ("local upgrade start\n"); upgrade_lock = 1; system_upgrade_init (); system_upgrade_flag_set (UPGRADE_FLAG_START); os_timer_disarm (&upgrade_check_timer); os_timer_setfn (&upgrade_check_timer, (os_timer_func_t *) upgrade_check_func, NULL); os_timer_arm (&upgrade_check_timer, 120000, 0); } else if (os_strcmp (pURL_Frame->pFilename, "reset") == 0) { response_send (ptrespconn, true); os_printf ("local upgrade restart\n"); system_upgrade_reboot (); } else { response_send (ptrespconn, false); } } else { response_send (ptrespconn, false); } break; } if (precvbuffer != NULL) { os_free (precvbuffer); precvbuffer = NULL; } os_free (pURL_Frame); pURL_Frame = NULL; _temp_exit: ; } else if (upgrade_lock == 1) { local_upgrade_download (ptrespconn, pusrdata, length); if (precvbuffer != NULL) { os_free (precvbuffer); precvbuffer = NULL; } os_free (pURL_Frame); pURL_Frame = NULL; } } /****************************************************************************** * FunctionName : webserver_recon * Description : the connection has been err, reconnection * Parameters : arg -- Additional argument to pass to the callback function * Returns : none *******************************************************************************/ static ICACHE_FLASH_ATTR void webserver_recon (void *arg, sint8 err) { struct espconn *pesp_conn = arg; os_printf ("webserver's %d.%d.%d.%d:%d err %d reconnect\n", pesp_conn->proto.tcp->remote_ip[0], pesp_conn->proto.tcp->remote_ip[1], pesp_conn->proto.tcp->remote_ip[2], pesp_conn->proto.tcp->remote_ip[3], pesp_conn->proto.tcp->remote_port, err); } /****************************************************************************** * FunctionName : webserver_recon * Description : the connection has been err, reconnection * Parameters : arg -- Additional argument to pass to the callback function * Returns : none *******************************************************************************/ static ICACHE_FLASH_ATTR void webserver_discon (void *arg) { struct espconn *pesp_conn = arg; os_printf ("webserver's %d.%d.%d.%d:%d disconnect\n", pesp_conn->proto.tcp->remote_ip[0], pesp_conn->proto.tcp->remote_ip[1], pesp_conn->proto.tcp->remote_ip[2], pesp_conn->proto.tcp->remote_ip[3], pesp_conn->proto.tcp->remote_port); } /****************************************************************************** * FunctionName : user_accept_listen * Description : server listened a connection successfully * Parameters : arg -- Additional argument to pass to the callback function * Returns : none *******************************************************************************/ static void ICACHE_FLASH_ATTR webserver_listen (void *arg) { struct espconn *pesp_conn = arg; espconn_regist_recvcb (pesp_conn, webserver_recv); espconn_regist_reconcb (pesp_conn, webserver_recon); espconn_regist_disconcb (pesp_conn, webserver_discon); } /****************************************************************************** * FunctionName : user_webserver_init * Description : parameter initialize as a server * Parameters : port -- server port * Returns : none *******************************************************************************/ #endif