CoAP Device Server Client

Dependencies:   EthernetInterface mbed-rtos mbed nsdl_lib

Fork of COAPmbed by th.iotkit2.ch

Constrained Application Protocol (Coap) ist ein Software-Protokoll welches für Internet der Dinge Geräte zugeschnitten ist.

COAP ist auf den meisten Geräten, die UDP Unterstützen, lauffähig.

Ein COAP fähiges Gerät publiziert seine Sensoren und Aktoren in einem Resource Directory oder stellt selber ein solches zur Verfügung.

Mittels Resource Discovery können die vorhandenen Sensoren und Aktoren mit ihren Attributen abgefragt werden.

Zeile 29: Node Name aendern und folgende Adresse aufrufen: http://nsp.cloudapp.net:8083/, User/PW = demo

main.cpp

Committer:
terohoo
Date:
2013-10-09
Revision:
0:2edbfea18d23
Child:
1:e35d7f10999a

File content as of revision 0:2edbfea18d23:

/* Define DEBUG for USB serial communication */
#define DEBUG

#include "mbed.h"
#include "EthernetInterface.h"
#include "C12832_lcd.h"
#include "LM75B.h"
#include "MMA7660.h"
#include "Beep.h"
/* Sensinode includes */
#include "sn_nsdl.h"
#include "sn_coap_header.h"
#include "sn_coap_protocol.h"
#include "sn_nsdl_lib.h"

#include "resource_generation_help.h"

/* Define this to enable DHCP, otherwise manual address configuration is used */
#define DHCP

/* Manual IP configurations, if DHCP not defined */
#define IP      "10.45.0.206"
#define MASK    "255.255.255.0"
#define GW      "10.45.0.1"

/* Change this IP address to that of your NanoService Platform installation */
const char* NSP_ADDRESS = "10.45.3.42"; /* internal NSP*/
const int NSP_PORT = 5683;

uint8_t nsp_addr[4];

/* The number of seconds between NSP registration messages */
#define RD_UPDATE_PERIOD  60

/* Resource paths and registration parameters */
static uint8_t res_mgf[] = {"dev/mfg"};
static uint8_t res_mgf_val[] = {"Sensinode"};
static uint8_t res_mdl[] = {"dev/mdl"};
static uint8_t res_mdl_val[] = {"NSDL-C power node"};
static uint8_t res_temp[] = {"sen/temp"};
static uint8_t res_light[] = {"lt/0/dim"};
static uint8_t res_gps[] = {"gps/loc"};
static uint8_t res_gps_val[] = {"52.182382,0.178849"};
static uint8_t res_rel[] = {"lt/0/on"};

static uint8_t ep_type[] = {"PowerNode"};
static uint8_t lifetime_ptr[] = {"1200"};

/* stored data for observable resource */
uint8_t obs_number = 0;
uint8_t *obs_token_ptr = 0;
uint8_t obs_token_len = 0;
char temp_val[5];

/* App board related stuff */
Beep buzzer(p26);
//PwmOut led1(LED1);
PwmOut led2(LED2);
PwmOut led3(LED3);
//PwmOut led4(LED4);
#ifdef DEBUG
Serial pc(USBTX, USBRX); // tx, rx
#endif
C12832_LCD lcd;
LM75B tmp(p28,p27);
MMA7660 MMA(p28, p27);

EthernetInterface eth;
UDPSocket server;
Endpoint nsp;
Endpoint from;

/* For creating uniq name for board.. */
char mbed_uid[33];
char endpoint_name[15] = "MyMbedexam";

extern "C"
{
uint8_t tx_cb(sn_nsdl_capab_e protocol, uint8_t *data_ptr, uint16_t data_len, sn_nsdl_addr_s *address_ptr);
uint8_t rx_cb(sn_coap_hdr_s *coap_packet_ptr, sn_nsdl_addr_s *address_ptr);
void *own_alloc(uint16_t size);
void own_free(void* ptr_to_free);
static uint8_t temp_resource_cb(sn_coap_hdr_s *received_coap_ptr, sn_nsdl_addr_s *address, sn_proto_info_s * proto);
static uint8_t light_resource_cb(sn_coap_hdr_s *received_coap_ptr, sn_nsdl_addr_s *address, sn_proto_info_s * proto);
static uint8_t gps_resource_cb(sn_coap_hdr_s *received_coap_ptr, sn_nsdl_addr_s *address, sn_proto_info_s * proto);
static uint8_t relay_resource_cb(sn_coap_hdr_s *received_coap_ptr, sn_nsdl_addr_s *address, sn_proto_info_s * proto);
}

/* Thread for handling registration updates */
void registration_update_thread(void const *args)
{
    sn_nsdl_ep_parameters_s *endpoint_ptr = 0;
    while(true)
    {
        wait(RD_UPDATE_PERIOD);
        INIT_REGISTER_NSDL_ENDPOINT(endpoint_ptr, (uint8_t*)endpoint_name, ep_type, lifetime_ptr);
        if(sn_nsdl_register_endpoint(endpoint_ptr) != 0)
            pc.printf("NSP re-registering failed\r\n");
        else
            pc.printf("NSP re-registering OK\r\n");
        CLEAN_REGISTER_NSDL_ENDPOINT(endpoint_ptr);

    }
}

/* Thread for calling libNsdl exec function (cleanup, resendings etc..) */
/* Node updates temperature every 10 seconds. Notification sending is done here. */
void exec_call_thread(void const *args)
{
    int32_t time = 0;
    while (true)
    {
        wait(1);
        time++;
        sn_nsdl_exec(time);
        if((!(time % 10)) && obs_number != 0)
        {
            obs_number++;
            sprintf(temp_val,"%2.2f" ,tmp.read());
            if(sn_nsdl_send_observation_notification(obs_token_ptr, obs_token_len, (uint8_t*)temp_val, 5, &obs_number, 1, COAP_MSG_TYPE_NON_CONFIRMABLE, 0) == 0)
                pc.printf("Observation sending failed\r\n");
            else
                pc.printf("Observation\r\n");
        }
    }
}

int main()
{

    Thread registration_thread(registration_update_thread);
    Thread exec_thread(exec_call_thread);

    sn_nsdl_mem_s memory_cbs;
    sn_nsdl_resource_info_s *resource_ptr = 0;
    sn_nsdl_ep_parameters_s *endpoint_ptr = 0;
    sn_nsdl_addr_s received_packet_address;
    uint8_t received_address[4];

    memset(&received_packet_address, 0, sizeof(sn_nsdl_addr_s));
    received_packet_address.addr_ptr = received_address;

    lcd.cls();
    lcd.locate(0,0);
    lcd.printf("mbed NanoService demo");
#ifdef DEBUG
    pc.printf("mbed NanoService Example App 0.1\n\n\r");
#endif

    /* Initialize network */
#ifdef DHCP
#ifdef DEBUG
    pc.printf("DHCP in use\r\n");
#endif
    eth.init();
#else
    eth.init(IP, MASK, GW);
#endif
    if(eth.connect(30000) == 0)
        pc.printf("Connect OK\n\r");

    mbed_interface_uid(mbed_uid);
    mbed_uid[32] = '\0';
    memcpy(&endpoint_name[10], &mbed_uid[27], 5);

    lcd.locate(0,11);
    lcd.printf("IP:%s", eth.getIPAddress());

#ifdef DEBUG
    pc.printf("IP Address:%s \n\r", eth.getIPAddress());
#endif
    server.init();
    server.bind(NSP_PORT);

    nsp.set_address(NSP_ADDRESS,NSP_PORT);

#ifdef DEBUG
    pc.printf("name: %s\n\r", endpoint_name);
    pc.printf("NSP=%s - port %d\r\n\n",NSP_ADDRESS, NSP_PORT);
#endif

    lcd.locate(0,22);
    lcd.printf("EP name:%s", endpoint_name);

    memory_cbs.sn_nsdl_alloc = &own_alloc;
    memory_cbs.sn_nsdl_free = &own_free;

    /* Initialize libNsdl */
    if(sn_nsdl_init(&tx_cb, &rx_cb, &memory_cbs) == -1)
        pc.printf("libNsdl init failed\r\n");
    else
        pc.printf("libNsdl init done\r\n");

    /* Set nsp address for library */
    set_NSP_address(nsp_addr, 5683, SN_NSDL_ADDRESS_TYPE_IPV4);

#ifdef DEBUG
    pc.printf("Creating resources\r\n");
#endif
    /* Create resources */
    resource_ptr = (sn_nsdl_resource_info_s*)own_alloc(sizeof(sn_nsdl_resource_info_s));
    if(!resource_ptr)
        return 0;
    memset(resource_ptr, 0, sizeof(sn_nsdl_resource_info_s));

    resource_ptr->resource_parameters_ptr = (sn_nsdl_resource_parameters_s*)own_alloc(sizeof(sn_nsdl_resource_parameters_s));
    if(!resource_ptr->resource_parameters_ptr)
    {
        own_free(resource_ptr);
        return 0;
    }
    memset(resource_ptr->resource_parameters_ptr, 0, sizeof(sn_nsdl_resource_parameters_s));

    /* Static resurces */
    CREATE_STATIC_RESOURCE(resource_ptr, sizeof(res_mgf)-1, (uint8_t*) res_mgf, 0, 0,  (uint8_t*) res_mgf_val, sizeof(res_mgf_val)-1);
    CREATE_STATIC_RESOURCE(resource_ptr, sizeof(res_mdl)-1, (uint8_t*) res_mdl, 0, 0,  (uint8_t*) res_mdl_val, sizeof(res_mdl_val)-1);

    CREATE_DYNAMIC_RESOURCE(resource_ptr, sizeof(res_temp)-1, (uint8_t*) res_temp, 0, 0, 1, &temp_resource_cb, SN_GRS_GET_ALLOWED);
    CREATE_DYNAMIC_RESOURCE(resource_ptr, sizeof(res_light)-1, (uint8_t*) res_light, 0, 0, 0, &light_resource_cb, (SN_GRS_GET_ALLOWED | SN_GRS_PUT_ALLOWED));
    CREATE_DYNAMIC_RESOURCE(resource_ptr, sizeof(res_gps)-1, (uint8_t*) res_gps, 0, 0, 0, &gps_resource_cb, SN_GRS_GET_ALLOWED);
    CREATE_DYNAMIC_RESOURCE(resource_ptr, sizeof(res_rel)-1, (uint8_t*) res_rel, 0, 0, 0, &relay_resource_cb, (SN_GRS_GET_ALLOWED | SN_GRS_PUT_ALLOWED));


        /* Register with NSP */
    INIT_REGISTER_NSDL_ENDPOINT(endpoint_ptr, (uint8_t*)endpoint_name, ep_type, lifetime_ptr);

    if(sn_nsdl_register_endpoint(endpoint_ptr) != 0)
        pc.printf("NSP registering failed\r\n");
    else
        pc.printf("NSP registering OK\r\n");

    CLEAN_REGISTER_NSDL_ENDPOINT(endpoint_ptr);

    own_free(resource_ptr->resource_parameters_ptr);
    own_free(resource_ptr);

    char buffer[1024];
    while(1)
    {
        int n = server.receiveFrom(from, buffer, sizeof(buffer));
        if (n < 0)
        {
            pc.printf("Socket error\n\r");
        }
        else
        {   
            pc.printf("Received %d bytes\r\n", n);
            sn_nsdl_process_coap((uint8_t*)buffer, n, &received_packet_address);
        }
    }
}
uint8_t tx_cb(sn_nsdl_capab_e protocol, uint8_t *data_ptr, uint16_t data_len, sn_nsdl_addr_s *address_ptr)
{
    pc.printf("TX callback!\n\rSending %d bytes:\r\n", data_len);

    if(server.sendTo(nsp, (char*)data_ptr, data_len) != data_len)
        pc.printf("sending failed\n\r");

    return 1;
}


uint8_t rx_cb(sn_coap_hdr_s *coap_packet_ptr, sn_nsdl_addr_s *address_ptr)
{
    pc.printf("RX callback!\r\n");

    return 0;
}

void *own_alloc(uint16_t size)
{
    return malloc(size);
}

void own_free(void* ptr_to_free)
{
    free(ptr_to_free);
}

/* Only GET method allowed */
/* Observable resource */
static uint8_t temp_resource_cb(sn_coap_hdr_s *received_coap_ptr, sn_nsdl_addr_s *address, sn_proto_info_s * proto)
{
    sprintf(temp_val,"%2.2f" ,tmp.read());
    sn_coap_hdr_s *coap_res_ptr = 0;

    pc.printf("temp callback\r\n");
    coap_res_ptr = sn_coap_build_response(received_coap_ptr, COAP_MSG_CODE_RESPONSE_CONTENT);

    coap_res_ptr->payload_len = 5;
    coap_res_ptr->payload_ptr = (uint8_t*)temp_val;

    if(received_coap_ptr->token_ptr)
    {
        pc.printf("Token included\r\n");
        if(obs_token_ptr)
        {
            free(obs_token_ptr);
            obs_token_ptr = 0;
        }
        obs_token_ptr = (uint8_t*)malloc(received_coap_ptr->token_len);
        if(obs_token_ptr)
        {
            memcpy(obs_token_ptr, received_coap_ptr->token_ptr, received_coap_ptr->token_len);
            obs_token_len = received_coap_ptr->token_len;
        }
    }

    if(received_coap_ptr->options_list_ptr->observe)
    {
        coap_res_ptr->options_list_ptr = (sn_coap_options_list_s*)malloc(sizeof(sn_coap_options_list_s));
        memset(coap_res_ptr->options_list_ptr, 0, sizeof(sn_coap_options_list_s));
        coap_res_ptr->options_list_ptr->observe_ptr = &obs_number;
        coap_res_ptr->options_list_ptr->observe_len = 1;
        obs_number++;
    }

    sn_nsdl_send_coap_message(address, coap_res_ptr);

    /* sn_coap_release.... */
    if(coap_res_ptr->options_list_ptr)
        free(coap_res_ptr->options_list_ptr);
    if(coap_res_ptr->token_ptr)
    {
        own_free(coap_res_ptr->token_ptr);
    }
    own_free(coap_res_ptr);
    return 0;
}

/* Only GET and PUT method allowed */
static uint8_t light_resource_cb(sn_coap_hdr_s *received_coap_ptr, sn_nsdl_addr_s *address, sn_proto_info_s * proto)
{
    sn_coap_hdr_s *coap_res_ptr = 0;
    static float led_dimm = 0;
    int led_state = 0;
    char led_dimm_temp[4];

    pc.printf("light callback\r\n");

    if(received_coap_ptr->msg_code == COAP_MSG_CODE_REQUEST_GET)
    {
        coap_res_ptr = sn_coap_build_response(received_coap_ptr, COAP_MSG_CODE_RESPONSE_CONTENT);

        led_state = led_dimm * 100;
        sprintf(led_dimm_temp, "%d", led_state);

        coap_res_ptr->payload_len = strlen(led_dimm_temp);
        coap_res_ptr->payload_ptr = (uint8_t*)led_dimm_temp;
    }
    if(received_coap_ptr->msg_code == COAP_MSG_CODE_REQUEST_PUT)
    {
        memcpy(led_dimm_temp, (char *)received_coap_ptr->payload_ptr, received_coap_ptr->payload_len);

        led_dimm_temp[received_coap_ptr->payload_len] = '\0';

        led_dimm = atof(led_dimm_temp);
        led_dimm = led_dimm/100;

        //led1.write(led_dimm);
        led2.write(led_dimm);
        led3.write(led_dimm);
        //led4.write(led_dimm);

        coap_res_ptr = sn_coap_build_response(received_coap_ptr, COAP_MSG_CODE_RESPONSE_CHANGED);
    }

    sn_nsdl_send_coap_message(address, coap_res_ptr);

    /* sn_coap_release.... */
    if(coap_res_ptr->token_ptr)
    {
        own_free(coap_res_ptr->token_ptr);
    }
    own_free(coap_res_ptr);
    return 0;
}

/* Only GET method allowed */
static uint8_t gps_resource_cb(sn_coap_hdr_s *received_coap_ptr, sn_nsdl_addr_s *address, sn_proto_info_s * proto)
{
    sn_coap_hdr_s *coap_res_ptr = 0;
    static float led_dimm = 0;
    int led_state = 0;
    char led_dimm_temp[4];

    pc.printf("gps callback\r\n");

    coap_res_ptr = sn_coap_build_response(received_coap_ptr, COAP_MSG_CODE_RESPONSE_CONTENT);

    led_state = led_dimm * 100;
    sprintf(led_dimm_temp, "%d", led_state);

    coap_res_ptr->payload_len = sizeof(res_gps_val)-1;
    coap_res_ptr->payload_ptr = (uint8_t*)res_gps_val;

    sn_nsdl_send_coap_message(address, coap_res_ptr);

    /* sn_coap_release.... */
    if(coap_res_ptr->token_ptr)
    {
        own_free(coap_res_ptr->token_ptr);
    }
    own_free(coap_res_ptr);
    return 0;
}

/* Only GET and PUT method allowed */
static uint8_t relay_resource_cb(sn_coap_hdr_s *received_coap_ptr, sn_nsdl_addr_s *address, sn_proto_info_s * proto)
{
    sn_coap_hdr_s *coap_res_ptr = 0;
    static uint8_t relay_state = '0';

    pc.printf("relay callback\r\n");

    if(received_coap_ptr->msg_code == COAP_MSG_CODE_REQUEST_GET)
    {
        coap_res_ptr = sn_coap_build_response(received_coap_ptr, COAP_MSG_CODE_RESPONSE_CONTENT);

        coap_res_ptr->payload_len = 1;
        coap_res_ptr->payload_ptr = &relay_state;
    }
    if(received_coap_ptr->msg_code == COAP_MSG_CODE_REQUEST_PUT)
    {
        if(received_coap_ptr->payload_len)
        {
            if(*(received_coap_ptr->payload_ptr) == '1')
            {
                buzzer.beep(1000,0);
                relay_state = '1';
                
            }
            else if(*(received_coap_ptr->payload_ptr) == '0')
            {
                buzzer.nobeep();
                relay_state = '0';
            }
            
            coap_res_ptr = sn_coap_build_response(received_coap_ptr, COAP_MSG_CODE_RESPONSE_CHANGED);
            
        }
    }

    sn_nsdl_send_coap_message(address, coap_res_ptr);

    /* sn_coap_release.... */
    if(coap_res_ptr->token_ptr)
    {
        own_free(coap_res_ptr->token_ptr);
    }
    own_free(coap_res_ptr);
    return 0;
}