MQTT and Wishield

Questions specifically related to the TCP/IP stack that interfaces with the driver.

MQTT and Wishield

Postby johncohn » Thu Dec 31, 2009 11:03 am

Friends,
I'm new to WiShelid and trying to get MQTT , the pub/sub communication protocol from Andy Stanford-Clark and friends, working on an arduino. (see http://knolleary.net/arduino-client-for-mqtt/, I'm trying to figure out how to adapt it for the WiShield . I tried just adding #include <WiServer.h> but that wouldn't compile with the Ethernet.h header because of conflicting var definitions. I started to try and debug and modify the headers but soon realized this would get complicated. Before I spend more time on it has anyone
  • already got WiSheld working with MQTT ?
  • know what I'd have to hack in the PubSubClient function to substitute WiSheld TCPIP open/close etc for the Ethernet.h specific stuff that's already there ?

Any help appreciated .. Happy new year everyone !
-jc


Here's the MQTT test sketch from http://knolleary.net/arduino-client-for-mqtt/
Code: Select all
#include <Ethernet.h>
#include <PubSubClient.h>

byte mac[] = {  0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
byte ip[] = { 172, 16, 0, 1 };
byte server[] = { 172, 16, 0, 100 };

void callback(char* topic, byte* payload,int length) {
  // handle message arrived
}

PubSubClient client(server, 1883, callback);

void setup()
{
  Ethernet.begin(mac, ip);
  if (client.connect("arduino")) {
    client.publish("foo","hello world");
    client.subscribe("bar");
  }
}

void loop()
{
  client.loop();
}


Here's the PubSubClient.cpp from http://knolleary.net/arduino-client-for-mqtt/
Code: Select all
/*
PubSubClient.cpp - A simple client for MQTT.
  Nicholas O'Leary
  http://knolleary.net
*/

#include "WConstants.h"
#include "PubSubClient.h"
#include "Client.h"
#include "string.h"

#define MQTTCONNECT 1<<4
#define MQTTPUBLISH 3<<4
#define MQTTSUBSCRIBE 8<<4


PubSubClient::PubSubClient(uint8_t *ip, uint16_t port, void (*callback)(char*,uint8_t*,int)) : _client(ip,port) {
   this->callback = callback;
}
int PubSubClient::connect(char *id) {
   return connect(id,0,0,0,0);
}

int PubSubClient::connect(char *id, char* willTopic, uint8_t willQos, uint8_t willRetain, char* willMessage) {
   if (!_client.connected()) {
      if (_client.connect()) {
         nextMsgId = 1;
         uint8_t d[9] = {0x00,0x06,0x4d,0x51,0x49,0x73,0x64,0x70,0x03};
         uint8_t length = 0;
         int j;
         for (j = 0;j<9;j++) {
            buffer[length++] = d[j];
         }
         if (willTopic) {
            buffer[length++] = 0x06|(willQos<<3)|(willRetain<<5);
         } else {
            buffer[length++] = 0x02;
         }
         buffer[length++] = 0;
         buffer[length++] = (KEEPALIVE/500);
         length = writeString(id,buffer,length);
         if (willTopic) {
            length = writeString(willTopic,buffer,length);
            length = writeString(willMessage,buffer,length);
         }
         write(MQTTCONNECT,buffer,length);
         while (!_client.available()) {}
         uint8_t len = readPacket();
         if (len == 4 && buffer[3] == 0) {
            lastActivity = millis();
            return 1;
         }
         
         _client.stop();
      }
   }
   return 0;
}

uint8_t PubSubClient::readPacket() {
   uint8_t len = 0;
   buffer[len++] = _client.read();
   
   uint8_t multiplier = 1;
   uint8_t length = 0;
   uint8_t digit = 0;
   do {
      digit = _client.read();
      buffer[len++] = digit;
      length += (digit & 127) * multiplier;
      multiplier *= 128;
   } while ((digit & 128) != 0);
   
   for (int i = 0;i<length;i++)
   {
      if (len < MAX_PACKET_SIZE) {
         buffer[len++] = _client.read();
      } else {
         _client.read();
         len = 0; // This will cause the packet to be ignored.
      }
   }
   return len;
}

int PubSubClient::loop() {
   if (_client.connected()) {
      long t = millis();
      if (t - lastActivity > KEEPALIVE) {
         _client.write(192);
         _client.write((uint8_t)0);
         lastActivity = t;
      }
      if (_client.available()) {
         uint8_t len = readPacket();
         if (len > 0) {
            uint8_t type = buffer[0]>>4;
            if (type == 3) { // PUBLISH
               if (callback) {
                  uint8_t tl = (buffer[2]<<3)+buffer[3];
                  char topic[tl+1];
                  for (int i=0;i<tl;i++) {
                     topic[i] = buffer[4+i];
                  }
                  topic[tl] = 0;
                  // ignore msgID - only support QoS 0 subs
                  uint8_t *payload = buffer+4+tl;
                  callback(topic,payload,len-4-tl);
               }
            } else if (type == 12) { // PINGREG
               _client.write(208);
               _client.write((uint8_t)0);
               lastActivity = t;
            }
         }
      }
      return 1;
   }
   return 0;
}

int PubSubClient::publish(char* topic, char* payload) {
   return publish(topic,(uint8_t*)payload,strlen(payload));
}


int PubSubClient::publish(char* topic, uint8_t* payload, uint8_t plength) {
   if (_client.connected()) {
      uint8_t length = writeString(topic,buffer,0);
      int i;
      for (i=0;i<plength;i++) {
         buffer[length++] = payload[i];
      }
      //header |= 1; retain
      write(MQTTPUBLISH,buffer,length);
      return 1;
   }
   return 0;
}


int PubSubClient::write(uint8_t header, uint8_t* buf, uint8_t length) {
   _client.write(header);
   _client.write(length);
   for (int i=0;i<length;i++) {
      _client.write(buf[i]);
   }
   return 0;
}


void PubSubClient::subscribe(char* topic) {
   if (_client.connected()) {
      uint8_t length = 2;
      nextMsgId++;
      buffer[0] = nextMsgId >> 8;
      buffer[1] = nextMsgId - (buffer[0]<<8);
      length = writeString(topic, buffer,length);
      buffer[length++] = 0; // Only do QoS 0 subs
      write(MQTTSUBSCRIBE,buffer,length);
   }
}

void PubSubClient::disconnect() {
   _client.write(224);
   _client.write((uint8_t)0);
   _client.stop();
   lastActivity = millis();
}

uint8_t PubSubClient::writeString(char* string, uint8_t* buf, uint8_t pos) {
   char* idp = string;
   uint8_t i = 0;
   pos += 2;
   while (*idp) {
      buf[pos++] = *idp++;
      i++;
   }
   buf[pos-i-2] = 0;
   buf[pos-i-1] = i;
   return pos;
}


int PubSubClient::connected() {
   return (int)_client.connected();
}


and here's the PubSubClient.h from http://knolleary.net/arduino-client-for-mqtt/
Code: Select all
/*
PubSubClient.h - A simple client for MQTT.
  Nicholas O'Leary
  http://knolleary.net
*/

#ifndef PubSubClient_h
#define PubSubClient_h

#include "Client.h"

#define MAX_PACKET_SIZE 128
#define KEEPALIVE 15000 // max value = 255000


class PubSubClient {
private:
   Client _client;
   uint8_t buffer[MAX_PACKET_SIZE];
   uint8_t nextMsgId;
   long lastActivity;
   void (*callback)(char*,uint8_t*,int);
   uint8_t readPacket();
   int write(uint8_t header, uint8_t* buf, uint8_t length);
   uint8_t writeString(char* string, uint8_t* buf, uint8_t pos);
public:
   PubSubClient(uint8_t *, uint16_t, void(*)(char*,uint8_t*,int));
   int connect(char *);
   int connect(char*, char*, uint8_t, uint8_t, char*);
   void disconnect();
   int publish(char *, char *);
   int publish(char *, uint8_t *, uint8_t);
   void subscribe(char *);
   int loop();
   int connected();
};


#endif
johncohn
 
Posts: 7
Joined: Sun Dec 27, 2009 11:06 pm

Re: MQTT and Wishield

Postby GregEigsti » Thu Dec 31, 2009 12:16 pm

Not familiar with MQTT. Is this ethernet.h the header for the typical Arduino ethernet shield? If so you will need to trash it and start porting their code over to the uIP stack that the WiShield uses (or better yet write an abstraction layer that presents the uIP stack as a BSD compatible stack). The typical Arduino ethernet controller (that I have seen) has the stack implemented on board as part of the shield - the WiShield does not, rather it uses the uIP stack that gets built into your project. Given that the two stacks are very different and your user code talks to them differently you will not be able to use ethernet.h

Greg
Check out the wiki!
uIP Stack Docs
Compatible Access Point List
WiShield user contrib branch - DNS, DHCP, AP Scanning, bug fixes, etc.
SlackLab.org - My geek projects blog.
User avatar
GregEigsti
 
Posts: 1067
Joined: Sun Aug 02, 2009 5:23 pm
Location: Sammamish WA USA (near Seattle)
  • Website

Re: MQTT and Wishield

Postby johncohn » Thu Dec 31, 2009 1:44 pm

Greg,
Thanks for the input.. I was pretty sure that I would have to re-map the MQTT stuff over to the new TC/IP stack.. I just cant find it documented anywhere. All I have is the source code for the stack I got from Git. Is that what I have to go on ... or is there some other documentation for it ?
-jc
johncohn
 
Posts: 7
Joined: Sun Dec 27, 2009 11:06 pm

Re: MQTT and Wishield

Postby GregEigsti » Thu Dec 31, 2009 1:54 pm

uIP stack home page
http://www.sics.se/~adam/uip/index.php/Main_Page
uIP stack docs (PDF, HTML is available on the site as well)
http://www.sics.se/~adam/download/uip-1.0-refman.pdf

The uIP docs are really worth reading if you are serious about having a deeper understanding of the WiShield.

Greg
Check out the wiki!
uIP Stack Docs
Compatible Access Point List
WiShield user contrib branch - DNS, DHCP, AP Scanning, bug fixes, etc.
SlackLab.org - My geek projects blog.
User avatar
GregEigsti
 
Posts: 1067
Joined: Sun Aug 02, 2009 5:23 pm
Location: Sammamish WA USA (near Seattle)
  • Website

Re: MQTT and Wishield

Postby franklovecchio » Thu Aug 12, 2010 9:27 am

@JohnCohn

Did you ever get MQTT working with Wishield?
franklovecchio
 
Posts: 9
Joined: Wed Aug 04, 2010 5:14 pm

Re: MQTT and Wishield

Postby johncohn » Thu Aug 12, 2010 2:05 pm

No.. I never did.. Are you interested in getting that done ?
-jc
johncohn
 
Posts: 7
Joined: Sun Dec 27, 2009 11:06 pm

Re: MQTT and Wishield

Postby franklovecchio » Thu Aug 12, 2010 4:07 pm

Yes. My C experience is limited, but it would be very worthwhile to me.
franklovecchio
 
Posts: 9
Joined: Wed Aug 04, 2010 5:14 pm


Return to TCP/IP Stack

Who is online

Users browsing this forum: No registered users and 1 guest