Mbed WIZwiki-W7500 platform with Smart IoT Cloud Server Thinger.io


#1

mbed WIZwiki-W7500 platform with Smart IoT Cloud Server Thinger.io


This project is based on mbed WIZwiki-W7500 platform launced by WIZnet. WIZwiki-W7500 can connect to the smart IoT cloud server called thinger.io.

Overview

This project started from my finding an easy & optimized smart IoT cloud services for easy to work with WIZwiki-W7500 platform. I found a cloud server called as thinger.io. But, thinger.io cloud server supports just only the device APIs based on Arduino IDE. But I need a device APIs based on mbed. Fortunately, thinger.io supports the Ardunio Ethernet device APIs, and I can port these APIs to mbed ethernet device API for WIZwiki-W7500.

In porting, The developer of thinger.io give me so much help & support.

Thru this post, I thank him server soooo much.

I tested my thinger.io device API for mbed with YuRobot Easy module shiled v1 have many sensors and LEDs.

WIZwiki-W7500

This IoT platform made by WIZnet and lauched on mbed as silicon parter.

There are many example on mbed. For more detail, Refer to Wiki site or mbed.

This is compatible with Arduino PIN map.

Thinger.io

![]( “Sourced by https://github.com/thinger-io/”)

Thinger.io is a platform that allows connecting things to the Internet.

And what’s new?

  • Hardware agnostic: Connect anything! from basic ** Arduinos ** with very limited resources, to more complex embedded systems running linux like Raspberry Pi.

  • It is Open Source, so you can take the code an build your own cloud if you want. It provides thing API discovery right out of the box, so you can code your things and interact easily from the web. Turning a led on from the Internet just take one line of code in the device, seriously!. It has been designed with developers in mind, so any developer will love to work with this platform.

For more detail, Refer to thinger.io.

<NOTICE> This site povids beta sevice. If you want to test your device on thinger.io, You should get a beta access keys.

YuRobot Easy shiled V1

YoRobot Shield provide many sensor such as light, temperature, humidity, IR and etc.


What I do

Compatible Client Class for Arduino

This class - TCPSocketConnectionArdu - need to minimize modification to Arduino Ethernet Device API of thinger.io.

class TCPSocketConnectionArdu : public TCPSocketConnection {

    public:

    /** TCP socket connection **/
    TCPSocketConnectionArdu() {};
    virtual ~TCPSocketConnectionArdu() { TCPSocketConnection::close(); };

    ssize_t write(uint8_t);

    /** Send data to the remote host.
    \param data The buffer to send to the host.
    \param length The length of the buffer to send.
    \return the number of written bytes on success (>=0) or -1 on failure
     */
    virtual ssize_t write(const void *buf, size_t size);
    virtual int available();
    ssize_t read();    
    virtual ssize_t read(void *buf, size_t size);    
    virtual ssize_t readBytes(uint8_t* buf, size_t size);
    virtual ssize_t peek();
    virtual void flush();
    virtual void stop();

    /** Check if the socket is connected
    \return true if connected, false otherwise.
    */
    virtual uint8_t connected();
    virtual operator bool(); 

    friend class TCPSocketServer;
};

Ethernet & TCP Client API for mbed : ThingerMBedEthernet, ThingerMBedClient

This is ported from ThingerEthernet & ThingerClient.h in Arduino Ethernet Library of thinger.io

  • ThingerEthernet
#ifndef _DHCP_   // You should be define your network if no DHCP
    #define DEV_IP_ADDRESS "xxx.xxx.xxx.xxx"
    #define DEV_GW_ADDRESS "xxx.xxx.xxx.xxx"
    #define DEV_SN_ADDRESS "255.255.255.0"
#endif    

class ThingerEthernet : public ThingerClient {
public:

    ThingerEthernet(const char* user, const char* device, const char* device_credential) :
            ThingerClient(client_, user, device, device_credential), connected_(false)
    {}
    ~ThingerEthernet(){
    }

protected:
    virtual bool network_connected(){
        return connected_;
    }

    virtual bool connect_network(){
        if(connected_) return true;
        uint8_t mac[6] = { 0x1D, 0xdc, 0x08, 0x00, 0x62, 0x11 };
        unsigned long ethernet_timeout = millis();

#ifdef _DHCP_        
    #ifdef _DEBUG_
        printf("[NETWORK] Getting DHCP IP Address...\r\n");
    #endif
        ((EthernetInterface*)WIZnet_Chip::getInstance()).init(mac);
    #else
        ((EthernetInterface*)WIZnet_Chip::getInstance())->init(mac,DEV_IP_ADDRESS,DEV_SN_ADDRESS,DEV_GW_ADDRESS);
    #endif
        ((EthernetInterface*)WIZnet_Chip::getInstance())->ethernet_link();
        delay(3000);
    #ifdef _DEBUG_
        #ifdef _DHCP_
            printf("[NETWORK] Waiting for IP...\r\n");
        #endif
    #endif
        connected_ = true;    
        if(((EthernetInterface*)WIZnet_Chip::getInstance())->connect() > 0) connected_ = false;
#ifdef _DEBUG_
        printf("[NETWORK] Got Ip Address: %s\r\n",((EthernetInterface*)WIZnet_Chip::getInstance())->getIPAddress());
#endif
        delay(1000);
        return connected_;
    }

private:
    bool connected_;
    TCPSocketConnectionArdu  client_;
};
  • ThingerClient
//---For MBED---//

#ifndef Client
    #define Client              TCPSocketConnectionArdu
#endif

#ifndef millis
    #define millis()        us_ticker_read()/1000
#endif

#ifndef delay    
    #define delay               wait_ms
#endif    

class ThingerClient : public thinger::thinger {
public:

    ThingerClient(Client& client, const char* user, const char* device, const char* device_credential) : client_(client), username_(user), device_id_(device), device_password_(device_credential),
            temp_data_(NULL), out_size_(0)
    {
    }
    ~ThingerClient()
    {
    }

protected:
    virtual bool read(char* buffer, size_t size)
    {
        size_t total_read = 0;
        while(total_read<size){
            int read = client_.readBytes((uint8_t*)buffer, size-total_read);
            if(read<0) return false;
            total_read += read;
        }
        return total_read == size;
    }

    // TODO Allow removing this Nagle's algorithm implementation if the underlying device already implements it
    virtual bool write(const char* buffer, size_t size, bool flush=false){
        if(size>0){
            temp_data_ = (uint8_t*) realloc(temp_data_, out_size_ + size);
            memcpy(&temp_data_[out_size_], buffer, size);
            out_size_ += size;
        }

        if(flush && out_size_>0){
            #ifdef _DEBUG_
                printf("[THINGER] Writing bytes: %d", out_size_);
            #endif
            size_t written = client_.write(temp_data_, out_size_);
            bool success = written == out_size_;
            free(temp_data_);
            temp_data_ = NULL;
            out_size_ = 0;

            #ifdef _DEBUG_
                printf(" [%s]\r\n",success ? "OK" : "FAIL");
            #endif

            //FIXME Without this small delay or activating the debug (which takes time), the CC3200 does not work well. Why?
            #ifdef __CC3200R1M1RGC__
                delay(1);
            #endif
            return success;
        }
        return true;
    }

    virtual void disconnected(){
        thinger_state_listener(SOCKET_TIMEOUT);
        client_.stop();
        thinger_state_listener(SOCKET_DISCONNECTED);
    }
    virtual bool connect_network(){
        return true;
    }
    virtual bool network_connected(){
        return true;
    }

    enum THINGER_STATE{
        NETWORK_CONNECTING,
        NETWORK_CONNECTED,
        NETWORK_CONNECT_ERROR,
        SOCKET_CONNECTING,
        SOCKET_CONNECTED,
        SOCKET_CONNECTION_ERROR,
        SOCKET_DISCONNECTED,
        SOCKET_TIMEOUT,
        THINGER_AUTHENTICATING,
        THINGER_AUTHENTICATED,
        THINGER_AUTH_FAILED
    };

    virtual void thinger_state_listener(THINGER_STATE state){
        #ifdef _DEBUG_
        switch(state){
            case NETWORK_CONNECTING:
                printf("[NETWORK] Starting connection...\r\n");
                break;
            case NETWORK_CONNECTED:
                printf("[NETWORK] Connected!\r\n");
                break;
            case NETWORK_CONNECT_ERROR:
                printf("[NETWORK] Cannot connect!\r\n");
                break;
            case SOCKET_CONNECTING:
                printf("[_SOCKET] Connecting to %s : %d ...", THINGER_SERVER,THINGER_PORT);   
                break;
            case SOCKET_CONNECTED:
                printf("[_SOCKET] Connected!\r\n");
                break;
            case SOCKET_CONNECTION_ERROR:
                printf("[_SOCKET] Error while connecting!\r\n");
                break;
            case SOCKET_DISCONNECTED:
                printf("[_SOCKET] Is now closed!\r\n");
                break;
            case SOCKET_TIMEOUT:
                printf("[_SOCKET] Timeout!\r\n");
                break;
            case THINGER_AUTHENTICATING:
                printf("[THINGER] Authenticating. User: %s Device: %s\r\n",username_,device_id_);
                break;
            case THINGER_AUTHENTICATED:
                printf("[THINGER] Authenticated!\r\n");
                break;
            case THINGER_AUTH_FAILED:
                printf("[THINGER] Auth Failed! Check username, device id, or device credentials.\r\n");
                break;
        }
        #endif
    }
    bool handle_connection()
    {
        bool network = network_connected();
        if(!network){
            thinger_state_listener(NETWORK_CONNECTING);
            network = connect_network();
            if(!network){
                thinger_state_listener(NETWORK_CONNECT_ERROR);
                return false;
            }
            thinger_state_listener(NETWORK_CONNECTED);
        }
        bool client = client_.connected();
        if(!client){
            client = connect_client();
            if(!client){
                return false;
            }
        }
        return network && client;
    }
    bool connect_client(){
        bool connected = false;
        client_.stop(); // cleanup previous socket
        thinger_state_listener(SOCKET_CONNECTING);
        if (client_.connect(THINGER_SERVER, THINGER_PORT) == 0) {
            delay(3000);
            thinger_state_listener(SOCKET_CONNECTED);
            thinger_state_listener(THINGER_AUTHENTICATING);
            connected = thinger::thinger::connect(username_, device_id_, device_password_);
            if(!connected){
                thinger_state_listener(THINGER_AUTH_FAILED);
                client_.stop();
                thinger_state_listener(SOCKET_DISCONNECTED);
            }
            else{
                thinger_state_listener(THINGER_AUTHENTICATED);
            }
        }
        else{
            thinger_state_listener(SOCKET_CONNECTION_ERROR);
        }
        return connected;
    }

public:
    void handle(){
        if(handle_connection()){
            #ifdef _DEBUG_
            if(client_.available()>0){
                printf("[THINGER] Available bytes: %d", client_.available());
            }
            #endif
            thinger::thinger::handle(millis(), client_.available()>0);
        }else{
            delay(RECONNECTION_TIMEOUT); // get some delay for a connection retry
        }
    }
private:
    Client& client_;
    const char* username_;
    const char* device_id_;
    const char* device_password_;
    uint8_t * temp_data_;
    size_t out_size_;
};

Registration WIZwiki-W7500 to thinger.io

<NOTICE> You should remmber your DEvice credentials becase the credentials can't be shown after add device.
  • You’re ready to work WIZwiki-W7500 with thinger.io Cloud Service.

Add to your main

#include "mbed.h"
#include "EthernetInterface.h"
#include "DHT.h"
#include "TCPSocketConnectionArdu.h"
#include "ThingerMBedEthernet.h"
#include "ThingerMBedClient.h"

/* ThingerIO Define */
#define USERNAME "MidnightCow"
#define DEVICE_ID "WIZwiki_W7500_mbed_01"
#define DEVICE_CREDENTIAL "your access key" // Should be your access key.

/* YUROBOT SHILED1 PIN Define*/
#define myLED1      D13
#define myLED2      D12

#define myRLED      D9
#define myGLED      D10
#define myBLED      D11

#define myBUZZ      D5

#define myTEMPHUMM  D4

#define myLIGHT     A1

//using namespace std;
DigitalOut myled1(myLED1);
DigitalOut myled2(myLED2);

DigitalOut myrled(myRLED);
DigitalOut mygled(myGLED);
DigitalOut mybled(myBLED);

DigitalOut myBuzz(myBUZZ);

AnalogIn   mylight(myLIGHT);

DHT myTempHumm(myTEMPHUMM, DHT11);

void my_led1(pson& in)
{
    myled1 = (in) ? 1 : 0;
}
void my_led2(pson& in)
{
    myled2 = (in) ? 1 : 0;
}

void my_TempHumm(pson& out)
{
    if(myTempHumm.readData() == 0)
    {
        out["Cecelcius"] = myTempHumm.ReadTemperature(CELCIUS);
        out["Humidity"]  = myTempHumm.ReadHumidity();        
    }
    else
    {
        out["Cecelcius"] = 65535;
        out["Humidity"]  = 65535;
    }
}

/*
void my_rgbled(pson& in)
{
    myrled = (in["Red"])   ?  1 : 0;
    mygled = (in["Green"]) ?  1 : 0;
    mybled = (in["Blue"])  ?  1 : 0;    
}
*/

int main() {
    EthernetInterface eth;
    ThingerEthernet thing(USERNAME, DEVICE_ID, DEVICE_CREDENTIAL);
    myled1 = 1;
    myled2 = 1;

    // resource input example (i.e. turning on/off a light, a relay, configuring a parameter, etc)
    thing["myled1"] << my_led1;
    thing["myled2"] << my_led2;
    thing["mySensor"] >> my_TempHumm;
    //thing["myRGB"] << my_rgbled;

    while(1)
    {
        thing.handle();
    }
}

Demo Movie

WIZwiki-W7500 with ThingerIO from MidnightCow on Vimeo.

Conclusion

Thinger.io cloud sevice is very powerful for small IoT Device, becase This service support a small encoded packet called as Protoson.

So, WIZwiki-W7500 platform is suitable for thinger.io.

Thank you and enjoy them.


You can import my thinger.io mbed example here.

https://developer.mbed.org/users/MidnightCow/code/ThingerIO/


#2

Great! Thanks for this awesome contribution! Glad to see an operational port for a different platform. This makes the platform much more hardware agnostic :grinning:

We will look forward to integrate this code with our official repository. Maybe it can be also a starting point for creating a much more generic library for ARM mbed platform.


#3

Thank you.
I wait for the integrated thinger.io device API with mbed.