Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add MQTT Auto discovery (device) support for HomeAssistant #29

Closed
wants to merge 4 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
52 changes: 52 additions & 0 deletions InverterData.py
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@ def PrepareDomoticzData(DData, idx, svalue):
ifpass=configParser.get('InfluxDB', 'influxdb_password')
ifdb=configParser.get('InfluxDB', 'influxdb_dbname')
DomoticzSupport=configParser.get('Domoticz', 'domoticz_support')
HomeAssistantSupport=configParser.get('HomeAssistant', 'homeassistant_support')
# END CONFIG

timestamp=str(datetime.utcnow().strftime('%Y-%m-%d %H:%M:%S'))
Expand All @@ -108,6 +109,8 @@ def PrepareDomoticzData(DData, idx, svalue):
totaltime=0
PMData=[]
DomoticzData=[]
# Initialise mqtt HomeAssistant discovery support
if HomeAssistantSupport=="1":HomeAssistantData = []

while chunks<2:
if verbose=="1": print("*** Chunk no: ", chunks);
Expand Down Expand Up @@ -210,6 +213,7 @@ def PrepareDomoticzData(DData, idx, svalue):
if prometheus=="1" and graph==1: PMetrics(metric_name, metric_type, label_name, label_value, response);
if influxdb=="1" and graph==1: PrepareInfluxData(InfluxData, metric_name.split('_')[0]+"_"+label_value, response);
if DomoticzSupport=="1" and DomoticzIdx>0: PrepareDomoticzData(DomoticzData, DomoticzIdx, response);
if HomeAssistantSupport=="1":HomeAssistantData.append([title, ratio, unit, metric_type, metric_name, label_name, label_value, response,register])
if unit!="":
output=output+"\""+ title + " (" + unit + ")" + "\":" + str(response)+","
else:
Expand All @@ -222,6 +226,7 @@ def PrepareDomoticzData(DData, idx, svalue):
if prometheus=="1" and graph==1: PMetrics(metric_name, metric_type, label_name, label_value, (totalpower*1000));
if influxdb=="1" and graph==1: PrepareInfluxData(InfluxData, metric_name.split('_')[0]+"_"+label_value, totalpower);
if DomoticzSupport=="1" and DomoticzIdx>0: PrepareDomoticzData(DomoticzData, DomoticzIdx, response);
if HomeAssistantSupport=="1":HomeAssistantData.append([title, ratio, unit, metric_type, metric_name, label_name, label_value, response,(totalpower*1000)])
if hexpos=='0x0017': totaltime+=response*ratio*65536;
if hexpos=='0x0018':
totaltime+=response*ratio
Expand All @@ -230,6 +235,7 @@ def PrepareDomoticzData(DData, idx, svalue):
if prometheus=="1" and graph==1: PMetrics(metric_name, metric_type, label_name, label_value, totaltime);
if influxdb=="1" and graph==1: PrepareInfluxData(InfluxData, metric_name.split('_')[0]+"_"+label_value, totaltime);
if DomoticzSupport=="1" and DomoticzIdx>0: PrepareDomoticzData(DomoticzData, DomoticzIdx, response);
if HomeAssistantSupport=="1":HomeAssistantData.append([title, ratio, unit, metric_type, metric_name, label_name, label_value, response,totaltime])
a+=1
if chunks==0:
pini=reg_start2
Expand Down Expand Up @@ -269,6 +275,52 @@ def PrepareDomoticzData(DData, idx, svalue):
result.wait_for_publish()
if not result.is_published:
print("Error publishing data for Domoticz to MQTT")
if HomeAssistantSupport=="1":
if verbose=="1": print("*** MQTT messages for HomeAssistant:");
# last will for unexpected disconnection
client.will_set("Sofar/Logger/"+str(inverter_sn)+"/state/connected","false")
# Send status of device: enabled = true
result=client.publish("Sofar/Logger/"+str(inverter_sn)+"/enabled","true")
result.wait_for_publish()
if not result.is_published:
print("Error publishing device status for HomeAssistant to MQTT")
# Send state of device: connected = true
result=client.publish("Sofar/Logger/"+str(inverter_sn)+"/state/connected","true")
result.wait_for_publish()
if not result.is_published:
print("Error publishing device state for HomeAssistant to MQTT")
HAcount=0
for mqtt_data in HomeAssistantData:
# Sensors for ENERGY module with kWh, Wh, W
if mqtt_data[2]=="kWh" or mqtt_data[2]=="Wh" or mqtt_data[2]=="W":
# Send auto discover device sensor template
result=client.publish("homeassistant/sensor/SofarLogger/"+str(inverter_sn)+"_"+str(HAcount)+"/config","{\"avty\":{\"topic\":\"Sofar/Logger/"+str(inverter_sn)+"/state/connected\",\"payload_available\":\"true\",\"payload_not_available\":\"false\"},\"~\":\"Sofar/Logger/"+str(inverter_sn)+"/\",\"device\":{\"ids\":\""+str(inverter_sn)+"\",\"mf\":\"Sofar\",\"name\":\"WLS-3\",\"sw\":\"x.x.x\"},\"name\":\""+(mqtt_data[0])+" ["+(mqtt_data[2])+"]\",\"uniq_id\":\""+str(inverter_sn)+"_"+str(HAcount)+"\",\"qos\":0,\"unit_of_meas\":\""+(mqtt_data[2])+"\",\"stat_t\":\"~state/"+(mqtt_data[4])+(mqtt_data[6])+"\",\"val_tpl\":\"{{ value | round(5) }}\",\"dev_cla\":\"energy\",\"state_class\":\"total_increasing\"}")
result.wait_for_publish()
if not result.is_published:
print("[",str(HAcount),"]","Error publishing data for HomeAssistant to MQTT")
else:
print ("[",str(HAcount),"]",mqtt_data[0] , ": " , mqtt_data[7])
# Send sensor values data
result=client.publish("Sofar/Logger/"+str(inverter_sn)+"/state/"+(mqtt_data[4])+(mqtt_data[6]),(mqtt_data[7]))
result.wait_for_publish()
if not result.is_published:
print("[",str(HAcount),"]","Error publishing data for HomeAssistant to MQTT")
HAcount=HAcount+1
# Rest of sensors
else:
# Send auto discover device sensor template
result=client.publish("homeassistant/sensor/SofarLogger/"+str(inverter_sn)+"_"+str(HAcount)+"/config","{\"avty\":{\"topic\":\"Sofar/Logger/"+str(inverter_sn)+"/state/connected\",\"payload_available\":\"true\",\"payload_not_available\":\"false\"},\"~\":\"Sofar/Logger/"+str(inverter_sn)+"/\",\"device\":{\"ids\":\""+str(inverter_sn)+"\",\"mf\":\"Sofar\",\"name\":\"WLS-3\",\"sw\":\"x.x.x\"},\"name\":\""+(mqtt_data[0])+" ["+(mqtt_data[2])+"]\",\"uniq_id\":\""+str(inverter_sn)+"_"+str(HAcount)+"\",\"qos\":0,\"unit_of_meas\":\""+(mqtt_data[2])+"\",\"stat_t\":\"~state/"+(mqtt_data[4])+(mqtt_data[6])+"\",\"val_tpl\":\"{{ value | round(5) }}\",\"dev_cla\":\"current\",\"state_class\":\"measurement\"}")
result.wait_for_publish()
if not result.is_published:
print("[",str(HAcount),"]","Error publishing data for HomeAssistant to MQTT")
else:
print ("[",str(HAcount),"]",mqtt_data[0] , ": " , mqtt_data[7])
# Send sensor values data
result=client.publish("Sofar/Logger/"+str(inverter_sn)+"/state/"+(mqtt_data[4])+(mqtt_data[6]),(mqtt_data[7]))
result.wait_for_publish()
if not result.is_published:
print("[",str(HAcount),"]","Error publishing data for HomeAssistant to MQTT")
HAcount=HAcount+1
else:
result=client.publish(mqtt_topic+"/attributes",output)
result.wait_for_publish()
Expand Down
2 changes: 1 addition & 1 deletion InverterHWData.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ def hex_zfill(intval):
hexvalue=hex(intval)
return '0x' + str(hexvalue)[2:].zfill(4)

os.chdir(os.path.dirname(sys.argv[0]))
os.chdir(os.path.dirname(os.path.abspath(sys.argv[0])))

# CONFIG
configParser = configparser.RawConfigParser()
Expand Down
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,9 @@ mqtt_cacert= # CA certificate path/filename
[Domoticz]
domoticz_support=0 # 0: disabled, 1: enabled

[HomeAssistant]
homeassistant_support=0 # 0: disabled, 1: enabled

Files SOFARMap.xml and SOFARHWMap.xml contain MODBUS inverter's registers mapping for Sofar Solar K-TLX product line
and Prometheus/InfluxDB metrics configuration.
Edit i.e. to get captions in a different language, change Prometheus/InfluxDB metrics names or
Expand Down
3 changes: 3 additions & 0 deletions config.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -37,3 +37,6 @@ mqtt_cacert=

[Domoticz]
domoticz_support=0

[HomeAssistant]
homeassistant_support=1