STM32+ESP-01 docking with Alibaba Feiyan platform
In recent years, with the rapid development of microelectronics technology and computer information technology, the Internet of things technology has emerged, and the interconnection of everything is possible. At present, most consumer electronic products and home appliances have been loaded with WIFI module or Bluetooth module, so that they can connect to the network and realize interconnection. Remote control and intelligent control have become the selling points of many consumer electronic products. Therefore, the application of WIFI module has become an essential skill for embedded engineers.
Due to the shortage of IPv4 address resources, the devices in the LAN can not directly establish the connection with the external network through the local IP, and need to map the IP through the NAT gateway. Therefore, the best solution for remote control of the Internet of things devices in the LAN is to forward messages through the external network server. At present, major Internet companies have launched their own Internet of things platforms. For example, Alibaba's Feiyan platform, Tencent's wechat hardware platform, and the smart cloud platform launched by smart cloud, etc.
In view of the strong influence of Alibaba group, let's take Feiyan platform as an example to discuss how to develop our Internet of things products by connecting WIFI devices to servers and mobile terminals through the Internet of things platform. For more information about the flying swallow platform, please refer to its help documentation https://help.aliyun.com/product/93051.html?spm=a2c4g.750001.list.264.36f87b13MRwU2W
Due to the different docking procedures corresponding to different hardware platforms, we need to determine which hardware platform to use before docking. For example, today's discussion is based on the hardware configuration of STM32MCU+ESP-01S WIFI module. Because the original firmware of ESP-01S only supports TCP but does not support MQTT, the business logic control and MQTT protocol should run on MCU. The connection block diagram is as follows:
Alibaba Feiyan platform is based on the MQTT protocol, so let's first understand the MQTT protocol. According to the network protocol, the hierarchy is as follows:
MQTT (message queue telemetry transmission) is a message protocol based on publish / subscribe paradigm in ISO standard (ISO/IEC PRF 20922). It is an application layer protocol based on TCP/IP protocol cluster. It is a publish / subscribe message protocol designed for remote devices with low hardware performance and under the condition of bad network conditions. MQTT is a client server based message publish / subscribe transport protocol. MQTT protocol is lightweight, simple, open and easy to implement, which makes it widely used. In many cases, including limited environments, such as machine to machine (M2M) communication and Internet of things (IoT). It has been widely used in satellite link communication sensors, occasionally dial-up medical devices, smart home, and some miniaturized devices.
Please move to the next step for details of MQTT protocol https://www.cnblogs.com/dongkuo/p/11360419.html
The blogger gave a detailed introduction to the agreement.
In order to facilitate the user's use and simplify the cumbersome bottom-level procedures when docking the platform, Alibaba Feiyan platform provides SDK s for various development languages. The download address is as follows:
https://code.aliyun.com/linkkit/c-sdk/repository/archive.zip?spm=a2c4g.11186623.2.36.63fb4e1eEOB1mz&ref=v3.0.1
Please refer to the help document for details of SDK application methods
https://help.aliyun.com/product/93051.html?spm=a2c4g.750001.list.264.36f87b13MRwU2W
After downloading the SDK, unzip it. Double click to open it config.bat File, a configuration interface of the selection module will pop up as follows:
By moving the cursor up and down the left and right arrow keys, and selecting and deselecting the space bar, we select the following options
- PLATFORM_HAS_STDINT
- PLATFORM_HAS_DYNMEM
- FEATURE_MQTT_COMM_ENABLED
3.1 FEATURE_MQTT_DEFAULT_IMPL
3.2 FEATURE_MQTT_DIRECT - FEATURE_ATM_ENABLED
4.1 FEATURE_AT_TCP_ENABLED
Due to the difference of at instructions in different modules, we do not use the at instruction parsing module of SDK, so we use the feature_ ATM_ Select only feature under enabled_ AT_ TCP_ Enabled option. Save exit after selection. Then double click to open extract.bat , all files under \ output\eng and \ output \ examples \ MQTT will be generated in the output folder_ example_ at.c(MQTT_ example_ The at. C file is an application instance of MQTT client API) copied to the STM32 project directory in KEIL or IAR and added to the project. Then we need to modify the relevant functions in \ output\eng\wrappers\wrapper.c to realize docking. The functions to be modified are as follows:
Because we didn't run OS on MCU, we didn't need the above functions, but the SDK generated the above function entities. We just need to return the function to the correct value, such as HAL_MutexCreate returns (void *) 1, others return 0.
The above functions are the main implementation functions of AT command communication between MCU and ESP-01S through serial port.
- HAL_AT_CONN_Init
#define LINK_ID_MAX 5 typedef struct link_s { int fd; } link_t; static link_t g_link[LINK_ID_MAX]; int HAL_AT_CONN_Init(void) { int link; memset(g_link, 0, sizeof(g_link)); for (link = 0; link < LINK_ID_MAX; link++) { g_link[link].fd = -1; } char cmd0[64] = {0}; char out0[64] = {0}; //Select mode 1.Station 2.AP 3.AP+Station HAL_Snprintf(cmd0, sizeof(cmd0), "AT+CWMODE=%d\r\n",3); if(at_send_cmd_wait_reply(cmd0,sizeof(cmd0),out0,sizeof(out0),"\r\n","OK\r\n",6000) < 0) { at_conn_hal_debug("%s %d failed", __func__, __LINE__); return -1; } //Select mode disconnect WIFI HAL_Snprintf(cmd0, sizeof(cmd0), "AT+CWQAP\r\n"); if(at_send_cmd_wait_reply(cmd0,sizeof(cmd0),out0,sizeof(out0),"\r\n","OK\r\n",6000) < 0) { at_conn_hal_debug("%s %d failed", __func__, __LINE__); return -1; } //Select mode to connect to WIFI, SSID: WIFI password: WIFI password HAL_Snprintf(cmd0, sizeof(cmd0), "AT+CWJAP=\"%s\",\"%s\"\r\n","WIFISSID","WIFIPassword"); if(at_send_cmd_wait_reply(cmd0,sizeof(cmd0),out0,sizeof(out0),"\r\n","OK\r\n",6000) < 0) { at_conn_hal_debug("%s %d failed", __func__, __LINE__); return -1; } inited = true; return 0; }
- HAL_AT_CONN_Deinit
int HAL_AT_CONN_Deinit(void) { if (!inited) { return 0; } inited = false; return 0; }
- HAL_AT_CONN_Start
int HAL_AT_CONN_Start(at_conn_t *c) { char cmd0[128] = {0}; char out0[128] = {0}; //Select TCP connection mode as multi connection HAL_Snprintf(cmd0, sizeof(cmd0), "AT+CIPMUX=%d\r\n",1); if(at_send_cmd_wait_reply(cmd0,sizeof(cmd0),out0,sizeof(out0),"\r\n","OK\r\n",6000) < 0) { at_conn_hal_debug("%s %d failed", __func__, __LINE__); return -1; } int link_id; for (link_id = 0; link_id < LINK_ID_MAX; link_id++) { if (g_link[link_id].fd >= 0) { continue; } else { g_link[link_id].fd = conn->fd; break; } } //Establish a TCP connection HAL_Snprintf(cmd0, sizeof(cmd0), "AT+CIPSTART=%d,\"%s\",\"%s\",%d\r\n",link_id,"TCP",conn->addr,conn->r_port); if(at_send_cmd_wait_reply(cmd0,sizeof(cmd0),out0,sizeof(out0),"\r\n","OK\r\n",300) < 0) { at_conn_hal_debug("%s %d failed", __func__, __LINE__); return -1; } return (int)0; }
- HAL_AT_CONN_Close
int HAL_AT_CONN_Close(int fd, int32_t remote_port) { int link_id; link_id = fd_to_linkid(fd); if(link_id < 0 || link_id >= LINK_ID_MAX) { at_conn_hal_debug("No connection found for fd (%d) in %s in %s", fd, __func__, __LINE__); return -1; } char cmd0[64] = {0}; char out0[64] = {0}; //Close TCP connection HAL_Snprintf(cmd0, sizeof(cmd0), "AT+CIPCLOSE=%d\r\n",link_id); if(at_send_cmd_wait_reply(cmd0,sizeof(cmd0),out0,sizeof(out0),"\r\n","OK\r\n",6000) < 0) { //at_conn_hal_debug("%s %d failed", __func__, __LINE__); //return -1; } g_link[link_id].fd = -1; return 0; }
- HAL_AT_CONN_Send
int HAL_AT_CONN_Send(int fd, uint8_t *data, uint32_t len, char remote_ip[16], int32_t remote_port, int32_t timeout) { int link_id; if (!data) { return -1; } link_id = fd_to_linkid(fd); if (link_id < 0 || link_id >= LINK_ID_MAX) { at_conn_hal_debug("No connection found for fd (%d) in %s in %s", fd, __func__, __LINE__); return -1; } char cmd0[64] = {0}; char out0[64] = {0}; //Set send data to connection link_id, data length len HAL_Snprintf(cmd0, sizeof(cmd0), "AT+CIPSEND=%d,%d\r\n",link_id,len); if(at_send_cmd_wait_reply(cmd0,sizeof(cmd0),out0,sizeof(out0),"\r\n","OK\r\n",300) < 0) { at_conn_hal_debug("%s %d failed", __func__, __LINE__); return -1; } //Start sending data if(at_send_data_wait_reply(data,len,out0,sizeof(out0),">","OK\r\n",6000) < 0) { at_conn_hal_debug("%s %d failed", __func__, __LINE__); return -1; } HAL_SleepMs(5000); char Prefix[64] = {0}; HAL_Snprintf(Prefix, sizeof(Prefix), "+IPD,%d,",link_id); //Waiting for reply if (at_yield(out0, sizeof(out0), Prefix, ":", AT_UART_TIMEOUT_MS) < 0) { return -1; } char mqtt_reply[256] = {0}; char c = NULL; int num = atoi(out0); for(int i=0;i < num;i++) { //Crawl back to mqtt_reply if (at_getc(&c,timeout) != 0) { return -1; } mqtt_reply[i] = c; } struct at_conn_input param; if (g_link[link_id].fd >= 0) { param.fd = g_link[link_id].fd; param.data = mqtt_reply; param.datalen = num; param.remote_ip = NULL; param.remote_port = 0; //Upload the received data to the upper layer of MQTT protocol if (IOT_ATM_Input(¶m) != 0) { at_conn_hal_debug(" %s socket %d get data len %d fail to post to at_conn, drop it\n",__func__, g_link[link_id].fd, len); } } return (int)0; }
- HAL_AT_CONN_DomainToIp
int HAL_AT_CONN_DomainToIp(char *domain, char ip[16]) { char cmd0[128] = {0}; char out0[128] = {0}; //Get IP address according to domain name HAL_Snprintf(cmd0, sizeof(cmd0), "AT+CIPDOMAIN=\"%s\"\r\n",domain); if(at_send_cmd_wait_reply(cmd0,sizeof(cmd0),out0,sizeof(out0),"+CIPDOMAIN:","\r\n",6000) < 0) { at_conn_hal_debug("%s %d failed", __func__, __LINE__); return -1; } for(int i=0;i < 16;i++) { ip[i] = out0[i]; } at_conn_hal_debug("IP->%s", ip); return 0; }
The above procedures are written in the test phase, which is relatively casual. I hope to criticize and correct the shortcomings.
After the device-side program is completed, we can debug it on the Internet of things platform on the console of Alibaba Feiyan platform. First, we modify the get class in the custom Topic to publish and subscribe, because in mqtt_ example_ In the debugging example of at. C, the Topic of subscription and publication is used.
Finally, we can start the program to connect to the flying swallow platform. If mqtt is applied_ example_ At. C debugging example, we need to put mqtt_example_ In at. C, the main function modifies a name such as mqtt_example, so as not to conflict with our own main function, and call mqtt_ in the main function we defined. example.