Home Automation with Asterisk - Astricon 2015 - Alberto Sagredo Castro
-
Upload
alberto-sagredo-castro -
Category
Technology
-
view
18.468 -
download
2
Transcript of Home Automation with Asterisk - Astricon 2015 - Alberto Sagredo Castro
Home Automation with Asterisk
Alberto Sagredo Castro
www.voipnovatos.es
10/14/2015
Who i am• Alberto Sagredo Castro
• a.k.a @albersag on twitter
• Working in VoIP since ten years ago
• Working with Asterisk for about 10 years
• Several large projects with Asterisk and many Asterisk compiled thru Spain and Europe
• Working for Avanzada 7 and USA VOIP
• Other Stuff : Mikrotik, Ubiquiti, Ham Radio and all that contains bits on it
2
Why home automation
• It makes life easier
• Its not expensive
• It helps disabled people
• Internet of Things (IOT) is here
• Its not complex
• Eco friendly and save money
• Just play !3
Home automation vs Asterisk
4
• Asterisk natively does not support home automation protocols
• We need something to interact with ha (home automation)
• What could we use? PHPARI, AGI, .call files, asterisk dialplan, SQL …
• Any programmer here? What about chan_zwave :)
Which protocol to use
5
• home automation is plenty of protocols, open, proprietary, half open half proprietary :) all flavours.
• smarthings
• z-wave
• knx
• insteon
• x10
• zigbee
• opensprinkler
• MQTT
Z-Wave
6
• Its a “propietary” protocol owned by Sigma Designs
• Its widely supported by enterprise and really good compatibility
• Its cheap (50 $/device)
• USA & EU frecuencies
• Feedback from device status
• Low energy
• Zwave alliance (+ 400 manufacturers)
• Mesh network between devices. Good for homes
Do not reinvent the wheel
8
• Ok. Asterisk does not support (yet) home automation but i want to use Asterisk in my home automation system…. What could i do?
• I will use Asterisk to generate calls when events happens on my HA system and to interact with them by phone.
• Phone is easier than using apps and works on any platform :)
OpenHab
9
• Its the swedish knife (a.k.a Olle :) for home automation.
• Lots of binding, plenty of protocols supported and many more
• REST API
• Items
• Sitemaps
• Scripts / Rules (Xtend scripting language)
• Transforms
• Interface to admin Habmin and App for design (Openhab Designer)
OpenHab
10
• Its Java .
• Runs on BananaPi or Raspberry Pi without any issues.
• Easy to install.
• Easy as Asterisk to configure.
• Scripting language so you would feel confortable with it
How to start
12
• We would need an USB Zwave Dongle (Aeon Labs, Zwave.me,…)
• A Raspberry Pi or Banana Pi
• Zwave devices
• Asterisk of course
• Internet for notifications and persistent data to the cloud
Installing OpenHab
14
• If you use Debian install repos
curl 'https://bintray.com/user/downloadSubjectPublicKey?username=openhab' | sudo apt-key add -
echo "deb http://dl.bintray.com/openhab/apt-repo stable main" | sudo tee /etc/apt/sources.list.d/openhab.list
sudo apt-get update
sudo apt-get install openhab-runtime
update-rc.d openhab defaults
service openhab start
Install Java & esential bindings
15
sudo tar zxvf jdk-8-ea-b36e-linux-arm-hflt-*.tar.gz -C /opt
sudo update-alternatives --install "/usr/bin/java" "java" "/opt/jdk1.8.0/bin/java" 1
sudo update-alternatives for other commands if needed (e.g. javac).
java -version
Install Java & esential bindings
16
sudo apt-get install openhab-addon-binding-samsungtv
sudo apt-get install openhab-addon-binding-zwave
sudo apt-get install openhab-addon-io-myopenhab
sudo apt-get install openhab-addon-persistence-exec openhab-addon-persistence-logging
sudo apt-get install openhab-addon-binding-opensprinkler
sudo apt-get install openhab-addon-binding-http openhab-addon-binding-ntp
sudo apt-get install openhab-addon-action-pushover
sudo apt-get install openhab-addon-binding-asterisk
Integration. Lets fun!
18
• Lets focus in how to integrate this cool “weapons” together.
• We could use:
• ARI
• REST API
• CLI
• .call files
• AstDB
• MySQL
• etc…..
Dangerous Demo 1
19
• IVR to interact with Lights and if everything goes fine, open my garden sprinklers in spain remotely (dont be nasty)
• WIFI SSID -> “VOIPNOVATOS”
• Asterisk -> “10.0.2.x”
• User Extension “20x”
• Password : “astricon” of course
• Call 666 and don't be evil!
Dangerous Demo 1
20
• Asterisk Dialplan [astricon-ivr]
exten => s,1,Noop exten => s,n,Background(welcomeivr) exten => s,n,WaitExten(10) exten => s,n,Hangup
exten => 1,1,Noop(Turn on light) exten => 1,n,GotoIf($[${DB(light/astricon)} = "ON"]?lighton:lightoff) exten => 1,n(lighton),Set(${DB(light/astricon)="OFF"}) exten => 1,n,System(curl --header "Content-Type: text/plain" --request POST --data "OFF" http://10.0.2.2:8080/rest/items/Z_Socket1/) exten => 1,n,Playback(lightoff) exten => 1,n,Hangup exten => 1,n(lightoff),Set(${DB(light/astricon)="ON"}) exten => 1,n,System(curl --header "Content-Type: text/plain" --request POST --data "ON" http://10.0.2.2:8080/rest/items/Z_Socket1/) exten => 1,n,Playback(lighton) exten => 1,n,Hangup
exten => 2,1,Noop(Fire Alarm) exten => 2,n,GotoIf($[${DB(alarm/astricon)} = "ON"]?fired:notfired) exten => 2,n(fired),Set(${DB(alarm/astricon)="OFF"}) exten => 2,n,System(curl --header "Content-Type: text/plain" --request POST --data "OFF" http://10.0.2.2:8080/rest/items/FortrezZ_Siren) exten => 2,n,Playback(thieves) exten => 2,n,Hangup exten => 2,n(notfired),Set(${DB(alarm/astricon)="ON"}) exten => 2,n,System(curl --header "Content-Type: text/plain" --request POST --data "ON" http://10.0.2.2:8080/rest/items/FortrezZ_Siren) exten => 2,n,Playback(nothieves) exten => 2,n,Hangup
exten => 3,1,Noop(Sprinkler) exten => 3,n,GotoIf($[${DB(sprinkler/astricon)} = "ON"]?on:off) exten => 3,n(on),Set(${DB(sprinkler/astricon)="OFF"}) exten => 3,n,System(curl --header "Content-Type: text/plain" --request POST --data "OFF" http://10.0.2.2:8080/rest/items/Sprinklers_Zone4) exten => 3,n,Playback(closedsprinklers) exten => 3,n,Hangup exten => 3,n(off),Set(${DB(sprinkler/astricon)="ON"}) exten => 3,n,System(curl --header "Content-Type: text/plain" --request POST --data "ON" http://10.0.2.2:8080/rest/items/Sprinklers_Zone4) exten => 3,n,Playback(opensprinklers) exten => 3,n,Hangup
Dangerous Demo 2
21
• For some people it could be great to interact using voice while in its home. Being at home or not, Asterisk could turn on lights, turn off alarm and make emergency calls
• Use Google ASR, Its free and it works well! (Use latest agi version as oldest has issues)
• You need internet connection! Hope astricon one would work well!
Dangerous Demo 2
22
• Google ASR
• Asterisk Speech Recognition http://zaf.github.io/asterisk-speech-recog/
Dangerous Demo 2
23
• Asterisk Dialplan [astricon-asr]
exten => s,1,Noop exten => s,n,Background(welcomeivr) exten => s,n,agi(speech-recog-tiny.agi,en-US) exten => s,n,Verbose(1,The text you just said is: ${utterance}) exten => s,n,Verbose(1,The probability to be right is: ${confidence}) exten => s,n,GotoIf($["${uterance}" = "fire alarm"]?firealarm) exten => s,n,GotoIf($["${uterance}" = "turn on"]?turnonlight:out) exten => s,n(firealarm),Goto(firealarm,1) exten => s,n,Hangup exten => s,n(turnonlight),Goto(turnonlight,1) exten => s,n(out),Hangup
exten => turnonlight,1,Noop(Turn on light) exten => turnonlight,n,GotoIf($[${DB(light/astricon)} = "ON"]?lighton:lightoff) exten => turnonlight,n(lighton),Set(DB(light/astricon)="OFF") exten => turnonlight,n,System(curl --header "Content-Type: text/plain" --request POST --data "OFF" http://10.0.2.19:8080/rest/items/Z_Socket1/) exten => turnonlight,n,Playback(lightoff) exten => turnonlight,n,Hangup exten => turnonlight,n(lightoff),Set(DB(light/astricon)="ON") exten => turnonlight,n,System(curl --header "Content-Type: text/plain" --request POST --data "ON" http://10.0.2.19:8080/rest/items/Z_Socket1/) exten => turnonlight,n,Playback(lighton) exten => turnonlight,n,Hangup
exten => firealarm,1,Noop(Fire Alarm) exten => firealarm,n,GotoIf($[${DB(alarm/astricon)} = "ON"]?fired:notfired) exten => firealarm,n(fired),Set(DB(alarm/astricon)="OFF") exten => firealarm,n,System(curl --header "Content-Type: text/plain" --request POST --data "OFF" http://10.0.2.19:8080/rest/items/FortrezZ_Siren) exten => firealarm,n,Playback(nothieves) exten => firealarm,n,Hangup exten => firealarm,n(notfired),Set(DB(alarm/astricon)="ON") exten => firealarm,n,System(curl --header "Content-Type: text/plain" --request POST --data "ON" http://10.0.2.19:8080/rest/items/FortrezZ_Siren) exten => firealarm,n,Playback(thieves) exten => firealarm,n,Hangup
Dangerous Demo 3
24
• Smart followme
• You can use Wifi to detect you are at home or presence detectors.
• If you are outside home, divert your calls to cell phone. Just ring on Kitchens phone if you are cooking (Advise: this will not work if you have kids moving around)
• Here we could use AGI to get motion status from Openhab.
Dangerous Demo 3
25
• Asterisk Dialplan
[astricon-presence]
exten => s,1,Answer() exten => s,n,AGI(openhab.agi, "asterisk", "password", "Fibaro_Motion_1_Motion", "atHomeMotion") exten => s,n,AGI(openhab.agi, "asterisk", "password", "Home_Presence", "atHomeWifi") exten => s,n,GotoIf($["${atHomeMotion}" == "ON"]?athome) exten => s,n,GotoIf($["${atHomeWifi}" == "ON"]?athome:away) exten => s,n,Goto(bye) exten => s,n(athome),Playback(movementdetected) exten => s,n,Hangup() exten => s,n(away),Playback(movementnotdetected) exten => s,n(bye),Hangup()
[astricon-presence2]
exten => s,1,Answer() exten => s,n,GotoIf($["${PRESENCE}" == "ON"]?athome:away) exten => s,n(athome),Playback(movementdetected) exten => s,n,Hangup() exten => s,n(away),Playback(movementnotdetected) exten => s,n,Hangup()
Dangerous Demo 3
26
• Openhab.agi
#!/usr/bin/python
import sys,os,datetime import httplib import base64
def send(data): sys.stdout.write("%s \n"%data) sys.stdout.flush()
AGIENV={} env = "" while(env != "\n"): env = sys.stdin.readline() envdata = env.split(":") if len(envdata)==2: AGIENV[envdata[0].strip()]=envdata[1].strip()
username = AGIENV['agi_arg_1'] password = AGIENV['agi_arg_2'] item = AGIENV['agi_arg_3'] varname = AGIENV['agi_arg_4']
auth = base64.encodestring('%s:%s' % (username, password)).replace('\n', '') headers = {"Authorization" : "Basic %s" % auth} conn = httplib.HTTPConnection("localhost", 8080) conn.request('GET', "/rest/items/%s/state"%item, "", headers) response = conn.getresponse() item_state = response.read()
send("SET VARIABLE %s %s"%(varname, item_state)) sys.stdin.readline()
Dangerous Demo 3
27
• Openhab rules
rule "MotionOn" when Item Fibaro_Motion_1_Motion changed from OFF to ON then counter = counter + 1 logInfo("Rules", "Motion Rule ON") executeCommandLine("/usr/src/openhab/configurations/rules/curlon.sh") pushover("Motion Detected on Astricon")
end
rule "MotionOff" when Time cron "0 */2 * * * ?" then
if(lastCheck == counter) { counter = 0 lastCheck = -1;
logInfo("Rules", "Motion Rule OFF") executeCommandLine("/usr/src/openhab/configurations/rules/curloff.sh") } else { lastCheck = counter } end
Dangerous Demo 3
28
• Openhab rules var Timer timer = null
rule "MotionOn2" when Item Fibaro_Door changed then
if(Fibaro_Door.state==ON) { executeCommandLine("/etc/openhab/configurations/rules/curlondoor.sh") if(timer==null) { timer = createTimer(now.plusSeconds(10)) [| executeCommandLine("/etc/openhab/configurations/rules/curloffdoor.sh") ] } else { timer.reschedule(now.plusSeconds(10)) } } else if(Fibaro_Door.state==OFF) { if(timer!=null) { timer.cancel timer = null } }
end
Dangerous Demo 3
29
• Wifi Detector #!/bin/sh
macalberto="f0:27:2d:00:44:12" athome=0
macs=$(iw dev wlan0 station dump | grep Station | cut -f 2 -s -d" ")
for mac in $macs; do case $mac in "$macalberto") athome=1;; esac done
if [ $athome -eq 1 ]; then
curl --header "Content-Type: text/plain" --request POST --data "ON" http://10.0.2.19:8080/rest/items/Home_Presence/
else
curl --header "Content-Type: text/plain" --request POST --data "OFF" http://10.0.2.19:8080/rest/items/Home_Presence/
fi
• curlon.sh #!/bin/bash curl -v -u asterisk:asterisk -X POST "http://10.0.2.19:8088/ari/asterisk/variable?variable=PRESENCEvalue=ON&api_key=asterisk:asterisk"
Dangerous Demo 4
30
• Create your own Alarm System controlled by phone
• We could arm alarm system by phone
• No monthly fees
• If armed and motion is detected call police or call you before police that would be better :)
• If fired, open sprinklers at garden..
• Used ARI to gen calls on Asterisk
Dangerous Demo 4
31
• ari.conf [general] enabled = yes
allowed_origins=http://ari.asterisk.org
[asterisk] type = user read_only = no password = asterisk
• http.conf [general] enabled = yes bindaddr=0.0.0.0
• manager.conf [general] enabled = yes ;webenabled = yes
port = 5038 bindaddr = 127.0.0.1
[asterisk] secret = asterisk read = system,call,log,verbose,agent,user,config,dtmf,reporting,cdr,dialplan write = system,call,agent,user,config,command,reporting,originate,message
Dangerous Demo 4
32
• extensions.conf [extensiones]
exten => _2XX,1,Dial(SIP/${EXTEN},20,TtrR) exten => _2XX,n,hangup
exten => 900,1,Answer exten => 900,n,Playback(policecall) exten => 900,n,Ringing() exten => 900,n,Wait(10) exten => 900,n,Hangup
• alarmon.sh #!/bin/bash curl -v -u asterisk:asterisk -X POST "http://10.0.2.19:8088/ari/asterisk/variable?variable=ALARM&value=ON&api_key=asterisk:asterisk" curl -v -u asterisk:asterisk -X POST "http://10.0.2.19:8088/ari/channels?endpoint=SIP%2F201&extension=900&context=extensiones&priority=1&callerId=ALARM%20DETECTED%20ASTRICON&timeout=30&api_key=asterisk:asterisk"
Dangerous Demo 4
33
• Openhab rules rule "Alarm" when Item Fibaro_Door changed from OFF to ON
then
if(Fibaro_Door.state == ON && Alarm_Switch.state == ON ) { logInfo("Rules", "Alarm Alarm Alarm") executeCommandLine("/etc/openhab/configurations/rules/alarmon.sh") pushover("Alarm on Astricon") }
end
rule "Water" when Item Fibaro_Flood changed
then
if(Fibaro_Flood.state == 255 && Alarm_Switch.state == ON ) { logInfo("Rules", "Alarm Alarm Alarm") executeCommandLine("/etc/openhab/configurations/rules/alarmon.sh") pushover("Alarm on Astricon") }
end
Bonus Demo
34
• Asterisk Ringing Status and Called/Calling Number
• We have an openhab binding but it does not work with new AMI
• Using JSON answer from Asterisk ARI and jq , json parser will try to get this working.
Bonus Demo
35
• extensions.conf [extensiones]
exten => 999,1,Set(${CALLERID(num)}=778811) exten => 999,n,System(curl --header "Content-Type: text/plain" --request POST --data "ON" http://10.0.2.19:8080/rest/items/Asterisk_Ring) exten => 999,n,Ringing() exten => 999,n,Wait(10) exten => 999,n,Answer() exten => 999,n,Echo() exten => 999,n,Hangup
exten => h,1,System(curl --header "Content-Type: text/plain" --request POST --data "OFF" http://10.0.2.19:8080/rest/items/Asterisk_Ring)
• call.sh #!/bin/bash
json_clause=$(curl http://10.0.2.19:8088/ari/channels?api_key=asterisk:asterisk)
state=$(echo $json_clause | jq '.[0].state') name=$(echo $json_clause | jq '.[0].name') numbercalling=$(echo $json_clause | jq '.[0].caller.number') numbercalled=$(echo $json_clause | jq '.[0].dialplan.exten') numbercalled2=$(echo $json_clause | jq '.[0].connected.number')
curl --header 'Content-Type: text/plain' --request PUT --data "$numbercalling" http://localhost:8080/rest/items/Active_Calling/state/ curl --header 'Content-Type: text/plain' --request PUT --data "$numbercalled" http://localhost:8080/rest/items/Active_Called/state/
Bonus Demo
36
• Openhab rules rule "Call" when Item Asterisk_Ring changed then
if(Asterisk_Ring.state == ON) {
executeCommandLine("bash /etc/openhab/configurations/rules/call.sh") }
if(Asterisk_Ring.state == OFF) { executeCommandLine(" bash /etc/openhab/configurations/rules/calloff.sh") }
end
Resources
38
• www.openhab.org
• https://github.com/openhab/openhab/wiki/Samples-Rules
• https://github.com/openhab/openhab/wiki/Explanation-of-items
• https://github.com/openhab/openhab/wiki/Linux---OS-X
• http://raspberrypi.stackexchange.com/questions/4683/how-to-install-the-java-jdk-on-raspberry-pi
• http://zaf.github.io/asterisk-speech-recog/
• http://tinsley.io/2015/03/openhab-presence-detection-with-dd-wrt/