demo project
Dependencies: AX-12A Dynamixel mbed iothub_client EthernetInterface NTPClient ConfigFile SDFileSystem iothub_amqp_transport mbed-rtos proton-c-mbed wolfSSL
IothubRobotArm.cpp
- Committer:
- henryrawas
- Date:
- 2016-01-19
- Revision:
- 15:4bd10f531cdc
- Parent:
- 14:570c8071f577
- Child:
- 18:224289104fc0
File content as of revision 15:4bd10f531cdc:
// Copyright (c) Microsoft. All rights reserved. // Licensed under the MIT license. See LICENSE file in the project root for full license information. #include "mbed.h" #include "rtos.h" #include "EthernetInterface.h" #include "mbed/logging.h" #include "mbed/mbedtime.h" #include <NTPClient.h> #include "iothub_client.h" #include "iothub_message.h" #include "threadapi.h" #include "crt_abstractions.h" #include "iothubtransportamqp.h" #include "MeasureBuf.h" #include "IothubRobotArm.h" #include "IothubSerial.h" #ifdef MBED_BUILD_TIMESTAMP #include "certs.h" #endif // MBED_BUILD_TIMESTAMP // TODO: move to config file static const char* connectionString = "HostName=HenryrIot.azure-devices.net;DeviceId=RobotArm;SharedAccessKey=FUTqsobGrV0ldHbnmOKluN6W90FG1G5z/jnhz+Gr53k="; extern void ShowLedColor(int col); // method to initialize platform - Time of day int setupRealTime(void) { int result; (void)printf("setupRealTime begin\r\n"); if (EthernetInterface::connect()) { (void)printf("Error initializing EthernetInterface.\r\n"); result = __LINE__; } else { (void)printf("setupRealTime NTP begin\r\n"); NTPClient ntp; if (ntp.setTime("0.pool.ntp.org") != 0) { (void)printf("Failed setting time.\r\n"); result = __LINE__; } else { (void)printf("set time correctly!\r\n"); result = 0; } (void)printf("setupRealTime NTP end\r\n"); EthernetInterface::disconnect(); } (void)printf("setupRealTime end\r\n"); return result; } // method to initialize platform - Ethernet int InitEthernet() { (void)printf("Initializing ethernet..\r\n"); /* These are needed in order to initialize the time provider for Proton-C */ mbed_log_init(); mbedtime_init(); if (EthernetInterface::init()) { (void)printf("Error initializing EthernetInterface.\r\n"); return -1; } if (setupRealTime() != 0) { (void)printf("Failed setting up real time clock\r\n"); return -1; } if (EthernetInterface::connect()) { (void)printf("Error connecting EthernetInterface.\r\n"); return -1; } return 0; } // IoTHub SDK stuff DEFINE_ENUM_STRINGS(IOTHUB_CLIENT_CONFIRMATION_RESULT, IOTHUB_CLIENT_CONFIRMATION_RESULT_VALUES); typedef struct EVENT_INSTANCE_TAG { IOTHUB_MESSAGE_HANDLE messageHandle; int messageTrackingId; // For tracking the messages within the user callback. } EVENT_INSTANCE; // message buffers to use #define MESSAGE_LEN 1024 static char msgText[MESSAGE_LEN]; // a larger MESSAGE_COUNT results in being able to send as data is available // but requires more heap space to hold buffers #define MESSAGE_COUNT 2 EVENT_INSTANCE messages[MESSAGE_COUNT]; // sending thread timeout #define SEND_POLL_MS 500 // context for send & receive static int receiveContext; static int callbackCounter; static int msgNumber; static IOTHUB_CLIENT_HANDLE iotHubClientHandle; // used to detect send confirmation timeout #define SEND_CONFIRM_TO 30000 RtosTimer* confirmTimer; // pass received commands to device extern void ControlArmCommands(const char* cmd); // callback for incoming messages static IOTHUBMESSAGE_DISPOSITION_RESULT ReceiveMessageCallback(IOTHUB_MESSAGE_HANDLE message, void* userContextCallback) { int* counter = (int*)userContextCallback; const char* buffer; size_t size; char cmdbuf[20]; if (IoTHubMessage_GetByteArray(message, (const unsigned char**)&buffer, &size) == IOTHUB_MESSAGE_OK) { int slen = size; if (size >= 20) slen = 19; strncpy(cmdbuf, buffer, slen); cmdbuf[slen] = 0; (void)printf(cmdbuf); (void)printf("\r\n"); ControlArmCommands((const char*)cmdbuf); } (*counter)++; return IOTHUBMESSAGE_ACCEPTED; } // callback for completion of sent messages static void SendConfirmationCallback(IOTHUB_CLIENT_CONFIRMATION_RESULT result, void* userContextCallback) { EVENT_INSTANCE* eventInstance = (EVENT_INSTANCE*)userContextCallback; if (eventInstance == NULL) { printf("SendConfirmation with NULL context\r\n"); return; } (void)printf("Confirmation received\r\n"); confirmTimer->stop(); callbackCounter++; IoTHubMessage_Destroy(eventInstance->messageHandle); } // communication timeout void CommunicationTO(void const * tid) { (void)printf("*** Iothub thread communication Timeout\r\n"); ShowLedColor(2); } // IoT Hub thread static THREAD_HANDLE IotThread; static bool IotThreadClose; // entry point for ITHub sending thread int IothubThread(void *args) { (void)printf("Iothub thread start\r\n"); IotThreadClose = false; IothubRobotArm iotRobot; confirmTimer = new RtosTimer(CommunicationTO, osTimerOnce, (void *)osThreadGetId()); iotRobot.Init(); // wait for connection establishment for SSL ThreadAPI_Sleep(15000); while (1) { if (IotThreadClose) { (void)printf("Iothub thread close\r\n"); iotRobot.Terminate(); break; } else { iotRobot.SendMessage(); } ThreadAPI_Sleep(SEND_POLL_MS); } return 0; } bool StartIothubThread() { InitEthernet(); ThreadAPI_Create(&IotThread, IothubThread, NULL); //IotThread = new Thread(IothubThread, NULL, osPriorityLow); return true; } void EndIothubThread() { IotThreadClose = true; } IothubRobotArm::IothubRobotArm() { iotHubClientHandle = NULL; } bool IothubRobotArm::Init() { receiveContext = 0; callbackCounter = 0; msgNumber = 0; (void)printf("Starting the IoTHub RobotArm sample AMQP...\r\n"); if ((iotHubClientHandle = IoTHubClient_CreateFromConnectionString(connectionString, AMQP_Protocol)) == NULL) { (void)printf("ERROR: iotHubClientHandle is NULL!\r\n"); return false; } else { #ifdef MBED_BUILD_TIMESTAMP (void)printf("INFO: IoTHubClient_SetOption\r\n"); // For mbed add the certificate information if (IoTHubClient_SetOption(iotHubClientHandle, "TrustedCerts", certificates) != IOTHUB_CLIENT_OK) { printf("failure to set option \"TrustedCerts\"\r\n"); return false; } #endif // MBED_BUILD_TIMESTAMP (void)printf("INFO: IoTHubClient_SetMessageCallback\r\n"); /* Setting Message call back, so we can receive Commands. */ if (IoTHubClient_SetMessageCallback(iotHubClientHandle, ReceiveMessageCallback, &receiveContext) != IOTHUB_CLIENT_OK) { (void)printf("ERROR: IoTHubClient_SetMessageCallback..........FAILED!\r\n"); return false; } else { (void)printf("IoTHubClient_SetMessageCallback...successful.\r\n"); } } return true; } void IothubRobotArm::Terminate() { if (iotHubClientHandle != NULL) { IoTHubClient_Destroy(iotHubClientHandle); iotHubClientHandle = NULL; } } void IothubRobotArm::SendMessage(void) { // send until circular buf empty or no sending buffers avail // may drop message if confirmations are slow while (msgNumber - callbackCounter < MESSAGE_COUNT) { // get buffer from array int i = msgNumber % MESSAGE_COUNT; int msglen = 0; // get alert if any, otherwise get measure data msglen = msgSerialize.AlertBufToString(msgText, MESSAGE_LEN); if (msglen == 0) { msglen = msgSerialize.MeasureBufToString(msgText, MESSAGE_LEN); } if (msglen > 0) { if ((messages[i].messageHandle = IoTHubMessage_CreateFromByteArray((const unsigned char*)msgText, msglen)) == NULL) { (void)printf("ERROR: iotHubMessageHandle is NULL!\r\n"); } else { messages[i].messageTrackingId = msgNumber; confirmTimer->stop(); if (IoTHubClient_SendEventAsync(iotHubClientHandle, messages[i].messageHandle, SendConfirmationCallback, &messages[i]) != IOTHUB_CLIENT_OK) { (void)printf("ERROR: IoTHubClient_SendEventAsync..........FAILED!\r\n"); } else { confirmTimer->start(SEND_CONFIRM_TO); (void)printf("Send async completed\r\n"); } msgNumber++; } } else if (msglen == 0) { break; } else if (msglen < 0) { (void)printf("ERROR: Serialized message too big for buffer\r\n"); break; } } // while }