iot_water_monitor_v2

Dependencies:   easy-connect-v16 Watchdog FP MQTTPacket RecordType-v-16 watersenor_and_temp_code

Committer:
DuyLionTran
Date:
Tue Dec 26 14:35:19 2017 +0000
Revision:
20:100d321e334b
version 1.7: relays' states added

Who changed what in which revision?

UserRevisionLine numberNew contents of line
DuyLionTran 20:100d321e334b 1 #ifndef __SIMPLEMQTT_H__
DuyLionTran 20:100d321e334b 2 #define __SIMPLEMQTT_H__
DuyLionTran 20:100d321e334b 3
DuyLionTran 20:100d321e334b 4 /***************************************************************
DuyLionTran 20:100d321e334b 5 * Includes
DuyLionTran 20:100d321e334b 6 ***************************************************************/
DuyLionTran 20:100d321e334b 7 #include "easy-connect.h"
DuyLionTran 20:100d321e334b 8 #include "MQTTClient.h"
DuyLionTran 20:100d321e334b 9 #include "NDefLib/NDefNfcTag.h"
DuyLionTran 20:100d321e334b 10 #include "NDefLib/RecordType/RecordURI.h"
DuyLionTran 20:100d321e334b 11 #include "MQTTNetwork.h"
DuyLionTran 20:100d321e334b 12 #include "MQTTmbed.h"
DuyLionTran 20:100d321e334b 13
DuyLionTran 20:100d321e334b 14 /***************************************************************
DuyLionTran 20:100d321e334b 15 * Definitions
DuyLionTran 20:100d321e334b 16 ***************************************************************/
DuyLionTran 20:100d321e334b 17 // Configuration values needed to connect to IBM IoT Cloud
DuyLionTran 20:100d321e334b 18 #define ORG MQTT_ORG_ID // connect to ORG.internetofthings.ibmcloud.com/ For a registered connection, replace with your org
DuyLionTran 20:100d321e334b 19 #define ID MQTT_DEVICE_ID // For a registered connection is your device id
DuyLionTran 20:100d321e334b 20 #define AUTH_TOKEN MQTT_DEVICE_PASSWORD // For a registered connection is a device auth-token
DuyLionTran 20:100d321e334b 21 #define DEFAULT_TYPE_NAME MQTT_DEVICE_TYPE // For a registered connection is device type
DuyLionTran 20:100d321e334b 22 #define AUTH_METHOD MQTT_USERNAME
DuyLionTran 20:100d321e334b 23
DuyLionTran 20:100d321e334b 24 #define TYPE DEFAULT_TYPE_NAME // For a registered connection, replace with your type
DuyLionTran 20:100d321e334b 25 #define IBM_IOT_PORT MQTT_PORT
DuyLionTran 20:100d321e334b 26
DuyLionTran 20:100d321e334b 27 #define MQTT_MAX_PACKET_SIZE 400
DuyLionTran 20:100d321e334b 28 #define MQTT_MAX_PAYLOAD_SIZE 300
DuyLionTran 20:100d321e334b 29
DuyLionTran 20:100d321e334b 30 /***************************************************************
DuyLionTran 20:100d321e334b 31 * Variables
DuyLionTran 20:100d321e334b 32 ***************************************************************/
DuyLionTran 20:100d321e334b 33 char *projectName = "WaterMonitor";
DuyLionTran 20:100d321e334b 34 static char id[30] = ID; // mac without colons
DuyLionTran 20:100d321e334b 35 static char org[12] = ORG;
DuyLionTran 20:100d321e334b 36 static char type[30] = TYPE;
DuyLionTran 20:100d321e334b 37 static char auth_token[30] = AUTH_TOKEN; // Auth_token is only used in non-quickstart mode
DuyLionTran 20:100d321e334b 38 static int connack_rc = 0; // MQTT connack return code
DuyLionTran 20:100d321e334b 39 static bool netConnecting = false;
DuyLionTran 20:100d321e334b 40 static bool mqttConnecting = false;
DuyLionTran 20:100d321e334b 41 static bool netConnected = false;
DuyLionTran 20:100d321e334b 42 static bool connected = false;
DuyLionTran 20:100d321e334b 43 static int retryAttempt = 0;
DuyLionTran 20:100d321e334b 44 static int connectTimeout = 1000;
DuyLionTran 20:100d321e334b 45 uint16_t commandID = 0;
DuyLionTran 20:100d321e334b 46 static char subscription_url[MQTT_MAX_PAYLOAD_SIZE];
DuyLionTran 20:100d321e334b 47
DuyLionTran 20:100d321e334b 48 /***************************************************************
DuyLionTran 20:100d321e334b 49 * Unity function definitions
DuyLionTran 20:100d321e334b 50 ***************************************************************/
DuyLionTran 20:100d321e334b 51 /** brief Callback function when MQTT message arrives
DuyLionTran 20:100d321e334b 52 * param[in] msgMQTT
DuyLionTran 20:100d321e334b 53 * retral None
DuyLionTran 20:100d321e334b 54 */
DuyLionTran 20:100d321e334b 55 void MQTT_SubscribeCallback(MQTT::MessageData & msgMQTT);
DuyLionTran 20:100d321e334b 56
DuyLionTran 20:100d321e334b 57 /** brief Subscribe to a MQTT topic and set the MQTT callback function
DuyLionTran 20:100d321e334b 58 * param[in] subscribeTopic Topic to be subscribed
DuyLionTran 20:100d321e334b 59 * param[in] client MQTT client
DuyLionTran 20:100d321e334b 60 * retral returnCode from MQTTClient.h
DuyLionTran 20:100d321e334b 61 */
DuyLionTran 20:100d321e334b 62 int MQTT_Subscribe(char *subscribeTopic, MQTT::Client<MQTTNetwork, Countdown, MQTT_MAX_PACKET_SIZE>* client);
DuyLionTran 20:100d321e334b 63
DuyLionTran 20:100d321e334b 64 /** brief Connect to the internet then the MQTT network
DuyLionTran 20:100d321e334b 65 * param[in] client MQTT client
DuyLionTran 20:100d321e334b 66 * param[in] mqttNetwork MQTT network
DuyLionTran 20:100d321e334b 67 * param[in] network The internet network interface (ethernet, wifi...)
DuyLionTran 20:100d321e334b 68 * retral Internet connect result and returnCode from MQTTClient.h
DuyLionTran 20:100d321e334b 69 */
DuyLionTran 20:100d321e334b 70 int MQTT_Connect(MQTT::Client<MQTTNetwork, Countdown, MQTT_MAX_PACKET_SIZE>* client, MQTTNetwork *mqttNetwork, NetworkInterface* network);
DuyLionTran 20:100d321e334b 71
DuyLionTran 20:100d321e334b 72 /** brief Setup the number of attempt to re-connect to the internet
DuyLionTran 20:100d321e334b 73 * param[in] attemptNumber The number of attemp
DuyLionTran 20:100d321e334b 74 */
DuyLionTran 20:100d321e334b 75 int MQTT_GetConnTimeout(int attemptNumber);
DuyLionTran 20:100d321e334b 76 void MQTT_AttemptConnect(MQTT::Client<MQTTNetwork, Countdown, MQTT_MAX_PACKET_SIZE>* client, MQTTNetwork *mqttNetwork, NetworkInterface* network);
DuyLionTran 20:100d321e334b 77
DuyLionTran 20:100d321e334b 78 /** brief Connect to the internet then the MQTT network
DuyLionTran 20:100d321e334b 79 * param[in] client MQTT client
DuyLionTran 20:100d321e334b 80 * param[in] inputTime The time when the data is attempt to be sent
DuyLionTran 20:100d321e334b 81 * param[in] adcVal_0 The ADC value to be sent
DuyLionTran 20:100d321e334b 82 * retral returnCode from MQTTClient.h
DuyLionTran 20:100d321e334b 83 */
DuyLionTran 20:100d321e334b 84 int MQTT_PublishADC(MQTT::Client<MQTTNetwork, Countdown, MQTT_MAX_PACKET_SIZE>* client, time_t inputTime, float adcVal_0);
DuyLionTran 20:100d321e334b 85
DuyLionTran 20:100d321e334b 86 /** brief Connect to the internet then the MQTT network
DuyLionTran 20:100d321e334b 87 * param[in] client MQTT client
DuyLionTran 20:100d321e334b 88 * param[in] inputTime The time when the data is attempt to be sent
DuyLionTran 20:100d321e334b 89 * param[in] relay1 Relay 1 state
DuyLionTran 20:100d321e334b 90 * param[in] relay2 Relay 2 state
DuyLionTran 20:100d321e334b 91 * retral returnCode from MQTTClient.h
DuyLionTran 20:100d321e334b 92 */
DuyLionTran 20:100d321e334b 93 int MQTT_PublishRelayState(MQTT::Client<MQTTNetwork, Countdown, MQTT_MAX_PACKET_SIZE>* client, time_t inputTime, int relay1, int relay2);
DuyLionTran 20:100d321e334b 94
DuyLionTran 20:100d321e334b 95 /***************************************************************
DuyLionTran 20:100d321e334b 96 * Unity function declarations
DuyLionTran 20:100d321e334b 97 ***************************************************************/
DuyLionTran 20:100d321e334b 98 void MQTT_SubscribeCallback(MQTT::MessageData & msgMQTT) {
DuyLionTran 20:100d321e334b 99 char msg[MQTT_MAX_PAYLOAD_SIZE];
DuyLionTran 20:100d321e334b 100 msg[0]='\0';
DuyLionTran 20:100d321e334b 101 strncat (msg, (char*)msgMQTT.message.payload, msgMQTT.message.payloadlen);
DuyLionTran 20:100d321e334b 102 printf ("--->>> MQTT_SubscribeCallback msg: %s\n\r", msg);
DuyLionTran 20:100d321e334b 103 }
DuyLionTran 20:100d321e334b 104
DuyLionTran 20:100d321e334b 105 int MQTT_Subscribe(char *subscribeTopic, MQTT::Client<MQTTNetwork, Countdown, MQTT_MAX_PACKET_SIZE>* client) {
DuyLionTran 20:100d321e334b 106 return client->subscribe(subscribeTopic, MQTT::QOS1, MQTT_SubscribeCallback);
DuyLionTran 20:100d321e334b 107 }
DuyLionTran 20:100d321e334b 108
DuyLionTran 20:100d321e334b 109 int MQTT_Connect(MQTT::Client<MQTTNetwork, Countdown, MQTT_MAX_PACKET_SIZE>* client, MQTTNetwork *mqttNetwork, NetworkInterface* network) {
DuyLionTran 20:100d321e334b 110 const char* iot_ibm = MQTT_BROKER_URL;
DuyLionTran 20:100d321e334b 111 char hostname[strlen(org) + strlen(iot_ibm) + 1];
DuyLionTran 20:100d321e334b 112
DuyLionTran 20:100d321e334b 113 sprintf(hostname, "%s%s", org, iot_ibm);
DuyLionTran 20:100d321e334b 114 // Construct clientId - d:org:type:id
DuyLionTran 20:100d321e334b 115 char clientId[strlen(org) + strlen(type) + strlen(id) + 5];
DuyLionTran 20:100d321e334b 116 sprintf(clientId, "d:%s:%s:%s", org, type, id);
DuyLionTran 20:100d321e334b 117 sprintf(subscription_url, "%s.%s/#/device/%s/%s/", org, "internetofthings.ibmcloud.com", id, DEFAULT_TYPE_NAME);
DuyLionTran 20:100d321e334b 118
DuyLionTran 20:100d321e334b 119 // Network debug statements
DuyLionTran 20:100d321e334b 120 LOG("=====================================\n\r");
DuyLionTran 20:100d321e334b 121 LOG("Nucleo IP ADDRESS: %s\n\r", network->get_ip_address());
DuyLionTran 20:100d321e334b 122 LOG("Nucleo MAC ADDRESS: %s\n\r", network->get_mac_address());
DuyLionTran 20:100d321e334b 123 LOG("Server Hostname: %s port: %d\n\r", hostname, IBM_IOT_PORT);
DuyLionTran 20:100d321e334b 124 LOG("Client ID: %s\n\r", clientId);
DuyLionTran 20:100d321e334b 125 LOG("Topic: %s\n\r",MQTT_EVENT_TOPIC);
DuyLionTran 20:100d321e334b 126 LOG("Subscription URL: %s\n\r", subscription_url);
DuyLionTran 20:100d321e334b 127 LOG("=====================================\n\r");
DuyLionTran 20:100d321e334b 128 netConnecting = true;
DuyLionTran 20:100d321e334b 129 int rc = mqttNetwork->connect(hostname, IBM_IOT_PORT);
DuyLionTran 20:100d321e334b 130 if (rc != 0) {
DuyLionTran 20:100d321e334b 131 printf("rc from TCP connect is %d\r\n", rc);
DuyLionTran 20:100d321e334b 132 return rc;
DuyLionTran 20:100d321e334b 133 }
DuyLionTran 20:100d321e334b 134
DuyLionTran 20:100d321e334b 135 printf ("--->TCP Connected\n\r");
DuyLionTran 20:100d321e334b 136 netConnected = true;
DuyLionTran 20:100d321e334b 137 netConnecting = false;
DuyLionTran 20:100d321e334b 138
DuyLionTran 20:100d321e334b 139 // MQTT Connect
DuyLionTran 20:100d321e334b 140 mqttConnecting = true;
DuyLionTran 20:100d321e334b 141 MQTTPacket_connectData data = MQTTPacket_connectData_initializer;
DuyLionTran 20:100d321e334b 142 data.MQTTVersion = 4;
DuyLionTran 20:100d321e334b 143 data.struct_version = 0;
DuyLionTran 20:100d321e334b 144 data.clientID.cstring = clientId;
DuyLionTran 20:100d321e334b 145 data.keepAliveInterval = MQTT_KEEPALIVE; // in Sec
DuyLionTran 20:100d321e334b 146 data.username.cstring = AUTH_METHOD;
DuyLionTran 20:100d321e334b 147 data.password.cstring = auth_token;
DuyLionTran 20:100d321e334b 148 printf ("AutToken: %s\n\r", auth_token);
DuyLionTran 20:100d321e334b 149
DuyLionTran 20:100d321e334b 150 if ((rc = client->connect(data)) != 0) {
DuyLionTran 20:100d321e334b 151 printf("rc from MQTT connect is %d\r\n", rc);
DuyLionTran 20:100d321e334b 152 connack_rc = rc;
DuyLionTran 20:100d321e334b 153 return rc;
DuyLionTran 20:100d321e334b 154 }
DuyLionTran 20:100d321e334b 155 connected = true;
DuyLionTran 20:100d321e334b 156 printf ("--->MQTT Connected\n\r");
DuyLionTran 20:100d321e334b 157 if ((rc = MQTT_Subscribe(MQTT_COMMAND_TOPIC, client)) == 0) {
DuyLionTran 20:100d321e334b 158 LOG ("--->>>MQTT subscribed to: %s\n\r", MQTT_COMMAND_TOPIC);
DuyLionTran 20:100d321e334b 159 } else {
DuyLionTran 20:100d321e334b 160 LOG ("--->>>ERROR MQTT subscribe : %s\n\r", MQTT_COMMAND_TOPIC);
DuyLionTran 20:100d321e334b 161 }
DuyLionTran 20:100d321e334b 162 mqttConnecting = false;
DuyLionTran 20:100d321e334b 163 connack_rc = rc;
DuyLionTran 20:100d321e334b 164 return rc;
DuyLionTran 20:100d321e334b 165 }
DuyLionTran 20:100d321e334b 166
DuyLionTran 20:100d321e334b 167
DuyLionTran 20:100d321e334b 168 int MQTT_GetConnTimeout(int attemptNumber) { // First 10 attempts try within 3 seconds, next 10 attempts retry after every 1 minute
DuyLionTran 20:100d321e334b 169 // after 20 attempts, retry every 10 minutes
DuyLionTran 20:100d321e334b 170 return (attemptNumber < 10) ? 3 : (attemptNumber < 20) ? 60 : 600;
DuyLionTran 20:100d321e334b 171 }
DuyLionTran 20:100d321e334b 172
DuyLionTran 20:100d321e334b 173
DuyLionTran 20:100d321e334b 174 void MQTT_AttemptConnect(MQTT::Client<MQTTNetwork, Countdown, MQTT_MAX_PACKET_SIZE>* client, MQTTNetwork *mqttNetwork, NetworkInterface* network) {
DuyLionTran 20:100d321e334b 175 connected = false;
DuyLionTran 20:100d321e334b 176
DuyLionTran 20:100d321e334b 177 while (MQTT_Connect(client, mqttNetwork, network) != MQTT_CONNECTION_ACCEPTED) {
DuyLionTran 20:100d321e334b 178 if (connack_rc == MQTT_NOT_AUTHORIZED || connack_rc == MQTT_BAD_USERNAME_OR_PASSWORD) {
DuyLionTran 20:100d321e334b 179 printf ("File: %s, Line: %d Error: %d\n\r",__FILE__,__LINE__, connack_rc);
DuyLionTran 20:100d321e334b 180 return; // don't reattempt to connect if credentials are wrong
DuyLionTran 20:100d321e334b 181 }
DuyLionTran 20:100d321e334b 182 int timeout = MQTT_GetConnTimeout(++retryAttempt);
DuyLionTran 20:100d321e334b 183 WARN("Retry attempt number %d waiting %d\n", retryAttempt, timeout);
DuyLionTran 20:100d321e334b 184
DuyLionTran 20:100d321e334b 185 // if ipstack and client were on the heap we could deconstruct and goto a label where they are constructed
DuyLionTran 20:100d321e334b 186 // or maybe just add the proper members to do this disconnect and call MQTT_AttemptConnect(...)
DuyLionTran 20:100d321e334b 187 // this works - reset the system when the retry count gets to a threshold
DuyLionTran 20:100d321e334b 188 if (retryAttempt == 5)
DuyLionTran 20:100d321e334b 189 NVIC_SystemReset();
DuyLionTran 20:100d321e334b 190 else
DuyLionTran 20:100d321e334b 191 wait(timeout);
DuyLionTran 20:100d321e334b 192 }
DuyLionTran 20:100d321e334b 193 }
DuyLionTran 20:100d321e334b 194
DuyLionTran 20:100d321e334b 195 int MQTT_PublishADC(MQTT::Client<MQTTNetwork, Countdown, MQTT_MAX_PACKET_SIZE>* client, time_t inputTime, float adcVal_0) {
DuyLionTran 20:100d321e334b 196 MQTT::Message message;
DuyLionTran 20:100d321e334b 197 const char* pubTopic = MQTT_EVENT_TOPIC;
DuyLionTran 20:100d321e334b 198
DuyLionTran 20:100d321e334b 199 char buf[MQTT_MAX_PAYLOAD_SIZE];
DuyLionTran 20:100d321e334b 200 char timeBuf[50];
DuyLionTran 20:100d321e334b 201
DuyLionTran 20:100d321e334b 202 if (!client->isConnected()) {
DuyLionTran 20:100d321e334b 203 printf ("---> MQTT DISCONNECTED\n\r"); return MQTT::FAILURE;
DuyLionTran 20:100d321e334b 204 }
DuyLionTran 20:100d321e334b 205
DuyLionTran 20:100d321e334b 206 strftime(timeBuf, 50, "%Y/%m/%d %H:%M:%S", localtime(&inputTime));
DuyLionTran 20:100d321e334b 207 // sprintf(buf,
DuyLionTran 20:100d321e334b 208 // "{\"Project\":\"%s\",\"Time\":\"%s\",\"Type\":1,\"cmdID\":%d,\"ADC0\":%0.2f}",
DuyLionTran 20:100d321e334b 209 // projectName, timeBuf, commandID, adcVal_0);
DuyLionTran 20:100d321e334b 210 sprintf(buf, "{\"type\":1,\"deviceId\":\"PROEVN\",\"time\":\"%s\",\"cmdId\":%d,\"adc0\":%0.2f}",
DuyLionTran 20:100d321e334b 211 timeBuf, commandID, adcVal_0);
DuyLionTran 20:100d321e334b 212 message.qos = MQTT::QOS0;
DuyLionTran 20:100d321e334b 213 message.retained = false;
DuyLionTran 20:100d321e334b 214 message.dup = false;
DuyLionTran 20:100d321e334b 215 message.payload = (void*)buf;
DuyLionTran 20:100d321e334b 216 message.payloadlen = strlen(buf);
DuyLionTran 20:100d321e334b 217
DuyLionTran 20:100d321e334b 218 if((message.payloadlen + strlen(pubTopic)+1) >= MQTT_MAX_PACKET_SIZE)
DuyLionTran 20:100d321e334b 219 printf("message too long!\r\n");
DuyLionTran 20:100d321e334b 220
DuyLionTran 20:100d321e334b 221 LOG("Publishing %s\n\r", buf);
DuyLionTran 20:100d321e334b 222 return client->publish(pubTopic, message);
DuyLionTran 20:100d321e334b 223 }
DuyLionTran 20:100d321e334b 224
DuyLionTran 20:100d321e334b 225 int MQTT_PublishRelayState(MQTT::Client<MQTTNetwork, Countdown, MQTT_MAX_PACKET_SIZE>* client, time_t inputTime, int relay1, int relay2) {
DuyLionTran 20:100d321e334b 226 MQTT::Message message;
DuyLionTran 20:100d321e334b 227 const char* pubTopic = MQTT_EVENT_TOPIC;
DuyLionTran 20:100d321e334b 228
DuyLionTran 20:100d321e334b 229 char buf[MQTT_MAX_PAYLOAD_SIZE];
DuyLionTran 20:100d321e334b 230 char timeBuf[50];
DuyLionTran 20:100d321e334b 231
DuyLionTran 20:100d321e334b 232 if (!client->isConnected()) {
DuyLionTran 20:100d321e334b 233 printf ("---> MQTT DISCONNECTED\n\r");
DuyLionTran 20:100d321e334b 234 return MQTT::FAILURE;
DuyLionTran 20:100d321e334b 235 }
DuyLionTran 20:100d321e334b 236
DuyLionTran 20:100d321e334b 237 strftime(timeBuf, 50, "%Y/%m/%d %H:%M:%S", localtime(&inputTime));
DuyLionTran 20:100d321e334b 238 sprintf(buf, "{\"type\":1,\"deviceId\":\"PROEVN\",\"time\":\"%s\",\"cmdId\":%d,\"relay1\":%d,\"relay2\":%d}",
DuyLionTran 20:100d321e334b 239 timeBuf, commandID, relay1, relay2);
DuyLionTran 20:100d321e334b 240 message.qos = MQTT::QOS0;
DuyLionTran 20:100d321e334b 241 message.retained = false;
DuyLionTran 20:100d321e334b 242 message.dup = false;
DuyLionTran 20:100d321e334b 243 message.payload = (void*)buf;
DuyLionTran 20:100d321e334b 244 message.payloadlen = strlen(buf);
DuyLionTran 20:100d321e334b 245
DuyLionTran 20:100d321e334b 246 if((message.payloadlen + strlen(pubTopic)+1) >= MQTT_MAX_PACKET_SIZE)
DuyLionTran 20:100d321e334b 247 printf("message too long!\r\n");
DuyLionTran 20:100d321e334b 248
DuyLionTran 20:100d321e334b 249 LOG("Publishing %s\n\r", buf);
DuyLionTran 20:100d321e334b 250 return client->publish(pubTopic, message);
DuyLionTran 20:100d321e334b 251 }
DuyLionTran 20:100d321e334b 252 #endif /* __SIMPLEMQTT_H__ */