I’ve implemented My-PV AC-THOR to my Home Assistant.
Dashboard:
type: entities
entities:
- entity: sensor.ac_thor_leistung
- entity: sensor.ac_thor_meter
- entity: sensor.ac_thor_temperatur
configuration.yaml:
modbus: !include modbus.yaml
modbus.yaml:
- name: AC-THOR
type: tcp
host: ac-thor.local
port: 502
sensors:
- name: "AC_THOR Meter"
unique_id: ac_thor_meter
address: 1069
unit_of_measurement: W
state_class: total_increasing
- name: "AC_THOR Leistung"
unique_id: ac_thor_power
address: 1000
unit_of_measurement: W
state_class: total_increasing
- name: "AC_THOR Temperatur"
unique_id: ac_thor_temperature
address: 1001
scale: 0.1
unit_of_measurement: "°C"
AC-THOR would need a ModBus Server where it could read Meter + battery charging" values from.
Unfortunately, I have a Battery system, which does not speak ModBus (Tesla Powerwall), but I can read the values through REST-API from the Powerwall.
I would need a ModBus Server as an add-on for the hass-os, where I can set-up some
on the Homeassistant Server, which emulates some hold registers by looking them up from corresponding hass sensor values. Does something like this exist?
I’ve already wrote a prototype (without hass integration), which already emulates modbus registers 40206 - 40210 - unfortunately only hardcoded - please keep in mind, this is a brutal hack) of an emulated “SolarEdge Manual” backend system, which uses values from the Powerwall values (which includes metering of the capacity from photovoltaik versus grid). Integration within Hass would be nice, but I’m not experienced, how to write a module.
#!/usr/bin/env python3
# pyModbusTCP pyPowerWall Modbus-Frontend für Tesla Powerwall
# using example https://pymodbustcp.readthedocs.io/en/latest/examples/server_virtual_data.html
from pypowerwall import Powerwall
from pyModbusTCP.server import ModbusServer, DataBank, DataHandler
from pyModbusTCP.constants import EXP_ILLEGAL_FUNCTION, EXP_NONE, EXP_DATA_ADDRESS
from time import sleep
from random import uniform
from datetime import datetime
# some const
ALLOW_R_L = ['127.0.0.1', '192.168.1.xxxx_ip_of_ac_thor']
PW_IP = "192.168.1.xxxx_ip_of_powerwall"
PW_LO = "[email protected]"; PW_PW = "powerwall_customer_pw"
PW_TZ = "Europe/Berlin"
class MyDataHandler(DataHandler):
def read_coils(self, address, count, srv_info):
if srv_info.client.address in ALLOW_R_L:
print ("Coil", address, count)
return super().read_coils(address, count, srv_info)
else:
return DataHandler.Return(exp_code=EXP_ILLEGAL_FUNCTION)
def read_d_inputs(self, address, count, srv_info):
if srv_info.client.address in ALLOW_R_L:
print ("Inputs", address, count)
return super().read_d_inputs(address, count, srv_info)
else:
return DataHandler.Return(exp_code=EXP_ILLEGAL_FUNCTION)
def read_h_regs(self, address, count, srv_info):
if srv_info.client.address in ALLOW_R_L:
if (address == 40206 and count == 5):
grid = -pw.grid()
if grid > 2000:
grid = grid - 2000
else:
grid = 0
print ("Handle", grid)
return DataHandler.Return(exp_code=EXP_NONE,
data=[grid, 0, 0, 0, 0])
else:
print ("Handle", address, count)
return super().read_h_regs(address, count, srv_info)
else:
return DataHandler.Return(exp_code=EXP_ILLEGAL_FUNCTION)
def read_i_regs(self, address, count, srv_info):
if srv_info.client.address in ALLOW_R_L:
print ("I_Regs", address, count)
return super().read_i_regs(address, count, srv_info)
else:
return DataHandler.Return(exp_code=EXP_ILLEGAL_FUNCTION)
def write_coils(self, address, bits_l, srv_info):
if srv_info.client.address in ALLOW_W_L:
return super().write_coils(address, bits_l, srv_info)
else:
return DataHandler.Return(exp_code=EXP_ILLEGAL_FUNCTION)
def write_h_regs(self, address, words_l, srv_info):
if srv_info.client.address in ALLOW_W_L:
return super().write_h_regs(address, words_l, srv_info)
else:
return DataHandler.Return(exp_code=EXP_ILLEGAL_FUNCTION)
if __name__ == '__main__':
pw = Powerwall(PW_IP, PW_PW, PW_LO, PW_TZ)
server = ModbusServer("0.0.0.0", 502, no_block=True, data_hdl=MyDataHandler())
try:
print("Start server...")
server.start()
print("Server is online")
state = [0]
while True:
sleep(60)
except:
print("Shutdown server ...")
server.stop()
print("Server is offline")