Usage is simple, set the IP address of the iKettle2 and Domoticz server in the script and then use it like this:
python kettle.py control on40 (this command would boil the kettle to 40 degrees).
python kettle.py control on60
python kettle.py control on80
python kettle.py control on100
python kettle.py control on (this command would boil the kettle to 100 degrees).
python kettle.py control off
python kettle.py status monitor
python kettle.py status domoticzsync
kettle.py
Code: Select all
import requests
import socket
import sys
import time
import json
import urllib
# Domoticz Settings
server = "USERNAME:[email protected]:80"
# iKettle 2 Settings
host = '192.168.0.85';
port = 2081;
# Kettle Control --------- Start
if sys.argv[1] == "control":
if sys.argv[2] == "on40":
message_to_send = "\x15\x28\x00\x7e"
if sys.argv[2] == "on60":
message_to_send = "\x15\x3C\x00\x7e"
if sys.argv[2] == "on80":
message_to_send = "\x15\x50\x00\x7e"
if sys.argv[2] == "on100":
message_to_send = "\x21\x7e"
if sys.argv[2] == "on":
message_to_send = "\x21\x7e"
if sys.argv[2] == "off":
message_to_send = "\x16"
try:
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((host, port))
s.send(message_to_send)
data = s.recv(10)
s.close()
except socket.error, msg:
print 'Failed to create socket. Error code: ' + str(msg[0]) + ' , Error message : ' + msg[1]
sys.exit();
return_code = unicode(data)
success=0
message=""
if return_code =="\x03\x00~":
success=1
message="Kettle has received the command."
else:
message="check kettle"
print message
quit()
sys.exit()
# Kettle Control --------- End
# Kettle Status Monitor --------- Start
if sys.argv[1] == "status":
while 1:
from array import array
incommingCommandSecond = ""
incommingCommandFirst = ""
try:
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
except socket.error:
print 'Failed to create socket'
sys.exit()
statusMessageType = {
'0x0' : "Ready",
'0x1' : "Boiling",
'0x2' : "Keep warm",
'0x3' : "Boiling finished??",
'0x4' : "Cooling? not sure",
}
locatedMessageType = {
'0x9' : "On base",
'0xa' : "On base",
'0x8' : "On base",
'0x7' : "Off base",
}
s.connect((host , port))
print 'Socket Connected to ' + host + ' on ip ' + host
# while 1:
reply = s.recv(4096)
incommingCommandFirst = reply
if incommingCommandFirst == incommingCommandSecond:
pass
else:
incommingCommandSecond = reply
a = array("B", reply)
b = map(hex, a)
deviceMessage = b[0]
statusMessage = b[1]
temperatureMessage = int(b[2], 0)
locatedMessage = b[3]
waterlevelMessage = int(b[4], 0)
print
if waterlevelMessage < 85:
waterlevel = "Empty"
if waterlevelMessage > 85 < 105:
waterlevel = "Not enough water"
if waterlevelMessage > 105 < 138:
waterlevel = "1 Cups"
if waterlevelMessage > 140 < 160:
waterlevel = "2 Cups"
if waterlevelMessage > 160 < 180:
waterlevel = "3 Cups"
if waterlevelMessage > 180 < 200:
waterlevel = "4 Cups"
if waterlevelMessage > 200 < 220:
waterlevel = "5 Cups"
if waterlevelMessage > 220 < 250:
waterlevel = "6 Cups"
if waterlevelMessage > 250:
waterlevel = "Max full"
print 'Status:', statusMessageType[statusMessage]
if temperatureMessage is not 127:
locatedMessage = "On base"
if temperatureMessage is 127:
locatedMessage = "Off base"
temperatureMessage = "unavailable"
waterlevel = "unavailable"
print 'Located:', locatedMessage
print 'Temperature:', temperatureMessage
print 'Water level:', waterlevel
# Kettle Status Monitor --------- End
# Kettle Domoticz Sync --------- Start
if sys.argv[2] == "domoticzsync":
# Get the Kettle Status in Domoticz, compare against current value and update if not match
url = "http://" + str(server) + "/json.htm?type=command¶m=getuservariable&idx=8"
response = urllib.urlopen(url)
data = json.loads(response.read())
if data["result"][0]["Value"] != str(statusMessageType[statusMessage]):
requests.get("http://" + str(server) + "/json.htm?type=command¶m=updateuservariable&vname=Kettle Status&vtype=2&vvalue=" + str(statusMessageType[statusMessage]))
# Get the Kettle Location in Domoticz, compare against current value and update if not match
url = "http://" + str(server) + "/json.htm?type=command¶m=getuservariable&idx=9"
response = urllib.urlopen(url)
data = json.loads(response.read())
if data["result"][0]["Value"] != str(locatedMessage):
requests.get("http://" + str(server) + "/json.htm?type=command¶m=updateuservariable&vname=Kettle Location&vtype=2&vvalue=" + str(locatedMessage))
# Get the Kettle Temperature in Domoticz, compare against current value and update if not match
url = "http://" + str(server) + "/json.htm?type=command¶m=getuservariable&idx=10"
response = urllib.urlopen(url)
data = json.loads(response.read())
if data["result"][0]["Value"] != str(temperatureMessage):
requests.get("http://" + str(server) + "/json.htm?type=command¶m=updateuservariable&vname=Kettle Temperature&vtype=2&vvalue=" + str(temperatureMessage))
# Get the Kettle Water Level in Domoticz, compare against current value and update if not match
url = "http://" + str(server) + "/json.htm?type=command¶m=getuservariable&idx=11"
response = urllib.urlopen(url)
data = json.loads(response.read())
if data["result"][0]["Value"] != str(waterlevel):
requests.get("http://" + str(server) + "/json.htm?type=command¶m=updateuservariable&vname=Kettle Water Level&vtype=2&vvalue=" + str(waterlevel))
print
print 'Domoticz Sync Mode Active'
# Kettle Domoticz Sync --------- End
if sys.argv[1] == "help":
print
print 'Usage:'
print 'python kettle.py control on40 (this command would boil the kettle to 40 degrees)'
print 'python kettle.py control on60'
print 'python kettle.py control on80'
print 'python kettle.py control on100'
print 'python kettle.py control on (this command would boil the kettle to 100 degrees)'
print 'python kettle.py control off'
print 'python kettle.py status monitor'
print 'python kettle.py status domoticzsync'
print
All the variable types in Domoticz for the kettle should be set to: String
The water level (number of cups) was measured by putting one cup of water after another into the kettle and recording the values to come up with an approximate number of cups that the number represents.
Here is a one line script for running kettle.py in a screen session (useful for having it run 24/7 in the background) and on startup checking the status and updating Domoticz. I put this into a file called startup.sh in the same directory as kettle.py then gave it executable permissions using chmod 755 startup.sh then finally I told the system to put it into startup using: update-rc.d kettlebridge defaults
Code: Select all
/usr/bin/screen -S KettleMonitor -d -m python /root/smarter/kettle.py status domoticzsync
nano /etc/init.d/kettlebridge
inside I put this code (making sure to set the location to the startup.sh in the script)
Code: Select all
#!/bin/sh
### BEGIN INIT INFO
# Provides: kettlebridge
# Required-Start: $network
# Required-Stop: $network
# Default-Start: 2 3 5
# Default-Stop:
# Description:
### END INIT INFO
case "$1" in
'start')
/root/smarter/kettle/startup.sh
;;
'stop')
;;
*)
echo "Usage: $0 { start | stop }"
;;
esac
exit 0
I also wanted to automatically restart kettlebridge if it crashed for some reason so I put this code into Monit, read here if you don't know what Monit is:
https://www.domoticz.com/wiki/Monitoring_domoticz
The code for Monit which I put into the file /etc/monit/monitrc is:
Code: Select all
# Monitor Kettle Bridge
check process KettleBridge with match KettleBridge
start program = "/etc/init.d/kettlebridge start"
if cpu usage > 70% for 3 cycles then restart
if memory usage > 50% for 3 cycles then restart
Here is an example Lua script for doing something when a variable status changes (in this case Ready vs Boiling), note that the script MUST be placed in the Domoticz/scripts/lua directory and that the file name MUST start with: script_variable
In this case the full file name I'm using is: script_variable_kettle.lua
You cannot simply place this script in the "Events" web interface, it must go in a file in the directory mentioned above.
script_variable_kettle.lua
Code: Select all
commandArray = {}
-- Announce if the kettle is boiling
if (uservariablechanged['Kettle Status'] == 'Boiling') then
os.execute ('sh /root/domoticz/speak.sh "speaker3 Boiling initiated."')
end
-- Turn off the kettle when it's finished boiling and make verbal announcement
if (uservariablechanged['Kettle Status'] == 'Ready') then
commandArray['Kettle']='Off'
os.execute ('sh /root/domoticz/speak.sh "speaker3 The kettle has finished boiling."')
end
return commandArray
script_device_kettle.lua
Code: Select all
commandArray = {}
-- Turn on the kettle (boil)
if (devicechanged['Kettle'] == '40°') then
os.execute ('python /root/smarter/kettle/kettle.py control on40')
end
if (devicechanged['Kettle'] == '60°') then
os.execute ('python /root/smarter/kettle/kettle.py control on60')
end
if (devicechanged['Kettle'] == '80°') then
os.execute ('python /root/smarter/kettle/kettle.py control on80')
end
if (devicechanged['Kettle'] == '100°') then
os.execute ('python /root/smarter/kettle/kettle.py control on100')
end
-- Manually turn off the kettle (if you use the switch in Domoticz and the kettle is boiling)
if (devicechanged['Kettle'] == 'Off' and uservariables["Kettle Status"] == 'Boiling') then
os.execute ('python /root/smarter/kettle/kettle.py control off')
end
return commandArray