robot arm demo team / Mbed 2 deprecated RobotArmDemo Featured

Dependencies:   AX-12A Dynamixel mbed iothub_client EthernetInterface NTPClient ConfigFile SDFileSystem iothub_amqp_transport mbed-rtos proton-c-mbed wolfSSL

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers IothubRobotArm.cpp Source File

IothubRobotArm.cpp

00001 // Copyright (c) Microsoft. All rights reserved.
00002 // Licensed under the MIT license. See LICENSE file in the project root for full license information.
00003 
00004 #include "mbed.h"
00005 #include "rtos.h"
00006 
00007 #include "EthernetInterface.h"
00008 #include "mbed/logging.h"
00009 #include "mbed/mbedtime.h"
00010 #include <NTPClient.h>
00011 
00012 #include "iothub_mod_client.h"
00013 #include "iothub_message.h"
00014 #include "threadapi.h"
00015 #include "crt_abstractions.h"
00016 #include "iothubtransportamqp.h"
00017 
00018 #include "MeasureBuf.h"
00019 #include "IothubRobotArm.h"
00020 #include "IothubSerial.h"
00021 
00022 #ifdef MBED_BUILD_TIMESTAMP
00023 #include "certs.h"
00024 #endif // MBED_BUILD_TIMESTAMP
00025 
00026 #include "RobotArmCfg.h"
00027 
00028 extern void ShowLedColor(int col);
00029 
00030 // method to initialize platform - Time of day
00031 int setupRealTime(void)
00032 {
00033     int result;
00034 
00035     (void)printf("setupRealTime begin\r\n");
00036     if (EthernetInterface::connect())
00037     {
00038         (void)printf("Error initializing EthernetInterface.\r\n");
00039         result = __LINE__;
00040     }
00041     else
00042     {
00043         (void)printf("setupRealTime NTP begin\r\n");
00044         NTPClient ntp;
00045         if (ntp.setTime("0.pool.ntp.org") != 0)
00046         {
00047             (void)printf("Failed setting time.\r\n");
00048             result = __LINE__;
00049         }
00050         else
00051         {
00052             (void)printf("set time correctly!\r\n");
00053             result = 0;
00054         }
00055         (void)printf("setupRealTime NTP end\r\n");
00056         EthernetInterface::disconnect();
00057     }
00058     (void)printf("setupRealTime end\r\n");
00059 
00060     return result;
00061 }
00062 
00063 // method to initialize platform - Ethernet
00064 int InitEthernet()
00065 {
00066     (void)printf("Initializing ethernet..\r\n");
00067 
00068     /* These are needed in order to initialize the time provider for Proton-C */
00069     mbedtime_init();
00070 
00071     if (EthernetInterface::init())
00072     {
00073         (void)printf("Error initializing EthernetInterface.\r\n");
00074         return -1;
00075     }
00076 
00077     if (setupRealTime() != 0)
00078     {
00079         (void)printf("Failed setting up real time clock\r\n");
00080         return -1;
00081     }
00082 
00083     if (EthernetInterface::connect())
00084     {
00085         (void)printf("Error connecting EthernetInterface.\r\n");
00086         return -1;
00087     }
00088     
00089     return 0;
00090 }
00091 
00092 // IoTHub SDK stuff
00093 DEFINE_ENUM_STRINGS(IOTHUB_CLIENT_CONFIRMATION_RESULT, IOTHUB_CLIENT_CONFIRMATION_RESULT_VALUES);
00094 
00095 typedef struct EVENT_INSTANCE_TAG
00096 {
00097     IOTHUB_MESSAGE_HANDLE messageHandle;
00098     int messageTrackingId;  // For tracking the messages within the user callback.
00099 } EVENT_INSTANCE;
00100 
00101 
00102 // message buffers to use
00103 #define MESSAGE_LEN         1024
00104 static char msgText[MESSAGE_LEN];
00105 
00106 // a larger MESSAGE_COUNT results in being able to send as data is available
00107 // but requires more heap space to hold buffers
00108 #define MESSAGE_COUNT       4
00109 EVENT_INSTANCE messages[MESSAGE_COUNT];
00110 
00111 
00112 // context for send & receive
00113 static int receiveContext;
00114 static int callbackCounter;
00115 static int msgNumber;
00116 
00117 static  IOTHUB_CLIENT_HANDLE iotHubClientHandle;
00118 
00119 // used to detect send confirmation timeout
00120 #define SEND_CONFIRM_TO  30000
00121 RtosTimer* confirmTimer;
00122 
00123 // object for IoTHub interface
00124 IothubRobotArm iotRobot;
00125 
00126 
00127 // pass received commands to device
00128 extern void ControlArmCommands(const char* cmd);
00129 
00130 // callback for incoming messages
00131 static IOTHUBMESSAGE_DISPOSITION_RESULT ReceiveMessageCallback(IOTHUB_MESSAGE_HANDLE message, void* userContextCallback)
00132 {
00133     int* counter = (int*)userContextCallback;
00134     const char* buffer;
00135     size_t size;
00136     char cmdbuf[20];
00137     
00138     if (IoTHubMessage_GetByteArray(message, (const unsigned char**)&buffer, &size) == IOTHUB_MESSAGE_OK)
00139     {
00140         int slen = size;
00141 
00142         if (size >= 20)
00143             slen = 19;
00144         strncpy(cmdbuf, buffer, slen);
00145         cmdbuf[slen] = 0;
00146         (void)printf(cmdbuf);
00147         (void)printf("\r\n");
00148         ControlArmCommands((const char*)cmdbuf);
00149     }
00150 
00151     (*counter)++;
00152     return IOTHUBMESSAGE_ACCEPTED;
00153 }
00154 
00155 // callback for completion of sent messages
00156 static void SendConfirmationCallback(IOTHUB_CLIENT_CONFIRMATION_RESULT result, void* userContextCallback)
00157 {
00158     EVENT_INSTANCE* eventInstance = (EVENT_INSTANCE*)userContextCallback;
00159     if (eventInstance == NULL)
00160     {
00161         printf("SendConfirmation with NULL context\r\n");
00162         return;
00163     }
00164 
00165     (void)printf("Confirmation received\r\n");
00166 
00167     confirmTimer->stop();
00168     callbackCounter++;
00169     IoTHubMessage_Destroy(eventInstance->messageHandle);
00170 }
00171 
00172 
00173 static void SendCallback(IOTHUB_CLIENT_HANDLE iotHubClientHandle, void* userContextCallback)
00174 {
00175     iotRobot.SendMessage(iotHubClientHandle, userContextCallback);
00176 }
00177 
00178 // communication timeout
00179 void CommunicationTO(void const * tid)
00180 {
00181     (void)printf("*** Iothub thread communication Timeout\r\n");
00182     ShowLedColor(2);
00183 }
00184 
00185 // entry point to start IoTHub connection
00186 bool StartIothubThread()
00187 {
00188     InitEthernet();
00189     
00190     confirmTimer = new RtosTimer(CommunicationTO, osTimerOnce, (void *)osThreadGetId());
00191   
00192     iotRobot.Init();
00193  
00194     return true;
00195 }
00196 
00197 // stop IoTHub connection
00198 void EndIothubThread()
00199 {
00200     iotRobot.Terminate();
00201 }
00202 
00203 // IoTHub connection for RobotArm
00204 // sends and receives messages between RobotArm and IoTHub
00205 IothubRobotArm::IothubRobotArm()
00206 {
00207     iotHubClientHandle = NULL;
00208 }
00209 
00210 bool IothubRobotArm::Init()
00211 {
00212     receiveContext = 0;
00213     callbackCounter = 0;
00214     msgNumber = 0;
00215     
00216     (void)printf("Starting the IoTHub RobotArm connection\r\n");
00217     
00218     if (connectionString[0] == '[')
00219     {
00220         // forgot to replace placeholder
00221         (void)printf("ERROR: connectionString is not set to a device connection!\r\n");
00222         return false;
00223     }
00224 
00225     if ((iotHubClientHandle = IoTHubClient_Mod_CreateFromConnectionString(connectionString, AMQP_Protocol)) == NULL)
00226     {
00227         (void)printf("ERROR: iotHubClientHandle is NULL!\r\n");
00228         return false;
00229     }
00230     else
00231     {
00232 #ifdef MBED_BUILD_TIMESTAMP
00233         // For mbed add the certificate information
00234         if (IoTHubClient_Mod_SetOption(iotHubClientHandle, "TrustedCerts", certificates) != IOTHUB_CLIENT_OK)
00235         {
00236             printf("failure to set option \"TrustedCerts\"\r\n");
00237             return false;
00238         }
00239 #endif // MBED_BUILD_TIMESTAMP
00240 
00241         /* Setting Message call back, so we can receive Commands. */
00242         if (IoTHubClient_Mod_SetMessageCallback(iotHubClientHandle, ReceiveMessageCallback, &receiveContext) != IOTHUB_CLIENT_OK)
00243         {
00244             (void)printf("ERROR: IoTHubClient_SetMessageCallback..........FAILED!\r\n");
00245             return false;
00246         }
00247         else
00248         {
00249             (void)printf("IoTHubClient_SetMessageCallback...successful.\r\n");
00250         }
00251 
00252         /* Setting Send call back, so we can send from worker thread. */
00253         if (IoTHubClient_Mod_SetSendCallback(iotHubClientHandle, SendCallback, &receiveContext) != IOTHUB_CLIENT_OK)
00254         {
00255             (void)printf("ERROR: IoTHubClient_SetSendCallback..........FAILED!\r\n");
00256             return false;
00257         }
00258         else
00259         {
00260             (void)printf("IoTHubClient_SetSendCallback...successful.\r\n");
00261         }
00262     }
00263     return true;
00264 }
00265 
00266 void IothubRobotArm::Terminate()
00267 {
00268     if (iotHubClientHandle != NULL)
00269     {
00270         IoTHubClient_Mod_Destroy(iotHubClientHandle);
00271         iotHubClientHandle = NULL;
00272     }
00273 }
00274 
00275 // Invoked from callback
00276 void IothubRobotArm::SendMessage(IOTHUB_CLIENT_HANDLE iotHubClient, void* userContextCallback)
00277 {
00278     // send until circular buf empty or no sending buffers avail
00279     // may drop message if confirmations are slow
00280     while (msgNumber - callbackCounter < MESSAGE_COUNT)
00281     {
00282         // get buffer from array
00283         int i = msgNumber % MESSAGE_COUNT;
00284     
00285         int msglen = 0;
00286 
00287         // get alert if any, otherwise get measure data
00288         msglen = _msgSerialize.AlertBufToString(msgText, MESSAGE_LEN);
00289         if (msglen == 0)
00290         {
00291             msglen = _msgSerialize.MeasureBufToString(msgText, MESSAGE_LEN);
00292         }
00293         
00294         if (msglen > 0)
00295         {
00296             if ((messages[i].messageHandle = IoTHubMessage_CreateFromByteArray((const unsigned char*)msgText, msglen)) == NULL)
00297             {
00298                 (void)printf("ERROR: iotHubMessageHandle is NULL!\r\n");
00299             }
00300             else
00301             {
00302                 messages[i].messageTrackingId = msgNumber;
00303 
00304                 confirmTimer->stop();
00305                 if (IoTHubClient_Mod_SendEventAsync(iotHubClient, messages[i].messageHandle, SendConfirmationCallback, &messages[i]) != IOTHUB_CLIENT_OK)
00306                 {
00307                     (void)printf("ERROR: IoTHubClient_SendEventAsync..........FAILED!\r\n");
00308                 }
00309                 else
00310                 {
00311                     confirmTimer->start(SEND_CONFIRM_TO);
00312                    (void)printf("Send async completed\r\n");
00313                 }
00314                 msgNumber++;
00315             }
00316         }
00317         else if (msglen == 0)
00318         {
00319            break;
00320         }
00321         else if (msglen < 0)
00322         {
00323             (void)printf("ERROR: Serialized message too big for buffer\r\n");
00324             break;
00325         }
00326     } // while
00327 
00328 }
00329