mbed xpl base example

main.cpp

Committer:
richnash
Date:
2018-07-30
Revision:
0:0fc77069cf70

File content as of revision 0:0fc77069cf70:


// ##################################################################################
//      XPL Test Program
// ##################################################################################

#if !FEATURE_LWIP
    #error [NOT_SUPPORTED] LWIP not supported for this target
#endif

// -----------------------------------------------------------
// MBED Headers
#include "mbed.h"
#include "EthernetInterface.h"
#include "rtos.h"

// -----------------------------------------------------------
// My Headers
#include "Watchdog.h"
#include "xPL.h"

// -----------------------------------------------------------
// defines
#define UDP_PORT            3865
#define UDP_BUFFER_SIZE     500

// -----------------------------------------------------------
// global variables
Watchdog wd;
xPL xpl;

DigitalOut led1(LED1);
DigitalOut led2(LED2);
DigitalOut led3(LED3);
DigitalOut led4(LED4);

Serial logger(SERIAL_TX, SERIAL_RX);

EthernetInterface   gEth;
UDPSocket           _socket;
UDPSocket           _socketSender;
char                in_buffer[UDP_BUFFER_SIZE];

// -----------------------------------------------------------
// 
// -----------------------------------------------------------
void terminal_error_state( void )
{
    led1=0;
    led2=0;
    led3=0;
    logger.printf("\r\n\r\nJUST TO BE CLEAR - THIS IS BAD BAD NEWS !!! \r\n");
    logger.printf("\r\n\r\n---- WAITING FOR THE WATCHDOG TO RESET US ---- \r\n");
    while( 1 )
        {
        led1 = !led1;
        led2 = !led2;
        led3 = !led3;
        wait(0.3);
        }
}

// -----------------------------------------------------------
// 
// -----------------------------------------------------------
static bool DeviceConnect()
{
    int retries = 10;
    int rc = 0;
    
    while (retries--) 
        {
        rc = gEth.connect();
        if (rc == 0) {
            // done
            return true;
            }
        else
            {
            logger.printf("Connecting... ERR %d\r\n", rc);
            }
        }
    
    logger.printf("Connecting... FAILED\r\n");
    return false;
}

// -----------------------------------------------------------
// 
// -----------------------------------------------------------
static bool DeviceEthStartup()
{
   int rc = 0;
   
   // get ethernet up !
    if( !DeviceConnect() ) terminal_error_state();
    
    // Output the network address
    const char *ip = gEth.get_ip_address();
    const char *netmask = gEth.get_netmask();
    const char *gateway = gEth.get_gateway();
    printf("IP address: %s\r\n", ip ? ip : "None");
    printf("Netmask: %s\r\n", netmask ? netmask : "None");
    printf("Gateway: %s\r\n", gateway ? gateway : "None");
    
    // setup a UDP listener
    _socket.set_blocking(true);
    _socket.set_timeout(3000);
    //_socket.set_broadcasting(true);
    
    // open the socket
    rc = _socket.open((NetworkInterface*)&gEth);
    if( rc != 0)
        {
        logger.printf("UDPSocket RECEIVER OPEN ERROR   (rc=%d)\r\n", rc);
        terminal_error_state();
        }
    
    // bind the XPL port
    rc = _socket.bind(UDP_PORT);
    logger.printf("Binding port %d\r\n", UDP_PORT);
    if( rc != 0)
        {
        logger.printf("UDPSocket BIND ERROR   (rc=%d)\r\n", rc);
        terminal_error_state();
        }
    
    // open the sender socket
    rc = _socketSender.open((NetworkInterface*)&gEth);
    if( rc != 0)
        {
        logger.printf("UDPSocket SENDER OPEN ERROR   (rc=%d)\r\n", rc);
        terminal_error_state();
        }
    //_socketSender.set_broadcasting(true);
    
    return true;
}


// -----------------------------------------------------------
// 
// -----------------------------------------------------------
void SendUdPMessage(char *buffer)
{
    //const char * msg = "xpl-stat{\nhop=1\nsource=NIHH-NUCLEO1.100040\ntarget=*\n}\nsensor.basic\n{\ncurrent=133\ndevice=NUCLEO1\n}";
    
    //SocketAddress *_sAddr = new SocketAddress("255.255.255.255",UDP_PORT);
    //_socketSender.sendto( _sAddr, (const void *)buffer, strlen( buffer ) );
    
    //int rc = _socketSender.sendto( "10.0.0.51", UDP_PORT, (const void *)buffer, strlen( buffer ) );
    //logger.printf("[SEND rc=%d] %s\r\n", rc, buffer);
    
    //int rc = _socketSender.sendto( "255.255.255.255", UDP_PORT, (const void *)msg, strlen( msg ) );
    //logger.printf("[SEND rc=%d] %s\r\n", rc, buffer);
    
    //int rc = _socketSender.sendto( "10.0.0.53", 3800, (const void *)buffer, strlen( buffer ) );
    //int rc = _socketSender.sendto( "10.0.0.53", UDP_PORT, (const void *)buffer, strlen( buffer ) );
    int rc = _socketSender.sendto( "255.255.255.255", UDP_PORT, (const void *)buffer, strlen( buffer ) );
    
    //logger.printf("[SEND rc=%d] buffer[%d]\r\n", rc, strlen(buffer) );
    logger.printf("[SEND rc=%d] buffer[%d]\r\n%s\r\n", rc, strlen(buffer), buffer);
    
/*
    SocketAddress *_socketAddress;
    _socketAddress = new SocketAddress((NetworkInterface*)&gEth, "10.0.0.255", UDP_PORT);
    int rc = _socketSender.sendto( _socketAddress, (const void *)msg, strlen( msg ) );
    logger.printf("[SEND rc=%d] %s\r\n", rc, msg);
*/
}

/* *******************************************************

xpl-stat
{
hop=1
source=NIHH-NUCLEO1.100043
target=*
}
clock.update
{
time=20180730113315
}

xpl-stat
{
hop=1
source=NIHH-NUCLEO1.100043
target=*
}
hbeat.app
{
interval=300
port=3865
remote-ip=8.8.8.8
version=1.0
}

******************************************************* */




// -----------------------------------------------------------
// 
// -----------------------------------------------------------
void SendXPLint(char *Device, int iCurrent )
{
//    xPL_Message _message;
//    _message.SetTarget( "*" );
//    _message.AddCommand("device", "xxxxx");
//    _message.AddCommand("current", "0");
//    xpl.SendMessage( &_message, true );
}


// -----------------------------------------------------------
// 
// -----------------------------------------------------------
void SendXPLString(char *Device, char *szCurrent )
{
//    xPL_Message _message;
//    _message.SetTarget( "*" );
//    _message.AddCommand("device", "xxxxx");
//    _message.AddCommand("current", "0");
//    xpl.SendMessage( &_message, true );
}


// -----------------------------------------------------------
// 
// -----------------------------------------------------------
void AfterParseAction(xPL_Message * message)
{
    /*    
    if (xpl.TargetIsMe(message))
    {
      if (message->IsSchema("lighting", "basic"))
      {
        Serial.println("is lighting.basic");
      }
    }
    */
    
    logger.printf("[%s]\r\n", message->source.device_id );
    
    // do we have any data ???  maybe the parse failed....
    if( message->command_count == 0 )
        {
        // 
        logger.printf("+++++++++++++\r\n%s\r\n", in_buffer );
        }
    else
        {
        // output the message data  
        for (short i=0; i<message->command_count; i++)
            {
            //logger.printf("%s=%s\r\n", message->command[i].name, message->command[i].value);
            }
        }
    
    // output the full msg!
    //logger.printf("%s\r\n", message->toString());
}



// -----------------------------------------------------------
// 
// -----------------------------------------------------------
void Receiver_Thread(void const *argument)
{
    SocketAddress   _sAddr;
    int             iNoDataCount = 0;
    
    // loop forever
    while(1)
        {
        // receive from the udp socket
        led2 = 0;
        int n = _socket.recvfrom(&_sAddr, in_buffer, UDP_BUFFER_SIZE);
        //led2 = 1;
        
        // see what weve got !
        if (n == NSAPI_ERROR_WOULD_BLOCK)
            {
            // timeout with no data...
            ++iNoDataCount;
            logger.printf("-- NoData (TIMEOUT)\r\n");
            led2 = 0;
            }
        else if (n < 0)
            {
            // some other error
            ++iNoDataCount;
            logger.printf("-- NoData (ERR) %i\r\n", n);
            led2 = 0;
            }
        else if( n > 0)
            {
            // good data :)
            iNoDataCount = 0;
            in_buffer[n] = '\0';
            // logger.printf("[%d bytes] %s:%d\r\n", n, _sAddr.get_ip_address(), _sAddr.get_port());
            // logger.printf("%s\r\n", in_buffer);
            led2 = 1;
            
            // try and parse the msg
            xpl.ParseInputMessage(in_buffer);
            }
        
        // have we stopped receiving data ?!?!?
        if( iNoDataCount > 20 )
            {
            logger.printf("-------- Arghhhh NO DATA !!! ---------\r\n");
            
            // maybe - looks dodgy at least...  try the reset
            //gEth.disconnect();
            //wait(0.5);
            //DeviceEthStartup();
            //Thread::wait(1000);
            terminal_error_state();
            }
        
        // stroke the WD
        wd.Service();
        }
}


// -----------------------------------------------------------
// 
// -----------------------------------------------------------
int main()
{
    int iAppLoop=0;
    int iXPLdata=0;
    
    // FIRST THINGS FIRST!!!  set the WD timeout interval...
    // enough to get up and running!
    wd.Configure(1000.0);
    
    // setup the pc serial logger
    logger.baud(115200);
    logger.printf("\r\n\r\n<<<<<<<<< Basic UDP XPL Listener >>>>>>>>>>\r\n");
    
    led1 = 0;
    led2 = 0;
    led3 = 0;
    led4 = 0;
    
    // WatchDog Startup Information
    logger.printf("\r\n------------------------------------------------------\r\n" );
    logger.printf("[SystemCoreClock] %d Hz\r\n", SystemCoreClock);
    logger.printf("[Reset reason] ");
    if (__HAL_RCC_GET_FLAG(RCC_FLAG_IWDGRST)) logger.printf("Independant-Watchdog  ");
    if (__HAL_RCC_GET_FLAG(RCC_FLAG_WWDGRST)) logger.printf("Window-Watchdog  ");
    if (__HAL_RCC_GET_FLAG(RCC_FLAG_LPWRRST)) logger.printf("Low-Power-Reset  ");
    if (__HAL_RCC_GET_FLAG(RCC_FLAG_SFTRST)) logger.printf("Software-Reset  ");
    if (__HAL_RCC_GET_FLAG(RCC_FLAG_PORRST)) logger.printf("Power-On/Down-Reset  ");
    if (__HAL_RCC_GET_FLAG(RCC_FLAG_PINRST)) logger.printf("Reset-pin  ");
    if (__HAL_RCC_GET_FLAG(RCC_FLAG_BORRST)) logger.printf("Brownout  ");
    if (__HAL_RCC_GET_FLAG(RCC_FLAG_LSIRDY)) logger.printf("Low-speed-internal-clock-ready  ");
    __HAL_RCC_CLEAR_RESET_FLAGS();
    logger.printf("\r\n------------------------------------------------------\r\n");
    
    if (wd.WatchdogCausedReset())
        {
        logger.printf("<<Watchdog caused reset>>\r\n");
        led3 = 1;
        }
    else
        {
        logger.printf("<<Normal Startup>>\r\n");
        led1 = 1;
        led2 = 1;
        led3 = 0;
        }
    logger.printf("------------------------------------------------------\r\n\r\n");
    
    // Fireup the Ethernet
    DeviceEthStartup();
    
    // now set the WD to something to run with - between receving data
    wd.Service();
    wd.Configure(300.0);
    
    // setup xpl
    xpl.SendExternal = &SendUdPMessage;  // pointer to the send callback
    xpl.AfterParseAction = &AfterParseAction;  // pointer to a post parsing action callback 
    xpl.SetSource( "NIHH", "NUCLEO1", "100043"); // parameters for hearbeat message
    
    // kick off the XPL receiver thread to run in the background
    Thread thread1(Receiver_Thread, NULL, osPriorityHigh); //, DEFAULT_STACK_SIZE);
    
    // start running the main processing stuff here
    while (true) 
        {
        led1 = 0;
        Thread::wait(2000);
        led1 = 1;
        logger.printf("*\r\n");
        Thread::wait(100);
        
        // allow xpl to do its thing...
        xpl.Process();
        
        // every 10 loops send an XPL msg
        ++iAppLoop;
        if( iAppLoop >= 5 )
            {
            xPL_Message _message;
            
            /*
            _message.SetSchema( "clock", "update" );
            _message.SetTarget( "*" );
            _message.type = XPL_STAT;
            _message.hop = 1;
            _message.AddCommand("time", "20180730113315");
            xpl.SendMessage( (xPL_Message *)&_message, true );
            */
            
            _message.SetSchema( "sensor", "basic" );
            _message.SetTarget( "*" );
            _message.type = XPL_STAT;
            _message.hop = 1;
            _message.AddCommand("device", "test1");
            _message.AddCommand("type", "test");
            _message.AddCommand("current", "1");
            xpl.SendMessage( (xPL_Message *)&_message, true );
            
            // reset
            iAppLoop = 0;
            }
        }
}