Apple HomeKit on iOS with Arduino (ESP8266) through Raspberry Pi – Part 2

Apple HomeKit on iOS with Arduino (ESP8266) through Raspberry Pi

Part 1 of this article explained how to install a HomeKit server on a Raspberry Pi. This will allow you to add new, DIY accessories that can receive commands from Siri.

Part 2 (this article) explains how to install an MQTT server that can be a “bridge” between Siri (through you HomeKit server) and you hardware.

IoT Part 2

MQTT is a communication protocol that will let you send and receive simple messages from one computer to another. You need one server a a number of clients. We will setup the server on our Raspberry Pi, but there are servers available publicly.

Install the MQTT server: Mosquitto

There are other MQTT servers available but this one works well and is easy to install.

sudo wget http://repo.mosquitto.org/debian/mosquitto-repo.gpg.key
sudo apt-key add mosquitto-repo.gpg.key
cd /etc/apt/sources.list.d/
sudo wget http://repo.mosquitto.org/debian/mosquitto-wheezy.list
sudo apt-get update
sudo apt-get install mosquitto

This will add the mosquitto repo to your list, then the last instruction actually uses the standard apt-get install.

Next,  install the Mosquitto clients to test your server (if you want). They are the actual commands to use your Raspberry Pi as an MQTT client.

sudo apt-get install mosquitto-clients

This link has many good pointers to configure the Mosquitto server to start and stop as a service, but this simple installation will be ok for testing.

Let’s test our mosquitto server. Open a new terminal window on your Raspberry Pi (or an SSH session if you are accesing it remotely) and type

mosquitto_sub -d -t hello/world

This will “subscribe” to the “hello” topic (-t), “world” sub-topic on your server (localhost). This can be ANYTHING you want. There is no real format and the / or /’s are optional.  The terminal will be executing MQTT in “subscribe” (think if it as “receive” or “listen”) mode and will just wait for the proper incoming message, meaning with the proper topic.

Now we need to publish a message (-m) on the same topic (-t), but in a new terminal window (or SSH session):

mosquitto_pub -d -t hello/world -m "Hello from Terminal window 2!"

The first window should show the message

Client mosqsub/12234-raspberry received PUBLISH (d0, q0, r0, m0, 'hello/world', ... (29 bytes))
Hello from Terminal window 2!

In my environment, I have one MQTT server on a Raspberry Pi and messages coming and going from other Raspberry Pis and sensor equipped Arduinos.

A particular device can send or receive MQTT messages and can also do both at the same time.

EPS8266 Fifi Micro-controller

For this article, I’m using an Arduino type of micro-controller that has a Wifi stack. Someone has written an Arduino library that handles MQTT communications, and being Wifi, this Arduino also has a Wifi library taking care of communications.

I’m using an Adafruit Huzzah ESP8266 micro controller. It has Wifi on board and is compatible with the Arduino environment. It’s not strictly an arduino, and the processor is not the typical Atmel 328, but Adafruit has written everything you need to program it from the Arduino IDE. Any wifi-enabled Arduino could be used, but the the ESP8266 is dirt cheap (10$) and is very compact. Please use the link above to learn how to dowload the appropriate Arduino library and run some tests for Wifi connections.

Now, let’s test the ESP8266 with a simple sketch that will send a message on the topic “/hello”. The message is “world” and is sent every minute. The sketch will also listen to the topic “hello/world” and print incoming messages. So if everything goes well, it will print the message it just sent to the MQTT server!

/*
  Basic ESP8266 MQTT example

  This sketch demonstrates the capabilities of the pubsub library in combination
  with the ESP8266 board/library.

  It connects to an MQTT server then:
  - publishes "hello world" to the topic "outTopic" every two seconds
  - subscribes to the topic "inTopic", printing out any messages
    it receives. NB - it assumes the received payloads are strings not binary
  - If the first character of the topic "inTopic" is an 1, switch ON the ESP Led,
    else switch it off

  It will reconnect to the server if the connection is lost using a blocking
  reconnect function. See the 'mqtt_reconnect_nonblocking' example for how to
  achieve the same result without blocking the main loop.

  To install the ESP8266 board, (using Arduino 1.6.4+):
  - Add the following 3rd party board manager under "File -> Preferences -> Additional Boards Manager URLs":
       http://arduino.esp8266.com/stable/package_esp8266com_index.json
  - Open the "Tools -> Board -> Board Manager" and click install for the ESP8266"
  - Select your ESP8266 in "Tools -> Board"

*/

#include <ESP8266WiFi.h>
#include <PubSubClient.h>

// Update these with values suitable for your network.

const char* ssid = "default";
const char* password = "leborddulac";
const char* mqtt_server = "192.168.2.180";
const char* host = "hello/world"; //used to identify topic. This is the string of
//  characcters used in the *_accessory.js file to identify the topic

WiFiClient espClient;
PubSubClient client(espClient);
long lastMsg = 0;
char msg[50];
int value = 0;

void setup() {
  pinMode(BUILTIN_LED, OUTPUT);     // Initialize the BUILTIN_LED pin as an output
  digitalWrite(BUILTIN_LED, HIGH); // ...and turn if off (reversed logic for the esp8266)
  Serial.begin(115200);
  setup_wifi();
  client.setServer(mqtt_server, 1883); //connect to the mqtt server at address above
  client.setCallback(callback);
}

void setup_wifi() {

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

  WiFi.begin(ssid, 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 callback(char* topic, byte* payload, unsigned int length) {
 Serial.print("Message arrived [");
 Serial.print(topic);
 Serial.print("] ");
 String mypayload = " ";
 for (int i = 0; i < length; i++) {
 Serial.print((char)payload[i]);
 mypayload[i] = (char)payload[i];
 }
 Serial.print(" Payload: ");
 Serial.print(mypayload);
 Serial.println();
 String mytopic = String(topic);
 if (mytopic == host) { // Is this the right Topic?
 // Switch on the LED if the payload in "on"
 //if ((char)payload[1] == 'n') { if (mypayload == statusOn) {
 if (mypayload == statusOn) {
 digitalWrite(BUILTIN_LED, LOW); // Turn the LED on (Note that LOW is the voltage level
 // but actually the LED is on; this is because
 // it is acive low on the ESP-01)
 //client.publish(host, "Powered");
 } else {
 digitalWrite(BUILTIN_LED, HIGH); // Turn the LED off by making the voltage HIGH
 //client.publish(host, "NOTPowered");
 }
 }
}

void reconnect() {
 // Loop until we're reconnected
 while (!client.connected()) {
 Serial.print("Attempting MQTT connection...");
 // Attempt to connect
 if (client.connect("ESP8266Client")) {
 Serial.println("connected");
 // Once connected, publish an announcement...
 client.publish("outTopic", "hello world");
 // ... and resubscribe
 client.subscribe("#");
 } else {
 Serial.print("failed, rc=");
 Serial.print(client.state());
 Serial.println(" try again in 5 seconds");
 // Wait 5 seconds before retrying
 delay(5000);
 }
 }
}

void loop() {

 if (!client.connected()) {
 reconnect();
 }
 client.loop();

 long now = millis();
 if (now - lastMsg > 60000) {
 lastMsg = now;
 ++value;
 snprintf (msg, 75, "hello world #%ld", value);
 Serial.print("Publish message: ");
 Serial.println(msg);
 client.publish("outTopic", msg);
 }
}

Once you ESP8266 is communicating with your MQTT server, most of the hard work is done. You now have an Arduino type micro-controller linked to your MQTT network.

You could decide to go no further and not link this to HomeKit and Siri. In fact, most of my sensors use MQTT to communicate together on my Wifi network, and these sensors are connected to Arduino, Raspberry Pi and other computers. In a future article, I will talk about HomeKit in more details, and eventually I will explain my node-red setup and interface.

This entry was posted in Arduino, Electronics. Bookmark the permalink.

3 Responses to Apple HomeKit on iOS with Arduino (ESP8266) through Raspberry Pi – Part 2

  1. homekit says:

    Part 3 coming soon?

Leave a Reply

Your email address will not be published. Required fields are marked *