SMS and Email Notifications

Discussions about RaZberry - Z-Wave board for Raspberry computer
Zway424
Posts: 36
Joined: 26 Aug 2015 04:40

SMS and Email Notifications

Post by Zway424 »

I'm a newbie and would like to know how do I receive SMS and/or email notifications from Z-way after an event has occurred (e.g. Z wave door sensor is activated and SMS and/or email is sent to notify that event occured)? Please include all files/folders that need to be modified and all URL commands that would need to be issued. Examples source code would be very helpful.

Thanks!
AlphaX2
Posts: 110
Joined: 25 Jul 2015 15:03

Re: SMS and Email Notifications

Post by AlphaX2 »

Hi,

in the Z-Way software itself, there are some "apps" to do this, but just with sms.ru (which seems not to send SMS in all countries). So I'm writing for my case(s) a python script. It's not finished yet, but will soon. It's using Google Mail to send emails (created new account) and Mobilant.com for SMS service. Mobilant offers some SMS for free, but is a paid service, but fastest SMS type is just ~ 8€ent.

Maybe it's an option for you? I could post the script here if you wish! Should be easy to modify mail part (if you don't want to use Google), if you want to use another SMS service it should support sending via http requests/http API. Makes changes easier. :)

AlphaX2
Zway424
Posts: 36
Joined: 26 Aug 2015 04:40

Re: SMS and Email Notifications

Post by Zway424 »

Hi,

I would definitely be interested in viewing your python source code when it's complete. I've been using the "app" in the Z-way software for email, however it only sends the email to mandrillapp server. I'm unable to view these emails on an iOS device. Gmail would be much better option for receiving email notifications. Any info is appreciated.

Thanks!
AlphaX2
Posts: 110
Joined: 25 Jul 2015 15:03

Re: SMS and Email Notifications

Post by AlphaX2 »

Hi again,

as I said, my Python script is finished to a point I think it's okay. Not perfect, but working as it should! :)

Code: Select all

#!/usr/bin/env python3
# -*- coding: utf-8 -*-

import os
import sys
import json
import time
import smtplib

import requests



### script properties ###
# edit the data after ":" to fit your case

p = {"RASP_IP": "192.168.1.121",    # IP Adress of your Raspberry PI
    "RASP_PORT": "8083",            # Z-Way standard port is 8083
    "LOGIN": "Z-Way-User",          # Your Z-Way Account name
    "PWD": "Password2000!",         # Your Z-Way Account password
    "DEVICES": ["DummyDevice_14"],  # All devices you want a notify message from: ["Device1", "Device2", ... ]
    "LEVEL": "on",                  # The status that triggers the notification - same for ALL devices!
    
    "MAIL": "my_zway_mail@gmail.com", # the (Google) mail you want to send from
    "MAIL_PWD": "my_zway_mail_pw",    # the (Google) mails account password
    
    "MAIL_TO": ["send_me@notification.com", "also_send@here.com"], # recipients you want to send the message
    "SUBJECT": "Z-Way SmartHome: Smoke detection warning!",        # subject text of notify message
    "BODY_TEXT": "Warning: {0} triggered at {1} the smoke alarm!", # text of the mail, {0} and {1} must be there, they will be replaced with device name and time! 
    
    "MOBILANT_KEY": "xxxxxxxxxxxxxxxxxxxxxxx",  # the API key you can find at Mobilant.com
    "PHONE_NUMBERS": ["0049162123456789"],      # the number(s) ["123","132",...] you want to send a message / None means no sms notification
    "MOBILANT_SMS_ROUTE": "directplus"}         # which route should be used (see Mobilant.com for details)


##### DON NOT EDIT BEYOND THIS POINT #####

class ZWayScript:    
    def __init__(self):
        
        # get pid of this script, write a pid file
        self.PID = os.getpid()
        self.FILE_NAME = os.path.basename(sys.argv[0])
        self.PID_FILE = "pid_{0}_{1}".format(self.FILE_NAME, time.strftime("%d.%m.%Y_%H.%M.%S"))

        with open(self.PID_FILE, "w") as f:
            f.write(str(self.PID))
            f.close()

        # ZWAY API CONFIG
        self.SERVER = "http://{0}:{1}".format(p["RASP_IP"], p["RASP_PORT"])

        print(self.SERVER)
        
        self.API = "/ZAutomation/api/v1"
        self.SESSION = requests.Session()

        # ZWAY CONFIG
        self.ZWAY_LOGIN = p["LOGIN"] 
        self.ZWAY_PWD = p["PWD"]
        self.ZWAY_DEVICES = p["DEVICES"]
        self.ZWAY_DEVICE_LEVEL = p["LEVEL"]
                    
        # MAIL CONFIG
        self.MAIL_FROM = p["MAIL"] 
        self.MAIL_FROM_PWD = p["MAIL_PWD"] 
        self.MAIL_TO = p["MAIL_TO"]
        self.MAIL_TO_SUBJECT = p["SUBJECT"]
        self.MAIL_TO_BODY_TEXT = p["BODY_TEXT"]

        # SMS CONFIG
        self.MOBILANT_KEY = p["MOBILANT_KEY"]
        self.PHONE_NUMBERS = p["PHONE_NUMBERS"]
        self.MOBILANT_ROUTE = p["MOBILANT_SMS_ROUTE"]

        
    def login(self):
        # create session and login, Requests remembers the login data for the session
        login_url = self.SERVER+self.API+"/login"

        print(login_url)
        
        payload = {"form":True, 
                   "login":self.ZWAY_LOGIN, 
                   "password":self.ZWAY_PWD, 
                   "keepme":False, 
                   "default_ui":1}
        headers = {"Accept": "application/json", 
                   "Content-Type": "application/json"}   
        auth_r = self.SESSION.post(login_url, 
                                   headers=headers, 
                                   data=json.dumps(payload))
        print("Login-Response:", auth_r.status_code)


    def run(self):
        while True:
            lc = time.localtime()

            devices_r = self.SESSION.get(self.SERVER+self.API+"/devices")
            print("Devices-Response:", devices_r.status_code)
            devices = devices_r.json()

            # looking for relevant data
            for d in devices["data"]["devices"]:

                # Status of the device (fire alarm/switch/fake device)
                if d["id"] in self.ZWAY_DEVICES:
                    device_status = d["metrics"]["level"]
                    device_name = d["metrics"]["title"]
                    
                    print("Device status:", str(device_status))

                    if str(device_status) == self.ZWAY_DEVICE_LEVEL:
                        # email notification
                        if self.MAIL_FROM:
                            self.send_mail_notification(device_name)
                        else:
                            print("WARNING: No mail to send from - can't send a mail!!!")

                        # sms notification
                        if self.PHONE_NUMBERS and len(self.PHONE_NUMBERS) >= 1:
                            self.send_sms_notification(device_name)
                        else:
                            print("WARNING: No phone number - will not send SMS!")

            # check the status all 10 sec.
            time.sleep(10)


    def send_mail_notification(self, name):
    
        print("Try to send a mail from: {0} to {1}!".format(self.MAIL_FROM, self.MAIL_TO))
    
        # while loop trigger for sending mails
        SEND_DONE = False

        # create header and body
        header = "From: {0}\n".format(self.MAIL_FROM)
        header += "To: {0}\n".format(self.MAIL_TO)
        header += "Subject: {0}\n\n".format(self.MAIL_TO_SUBJECT)
        body = self.MAIL_TO_BODY_TEXT.format(name, 
                                             time.strftime("%d.%m.%Y %H:%M:%S"))
        msg = header+body

        # send mail
        print("Try to send...")
        while not SEND_DONE:
            try:
                s = smtplib.SMTP(host="smtp.gmail.com", port=587)
                s.ehlo()
                s.starttls()
                s.login(self.MAIL_FROM, self.MAIL_FROM_PWD)        
                s.sendmail(self.MAIL_FROM, self.MAIL_TO, msg)
                s.quit()
                SEND_DONE = True
                print("Mail was send!")
                break
            except:
                # print all error messages
                e = sys.exc_info()[0]
                print(e)


    def send_sms_notification(self, name):

        for number in self.PHONE_NUMBERS:
            print(number)
            print("Try to send a SMS to number: {0}".format(number))
            sms_msg_text = self.MAIL_TO_BODY_TEXT.format(name,
                                                         time.strftime("%d.%m.%Y %H:%M:%S"))
            sms_msg_text = sms_msg_text.replace(" ", "+")
            sms_send_url = "http://gw.mobilant.net/?key={0}&to={1}&message={2}&route={3}".format(self.MOBILANT_KEY,
                                                                                                 number,
                                                                                                 sms_msg_text,
                                                                                                 self.MOBILANT_ROUTE)
            if self.MOBILANT_ROUTE == "lowcostplus" or self.MOBILANT_ROUTE == "directplus":
                sms_send_url += "&from=RaZberry"

            print(sms_send_url)

            self.SESSION.get(sms_send_url)


if __name__ == "__main__":    
    zs = ZWayScript()
    zs.login()
    zs.run()
Installation and preperations:
  • Step 1: Create a directory in your Home folder (optional) could also put there directly.

    Step 2: Download the latest "requests" Python module from: GitHub. The version in Raspberry repos is very/toooo old.

    Step 3: Put the "requests" folder from downloaded "requests-master.zip" in your folder from Step 1.

    Step 4: Save the code above to a file with a name you like with *.py extension. For example: "zway_email_notification.py". Save the file in the folder from Step 1.

    Step 5: Edit the script with your data on lines: 17-33 to fit your needs.
Informations:
The device name can be found by clicking on the gears in the normal Z-Way UI.

As I said, it uses Google Mail (it's possible to use the receiver as the sender), and Mobilant.com for SMS support. Please note that SMS support is just working when your Raspberry Pi is online, it can't replace mail in case of internet connection problems! If you don't want SMS support just edit line #32: "PHONE_NUMBERS": None.

You can fill in a list of devices, mails and phone numbers to get notifications from/to. But (at the moment) you can just fill in one "level". So you can get notification, from 10 devices, if all of them have level "on", for example Alarms or Switches. So you could fill in all your Smoke detectors and "on" as the trigger for a notification.

What kind off level your device is reporting, can be easily checked by looking in the API response:
http://<RASPBERRY_IP>:8083/ZAutomation/api/v1/devices
How to run the script:
Now you can run the script with:
python3 /path/to/the/file/name.py
You can also edit your crontab to start the script on Raspberry boot, by adding the following line:
@reboot python3 /path/to/the/file/name.py &

If you have any questions, feel free to ask! :)

Thanks,

AlphaX2
Last edited by AlphaX2 on 14 Sep 2015 23:11, edited 1 time in total.
Zway424
Posts: 36
Joined: 26 Aug 2015 04:40

Re: SMS and Email Notifications

Post by Zway424 »

Thank you for your response! I will try this soon!
brun368
Posts: 14
Joined: 12 Sep 2015 01:49

Re: SMS and Email Notifications

Post by brun368 »

Thanks for that script. It was a big help for me as a beginner.

The google server isn't working because google ignores this "unsafe application".
I changed it to gmx.net

To start the script @reboot i added 10 sec sleep time at the beginning because the script started already without the z-way server being up. In that case the script didn't work.

I also change the mail notification, that only the change to the defined state forces a mail notification.
eg. off -> on

Code: Select all

#!/usr/bin/env python3
# -*- coding: utf-8 -*-

import os
import sys
import json
import time
import smtplib

import requests



### script properties ###
# edit the data after ":" to fit your case

p = {"RASP_IP": "192.168.1.121",    # IP Adress of your Raspberry PI
    "RASP_PORT": "8083",            # Z-Way standard port is 8083
    "LOGIN": "Z-Way-User",          # Your Z-Way Account name
    "PWD": "Password2000!",         # Your Z-Way Account password
    "DEVICES": ["DummyDevice_14"],  # All devices you want a notify message from: ["Device1", "Device2", ... ]
    "LEVEL": "on",                  # The status that triggers the notification - same for ALL devices!
    
    "MAIL": "my_zway_mail@gmail.com", # the (Google) mail you want to send from
    "MAIL_PWD": "my_zway_mail_pw",    # the (Google) mails account password
    
    "MAIL_TO": ["send_me@notification.com", "also_send@here.com"], # recipients you want to send the message
    "SUBJECT": "Z-Way SmartHome: Smoke detection warning!",        # subject text of notify message
    "BODY_TEXT": "Warning: {0} triggered at {1} the smoke alarm!", # text of the mail, {0} and {1} must be there, they will be replaced with device name and time! 
    
    "MOBILANT_KEY": "xxxxxxxxxxxxxxxxxxxxxxx",  # the API key you can find at Mobilant.com
    "PHONE_NUMBERS": ["0049162123456789"],      # the number(s) ["123","132",...] you want to send a message / None means no sms notification
    "MOBILANT_SMS_ROUTE": "directplus"}         # which route should be used (see Mobilant.com for details)


##### DON NOT EDIT BEYOND THIS POINT #####

class ZWayScript:    
    def __init__(self):
        
        # get pid of this script, write a pid file
        self.PID = os.getpid()
        self.FILE_NAME = os.path.basename(sys.argv[0])
        self.PID_FILE = "pid_{0}_{1}".format(self.FILE_NAME, time.strftime("%d.%m.%Y_%H.%M.%S"))

        with open(self.PID_FILE, "w") as f:
            f.write(str(self.PID))
            f.close()

        # ZWAY API CONFIG
        self.SERVER = "http://{0}:{1}".format(p["RASP_IP"], p["RASP_PORT"])

        print(self.SERVER)
        
        self.API = "/ZAutomation/api/v1"
        self.SESSION = requests.Session()

        # ZWAY CONFIG
        self.ZWAY_LOGIN = p["LOGIN"] 
        self.ZWAY_PWD = p["PWD"]
        self.ZWAY_DEVICES = p["DEVICES"]
        self.ZWAY_DEVICE_LEVEL = p["LEVEL"]
        self.ZWAY_DEVICE_LEVEL_OLD =p["LEVEL"]
                    
        # MAIL CONFIG
        self.MAIL_FROM = p["MAIL"] 
        self.MAIL_FROM_PWD = p["MAIL_PWD"] 
        self.MAIL_TO = p["MAIL_TO"]
        self.MAIL_TO_SUBJECT = p["SUBJECT"]
        self.MAIL_TO_BODY_TEXT = p["BODY_TEXT"]

        # SMS CONFIG
        self.MOBILANT_KEY = p["MOBILANT_KEY"]
        self.PHONE_NUMBERS = p["PHONE_NUMBERS"]
        self.MOBILANT_ROUTE = p["MOBILANT_SMS_ROUTE"]

        
    def login(self):
        # create session and login, Requests remembers the login data for the session
        login_url = self.SERVER+self.API+"/login"

        print(login_url)
        
        payload = {"form":True, 
                   "login":self.ZWAY_LOGIN, 
                   "password":self.ZWAY_PWD, 
                   "keepme":False, 
                   "default_ui":1}
        headers = {"Accept": "application/json", 
                   "Content-Type": "application/json"}   
        auth_r = self.SESSION.post(login_url, 
                                   headers=headers, 
                                   data=json.dumps(payload))
        print("Login-Response:", auth_r.status_code)


    def run(self):
        while True:
            lc = time.localtime()

            devices_r = self.SESSION.get(self.SERVER+self.API+"/devices")
            print("Devices-Response:", devices_r.status_code)
            devices = devices_r.json()

            # looking for relevant data
            for d in devices["data"]["devices"]:

                # Status of the device (fire alarm/switch/fake device)
                if d["id"] in self.ZWAY_DEVICES:
                    device_status = d["metrics"]["level"]
                    device_name = d["metrics"]["title"]
                    
                    print("Device status:", str(device_status))
                    if str(device_status) != self.ZWAY_DEVICE_LEVEL_OLD:
                        self.ZWAY_DEVICE_LEVEL_OLD = "none"
                    
                    if str(device_status) == self.ZWAY_DEVICE_LEVEL and str(device_status) != self.ZWAY_DEVICE_LEVEL_OLD:
                        self.ZWAY_DEVICE_LEVEL_OLD = str(device_status)
                        # email notification
                        if self.MAIL_FROM:
                            self.send_mail_notification(device_name)
                        else:
                            print("WARNING: No mail to send from - can't send a mail!!!")

                        # sms notification
                        if self.PHONE_NUMBERS and len(self.PHONE_NUMBERS) >= 1:
                            self.send_sms_notification(device_name)
                        else:
                            print("WARNING: No phone number - will not send SMS!")
            
            # check the status all 10 sec.
            time.sleep(10)


    def send_mail_notification(self, name):
    
        print("Try to send a mail from: {0} to {1}!".format(self.MAIL_FROM, self.MAIL_TO))
    
        # while loop trigger for sending mails
        SEND_DONE = False

        # create header and body
        header = "From: {0}\n".format(self.MAIL_FROM)
        header += "To: {0}\n".format(self.MAIL_TO)
        header += "Subject: {0}\n\n".format(self.MAIL_TO_SUBJECT)
        body = self.MAIL_TO_BODY_TEXT.format(name, 
                                             time.strftime("%d.%m.%Y %H:%M:%S"))
        msg = header+body

        # send mail
        print("Try to send...")
        while not SEND_DONE:
            try:
                s = smtplib.SMTP(host="mail.gmx.net", port=587)
                s.ehlo()
                s.starttls()
                s.login(self.MAIL_FROM, self.MAIL_FROM_PWD)        
                s.sendmail(self.MAIL_FROM, self.MAIL_TO, msg)
                s.quit()
                SEND_DONE = True
                print("Mail was send!")
                break
            except:
                # print all error messages
                e = sys.exc_info()[0]
                print(e)


    def send_sms_notification(self, name):

        for number in self.PHONE_NUMBERS:
            print(number)
            print("Try to send a SMS to number: {0}".format(number))
            sms_msg_text = self.MAIL_TO_BODY_TEXT.format(name,
                                                         time.strftime("%d.%m.%Y %H:%M:%S"))
            sms_msg_text = sms_msg_text.replace(" ", "+")
            sms_send_url = "http://gw.mobilant.net/?key=ENVfJAybda3bd739rxJgmAU&to={0}&message={1}&route={2}".format(number,
                                                                                                                     sms_msg_text,
                                                                                                                     self.MOBILANT_ROUTE)
            if self.MOBILANT_ROUTE == "lowcostplus" or self.MOBILANT_ROUTE == "directplus":
                sms_send_url += "&from=RaZberry"

            print(sms_send_url)

            self.SESSION.get(sms_send_url)


if __name__ == "__main__":    
    time.sleep(10)
    zs = ZWayScript()
    zs.login()
    zs.run()
AlphaX2
Posts: 110
Joined: 25 Jul 2015 15:03

Re: SMS and Email Notifications

Post by AlphaX2 »

Hey,

thanks for the reply. As I said it's not perfect at the moment. In my case I use a extra Gmail adress, so I allowed unsafe applications. This startup bug did not happen for me, but I'll check again, maybe the best solution would be a check that z-way-server is found running. The point with the trigger is a bit complicated, I've seen already devices with "update" as status, so I check explicit the level.

But I thought also about some trigger, atm in my latest version I use a longer sleep of 120s after sending message, to prevent mail/sms bombing. :-) Should be enough time to switch off the device, but is not the best solution for window/door devices for example.

Hope we can tune it a bit more together. ;-)

AlphaX2
pofs
Posts: 688
Joined: 25 Mar 2011 19:03

Re: SMS and Email Notifications

Post by pofs »

I'm pretty sure sending sms can be easily done from JS without calling external python script. Look at http.request() in developer manual.
This would allow direct access to devices, and you won't need to check whether ZWay is running.
AlphaX2
Posts: 110
Joined: 25 Jul 2015 15:03

Re: SMS and Email Notifications

Post by AlphaX2 »

pofs wrote:I'm pretty sure sending sms can be easily done from JS without calling external python script. Look at http.request() in developer manual.
This would allow direct access to devices, and you won't need to check whether ZWay is running.
Sure this is also a solution doing it. But I was coding in Python and I thought about SMS sending, my first idea was to use an Mail2SMS service, but Mobilant offered also this easy to use http request method! ;)
islipfd19
Posts: 126
Joined: 07 Jul 2014 03:35

Re: SMS and Email Notifications

Post by islipfd19 »

I modified the current email / sms moules to send emails. It can also send sms but you need to know the carriers domain extension; for example T-Mobile allows sending emails as text meesages. It's <your phone number>@tmomail.net.Well, that's what it is in the U.S.

The module is updated on my fork'd git-hub. https://github.com/islipfd19/home-autom ... ules/Email if anyone wants to use it. You can add as many emails as you like. Italso requires sendmail to be installed and configured in order to use it and a couple of commands added to .syscommands file.
Post Reply