Friday 30 November 2018

Autogate Adventures: Voice Control via Google Home. Part 2 of 3: ESP8266, MQTT and IFTTT

In Part 1, the autogate became a smarthome device, controlled by voice via my Google Home speaker or Google Assistant on my phone. However every time we went out, it needed four voice commands to open and close the gate.

I can also use an ESP8266 relay board, MQTT and IFTTT like I did for my ancient lantern, but there were a couple of problems. First the MQTT code would stop working after a few days. Secondly I had not figured out how to share the device on Google Home with my wife.

Top: 230Vac to 5V@1A power supply. Bottom: ESP-01S with 1-channel relay adapter

It did not take long to find out why the program stopped running. The routine MQTT_connect() is run in a loop and normally returns non-zero for a valid connection to MQTT server. However if the connection should drop (maybe WiFi interference, power outtage affecting the router, it tries to reconnect 3 times and then goes into an infinite loop waiting for a watchdog timer.

The watchdog timer is enabled by default, and is serviced by various routines in the library, so there is really no good way to use it except as a delayed reset. There is a good article on it here.

  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
    retries--;
    if (retries == 0) {
      // basically die and wait for WDT to reset me
      while (1);
    }
  }

The reason for the failure seems to be mqtt.connect() or perhaps the WiFi router sometimes cannot detect there is no longer a connection. For now the best workaround seems to be to have an active MQTT input, that is to regularly 'publish' to the MQTT broker Adafruit. After a few minutes (normally less than 30) mqtt.connect() will eventually work and the device will reconnect.

Getting Google Home to share the device took a little more time. On the face of it, IFTTT allows me to share: I can publish my Applet for unlimited sharing. But that is too much sharing: letting a random user open my gate from the Internet is a not good idea.

I get my MQTT service from Adafruit, (which IFTTT needs to link the ESP8266 to Google Home) and I can share just my Adafruit feed for the autogate with my wife. Indeed she can activate the autogate from the Adafruit App, but Google Home will not link to a shared feed. Furthermore the Adafruit share turned out to be a global share as well, again an unacceptable security risk.

It turned out that if I got the wife to register with IFTTT and Adafruit, and if I duplicated the ESP8266 code using my wife's Adafruit account and secret key (AIO) the device will support both Adafruit feeds.

Adafruit_MQTT_Client mqtt(&client, AIO_SERVER, AIO_SERVERPORT, AIO_USERNAME, AIO_KEY);
Adafruit_MQTT_Client wife_mqtt(&wife_client, AIO_SERVER, AIO_SERVERPORT, AIO_WIFENAME, AIO_WIFEKEY);

// Setup feeds Adafruit_MQTT_Subscribe lantern = Adafruit_MQTT_Subscribe(&mqtt, AIO_USERNAME"/feeds/frontgate");
Adafruit_MQTT_Subscribe wife_autogate = Adafruit_MQTT_Subscribe(&wife_mqtt, AIO_WIFENAME"/feeds/frontgate");

Converting the Open/Close Google Home commands to autogate pulses is now easy:

while ((subscription = mqtt.readSubscription(2000))) {
    if (subscription == &gate) {
      Serial.print(F("Got: "));
      Serial.println((char *)gate.lastread);
      int gate_State = atoi((char *)gate.lastread);
      Serial.print("Autogate openclose ");
      Serial.println(gate_State);
      digitalWrite(0, 1); // Issue a command to toggle gate
      delay(500);
      digitalWrite(0, 0); // Autogate CPU input is monostable. Issue command to reset  
    }
  }

Tight fit: clockwise from top left: autogate control board, RF remote control module, 12V battery and ESP8266 relay module

Here's a little youtube video of the result.

I am still a little unhappy with it: I would it like to feedback (ie 'publish' in MQTT-speak) actual gate open/close state, and I would have to manually dismantle and reprogram it should my parents come to visit. Also it would be nice to keep a log of the autogate usage, but perhaps that is a future project, an MQTT server. But in the spirit of DevOps, let's just put it up and look for those all-important gotchas that are so critical to a product's eventual success.

There you have it- a voice-controlled autogate. I have not looked very hard, but with a little luck, this should be one of the first homebrew Google Home autogate smart remotes.

Happy Trails.

Thursday 29 November 2018

Autogate Adventures: Voice Control via Google Home. Part 1 of 3: Sonoff Basic

About a year ago I decided to maintain the autogate myself, and naturally could not resist adding a Bluetooth remote function, in addition to its keychain RF remote control. Later I added a Raspberry Pi Zero W IoT gateway, which let me control it from my smartphone. The next step would be to make it a smarthome device - voice control via my Google Home speaker or Google Assistant on my phone.

The obvious way would be to use an ESP8266 relay board, MQTT and IFTTT like I did for my ancient lantern, but there were a couple of problems. First the MQTT code would stop working after a few days. Secondly I had not figured out how to share the device on Google Home with my wife. So I though I would use a commercially-available IoT device, a Sonoff Basic.

Sonoff Basic was RM23 from Lazada
There was no trouble sharing the Sonoff Basic with home members and it was a lot more reliable. I had been using it to control some of the lights in the house. The Basic takes 230Vac input and puts out 230Vac when it turns on. But the autogate needed a dry (ie voltage-free) contact, so I simply added a 230Vac relay , an Omron MY2N.

Omron MY2N 230Vac coil relay, RM10 
I found difficult to mount in the available space in the autogate enclosure, so eventually replaced it with a solid-state relay, the Omron G3TA-IAZR02S.

The OMRON G3TA-IAZR025 was a whopping RM45
Sonoff Basic converted to output dry contact
It worked ... here's a video ... sort of. Trouble was the autogate controller needed a pulse to toggle the gate open and shut. The Sonoff Basic puts out a steady on or off command. Opening the gate was easy:

"OK Google Open autogate"

Now I need to deactivate the signal to the autogate controller, so

"OK Google Close autogate"

But the gate is still open, so now it is time to close it:

"OK Google Open autogate"

And then

"OK Google Close autogate"

It took all of 15 minutes before I got tired of it. I guess it is time for Part 2.