Super que tout marche bien ! Non, pas besoin de la béta. Il suffit d'utiliser une version stable après mars 2016.
Code : Tout sélectionner
#!/usr/bin/python
# domo2vito
# JS MARTIN - 05/2016
# version 1.4
import telnetlib
import sys
import os
import time
import requests
from requests.auth import HTTPBasicAuth
import json
############# Parameters #################################
#~~~~~~~~~~ Parameters Domoticz ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
domoticz_ip='192.168.10.40'
domoticz_port='8080'
user=''
password=''
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Commands viTalk
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#autorized commands
commands = ["mode","saving","party","party_soll_temp","outdoor_temp","raum_soll_temp","raum_ist_temp","k_ist_temp","ww_soll_temp","ww_ist_temp","k_abgas_temp","power","errors"]
#write only commands
write_only_commands = ["mode","saving","party","party_soll_temp","ww_soll_temp"]
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# IDX de Domoticz
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# remplacer XXX par votre idx de votre widget
dummy_idx={'mode':343, 'saving': 344, 'party':345, 'party_soll_temp':346, 'outdoor_temp':347, 'raum_soll_temp':355, 'raum_ist_temp':349, 'k_ist_temp':350, 'ww_soll_temp':351, 'ww_ist_temp':352, 'k_abgas_temp':353, 'power':354, 'error_log':371, 'problem':416}
# mode : dummy selector switch OFF/Water/Heating (Boiler [FR:chaudiere] stand-by/water only/water+heating)
# saving : dummy switch ON/OFF (Boiler eco ON/OFF)
# party : dummy switch ON/OFF (party temporary manual control)
# party_soll_temp: dummy thermostat setpoint (party temperature)
# outdoor_temp : dummy temp (outdoor temperature)
# raum_soll_temp : dummy temp (heating setpoint [FR:consigne] temperature) - note : without vitotronic, use thermostat setpoint
# raum_ist_temp : dummy temp (heating current [FR:actuelle] temperature)
# k_ist_temp : dummy temp (boiler current temperature)
# ww_soll_temp : dummy temp (hot water setpoint temperature)
# ww_ist_temp : dummy temp (hot water current temperature)
# k_abgas_temp : dummy temp (exhaust gas [FR:gaz evacue'] temperature)
# power : dummy percentage (% boiler power)
# error_log : dummy alert (show the two last log codes)
# problem : dummy switch (set switch to On if there is a internal boiler problem)
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Mode debug
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# if debug = True => verbose
debug=True
#######################################################################
###### viTalk_connect() : connect to viTalk localhost:83
#######################################################################
def viTalk_connect():
retry=3
while retry!=0:
try:
tn = telnetlib.Telnet("localhost", 83)
print "Connected to viTalk telnet !"
return tn
except:
print "Connection ERROR - I try to restart viTalk deamon"
#I try to restart viTalk
cmd = 'sudo service vitalk restart'
os.system(cmd)
time.sleep(10)
retry-=1
else:
tn.read_until(b"$", 5)
if retry==0:
tn.close()
print "Connection ERROR - I could not restart viTalk deamon"
sys.exit()
######
#######################################################################
###### viTalk_read(cmd) : read a value
#######################################################################
def viTalk_read(cmd):
global debug
global tn
retry=3
value=""
while retry!=0:
tn.read_until(b"$", 5)
tn.write(b"g "+cmd+"\n")
value=tn.read_until(b"$", 5).strip("\n$")
if value!="" and value!='NULL':
break
retry-=1
if retry==0:
print "Connection ERROR - I try to restart viTalk deamon"
os.system('sudo service vitalk restart')
#tn.close()
print(cmd+": "+value+" error")
sys.exit()
value = value.strip("\n$")
if debug:
print "get "+cmd+" : answer = "+value
return value
######
#######################################################################
###### viTalk_check() : test viTalk and restart it if needed
#######################################################################
def viTalk_check():
global debug
global tn
retry=3
value=""
while retry!=0:
tn.read_until(b"$", 5)
tn.write(b"g mode \n")
value=tn.read_until(b"$", 5).strip("\n$")
if value!="" and value!='NULL':
if debug:
print "Check viTalk data OK ! (no NULL data received)"
break
retry-=1
if retry==0:
print "Connection ERROR - I try to restart viTalk deamon"
os.system('sudo service vitalk restart')
sys.exit()
######
#######################################################################
###### viTalk_set(cmd,val) : unsecured write
#######################################################################
def viTalk_set(cmd,val):
global debug
global tn
tn.write(b"s "+cmd+" "+val+"\n")
tn.read_until(b"$", 5).strip("\n$")
if debug:
print("set "+cmd+" "+val)
######
#######################################################################
###### viTalk_write(cmd,val) : secured write (I check if value is
###### really updated)
#######################################################################
def viTalk_write(cmd,val):
global debug
global tn
retry=3
value=""
while retry!=0:
viTalk_set(cmd,val)
tn.read_until(b"$", 5)
value=viTalk_read(cmd)
if val==value:
break
retry-=1
if retry==0:
tn.close()
print(cmd+" "+val+" : error")
sys.exit()
if debug:
print "check last command set "+cmd+" "+val+" : OK"
#########
#######################################################################
###### check_command(cmd) : is it an authorized command ?
#######################################################################
def check_command(cmd):
global commands
global debug
try:
#check position of cmd in commands list
commands.index(cmd)
except:
print "command not found"
return False
else:
if debug:
print "this command "+cmd+" is known"
return True
####
#######################################################################
###### check_set_command(cmd) : is it an authorized write command ?
#######################################################################
def check_set_command(cmd):
global commands
global debug
try:
#check position of cmd in write only commands list
write_only_commands.index(cmd)
except:
print "set command not found (I can't write with this command)"
return False
else:
if debug:
print "this command "+cmd+" is known for writing"
return True
####
#######################################################################
###### get_setpoint_temp(idx) : get temperature from domoticz setpoint
#######################################################################
def get_setpoint_temp(idx):
r = requests.get('http://'+domoticz_ip+':'+domoticz_port+'/json.htm?type=devices&rid='+str(idx),auth=HTTPBasicAuth(user,password))
status=r.status_code
if status == 200:
r=r.json()
result={}
return r['result'][0]['Data']
else:
print "Get setpoint temp error - IDX:"+str(idx)
####
########################################################################
###### get_boiler_state(idx) : get boiler state(OK or not) from domoticz
########################################################################
def get_boiler_state(idx):
r = requests.get('http://'+domoticz_ip+':'+domoticz_port+'/json.htm?type=devices&rid='+str(idx),auth=HTTPBasicAuth(user,password))
status=r.status_code
if status == 200:
r=r.json()
result={}
return r['result'][0]['Data']
else:
print "Get state error - IDX:"+str(idx)
####
#-----------------------------------### START ###--------------------------------------------#
# arguments in command line
nb_arg=len(sys.argv)-1
if nb_arg==0:
print "HELP : "
print "domo2vito update : update all domoticz values"
print "domo2vito command : get command (e.g. domo2vito mode <=> get mode)"
print "domo2vito command value : set command value (e.g. domo2vito mode 1 <=> set mode 1)"
if nb_arg==1 and sys.argv[1]!="update":
if check_command(sys.argv[1]):
if debug:
print "get "+sys.argv[1]
tn=viTalk_connect()
viTalk_read(sys.argv[1])
tn.close()
if nb_arg==1 and sys.argv[1]=="update":
tn=viTalk_connect()
viTalk_check()
values=[]
i=0
tn.read_until(b"$", 5)
for command in commands:
tn.write(b"g "+command+"\n")
value=tn.read_until(b"$", 5).strip("\n$")
if debug:
print str(i)+") command : get "+command+ " => "+value
values.append(value)
i+=1
# get setpoint party_soll_temp and update boiler if needed
temp=int(float(get_setpoint_temp(dummy_idx['party_soll_temp'])))
if temp!=int(float(values[3])): #Viessmann ignore decimales
if debug:
print "party setpoint has changed : I update it!"
if temp<12: # party mini temp
temp=12
if temp>25: # party maxi temp
temp=25
viTalk_set("party_soll_temp",str(temp))
# get setpoint ww_soll_temp and update boiler if needed
temp=int(float(get_setpoint_temp(dummy_idx['ww_soll_temp'])))
if temp!=int(float(values[8])): #Viessmann ignore decimales
if debug:
print "hot water setpoint has changed : I update it!"
if temp<20: # hot water mini temp
temp=20
if temp>70: # hot water maxi temp
temp=70
viTalk_set("ww_soll_temp",str(temp))
tn.close()
#mode (selector level : 0=OFF 10=water 20=heating)
req='http://'+domoticz_ip+':'+domoticz_port+'/json.htm?type=command¶m=switchlight&idx='+str(dummy_idx['mode'])+'&switchcmd=Set%20Level&level='+str(int(values[0])*10)
requests.get(req,auth=HTTPBasicAuth(user,password))
# saving : dummy switch ON/OFF (Boiler eco ON/OFF) : if a user modify boiler or vitotrol, update Domoticz
if values[1]=="0":
req='http://'+domoticz_ip+':'+domoticz_port+'/json.htm?type=command¶m=switchlight&idx='+str(dummy_idx['saving'])+'&switchcmd=Off'
else:
req='http://'+domoticz_ip+':'+domoticz_port+'/json.htm?type=command¶m=switchlight&idx='+str(dummy_idx['saving'])+'&switchcmd=On'
requests.get(req,auth=HTTPBasicAuth(user,password))
# party : dummy switch ON/OFF (party temporary manual control) : if a user modify boiler or vitotrol, update Domoticz
if values[2]=="0":
req='http://'+domoticz_ip+':'+domoticz_port+'/json.htm?type=command¶m=switchlight&idx='+str(dummy_idx['party'])+'&switchcmd=Off'
else:
req='http://'+domoticz_ip+':'+domoticz_port+'/json.htm?type=command¶m=switchlight&idx='+str(dummy_idx['party'])+'&switchcmd=On'
requests.get(req,auth=HTTPBasicAuth(user,password))
# party_soll_temp: dummy thermostat setpoint (party temperature) note:Domoticz setpoint manage this parameter
#req='http://'+domoticz_ip+':'+domoticz_port+'/json.htm?type=command¶m=udevice&idx='+str(dummy_idx['party_soll_temp'])+'&nvalue=0&svalue='+values[3]
#requests.get(req,auth=HTTPBasicAuth(user,password))
# outdoor_temp : dummy temp (outdoor temperature)
req='http://'+domoticz_ip+':'+domoticz_port+'/json.htm?type=command¶m=udevice&idx='+str(dummy_idx['outdoor_temp'])+'&nvalue=0&svalue='+values[4]
requests.get(req,auth=HTTPBasicAuth(user,password))
# raum_soll_temp : dummy temp (heating setpoint [FR:consigne] temperature) - note : without vitotronic, use thermostat setpoint
req='http://'+domoticz_ip+':'+domoticz_port+'/json.htm?type=command¶m=udevice&idx='+str(dummy_idx['raum_soll_temp'])+'&nvalue=0&svalue='+values[5]
requests.get(req,auth=HTTPBasicAuth(user,password))
# raum_ist_temp : dummy temp (heating current [FR:actuelle] temperature)
req='http://'+domoticz_ip+':'+domoticz_port+'/json.htm?type=command¶m=udevice&idx='+str(dummy_idx['raum_ist_temp'])+'&nvalue=0&svalue='+values[6]
requests.get(req,auth=HTTPBasicAuth(user,password))
# k_ist_temp : dummy temp (boiler current temperature)
req='http://'+domoticz_ip+':'+domoticz_port+'/json.htm?type=command¶m=udevice&idx='+str(dummy_idx['k_ist_temp'])+'&nvalue=0&svalue='+values[7]
requests.get(req,auth=HTTPBasicAuth(user,password))
# ww_soll_temp : dummy setpoint (hot water setpoint temperature) note:Domoticz setpoint manage this parameter
#req='http://'+domoticz_ip+':'+domoticz_port+'/json.htm?type=command¶m=udevice&idx='+str(dummy_idx['ww_soll_temp'])+'&nvalue=0&svalue='+values[8]
#requests.get(req,auth=HTTPBasicAuth(user,password))
# ww_ist_temp : dummy temp (hot water current temperature)
req='http://'+domoticz_ip+':'+domoticz_port+'/json.htm?type=command¶m=udevice&idx='+str(dummy_idx['ww_ist_temp'])+'&nvalue=0&svalue='+values[9]
requests.get(req,auth=HTTPBasicAuth(user,password))
# k_abgas_temp : dummy temp (exhaust gas [FR:gaz evacue'] temperature)
req='http://'+domoticz_ip+':'+domoticz_port+'/json.htm?type=command¶m=udevice&idx='+str(dummy_idx['k_abgas_temp'])+'&nvalue=0&svalue='+values[10]
requests.get(req,auth=HTTPBasicAuth(user,password))
# power : dummy percentage (% boiler power)
req='http://'+domoticz_ip+':'+domoticz_port+'/json.htm?type=command¶m=udevice&idx='+str(dummy_idx['power'])+'&nvalue=0&svalue='+values[11]
requests.get(req,auth=HTTPBasicAuth(user,password))
# error_log : dummy alert (show the two last log codes)
# problem : dummy switch (set switch to On if there is a internal boiler problem)
#values[12]="123,255,235,244,244,244,244,244,244,244 ;"
V_error=values[12][0:3]
V_previous_error=values[12][4:7]
V_error_hexa=str(hex(int(V_error)))[2:4] # hexa convertion
V_previous_error_hexa=str(hex(int(V_previous_error)))[2:4] # hexa convertion
V_previous_error_state=get_boiler_state(str(dummy_idx['error_log']))[0:2]
V_previous_problem_state=get_boiler_state(str(dummy_idx['problem']))
if V_error=="000":
if debug:
print "no internal error : all it is OK"+" (previous code="+V_previous_error_hexa+")"
if V_previous_error_state!="OK": # I update error_log alert only if state is modified
req='http://'+domoticz_ip+':'+domoticz_port+'/json.htm?type=command¶m=udevice&idx='+str(dummy_idx['error_log'])+'&nvalue=1&svalue='+'OK (previous='+V_previous_error_hexa+')'
requests.get(req,auth=HTTPBasicAuth(user,password))
if V_previous_problem_state=="On": # I update problem switch only if state is modified
if debug:
print "State of boiler error status changed (no problem): I update the Domotics boiler problem switch"
req='http://'+domoticz_ip+':'+domoticz_port+'/json.htm?type=command¶m=switchlight&idx='+str(dummy_idx['problem'])+'&switchcmd=Off'
requests.get(req,auth=HTTPBasicAuth(user,password))
else:
if debug:
print "There is an internal error : code="+V_error_hexa+" ( previous ="+V_previous_error_hexa+")"
if V_previous_error_state!=V_error_hexa: # I update error_log alert only if state is modified
req='http://'+domoticz_ip+':'+domoticz_port+'/json.htm?type=command¶m=udevice&idx='+str(dummy_idx['error_log'])+'&nvalue=4&svalue='+V_error_hexa+' error (previous='+V_previous_error_hexa+')'
requests.get(req,auth=HTTPBasicAuth(user,password))
if V_previous_problem_state=="Off": # I update problem switch only if state is modified
if debug:
print "State of boiler error status changed (problem): I update the Domotics boiler problem switch"
req='http://'+domoticz_ip+':'+domoticz_port+'/json.htm?type=command¶m=switchlight&idx='+str(dummy_idx['problem'])+'&switchcmd=On'
requests.get(req,auth=HTTPBasicAuth(user,password))
if nb_arg==2:
if check_set_command(sys.argv[1]):
print "set "+sys.argv[1]+" "+sys.argv[2]
tn=viTalk_connect()
viTalk_write(sys.argv[1],sys.argv[2])
tn.close()