Smarter Wifi iKettle 2 script for Domoticz

Python and python framework

Moderator: leecollings

ben53252642
Posts: 543
Joined: Saturday 02 July 2016 5:17
Target OS: Linux
Domoticz version: Beta
Contact:

Smarter Wifi iKettle 2 script for Domoticz

Post by ben53252642 »

This is a python script for controlling the new smarter iKettle 2

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&param=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&param=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&param=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&param=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&param=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&param=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&param=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&param=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
If you use python kettle.py status domoticzsync, you can setup 4 variables in Domoticz and the script will update them if the device status changes. Be sure to set the IDX value for each device in the kettle.py so it knows which variable to update in Domoticz, these are in the "Kettle Domoticz Sync" section of the script.
Screen Shot 2016-07-31 at 6.50.54 AM.png
Screen Shot 2016-07-31 at 6.50.54 AM.png (79.12 KiB) Viewed 4163 times
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
Then I wanted the startup.sh script to automatically run each time the system boots and run in the background so I created a script:
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
Then I granted kettlebridge executable permissions using chmod 755 kettlebridge

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
Monit has a nice web interface, I have many bridges and scripts being monitored by it every 30 seconds.
Screen Shot 2016-07-31 at 10.19.27 AM.png
Screen Shot 2016-07-31 at 10.19.27 AM.png (42.89 KiB) Viewed 4120 times
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
Here is a Lua script for controlling the kettle with temperature options, in this case I have a virtual selector device in Domoticz called "Kettle" and when I select a temperature option this script does the action to call Python kettle.py and control the kettle.

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
Each level name in the Domoticz selector switch is like so with the temperature option (40, 60, 80 or 100): 40°
domoticzkettle.png
domoticzkettle.png (28.78 KiB) Viewed 4022 times
Last edited by ben53252642 on Sunday 07 August 2016 11:46, edited 38 times in total.
Unless otherwise stated, all my code is released under GPL 3 license: https://www.gnu.org/licenses/gpl-3.0.en.html
Derik
Posts: 1601
Joined: Friday 18 October 2013 23:33
Target OS: Raspberry Pi / ODroid
Domoticz version: BETA
Location: Arnhem/Nijmegen Nederland
Contact:

Re: Smarter iKettle 2 script for Domoticz

Post by Derik »

great...
I do not have a thing like this..
Only the question for me is, how connect this Ikettle with domoticz ?
Xu4: Beta Extreme antenna RFXcomE,WU Fi Ping ip P1 Gen5 PVOutput Harmony HUE SolarmanPv OTG Winddelen Alive ESP Buienradar MySensors WOL Winddelen counting RPi: Beta SMAspot RFlinkTest Domoticz ...Different backups
trixwood

Re: Smarter iKettle 2 script for Domoticz

Post by trixwood »

No domoticz monitor but

Update: https://github.com/Tristan79/iBrew

Full console, command line also for smarter coffee.


Fun reading also explains some of the api (search github for wrappers):

https://www.pentestpartners.com/blog/sm ... onfigured/
https://www.pentestpartners.com/blog/ha ... ne-part-1/
Last edited by trixwood on Tuesday 09 August 2016 9:53, edited 2 times in total.
ben53252642
Posts: 543
Joined: Saturday 02 July 2016 5:17
Target OS: Linux
Domoticz version: Beta
Contact:

Re: Smarter iKettle 2 script for Domoticz

Post by ben53252642 »

Derik, you just use the mobile app to get the kettle on your wifi network, then you can use the above script to turn it on / off from Domoticz.

I also ordered the Smarter coffee machine at the same time as the kettle so I'll be posting a script for controlling that shortly. The kettle and the coffee machine use a very similar control mechanism. :)
Unless otherwise stated, all my code is released under GPL 3 license: https://www.gnu.org/licenses/gpl-3.0.en.html
ben53252642
Posts: 543
Joined: Saturday 02 July 2016 5:17
Target OS: Linux
Domoticz version: Beta
Contact:

Re: Smarter iKettle 2 script for Domoticz

Post by ben53252642 »

It's also possible to control the kettle with a simple bash script for those not wanting to use Python

Usage (change the directory as needed):
/root/smarter/kettle.sh "on"
/root/smarter/kettle.sh "off"

name: kettle.sh

Code: Select all

#!/bin/bash
if [[ $1 == 'on' ]]; then
echo -e '\x21' | nc 192.168.0.85 2081
fi
if [[ $1 == 'off' ]]; then
echo -e '\x16' | nc 192.168.0.85 2081
fi
Unless otherwise stated, all my code is released under GPL 3 license: https://www.gnu.org/licenses/gpl-3.0.en.html
ben53252642
Posts: 543
Joined: Saturday 02 July 2016 5:17
Target OS: Linux
Domoticz version: Beta
Contact:

Re: Smarter iKettle 2 script for Domoticz

Post by ben53252642 »

Trixwood are you able to work out how one would set the temperature?

I've tried many different methods such as:

echo -e '\x21\x32' | nc 192.168.0.85 2081

The x32 translates to 50, if anyone is able to work out temperature it would be hugely appreciated.

Also I've not been successful in getting any detailed responses from the kettle, I can send commands but haven't worked out how to get the responses.

I've been working off exactly the page you linked.
Unless otherwise stated, all my code is released under GPL 3 license: https://www.gnu.org/licenses/gpl-3.0.en.html
trixwood

Re: Smarter iKettle 2 script for Domoticz

Post by trixwood »

No do not have an ikettle, these guys have one

viewtopic.php?t=9861
ben53252642
Posts: 543
Joined: Saturday 02 July 2016 5:17
Target OS: Linux
Domoticz version: Beta
Contact:

Re: Smarter iKettle 2 script for Domoticz

Post by ben53252642 »

That's the iKettle 1 which uses a different protocol unfortunately (I created a new thread for the iKettle 2).

I'll keep working on it and post once I have it figured out.

Cheers
Unless otherwise stated, all my code is released under GPL 3 license: https://www.gnu.org/licenses/gpl-3.0.en.html
trixwood

Re: Smarter iKettle 2 script for Domoticz

Post by trixwood »

Check out this link:

https://github.com/Jamstah/libsmarteram ... umentation

Far better protocol description, Seems you have to end your messages with '0x7e'.
Last edited by trixwood on Friday 29 July 2016 21:42, edited 2 times in total.
ben53252642
Posts: 543
Joined: Saturday 02 July 2016 5:17
Target OS: Linux
Domoticz version: Beta
Contact:

Re: Smarter iKettle 2 script for Domoticz

Post by ben53252642 »

Yep also been looking at that page, interesting the on command mentioned

https://github.com/Jamstah/libsmarteram ... umentation

"0x15 Turn on (iKettle 2.0)."

Doesn't work for my machine, the on command for me is 0x21.

Just been going through working out what does and doesn't work putting a script together.
Unless otherwise stated, all my code is released under GPL 3 license: https://www.gnu.org/licenses/gpl-3.0.en.html
trixwood

Re: Smarter iKettle 2 script for Domoticz

Post by trixwood »

Typos/different versions, more likely two different command options :-)

Try to:

echo -e '\x21\x32\x7e' | nc 192.168.0.85 2081
or
echo -e '\x15\x50\x7e' | nc 192.168.0.85 2081

You are not ending the messages
trixwood

Re: Smarter iKettle 2 script for Domoticz

Post by trixwood »

And what is the output of do you get a status message back?

echo -e '\x14\x7e' | nc 192.168.0.85 2081
ben53252642
Posts: 543
Joined: Saturday 02 July 2016 5:17
Target OS: Linux
Domoticz version: Beta
Contact:

Re: Smarter iKettle 2 script for Domoticz

Post by ben53252642 »

The top one boils the kettle to 100c ignoring the temperature
echo -e '\x21\x32\x7e' | nc 192.168.0.85 2081
this one doesn't do anything
echo -e '\x15\x50\x7e' | nc 192.168.0.85 2081

no messages come back using the bash method, if I use python I'm getting either

i~
or
~

If I connect to the unit via telnet it just sends this every second or so:
?~

I mean not that I really need to be getting messages from the kettle... it's a kettle, boiling is sufficient functionality for me but it would just be nice to see the water level and be able to boil a lower temperature for making certain drinks.
Unless otherwise stated, all my code is released under GPL 3 license: https://www.gnu.org/licenses/gpl-3.0.en.html
trixwood

Re: Smarter iKettle 2 script for Domoticz

Post by trixwood »

Looking at homey plugin for ikettle 2 i notice that they are sending a zero with it:

Code: Select all

var turnOn = new Buffer([21, temperature, 0, 126]);
https://github.com/athombv/am.smarter/b ... ttle2.0.js

So have you tried?

echo -e '\x21\x32\0x00\x7e' | nc 192.168.0.85 2081

and are you sure it not x15 instead of x21?

The garbage output is because you have to decode the bytes.

try passing it to 'od -t x1'

echo -e '\x14\x7e' | nc 192.168.0.85 2081 | od -t x1

now you can read it as described in the protocol (for test purposes)
ben53252642
Posts: 543
Joined: Saturday 02 July 2016 5:17
Target OS: Linux
Domoticz version: Beta
Contact:

Re: Smarter iKettle 2 script for Domoticz

Post by ben53252642 »

This is interesting

root@Domoticz:~/smarter# python kettle.py "status" | od -t x1
0000000 03 00 7e 0a
0000004

im sending \x100\0x00\x7e which should be for status

the 03 is for command acknowledged :)
Unless otherwise stated, all my code is released under GPL 3 license: https://www.gnu.org/licenses/gpl-3.0.en.html
trixwood

Re: Smarter iKettle 2 script for Domoticz

Post by trixwood »

it seems (from the same homey plugin code)

that to keep your kettle warm you can use

Code: Select all

enableKeepWarm(temperature, minutes) {
...
 new Buffer([21, temperature, minutes, 126])
...
that means the added 0 in the previous post is the time it keeps the kettle on temperature after it boils (i think that it).

Anyway good luck!
trixwood

Re: Smarter iKettle 2 script for Domoticz

Post by trixwood »

btw monday/tuesday I can play with the real thing! So if you finish before that would be nice! :mrgreen:
ben53252642
Posts: 543
Joined: Saturday 02 July 2016 5:17
Target OS: Linux
Domoticz version: Beta
Contact:

Re: Smarter iKettle 2 script for Domoticz

Post by ben53252642 »

lol, good choice, the kettle is very good quality. :D
Unless otherwise stated, all my code is released under GPL 3 license: https://www.gnu.org/licenses/gpl-3.0.en.html
trixwood

Re: Smarter iKettle 2 script for Domoticz

Post by trixwood »

119 euro for europe verions

https://www.rovara.nl/smarter-ikettle-2 ... 0wodkF8E-g

108 euro for uk version

http://www.zavvi.nl/cadeau-huis-kantoor ... aign=Zanox

Still fragging expensive.
Post Reply

Who is online

Users browsing this forum: Google Adsense [Bot] and 1 guest