STM32 + W5500 + MQTT

Dependencies:   MQTT WIZnet_Library mbed

Files at this revision

API Documentation at this revision

Comitter:
zhangyx
Date:
Mon Jun 04 15:16:05 2018 +0000
Parent:
1:9689429a0a29
Commit message:
better API

Changed in this revision

WIZnet_Library.lib Show annotated file Show diff for this revision Revisions of this file
main.cpp Show annotated file Show diff for this revision Revisions of this file
networking.cpp Show annotated file Show diff for this revision Revisions of this file
networking.h Show annotated file Show diff for this revision Revisions of this file
--- a/WIZnet_Library.lib	Fri Aug 25 15:46:28 2017 +0000
+++ b/WIZnet_Library.lib	Mon Jun 04 15:16:05 2018 +0000
@@ -1,1 +1,1 @@
-https://mbed.org/teams/WIZnet/code/WIZnet_Library/#cb8808b47e69
+https://os.mbed.com/users/zhangyx/code/WIZnet_Library/#f390679a0468
--- a/main.cpp	Fri Aug 25 15:46:28 2017 +0000
+++ b/main.cpp	Mon Jun 04 15:16:05 2018 +0000
@@ -1,86 +1,50 @@
 #include "mbed.h"
-#include "WIZnetInterface.h"
-#include "MQTTSocket.h"
-#include "MQTTClient.h"
+#include "networking.h"
 
+Serial pc(PA_9,PA_10);
 DigitalIn BTN(PC_13);
- //W5500接线 mosi,miso,sclk,cs,reset
-WIZnetInterface wiz(PA_7,PA_6,PA_5,PB_6,PC_7);
-//节点名称任取
-#define NODE_NAME "n_12345"
- //接在同一子网下的设备MAC地址必须不同
-uint8_t mac_addr[6]={0x50,0x51,0x50,0x00,0x00,0x01};
+DigitalOut LED(PB_8);
 
-typedef MQTT::Client<MQTTSocket,Countdown> MClient;
-void meta_report(MClient& client, const char* ns, const char* type, 
-                    const char* payload = NULL, size_t payload_len = 0, 
-                    bool retain = false, MQTT::QoS qos = MQTT::QOS1){
-    char topic[64];
-    sprintf(topic, "/%s/" NODE_NAME "/%s", ns, type);
-    int ret = client.publish(topic, (void*)payload, payload_len, qos, retain);
-    printf("client.publish()=%d\r\n",ret);
-}
-void messageArrived(MQTT::MessageData& md)
+void on_control_cmd(const char* actuator_name, const char* control_value)
 {
-    MQTT::Message &message = md.message;
-    char buf[64];
-    int value, len = sizeof(buf)-1;
-    if(message.payloadlen < len)
-        len = message.payloadlen;
-    memcpy(buf, message.payload, len);
-    buf[len] = '\0';
-    sscanf(buf, "%d", &value);
-    printf("received %d\r\n", value);
+    pc.printf("Received CMD %s %s\r\n", actuator_name, control_value);
+    if(strcmp(actuator_name, "led") == 0)
+        LED = atoi(control_value);
 }
- 
+
 int main() {
-    int ret;
-    wiz.init(mac_addr);
-    printf("DHCP...\r\n");
-    wiz.connect();
-    printf("IP: %s\r\n", wiz.getIPAddress());
     
     MQTTSocket sock;
     MClient client(sock);
     
-    ret = sock.connect("tdxls-iot.xicp.net",1883);
-    if(ret != 0){
-        printf("failed to connect to TCP server\r\n");
-        return 1;
-    }
-    printf("sock.connect()=%d\r\n",ret);
-    
-    ret = client.connect();
-    if(ret != 0){
-        printf("MQTT connect failed\r\n");
-        return 1;
-    }
-    printf("client.connect()=%d\r\n",ret);
-    
-    const char* actuators = "switch,int\n";
-    const char* sensors = "analog,mV\n";
+    //声明所有的传感器,每行一个,每个由名字、单位两部分组成,最后一行必须为空指针作为结尾
+    const char* sensors[][2] = {
+        "test", " ",
+        "button", "V",
+        NULL, NULL //最后一行以空指针作为结束标记
+    };
 
-    ret = client.subscribe("/control/" NODE_NAME "/switch", MQTT::QOS1, messageArrived);    
-    printf("sock.subscribe()=%d\r\n",ret);
+    //声明所有的执行器,每行一个,每个由名字、参数类型两部分组成,最后一行必须为空指针作为结尾
+    const char* actuators[][2] = {
+        "led", "int",
+        NULL, NULL //最后一行以空指针作为结束标记
+    };
+    networking_init(sock, client, "tdxls-iot.xicp.net", sensors, actuators, on_control_cmd);
 
-    //节点上线消息
-    meta_report(client, "events","online");
-    //报告所有可接受的控制指令
-    meta_report(client, "capability","control", actuators, strlen(actuators), true);
-    //报告所有的传感器
-    meta_report(client, "capability","values", sensors, strlen(sensors), true);
-    
     bool btn = 0;
     while(1){
         bool newBTN = BTN;
         if(newBTN != btn){
             char buf[16];
-            int value = newBTN ? 3300 : 0;
+            int value = (bool)newBTN;
+            
             sprintf(buf, "%d mV", value);
-            meta_report(client, "values","analog",buf,strlen(buf),true);
+            publish_value(client,"button",buf);
+            
             btn = newBTN;
         }else{
-            client.yield(100);
+            client.yield(1000);
+            publish_value(client,"test","hello world");
         }
     }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/networking.cpp	Mon Jun 04 15:16:05 2018 +0000
@@ -0,0 +1,165 @@
+#include "mbed.h"
+#include "WIZnetInterface.h"
+#include "MQTTSocket.h"
+#include "MQTTClient.h"
+#include "networking.h"
+
+extern Serial pc;
+ //W5500接线 mosi,miso,sclk,cs,reset
+WIZnetInterface wiz(PB_5,PB_4,PB_3,PC_14,NC);
+//节点名称任取
+#define NODE_NAME "n_12345"
+ //接在同一子网下的设备MAC地址必须不同
+uint8_t mac_addr[6]={0x50,0x51,0x50,0x00,0x00,0x01};
+
+recv_ctl_cb g_recv_cb;
+const char* (*g_actuators)[2];
+static Timer g_timer;
+
+void disable_LSE() //调用此函数将 PC_14, PC_15 用作普通I/O
+{
+    RCC_OscInitTypeDef OscInitStruct;
+    HAL_RCC_GetOscConfig(&OscInitStruct);
+//    pc.printf("%u %u %u %u\r\n",OscInitStruct.HSEState,OscInitStruct.LSEState,OscInitStruct.HSIState,OscInitStruct.LSIState);
+    
+    // Enable access to Backup domain
+    HAL_PWR_EnableBkUpAccess();
+    // Reset Backup domain
+    __HAL_RCC_BACKUPRESET_FORCE();
+    __HAL_RCC_BACKUPRESET_RELEASE();
+    // Disable access to Backup domain
+    HAL_PWR_DisableBkUpAccess();
+    
+    OscInitStruct.LSEState=RCC_LSE_OFF;
+    HAL_RCC_OscConfig(&OscInitStruct);
+    
+    HAL_RCC_GetOscConfig(&OscInitStruct);
+//    pc.printf("%u %u %u %u\r\n",OscInitStruct.HSEState,OscInitStruct.LSEState,OscInitStruct.HSIState,OscInitStruct.LSIState);
+}
+
+
+void meta_report(MClient& client, const char* ns, const char* type, 
+                    const char* payload = NULL, size_t payload_len = 0, 
+                    bool retain = false, MQTT::QoS qos = MQTT::QOS1){
+    char topic[64];
+    sprintf(topic, "/%s/" NODE_NAME "/%s", ns, type);
+    int ret = client.publish(topic, (void*)payload, payload_len, qos, retain);
+    //pc.printf("client.publish()=%d\r\n",ret);
+}
+void messageArrived(MQTT::MessageData& md)
+{
+    MQTT::Message &message = md.message;
+//    pc.printf("messageArrived '%s' %d,%d\r\n", md.topicName.cstring, md.topicName.lenstring.len, message.payloadlen);
+
+//    char buf[64];
+//    int value, len = sizeof(buf)-1;
+//    if(message.payloadlen < len)
+//        len = message.payloadlen;
+//    memcpy(buf, message.payload, len);
+//    buf[len] = '\0';
+//    sscanf(buf, "%d", &value);
+//    pc.printf("received %d\r\n", value);
+
+    char* payload = new char[message.payloadlen+1];
+    if(!payload)
+        return;
+    memcpy(payload, message.payload, message.payloadlen);
+    payload[message.payloadlen]='\0';
+    
+    char* topic = new char[md.topicName.lenstring.len+1];
+    if(!topic){
+        delete[] payload;
+        return;
+    }
+    memcpy(topic, md.topicName.lenstring.data, md.topicName.lenstring.len);
+    topic[md.topicName.lenstring.len]='\0';
+    
+    char *pch = strtok (topic,"/");
+    for (int tok=0; tok<2 && pch != NULL; tok++)
+    {
+//        pc.printf ("%s\r\n",pch);
+        pch = strtok (NULL, "/");
+    }
+    if(pch)
+        g_recv_cb(pch, payload);
+    delete[] topic;
+    delete[] payload;
+}
+
+void publish_value(MClient &client, const char *topic, const char *buf)
+{
+    meta_report(client, "values",topic,buf,strlen(buf),true);
+}
+
+void buildCapability(char *out, const char* infoList[][2])
+{
+    out[0] = '\0';
+    for (int i = 0; infoList[i][0]; ++i)
+    {
+        strcat(out, infoList[i][0]);
+        strcat(out, ",");
+        strcat(out, infoList[i][1]);
+        strcat(out, "\\n");
+    }
+}
+ 
+int networking_init(MQTTSocket &sock, MClient &client, const char *broker,const char* sensors[][2], const char* actuators[][2], recv_ctl_cb cb) {
+    int ret;
+    g_timer.start();
+    disable_LSE(); //free LSE pins
+    wiz.init(mac_addr);
+    pc.printf("DHCP...\r\n");
+    wiz.connect();
+    pc.printf("IP: %s\r\n", wiz.getIPAddress());
+    
+    srand(rand()^g_timer.read_us());
+    
+    ret = sock.connect((char*)broker,1883);
+    if(ret != 0){
+        pc.printf("failed to connect to TCP server\r\n");
+        return 1;
+    }
+    pc.printf("sock.connect()=%d\r\n",ret);
+    
+    srand(rand()^g_timer.read_us());
+    
+    ret = client.connect();
+    if(ret != 0){
+        pc.printf("MQTT connect failed\r\n");
+        return 1;
+    }
+    pc.printf("client.connect()=%d\r\n",ret);
+    
+    
+    ret = client.subscribe("/control/" NODE_NAME "/+", MQTT::QOS1, messageArrived);    
+    pc.printf("sock.subscribe()=%d\r\n", ret);
+
+    g_recv_cb = cb;
+    g_actuators = actuators;
+
+    char * capabilities = new char[128];
+    if(!capabilities){
+        pc.printf("failed to alloc memory\r\n");
+        return 1;
+    }
+    //for (int i = 0; actuators[i][0]; ++i){
+//        sprintf(capabilities,"/control/" NODE_NAME "/+",actuators[i][0]);
+//        ret = client.subscribe(capabilities, MQTT::QOS1, messageArrived);    
+//        pc.printf("sock.subscribe(%s)=%d\r\n", capabilities, ret);
+//    }
+
+    //节点上线消息
+    meta_report(client, "events","online");
+    
+    //报告所有可接受的控制指令
+    buildCapability(capabilities, actuators);
+    meta_report(client, "capability","control", capabilities, strlen(capabilities), true);
+    //报告所有的传感器
+    buildCapability(capabilities, sensors);
+    meta_report(client, "capability","values", capabilities, strlen(capabilities), true);
+    delete[] capabilities;
+
+    pc.printf("Initialization done.\r\n");
+    
+    return 0;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/networking.h	Mon Jun 04 15:16:05 2018 +0000
@@ -0,0 +1,10 @@
+#pragma once
+
+#include "MQTTSocket.h"
+#include "MQTTClient.h"
+
+typedef MQTT::Client<MQTTSocket,Countdown> MClient;
+typedef void (*recv_ctl_cb)(const char*, const char*);
+
+int networking_init(MQTTSocket &sock, MClient &client, const char *broker,const char* sensors[][2], const char* actuators[][2], recv_ctl_cb cb);
+void publish_value(MClient &client, const char *topic, const char *buf);