• Blog
  • Research
  • IoT message passing via Jabber/XMPP: Instant Messaging for Bots

    04 February, 2019 | Home Automation

    One of the downsides of not having just one "fit-and-forget" home automation system is that I need to write 'bridge' scripts. For example, my house sensors all communicate just fine on Z-Wave, and I have a central point (a Raspberry Pi running Z-Way) for them to communicate. Likewise, my lights are all Zigbee (because the excellent Philips Hue lights only use Zigbee) so in order to have my garage light come on when I walk into the garage, I need to attach an event handler to the sensor somewhere within the Z-Wave system that calls the Hue bridge, which tells the garage light to come on. It gets more complicated when I've made the system from the ground up, for example, my cabinet lights are all IKEA LED lights controlled via Raspberry Pis - so I need to write all the software to control those intelligently. How do I go about that? Do I have an HTTP server running on the Pi connected to the cabinet lights, and have the sensors call that? Or do I have the Pi continually call the sensors, check their status and change light state accordingly? What if I want a more complicated if-then-else situation... I'd like my cabinet lights to come on if I'm in the house but only the office light is off - but not if all the lights in the house are off because I'm probably in bed. Do I need to have a bit of code running in all these places? What if time is critical; if someone rings my doorbell (which is also a Z-Wave device that I'll detail in a future post) I don't want a notification when the next cron job runs, the person who rang the bell would have given up and gone away by then. And (gulp) what if I need to change something?

    I recently became aware of Errbot. It's a framework, written in Python 3, that makes writing a Jabber bot trivial. To me, this just makes sense for IoT control. XMPP, also known as Jabber, for those who don't know, is basically an open chat protocol. Like Slack or Skype (or MSN or ICQ for the older nerds among us) but just a protocol without an app. The benefit of the open nature of XMPP is that you can run your own server, host your own chat rooms and ensure only you and your bots can access it. But the protocol is open and it's been around long enough that there's a library for it in pretty much every programming language. Google the name of your favourite language with XMPP or Jabber tagged on the end of the search query and I bet you find something.

    Errbot is installable via PIP and very simple to configure. Once you've set up an XMPP server, you can write as many bots as you like, giving each one its own ID, and have it do things. My Z-Wave hub now, rather than doing any complicated logic like "ooh, the garage sensor is triggered, that means I need to tell the Hue to turn the light on..." simply broadcasts a "garage sensor on" message to a chat room on my XMPP server. Anything else (such as the Hue) that might want to act on this will also have a bot in the chat room and can act - or indeed not act - accordingly. I also have a bot for my heating that keeps track of all movement in the house and turns the heating off if it's not seen a motion reading for a while, but turns it back on again if one of the motion sensors trips. Oh, and I also have a bot that sends a generic presence reading to the chat room every minute or so if my phone is connected to the wifi, so the heating can 'detect' that too, so the heating doesn't just go off if I'm not in range of the sensors or haven't moved in a while. It just makes a lot more sense to me, rather than have the office motion sensor say "right, no motion for 10 minutes, I need to turn off the light, and put the screen to low power, and pause the music..." it just says "hey, guys, no movement in the office" and everything else acts on its own accord based on that.

    undefined

    An Errbot bot can do anything Python can do, and be controlled in one of two ways via XMPP - either through passive listening and looking for a particular word or phrase, in a chat room for example, or through direct interaction. So if you wanted to actually override the automatic decisions of your lights controller, you can explicitly tell it "oi, office light, on" without having to work out what turned it off and fix that. Plus it really feeds my worryingly unhealthy god complex to have a bunch of bots under my control that all talk to each other and make decisions, like a mini-society of my own creation :)

    UPDATE 4th March 2019

    My adventures with XMPP for IoT continue, it's come to my attention that you can configure a Raspberry Pi to run Errbot in the background, and on boot, by configuring it as a service. To do this, you just need to write one extra script and put it in the systemd directory. You can customise this process as you need to, but on my RPis, I create a file /etc/systemd/system/errbot.service which looks like this...

    [Unit]
    Description=Start Errbot chatbot
    After=network.service

    [Service]
    Environment="LC_ALL=en_US.UTF-8"
    ExecStartPre=/bin/sleep 60
    ExecStart=/usr/bin/errbot --config /home/pi/errbot/config.py
    WorkingDirectory=/usr/bin/errbot/
    User=pi
    Restart=always
    KillSignal=SIGINT

    [Install]
    WantedBy=multi-user.target

    I should point out - this script is not for production systems that need to be secure! Errbot will run as the pi user, rather than its own user, and it really should be running in a virtualenv or something, not the core system.

    The line beginning ExecStartPre simply makes the bot wait 60 seconds after boot before trying to start. In my experience, you don't need this line on an original Raspberry Pi but you do on a Pi 2 or anything later. A cleaner way of doing this would be to actually work out the boot order and adjust the script accordingly, but this works for me, and I'm lazy.

    Once you've put this script in the systemd directory, you need to run (as root)...

    systemctl enable errbot.service

    From then on you can stop and start the service with

    service errbot stop ; service errbot start