IoT sensor/controller using STM32, W5500 ethernet, MQTT
Dependencies: mbed WIZnet_Library Watchdog DHT MQTT DS1820
main.cpp@11:2a397ea7acc8, 2020-03-03 (annotated)
- Committer:
- Geekshow
- Date:
- Tue Mar 03 00:15:32 2020 +0000
- Revision:
- 11:2a397ea7acc8
- Parent:
- 10:3ad12f8d8b46
- Child:
- 12:bcb38c1af703
Added DS18B20 temp measurement
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
zhangyx | 0:1170747a672f | 1 | #include "mbed.h" |
Geekshow | 7:3c2222251deb | 2 | #include "Watchdog.h" |
Geekshow | 3:de9611d75590 | 3 | //#include "rtos.h" |
Geekshow | 3:de9611d75590 | 4 | //#include "pins.h" |
Geekshow | 4:ebaf1973d008 | 5 | #include "WIZnetInterface.h" |
Geekshow | 4:ebaf1973d008 | 6 | #include "MQTTSocket.h" |
Geekshow | 4:ebaf1973d008 | 7 | #include "MQTTClient.h" |
Geekshow | 3:de9611d75590 | 8 | |
Geekshow | 3:de9611d75590 | 9 | // ========== PIN DEFINITIONS ============ |
Geekshow | 6:4d30bc5a8076 | 10 | // TODO move pin definitions into separate file |
Geekshow | 4:ebaf1973d008 | 11 | #define LED_GREEN PA_5 |
Geekshow | 4:ebaf1973d008 | 12 | #define LED_ORANGE PA_1 // Don't use! Shared with D3 |
Geekshow | 3:de9611d75590 | 13 | #define BUTTON PC_9 |
Geekshow | 3:de9611d75590 | 14 | |
Geekshow | 6:4d30bc5a8076 | 15 | #define A_0 PC_0 // Analogue Input 0 |
Geekshow | 6:4d30bc5a8076 | 16 | #define A_1 PC_1 // Analogue Input 1 |
Geekshow | 6:4d30bc5a8076 | 17 | #define A_2 PC_2 // Analogue Input 2 |
Geekshow | 6:4d30bc5a8076 | 18 | #define A_3 PC_3 // Analogue Input 3 |
Geekshow | 6:4d30bc5a8076 | 19 | #define A_4 PC_4 // Analogue Input 4 |
Geekshow | 6:4d30bc5a8076 | 20 | #define A_5 PC_5 // Analogue Input 5 |
Geekshow | 3:de9611d75590 | 21 | |
Geekshow | 6:4d30bc5a8076 | 22 | #define D_0 PA_3 // digital output D0 |
Geekshow | 6:4d30bc5a8076 | 23 | #define D_1 PA_2 // digital output D1 |
Geekshow | 6:4d30bc5a8076 | 24 | #define D_2 PA_0 // digital output D2 |
Geekshow | 6:4d30bc5a8076 | 25 | #define D_3 PA_1 // digital output D3 |
Geekshow | 6:4d30bc5a8076 | 26 | #define D_4 PB_5 // digital output D4 |
Geekshow | 6:4d30bc5a8076 | 27 | #define D_5 PB_6 // digital output D5 |
Geekshow | 6:4d30bc5a8076 | 28 | #define D_6 PA_8 // digital output D6 |
Geekshow | 6:4d30bc5a8076 | 29 | #define D_7 PA_9 // digital output D7 |
Geekshow | 6:4d30bc5a8076 | 30 | #define D_8 PA_10 // digital output D8 |
Geekshow | 6:4d30bc5a8076 | 31 | #define D_9 PB_7 // digital output D9 |
Geekshow | 6:4d30bc5a8076 | 32 | #define D_10 PA_4 // digital output D10 - SPI1 SS |
Geekshow | 6:4d30bc5a8076 | 33 | #define D_11 PA_4 // digital output D11 - SPI1 MOSI |
Geekshow | 6:4d30bc5a8076 | 34 | #define D_12 PA_4 // digital output D12 - SPI1 MISO |
Geekshow | 6:4d30bc5a8076 | 35 | //#define D_13 PA_4 // digital output D13 - SPI1 CLK - GREEN LED |
Geekshow | 6:4d30bc5a8076 | 36 | #define D_14 PB_8 // digital output D14 |
Geekshow | 8:6d7be3bed961 | 37 | #define D_35 PC_6 // pin 13 on Extension |
Geekshow | 8:6d7be3bed961 | 38 | #define D_36 PC_7 // pin 14 on Extension |
Geekshow | 8:6d7be3bed961 | 39 | #define D_37 PC_8 // pin 15 on Extension (last) |
Geekshow | 3:de9611d75590 | 40 | // ================= *************** ================== |
Geekshow | 8:6d7be3bed961 | 41 | #define USART3_TX PC_10 // D26 - pin 4 on Extension |
Geekshow | 6:4d30bc5a8076 | 42 | // ================= *************** ================== |
Geekshow | 6:4d30bc5a8076 | 43 | // serial output? for uLCD |
Geekshow | 6:4d30bc5a8076 | 44 | // ================= *************** ================== |
Geekshow | 8:6d7be3bed961 | 45 | // sensor inputs |
Geekshow | 11:2a397ea7acc8 | 46 | #include "DS1820.h" |
Geekshow | 11:2a397ea7acc8 | 47 | #define MAX_PROBES 4 |
Geekshow | 11:2a397ea7acc8 | 48 | #define ONEWIRE_PIN PB_11 // D30 pin 6 on UEXT // pin 8 on Extension |
Geekshow | 11:2a397ea7acc8 | 49 | DS1820* probe[MAX_PROBES]; |
Geekshow | 11:2a397ea7acc8 | 50 | #include "DHT.h" |
Geekshow | 11:2a397ea7acc8 | 51 | #define DHT_PIN PB_10 // D29 pin 5 on UEXT // pin 7 on Extension |
Geekshow | 3:de9611d75590 | 52 | // ================= *************** ================== |
Geekshow | 4:ebaf1973d008 | 53 | #define NODE_NAME "controller03" // TODO just define node number |
Geekshow | 3:de9611d75590 | 54 | |
Geekshow | 6:4d30bc5a8076 | 55 | #define NUM_OUTPUTS 8 |
Geekshow | 6:4d30bc5a8076 | 56 | DigitalOut outputs[NUM_OUTPUTS] = {D_0, D_1, D_2, D_3, D_4, D_5, D_6, D_7}; |
Geekshow | 6:4d30bc5a8076 | 57 | #define NUM_INPUTS 6 |
Geekshow | 6:4d30bc5a8076 | 58 | DigitalIn inputs[NUM_INPUTS] = {PC_0, PC_1, PC_2, PC_3, PC_4, PC_5}; |
Geekshow | 6:4d30bc5a8076 | 59 | bool input_state[NUM_INPUTS]; |
Geekshow | 6:4d30bc5a8076 | 60 | |
Geekshow | 6:4d30bc5a8076 | 61 | Serial pc(USART3_TX, NC); // serial debug output on D26 (pin 4 of Extension) |
Geekshow | 6:4d30bc5a8076 | 62 | //Serial pc(PA_9, NC); // serial debug output on D7 |
Geekshow | 6:4d30bc5a8076 | 63 | //Serial xxxxxx // find a serial port for Amp/uLCD connection |
Geekshow | 6:4d30bc5a8076 | 64 | |
Geekshow | 6:4d30bc5a8076 | 65 | DigitalIn button(BUTTON); |
Geekshow | 6:4d30bc5a8076 | 66 | DigitalOut led(LED_GREEN); |
Geekshow | 6:4d30bc5a8076 | 67 | |
Geekshow | 11:2a397ea7acc8 | 68 | DHT dht0(DHT_PIN, DHT22); |
Geekshow | 11:2a397ea7acc8 | 69 | float temp[1]; |
Geekshow | 11:2a397ea7acc8 | 70 | float humidity[1]; |
Geekshow | 9:a8098e772b48 | 71 | |
Geekshow | 7:3c2222251deb | 72 | Watchdog wd; |
Geekshow | 6:4d30bc5a8076 | 73 | Ticker tick_60sec; |
Geekshow | 5:b2ae1ed8a30e | 74 | Ticker tick_5sec; |
Geekshow | 5:b2ae1ed8a30e | 75 | Ticker tick_1sec; |
Geekshow | 6:4d30bc5a8076 | 76 | Ticker tick_500ms; |
Geekshow | 6:4d30bc5a8076 | 77 | |
Geekshow | 6:4d30bc5a8076 | 78 | bool flag_publish; |
Geekshow | 11:2a397ea7acc8 | 79 | bool flag_read_dht; |
Geekshow | 11:2a397ea7acc8 | 80 | bool flag_read_ds18b20; |
Geekshow | 4:ebaf1973d008 | 81 | |
Geekshow | 4:ebaf1973d008 | 82 | typedef MQTT::Client<MQTTSocket,Countdown> MClient; |
Geekshow | 4:ebaf1973d008 | 83 | |
Geekshow | 6:4d30bc5a8076 | 84 | const char* ONOFF[] = {"ON", "OFF"}; |
Geekshow | 4:ebaf1973d008 | 85 | const char* OPENCLOSED[] = {"CLOSED", "OPEN"}; |
Geekshow | 6:4d30bc5a8076 | 86 | enum IO_STATE{IO_ON, IO_OFF}; |
Geekshow | 4:ebaf1973d008 | 87 | |
Geekshow | 5:b2ae1ed8a30e | 88 | uint8_t mac_addr[6]={0x00, 0x00, 0x00, 0xBE, 0xEF, 0x03}; // TODO make last byte dynamic |
Geekshow | 8:6d7be3bed961 | 89 | //const char* mqtt_broker = "192.168.10.4"; |
Geekshow | 8:6d7be3bed961 | 90 | const char* mqtt_broker = "192.168.1.99"; |
Geekshow | 5:b2ae1ed8a30e | 91 | const int mqtt_port = 1883; |
Geekshow | 5:b2ae1ed8a30e | 92 | unsigned long uptime_sec = 0; |
Geekshow | 6:4d30bc5a8076 | 93 | int connected = -1; |
Geekshow | 5:b2ae1ed8a30e | 94 | |
Geekshow | 5:b2ae1ed8a30e | 95 | |
Geekshow | 4:ebaf1973d008 | 96 | |
Geekshow | 6:4d30bc5a8076 | 97 | void on_control_cmd(const char* topic, const char* message) |
zhangyx | 0:1170747a672f | 98 | { |
Geekshow | 4:ebaf1973d008 | 99 | int new_state = 0; |
Geekshow | 6:4d30bc5a8076 | 100 | pc.printf("Received CMD %s %s\r\n", topic, message); |
Geekshow | 6:4d30bc5a8076 | 101 | // find out command first |
Geekshow | 6:4d30bc5a8076 | 102 | if(strcmp(message, "ON") == 0) { |
Geekshow | 4:ebaf1973d008 | 103 | pc.printf("ON value requested!\r\n"); |
Geekshow | 6:4d30bc5a8076 | 104 | new_state = IO_ON; |
Geekshow | 4:ebaf1973d008 | 105 | } |
Geekshow | 6:4d30bc5a8076 | 106 | else if(strcmp(message, "OFF") == 0) { |
Geekshow | 4:ebaf1973d008 | 107 | pc.printf("OFF value requested!\r\n"); |
Geekshow | 6:4d30bc5a8076 | 108 | new_state = IO_OFF; |
Geekshow | 4:ebaf1973d008 | 109 | } |
Geekshow | 4:ebaf1973d008 | 110 | else { |
Geekshow | 6:4d30bc5a8076 | 111 | pc.printf("Unknown command value specified!\r\n"); // TODO return current value on no message |
Geekshow | 4:ebaf1973d008 | 112 | return; |
Geekshow | 4:ebaf1973d008 | 113 | } |
Geekshow | 6:4d30bc5a8076 | 114 | // are we updating an output? |
Geekshow | 6:4d30bc5a8076 | 115 | if(strncmp(topic, "output", 6) == 0) { |
Geekshow | 6:4d30bc5a8076 | 116 | // find out which output to apply it to |
Geekshow | 6:4d30bc5a8076 | 117 | int output_num = int(topic[6])-48; |
Geekshow | 6:4d30bc5a8076 | 118 | if(output_num >= NUM_OUTPUTS) { |
Geekshow | 6:4d30bc5a8076 | 119 | pc.printf("ERROR: unknown output num %d\r\n", output_num); |
Geekshow | 6:4d30bc5a8076 | 120 | } |
Geekshow | 6:4d30bc5a8076 | 121 | else { |
Geekshow | 6:4d30bc5a8076 | 122 | // turn something on/off! |
Geekshow | 6:4d30bc5a8076 | 123 | pc.printf("Output: %d updated to %s\r\n", output_num, ONOFF[new_state]); |
Geekshow | 6:4d30bc5a8076 | 124 | outputs[output_num] = new_state; |
Geekshow | 10:3ad12f8d8b46 | 125 | flag_publish = 1; // workaround for below |
Geekshow | 10:3ad12f8d8b46 | 126 | // publish_value(client, topic, ONOFF[new_state], false); // needs to access client :-/ |
Geekshow | 6:4d30bc5a8076 | 127 | } |
Geekshow | 6:4d30bc5a8076 | 128 | } |
Geekshow | 6:4d30bc5a8076 | 129 | else { |
Geekshow | 6:4d30bc5a8076 | 130 | pc.printf("ERROR: Couldn't parse topic: %s\r\n", topic); |
Geekshow | 4:ebaf1973d008 | 131 | } |
Geekshow | 4:ebaf1973d008 | 132 | } |
Geekshow | 4:ebaf1973d008 | 133 | |
Geekshow | 4:ebaf1973d008 | 134 | int publish(MClient& client, const char* msg_type, const char* point, |
Geekshow | 4:ebaf1973d008 | 135 | const char* payload = NULL, size_t payload_len = 0, |
Geekshow | 4:ebaf1973d008 | 136 | bool retain = false, MQTT::QoS qos = MQTT::QOS1){ |
Geekshow | 4:ebaf1973d008 | 137 | char topic[64]; |
Geekshow | 4:ebaf1973d008 | 138 | sprintf(topic, "%s/" NODE_NAME "/%s", msg_type, point); |
Geekshow | 4:ebaf1973d008 | 139 | int ret = client.publish(topic, (void*)payload, payload_len, qos, retain); |
Geekshow | 4:ebaf1973d008 | 140 | if(ret == -1) { |
Geekshow | 4:ebaf1973d008 | 141 | pc.printf("ERROR during client.publish() = %d\r\n",ret); |
Geekshow | 4:ebaf1973d008 | 142 | } |
Geekshow | 4:ebaf1973d008 | 143 | return ret; |
zhangyx | 0:1170747a672f | 144 | } |
zhangyx | 2:a50b794b8ede | 145 | |
Geekshow | 4:ebaf1973d008 | 146 | |
Geekshow | 4:ebaf1973d008 | 147 | void messageArrived(MQTT::MessageData& md) |
Geekshow | 3:de9611d75590 | 148 | { |
Geekshow | 6:4d30bc5a8076 | 149 | // MQTT callback function |
Geekshow | 4:ebaf1973d008 | 150 | MQTT::Message &message = md.message; |
Geekshow | 4:ebaf1973d008 | 151 | |
Geekshow | 4:ebaf1973d008 | 152 | // copy message payload into local char array IMPROVE ME! |
Geekshow | 4:ebaf1973d008 | 153 | char* payload = new char[message.payloadlen+1]; |
Geekshow | 6:4d30bc5a8076 | 154 | if(!payload) // will this ever happen? |
Geekshow | 4:ebaf1973d008 | 155 | return; |
Geekshow | 4:ebaf1973d008 | 156 | memcpy(payload, message.payload, message.payloadlen); |
Geekshow | 4:ebaf1973d008 | 157 | payload[message.payloadlen]='\0'; |
Geekshow | 4:ebaf1973d008 | 158 | |
Geekshow | 4:ebaf1973d008 | 159 | // copy topic payload into local char array IMPROVE ME! |
Geekshow | 4:ebaf1973d008 | 160 | char* topic = new char[md.topicName.lenstring.len+1]; |
Geekshow | 6:4d30bc5a8076 | 161 | if(!topic){ // will this ever happen? |
Geekshow | 4:ebaf1973d008 | 162 | delete[] payload; |
Geekshow | 4:ebaf1973d008 | 163 | return; |
Geekshow | 4:ebaf1973d008 | 164 | } |
Geekshow | 4:ebaf1973d008 | 165 | memcpy(topic, md.topicName.lenstring.data, md.topicName.lenstring.len); |
Geekshow | 4:ebaf1973d008 | 166 | topic[md.topicName.lenstring.len]='\0'; |
Geekshow | 4:ebaf1973d008 | 167 | |
Geekshow | 4:ebaf1973d008 | 168 | pc.printf("Rcvd: %s : %s\r\n", topic, payload); |
Geekshow | 4:ebaf1973d008 | 169 | |
Geekshow | 6:4d30bc5a8076 | 170 | // find first delimiter in topic string |
Geekshow | 4:ebaf1973d008 | 171 | char *topics = strtok (topic,"/"); |
Geekshow | 4:ebaf1973d008 | 172 | for (int tok=0; tok<2 && topics != NULL; tok++) // WARNING! hard coded 2 layer topic! |
Geekshow | 4:ebaf1973d008 | 173 | { |
Geekshow | 6:4d30bc5a8076 | 174 | // pc.printf ("Topics %d: %s\r\n",tok, topics); |
Geekshow | 4:ebaf1973d008 | 175 | topics = strtok (NULL, "/"); |
Geekshow | 4:ebaf1973d008 | 176 | } |
Geekshow | 4:ebaf1973d008 | 177 | on_control_cmd(topics, payload); |
Geekshow | 4:ebaf1973d008 | 178 | delete[] topic; |
Geekshow | 4:ebaf1973d008 | 179 | delete[] payload; |
Geekshow | 3:de9611d75590 | 180 | } |
Geekshow | 3:de9611d75590 | 181 | |
Geekshow | 4:ebaf1973d008 | 182 | |
Geekshow | 10:3ad12f8d8b46 | 183 | int publish_value(MClient &client, const char *topic, const char *buf, bool retain = false) |
Geekshow | 3:de9611d75590 | 184 | { |
Geekshow | 10:3ad12f8d8b46 | 185 | return publish(client, "stat", topic, buf, strlen(buf), retain); |
Geekshow | 4:ebaf1973d008 | 186 | } |
Geekshow | 4:ebaf1973d008 | 187 | |
Geekshow | 6:4d30bc5a8076 | 188 | |
Geekshow | 6:4d30bc5a8076 | 189 | void publish_outputs(MClient &client) { |
Geekshow | 6:4d30bc5a8076 | 190 | for(int i=0; i<NUM_OUTPUTS; i++) { |
Geekshow | 6:4d30bc5a8076 | 191 | bool output_state = outputs[i]; |
Geekshow | 6:4d30bc5a8076 | 192 | char topic[] = "outputx"; |
Geekshow | 6:4d30bc5a8076 | 193 | topic[6] = i+48; |
Geekshow | 6:4d30bc5a8076 | 194 | pc.printf("Output: %s is %s\r\n", topic, ONOFF[output_state]); |
Geekshow | 10:3ad12f8d8b46 | 195 | connected = publish_value(client, topic, ONOFF[output_state], false); |
Geekshow | 10:3ad12f8d8b46 | 196 | } |
Geekshow | 10:3ad12f8d8b46 | 197 | } |
Geekshow | 10:3ad12f8d8b46 | 198 | |
Geekshow | 10:3ad12f8d8b46 | 199 | void publish_inputs(MClient &client) { |
Geekshow | 10:3ad12f8d8b46 | 200 | for(int i=0; i<NUM_INPUTS; i++) { |
Geekshow | 10:3ad12f8d8b46 | 201 | char topic_str[8]; // long enough string for inputx |
Geekshow | 10:3ad12f8d8b46 | 202 | sprintf(topic_str, "input%d", i); |
Geekshow | 10:3ad12f8d8b46 | 203 | connected = publish_value(client,topic_str,OPENCLOSED[input_state[i]], false); |
Geekshow | 6:4d30bc5a8076 | 204 | } |
Geekshow | 6:4d30bc5a8076 | 205 | } |
Geekshow | 6:4d30bc5a8076 | 206 | |
Geekshow | 6:4d30bc5a8076 | 207 | |
Geekshow | 6:4d30bc5a8076 | 208 | void publish_info(MClient &client) { |
Geekshow | 6:4d30bc5a8076 | 209 | // uptime |
Geekshow | 6:4d30bc5a8076 | 210 | pc.printf("Uptime %d\r\n", uptime_sec); |
Geekshow | 6:4d30bc5a8076 | 211 | char uptime_sec_str[12]; // long enough string for a long int |
Geekshow | 6:4d30bc5a8076 | 212 | sprintf(uptime_sec_str, "%d", uptime_sec); |
Geekshow | 10:3ad12f8d8b46 | 213 | connected = publish_value(client,"uptime",uptime_sec_str, false); |
Geekshow | 10:3ad12f8d8b46 | 214 | // alive |
Geekshow | 10:3ad12f8d8b46 | 215 | publish_value(client, "alive","ON", false); |
Geekshow | 6:4d30bc5a8076 | 216 | } |
Geekshow | 6:4d30bc5a8076 | 217 | |
Geekshow | 6:4d30bc5a8076 | 218 | |
Geekshow | 8:6d7be3bed961 | 219 | void read_inputs(MClient &client) { |
Geekshow | 6:4d30bc5a8076 | 220 | for(int i=0; i<NUM_INPUTS; i++) { |
Geekshow | 6:4d30bc5a8076 | 221 | bool old_state = input_state[i]; // save old state |
Geekshow | 6:4d30bc5a8076 | 222 | input_state[i] = inputs[i]; // read new value |
Geekshow | 6:4d30bc5a8076 | 223 | // pc.printf("Input %d is %d\r\n", i, input_state[i]); |
Geekshow | 6:4d30bc5a8076 | 224 | if(input_state[i] != old_state) { |
Geekshow | 6:4d30bc5a8076 | 225 | // input has changed state |
Geekshow | 6:4d30bc5a8076 | 226 | pc.printf("Input %d changed to %s\r\n", i, OPENCLOSED[input_state[i]]); |
Geekshow | 6:4d30bc5a8076 | 227 | char topic_str[8]; // long enough string for inputx |
Geekshow | 6:4d30bc5a8076 | 228 | sprintf(topic_str, "input%d", i); |
Geekshow | 10:3ad12f8d8b46 | 229 | connected = publish_value(client,topic_str,OPENCLOSED[input_state[i]], false); |
Geekshow | 6:4d30bc5a8076 | 230 | } |
Geekshow | 6:4d30bc5a8076 | 231 | } |
Geekshow | 6:4d30bc5a8076 | 232 | } |
Geekshow | 6:4d30bc5a8076 | 233 | |
Geekshow | 5:b2ae1ed8a30e | 234 | |
Geekshow | 11:2a397ea7acc8 | 235 | void read_dht(MClient &client) { |
Geekshow | 9:a8098e772b48 | 236 | int error = dht0.readData(); |
Geekshow | 9:a8098e772b48 | 237 | if (0 == error) { |
Geekshow | 9:a8098e772b48 | 238 | temp[0] = dht0.ReadTemperature(CELCIUS); |
Geekshow | 9:a8098e772b48 | 239 | humidity[0] = dht0.ReadHumidity(); |
Geekshow | 11:2a397ea7acc8 | 240 | pc.printf("Temperature: %3.1f, Humidity: %3.1f\n", temp[0], humidity[0]); |
Geekshow | 9:a8098e772b48 | 241 | } else { |
Geekshow | 9:a8098e772b48 | 242 | pc.printf("DHT read error: %d\n", error); |
Geekshow | 10:3ad12f8d8b46 | 243 | return; |
Geekshow | 9:a8098e772b48 | 244 | } |
Geekshow | 9:a8098e772b48 | 245 | // convert to string and publish |
Geekshow | 9:a8098e772b48 | 246 | char temp_str[6]; |
Geekshow | 9:a8098e772b48 | 247 | sprintf(temp_str, "%3.1f", temp[0]); |
Geekshow | 10:3ad12f8d8b46 | 248 | connected = publish_value(client,"temp0",temp_str, false); |
Geekshow | 9:a8098e772b48 | 249 | char humidity_str[6]; |
Geekshow | 9:a8098e772b48 | 250 | sprintf(humidity_str, "%3.1f", humidity[0]); |
Geekshow | 10:3ad12f8d8b46 | 251 | connected = publish_value(client,"humidity0",humidity_str, false); |
Geekshow | 11:2a397ea7acc8 | 252 | } |
Geekshow | 11:2a397ea7acc8 | 253 | |
Geekshow | 11:2a397ea7acc8 | 254 | |
Geekshow | 11:2a397ea7acc8 | 255 | void read_ds18b20(MClient &client, int num_ds18b20) { |
Geekshow | 11:2a397ea7acc8 | 256 | // Announce num of DS18B20 found |
Geekshow | 11:2a397ea7acc8 | 257 | char temp_str[6]; |
Geekshow | 11:2a397ea7acc8 | 258 | char topic_str[6]; |
Geekshow | 11:2a397ea7acc8 | 259 | sprintf(temp_str, "%d", num_ds18b20); |
Geekshow | 11:2a397ea7acc8 | 260 | connected = publish_value(client,"num_ds18b20",temp_str, false); |
Geekshow | 11:2a397ea7acc8 | 261 | //Start temperature conversion, wait until ready |
Geekshow | 11:2a397ea7acc8 | 262 | probe[0]->convertTemperature(true, DS1820::all_devices); |
Geekshow | 11:2a397ea7acc8 | 263 | for (int i = 0; i<num_ds18b20; i++) { |
Geekshow | 11:2a397ea7acc8 | 264 | float temp = probe[i]->temperature(); |
Geekshow | 11:2a397ea7acc8 | 265 | pc.printf("Device %d returns %3.3foC\r\n", i, temp); |
Geekshow | 11:2a397ea7acc8 | 266 | // convert to string and publish |
Geekshow | 11:2a397ea7acc8 | 267 | sprintf(temp_str, "%3.3f", temp); |
Geekshow | 11:2a397ea7acc8 | 268 | sprintf(topic_str, "probetemp%d", i); |
Geekshow | 11:2a397ea7acc8 | 269 | connected = publish_value(client,topic_str,temp_str, false); |
Geekshow | 11:2a397ea7acc8 | 270 | } |
Geekshow | 9:a8098e772b48 | 271 | } |
Geekshow | 8:6d7be3bed961 | 272 | |
Geekshow | 8:6d7be3bed961 | 273 | |
Geekshow | 5:b2ae1ed8a30e | 274 | int networking_init(MQTTSocket &sock, MClient &client, WIZnetInterface &wiz) { |
Geekshow | 4:ebaf1973d008 | 275 | int ret = 0; |
Geekshow | 4:ebaf1973d008 | 276 | pc.printf("\n\nNode: %s\r\n", NODE_NAME); |
Geekshow | 4:ebaf1973d008 | 277 | pc.printf("%s attempting ethernet connection...\r\n", NODE_NAME); |
Geekshow | 4:ebaf1973d008 | 278 | wiz.init(mac_addr); // resets the w5500 |
Geekshow | 4:ebaf1973d008 | 279 | if (wiz.connect() == (-1)) { |
Geekshow | 4:ebaf1973d008 | 280 | pc.printf("Error getting DHCP address!!\r\n"); |
Geekshow | 4:ebaf1973d008 | 281 | } |
Geekshow | 4:ebaf1973d008 | 282 | |
Geekshow | 4:ebaf1973d008 | 283 | pc.printf("IP: %s\r\n", wiz.getIPAddress()); |
Geekshow | 5:b2ae1ed8a30e | 284 | |
Geekshow | 4:ebaf1973d008 | 285 | ret = sock.connect((char*)mqtt_broker,mqtt_port); |
Geekshow | 4:ebaf1973d008 | 286 | if(ret != 0){ |
Geekshow | 4:ebaf1973d008 | 287 | pc.printf("failed to connect to TCP server\r\n"); |
Geekshow | 4:ebaf1973d008 | 288 | return 1; |
Geekshow | 4:ebaf1973d008 | 289 | } |
Geekshow | 4:ebaf1973d008 | 290 | pc.printf("sock.connect()=%d\r\n",ret); |
Geekshow | 5:b2ae1ed8a30e | 291 | |
Geekshow | 4:ebaf1973d008 | 292 | if(client.connect() != 0){ |
Geekshow | 4:ebaf1973d008 | 293 | pc.printf("MQTT connect failed\r\n"); |
Geekshow | 4:ebaf1973d008 | 294 | return -1; |
Geekshow | 4:ebaf1973d008 | 295 | } |
Geekshow | 4:ebaf1973d008 | 296 | pc.printf("client.connect()=%d\r\n",ret); |
Geekshow | 4:ebaf1973d008 | 297 | |
Geekshow | 4:ebaf1973d008 | 298 | ret = client.subscribe("cmnd/" NODE_NAME "/+", MQTT::QOS1, messageArrived); |
Geekshow | 4:ebaf1973d008 | 299 | pc.printf("client.subscribe()=%d\r\n", ret); |
Geekshow | 6:4d30bc5a8076 | 300 | // TODO add client ID when subscribing |
Geekshow | 4:ebaf1973d008 | 301 | |
Geekshow | 4:ebaf1973d008 | 302 | // Node online message |
Geekshow | 10:3ad12f8d8b46 | 303 | publish_value(client, "alive","ON", false); |
Geekshow | 10:3ad12f8d8b46 | 304 | publish_value(client, "IPAddress", wiz.getIPAddress(), true); |
Geekshow | 4:ebaf1973d008 | 305 | pc.printf("Initialization done.\r\n"); |
Geekshow | 4:ebaf1973d008 | 306 | |
Geekshow | 4:ebaf1973d008 | 307 | return 0; |
Geekshow | 5:b2ae1ed8a30e | 308 | } |
Geekshow | 5:b2ae1ed8a30e | 309 | |
Geekshow | 6:4d30bc5a8076 | 310 | void every_60sec() { |
Geekshow | 6:4d30bc5a8076 | 311 | // no waits or blocking routines here please! |
Geekshow | 11:2a397ea7acc8 | 312 | flag_read_dht = 1; |
Geekshow | 11:2a397ea7acc8 | 313 | flag_read_ds18b20 = 1; |
Geekshow | 6:4d30bc5a8076 | 314 | } |
Geekshow | 6:4d30bc5a8076 | 315 | |
Geekshow | 6:4d30bc5a8076 | 316 | void every_5sec() { |
Geekshow | 6:4d30bc5a8076 | 317 | // no waits or blocking routines here please! |
Geekshow | 6:4d30bc5a8076 | 318 | flag_publish = 1; |
Geekshow | 3:de9611d75590 | 319 | } |
Geekshow | 3:de9611d75590 | 320 | |
Geekshow | 5:b2ae1ed8a30e | 321 | void every_second() { |
Geekshow | 6:4d30bc5a8076 | 322 | // no waits or blocking routines here please! |
Geekshow | 5:b2ae1ed8a30e | 323 | uptime_sec++; |
Geekshow | 6:4d30bc5a8076 | 324 | if(connected == 0) { |
Geekshow | 6:4d30bc5a8076 | 325 | led = !led; |
Geekshow | 9:a8098e772b48 | 326 | } |
Geekshow | 9:a8098e772b48 | 327 | wd.Service(); // kick the dog before the timeout |
Geekshow | 9:a8098e772b48 | 328 | } |
Geekshow | 6:4d30bc5a8076 | 329 | |
Geekshow | 6:4d30bc5a8076 | 330 | void every_500ms() { |
Geekshow | 6:4d30bc5a8076 | 331 | // no waits or blocking routines here please! |
Geekshow | 6:4d30bc5a8076 | 332 | if(connected != 0) { |
Geekshow | 6:4d30bc5a8076 | 333 | led = !led; |
Geekshow | 6:4d30bc5a8076 | 334 | } |
Geekshow | 5:b2ae1ed8a30e | 335 | } |
Geekshow | 3:de9611d75590 | 336 | |
Geekshow | 3:de9611d75590 | 337 | int main() |
Geekshow | 3:de9611d75590 | 338 | { |
Geekshow | 10:3ad12f8d8b46 | 339 | wd.Configure(20.0); |
Geekshow | 9:a8098e772b48 | 340 | // WIZnetInterface wiz(PA_7, PA_6, PA_5, PA_4, NC); // SPI1 with no reset |
Geekshow | 11:2a397ea7acc8 | 341 | WIZnetInterface wiz(PB_15, PB_14, PB_13, PB_12, PC_6); // SPI2 with D35 reset |
Geekshow | 6:4d30bc5a8076 | 342 | MQTTSocket sock; |
Geekshow | 6:4d30bc5a8076 | 343 | MClient client(sock); |
Geekshow | 6:4d30bc5a8076 | 344 | |
Geekshow | 6:4d30bc5a8076 | 345 | tick_500ms.attach(&every_500ms, 0.5); |
Geekshow | 5:b2ae1ed8a30e | 346 | tick_1sec.attach(&every_second, 1.0); |
Geekshow | 11:2a397ea7acc8 | 347 | tick_5sec.attach(&every_5sec, 5.1); |
Geekshow | 11:2a397ea7acc8 | 348 | tick_60sec.attach(&every_60sec, 59); |
Geekshow | 6:4d30bc5a8076 | 349 | |
Geekshow | 6:4d30bc5a8076 | 350 | //pulse all outputs |
Geekshow | 6:4d30bc5a8076 | 351 | for(int i=0; i<NUM_OUTPUTS; i++) { |
Geekshow | 6:4d30bc5a8076 | 352 | outputs[i] = IO_OFF; |
Geekshow | 6:4d30bc5a8076 | 353 | wait(0.2); |
Geekshow | 6:4d30bc5a8076 | 354 | } |
Geekshow | 10:3ad12f8d8b46 | 355 | |
Geekshow | 5:b2ae1ed8a30e | 356 | pc.printf("\n\nNode: %s\r\n", NODE_NAME); |
Geekshow | 6:4d30bc5a8076 | 357 | |
Geekshow | 10:3ad12f8d8b46 | 358 | wd.Service(); // kick the dog before the timeout |
Geekshow | 5:b2ae1ed8a30e | 359 | connected = networking_init(sock, client, wiz); |
Geekshow | 11:2a397ea7acc8 | 360 | |
Geekshow | 11:2a397ea7acc8 | 361 | // Initialize DS18B20 probe array to DS1820 objects |
Geekshow | 11:2a397ea7acc8 | 362 | int num_ds18b20 = 0; |
Geekshow | 11:2a397ea7acc8 | 363 | while(DS1820::unassignedProbe(ONEWIRE_PIN)) { |
Geekshow | 11:2a397ea7acc8 | 364 | probe[num_ds18b20] = new DS1820(ONEWIRE_PIN); |
Geekshow | 11:2a397ea7acc8 | 365 | num_ds18b20++; |
Geekshow | 11:2a397ea7acc8 | 366 | if (num_ds18b20 == MAX_PROBES) |
Geekshow | 11:2a397ea7acc8 | 367 | break; |
Geekshow | 11:2a397ea7acc8 | 368 | } |
Geekshow | 11:2a397ea7acc8 | 369 | pc.printf("DS18B20: Found %d device(s)\r\n", num_ds18b20); |
Geekshow | 5:b2ae1ed8a30e | 370 | |
Geekshow | 3:de9611d75590 | 371 | while(1) { |
Geekshow | 6:4d30bc5a8076 | 372 | read_inputs(client); |
Geekshow | 5:b2ae1ed8a30e | 373 | |
Geekshow | 5:b2ae1ed8a30e | 374 | if(connected != 0) { |
Geekshow | 5:b2ae1ed8a30e | 375 | pc.printf("Restarting network....\r\n"); |
Geekshow | 6:4d30bc5a8076 | 376 | connected = networking_init(sock, client, wiz); |
Geekshow | 6:4d30bc5a8076 | 377 | } |
Geekshow | 6:4d30bc5a8076 | 378 | else { |
Geekshow | 6:4d30bc5a8076 | 379 | // we're connected, do stuff! |
Geekshow | 6:4d30bc5a8076 | 380 | if(flag_publish) { |
Geekshow | 6:4d30bc5a8076 | 381 | publish_outputs(client); |
Geekshow | 10:3ad12f8d8b46 | 382 | publish_inputs(client); |
Geekshow | 6:4d30bc5a8076 | 383 | publish_info(client); |
Geekshow | 6:4d30bc5a8076 | 384 | flag_publish = 0; |
Geekshow | 6:4d30bc5a8076 | 385 | } |
Geekshow | 11:2a397ea7acc8 | 386 | else if(flag_read_dht) { |
Geekshow | 11:2a397ea7acc8 | 387 | read_dht(client); |
Geekshow | 11:2a397ea7acc8 | 388 | flag_read_dht = 0; |
Geekshow | 11:2a397ea7acc8 | 389 | } |
Geekshow | 11:2a397ea7acc8 | 390 | else if(flag_read_ds18b20) { |
Geekshow | 11:2a397ea7acc8 | 391 | read_ds18b20(client, num_ds18b20); |
Geekshow | 11:2a397ea7acc8 | 392 | flag_read_ds18b20 = 0; |
Geekshow | 9:a8098e772b48 | 393 | } |
zhangyx | 0:1170747a672f | 394 | } |
Geekshow | 7:3c2222251deb | 395 | |
Geekshow | 10:3ad12f8d8b46 | 396 | client.yield(50); // pause a while, yawn...... |
zhangyx | 0:1170747a672f | 397 | } |
zhangyx | 0:1170747a672f | 398 | } |