Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependencies: AX-12A Dynamixel mbed iothub_client EthernetInterface NTPClient ConfigFile SDFileSystem iothub_amqp_transport mbed-rtos proton-c-mbed wolfSSL
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
Generated on Tue Jul 12 2022 16:05:14 by
1.7.2