IoT sensor/controller using STM32, W5500 ethernet, MQTT
Dependencies: mbed WIZnet_Library Watchdog DHT MQTT DS1820
main.cpp@5:b2ae1ed8a30e, 2020-02-24 (annotated)
- Committer:
- Geekshow
- Date:
- Mon Feb 24 00:40:29 2020 +0000
- Revision:
- 5:b2ae1ed8a30e
- Parent:
- 4:ebaf1973d008
- Child:
- 6:4d30bc5a8076
All in main.cpp, Tickers added!
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
zhangyx | 0:1170747a672f | 1 | #include "mbed.h" |
Geekshow | 3:de9611d75590 | 2 | //#include "rtos.h" |
Geekshow | 3:de9611d75590 | 3 | //#include "pins.h" |
Geekshow | 4:ebaf1973d008 | 4 | #include "WIZnetInterface.h" |
Geekshow | 4:ebaf1973d008 | 5 | #include "MQTTSocket.h" |
Geekshow | 4:ebaf1973d008 | 6 | #include "MQTTClient.h" |
Geekshow | 3:de9611d75590 | 7 | |
Geekshow | 3:de9611d75590 | 8 | // ========== PIN DEFINITIONS ============ |
Geekshow | 3:de9611d75590 | 9 | #define NUM_OF_OUTPUTS 11 |
Geekshow | 3:de9611d75590 | 10 | #define NUM_OF_INPUTS 12 |
Geekshow | 3:de9611d75590 | 11 | |
Geekshow | 4:ebaf1973d008 | 12 | #define LED_GREEN PA_5 |
Geekshow | 4:ebaf1973d008 | 13 | #define LED_ORANGE PA_1 // Don't use! Shared with D3 |
Geekshow | 3:de9611d75590 | 14 | #define BUTTON PC_9 |
Geekshow | 3:de9611d75590 | 15 | |
Geekshow | 3:de9611d75590 | 16 | #define ANALOGPIN0 PC_0 // Analogue Input 0 |
Geekshow | 3:de9611d75590 | 17 | #define ANALOGPIN1 PC_1 // Analogue Input 1 |
Geekshow | 3:de9611d75590 | 18 | #define ANALOGPIN2 PC_2 // Analogue Input 2 |
Geekshow | 3:de9611d75590 | 19 | #define ANALOGPIN3 PC_3 // Analogue Input 3 |
Geekshow | 3:de9611d75590 | 20 | #define ANALOGPIN4 PC_4 // Analogue Input 4 |
Geekshow | 3:de9611d75590 | 21 | #define ANALOGPIN5 PC_5 // Analogue Input 5 |
Geekshow | 3:de9611d75590 | 22 | |
Geekshow | 3:de9611d75590 | 23 | //#define INPUTPINx PC_15 // Don't use D23 |
Geekshow | 3:de9611d75590 | 24 | #define INPUTPIN0 PB_9 // DHT22 digital pin (D24) |
Geekshow | 3:de9611d75590 | 25 | #define INPUTPIN1 PD_2 // DHT22 digital pin (D25) |
Geekshow | 3:de9611d75590 | 26 | #define INPUTPIN2 PC_10 // DHT22 digital pin (D26) |
Geekshow | 3:de9611d75590 | 27 | //#define INPUTPINx PB_0 // Don't use D27 |
Geekshow | 3:de9611d75590 | 28 | //#define INPUTPINx PB_1 // Don't use D28 |
Geekshow | 3:de9611d75590 | 29 | #define INPUTPIN3 PB_10 // digital pin (D29) |
Geekshow | 3:de9611d75590 | 30 | #define INPUTPIN4 PB_11 // digital pin (D30) |
Geekshow | 3:de9611d75590 | 31 | #define INPUTPIN5 PB_12 // digital pin (D31) |
Geekshow | 3:de9611d75590 | 32 | #define INPUTPIN6 PB_13 // digital pin (D32) |
Geekshow | 3:de9611d75590 | 33 | #define INPUTPIN7 PB_14 // digital pin (D33) |
Geekshow | 3:de9611d75590 | 34 | #define INPUTPIN8 PB_15 // digital pin (D34) |
Geekshow | 3:de9611d75590 | 35 | #define INPUTPIN9 PC_6 // digital pin (D35) |
Geekshow | 3:de9611d75590 | 36 | #define INPUTPIN10 PC_7 // digital pin (D36) |
Geekshow | 3:de9611d75590 | 37 | #define INPUTPIN11 PC_8 // digital pin (D37) |
Geekshow | 3:de9611d75590 | 38 | |
Geekshow | 3:de9611d75590 | 39 | #define OUTPUTPIN0 PA_3 // digital output D0 |
Geekshow | 3:de9611d75590 | 40 | #define OUTPUTPIN1 PA_2 // digital output D1 |
Geekshow | 3:de9611d75590 | 41 | #define OUTPUTPIN2 PA_0 // digital output D2 |
Geekshow | 3:de9611d75590 | 42 | #define OUTPUTPIN3 PA_1 // digital output D3 |
Geekshow | 3:de9611d75590 | 43 | #define OUTPUTPIN4 PB_5 // digital output D4 |
Geekshow | 3:de9611d75590 | 44 | #define OUTPUTPIN5 PB_6 // digital output D5 |
Geekshow | 3:de9611d75590 | 45 | #define OUTPUTPIN6 PA_8 // digital output D6 |
Geekshow | 3:de9611d75590 | 46 | #define OUTPUTPIN7 PA_9 // digital output D7 |
Geekshow | 3:de9611d75590 | 47 | #define OUTPUTPIN8 PA_10 // digital output D8 |
Geekshow | 3:de9611d75590 | 48 | #define OUTPUTPIN9 PB_7 // digital output D9 |
Geekshow | 3:de9611d75590 | 49 | //#define OUTPUTPINx PA_4 // digital output D10 - SPI1 SS |
Geekshow | 3:de9611d75590 | 50 | //#define OUTPUTPINx PA_4 // digital output D11 - SPI1 MOSI |
Geekshow | 3:de9611d75590 | 51 | //#define OUTPUTPINx PA_4 // digital output D12 - SPI1 MISO |
Geekshow | 3:de9611d75590 | 52 | //#define OUTPUTPINx PA_4 // digital output D13 - SPI1 CLK |
Geekshow | 3:de9611d75590 | 53 | #define OUTPUTPIN10 PB_8 // digital output D14 |
Geekshow | 3:de9611d75590 | 54 | // ================= *************** ================== |
Geekshow | 3:de9611d75590 | 55 | #define USART3_TX PC_10 |
Geekshow | 3:de9611d75590 | 56 | // ================= *************** ================== |
Geekshow | 4:ebaf1973d008 | 57 | #define NODE_NAME "controller03" // TODO just define node number |
Geekshow | 3:de9611d75590 | 58 | |
Geekshow | 5:b2ae1ed8a30e | 59 | Ticker tick_5sec; |
Geekshow | 5:b2ae1ed8a30e | 60 | Ticker tick_1sec; |
Geekshow | 4:ebaf1973d008 | 61 | |
Geekshow | 4:ebaf1973d008 | 62 | typedef MQTT::Client<MQTTSocket,Countdown> MClient; |
Geekshow | 4:ebaf1973d008 | 63 | |
Geekshow | 4:ebaf1973d008 | 64 | const char* ONOFF[] = {"OFF", "ON"}; |
Geekshow | 4:ebaf1973d008 | 65 | const char* OPENCLOSED[] = {"CLOSED", "OPEN"}; |
Geekshow | 4:ebaf1973d008 | 66 | |
Geekshow | 4:ebaf1973d008 | 67 | Serial pc(USART3_TX, NC); // serial debug output on D26 (pin 4 of Extension) |
Geekshow | 3:de9611d75590 | 68 | |
Geekshow | 4:ebaf1973d008 | 69 | DigitalIn button(BUTTON); |
Geekshow | 4:ebaf1973d008 | 70 | DigitalOut led(LED_GREEN); |
Geekshow | 4:ebaf1973d008 | 71 | DigitalOut output0(OUTPUTPIN0); |
Geekshow | 4:ebaf1973d008 | 72 | |
Geekshow | 5:b2ae1ed8a30e | 73 | uint8_t mac_addr[6]={0x00, 0x00, 0x00, 0xBE, 0xEF, 0x03}; // TODO make last byte dynamic |
Geekshow | 5:b2ae1ed8a30e | 74 | const char* mqtt_broker = "192.168.1.99"; |
Geekshow | 5:b2ae1ed8a30e | 75 | const int mqtt_port = 1883; |
Geekshow | 5:b2ae1ed8a30e | 76 | unsigned long uptime_sec = 0; |
Geekshow | 5:b2ae1ed8a30e | 77 | |
Geekshow | 5:b2ae1ed8a30e | 78 | |
Geekshow | 4:ebaf1973d008 | 79 | const char* inputs[2] = { |
Geekshow | 4:ebaf1973d008 | 80 | "button", |
Geekshow | 4:ebaf1973d008 | 81 | NULL |
Geekshow | 4:ebaf1973d008 | 82 | }; |
Geekshow | 4:ebaf1973d008 | 83 | |
Geekshow | 4:ebaf1973d008 | 84 | const char* outputs[2] = { |
Geekshow | 4:ebaf1973d008 | 85 | "output0", |
Geekshow | 4:ebaf1973d008 | 86 | NULL |
Geekshow | 4:ebaf1973d008 | 87 | }; |
Geekshow | 4:ebaf1973d008 | 88 | |
zhangyx | 0:1170747a672f | 89 | |
zhangyx | 2:a50b794b8ede | 90 | void on_control_cmd(const char* actuator_name, const char* control_value) |
zhangyx | 0:1170747a672f | 91 | { |
Geekshow | 4:ebaf1973d008 | 92 | int new_state = 0; |
zhangyx | 2:a50b794b8ede | 93 | pc.printf("Received CMD %s %s\r\n", actuator_name, control_value); |
Geekshow | 4:ebaf1973d008 | 94 | if(strcmp(control_value, "ON") == 0) { |
Geekshow | 4:ebaf1973d008 | 95 | pc.printf("ON value requested!\r\n"); |
Geekshow | 4:ebaf1973d008 | 96 | new_state = 1; |
Geekshow | 4:ebaf1973d008 | 97 | } |
Geekshow | 4:ebaf1973d008 | 98 | else if(strcmp(control_value, "OFF") == 0) { |
Geekshow | 4:ebaf1973d008 | 99 | pc.printf("OFF value requested!\r\n"); |
Geekshow | 4:ebaf1973d008 | 100 | new_state = 0; |
Geekshow | 4:ebaf1973d008 | 101 | } |
Geekshow | 4:ebaf1973d008 | 102 | else { |
Geekshow | 4:ebaf1973d008 | 103 | pc.printf("No value specified! In future return the current value...\r\n"); |
Geekshow | 4:ebaf1973d008 | 104 | return; |
Geekshow | 4:ebaf1973d008 | 105 | } |
Geekshow | 4:ebaf1973d008 | 106 | |
Geekshow | 4:ebaf1973d008 | 107 | if(strcmp(actuator_name, "output0") == 0) { |
Geekshow | 4:ebaf1973d008 | 108 | pc.printf("Output: %s updated to %d\r\n", actuator_name, new_state); |
Geekshow | 4:ebaf1973d008 | 109 | led = new_state; |
Geekshow | 4:ebaf1973d008 | 110 | output0 = new_state; |
Geekshow | 4:ebaf1973d008 | 111 | } |
Geekshow | 4:ebaf1973d008 | 112 | } |
Geekshow | 4:ebaf1973d008 | 113 | |
Geekshow | 4:ebaf1973d008 | 114 | void read_inputs() |
Geekshow | 4:ebaf1973d008 | 115 | { |
Geekshow | 5:b2ae1ed8a30e | 116 | |
Geekshow | 4:ebaf1973d008 | 117 | } |
Geekshow | 4:ebaf1973d008 | 118 | |
Geekshow | 4:ebaf1973d008 | 119 | |
Geekshow | 4:ebaf1973d008 | 120 | void set_outputs() |
Geekshow | 4:ebaf1973d008 | 121 | { |
Geekshow | 4:ebaf1973d008 | 122 | } |
Geekshow | 4:ebaf1973d008 | 123 | |
Geekshow | 4:ebaf1973d008 | 124 | |
Geekshow | 4:ebaf1973d008 | 125 | int publish(MClient& client, const char* msg_type, const char* point, |
Geekshow | 4:ebaf1973d008 | 126 | const char* payload = NULL, size_t payload_len = 0, |
Geekshow | 4:ebaf1973d008 | 127 | bool retain = false, MQTT::QoS qos = MQTT::QOS1){ |
Geekshow | 4:ebaf1973d008 | 128 | char topic[64]; |
Geekshow | 4:ebaf1973d008 | 129 | sprintf(topic, "%s/" NODE_NAME "/%s", msg_type, point); |
Geekshow | 4:ebaf1973d008 | 130 | int ret = client.publish(topic, (void*)payload, payload_len, qos, retain); |
Geekshow | 4:ebaf1973d008 | 131 | if(ret == -1) { |
Geekshow | 4:ebaf1973d008 | 132 | pc.printf("ERROR during client.publish() = %d\r\n",ret); |
Geekshow | 4:ebaf1973d008 | 133 | } |
Geekshow | 4:ebaf1973d008 | 134 | return ret; |
zhangyx | 0:1170747a672f | 135 | } |
zhangyx | 2:a50b794b8ede | 136 | |
Geekshow | 4:ebaf1973d008 | 137 | |
Geekshow | 4:ebaf1973d008 | 138 | void messageArrived(MQTT::MessageData& md) |
Geekshow | 3:de9611d75590 | 139 | { |
Geekshow | 4:ebaf1973d008 | 140 | MQTT::Message &message = md.message; |
Geekshow | 4:ebaf1973d008 | 141 | |
Geekshow | 4:ebaf1973d008 | 142 | // copy message payload into local char array IMPROVE ME! |
Geekshow | 4:ebaf1973d008 | 143 | char* payload = new char[message.payloadlen+1]; |
Geekshow | 4:ebaf1973d008 | 144 | if(!payload) |
Geekshow | 4:ebaf1973d008 | 145 | return; |
Geekshow | 4:ebaf1973d008 | 146 | memcpy(payload, message.payload, message.payloadlen); |
Geekshow | 4:ebaf1973d008 | 147 | payload[message.payloadlen]='\0'; |
Geekshow | 4:ebaf1973d008 | 148 | |
Geekshow | 4:ebaf1973d008 | 149 | // copy topic payload into local char array IMPROVE ME! |
Geekshow | 4:ebaf1973d008 | 150 | char* topic = new char[md.topicName.lenstring.len+1]; |
Geekshow | 4:ebaf1973d008 | 151 | if(!topic){ |
Geekshow | 4:ebaf1973d008 | 152 | delete[] payload; |
Geekshow | 4:ebaf1973d008 | 153 | return; |
Geekshow | 4:ebaf1973d008 | 154 | } |
Geekshow | 4:ebaf1973d008 | 155 | memcpy(topic, md.topicName.lenstring.data, md.topicName.lenstring.len); |
Geekshow | 4:ebaf1973d008 | 156 | topic[md.topicName.lenstring.len]='\0'; |
Geekshow | 4:ebaf1973d008 | 157 | |
Geekshow | 4:ebaf1973d008 | 158 | pc.printf("Rcvd: %s : %s\r\n", topic, payload); |
Geekshow | 4:ebaf1973d008 | 159 | |
Geekshow | 4:ebaf1973d008 | 160 | // split up topic string |
Geekshow | 4:ebaf1973d008 | 161 | char *topics = strtok (topic,"/"); |
Geekshow | 4:ebaf1973d008 | 162 | for (int tok=0; tok<2 && topics != NULL; tok++) // WARNING! hard coded 2 layer topic! |
Geekshow | 4:ebaf1973d008 | 163 | { |
Geekshow | 4:ebaf1973d008 | 164 | // pc.printf ("%s\r\n",topics); |
Geekshow | 4:ebaf1973d008 | 165 | topics = strtok (NULL, "/"); |
Geekshow | 4:ebaf1973d008 | 166 | } |
Geekshow | 4:ebaf1973d008 | 167 | on_control_cmd(topics, payload); |
Geekshow | 4:ebaf1973d008 | 168 | delete[] topic; |
Geekshow | 4:ebaf1973d008 | 169 | delete[] payload; |
Geekshow | 3:de9611d75590 | 170 | } |
Geekshow | 3:de9611d75590 | 171 | |
Geekshow | 4:ebaf1973d008 | 172 | |
Geekshow | 4:ebaf1973d008 | 173 | int publish_value(MClient &client, const char *topic, const char *buf) |
Geekshow | 3:de9611d75590 | 174 | { |
Geekshow | 4:ebaf1973d008 | 175 | return publish(client, "stat", topic, buf, strlen(buf), true); |
Geekshow | 4:ebaf1973d008 | 176 | } |
Geekshow | 4:ebaf1973d008 | 177 | |
Geekshow | 5:b2ae1ed8a30e | 178 | WIZnetInterface wiz(PA_7, PA_6, PA_5, PA_4, PB_10); // SPI1 with D29 (reset) |
Geekshow | 5:b2ae1ed8a30e | 179 | MQTTSocket sock; |
Geekshow | 5:b2ae1ed8a30e | 180 | MClient client(sock); |
Geekshow | 5:b2ae1ed8a30e | 181 | int connected = -1; |
Geekshow | 5:b2ae1ed8a30e | 182 | |
Geekshow | 5:b2ae1ed8a30e | 183 | int networking_init(MQTTSocket &sock, MClient &client, WIZnetInterface &wiz) { |
Geekshow | 4:ebaf1973d008 | 184 | int ret = 0; |
Geekshow | 4:ebaf1973d008 | 185 | pc.printf("\n\nNode: %s\r\n", NODE_NAME); |
Geekshow | 4:ebaf1973d008 | 186 | pc.printf("%s attempting ethernet connection...\r\n", NODE_NAME); |
Geekshow | 4:ebaf1973d008 | 187 | wiz.init(mac_addr); // resets the w5500 |
Geekshow | 4:ebaf1973d008 | 188 | if (wiz.connect() == (-1)) { |
Geekshow | 4:ebaf1973d008 | 189 | pc.printf("Error getting DHCP address!!\r\n"); |
Geekshow | 4:ebaf1973d008 | 190 | } |
Geekshow | 4:ebaf1973d008 | 191 | |
Geekshow | 4:ebaf1973d008 | 192 | pc.printf("IP: %s\r\n", wiz.getIPAddress()); |
Geekshow | 5:b2ae1ed8a30e | 193 | |
Geekshow | 4:ebaf1973d008 | 194 | ret = sock.connect((char*)mqtt_broker,mqtt_port); |
Geekshow | 4:ebaf1973d008 | 195 | if(ret != 0){ |
Geekshow | 4:ebaf1973d008 | 196 | pc.printf("failed to connect to TCP server\r\n"); |
Geekshow | 4:ebaf1973d008 | 197 | return 1; |
Geekshow | 4:ebaf1973d008 | 198 | } |
Geekshow | 4:ebaf1973d008 | 199 | pc.printf("sock.connect()=%d\r\n",ret); |
Geekshow | 5:b2ae1ed8a30e | 200 | |
Geekshow | 4:ebaf1973d008 | 201 | if(client.connect() != 0){ |
Geekshow | 4:ebaf1973d008 | 202 | pc.printf("MQTT connect failed\r\n"); |
Geekshow | 4:ebaf1973d008 | 203 | return -1; |
Geekshow | 4:ebaf1973d008 | 204 | } |
Geekshow | 4:ebaf1973d008 | 205 | pc.printf("client.connect()=%d\r\n",ret); |
Geekshow | 4:ebaf1973d008 | 206 | |
Geekshow | 4:ebaf1973d008 | 207 | |
Geekshow | 4:ebaf1973d008 | 208 | ret = client.subscribe("cmnd/" NODE_NAME "/+", MQTT::QOS1, messageArrived); |
Geekshow | 4:ebaf1973d008 | 209 | pc.printf("client.subscribe()=%d\r\n", ret); |
Geekshow | 4:ebaf1973d008 | 210 | |
Geekshow | 4:ebaf1973d008 | 211 | // Node online message |
Geekshow | 5:b2ae1ed8a30e | 212 | publish_value(client, "alive","ON"); |
Geekshow | 5:b2ae1ed8a30e | 213 | publish_value(client, "IPAddress", wiz.getIPAddress()); |
Geekshow | 4:ebaf1973d008 | 214 | pc.printf("Initialization done.\r\n"); |
Geekshow | 4:ebaf1973d008 | 215 | |
Geekshow | 4:ebaf1973d008 | 216 | return 0; |
Geekshow | 5:b2ae1ed8a30e | 217 | } |
Geekshow | 5:b2ae1ed8a30e | 218 | |
Geekshow | 5:b2ae1ed8a30e | 219 | void periodic_announcement() { |
Geekshow | 5:b2ae1ed8a30e | 220 | // announce statuses |
Geekshow | 5:b2ae1ed8a30e | 221 | char uptime_sec_str[12]; |
Geekshow | 5:b2ae1ed8a30e | 222 | sprintf(uptime_sec_str, "%d", uptime_sec); |
Geekshow | 5:b2ae1ed8a30e | 223 | connected = publish_value(client,"uptime",uptime_sec_str); |
Geekshow | 3:de9611d75590 | 224 | } |
Geekshow | 3:de9611d75590 | 225 | |
Geekshow | 5:b2ae1ed8a30e | 226 | void every_second() { |
Geekshow | 5:b2ae1ed8a30e | 227 | uptime_sec++; |
Geekshow | 5:b2ae1ed8a30e | 228 | } |
Geekshow | 3:de9611d75590 | 229 | |
Geekshow | 3:de9611d75590 | 230 | int main() |
Geekshow | 3:de9611d75590 | 231 | { |
Geekshow | 5:b2ae1ed8a30e | 232 | tick_1sec.attach(&every_second, 1.0); |
Geekshow | 5:b2ae1ed8a30e | 233 | pc.printf("\n\nNode: %s\r\n", NODE_NAME); |
Geekshow | 3:de9611d75590 | 234 | |
Geekshow | 5:b2ae1ed8a30e | 235 | connected = networking_init(sock, client, wiz); |
Geekshow | 5:b2ae1ed8a30e | 236 | |
Geekshow | 5:b2ae1ed8a30e | 237 | tick_5sec.attach(&periodic_announcement, 5.0); |
Geekshow | 3:de9611d75590 | 238 | |
Geekshow | 3:de9611d75590 | 239 | while(1) { |
Geekshow | 4:ebaf1973d008 | 240 | set_outputs(); |
Geekshow | 4:ebaf1973d008 | 241 | read_inputs(); |
Geekshow | 3:de9611d75590 | 242 | |
Geekshow | 5:b2ae1ed8a30e | 243 | |
Geekshow | 5:b2ae1ed8a30e | 244 | if(connected != 0) { |
Geekshow | 5:b2ae1ed8a30e | 245 | pc.printf("Restarting network....\r\n"); |
Geekshow | 5:b2ae1ed8a30e | 246 | networking_init(sock, client, wiz); |
zhangyx | 0:1170747a672f | 247 | } |
Geekshow | 5:b2ae1ed8a30e | 248 | // pause a while, yawn...... |
Geekshow | 5:b2ae1ed8a30e | 249 | // client.yield(1000); |
zhangyx | 0:1170747a672f | 250 | } |
zhangyx | 0:1170747a672f | 251 | } |