Notifications to PC with Snarl
Domoticz supports notifications to mobile devices with Pushover, Pushsafer and Prowl. A good notification system to the PC desktop was missing because I do not carry the mobile phone at all times. Pushover can push messages to the desktop but this only works in a browser. Pushsafer can send messages with an image to iOS, Android and Windows 10 (Phone & Desktop).
When searching for notification receivers I found Snarl which is a great notification system for events like low diskspace, IM events, played music, time, anything you can think of! Only the link from Domoticz to Snarl was missing but in a few hours the author of Snarl popped out a Python script that connects to Snarl from the Pi.
Get the Snarl installer here: Download Snarl-3.1-setup.exe (9.9 MB).
It is also possible to get Snarl notifying on OSX or Linux.
Make sure to allow traffic to Snarl listening on port 9887 in your desktop firewall.
Then get the Python script here: Download snp-send-0.5.zip (3.8 KB) .
Copy snp-send.py to /home/pi/domoticz/scripts, you can use WinSCP for that.
On the Domoticz Pi, make sure you have Python3 installed. The command Python3 will give an error when it is not present or enter Python3 (ctrl-D to leave). This command will install Python3:
sudo apt-get install python3
About 30MB diskspace is used totally.
Now you can fire your first test command:
python3 snp-send.py -d 192.168.2.4 -b 'Hello, world' -i '!system-info' -n '!windowslogon' -s
snp-send: connecting to 192.168.2.4:9887...connected!
snp-send: notification sent
Change the IP address to your desktop's IP. All possible command options are explained in the Readme in the downloaded snp-send-0.5.zip. If all went well, you will see a text message Hello, world with an icon and a sound and see two messages on the Pi command line.
Now create a new bash script, or add a line to your existing Pushover notification script in /home/pi/domoticz/scripts:
snp-send: notification sent
/usr/bin/python3.2mu /home/pi/domoticz/scripts/snp-send.py -d 192.168.2.4 -b 'Hello, world!' -i '!system-yes' -n 'd:\shared\fluitje.mp3'
Change the IP address to your desktop's, and change or remove the sound option (-n). I borrowed the railway station bell sound from the NS app here :-) Save the file with ctrl+X. Then make it executable:
chmod +x snarltest.sh
In Domoticz - Switches, edit the switch you want to make notifications. Put this in field On Action:
If all went well, when you toggle the switch to on (or an event does this), then you will see a notification from Snarl on your desktop!
When the desktop is down or Snarl is not running, a message in the Domoticz log is written:
Thu Feb 5 08:12:48 2015 Error: Error executing script command (home/pi/domoticz/scripts/snarltest.sh). returned: 512
I snatched the Domoticz icon from the website and copied it to the Snarl default icon folder: C:\Program Files\Snarl\etc\default_theme\icons
Direct link to the icon picture.
python3.2 snp-send.py -d 192.168.2.4 -b 'Door 2 open for 5 minutes' -i '!domoticz-icon' -n 'd:\shared\fluitje.mp3'
Snarl notification on desktop
Here is the Python 3.2 script for the Raspberry Pi. Just copy it here or get the file here. This is snp-send.py version 0.5.
# snp-send.py -- multi-platform Snarl notification sender # Copyright (C) 2015 full phat products BUILD_VER = "0.5" # Change log: # # 0.5 - Even more Python 3.2 friendly # # 0.4 - Modified socket exception handling to work better on Python 3.2 # # 0.3 - No longer dependent on ipaddress module # # 0.2 - Added sticky, priority and callback options # Better option handling # More robust packet building # Validates IP address using ipaddress module # # 0.1 - initial version try: import ipaddress except ImportError: pass import socket import getopt import sys #import os class term: PURPLE = '\033[95m' CYAN = '\033[96m' DARKCYAN = '\033[36m' BLUE = '\033[94m' GREEN = '\033[92m' YELLOW = '\033[93m' RED = '\033[91m' BOLD = '\033[1m' UNDERLINE = '\033[4m' END = '\033[0m' destport = 9887 destip = "127.0.0.1" content = '' priority = 0 debugmode = False copyright = term.BOLD + "\nsnp-send " + BUILD_VER + "\n" + term.END + \ "Copyright (c) 2015 full phat products" usage = "usage: snp-send " \ "[-b body] [-c callback] [-d ip] [-i icon] [-n sound] " \ "[-p port] [-r priority] [-s] [-t title] \n" hint = "" \ " -b Notification body\n" \ " -c Callback URL, !bang command or @signal\n" \ " -d Destination IP address (default is 127.0.0.1)\n" \ " -i Url, !system icon or UNC path to image file\n" \ " -n Sound to play\n" \ " -p Destination TCP port (default is 9887)\n" \ " -r Notification priority. Must be between -2 and +2. Default is 0\n" \ " -s Requests notification to be displayed sticky (infinite duration)\n" \ " -t Notification title\n" \ "\n" \ "Notes\n" \ " - At least one of title, body or icon must be supplied.\n" # " - At least one of " + term.BOLD + "title" + term.END +", " + term.BOLD + "body" + term.END + " or " + term.BOLD + "icon" + term.END + " must be supplied.\n" if len(sys.argv) < 2: print('snp-send: arg missing') print(usage) sys.exit(0) try: opts, args = getopt.getopt(sys.argv[1:], "b:c:d:i:n:p:r:st:?", ["body=", "debug", "sticky", "title="]) except getopt.GetoptError: print('snp-send: arg missing') print(usage) sys.exit(2) for o, a in opts: if o == "-d": destip = a elif o == "-p": try: destport = int(a) except ValueError: print('snp-send: port must be an intger between 0 and 65535') sys.exit(2) elif o in ("-t", "--title"): content = content + 'title=' + a + '&' elif o in ("-b", "--body"): content = content + 'text=' + a + '&' elif o == "-c": content = content + 'callback=' + a + '&' elif o == "-i": content = content + 'icon=' + a + '&' elif o == "-n": content = content + 'sound=' + a + '&' elif o == "-r": # priority try: priority = int(a) except ValueError: print('snp-send: priority must be an intger between -2 and 2') sys.exit(2) if priority != 0: content = content + 'priority=' + a + '&' elif o in ("-s", "--sticky"): content = content + 'duration=0&' elif o == "-?": print(copyright) print(usage) print(hint) sys.exit(0) elif o == "--debug": debugmode = True # validate args try: ipaddress.ip_address(destip) except ValueError: print('snp-send: invalid destination IP address') sys.exit(2) except NameError: pass # construct the SNP/3.0 packet packet = 'SNP/3.0\r\nnotify?' # add rightstr(content, len(content) -1 ) packet = packet + content[:-1] + '\r\n' if debugmode: print("content:\n" + content) # TO-DO: add headers # add footer packet = packet + 'END\r\n' if debugmode: print("packet:\n" + packet) socket.setdefaulttimeout(5) s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) print('snp-send: connecting to ' + destip + ':' + str(destport) + '...', end = '') sys.stdout.flush() try: s.connect((destip, destport)) except socket.error as e: print('failed (' + str(e) + ')') sys.exit(2) else: print('connected!') s.send(bytes(packet, 'UTF-8')) print('snp-send: notification sent') data = s.recv(1024) s.close()