I’m trying to connect MQTT sensors to SmartThings HUB using the ST Thing Shield. So far I can update the status of the virtual devices using MQTT. But after the shield is not responding to the changes on the SmartThings App. I thing it is due the low memory of the Arduino Uno. if I comment the line ** check_subscription();** in the sketch the Shield start to respond to the mobile App, but does not check the MQTT subscriptions. I ordered a Arduino DUE and will do more tests when it arrives.
Does anyone have any ideas how the code could be improved/fixed? It is just my initial code, I have to write the MQTT publish part, but there is no point on doing that until the rest is fully functional.
###########################################################################
/***************************************************
Reads from SmartThings Shield and send MQTT and vice versa
****************************************************/
#include <SPI.h>
#include “Adafruit_MQTT.h”
#include “Adafruit_MQTT_Client.h”
#include <Ethernet.h>
#include <EthernetClient.h>
#include <Dns.h>
#include <Dhcp.h>
#include <SoftwareSerial.h> //TODO need to set due to some weird wire language linker, should we absorb this whole library into smartthings
#include <SmartThings.h>
/************************* Ethernet Client Setup *****************************/
byte mac[] = {0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED};
//Uncomment the following, and set to a valid ip if you don’t have dhcp available.
//IPAddress iotIP (192, 168, 0, 42);
//Uncomment the following, and set to your preference if you don’t have automatic dns.
//IPAddress dnsIP (8, 8, 8, 8);
//If you uncommented either of the above lines, make sure to change “Ethernet.begin(mac)” to “Ethernet.begin(mac, iotIP)” or “Ethernet.begin(mac, iotIP, dnsIP)”
/************************* MQTT Server Setup *********************************/
#define AIO_SERVER “192.168.0.2”
#define AIO_SERVERPORT 1883
#define AIO_USERNAME “”
#define AIO_KEY “”
/************************* SmartThings Shield pins and variables *********************************/
#define PIN_THING_RX 3
#define PIN_THING_TX 2
SmartThingsCallout_t messageCallout; // call out function forward decalaration
SmartThings smartthing(PIN_THING_RX, PIN_THING_TX, messageCallout); // constructor
int ledPin = 13;
bool isDebugEnabled; // enable or disable debug in this example
int stateLED; // state to track last set value of LED
/************ Global State (you don’t need to change this!) ******************/
//Set up the ethernet client
EthernetClient client;
// Store the MQTT server, client ID, username, and password in flash memory.
// This is required for using the Adafruit MQTT library.
const char MQTT_SERVER[] PROGMEM = AIO_SERVER;
// Set a unique MQTT client ID using the AIO key + the date and time the sketch
// was compiled (so this should be unique across multiple devices for a user,
// alternatively you can manually set this to a GUID or other random value).
const char MQTT_CLIENTID[] PROGMEM = TIME AIO_USERNAME;
const char MQTT_USERNAME[] PROGMEM = AIO_USERNAME;
const char MQTT_PASSWORD[] PROGMEM = AIO_KEY;
Adafruit_MQTT_Client mqtt(&client, MQTT_SERVER, AIO_SERVERPORT, MQTT_CLIENTID, MQTT_USERNAME, MQTT_PASSWORD);
// You don’t need to change anything below this line!
#define halt(s) { Serial.println(F( s )); while(1); }
/****************************** Feeds ***************************************/
// Setup a feed called ‘photocell’ for publishing.
// Notice MQTT paths for AIO follow the form: /feeds/
const char PHOTOCELL_FEED[] PROGMEM = AIO_USERNAME “myhouse/garage/door”;
Adafruit_MQTT_Publish photocell = Adafruit_MQTT_Publish(&mqtt, PHOTOCELL_FEED);
// Setup a feed called ‘onoff’ for subscribing to changes.
const char ONOFF_FEED[] PROGMEM = AIO_USERNAME “myhouse/garage/open”;
Adafruit_MQTT_Subscribe onoffbutton = Adafruit_MQTT_Subscribe(&mqtt, ONOFF_FEED);
/*************************** Sketch Code ************************************/
void setup() {
// SmartThings Shield state of global variables
isDebugEnabled = true;
stateLED = 0; // matches state of hardware pin set below
// SmartThings Shield setup hardware pins
pinMode(ledPin, OUTPUT); // define PIN_LED as an output
digitalWrite(ledPin, LOW); // set value to LOW (off) to match stateLED=0
Serial.begin(115200);
Serial.println(F(“Arduino SmartThings Shield - MQTT Client”));
if (isDebugEnabled)
{
Serial.println(F(“SmartThings Shield Debug enabled…”));
}
// Initialise the MQTT Client
Serial.print(F("\nInitiating Ethernet Client…"));
Ethernet.begin(mac);
delay(1000); //give the ethernet a second to initialize
mqtt.subscribe(&onoffbutton);
}
uint32_t x=0;
void loop() {
// Ensure the connection to the MQTT server is alive (this will make the first
// connection and automatically reconnect when disconnected). See the MQTT_connect
// function definition further below.
MQTT_connect();
check_subscription(); // this is our ‘wait for incoming subscription packets’ busy subloop
// publish(); // Publish MQTT message
smartthing.run(); // run smartthing logic
// ping the server to keep the mqtt connection alive
if(! mqtt.ping()) {
mqtt.disconnect();
}
}
void publish() {
// Now we can publish stuff!
Serial.print(F("\nPublishing val “));
Serial.print(x);
Serial.print(”…");
if (! photocell.publish(x)) { // Publish variable x
Serial.println(F(“Failed”));
} else {
Serial.println(F(“OK!”));
}
}
void check_subscription() {
// this is our ‘wait for incoming subscription packets’ busy subloop
Adafruit_MQTT_Subscribe *subscription;
while ((subscription = mqtt.readSubscription(1000))) {
if (subscription == &onoffbutton) {
Serial.print(F("Subscription received: "));
// Serial.println((char *)onoffbutton.lastread);
String str((char *)onoffbutton.lastread);
Serial.println(str);
if (str == “on”)
{
on();
}
else if (str == “off”)
{
off();
}
}
}
}
// Function to connect and reconnect as necessary to the MQTT server.
// Should be called in the loop function and it will take care if connecting.
void MQTT_connect() {
int8_t ret;
// Stop if already connected.
if (mqtt.connected()) {
return;
}
Serial.print("Connecting to MQTT… ");
while ((ret = mqtt.connect()) != 0) { // connect will return 0 for connected
Serial.println(mqtt.connectErrorString(ret));
Serial.println(“Retrying MQTT connection in 5 seconds…”);
mqtt.disconnect();
delay(5000); // wait 5 seconds
}
Serial.println(“MQTT Connected!”);
}
void on()
{
stateLED = 1; // save state as 1 (on)
digitalWrite(ledPin, HIGH); // turn LED on
smartthing.shieldSetLED(0, 0, 1);
smartthing.send(“on”); // send message to cloud
// Serial.println(“on”);
}
void off()
{
stateLED = 0; // set state to 0 (off)
digitalWrite(ledPin, LOW); // turn LED off
smartthing.shieldSetLED(0, 0, 0);
smartthing.send(“off”); // send message to cloud
// Serial.println(“off”);
}
void messageCallout(String message)
{
// if debug is enabled print out the received message
if (isDebugEnabled)
{
Serial.print(“Received message: '”);
Serial.println(message);
}
// if message contents equals to ‘on’ then call on() function
// else if message contents equals to ‘off’ then call off() function
if (message.equals(“on”))
{
on();
}
else if (message.equals(“off”))
{
off();
}
else if (message.equals(“hello”))
{
//hello();
}
}