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-02-04
- Revision:
- 33:8b9dcbf6d8ec
- Parent:
- 27:4239713d9690
File content as of revision 33:8b9dcbf6d8ec:
// 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_mod_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 #include "RobotArmCfg.h" 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 */ 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 4 EVENT_INSTANCE messages[MESSAGE_COUNT]; // 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; // object for IoTHub interface IothubRobotArm iotRobot; // 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); } static void SendCallback(IOTHUB_CLIENT_HANDLE iotHubClientHandle, void* userContextCallback) { iotRobot.SendMessage(iotHubClientHandle, userContextCallback); } // communication timeout void CommunicationTO(void const * tid) { (void)printf("*** Iothub thread communication Timeout\r\n"); ShowLedColor(2); } // entry point to start IoTHub connection bool StartIothubThread() { InitEthernet(); confirmTimer = new RtosTimer(CommunicationTO, osTimerOnce, (void *)osThreadGetId()); iotRobot.Init(); return true; } // stop IoTHub connection void EndIothubThread() { iotRobot.Terminate(); } // IoTHub connection for RobotArm // sends and receives messages between RobotArm and IoTHub IothubRobotArm::IothubRobotArm() { iotHubClientHandle = NULL; } bool IothubRobotArm::Init() { receiveContext = 0; callbackCounter = 0; msgNumber = 0; (void)printf("Starting the IoTHub RobotArm connection\r\n"); if (connectionString[0] == '[') { // forgot to replace placeholder (void)printf("ERROR: connectionString is not set to a device connection!\r\n"); return false; } if ((iotHubClientHandle = IoTHubClient_Mod_CreateFromConnectionString(connectionString, AMQP_Protocol)) == NULL) { (void)printf("ERROR: iotHubClientHandle is NULL!\r\n"); return false; } else { #ifdef MBED_BUILD_TIMESTAMP // For mbed add the certificate information if (IoTHubClient_Mod_SetOption(iotHubClientHandle, "TrustedCerts", certificates) != IOTHUB_CLIENT_OK) { printf("failure to set option \"TrustedCerts\"\r\n"); return false; } #endif // MBED_BUILD_TIMESTAMP /* Setting Message call back, so we can receive Commands. */ if (IoTHubClient_Mod_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"); } /* Setting Send call back, so we can send from worker thread. */ if (IoTHubClient_Mod_SetSendCallback(iotHubClientHandle, SendCallback, &receiveContext) != IOTHUB_CLIENT_OK) { (void)printf("ERROR: IoTHubClient_SetSendCallback..........FAILED!\r\n"); return false; } else { (void)printf("IoTHubClient_SetSendCallback...successful.\r\n"); } } return true; } void IothubRobotArm::Terminate() { if (iotHubClientHandle != NULL) { IoTHubClient_Mod_Destroy(iotHubClientHandle); iotHubClientHandle = NULL; } } // Invoked from callback void IothubRobotArm::SendMessage(IOTHUB_CLIENT_HANDLE iotHubClient, void* userContextCallback) { // 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_Mod_SendEventAsync(iotHubClient, 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 }