EDIT : 09 mars 2017 - Mise à jour du premier message pour rassembler toutes les informations nécessaires !
La base du travail est ici : https://openv.wikispaces.com/
C'est en allemand et pas toujours bien documenté.
Un très bon tuto en français qui est une bonne base de départ :
https://www.bricozone.fr/t/interface-vi ... -pi.14671/
Le principe :
Les deux LED d'état qui sont sur la chaudière sont aussi des recepteurs/emetteurs IR série. Il est donc possible de tout faire par le biais de ces LED sans connexion directe avec la chaudière.
Sur le site Allemand OpenV, l'interface documentée est OptoLink USB qui vaut 40€
Il est possible de se fabriquer son interface USB ou série. Ce n'est pas très compliqué et le coût est d'environ 15€. J'ai commencé à en parler ici : viewtopic.php?f=8&t=1891
Le montage maison :
sur une plaque d'essai trouvée sur eBay (moins de 1€) :
L'implantation :
l'installation des LEDs sur ma chaudière (Vitodens 222-W) :
Note : la LED noire est à droite, la violette à gauche
Le branchement :
Deux solutions :
1/ en serie directement sur le raspberry (/dev/ttyAMA0)
Le 3,3V et la masse sur les broches du raspberry (1 et 9 pour le Pi2/3)
Le TXD/RXD sur les broches 8 et 10 (Pi2/3)
Note : sur PI3, il faut impérativement ajouter dans le /boot/config.txt
Code : Tout sélectionner
dtoverlay=pi3-miniuart-bt
enable_uart=1
2/ en USB avec un adaptateur (/dev/ttyUSB0)
pour 1€ environ : convertisseur PL2303 USB <-> série.
Il faut choisir un adatateur qui gère le 3,3V et cela fonctionne parfaitement.
Comme la chaudière n'est pas à coté de mon Raspberry domoticz, j'ai tiré un cable RJ45 de 15m entre mon interface et le Pi : aucun problème de communication ! J'ai aussi un cable de 1m entre l'interface et les deux LED IR.
Pi <==15m - 4 fils nécessaires (3,3V/GND/TXD/RXD)==> interface optique <==1m - 4 fils nécessaire (2 fils par led)==> leds sur la chaudière
ViTalk : l'interface Telnet
Le code est disponible ici : https://github.com/klauweg/vitalk
ou via ce forum qui détaille bien ces étapes : https://www.bricozone.fr/t/interface-vi ... -pi.14671/
il faut le récupérer et le compiler :
Code : Tout sélectionner
sudo make install
Code : Tout sélectionner
sudo vitalk -t /dev/ttyAMA0
Code : Tout sélectionner
sudo vitalk -t /dev/ttyUSB0
Code : Tout sélectionner
Reset Communication to KW Proto..Success.
Try Proto 300 Init: Success.
Now listening to telnet Port 83
New connection from 127.0.0.1 on socket 5
Code : Tout sélectionner
telnet localhost 83
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
Welcome at vitalk, the Vitodens telnet Interface. (5)
Code : Tout sélectionner
$h
Short Help Text:
h, help - This Help Text
frame_debug <on/off> - Set state of Frame Debugging
list [class] - Show parameter List
g, get <p_name> - Query Parameter
gvu <p_name> - Get Value of Parameter with Unit
s, set <p_name> <value> - Set Parameter
gc <class> - Query a class of Parameters
Parameterklassen:
P_ALLE 0
P_ERRORS 1
P_ALLGEMEIN 2
P_KESSEL 3
P_WARMWASSER 4
P_HEIZKREIS 5
P_BRENNER 6
P_HYDRAULIK 7
Code : Tout sélectionner
$g raum_soll_temp
19
Code : Tout sélectionner
$s raum_soll_temp 20
OK
Code : Tout sélectionner
$s mode 0
Code : Tout sélectionner
$s mode 1
Code : Tout sélectionner
$s mode 2
Code : Tout sélectionner
$gc
deviceid: 0x20cb ;
mode: 2 ;
time: 00:34:43 ;
saving: 0 ;
party: 1 ;
mode_text: Heating and hot water ;
outdoor_temp: 8.90 oC;
outdoor_temp_tp: 8.90 oC;
outdoor_temp_smooth: 10.30 oC;
k_ist_temp: 39.00 oC;
k_ist_temp_tp: 39.00 oC;
k_soll_temp: 5.00 oC;
k_abgas_temp: 45.50 oC;
ww_soll_temp: 42 oC;
ww_ist_temp: 34.80 oC;
ww_ist_temp_tp: 34.80 oC;
ww_offset: 20 K;
vl_soll_temp: 0.00 oC;
raum_soll_temp: 19 oC;
raum_ist_temp: 20.30 oC;
red_raum_soll_temp: 14 oC;
party_soll_temp: 19 oC;
niveau: 0 K;
neigung: 1.1 ;
pp_max: 65 %;
pp_min: 30 %;
starts: 94442 ;
runtime_h: 6402.1 h;
runtime: 23047646 s;
power: 0.0 %;
ventil: 3 ;
ventil_text: Warm Water ;
pump_power: 0 %;
circ_pomp: 1 ;
WW_pomp: 0 ;
H_pomp: 0 ;
Code : Tout sélectionner
frame_debug on
Code : Tout sélectionner
TX: Data: 0x41 0x05 0x00 0x01 0x00 0xf8 0x02 0x00
RX: Data: 0x41 0x07 0x01 0x01 0x00 0xf8 0x02 0x20 0xcb 0xee
Liaison avec Domoticz
Je vous propose mon code Python qui va faire le lien entre viTalk et Domoticz.
Ce code "domo2vito" permet :
- de changer le mode de la chaudière (Off / ECS / ECS+chauffage avec programmation / mode vacances / ECS + chauffage On permanent)
- de régler le mode ECO (saving)
- de voir l'état du mode "Cocktail"(party) et de l'arreter (l'activation ne marche pas. Toutefois, avec le réglage du mode, ce n'est pas très génant)
- de régler la température du mode cocktail
- de visualiser la température de la sonde extérieure
- de connaitre la température de consigne (il est possible de la régler si vous n'avez pas de commande à distance type Vitorol 300)
- de connaitre la température réelle mesurée par la sonde intérieure (si elle existe)
- de connaitre la température de la chaudière
- de régler la température d'Eau Chaude Sanitaire (ECS)
- de connaitre la température des gaz de la chaudière
- de la puissance instantanée de la chaudière (en pourcentage)
- des éventuelles erreurs dans les logs de la chaudière (deux derniers événements)
- de régler un interrupteur qui passe à On en cas d'anomalie chaudière
- de mesurer le temps de fonctionnement en seconde de la chaudière entre deux appels du programme
- d'estimer la consommation de gaz de la chaudière
- de régler la température du mode réduit
- de régler la température du mode vacances
- en option, de régler la température du mode normal
Les réglages des températures via Domoticz implique que les réglages des températures via la chaudière soient inopérant. C'est pour cela que pour la température de consigne "normale", je ne recommande pas d'activer cette option (dans le code, elle est désactivée par défaut).
Le programme domo2vito.py (pensez à faire le "sudo chmod +x domo2vito.py " pour le rendre executable)
Code : Tout sélectionner
#!/usr/bin/python
# domo2vito
# JS MARTIN
# version 2.11 - 07032017
import telnetlib
import sys
import os
import time
import requests
from requests.auth import HTTPBasicAuth
import json
############# Parameters #################################
#~~~~~~~~~~ Parameters Domoticz ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
domoticz_ip='192.168.0.41'
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","runtime","red_raum_soll_temp"]
#write only commands
write_only_commands = ["mode","saving","party","party_soll_temp","ww_soll_temp","red_raum_soll_temp","raum_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, 'delta-rt': 537, 'gas':538, 'red_raum_soll_temp':548, 'holiday_temp':549, 'raum_soll_temp_W':577}
user_idx={'runtime-boiler':1} # please create a user variable [integer] (overall boiler time) - see https://www.domoticz.com/wiki/User_variables
# 0 mode : dummy selector switch OFF/Water/Heating (Boiler [FR:chaudiere] stand-by/water only/water+heating) {read/write}
# 1 saving : dummy switch ON/OFF (Boiler eco ON/OFF) {read/write}
# 2 party : dummy switch ON/OFF (party temporary manual control) - note : party ON does not work (vitalk bug ?) {read/write}
# 3 party_soll_temp : dummy thermostat setpoint (party temperature) {write only}
# 4 outdoor_temp : dummy temp (outdoor temperature) {read only}
# 5 raum_soll_temp : dummy temp (heating [FR:consigne] temperature ) {read only} - note : without vitotronic, you could use thermostat setpoint
# 6 raum_ist_temp : dummy temp (heating current [FR:actuelle] temperature) {read only}
# 7 k_ist_temp : dummy temp (boiler current temperature) {read only}
# 8 ww_soll_temp : dummy thermostat setpoint (hot water setpoint temperature) {write only}
# 9 ww_ist_temp : dummy temp (hot water current temperature) {read only}
#10 k_abgas_temp : dummy temp (exhaust gas [FR:gaz evacue'] temperature) {read only}
#11 power : dummy percentage (% boiler power) {read only}
#12 error_log : dummy alert (show the two last log codes) {read only}
# problem : dummy switch (set switch to On if there is a internal boiler problem)
#13 runtime : custom sensor [seconds] (Operating time of boiler since last script call) {read only}
# gas : dummy incremental counter [gas] (Estimation of Gas consumtion)
#14 red_raum_soll_temp: dummy thermostat setpoint (reduced temperature) {write only}
# holiday_temp : dummy thermostat setpoint (holiday temperature)
# raum_soll_temp_W : dummy thermostat setpoint (normal temperature) {write only} - note : does not work with vitotrol 300
# |_ for raum_soll_temp_W, you need to put the bolean Use_normal_temperature_setpoint to True
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Mode debug
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# if debug = True => verbose
debug=True
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Variable
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#Debit max gas (need to be adjust to synchronize estimated and real gas consumption)
Deb=0.1099 #0.12 = trop fort 1400 l / 0.09 = trop faible 390 l - 1min
# 0.136 - 3min
# Activated normal temperature setpoint
Use_normal_temperature_setpoint=False
#######################################################################
###### viTalk_connect() : connect to viTalk localhost:83
#######################################################################
def viTalk_connect():
global debug
retry=3
while retry!=0:
try:
tn = telnetlib.Telnet("localhost", 83)
if debug:
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 saving \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
if cmd!="mode":
tn.write(b"s "+cmd+" "+val+"\n")
else: # vitalk does not manage mode 3 and 4 => raw set directly
tn.write(b"rs 2323 "+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)
time.sleep(1)
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_state(idx) : get dummy state from domoticz
########################################################################
def get_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)+" not found ?"
####
########################################################################
###### get_last_runtime(idx) : get last runtime value from domoticz
########################################################################
def get_last_runtime(idx):
r = requests.get('http://'+domoticz_ip+':'+domoticz_port+'/json.htm?type=command¶m=getuservariable&idx='+str(idx),auth=HTTPBasicAuth(user,password))
status=r.status_code
if status == 200:
r=r.json()
result={}
return r['result'][0]['Value']
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)"
print "--> supported commands :"
for command in commands:
print " - "+command
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
if debug: print "+Now I check if I need to update some values into Viessmann boiler or into Domoticz..."
mcur=time.localtime().tm_min # to update setpoint one time every hour - get minute of current hour
if mcur>40 and mcur<46: # Heartbeat - update setpoint in Domoticz one time per hour just to avoid "lost widget status"
setpoint_heartbeat=True
else:
setpoint_heartbeat=False
# party_soll_temp : 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 temp<10: temp=10 # party mini temp
if temp>30: temp=30 # party maxi temp
if debug: print "3) party setpoint has changed : I update Viessmann boiler with party temperature = "+str(temp)
viTalk_set("party_soll_temp",str(temp))
else:
if setpoint_heartbeat:
req='http://'+domoticz_ip+':'+domoticz_port+'/json.htm?type=command¶m=udevice&idx='+str(dummy_idx['party_soll_temp'])+'&nvalue=0&svalue='+str(temp)
requests.get(req,auth=HTTPBasicAuth(user,password))
# 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 temp<20: temp=20 # hot water mini temp
if temp>70: temp=70 # hot water maxi temp
if debug: print "8) hot water setpoint has changed : I update Viessmann boiler with hot water temperature = "+str(temp)
viTalk_set("ww_soll_temp",str(temp))
else:
if setpoint_heartbeat:
req='http://'+domoticz_ip+':'+domoticz_port+'/json.htm?type=command¶m=udevice&idx='+str(dummy_idx['ww_soll_temp'])+'&nvalue=0&svalue='+str(temp)
requests.get(req,auth=HTTPBasicAuth(user,password))
# holiday mode : emulated* holiday mode *I put boiler in permanent reduce mode with a custom holiday temp
if int(values[0])==3: # mode 'permanent reduce'
if debug: print "Holiday mode : I check if reduced temp. = domoticz holiday setpoint temp."
temp=int(float(get_setpoint_temp(dummy_idx['holiday_temp'])))
if temp!=int(float(values[14])):
if temp<10: temp=10 # holidays mini temp
if temp>30: temp=30 # holidays maxi temp
viTalk_set("red_raum_soll_temp",str(temp)) # Reduced temp = domoticz holiday temp
if debug: print "- I update reduced temperature with domoticz holiday setpoint temperature"
else:
# get setpoint red_raum_soll_temp and update boiler if needed
if debug: print "NOT Holiday mode : I check if reduced temp. = domoticz reduced setpoint temp."
temp=int(float(get_setpoint_temp(dummy_idx['red_raum_soll_temp'])))
if temp!=int(float(values[14])): #Viessmann ignore decimales
if temp<10: temp=10 # reduced mini temp
if temp>30: temp=30 # reduced maxi temp
if debug: print "14) Reduced temp setpoint has changed : I update Viessmann boiler with reduced temperature = "+str(temp)
viTalk_set("red_raum_soll_temp",str(temp))
if Use_normal_temperature_setpoint:
if debug: print "Use_normal_temperature_setpoint => activated"
temp=int(float(get_setpoint_temp(dummy_idx['raum_soll_temp_W'])))
if temp!=int(float(values[5])): #Viessmann ignore decimales
if temp<10: temp=10 # reduced mini temp
if temp>30: temp=30 # reduced maxi temp
if debug: print "15) Normal temp setpoint has changed : I update Viessmann boiler with normal temperature = "+str(temp)
viTalk_set("raum_soll_temp",str(temp))
if setpoint_heartbeat:
temp=int(float(get_setpoint_temp(dummy_idx['holiday_temp'])))
if temp<10: temp=10 # holidays mini temp
if temp>30: temp=30 # holidays maxi temp
req='http://'+domoticz_ip+':'+domoticz_port+'/json.htm?type=command¶m=udevice&idx='+str(dummy_idx['holiday_temp'])+'&nvalue=0&svalue='+str(temp)
requests.get(req,auth=HTTPBasicAuth(user,password))
temp=int(float(get_setpoint_temp(dummy_idx['red_raum_soll_temp'])))
if temp<10: temp=10 # reduced mini temp
if temp>30: temp=30 # reduced maxi temp
req='http://'+domoticz_ip+':'+domoticz_port+'/json.htm?type=command¶m=udevice&idx='+str(dummy_idx['red_raum_soll_temp'])+'&nvalue=0&svalue='+str(temp)
requests.get(req,auth=HTTPBasicAuth(user,password))
if Use_normal_temperature_setpoint:
temp=int(float(get_setpoint_temp(dummy_idx['raum_soll_temp_W'])))
if temp<10: temp=10 # normal mini temp
if temp>30: temp=30 # normal maxi temp
req='http://'+domoticz_ip+':'+domoticz_port+'/json.htm?type=command¶m=udevice&idx='+str(dummy_idx['raum_soll_temp_W'])+'&nvalue=0&svalue='+str(temp)
requests.get(req,auth=HTTPBasicAuth(user,password))
tn.close()
# mode (selector level : 0=OFF 10=water 20=heating 30=holidays 40=always On)
previous_value=get_state(dummy_idx['mode'])
if previous_value=="Off": previous_value="Set Level: 0 %"
if int(previous_value[11:-1])!=int(values[0])*10:
if debug: print "0) Value MODE has changed : I update domoticz with mode = "+values[0]
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
previous_value=get_state(dummy_idx['saving'])
if (previous_value=="On" and values[1]=="0") or (previous_value=="Off" and values[1]=="1"):
if debug: print "1) Value SAVING has changed : I update domoticz with saving = "+values[1]
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
previous_value=get_state(dummy_idx['party'])
if (previous_value=="On" and values[2]=="0") or (previous_value=="Off" and values[2]=="1"):
if debug: print "2) Value PARTY has changed : I update domoticz with party = "+values[2]
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))
# 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_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)
previous_power_value=get_state(dummy_idx['power'])[:-1] # on supprime le % a la fin de la chaine
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))
# Get previous boiler runtime value from Domoticz database (user variable)
last_rt=int(get_last_runtime(user_idx['runtime-boiler']))
delta_rt=int(values[13])-last_rt # delta-runtime
# update boiler-runtime since last update
req='http://'+domoticz_ip+':'+domoticz_port+'/json.htm?type=command¶m=udevice&idx='+str(dummy_idx['delta-rt'])+'&nvalue=0&svalue='+str(delta_rt)
requests.get(req,auth=HTTPBasicAuth(user,password))
# Set overall boiler runtime into Domoticz database (user variable)
req='http://'+domoticz_ip+':'+domoticz_port+'/json.htm?type=command¶m=updateuservariable&idx='+str(user_idx['runtime-boiler'])+'&vname=runtime-boiler&vtype=0&vvalue='+values[13]
requests.get(req,auth=HTTPBasicAuth(user,password))
if debug: print "+Now I calculate the gas consumed since last script call:"
# gas : gas estimation
power_average=(float(previous_power_value)+float(values[11]))/2
gas_used=delta_rt*Deb*power_average/100
if debug:
print " -Viessmann boiler runtime since last script call (sec) = "+str(delta_rt)
print " -Viessmann boiler power average (%) = "+ str(power_average)
print " -Estimated gas used (liter) = "+str(gas_used)
req='http://'+domoticz_ip+':'+domoticz_port+'/json.htm?type=command¶m=udevice&idx='+str(dummy_idx['gas'])+'&nvalue=0&svalue='+str(gas_used)
requests.get(req,auth=HTTPBasicAuth(user,password))
if debug: print "+Now I check boiler error..."
# 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_state(str(dummy_idx['error_log']))[0:2]
V_previous_problem_state=get_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()
Pour une mise à jour régulière :
ajouter dans la crontable (crontab -e) la ligne :
Code : Tout sélectionner
*/3 * * * * /home/pi/domoticz/scripts/python/domo2vito.py update
La liste de tous les widgets à creer dans Domoticz :
Code : Tout sélectionner
# 0 mode : dummy selector switch OFF/Water/Heating (Boiler [FR:chaudiere] stand-by/water only/water+heating) {read/write}
# 1 saving : dummy switch ON/OFF (Boiler eco ON/OFF) {read/write}
# 2 party : dummy switch ON/OFF (party temporary manual control) - note : party ON does not work (vitalk bug ?) {read/write}
# 3 party_soll_temp : dummy thermostat setpoint (party temperature) {write only}
# 4 outdoor_temp : dummy temp (outdoor temperature) {read only}
# 5 raum_soll_temp : dummy temp (heating [FR:consigne] temperature ) {read only} - note : without vitotronic, you could use thermostat setpoint
# 6 raum_ist_temp : dummy temp (heating current [FR:actuelle] temperature) {read only}
# 7 k_ist_temp : dummy temp (boiler current temperature) {read only}
# 8 ww_soll_temp : dummy thermostat setpoint (hot water setpoint temperature) {write only}
# 9 ww_ist_temp : dummy temp (hot water current temperature) {read only}
#10 k_abgas_temp : dummy temp (exhaust gas [FR:gaz evacue'] temperature) {read only}
#11 power : dummy percentage (% boiler power) {read only}
#12 error_log : dummy alert (show the two last log codes) {read only}
# problem : dummy switch (set switch to On if there is a internal boiler problem)
#13 runtime : custom sensor [seconds] (Operating time of boiler since last script call) {read only}
# gas : dummy incremental counter [gas] (Estimation of Gas consumtion)
#14 red_raum_soll_temp: dummy thermostat setpoint (reduced temperature) {write only}
# holiday_temp : dummy thermostat setpoint (holiday temperature)
# raum_soll_temp_W (option) : dummy thermostat setpoint (normal temperature) {write only} - note : does not work with vitotrol 300
# |_ for raum_soll_temp_W, you need to put the bolean Use_normal_temperature_setpoint to True
(dans Domoticz : Reglage->Plus d'options->Variable utilisateur)
Code : Tout sélectionner
runtime-boiler : user variable [integer] (overall boiler time)
Le widget mode (selector) :
et sa configuration :
Les widgets switchs :
La configuration des switchs est très simple : il suffit de rajouter le script python et les paramètres en arguments :
(idem avec party en remplacant "saving" par "party") / note : viTalk ne fonctionne pas totalement avec le mode party : si party est activé, il est possible de le désactiver mais pas l'inverse) ; le mode saving fonctionne (si la chaudière est en mode chauffage bien entendu).
Pour les widgets température, il n'y a pas de difficulté :
Enfin, voici les widgets mesures :
Dans le code, vous pouvez ajuster la variable "Deb" pour le Debit max du gaz de votre installation.
Code : Tout sélectionner
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Variable
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#Debit max gas (need to be adjust to synchronize estimated and real gas consumption)
Deb=0.1365
SetGasIndex.py (pensez à faire le "sudo chmod +x domo2vito.py " pour le rendre executable) :
Code : Tout sélectionner
#!/usr/bin/python
# -*- coding: utf-8 -*-
import json
import requests
import urllib
#from requests.auth import HTTPBasicAuth
############# Parametres #################################
#~~~~~~~~~~ Parametres Domoticz ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
domoticz_ip="192.168.0.40"
domoticz_port="8080"
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# IDX de Domoticz
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# remplacer par votre idx de votre widget
dummy_idx={'compteur_gaz':538 }
############### fin des parametres #############################
water_index = input("Entrez l'index de votre compteur (en litre) : ")
#on recupère l'index actuel
r = requests.get('http://'+domoticz_ip+':'+domoticz_port+'/json.htm?type=devices&rid='+str(dummy_idx['compteur_gaz'])).json()
result={}
index=str(r['result'][0]['Counter'])
# on supprime le m3 à la fin de la chaine et on convertit en litre
index_litre=float(index[0:len(index)-3])*1000
print "Compteur gaz index actuel= "+str(index_litre)
#on calcul le nombre de litre a rajouter
ajout=float(water_index)-float(index_litre)
print "Il faut ajouter "+str(ajout)+" litres"
# compteur GAZ requete type json.htm?type=command¶m=udevice&idx=IDX&svalue=0&svalue=USAGE
requete='http://'+domoticz_ip+':'+domoticz_port+'/json.htm?type=command¶m=udevice&idx='+str(dummy_idx['compteur_gaz'])+'&svalue='+str(ajout/10)+' m3'
urllib.urlopen(requete)
L'image seule si ca vous branche de faire pareil :