Showing posts with label JSON over MQTT. Show all posts
Showing posts with label JSON over MQTT. Show all posts

Friday, April 22, 2016

Architecture of my Homy IoT platform

Since I received a lot of questions about the my IoT home control system, here is a description of it.

All the ESPs are sending  MQTT messages to an MQTT broker (I have an ESP8266 acting as a broker) inside the house. The MQTT broker is also bridging all the data to another MQTT broker instance that I have in a cloud.  From now there are two cases:

1. If I am in my WiFi coverage, my mobile app is connecting over the websokets to the MQTT broker and sees all the devices, control them etc.

2. If I am not in my Wifi coverage my mobile app is connecting to the cloud MQTT broker over websockets and sees all the devices, control them etc.

I've chosen to have connection between the mobile application and both MQTT brokers, instead to have one connection to the cloud broker, because if you are at home and your internet connection is down you can not control any device. Having a connection directly to your home MQTT broker is covering this scenario.

The mobile application first is connecting to the local MQTT broker and if is not succeed ( means you are not at home) it connecting to the cloud MQTT broker. This is done automatically and is transparent to the user.

As you can see no port forwarding, nothing to do in your router.

My IoT home control system

Thursday, December 17, 2015

ESP8266 as IR remote control

Today I've managed to make the ESP8266 to work as IR remote control over MQTT for my TV.

Range is now only 1m, but I am planning to increase it. Next step is to update the Android app to support TV, AC etc.

To test the code the JSON can be used:

mosquitto_pub -h broker_ip -p port -t "/62/ir/command" -m  "{\"device_name\":\"ESP_47106\", \"type\":\"ir\", \"value\":\"ON\"}"

Every minute the module will report its status with a JSON over MQTT

{"device_name":"ESP_470106","type":"ir","ipaddress":"192.168.8.150","bgn":3,"sdk":"1.3.0","version":"1","uptime":"1"}


#include <ArduinoJson.h>
#include <ESP8266WiFi.h>
#include <ESP8266mDNS.h>
#include <WiFiUdp.h>
#include <PubSubClient.h>
#include <IRremoteESP8266.h>
#include <Timer.h>

#define PanasonicAddress      0x4004     // Panasonic address (Pre data) 
#define PanasonicPower        0x100BCBD  // Panasonic Power button

#define wifi_ssid "WLAN_62"
#define wifi_password "........"

#define mqtt_server "......."
#define mqtt_user "CATA"
#define mqtt_password "CATA"
#define mqtt_port 1880
#define IR_PIN 14

#define ir_topic "/62/ir/command"
#define device_status_topic "/62/device/status"
// Callback function header
void rx_mqtt_callback(char* topic, byte* payload, unsigned int length);

#define DEBUG false
#define Serial if(DEBUG)Serial
#define DEBUG_OUTPUT Serial

IRsend irsend(IR_PIN); //an IR led is connected to GPIO pin
WiFiClient espClient;
PubSubClient client(mqtt_server, mqtt_port, rx_mqtt_callback,espClient);
Timer t;
StaticJsonBuffer<512> jsonDeviceStatus;
JsonObject& jsondeviceStatus = jsonDeviceStatus.createObject();

char dev_name[50]; 
char json_buffer_status[512];
char my_ip_s[16];

void setup_wifi() 
{
  delay(10);
  // We start by connecting to a WiFi network
  Serial.println();
  Serial.print("Connecting to ");
  Serial.println(wifi_ssid);

  WiFi.mode(WIFI_STA);
  WiFi.begin(wifi_ssid, wifi_password);

  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }

  Serial.println("");
  Serial.println("WiFi connected");
  Serial.println("IP address: ");
  Serial.println(WiFi.localIP());
}

void reconnect() {
  // Loop until we're reconnected
  while (!client.connected()) {
    Serial.print("Attempting MQTT connection...");
    if (client.connect(dev_name, mqtt_user, mqtt_password)) {
      Serial.println("connected");
    } else {
      Serial.print("failed, rc=");
      Serial.print(client.state());
      Serial.println(" try again in 5 seconds");
      // Wait 5 seconds before retrying
      delay(5000);
    }
  }
}

void sendMQTTUpdate()
{
  IPAddress my_ip_addr = WiFi.localIP();
  sprintf(my_ip_s, "%d.%d.%d.%d", my_ip_addr[0],my_ip_addr[1],my_ip_addr[2],my_ip_addr[3]);
  jsondeviceStatus ["device_name"] = dev_name;
  jsondeviceStatus["type"] = "ir"; 
  jsondeviceStatus["ipaddress"] = String(my_ip_s).c_str();
  jsondeviceStatus["bgn"] = 3;
  jsondeviceStatus["sdk"] = ESP.getSdkVersion();//"1.4.0";
  jsondeviceStatus["version"] = "1";
  jsondeviceStatus["uptime"] = "1";//ESP.getVcc();
  
  jsondeviceStatus.printTo(json_buffer_status, sizeof(json_buffer_status));  
  client.publish(device_status_topic, json_buffer_status , false);
  Serial.println(json_buffer_status);

}

void rx_mqtt_callback(char* topic, byte* payload, unsigned int length)
{
  //reserve space for incomming message
  StaticJsonBuffer<256> jsonRxMqttBuffer;
  int i = 0;
  char rxj[256];
  Serial.println(dev_name); Serial.print("Topic:");Serial.println(topic);
  for(i=0;i<length;i++)
  {
    rxj[i] = payload[i];
  }

  Serial.println(rxj);
  JsonObject& root = jsonRxMqttBuffer.parseObject(rxj);
  if (!root.success())
  {
    Serial.println("parseObject() failed");
    return;
  }

  const char* device_name  = root["device_name"];
  const char* type         = root["type"];
  const char* value        = root["value"];

  Serial.println(device_name); 
  Serial.println(type); Serial.println(value);

  //if( (type == "ir") && ((value == "ON") || (value == "OFF")))
  //{
   /* DO A SANITIZE ON THE MESSAGE AND IF IS CLEAN SEND IR*/
       sendIR();
  //} 
  Serial.println("<=rx_mqtt_callback");
  return;
}

void sendIR()
{
    int i = 0;
    Serial.print("sendIR for 2 sec");
    for(i=0;i<20; i++)
    {      
      irsend.sendPanasonic(PanasonicAddress,PanasonicPower); // This should turn your TV on and off
      delay(100);
    }
}
void setup() 
{
  delay(1000);
  irsend.begin();
  Serial.begin(115200); 
  sprintf(dev_name, "ESP_%d", ESP.getChipId());
  setup_wifi();
  client.setServer(mqtt_server, 1880);
  client.connect(dev_name, mqtt_user, mqtt_password);
  client.subscribe(ir_topic);
  if (!client.connected()) 
  {
    reconnect();
  }
  t.every(60 * 1000 , sendMQTTUpdate);
  
}

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


https://github.com/bcatalin/ESP8266-Infrared-Panasonic/

Monday, August 3, 2015

ESP8266 conclusions after 8 month




After 8 month of working with ESP8266 I think I made an impression on this tiny wireless chip.

- It is robust ( no crashes, disconnects etc)
- can be put in low power mode ( ~100 days on three AA with reading a value a every 10 minutes and publish it on a remote server)
- the chip producer, EspressIf, is very involved in adding more features and correcting small bugs ( documentation is still on ice age, but I hope that they will makeit more clear)
- can be interconnected with various sensors
- run in non demanding conditions ( I have one module that is running in 70% humidity and 50 to 60 Celsius )

Until now I have ESP8266 modules that are connected with temperature and humidity sensors and relays. Next devices: barometric pressure, scale, IR LED. 

The modules are sending MQTT to my broker ( hosted on a PogoPlug and some time on Raspberry Pi) that is connected to my cloudMQTT.com (they run a great MQTTservice) account were I have another MQTT broker. ( they are bridged). 

In this way, from my mobile application, I can control and see my modules anywhere in the word. 

If I am not at home, my application connects to my cloud broker that is connecting to my home broker where are connected my devices. In this way I can monitor and send them commands.

If I am at home my application is connecting to my local broker ( to avoid high RTD - which are not so high, something like 500 ms).

In conclusion, ESP8266EX is doing a great job, you can invest money and time in it.

Happy coding !!! 

Tuesday, June 2, 2015

Android application Homy

The new Android application that is connecting with my broker over web sockets is having now new features:

1. Auto-discovery. Each time the application is started, all devices are sending their status. Here there are 6 IoT devices discovered:

  • two plugs
  • two irritool ( one is in production for more then one month, and the other is for debugging and simulation ( NASA style :-)  )
  • two (dth - digital temperature and humidity sensors. They are mount on each irritool)


6 devices dicovered



2. Devices are presented on categories, based on the incoming  data from them. 
At  this stage the name is based on the unique device id and its type.

Plug devices discovered

3. Device detail. All the information about device is presented in here:
-device id
-ip address
-network type (B/G/N)
-up time ( if is configured to be transmitted)
and I am able to control the device ( like in plug/irritool case) or see the data for sensors.
Device detail - PLUG
Device detail - IRRITOOL 

Device detail - Sensor DTH


Looks ugly and hard to remember that the ESP_00A08478 is the name for irrigation controller so I've added the new option to rename the device name with whatever you want. This aliasing is persistent so every time I reopen the application, the mapping between device id and device alias is the same.


Here is a renamed plug:


Plug renamed 

Other feature is 7 day weather report for my location (need more work in presenting the data).

weather report next 7 days


I can declare now the application to be in alpha stage ....


4.Other option I have in the Menu:



Debug will be to see the messages received from broker.




There are a lot of picture in this post, but a picture is 1000 words.







Monday, April 20, 2015

First IoT device - Plug

Because was raining outside and I couldn't work in the backyard, I've made rapidly an IoT plug with ESP8266 .

Donor for the case was a timer plug that was in the house. After I've removed its content, I've added my stuff.

IoT plug
Inside the case I have:

  • power supply (220V-3v3 1A)
  • 5V relay ( is working fine on 3.3 V)
  • ESP-01 covered in blue tape 
And the final IoT plug:

IoT final plug



The ESP-01 is accepting JSON over MQTT from my mosquitto broker. 

To control the plug from my phone, I've created an android application that connects over
websockets to mosquitto broker and is sending commands. 

Plug is sending status every 15 seconds to its subscribers and a status after every command its receiving.

Cool.....now I can turn on or off  my  lamp with my IoT device. 

For Android application I've used for rapid development a template, but I am planning to build a totally new application that will discover the IoT devices and add them automatically to the control screen.



IoT Plug application
EDIT: The Android application is different now. See this post.

And a video: