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:
Tue Apr 25 22:00:32 2017 +0000
Revision:
3:a40321269c7f
Parent:
2:abc89d2aede3
Child:
4:2b412949efb9
Changed LED topic so it could be actuated

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