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
-
First, you log in thinger.io
-
Add your WIZwiki-W7500 by clicking “Add new Devices” on thinger.io dashboard as the following picture. For more detail, refer to https://community.thinger.io/t/register-a-device-in-the-console/23.
<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/