Example node for Yodiwo's Plegma API

Dependencies:   EthernetInterface FXOS8700Q HTTPClient HTTPD MQTTS SDFileSystem YodiwoPlegma mbed-rpc mbed-rtos mbed wolfSSL

yodiwo_functions.c

Committer:
mitsarionas
Date:
2015-09-28
Revision:
8:66d34592c1ad
Parent:
5:1ef168357347

File content as of revision 8:66d34592c1ad:

#include <stdint.h>
#include <stdbool.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <errno.h>

#include "yodiwo_functions.h"
#include "jsmn.h"
#include "yodiwo_helpers.h"

#define MAX_TOPIC_LEN 100
#define MAX_PORTEVENT_HANDLERS 5

int SeqNo = 0;

int handle_nodeinforeq(char *json, size_t len);
int handle_thingsreq(char *json, size_t len);
int handle_portstatersp(char *json, size_t len);
int handle_activeportkeysmsg(char *json, size_t len);
int handle_porteventmsg(char *json, size_t len);

typedef int (*portevent_handler_func)(Yodiwo_Plegma_PortEvent_t *event);

typedef struct
{
    char *portKey;
    portevent_handler_func handler;
} portevent_handler;

portevent_handler portevent_handlers[MAX_PORTEVENT_HANDLERS] = { 0 };
    
message_translators translators[] = {
//    {"loginreq", (func_ToJson *)Yodiwo_Plegma_LoginReq_ToJson, (func_FromJson *)Yodiwo_Plegma_LoginReq_FromJson, handle_loginreq},
//    {"loginrsp", (func_ToJson *)Yodiwo_Plegma_LoginRsp_ToJson, (func_FromJson *)Yodiwo_Plegma_LoginRsp_FromJson},
    {"nodeinforeq", (func_ToJson *)Yodiwo_Plegma_NodeInfoReq_ToJson, (func_FromJson *)Yodiwo_Plegma_NodeInfoReq_FromJson, handle_nodeinforeq},
//    {"nodeinforsp", (func_ToJson *)Yodiwo_Plegma_NodeInfoRsp_ToJson, (func_FromJson *)Yodiwo_Plegma_NodeInfoRsp_FromJson, handle_nodeinforsp},
    {"thingsreq", (func_ToJson *)Yodiwo_Plegma_ThingsReq_ToJson, (func_FromJson *)Yodiwo_Plegma_ThingsReq_FromJson, handle_thingsreq},
//    {"thingsrsp", (func_ToJson *)Yodiwo_Plegma_ThingsRsp_ToJson, (func_FromJson *)Yodiwo_Plegma_ThingsRsp_FromJson, handle_thingsrsp},
    {"porteventmsg", (func_ToJson *)Yodiwo_Plegma_PortEventMsg_ToJson, (func_FromJson *)Yodiwo_Plegma_PortEventMsg_FromJson, handle_porteventmsg},
//    {"portstatereq", (func_ToJson *)Yodiwo_Plegma_PortStateReq_ToJson, (func_FromJson *)Yodiwo_Plegma_PortStateReq_FromJson},
    {"portstatersp", (func_ToJson *)Yodiwo_Plegma_PortStateRsp_ToJson, (func_FromJson *)Yodiwo_Plegma_PortStateRsp_FromJson, handle_portstatersp},
    {"activeportkeysmsg", (func_ToJson *)Yodiwo_Plegma_ActivePortKeysMsg_ToJson, (func_FromJson *)Yodiwo_Plegma_ActivePortKeysMsg_FromJson, handle_activeportkeysmsg},
};

char node_name[50] = "";
static Array_Yodiwo_Plegma_Thing_t *array_things = NULL;
msg_sender send_func = NULL;

int translators_num = sizeof(translators) / sizeof(translators[0]);


void init_yodiwo(char *nodeName, Array_Yodiwo_Plegma_Thing_t *things, msg_sender sender)
{
    strcpy(node_name, nodeName);
    array_things = things;
    send_func = sender;
}

void get_topic_token(char *dst, char *src, int max_len, int token_idx)
{
    char buf[MAX_TOPIC_LEN];
    char *cur = buf;
    int i;
    buf[0] = '\0';
    strncat(buf, src, max_len);
    for(i = 0; i < token_idx + 1; i++) {
        cur = strtok((i==0) ? buf : NULL, "/");
//        printf("a token: %s\n", cur);
        if (cur == NULL) {
            *dst = '\0';
            return;
        }
    }
    strcpy(dst, cur);
}

int yodiwo_handle_message(char *message, int message_len, char *topic, int topic_len)
{
    int i;
    Yodiwo_Plegma_Mqtt_MqttAPIMessage_t api_msg;
    char token[40];
    
    i = Yodiwo_Plegma_Mqtt_MqttAPIMessage_FromJson(message, message_len, &api_msg);
    if (i < 0) {
        printf("Error deserializing MqttApiMessage\n");
        return -1;
    }
    
    get_topic_token(token, topic, topic_len, 4);
    
    printf("found token: %s\n", token);
    for (i = 0; i < translators_num; i++) {
        printf("checking for %s\n", translators[i].name);
        if (!strcmp(token, translators[i].name)) {
            printf("matched message type: %s\n", token);
            translators[i].msg_handler(api_msg.Payload, strlen(api_msg.Payload));
            break;
        }
    }
    // free api_msg internal
    return 0;
}

int publish_helper(char *msg, size_t len, char *subtopic, int responseToSeqNo)
{    
    int r;
    int final_len;
    Yodiwo_Plegma_Mqtt_MqttAPIMessage_t mqtt_api_msg;
    
    char *final_msg = (char *)malloc(len + 500); // TODO: more accurate / proper?
    if (final_msg == NULL) {
        printf("nomem\n");
        return -ENOMEM;
    }
    
    mqtt_api_msg.ResponseToSeqNo = responseToSeqNo;
    mqtt_api_msg.Payload = msg;
    final_len = Yodiwo_Plegma_Mqtt_MqttAPIMessage_ToJson(final_msg, len + 500,  &mqtt_api_msg);
    
    r = send_func(final_msg, final_len, subtopic);
    
    free(final_msg);
    return r;
}

int handle_nodeinforeq(char *json, size_t len)
{
    int r;
    Yodiwo_Plegma_NodeInfoReq_t msg;
    Yodiwo_Plegma_NodeInfoRsp_t rsp;
    r = Yodiwo_Plegma_NodeInfoReq_FromJson(json, len, &msg);
    printf("fromjson: %d\n", r);
    if (r)
        return r;
    char *json_rsp = (char *)malloc(100); //TODO proper size
    if (json_rsp == NULL) {
        return -ENOMEM;   
    }
    rsp.SeqNo = msg.SeqNo;
    rsp.Name = node_name;
    rsp.Type = Yodiwo_eNodeType_TestEndpoint;
    rsp.ThingTypes.num = 0;
    rsp.Capabilities = Yodiwo_eNodeCapa_None;  
    r = Yodiwo_Plegma_NodeInfoRsp_ToJson(json_rsp, 100, &rsp);
    printf("tojson: %d\n", r);    
    if (r < 0)
        return r;
    r =  publish_helper(json_rsp, r, "nodeinforsp", msg.SeqNo);
    
    free(json_rsp);
    return r;
}

int handle_thingsreq(char *json, size_t len)
{
    int r;
    Yodiwo_Plegma_ThingsReq_t msg;
    Yodiwo_Plegma_ThingsRsp_t rsp;
    char *sendbuf = NULL;
    r = Yodiwo_Plegma_ThingsReq_FromJson(json, len, &msg);
    printf("thingsreq json: %s\n", json);
    printf("fromjson: %d\n", r);
    if (r)
        goto exit;
    printf("%p\n", &msg);
    printf("%p\n", &msg.SeqNo);
    printf("%p\n", &msg.Operation);
    printf("%p\n", &msg.ThingKey);
    printf("%p\n", &msg.Data);
    
    rsp.SeqNo = msg.SeqNo;
    rsp.Operation = msg.Operation;
    printf("thingsreq operation: %d\n", msg.Operation);
    if (msg.Operation == Yodiwo_eThingsOperation_Get) {
        rsp.Data = *array_things;
        rsp.Status = 1;
    } else {
        rsp.Data.num = 0;
        rsp.Data.elems = NULL;
        rsp.Status = 0;
    }
    
    sendbuf = (char *)malloc(2500 * sizeof(char));
    if (sendbuf == NULL) {
        r = -ENOMEM;
        goto exit;
    }
    r = Yodiwo_Plegma_ThingsRsp_ToJson(sendbuf, 2500, &rsp);
    printf("thingsrsp json: %s\n", sendbuf);
    printf("tojson: %d\n", r);    
    if (r < 0)
        goto exit;
    r = publish_helper(sendbuf, r, "thingsrsp", msg.SeqNo);
exit:
    free(sendbuf);
    //free thingsreq internals
    return r;
}

int portevents(Array_Yodiwo_Plegma_PortEvent_t *events)
{
    Yodiwo_Plegma_PortEventMsg_t msg;
    char *msgbuf;
    int r;
    msg.SeqNo = SeqNo++;
    msg.PortEvents = *events;
    
    msgbuf = (char *)malloc(200); //proper
    if (msgbuf == NULL) {
        printf("can't remember\n");
        return -ENOMEM;
    }
    r = Yodiwo_Plegma_PortEventMsg_ToJson(msgbuf, 200, &msg);
    if (r < 0) {
        printf("i'm afraid json couldn't make it\n");
        free(msgbuf);
        return r;
    }
    r =  publish_helper(msgbuf, r, "porteventmsg", 0);
    
    free(msgbuf);
    return r;
}

int register_portevent_handler(char *portKey, portevent_handler_func handler)
{
    int i;
    for (i = 0; i < MAX_PORTEVENT_HANDLERS; i++) {
        if (portevent_handlers[i].portKey == NULL) {
            portevent_handlers[i].portKey = portKey;
            portevent_handlers[i].handler = handler;
            return 0;
        }
    }
    return -1;
}


int handle_portevent(Yodiwo_Plegma_PortEvent_t *event)
{
    int i, r;
    for (i = 0; i < MAX_PORTEVENT_HANDLERS; i++) {
        printf("checking handler for %s, event from %s\n", portevent_handlers[i].portKey, event->PortKey);
        if (portevent_handlers[i].portKey != NULL && !strcmp(portevent_handlers[i].portKey, event->PortKey)) {
            r = portevent_handlers[i].handler(event);
            if (r < 0)
                return r;
        }
    }
    return 0;
}

int handle_portstatersp(char *json, size_t len)
{
    return 0;
}

int handle_activeportkeysmsg(char *json, size_t len)
{
    return 0;
}

int handle_porteventmsg(char *json, size_t len)
{
    int i, r;
    Yodiwo_Plegma_PortEventMsg_t msg;
    r = Yodiwo_Plegma_PortEventMsg_FromJson(json, len, &msg);
    printf("fromjson: %d\n", r);
    if (r)
        return r;
    for (i = 0; i < msg.PortEvents.num; i++) {
        r = handle_portevent(&msg.PortEvents.elems[i]);
        if (r < 0)
            goto exit;
    }

exit:
    //TODO: free msg internals
    return r;
}