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-06
- Revision:
- 11:3a2e6eb9fbb8
- Parent:
- 10:9b21566a5ddb
- Child:
- 13:ffeff9b5e513
File content as of revision 11:3a2e6eb9fbb8:
// 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 "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); 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; } 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; } 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]; //static char propText[MESSAGE_LEN]; #define MESSAGE_COUNT 1 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; extern void ControlArm(const char* cmd); 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) { (void)printf("Received Message handle %x with Data: <%.*s> & Size=%d\r\n", message, (int)size, buffer, (int)size); int slen = size; if (size >= 20) slen = 19; strncpy(cmdbuf, buffer, slen); cmdbuf[slen] = 0; ControlArm((const char*)cmdbuf); } (*counter)++; return IOTHUBMESSAGE_ACCEPTED; } 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[%d] received for tracking id = %d with result = %d\r\n", eventInstance->messageHandle, eventInstance->messageTrackingId, result); confirmTimer->stop(); callbackCounter++; IoTHubMessage_Destroy(eventInstance->messageHandle); if (callbackCounter == msgNumber) { // call SendMeasurements again in case more to send SendIothubData(); } } // communication timeout void CommunicationTO(void const * tid) { (void)printf("*** Iothub thread communication Timeout\r\n"); ShowLedColor(2); } // IoT Hub thread static Thread* IotThread = NULL; static bool IotThreadClose; // entry point for ITHub sending thread void IothubThread(void const *args) { (void)printf("Iothub thread start\r\n"); IotThreadClose = false; IothubRobotArm iotRobot; confirmTimer = new RtosTimer(CommunicationTO, osTimerOnce, (void *)osThreadGetId()); confirmTimer->start(SEND_CONFIRM_TO); InitEthernet(); confirmTimer->stop(); iotRobot.Init(); while (1) { osEvent ev = Thread::signal_wait(IS_SendStatus); if (IotThreadClose) { (void)printf("Iothub thread close signal\r\n"); iotRobot.Terminate(); break; } else { iotRobot.SendMeasurements(); } } } bool StartIothubThread() { IotThread = new Thread(IothubThread, NULL, osPriorityLow); return true; } bool SendIothubData() { IotThread->signal_set(IS_SendStatus); return true; } void EndIothubThread() { IotThreadClose = true; IotThread->signal_set(IS_SendStatus); } IothubRobotArm::IothubRobotArm() { iotHubClientHandle = NULL; } bool IothubRobotArm::Init() { receiveContext = 0; callbackCounter = 0; msgNumber = 0; // in case calling init twice without terminate Terminate(); (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::SendMeasurements(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; bool ismeasure = false; // get alert if any, otherwise get measure data msglen = msgSerialize.AlertBufToString(msgText, MESSAGE_LEN); if (msglen == 0) { ismeasure = true; 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); if (ismeasure) (void)printf("IoTHubClient_SendEventAsync sending data to IoT Hub. tracking id: %d, bytes: %d\r\n", msgNumber, msglen); else (void)printf("IoTHubClient_SendEventAsync sending alert to IoT Hub. tracking id: %d, bytes: %d\r\n", msgNumber, msglen); } msgNumber++; } } else if (msglen == 0) { break; } else if (msglen < 0) { (void)printf("ERROR: Serialized message too big for buffer\r\n"); break; } } // while }