In this article I’ll describe how I created a simple home-brew burglar detection system to send me a mail when someone enters my house (so I can call the police). First my choice for the components is explained. Next how these components combine to achieve the functionality wanted. Based on this article you should be able to avoid certain issues I encountered and have a nice suggestion for a simple relatively cheap burglar detection system.
My purpose was to create a simple security system based on a Raspberry Pi. A Raspberry Pi is a tiny computer which can run a Debian like Linux distribution called Rasbian. I wanted to avoid going to low-level into sensor configuration and programming. That’s why I decided early on to use an extension board and not directly attach the sensors to the Raspberry Pi. I decided to go for the Razberry. I also looked at the GrovePi and Arduino. Both are still too low-level for my tastes though. The Razberry is an extension board for the Raspberry which provides a Z-Wave controller chip. Z-Wave is a wireless protocol popular in the area of home automation. This was an attractive option since if in the future I would want to use additional sensors or maybe even use a commercial home automation system, I could very well get compatibility out of the box. For the sensor, I decided on the Fibaro FGMS-001 Motion Sensor. This is a multi-sensor which allows detection of motion, temperature, luminiscence and vibrations. It can even detect tampering and earthquakes (which is relevant since I live in the Dutch city of Groningen).
Z-Wave.Me (the company providing the Razberry), provides software for the Razberry called Z-Way. There are several alternatives. One of the most popular seems to be Domoticz which is provided with OpenZWave. Domoticz allows quite extensive home automation but I was having difficulty getting the sensor to work with OpenZWave so I decided to go with Z-Way. Z-Way supported the sensor out of the box. With the Z-Way server however it was difficult to automate actions based on sensor values. How I solved this is also described in this article.
How to get the environment up
I started out with a Raspberry which had Rasbian pre-installed. Installing Z-Way was easy. After the installation was completed, I went to https://find.z-wave.me and it indicated my Z-Way server. This allowed me to set the admin password and login. I could access the Z-Way web interface from http://192.168.178.10:8083/smarthome. The expert interface was available at http://192.168.178.10:8083/expert and the API at http://192.168.178.10:8083/ZWaveAPI/Run.
Next I had to add the sensor. The Z-Wave controller and the sensor both need to get to know each other. this is called inclusion. The Z-Way software had a handy wizard to install the Fibaro sensor I bought. The sensor could be opened and the button inside pressed three times. the eye of the sensor would turn blue in order to indicate it was ready for inclusion or exclusion. After the sensor was known to the Z-Wave controller and the Z-Way software, I could start looking at sensor data.
So far pretty straightforward and no coding needed (the installation of the Z-Way software does not count). The motion detection sensor worked nicely. Now on to the not so straightforward part
Send me a mail when someone enters the room
Calling JavaScript from Z-Way
Automating actions based on sensor value changes was not straightforward. Under configuration, there are several apps in Z-Way. One of the apps allows you to load a custom JavaScript file. This file has to be present in your automation folder (/opt/z-way-server/automation) on your Raspberry. The JavaScript file is loaded when the server is started.
In order to debug this Javascript, you can look at /var/log/z-way-server.log on the Raspberry. You can also look at the Event log in the smarthome interface. It helps to have debugPrint statements in your JavaScript code.
When the server is starting, the JavaScript file is loaded. The zway specific classes are not always immediately available yet though. You need the ‘zway’ class to be able to access devices. You need to access the device if you want to act on sensor value changes (bind functions).The solution for this I found here and is as follows:
this.bindFunc1 = function (zwayName) { if (zwayName != "zway") return; // you want to bind to default zway instance var devices = global.ZWave[zwayName].zway.devices; //sensor specific code }; // process all active bindings if (global.ZWave) { global.ZWave().forEach(this.bindFunc1); } // and listen for future ones global.controller.on("ZWave.register", this.bindFunc1);
Call a Python script from JavaScript
Next challenge was calling a Python script from the JavaScript code. Why Python and not JavaScript? Well, I wanted to write files to the file system, send mails and do other things which might be not straightforward in the Google V8 engine which Z-Way uses. Python allows easy independent testing and debugging of a script without having to fiddle with the V8 debugger.
In /opt/z-way-server/automation there is a file called .syscommands. In this files you have to add the commands which are allowed to be executed from JavaScript. In my case I added lines like:
/usr/bin/python /opt/z-way-server/automation/trigger.py
/usr/bin/python /opt/z-way-server/automation/savemeasure.py
The trigger.py script I used for burglar detection and the savemeasure.py I used for temperature, luminescence and battery measures.
In the JavaScript code I could now call these scripts like:
system(‘/usr/bin/python /opt/z-way-server/automation/trigger.py’);
I could also add additional parameters like
system(‘/usr/bin/python /opt/z-way-server/automation/savemeasure.py’ ,’Temperature’,this.value);
Find the sensors
It was nice I could start a JavaScript file and execute Python scripts from it. What I wanted however was to do something when something happened. In order to achieve this, I needed to access my devices.
First I needed to get to obtain information on devices. Z-Way provides a nice API. http://192.168.178.10:8083/ZWaveAPI/Run/devices showed me all the devices. I could also browse the expert interface at http://192.168.178.10:8083/expert (it provided me with more information and control than the smarthome interface). The below locations of the sensors are of course environment specific. It does give you some idea though where to look.
Motion sensor
To access the motion sensor value I could go to
http://192.168.178.10:8083/ZWaveAPI/Run.devices[3].instances[0].commandClasses[48].data[1].level.value
Instead of commandClasses[48] you can also go to SensorBinary
http://192.168.178.10:8083/ZWaveAPI/Run.devices[3].instances[0].SensorBinary.data[1].level.value
(which gave ‘false’ when not triggered)
The available command classes are visible in the expert interface
Battery
The battery was a separate commandClass. The value could be obtained from:
http://192.168.178.10:8083/ZWaveAPI/Run.devices[3].instances[0].Battery.data.last.value
Other sensors
The device contained multiple sensors, the other sensors were available under commandClass 49; sensorMultilevel.
Temperature was available at
http://192.168.178.10:8083/ZWaveAPI/Run.devices[3].instances[0].SensorMultilevel.data[1].val
Luminescence was available at
http://192.168.178.10:8083/ZWaveAPI/Run.devices[3].instances[0].SensorMultilevel.data[3].val
Trigger on change
My JavaScript code ended up looking like:
this.bindFunc1 = function (zwayName) { if (zwayName != "zway") return; // you want to bind to default zway instance var devices = global.ZWave[zwayName].zway.devices; zway.devices[3].instances[0].commandClasses[48].data[1].level.bind(function() { if (this.value == true) debugPrint("Executing trigger"); system('/usr/bin/python /opt/z-way-server/automation/trigger.py'); }); zway.devices[3].instances[0].commandClasses[49].data[1].val.bind(function() { debugPrint("Saving measure"); system('/usr/bin/python /opt/z-way-server/automation/savemeasure.py','Temperature',this.value); }); zway.devices[3].instances[0].commandClasses[49].data[3].val.bind(function() { debugPrint("Saving measure"); system('/usr/bin/python /opt/z-way-server/automation/savemeasure.py','Luminescence',this.value); }); zway.devices[3].instances[0].Battery.data.last.bind(function() { debugPrint("Saving measure"); system('/usr/bin/python /opt/z-way-server/automation/savemeasure.py','Battery',this.value); }); }; // process all active bindings if (global.ZWave) { global.ZWave().forEach(this.bindFunc1); } // and listen for future ones global.controller.on("ZWave.register", this.bindFunc1);
Send a mail and saving measures
I found that making Z-Way API calls from the Python code via HTTP did not work well. My Z-Way server CPU regularly got to 100% and did not respond anymore. It is better to do the triggering from JavaScript and pass values along to the Python script (see savemeasure.py below) to avoid this issue.
trigger.py
My trigger.py script looked like (‘apt-get install python’ first of course to get Python on your Raspberry):
import time import datetime ts = time.time() st = datetime.datetime.fromtimestamp(ts).strftime('%Y-%m-%d %H:%M:%S') def send_email(user, pwd, recipient, subject, body): import smtplib gmail_user = user gmail_pwd = pwd FROM = user TO = recipient if type(recipient) is list else [recipient] SUBJECT = subject TEXT = body # Prepare actual message message = """\From: %s\nTo: %s\nSubject: %s\n\n%s """ % (FROM, ", ".join(TO), SUBJECT, TEXT) try: server = smtplib.SMTP("smtp.gmail.com", 587) server.ehlo() server.starttls() server.login(gmail_user, gmail_pwd) server.sendmail(FROM, TO, message) server.close() print 'successfully sent the mail' except: print "failed to send mail" send_email('xxx@gmail.com','pass','target@mail.nl','Intrusion detected','Intrusion detected at '+st) f = open('/opt/z-way-server/automation/intrusions.log', 'a') f.write(st+"\n") f.close()
Of course do not forget to allow ‘less secure apps’ to access to your GMail account if you use one (see here) or implement mail-server authentication in your script which is considered secure by Google. The result was I got a lot of mails so I turned the mails off but will enable them when I’m out on vacation for example.
savemeasure.py
My save measure.py script looked as followed:
import time import datetime import sys ts = time.time() st = datetime.datetime.fromtimestamp(ts).strftime('%Y-%m-%d %H:%M:%S') f = open('/opt/z-way-server/automation/measure.log', 'a') f.write(st+"\t"+sys.argv[1]+"\t"+sys.argv[2]+"\n") f.close()
Thus I end up here with 2 log files. One for intrusions; intrusions.log (motion detector gets triggered) and the other for sensor values; measure.log.
Finally
It took me about 2 days to get everything working. I encountered several issues. With this article I hope you will be able to get started faster and make the right choices in hard- and software for your home automation system. It was fun though to look into this and get it working.
Maybe in the future I’ll add a button to turn it on and off (and make it really cool!). I’m using the Z-Wave protocol, it should not be difficult to find something to make this possible. Also it would be nice to do something with the earthquake detection and tamper detection.
The next steps are of course to process the sensor data. Stay tuned!
“The next steps are of course to process the sensor data. Stay tuned!”
Have you done anything cool with your data?
Great post by the way, got it to work with my Aeotech multisensor.
To be honest, I haven’t. I was thinking of doing something in the area of machine learning with it but have not found a good use-case. Also our presence at home is not very regular. The weather might be easier to predict.
Next challenge was calling a Python script from the JavaScript code. Why Python and not JavaScript? Well, I wanted to write files to the file system, send mails and do other things which might be not straightforward in the Google V8 engine which Z-Way uses. Python allows easy independent testing and debugging of a script without having to fiddle with the V8 debugger.
Could someone please explain what he is saying here?
Dear Maarten,
This is a very useful article for me because I wanted to do pretty much what you describe, using a Raspberry Pi, Python, a Razberry z-wave controller, Z-way and a Fibaro Motion Sensor. I had not worked out how to get the Motion Sensor PIR to trigger a Python program and your article explained exactly what to do. I did not want to poll the PIR at 1 second intervals to detect it being triggered. I have never used JavaScript before but I edited yours to call my programs, which was easy enough. These programs are in the /PiHome/ folders, not in the /Automation folder. The only difficulty I had was that the z-way Local App “Load custom JavaScript code…” has a field “Z-Way instance for which execute your code” which is in red and is stated as being non-optional. This field has a drop-down box, which is empty, and one can’t type in the field. This confused me! However, the ONLINE App “Load custom JavaScript code” doesn’t have this field, so I used that successfully. Yet when I look at the code in the Active tab (http://192.168.1.10:8083/smarthome/#/apps/instance) the field is present, in red, non-optional, but empty. I assume this is a bug?
For info:
Z-Way Software Information:
Version number: v2.2.2
Compile-ID: d2212e41b6487bf6efe6df730db05571edc64915
Compile-Date: 2016-04-11 11:00:34 +0300
UI:
UI version 1.0.5
Many thanks for publishing your article.
Donald
Hi Maarten,
Interesting read, thanks. I’m running a similar setup at home, but I use pimatic, some random 433 Mhz transceiver parts from eBay and KlikAanKlikUit accessories (motion, switches, outlets, magnet sensors). All works fairly well, but I have some issues with range. Would you be able to comment on range of Z-Wave, preferably in a concrete house? Anyway, nice to see you share your experiences in this area, maybe we can have a chat about it some time in the near future.
Hi Maarten,
I like your work here. Actually I solved in a different way: I’ve used JS app to make a system call to a command which send to me a specific mail with postfix or an sms with gammu. Any way, I’ve used a zway dummy device to program a rule in which I have an and condition with the dummy. So, when dummy is ON, my system is armed, otherwise is OFF. Zway system log reports and stores every values of the sensors.