Martin Koníček

Blog

Connecting the IKEA Parasoll door sensor with Slack

Showcase image

IKEA's New Arrival

When IKEA recently came out with their new Parasoll door and window sensors, I thought, why not play around with it. IKEA products generally have the advantage of being very well-designed, which is given by strong distribution, and as is well known in IT, fixed costs are well spread among a strong user base.

I'll get back to this, but if, for example, the development of a processor costs a billion dollars, and the production of each chip costs ten dollars, then you need to spread that billion among the largest number of units produced. Therefore, generic manufacturers in China usually produce "junk" because they do not have good distribution and when selling low quantities, they are not able to invest as much in R&D (Research and Development) as large multinational corporations.

Therefore, I believe that in IoT devices there are two main players - IKEA and Philips, and to some extent, you can occasionally find something good and cheap from LIDL. Most of these manufacturers use the ZigBee protocol for the communication of these devices, which has low consumption and large range, and in the future will be replaced by the Matter protocol (new DIRIGERA hub from IKEA supports both kinds of protocols). However, this sensor does not support the Matter protocol, so we will be using ZigBee.

For a long time, I was thinking about how to communicate with these devices, my first thought was to use a wrapper over the obsolete IKEA gateway, but this solution did not work very well. It was not until the last LinuxDays that I found out about something called ZigBee2Mqtt, and I was thrilled. So, how does it actually work? With a docker image with ZigBee2Mqtt (which you can install on a Raspberry Pi Zero, for example), you can easily pair devices with the ZigBee protocol using a USB dongle (which can be purchased in Czech specialty shops), with which you can later communicate using a message queue.

Personally, I have a few projects that process messages from ZigBee devices (usually sensors), or even send them to them (usually switches). This can be easily handled in both Python and Javascript (probably also in other languages), as I personally master both languages, so my projects are usually in both, however, the aforementioned project is written in Javascript and uses the Bolt library for communication with Slack. I always generate some basic skeleton of the program using AI (it works relatively reliably), and then manually adjust it according to my needs.

What can the current application do and how is it designed?

I designed the application to send a "door open / door closed" message to a channel on Slack when the sensor is switched on or off, also, you can turn off the sending of messages by typing the word "alarm".

I had a bit of a struggle with the new Bolt framework from Slack, whose documentation is not entirely bad but is also not completely complete and especially lacks a lot of examples, so there was a minor problem figuring out how to do what - but precisely targeted Google queries helped, which located queries of other users on forums or in the issue tracker, and these guided me correctly.

What is also needed is to have the right notifications set up on your phone to alert you to all events with a beep. Even though I have no illusions that the device serves as some perfect alarm - it doesn't (for that you really have to have a paid surveillance center), it can provide you with some minor information, and maybe you can install it in the office of a small company and find out if someone is already at work, or you can connect it to the door of a rack, for example.

This is what the application looks like in Slack.
This is what the application looks like in Slack.

Creating an Application in Slack

The initial creation of an application in Slack is simple, just don't forget anything and don't overlook anything, so I'll guide you through the process easily. The first application can be created at https://api.slack.com/apps. Creating an Application in Slack

Again, the initial creation of an application in Slack is simple, just don't forget anything and don't overlook anything, I'll guide you through the process easily. The first application can be created at https://api.slack.com/apps.

Click on the "Create New App" box.
Click on the "Create New App" box.
Choose to create the application "from scratch" and name it.
Choose to create the application "from scratch" and name it.
For the application, you need to know the "signing secret".
For the application, you need to know the "signing secret".
In "OAuth & Permissions", set the appropriate permissions.
In "OAuth & Permissions", set the appropriate permissions.
And click on "Install to Workspace".
And click on "Install to Workspace".
You should obtain a "Bot Token", which you will use later on.
You should obtain a "Bot Token", which you will use later on.
Don't forget to subscribe to "Event Subscriptions".
Don't forget to subscribe to "Event Subscriptions".
And also turn on "Socket Mode".
And also turn on "Socket Mode".
And note down the "Socket Token".
And note down the "Socket Token".
Finally, in slack in the channel, you'll write the "@" symbol and mention your application, by which you add it to the channel.
Finally, in slack in the channel, you'll write the "@" symbol and mention your application, by which you add it to the channel.

Checklist

  • Create an application
  • Copy "Signing secret"
  • Set "Permissions"
  • Install into Workspace
  • Get "Bot Token"
  • Subscribe to "Event Subscriptions"
  • Note down "Socket Token"
  • Add to the channel

As you can see, creating an application in Slack is quite a complex process, mainly don't forget anything, because then it certainly won't work. After creating the application, you should own 3 tokens, which we will use later in the application.

The actual connection of the sensor

The actual sensor is simply stuck to the door, in my opinion a big advantage of the Ikea Parasoll sensor is the AAA battery used, which powers the sensor, and this is something we don't usually encounter with the competition (for example, a similar sensor in competing products uses smaller button batteries). Also, it is very nice that a red LED light turns on when the sensor status changes. In terms of competition, this is probably the best executed door / window sensor I have come across.

Parasoll sensor mounted on the door, blinks red when the status changes.
Parasoll sensor mounted on the door, blinks red when the status changes.

Zigbee2Mqtt

To connect the sensor to your computer, you need the necessary equipment. Primarily a ZigBee card, I used a Home Assistant SkyConnect USB, which I purchased for around 30 Eur.

When connected to a computer, the card presents itself as a serial port, which has many advantages - for example, you can comfortably share it even into Kubernetes and so on. For the connection, I used a Raspberry Pi Zero 2W priced at around 15 Eur. It's important to note that I highly recommend using a high-performance SD card for IO writes of standard A1 or A2. Personally, I used a SAMSUNG EVO Plus Micro SDXC 128GB priced at around 15 Eur.

Whether you use a Raspberry Pi, your own computer or server, you need to install the Zigbee2Mqtt product. The installation process using Docker is described directly on the product's website in the Getting Started guide. The only thing I need to point out is that on a Raspberry Pi Zero it takes a bit longer, even though the product then runs swiftly (if you are installing Raspbian I recommend turning off the graphical user interface, it speeds things up quite a bit).

Connecting a sensor is relatively simple, click the "Permit join (All)" button which enables pairing for a few minutes and press the pairing button on the Parasoll sensor, and it's done. After pairing, check your logs to make sure you see the correct device events.

Zigbee2Mqtt, To connect the sensor, click the "Permit join (All)" button.
Zigbee2Mqtt, To connect the sensor, click the "Permit join (All)" button.
After pairing, you will see its notification in the "Logs" when the status of the sensor changes, here is just an example with a different sensor.
After pairing, you will see its notification in the "Logs" when the status of the sensor changes, here is just an example with a different sensor.

The Application Itself

The application itself is published on GitHub and is written in JavaScript. By default, it starts with the alarm turned off, and to turn it on you have to check the enable checkbox, and then you start receiving notifications. The new Bolt framework from Slack was used, which, unfortunately, is documented, but the documentation lacks various usage examples, and a lot of research on the internet is needed before you find anything.

For example, writing text into the chat looks like this:

await app.client.chat.postMessage({channel:"home", text:"Alarm started in disabled state, type alarm to change"})

The actual connection of the application to the mqtt server is relatively simple, if you have the mqtt server (e.g., the IP address of the given Raspberry Pi Zero with installed Zigbee2Mqtt running on port 1833) specified in the environment variables, you can connect as follows.

const mqttServer = process.env.MQTT_SERVER;
const mqttTopic = process.env.MQTT_TOPIC;
const mqtt = require('mqtt');
const client = mqtt.connect(mqttServer);

Then you just have to wait for messages from the Parasall sensor, which are sent in the following format.

{"battery":100,"battery_low":false,"contact":false,"linkquality":255,"tamper":false,"update":{"installed_version":16777241,"latest_version":16777241,"state":"idle"}}

And when they are received, print everything into the Slack chat window using the following code.

client.on('message', (topic, message) => {
if (topic === mqttTopic && enabled) {
    const data = JSON.parse(message);
    console.log("Contact: ", data.contact);
    app.client.chat.postMessage({channel:"home", text:`Door ${data.contact ? "closed": "opened"}`})
}

The application itself is simply started after installation.

git clone ...
cd slack-alarm
npm install

With the command:

npm run dev

This, of course, requires that you have correctly filled in environment variables in the .env file (a .env.sample is attached so you know how to do it).

Deployment to Docker / Kubernetes

The application itself has a relatively simple Dockerfile, which I generated using ChatGPT. What you may notice is that I run the application using npm run prod, while when I run it alone, I run it using npm run dev. These commands are defined (and I say this mainly for those who do not have much experience with JavaScript) in the package.json file.

  "scripts": {
    ...
    "dev": "node --env-file .env app.js",
    "prod": "node app.js"

When you look at it, the only difference is that in the case of the dev environment, I use the .env file with variables, and in the case of Kubernetes (the sample deployment is in kuberneters/slack-alarm.yml) I use system variables, which I attach in a ConfigMap.

apiVersion: v1
kind: ConfigMap
metadata:
  name: slack-alarm-config
data:
  SLACK_BOT_TOKEN: "xoxb-"
  SLACK_SIGNING_SECRET: ""
  SLACK_APP_TOKEN: "xapp-1-" 
  MQTT_SERVER: "mqtt://server:port"
  MQTT_TOPIC: "zigbee2mqtt/0xXXXXXX"
---
kind: Deployment
apiVersion: apps/v1
metadata:
  name: slack-alarm
spec:
  replicas: 1
  selector:
    matchLabels:
      app: slack-alarm
  template:
    metadata:
      labels:
        app: slack-alarm
    spec:
      containers:
        - name: slack-alarm
          image: registry/slack-alarm:latest
          envFrom:
            - configMapRef:
                name: slack-alarm-config

Here, I have to admit a bit of a blunder, because I store TOKENs in the ConfigMap instead of in secrets, but I created it quickly, so I didn't bother much with it. Personally, I use my own registries and my own GitHub Workflow Workers (I describe how to use these on my website - Self Hosted GitHub Action Runner on Kubernetes), however, since there's probably nothing particularly private in the Dockerimage, you can also use public docker registries for free. If you would like to prepare your own GitHub Workflow, it might look something like this.


name: Slack-Alarm CI

on:
  push:
    branches: [ "main" ]
    paths:
      - 'Kubernetes/slack-alarm/**'
  pull_request:
    branches: [ "main" ]
    paths:
      - 'Kubernetes/slack-alarm/**'

jobs:
  build-docker-image:
    runs-on: ubuntu-latest
    steps: 
      - name: Docker login
        uses: docker/login-action@v2
        with:
          username: ${{ secrets.DOCKERHUB_USERNAME }}
          password: ${{ secrets.DOCKERHUB_TOKEN }}

      - name: Checkout
        uses: actions/checkout@v3
        
      - name: Build docker image
        run: cd Kubernetes/slack-alarm && docker build . --file Dockerfile --tag ${{ secrets.DOCKERHUB_USERNAME }}/slack-alarm:$(date +%s) --tag ${{ secrets.DOCKERHUB_USERNAME }}/slack-alarm:latest && docker push ${{ secrets.DOCKERHUB_USERNAME }}/slack-alarm --all-tags

I also publish the actual docker image on docker.io/krab55, so you can use it without having to compile anything yourself.

You can very easily install everything as a Docker image on the original Raspberry Pi Zero, but since I used the installation on Kubernetes, I can't provide a manual for this.

Conclusion

The solution itself is more of an inspiration of what is possible and how everything can be connected. I believe many readers will think of some improvements or other uses with different sensors, etc. What I probably struggled with the most was the use of the Bolt framework for Slack, where examples were missing in the documentation, everything else was relatively simple, it just took time to fine-tune it.

For you, there is already a prepared solution that you can put into operation in 30 minutes, and you don't have to worry about anything. You can use it, for example, to track access to the server room and similar. If you have any suggestions for improvements, I will welcome them in the comments.

  • MicroK8S failing with Kustomize
    MicroK8S failing with KustomizeWhen you get an error message error: failed to run '/snap/microk8s/5250/usr/bin/git fetch --depth=1 https://... main': fatal: couldn't find remote ref main this might be a solution
  • cs | en