⬆️ ⬇️

Working with ESP8266: Writing firmware to control the system nooLite

In previous articles, we looked at working with SoC Espressif ESP8266 on the example of working with basic AT firmware, building a compiler and writing your own firmware with the implementation of a TCP server (client). In this article, we will look at an example of writing firmware for working with the nooLite MT1132 transmitter module and try to control the lighting in a real apartment. Anyone who cares, I ask under habrakat.





To write the firmware, we will use Eclipse Luna and my Unofficial Development Kit for Espressif ESP8266 (it is worth noting that I recently updated it, now Python is not required for its work, libhal.a has been updated, and many examples have been added: 1wire_ds18b20, dht22, blinky, blinky2, i2c_24xx16, i2c_htu21d, etc.), I told about it in the last article .



For work we need the following materials and devices:

1. Board ESP-01 with chip ESP8266.

2. Module MT1132, you can buy in this online store or this .

3. Specification for ESP8266 chip .

4. Description of the ESP8266 SDK .

5. Manual for the module nooLite MT1132 .

')

The nooLite developers described in detail the MT1132 module in the documentation, and also gave an example of the scratch for the module to work with the Arduino , so there were no difficulties with connecting the module to the ESP-01 board.



The final wiring diagram:


In the firmware we implement 2 modes of operation ESP-01:

1. Configuration mode. In this mode, it will be possible to set the parameters for connecting ESP-01 to our AP via the Web interface, and set a unique ID for our card. The ID will only be used to identify the board, if we have several of them on the network.

2. Main mode. Through the Web interface in this mode, it will be possible to bind-untie the MT1132 module from the power blocks, turn the nooLite power blocks on and off.



A brief algorithm for the firmware is:

1. After powering on, we read wi-fi settings and configuration from memory, if there are no settings or wi-fi in STA mode, then we transfer wi-fi to STA-AP mode, give the AP the name NOOLITE_% MACADDRESS%, password% MACADDRESS%, start the web server in configuration mode.

2. Using a simple Web interface, we set the connection parameters to the AP, the ESP-01 board will connect to this AP in the main mode. Set the board ID. Save the settings in flash. Restart board to main mode.

3. In the main mode, a simple Web-server is started, through which you can bind-untie the module MT1132 from the power blocks, turn on / off the power blocks of nooLite.

4. We connect a regular button to GPIO0, the button closure to earth brings the ESP-01 back to the configuration mode.

5. To GPIO16 (in fact, the Chinese have deceived and this is not the GPIO output, but the RESET output) we connect a conventional button, closing the button to the ground produces a hardware reset of the board.



Now let's start writing the code (I’ll say right away that the implementation of the web server was borrowed from the elektronika-ba project):

The firmware consists of 6 main files:

driver \ uart.c - UART driver, it modified the uart0_rx_intr_handler procedure for receiving and parsing a response from MT1132;

user \ user_main.c - the main file, but not the main one;

user \ flash_param.c - work with flash-memory;

user \ noolite_platform.c - the main functions, all the logic of switching between different modes;

user \ noolite_config_server.c - configuration web-server;

user \ noolite_control_server.c - main mode web server, sending MT1132 commands;



Let's sort each file in order, under the spooler there will be a lot of code with comments:



User_main.c file
#include "ets_sys.h" #include "osapi.h" #include "noolite_platform.h" #include "driver/uart.h" extern int ets_uart_printf(const char *fmt, ...); void user_init(void) { //  UART   9600, ..  MT1132      uart_init(BIT_RATE_9600, BIT_RATE_9600); #ifdef NOOLITE_LOGGING ets_uart_printf("nooLite platform starting...\r\n"); #endif //      noolite_platform.c noolite_platform_init(); #ifdef NOOLITE_LOGGING ets_uart_printf("nooLite platform started!\r\n"); #endif } 


File noolite_platform.c
 #include "ets_sys.h" #include "osapi.h" #include "user_interface.h" #include "mem.h" #include "espconn.h" #include "os_type.h" #include "driver/uart.h" #include "gpio.h" #include "flash_param.h" #include "noolite_platform.h" #include "noolite_config_server.h" #include "noolite_control_server.h" //     wi-fi   AP os_timer_t WiFiLinker; //      os_timer_t DebounceTimer; static tConnState connState = WIFI_CONNECTING; uint16_t wifiErrorConnect = 0; uint16_t controlServerStatus = 0; LOCAL void input_intr_handler(void *arg); void ICACHE_FLASH_ATTR debounce_timer_cb(void *arg); //    wi-fi   AP static void ICACHE_FLASH_ATTR noolite_platform_check_ip(void *arg) { //   .   ip struct ip_info ipconfig; // .   os_timer_disarm(&WiFiLinker); //   IP wifi_get_ip_info(STATION_IF, &ipconfig); //     AP   IP  //   ,   web-    if (wifi_station_get_connect_status() == STATION_GOT_IP && ipconfig.ip.addr != 0) { connState = WIFI_CONNECTED; #ifdef NOOLITE_LOGGING char temp[80]; ets_uart_printf("WiFi connected\r\n"); os_sprintf(temp, "Client IP address: " IPSTR "\r\n", IP2STR(&ipconfig.ip)); ets_uart_printf(temp); os_sprintf(temp, "Client IP netmask: " IPSTR "\r\n", IP2STR(&ipconfig.netmask)); ets_uart_printf(temp); os_sprintf(temp, "Client IP gateway: " IPSTR "\r\n", IP2STR(&ipconfig.gw)); ets_uart_printf(temp); #endif wifiErrorConnect = 0; if(controlServerStatus == 0) { controlServerStatus++; #ifdef NOOLITE_LOGGING ets_uart_printf("Init noolite control server...\r\n"); #endif //  web-    noolite_control_server_init(); } //     wi-fi ,     //os_timer_setfn(&WiFiLinker, (os_timer_func_t *)noolite_platform_check_ip, NULL); //os_timer_arm(&WiFiLinker, 10000, 0); } else { // Wi-Fi   ,  ,      1,5 . if(wifi_station_get_connect_status() == STATION_WRONG_PASSWORD) { connState = WIFI_CONNECTING_ERROR; #ifdef PLATFORM_DEBUG ets_uart_printf("WiFi connecting error, wrong password\r\n"); #endif wifiErrorConnect++; os_timer_setfn(&WiFiLinker, (os_timer_func_t *)noolite_platform_check_ip, NULL); os_timer_arm(&WiFiLinker, 1500, 0); } // Wi-Fi   ,   AP,      1 . else if(wifi_station_get_connect_status() == STATION_NO_AP_FOUND) { connState = WIFI_CONNECTING_ERROR; #ifdef PLATFORM_DEBUG ets_uart_printf("WiFi connecting error, ap not found\r\n"); #endif wifiErrorConnect++; os_timer_setfn(&WiFiLinker, (os_timer_func_t *)noolite_platform_check_ip, NULL); os_timer_arm(&WiFiLinker, 1000, 0); } // Wi-Fi   , ,      1 . else if(wifi_station_get_connect_status() == STATION_CONNECT_FAIL) { connState = WIFI_CONNECTING_ERROR; #ifdef PLATFORM_DEBUG ets_uart_printf("WiFi connecting fail\r\n"); #endif wifiErrorConnect++; os_timer_setfn(&WiFiLinker, (os_timer_func_t *)noolite_platform_check_ip, NULL); os_timer_arm(&WiFiLinker, 1000, 0); } //  Wi-Fi , ... else { os_timer_setfn(&WiFiLinker, (os_timer_func_t *)noolite_platform_check_ip, NULL); os_timer_arm(&WiFiLinker, 1000, 0); connState = WIFI_CONNECTING; wifiErrorConnect++; #ifdef PLATFORM_DEBUG ets_uart_printf("WiFi connecting...\r\n"); #endif } controlServerStatus = 0; } } //    ,    ESP-01   STATIONAP    static void ICACHE_FLASH_ATTR noolite_platform_enter_configuration_mode(void) { wipe_flash_param(ESP_PARAM_SAVE_1); wifi_set_opmode(STATIONAP_MODE); #ifdef NOOLITE_LOGGING ets_uart_printf("Restarting in STATIONAP mode...\r\n"); #endif system_restart(); } //   CONFMODE (GPIO0) void BtnInit() { // . GPIO 0  - PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTDI_U, FUNC_GPIO0); // . .  PIN_PULLUP_EN(PERIPHS_IO_MUX_MTDI_U); // . . ETS_GPIO_INTR_DISABLE(); // .  .  ETS_GPIO_INTR_ATTACH(input_intr_handler, NULL); GPIO_DIS_OUTPUT(BTN_CONFIG_GPIO); //   GPIO_REG_WRITE(GPIO_STATUS_W1TC_ADDRESS, BIT(0)); // . gpio_pin_intr_state_set(GPIO_ID_PIN(BTN_CONFIG_GPIO), GPIO_PIN_INTR_NEGEDGE); // .. ETS_GPIO_INTR_ENABLE(); //  os_timer_disarm(&DebounceTimer); os_timer_setfn(&DebounceTimer, &debounce_timer_cb, 0); } //  .  LOCAL void input_intr_handler(void *arg) { //  GPIO uint32 gpio_status = GPIO_REG_READ(GPIO_STATUS_ADDRESS); //  GPIO_REG_WRITE(GPIO_STATUS_W1TC_ADDRESS, gpio_status); // . ETS_GPIO_INTR_DISABLE(); gpio_pin_intr_state_set(GPIO_ID_PIN(BTN_CONFIG_GPIO), GPIO_PIN_INTR_DISABLE); // . ETS_GPIO_INTR_ENABLE(); //   os_timer_arm(&DebounceTimer, 200, FALSE); } //      CONFMODE void ICACHE_FLASH_ATTR debounce_timer_cb(void *arg) { ETS_GPIO_INTR_DISABLE(); gpio_pin_intr_state_set(GPIO_ID_PIN(BTN_CONFIG_GPIO), GPIO_PIN_INTR_NEGEDGE); ETS_GPIO_INTR_ENABLE(); #ifdef NOOLITE_LOGGING ets_uart_printf("Button CONFMODE pressed, wiping configuration and restart in configuration mode...\r\n"); #endif noolite_platform_enter_configuration_mode(); } //  void ICACHE_FLASH_ATTR noolite_platform_init(void) { //    ,       4 tSetup nooLiteSetup; //    flash load_flash_param(ESP_PARAM_SAVE_1, (uint32 *)&nooLiteSetup, sizeof(tSetup)); //   CONFMODE BtnInit(); //   flash          STA,   web-  if(nooLiteSetup.SetupOk != SETUP_OK_KEY || wifi_get_opmode() != STATION_MODE) { //   wipe_flash_param(ESP_PARAM_SAVE_1); //      STA-AP,  .   if(wifi_get_opmode() != STATIONAP_MODE) { wifi_set_opmode(STATIONAP_MODE); #ifdef NOOLITE_LOGGING ets_uart_printf("Restarting in STATIONAP mode...\r\n"); #endif system_restart(); } char macaddr[6]; //  MAC   AP wifi_get_macaddr(SOFTAP_IF, macaddr); //   AP   IP struct ip_info ipinfo; IP4_ADDR(&ipinfo.ip, 10, 10, 10, 1); IP4_ADDR(&ipinfo.gw, 10, 10, 10, 1); IP4_ADDR(&ipinfo.netmask, 255, 255, 255, 0); wifi_set_ip_info(SOFTAP_IF, &ipinfo); //   AP  struct softap_config apConfig; os_memset(apConfig.ssid, 0, sizeof(apConfig.ssid)); os_sprintf(apConfig.ssid, "NOOLITE_%02x%02x%02x%02x%02x%02x", MAC2STR(macaddr)); os_memset(apConfig.password, 0, sizeof(apConfig.password)); os_sprintf(apConfig.password, "%02x%02x%02x%02x%02x%02x", MAC2STR(macaddr)); apConfig.authmode = AUTH_WPA_WPA2_PSK; apConfig.channel = 7; apConfig.max_connection = 255; apConfig.ssid_hidden = 0; wifi_softap_set_config(&apConfig); //  ,    , .noolite_platform.h #ifdef NOOLITE_LOGGING char temp[80]; os_sprintf(temp, "OPMODE: %u\r\n", wifi_get_opmode()); ets_uart_printf(temp); os_sprintf(temp, "SSID: %s\r\n", apConfig.ssid); ets_uart_printf(temp); os_sprintf(temp, "PASSWORD: %s\r\n", apConfig.password); ets_uart_printf(temp); os_sprintf(temp, "CHANNEL: %u\r\n", apConfig.channel); ets_uart_printf(temp); os_sprintf(temp, "CONFIGURATION WEB SERVER IP: " IPSTR "\r\n", IP2STR(&ipinfo.ip)); ets_uart_printf(temp); ets_uart_printf("Starting nooLite configuration web server...\r\n"); #endif //    noolite_config_server_init(); } else //     { #ifdef NOOLITE_LOGGING ets_uart_printf("Starting in normal mode...\r\n"); #endif //     STA if(wifi_get_opmode() != STATION_MODE) { #ifdef NOOLITE_LOGGING ets_uart_printf("Restarting in STATION mode...\r\n"); #endif wifi_set_opmode(STATION_MODE); system_restart(); } //  .    STA,     MAC  #ifdef NOOLITE_LOGGING char temp[80]; uint8 bssid[6]; struct station_config stationConf; wifi_station_get_config(&stationConf); os_sprintf(temp, "OPMODE: %u\r\n", wifi_get_opmode()); ets_uart_printf(temp); os_sprintf(temp, "AP SSID: %s\r\n", stationConf.ssid); ets_uart_printf(temp); os_sprintf(temp, "AP PASSWORD: %s\r\n", stationConf.password); ets_uart_printf(temp); wifi_get_macaddr(STATION_IF, bssid); os_sprintf(temp, "STA MACADDR: " MACSTR "\r\n", MAC2STR(bssid)); ets_uart_printf(temp); #endif #ifdef NOOLITE_LOGGING ets_uart_printf("System initialization done!\r\n"); #endif //     wi-fi   AP os_timer_disarm(&WiFiLinker); os_timer_setfn(&WiFiLinker, (os_timer_func_t *)noolite_platform_check_ip, NULL); os_timer_arm(&WiFiLinker, 100, 0); } } 


I see no point in describing the noolite_config_server.c file, it is launching a web server in configuration mode, by the principle of operation it is similar to the work in normal mode, which we will consider below.

The implementation of the web server is very simple and does not pretend to be flexible and functional, and moreover, implementing the web server on ESP8266 is not entirely correct, the more correct approach is to organize a TCP client on the ESP8266 that will keep the connection to the management server, and the management server already has to organize a full-fledged interaction interface (RESTfull or JSON) with the external environment; under the external environment, I mean the Web interface, various mobile and stationary clients (Windows, Android, iOS, etc.)



The appearance of the web-interface pages turned out this, the interface is very simple:



Configuration Mode, Main Page


When you click on Return to normal mode, the board returns to normal mode.



Configuration Mode, WiFi Connection Setup Page


Configuration mode, deviveID setup page


Main mode, main page


The deviceID page is used to get our device number for some auxiliary tasks; it simply gives out a number without any design.



Main mode, deviceID page


Main Mode, Power Block Binding Page


Main mode, power unit control page


Implementing all this in code:



File noolite_control_server.c
 #include "ets_sys.h" #include "osapi.h" #include "user_interface.h" #include "mem.h" #include "espconn.h" #include "driver/uart.h" #include "noolite_control_server.h" #include "flash_param.h" #include "noolite_platform.h" static struct espconn esp_conn; static esp_tcp esptcp; static unsigned char killConn; // http  404 static const char *http404Header = "HTTP/1.0 404 Not Found\r\nServer: nooLite-Control-Server\r\nContent-Type: text/plain\r\n\r\nNot Found (or method not implemented).\r\n"; // http  200 static const char *http200Header = "HTTP/1.0 200 OK\r\nServer: nooLite-Control-Server/0.1\r\nContent-Type: text/html\r\n"; // html ,   static const char *pageStart = "<html><head><title>nooLite Control Panel</title><style>body{font-family: Arial}</style></head><body><form method=\"get\" action=\"/\"><input type=\"hidden\" name=\"set\" value=\"1\">\r\n"; // html ,   static const char *pageEnd = "</form><hr>(c) 2014 by <a href=\"mailto:sleuthhound@gmail.com\" target=\"_blank\">Mikhail Grigorev</a>, <a href=\"http://programs74.ru\" target=\"_blank\">programs74.ru</a>\r\n</body></html>\r\n"; //  html  static const char *pageIndex = "<h2>Welcome to nooLite Control Panel</h2>nooLite Control deviceID: {deviceid}<ul><li><a href=\"?page=devid\">Get deviceID</a></li><li><a href=\"?page=bind\">nooLite bind-unbind channel</a></li><li><a href=\"?page=control\">nooLite control</a></li></ul>\r\n"; // html       static const char *pageSetBindChannel = "<h2><a href=\"/\">Home</a> / nooLite bind-unbind channel</h2><input type=\"hidden\" name=\"page\" value=\"bind\"><table border=\"0\"><tr><td><b>Channel #:</b></td><td><input type=\"text\" name=\"channel\" value=\"{channel}\" size=\"5\"> 0 .. 32</td></tr></tr><tr><td><b>Status:</b></td><td>{status}</td></tr><tr><td></td><td><input type=\"submit\" name = \"action\" value=\"Bind\"><input type=\"submit\" name = \"action\" value=\"Unbind\"></td></tr></table>\r\n"; // html     static const char *pageSetNooliteControl = "<h2><a href=\"/\">Home</a> / nooLite control</h2><input type=\"hidden\" name=\"page\" value=\"control\"><table border=\"0\"><tr><td><b>Channel #:</b></td><td><input type=\"text\" name=\"channel\" value=\"{channel}\" size=\"5\"> 0 .. 32</td></tr><tr><td><b>Status:</b></td><td>{status}</td></tr><tr><td></td><td><input type=\"submit\" name = \"action\" value=\"On\"><input type=\"submit\" name = \"action\" value=\"Off\"></td></tr></table>\r\n"; static const char *pageCommandSent = "<br><b style=\"color: green\">Command sent!</b>\r\n"; // html  ID ,     static const char *pageDevID = "{deviceid}"; int recvOK = 0; static void recvTask(os_event_t *events); //     UART  nooLite MT1132 //       http://www.noo.com.by/assets/files/PDF/MT1132.pdf static int ICACHE_FLASH_ATTR noolite_sendCommand(unsigned char channel, unsigned char command, unsigned char data, unsigned char format) { unsigned char buf[12]; unsigned int i; int checkSum = 0; recvOK = 0; os_memset(buf, 0, 12); buf[0] = 85; buf[1] = 80; buf[2] = command; buf[3] = format; buf[5] = channel; buf[6] = data; for(i = 0;i<10;i++){ checkSum+= buf[i]; } buf[10] = lowByte(checkSum); buf[11] = 170; uart0_tx_buffer(&buf, 12); sleepms(300); return recvOK; } #ifdef NOOLITE_LOGGING static void ICACHE_FLASH_ATTR noolite_control_server_recon(void *arg, sint8 err) { ets_uart_printf("noolite_control_server_recon\r\n"); } #endif #ifdef NOOLITE_LOGGING static void ICACHE_FLASH_ATTR noolite_control_server_discon(void *arg) { ets_uart_printf("noolite_control_server_discon\r\n"); } #endif //   static void ICACHE_FLASH_ATTR noolite_control_server_recv(void *arg, char *data, unsigned short len) { struct espconn *ptrespconn = (struct espconn *)arg; //   GET  if(os_strncmp(data, "GET ", 4) == 0) { char page[16]; os_memset(page, 0, sizeof(page)); //  GET     page noolite_control_server_get_key_val("page", sizeof(page), data, page); //  page=devid,     device id if(os_strncmp(page, "devid", 5) == 0 && strlen(page) == 5) { noolite_control_server_deviceid_page(ptrespconn, page, data); } else { //    noolite_control_server_process_page(ptrespconn, page, data); } return; } else //     ,   http404Header { espconn_sent(ptrespconn, (uint8 *)http404Header, os_strlen(http404Header)); killConn = 1; return; } } //     device id static void ICACHE_FLASH_ATTR noolite_control_server_deviceid_page(struct espconn *ptrespconn, char *page, char *request) { //    flash tSetup nooliteSetup; load_flash_param(ESP_PARAM_SAVE_1, (uint32 *)&nooliteSetup, sizeof(tSetup)); //  pageDevID     {},          char *stream = (char *)pageDevID; char templateKey[16]; os_memset(templateKey, 0, sizeof(templateKey)); unsigned char templateKeyIdx; while(*stream) { if(*stream == '{') { templateKeyIdx = 0; stream++; while(*stream != '}') { templateKey[templateKeyIdx++] = *stream; stream++; } //   {deviceid}   device id     if(os_strncmp(templateKey, "deviceid", 6) == 0) { char deviceid[3]; char i; for(i=0; i<16; i++) { os_sprintf(deviceid, "%02x", nooliteSetup.deviceId[i]); espconn_sent(ptrespconn, (uint8 *)deviceid, os_strlen(deviceid)); } } } else { espconn_sent(ptrespconn, (uint8 *)stream, 1); } stream++; } killConn = 1; } //     static void ICACHE_FLASH_ATTR noolite_control_server_process_page(struct espconn *ptrespconn, char *page, char *request) { //  http200Header espconn_sent(ptrespconn, (uint8 *)http200Header, os_strlen(http200Header)); espconn_sent(ptrespconn, (uint8 *)"\r\n", 2); //  pageStart espconn_sent(ptrespconn, (uint8 *)pageStart, os_strlen(pageStart)); //   char set[2] = {'0', '\0'}; noolite_control_server_get_key_val("set", sizeof(set), request, set); char channel_num[2] = "0"; char status[32] = "[status]"; char action[10] = "unbind"; os_memset(channel_num, 0, sizeof(channel_num)); os_memset(status, 0, sizeof(status)); os_memset(action, 0, sizeof(action)); //   pageSetBindChannel if(os_strncmp(page, "bind", 4) == 0 && strlen(page) == 4) { //    set     pageSetBindChannel //   1,  ,            ,      if(set[0] == '1') { //   ,     (  ) noolite_control_server_get_key_val("channel", sizeof(channel_num), request, channel_num); noolite_control_server_get_key_val("action", sizeof(action), request, action); //    MT1132 // noolite_sendCommand(channel, command, data, format) // channel = 0 .. 32 // command = 15 - bind // command = 9 - unbind // command = 2 - on // command = 0 - off //      ,  MT1132    OK  UART //         uart.c,        (.    system_os_task),   uart.c   0 //   ,   0  32 if(atoi(channel_num) >= 0 && atoi(channel_num) <= 32) { //  if(os_strncmp(action, "Bind", 4) == 0 && strlen(action) == 4) { if(noolite_sendCommand(atoi(channel_num), 15, 0, 0)) { os_sprintf(status, "Bind OK"); } else { os_sprintf(status, "Bind ERR"); } //  } else if(os_strncmp(action, "Unbind", 6) == 0 && strlen(action) == 6) { if(noolite_sendCommand(atoi(channel_num), 9, 0, 0)) { os_sprintf(status, "Unbind OK"); } else { os_sprintf(status, "Unbind ERR"); } } else { os_sprintf(status, "Err"); } } else { os_sprintf(status, "Err"); } } //     char *stream = (char *)pageSetBindChannel; char templateKey[16]; os_memset(templateKey, 0, sizeof(templateKey)); unsigned char templateKeyIdx; while(*stream) { if(*stream == '{') { templateKeyIdx = 0; stream++; while(*stream != '}') { templateKey[templateKeyIdx++] = *stream; stream++; } //    {}    if(os_strncmp(templateKey, "channel", 7) == 0) { if(strlen(channel_num) == 0) os_sprintf(channel_num, "0"); espconn_sent(ptrespconn, (uint8 *)channel_num, os_strlen(channel_num)); } else if(os_strncmp(templateKey, "status", 6) == 0) { if(strlen(status) == 0) { os_sprintf(status, "[status]"); } espconn_sent(ptrespconn, (uint8 *)status, os_strlen(status)); } } else { espconn_sent(ptrespconn, (uint8 *)stream, 1); } stream++; } //  pageCommandSent if(set[0] == '1') { espconn_sent(ptrespconn, (uint8 *)pageCommandSent, os_strlen(pageCommandSent)); } } //   pageSetNooliteControl,      else if(os_strncmp(page, "control", 7) == 0 && strlen(page) == 7) { if(set[0] == '1') { noolite_control_server_get_key_val("channel", sizeof(channel_num), request, channel_num); noolite_control_server_get_key_val("action", sizeof(action), request, action); // noolite_sendCommand(channel, command, data, format) // channel = 0 .. 32 // command = 15 - bind // command = 9 - unbind // command = 2 - on // command = 0 - off if(atoi(channel_num) >= 0 && atoi(channel_num) <= 32) { if(os_strncmp(action, "On", 2) == 0 && strlen(action) == 2) { if(noolite_sendCommand(atoi(channel_num), 2, 0, 0)) { os_sprintf(status, "On"); } else { os_sprintf(status, "On ERR"); } } else if(os_strncmp(action, "Off", 3) == 0 && strlen(action) == 3) { if (noolite_sendCommand(atoi(channel_num), 0, 0, 0)) { os_sprintf(status, "Off"); } else { os_sprintf(status, "Off ERR"); } } else { os_sprintf(status, "Err"); } } else { os_sprintf(status, "Err"); } } char *stream = (char *)pageSetNooliteControl; char templateKey[16]; os_memset(templateKey, 0, sizeof(templateKey)); unsigned char templateKeyIdx; while(*stream) { if(*stream == '{') { templateKeyIdx = 0; stream++; while(*stream != '}') { templateKey[templateKeyIdx++] = *stream; stream++; } // send the replacing value now if(os_strncmp(templateKey, "channel", 7) == 0) { if(strlen(channel_num) == 0 ) os_sprintf(channel_num, "0"); espconn_sent(ptrespconn, (uint8 *)channel_num, os_strlen(channel_num)); } else if(os_strncmp(templateKey, "status", 6) == 0) { if(strlen(status) == 0) { os_sprintf(status, "[status]"); } espconn_sent(ptrespconn, (uint8 *)status, os_strlen(status)); } } else { espconn_sent(ptrespconn, (uint8 *)stream, 1); } stream++; } if(set[0] == '1') { espconn_sent(ptrespconn, (uint8 *)pageCommandSent, os_strlen(pageCommandSent)); } } else //    pageIndex  device id { tSetup nooliteSetup; load_flash_param(ESP_PARAM_SAVE_1, (uint32 *)&nooliteSetup, sizeof(tSetup)); char *stream = (char *)pageIndex; char templateKey[16]; os_memset(templateKey, 0, sizeof(templateKey)); unsigned char templateKeyIdx; while(*stream) { if(*stream == '{') { templateKeyIdx = 0; stream++; while(*stream != '}') { templateKey[templateKeyIdx++] = *stream; stream++; } //  {deviceid} if(os_strncmp(templateKey, "deviceid", 6) == 0) { char deviceid[3]; char i; for(i=0; i<16; i++) { os_sprintf(deviceid, "%02x", nooliteSetup.deviceId[i]); espconn_sent(ptrespconn, (uint8 *)deviceid, os_strlen(deviceid)); } } } else { espconn_sent(ptrespconn, (uint8 *)stream, 1); } stream++; } } //  pageEnd espconn_sent(ptrespconn, (uint8 *)pageEnd, os_strlen(pageEnd)); killConn = 1; } //         key=value static unsigned char ICACHE_FLASH_ATTR noolite_control_server_get_key_val(char *key, unsigned char maxlen, char *str, char *retval) { unsigned char found = 0; char *keyptr = key; char prev_char = '\0'; *retval = '\0'; while( *str && *str!='\r' && *str!='\n' && !found ) { if(*str == *keyptr) { if(keyptr == key && !( prev_char == '?' || prev_char == '&' ) ) { str++; continue; } keyptr++; if (*keyptr == '\0') { str++; keyptr = key; if (*str == '=') { found = 1; } } } else { keyptr = key; } prev_char = *str; str++; } if(found == 1) { found = 0; while( *str && *str!='\r' && *str!='\n' && *str!=' ' && *str!='&' && maxlen>0 ) { *retval = *str; maxlen--; str++; retval++; found++; } *retval = '\0'; } return found; } // callback ,     static void ICACHE_FLASH_ATTR noolite_control_server_sent(void *arg) { struct espconn *pesp_conn = (struct espconn *)arg; if (pesp_conn == NULL) { return; } if(killConn) { espconn_disconnect(pesp_conn); } } // callback ,     static void ICACHE_FLASH_ATTR noolite_control_server_connect(void *arg) { struct espconn *pesp_conn = (struct espconn *)arg; #ifdef NOOLITE_LOGGING ets_uart_printf("noolite_control_server_connect\r\n"); #endif //   callback  espconn_regist_recvcb(pesp_conn, noolite_control_server_recv); espconn_regist_sentcb(pesp_conn, noolite_control_server_sent); #ifdef NOOLITE_LOGGING espconn_regist_reconcb(pesp_conn, noolite_control_server_recon); espconn_regist_disconcb(pesp_conn, noolite_control_server_discon); #endif } //    we- void ICACHE_FLASH_ATTR noolite_control_server_init() { #ifdef NOOLITE_LOGGING ets_uart_printf("noolite_control_server_init()\r\n"); #endif esptcp.local_port = 80; esp_conn.type = ESPCONN_TCP; esp_conn.state = ESPCONN_NONE; esp_conn.proto.tcp = &esptcp; //  callback  espconn_regist_connectcb(&esp_conn, noolite_control_server_connect); espconn_accept(&esp_conn); //         UART //  uart.c            MT1132 (. uart0_rx_intr_handler) //   OK,    0    system_os_post(recvTaskPrio, 0, atHead); os_event_t *recvTaskQueue = (os_event_t *)os_malloc(sizeof(os_event_t) * recvTaskQueueLen); system_os_task(recvTask, recvTaskPrio, recvTaskQueue, recvTaskQueueLen); } //    static void ICACHE_FLASH_ATTR recvTask(os_event_t *events) { switch (events->sig) { case 0: //    0,        recvOK = 1 #ifdef NOOLITE_LOGGING ets_uart_printf("nooLite MT1132 sent OK\r\n"); #endif recvOK = 1; break; default: break; } } 


And finally a small video demonstrating how the board works:

Demonstration of the Espressif ESP8266 and the module nooLite MT1132


In general, we once again see that the capabilities of the board on the ESP8266 chip are quite large.



In conclusion, I would like to thank the company Notekhnika , as well as the administration of the site Thinking-Home.RU for providing nooLite equipment for testing.



Project repository on Github



PS If someone has any wishes regarding the next article about ESP8266, then I am ready to listen to them. You can write about working with different sensors: DS18B20, DHT22, SHT21, BMP180, IR receiver / transmitter, external memory ms, for example Microchip 24xx16 series, etc.

Source: https://habr.com/ru/post/364113/



All Articles