Nucleo board and sensor, sending data to myDevices

Dependencies:   Cayenne-MQTT-mbed-M1 X_NUCLEO_IKS01A1 mbed mtsas-m1

Fork of Dragonfly_Cayenne_Sprint_IKS01A1 by Peter Ferland

Committer:
pferland
Date:
Thu Sep 07 16:15:34 2017 +0000
Revision:
7:179960f084ba
Parent:
6:d70ed27847fe
ME910 working

Who changed what in which revision?

UserRevisionLine numberNew contents of line
pferland 0:5107fce16490 1 #include "mbed.h"
pferland 0:5107fce16490 2
pferland 0:5107fce16490 3 #include "mtsas.h"
pferland 0:5107fce16490 4
pferland 0:5107fce16490 5 #include "MQTTTimer.h"
pferland 0:5107fce16490 6 #include "CayenneMQTTClient.h"
pferland 0:5107fce16490 7 #include "MQTTNetwork.h"
pferland 0:5107fce16490 8
pferland 0:5107fce16490 9 #include "x_nucleo_iks01a1.h"
pferland 0:5107fce16490 10
pferland 0:5107fce16490 11 #include <string>
pferland 0:5107fce16490 12 #include <sstream>
pferland 0:5107fce16490 13
pferland 0:5107fce16490 14 using std::string;
pferland 0:5107fce16490 15 typedef CayenneMQTT::MQTTClient<MQTTNetwork<Cellular>, MQTTTimer> MQTTClient;
pferland 0:5107fce16490 16
pferland 0:5107fce16490 17 // Cayenne authentication info. This should be obtained from the Cayenne Dashboard.
ScottHoppeMultitech 5:a2d72fe4d7bd 18 string username = "3f842710-8e51-11e7-a5d9-9de9b49680ec";
ScottHoppeMultitech 5:a2d72fe4d7bd 19 string password = "46f0e2add1dbcd1d7cab6fde2a2b93c4423a377a";
ScottHoppeMultitech 5:a2d72fe4d7bd 20 string clientID = "b0358dd0-8f43-11e7-b153-197ebdab87be";
pferland 0:5107fce16490 21
pferland 0:5107fce16490 22 DigitalOut Led1Out(LED1);
pferland 0:5107fce16490 23
pferland 0:5107fce16490 24 // Debug serial port
pferland 0:5107fce16490 25 //static Serial debug(USBTX, USBRX);
pferland 0:5107fce16490 26 Serial pc(USBTX, USBRX);
pferland 0:5107fce16490 27 // MTSSerialFlowControl - serial link between processor and radio
pferland 0:5107fce16490 28 static MTSSerialFlowControl* io;
pferland 0:5107fce16490 29
pferland 0:5107fce16490 30 // Cellular - radio object for cellular operations (SMS, TCP, etc)
pferland 0:5107fce16490 31 Cellular* radio;
pferland 0:5107fce16490 32
pferland 0:5107fce16490 33 /* Instantiate the expansion board */
pferland 0:5107fce16490 34 static X_NUCLEO_IKS01A1 *mems_expansion_board = X_NUCLEO_IKS01A1::Instance(I2C_SDA, I2C_SCL);
pferland 0:5107fce16490 35
pferland 0:5107fce16490 36 /* Retrieve the composing elements of the expansion board */
pferland 0:5107fce16490 37 static GyroSensor *gyroscope = mems_expansion_board->GetGyroscope();
pferland 0:5107fce16490 38 static MotionSensor *accelerometer = mems_expansion_board->GetAccelerometer();
pferland 0:5107fce16490 39 static MagneticSensor *magnetometer = mems_expansion_board->magnetometer;
pferland 0:5107fce16490 40 static HumiditySensor *humidity_sensor = mems_expansion_board->ht_sensor;
pferland 0:5107fce16490 41 static PressureSensor *pressure_sensor = mems_expansion_board->pt_sensor;
pferland 0:5107fce16490 42 static TempSensor *temp_sensor1 = mems_expansion_board->ht_sensor;
pferland 0:5107fce16490 43 static TempSensor *temp_sensor2 = mems_expansion_board->pt_sensor;
pferland 0:5107fce16490 44
pferland 0:5107fce16490 45
pferland 0:5107fce16490 46 CayenneMQTT::MessageData lastMessage;
pferland 0:5107fce16490 47 bool messageReady;
pferland 0:5107fce16490 48
pferland 0:5107fce16490 49 /*
pferland 0:5107fce16490 50 * Initialize cellular radio.
pferland 0:5107fce16490 51 */
pferland 0:5107fce16490 52 bool init_mtsas()
pferland 0:5107fce16490 53 {
ScottHoppeMultitech 5:a2d72fe4d7bd 54
ScottHoppeMultitech 5:a2d72fe4d7bd 55 io = new MTSSerialFlowControl(D8,D2,D3,D6);//This is the only thing that I have changed!
pferland 0:5107fce16490 56 if (! io)
pferland 0:5107fce16490 57 return false;
ScottHoppeMultitech 5:a2d72fe4d7bd 58
pferland 0:5107fce16490 59 io->baud(115200);
pferland 0:5107fce16490 60 radio = CellularFactory::create(io);
pferland 0:5107fce16490 61 if (! radio)
pferland 0:5107fce16490 62 return false;
pferland 0:5107fce16490 63
pferland 6:d70ed27847fe 64 //radio->setApn("wireless.twilio.com");
pferland 0:5107fce16490 65 Transport::setTransport(radio);
pferland 0:5107fce16490 66 while (! radio->connect()) {
pferland 0:5107fce16490 67 logError("failed to bring up PPP link");
pferland 0:5107fce16490 68 wait(2);
pferland 0:5107fce16490 69 }
pferland 0:5107fce16490 70
pferland 0:5107fce16490 71 printf("Signal Strength: %d\n\r", radio->getSignalStrength());
pferland 0:5107fce16490 72 return true;
pferland 0:5107fce16490 73 }
pferland 0:5107fce16490 74
pferland 0:5107fce16490 75 /**
pferland 0:5107fce16490 76 * Print the message info.
pferland 0:5107fce16490 77 * @param[in] message The message received from the Cayenne server.
pferland 0:5107fce16490 78 */
pferland 0:5107fce16490 79 void outputMessage(CayenneMQTT::MessageData& message)
pferland 0:5107fce16490 80 {
pferland 0:5107fce16490 81 switch (message.topic) {
pferland 0:5107fce16490 82 case COMMAND_TOPIC:
ScottHoppeMultitech 5:a2d72fe4d7bd 83 pc.printf("topic=Command");
pferland 0:5107fce16490 84 break;
pferland 0:5107fce16490 85 case CONFIG_TOPIC:
pferland 0:5107fce16490 86 printf("topic=Config");
pferland 0:5107fce16490 87 break;
pferland 0:5107fce16490 88 default:
pferland 0:5107fce16490 89 printf("topic=%d", message.topic);
pferland 0:5107fce16490 90 break;
pferland 0:5107fce16490 91 }
pferland 0:5107fce16490 92 printf(" channel=%d", message.channel);
pferland 0:5107fce16490 93 if (message.clientID) {
pferland 0:5107fce16490 94 printf(" clientID=%s", message.clientID);
pferland 0:5107fce16490 95 }
pferland 0:5107fce16490 96 if (message.type) {
pferland 0:5107fce16490 97 printf(" type=%s", message.type);
pferland 0:5107fce16490 98 }
pferland 0:5107fce16490 99 for (size_t i = 0; i < message.valueCount; ++i) {
pferland 0:5107fce16490 100 if (message.getValue(i)) {
pferland 0:5107fce16490 101 printf(" value=%s", message.getValue(i));
pferland 0:5107fce16490 102 }
pferland 0:5107fce16490 103 if (message.getUnit(i)) {
pferland 0:5107fce16490 104 printf(" unit=%s", message.getUnit(i));
pferland 0:5107fce16490 105 }
pferland 0:5107fce16490 106 }
pferland 0:5107fce16490 107 if (message.id) {
pferland 0:5107fce16490 108 printf(" id=%s", message.id);
pferland 0:5107fce16490 109 }
pferland 2:abc89d2aede3 110 printf("\r\n");
pferland 0:5107fce16490 111 }
pferland 0:5107fce16490 112
pferland 0:5107fce16490 113 /**
pferland 0:5107fce16490 114 * Handle messages received from the Cayenne server.
pferland 0:5107fce16490 115 * @param[in] message The message received from the Cayenne server.
pferland 0:5107fce16490 116 */
pferland 0:5107fce16490 117 void messageArrived(CayenneMQTT::MessageData& message)
pferland 0:5107fce16490 118 {
pferland 0:5107fce16490 119 int error = 0;
pferland 0:5107fce16490 120 //note: if you change this example to use mbed-os you will need a mutex
pferland 0:5107fce16490 121 lastMessage = message;
pferland 0:5107fce16490 122 messageReady = true;
pferland 0:5107fce16490 123
pferland 0:5107fce16490 124 }
pferland 0:5107fce16490 125
pferland 0:5107fce16490 126 /**
pferland 0:5107fce16490 127 * Connect to the Cayenne server.
pferland 0:5107fce16490 128 * @return Returns CAYENNE_SUCCESS if the connection succeeds, or an error code otherwise.
pferland 0:5107fce16490 129 */
pferland 0:5107fce16490 130 int connectClient(MQTTClient &mqttClient, MQTTNetwork<Cellular> &network)
pferland 0:5107fce16490 131 {
pferland 0:5107fce16490 132 int error = 0;
pferland 0:5107fce16490 133 // Connect to the server.
pferland 2:abc89d2aede3 134 printf("Connecting to %s:%d\r\n", CAYENNE_DOMAIN, CAYENNE_PORT);
pferland 0:5107fce16490 135 while ((error = network.connect(CAYENNE_DOMAIN, CAYENNE_PORT)) != 0) {
pferland 2:abc89d2aede3 136 printf("TCP connect failed, error: %d\r\n", error);
pferland 0:5107fce16490 137 wait(2);
pferland 0:5107fce16490 138 }
pferland 0:5107fce16490 139
pferland 0:5107fce16490 140 if ((error = mqttClient.connect()) != MQTT::SUCCESS) {
pferland 2:abc89d2aede3 141 printf("MQTT connect failed, error: %d\r\n", error);
pferland 0:5107fce16490 142 return error;
pferland 0:5107fce16490 143 }
pferland 2:abc89d2aede3 144 printf("Connected\r\n");
pferland 0:5107fce16490 145
pferland 0:5107fce16490 146 // Subscribe to required topics.
pferland 0:5107fce16490 147 if ((error = mqttClient.subscribe(COMMAND_TOPIC, CAYENNE_ALL_CHANNELS)) != CAYENNE_SUCCESS) {
pferland 2:abc89d2aede3 148 printf("Subscription to Command topic failed, error: %d\r\n", error);
pferland 0:5107fce16490 149 }
pferland 0:5107fce16490 150 if ((error = mqttClient.subscribe(CONFIG_TOPIC, CAYENNE_ALL_CHANNELS)) != CAYENNE_SUCCESS) {
pferland 2:abc89d2aede3 151 printf("Subscription to Config topic failed, error:%d\r\n", error);
pferland 0:5107fce16490 152 }
pferland 0:5107fce16490 153
pferland 0:5107fce16490 154 // Send device info. Here we just send some example values for the system info. These should be changed to use actual system data, or removed if not needed.
pferland 0:5107fce16490 155 mqttClient.publishData(SYS_VERSION_TOPIC, CAYENNE_NO_CHANNEL, NULL, NULL, CAYENNE_VERSION);
pferland 0:5107fce16490 156 mqttClient.publishData(SYS_MODEL_TOPIC, CAYENNE_NO_CHANNEL, NULL, NULL, "mbedDevice");
pferland 0:5107fce16490 157 //mqttClient.publishData(SYS_CPU_MODEL_TOPIC, CAYENNE_NO_CHANNEL, NULL, NULL, "CPU Model");
pferland 0:5107fce16490 158 //mqttClient.publishData(SYS_CPU_SPEED_TOPIC, CAYENNE_NO_CHANNEL, NULL, NULL, "1000000000");
pferland 0:5107fce16490 159
pferland 0:5107fce16490 160 return CAYENNE_SUCCESS;
pferland 0:5107fce16490 161 }
pferland 0:5107fce16490 162
pferland 0:5107fce16490 163 /**
pferland 0:5107fce16490 164 * Main loop where MQTT code is run.
pferland 0:5107fce16490 165 */
pferland 0:5107fce16490 166 void loop(MQTTClient &mqttClient, MQTTNetwork<Cellular> &network)
pferland 0:5107fce16490 167 {
pferland 0:5107fce16490 168 // Start the countdown timer for publishing data every 5 seconds. Change the timeout parameter to publish at a different interval.
pferland 2:abc89d2aede3 169 MQTTTimer timer(1000);
pferland 2:abc89d2aede3 170 printf("Starting loop.\r\n");
pferland 0:5107fce16490 171 while (true) {
pferland 0:5107fce16490 172 // Yield to allow MQTT message processing.
pferland 2:abc89d2aede3 173 mqttClient.yield(10);
pferland 0:5107fce16490 174 if(messageReady){
pferland 0:5107fce16490 175 int error = 0;
pferland 0:5107fce16490 176 messageReady = false;
pferland 0:5107fce16490 177 // Add code to process the message. Here we just ouput the message data.
pferland 0:5107fce16490 178 outputMessage(lastMessage);
pferland 0:5107fce16490 179
pferland 0:5107fce16490 180 if (lastMessage.topic == COMMAND_TOPIC) {
pferland 0:5107fce16490 181 switch(lastMessage.channel) {
pferland 0:5107fce16490 182 case 0:
pferland 0:5107fce16490 183 // Set the onboard LED state
pferland 0:5107fce16490 184 Led1Out = atoi(lastMessage.getValue());
pferland 0:5107fce16490 185 // Publish the updated LED state
pferland 3:a40321269c7f 186 if ((error = mqttClient.publishData(DATA_TOPIC, lastMessage.channel, NULL, NULL, Led1Out.read())) != CAYENNE_SUCCESS) {
pferland 2:abc89d2aede3 187 printf("Publish LED state failure, error: %d\r\n", error);
pferland 0:5107fce16490 188 }
pferland 0:5107fce16490 189 break;
pferland 0:5107fce16490 190 }
pferland 0:5107fce16490 191
pferland 0:5107fce16490 192 // If this is a command message we publish a response. Here we are just sending a default 'OK' response.
pferland 0:5107fce16490 193 // An error response should be sent if there are issues processing the message.
pferland 0:5107fce16490 194 if ((error = mqttClient.publishResponse(lastMessage.id, NULL, lastMessage.clientID)) != CAYENNE_SUCCESS) {
pferland 2:abc89d2aede3 195 printf("Response failure, error: %d\r\n", error);
pferland 0:5107fce16490 196 }
pferland 0:5107fce16490 197 }
pferland 0:5107fce16490 198 }
pferland 0:5107fce16490 199
pferland 0:5107fce16490 200 // Check that we are still connected, if not, reconnect.
pferland 0:5107fce16490 201 if (!network.connected() || !mqttClient.connected()) {
pferland 0:5107fce16490 202 network.disconnect();
pferland 0:5107fce16490 203 mqttClient.disconnect();
pferland 2:abc89d2aede3 204 printf("Reconnecting\r\n");
pferland 0:5107fce16490 205 while (connectClient(mqttClient, network) != CAYENNE_SUCCESS) {
pferland 0:5107fce16490 206 wait(2);
pferland 2:abc89d2aede3 207 printf("Reconnect failed, retrying\r\n");
pferland 0:5107fce16490 208 }
pferland 0:5107fce16490 209 }
pferland 0:5107fce16490 210
pferland 0:5107fce16490 211 // Publish some example data every few seconds. This should be changed to send your actual data to Cayenne.
pferland 0:5107fce16490 212 if (timer.expired()) {
pferland 0:5107fce16490 213 int error = 0;
pferland 0:5107fce16490 214 float temp_data;
pferland 0:5107fce16490 215 temp_sensor1->get_temperature(&temp_data);
pferland 2:abc89d2aede3 216 printf("Temperature was: %f \r\n", temp_data);
pferland 0:5107fce16490 217 if ((error = mqttClient.publishData(DATA_TOPIC, 1, TYPE_TEMPERATURE, UNIT_CELSIUS, temp_data)) != CAYENNE_SUCCESS) {
pferland 2:abc89d2aede3 218 printf("Publish temperature failed, error: %d\r\n", error);
pferland 0:5107fce16490 219 }
pferland 0:5107fce16490 220 humidity_sensor->get_humidity(&temp_data);
pferland 2:abc89d2aede3 221 printf("Humidity was: %f \r\n", temp_data);
pferland 0:5107fce16490 222 if ((error = mqttClient.publishData(DATA_TOPIC, 2, TYPE_RELATIVE_HUMIDITY, UNIT_PERCENT, temp_data)) != CAYENNE_SUCCESS) {
pferland 2:abc89d2aede3 223 printf("Publish luminosity failed, error: %d\r\n", error);
pferland 0:5107fce16490 224 }
pferland 0:5107fce16490 225 pressure_sensor->get_pressure(&temp_data);
pferland 2:abc89d2aede3 226 printf("Pressure was: %f \r\n", temp_data);
pferland 0:5107fce16490 227 if ((error = mqttClient.publishData(DATA_TOPIC, 3, TYPE_BAROMETRIC_PRESSURE, UNIT_HECTOPASCAL, temp_data)) != CAYENNE_SUCCESS) {
pferland 2:abc89d2aede3 228 printf("Publish barometric pressure failed, error: %d\r\n", error);
pferland 0:5107fce16490 229 }
pferland 2:abc89d2aede3 230 printf("Led is: %s\r\n", Led1Out.read() ? "on" : "off");
pferland 3:a40321269c7f 231 if ((error = mqttClient.publishData(DATA_TOPIC, 0, "digital_actuator", UNIT_DIGITAL, Led1Out.read())) != CAYENNE_SUCCESS) {
pferland 2:abc89d2aede3 232 printf("Publish LED status failed, error: %d\r\n", error);
pferland 2:abc89d2aede3 233 }
pferland 0:5107fce16490 234 // Restart the countdown timer for publishing data every 5 seconds. Change the timeout parameter to publish at a different interval.
pferland 0:5107fce16490 235 timer.countdown_ms(5000);
pferland 0:5107fce16490 236 } else {
pferland 2:abc89d2aede3 237 // debug
pferland 2:abc89d2aede3 238 // printf("Timer: %d", timer.left_ms());
pferland 0:5107fce16490 239 }
pferland 0:5107fce16490 240 }
pferland 0:5107fce16490 241 }
pferland 0:5107fce16490 242
pferland 0:5107fce16490 243 int main()
pferland 0:5107fce16490 244 {
pferland 0:5107fce16490 245 pc.baud(115200);
pferland 0:5107fce16490 246 Led1Out = 0;
pferland 0:5107fce16490 247 mts::MTSLog::setLogLevel(mts::MTSLog::TRACE_LEVEL);
pferland 0:5107fce16490 248 // init radio, setup Cayenne connection
pferland 0:5107fce16490 249 if (!init_mtsas()) {
pferland 0:5107fce16490 250 while (true) {
pferland 0:5107fce16490 251 logError("failed to initialize cellular radio");
pferland 0:5107fce16490 252 wait(1);
pferland 0:5107fce16490 253 }
pferland 0:5107fce16490 254 }
pferland 0:5107fce16490 255 // Test with a ping
pferland 0:5107fce16490 256 if(radio->ping("www.google.com")){
pferland 2:abc89d2aede3 257 printf("Ping test succeeded!\r\n");
pferland 0:5107fce16490 258 } else {
pferland 2:abc89d2aede3 259 printf("Failed ping test!\r\n");
pferland 0:5107fce16490 260 }
pferland 0:5107fce16490 261 MQTTNetwork<Cellular> network(*radio);
pferland 0:5107fce16490 262 messageReady = false;
pferland 0:5107fce16490 263 MQTTClient mqttClient(network, username.c_str(), password.c_str(), clientID.c_str());
pferland 0:5107fce16490 264
pferland 0:5107fce16490 265 // Set the default function that receives Cayenne messages.
pferland 0:5107fce16490 266 mqttClient.setDefaultMessageHandler(messageArrived);
pferland 0:5107fce16490 267
pferland 0:5107fce16490 268 // Connect to Cayenne.
pferland 0:5107fce16490 269 if (connectClient(mqttClient, network) == CAYENNE_SUCCESS) {
pferland 0:5107fce16490 270 // Run main loop.
pferland 0:5107fce16490 271 loop(mqttClient, network);
pferland 0:5107fce16490 272 }
pferland 0:5107fce16490 273 else {
pferland 2:abc89d2aede3 274 printf("Connection failed, exiting\r\n");
pferland 0:5107fce16490 275 }
pferland 0:5107fce16490 276
pferland 0:5107fce16490 277 if (mqttClient.connected())
pferland 0:5107fce16490 278 mqttClient.disconnect();
pferland 0:5107fce16490 279 if (network.connected())
pferland 0:5107fce16490 280 network.disconnect();
pferland 0:5107fce16490 281
pferland 0:5107fce16490 282 return 0;
pferland 0:5107fce16490 283 }