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:
2015-12-31
Revision:
8:d98e2dec0f40
Parent:
7:6723f6887d00
Child:
10:9b21566a5ddb

File content as of revision 8:d98e2dec0f40:

// 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 "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=";


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 10
EVENT_INSTANCE messages[MESSAGE_COUNT];

// context for send & receive
static int receiveContext;
static int callbackCounter;
static int msgNumber;


static  IOTHUB_CLIENT_HANDLE iotHubClientHandle;


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 [%d] with Data: <%.*s> & Size=%d\r\n", *counter, (int)size, buffer, (int)size);
        int slen = size;
        if (size >= 20)
            slen = 19;
        strncpy(cmdbuf, buffer, slen);
        cmdbuf[slen] = 0;
        ControlArm((const char*)cmdbuf);
    }

    // Retrieve properties from the message
    MAP_HANDLE mapProperties = IoTHubMessage_Properties(message);
    if (mapProperties != NULL)
    {
        const char*const* keys;
        const char*const* values;
        size_t propertyCount = 0;
        if (Map_GetInternals(mapProperties, &keys, &values, &propertyCount) == MAP_OK)
        {
            if (propertyCount > 0)
            {
                printf("Message Properties:\r\n");
                for (size_t index = 0; index < propertyCount; index++)
                {
                    printf("\tKey: %s Value: %s\r\n", keys[index], values[index]);
                }
                printf("\r\n");
            }
        }
    }

    /* Some device specific action code goes here... */
    (*counter)++;
    return IOTHUBMESSAGE_ACCEPTED;
}

static void SendConfirmationCallback(IOTHUB_CLIENT_CONFIRMATION_RESULT result, void* userContextCallback)
{
    EVENT_INSTANCE* eventInstance = (EVENT_INSTANCE*)userContextCallback;
    (void)printf("Confirmation[%d] received for message tracking id = %d with result = %s\r\n", callbackCounter, eventInstance->messageTrackingId, ENUM_TO_STRING(IOTHUB_CLIENT_CONFIRMATION_RESULT, result));

    callbackCounter++;
    IoTHubMessage_Destroy(eventInstance->messageHandle);
    
    if (callbackCounter == msgNumber)
    {
        // call SendMeasurements again in case more to send
        SendIothubData();
    }
}


// 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;
    iotRobot.Init();
    
    while (1)
    {
        (void)printf("Iothub thread wait signal\r\n");
        osEvent ev = Thread::signal_wait(IS_SendStatus);
        //if ((ev.value.signals & IS_Close)  == IS_Close)
        if (IotThreadClose)
        {
            (void)printf("Iothub thread close signal\r\n");
            iotRobot.Terminate();
            break;
        }
        else
        {
            if ((ev.value.signals & IS_SendStatus) == IS_SendStatus)
            {
                iotRobot.SendMeasurements();
            }
            else
            {
                (void)printf("Iothub thread unknown signal\r\n");
            }
        }
    }
}


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;
                
                //MAP_HANDLE propMap = IoTHubMessage_Properties(messages[i].messageHandle);
                //sprintf_s(propText, sizeof(propText), "PropMsg_%d", msgNumber);
                //if (Map_AddOrUpdate(propMap, "PropName", propText) != MAP_OK)
                //{
                //    (void)printf("ERROR: Map_AddOrUpdate Failed!\r\n");
                //}

                if (IoTHubClient_SendEventAsync(iotHubClientHandle, messages[i].messageHandle, SendConfirmationCallback, &messages[i]) != IOTHUB_CLIENT_OK)
                {
                    (void)printf("ERROR: IoTHubClient_SendEventAsync..........FAILED!\r\n");
                }
                else
                {
                    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

}