ME910 changes
Dependencies: Cayenne-MQTT-mbed-M1 X_NUCLEO_IKS01A1 mbed mtsas-m1
Fork of 5_Dragonfly_Cayenne_Sprint_IKS01A1 by
main.cpp@3:a40321269c7f, 2017-04-25 (annotated)
- 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?
User | Revision | Line number | New 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 | } |