I have this setup now in my configuration.yaml, and it works (mostly)
mqtt:
sensor:
- name: "EM340_in"
state_topic: "EM340/kWh_in"
value_template: "{{ value | float | round (2) }}"
unit_of_measurement: "kWh"
device_class: energy
state_class: total_increasing
- name: "EM340_out"
state_topic: "EM340/kWh_out"
value_template: "{{ value | float | round (2) }}"
unit_of_measurement: "kWh"
device_class: energy
state_class: total_increasing
- name: "EM340_A1"
state_topic: "EM340/A1"
value_template: "{{ value | float | round (2) }}"
unit_of_measurement: "A"
device_class: current
state_class: measurement
- name: "EM340_A2"
state_topic: "EM340/A2"
value_template: "{{ value | float | round (2) }}"
unit_of_measurement: "A"
device_class: current
state_class: measurement
- name: "EM340_A3"
state_topic: "EM340/A3"
value_template: "{{ value | float | round (2) }}"
unit_of_measurement: "A"
device_class: current
state_class: measurement
I am publishing to mqqt with a python script on a raspberry pi that has a RS485-CAN-hat attached to it. I intend to swap out the rpi for an esp8266 later in the week. The python code :
from pymodbus.client.sync import ModbusSerialClient
from pymodbus.pdu import ExceptionResponse
from pymodbus.exceptions import ModbusIOException
from pymodbus.payload import BinaryPayloadDecoder
from pymodbus.constants import Endian
import struct
import time
import paho.mqtt.client as mqtt #import the client1
broker_address='192.168.1.90'
port=1883
class ModbusException(Exception):
def __init__(self, resp):
self.msg = str(result)
def __str__(self):
return self.msg
class ModbusRequestDefinition(object):
def __init__(self, kind, unit, address, count, converter, label, decimals, topic):
self.kind = kind
self.unit = unit
self.address = address
self.count = count
self.converter = converter
self.label = label
self.decimals = decimals
self.topic = topic
reqs = [
#ModbusRequestDefinition('H', 1, 0x0002, 2, '', 'V1'),
#ModbusRequestDefinition('H', 1, 0x0002, 2, '', 'V2'),
#ModbusRequestDefinition('H', 1, 0x0004, 2, '', 'V3'),
ModbusRequestDefinition('H', 1, 0x000C, 2, '', 'A1', 1000,'EM340/A1'),
ModbusRequestDefinition('H', 1, 0x000E, 2, '', 'A2', 1000,'EM340/A2'),
ModbusRequestDefinition('H', 1, 0x0010, 2, '', 'A3', 1000,'EM340/A3'),
ModbusRequestDefinition('H', 1, 0x0034, 2, '', 'kWh+', 10,'EM340/kWh_in'),
ModbusRequestDefinition('H', 1, 0x004E, 2, '', 'kWh-', 10,'EM340/kWh_out')
]
client = ModbusSerialClient(method='rtu', port='/dev/ttyAMA0', baudrate=9600, stopbits=1, timeout=1)
client.connect()
delay = 0.05
#period = 0.5
period = 5
mqttclient = mqtt.Client("P1") #create new instance
mqttclient.username_pw_set("your mqqt user", "your mqtt password") # !! insert your own credentials here !!
mqttclient.connect(broker_address) #connect to broker
while True:
for req in reqs:
try:
time.sleep(delay)
if req.kind == 'H':
result = client.read_holding_registers(address=req.address,
count=req.count,
unit=req.unit)
if type(result) in [ExceptionResponse, ModbusIOException]:
raise ModbusException(result)
# print(req.label, end ="\t" )
# print(req.topic, end ="\t" )
decoder = BinaryPayloadDecoder.fromRegisters(result.registers, byteorder=Endian.Big, wordorder=Endian.Little)
val = decoder.decode_32bit_int()/req.decimals
# print(val)
mqttclient.publish(req.topic,val)
except ModbusException as e:
print("ERROR when querying '{0}': {1!s}".format(req.label, e))
if client.socket is None:
print("renew socket")
#client.socket = getSerial()
#print("-------------")
time.sleep(period)
client.close()
this is old pymodbus v2.5 as I couldnt yet port to the new release v3. Anyone have a working example there that I could start from then I would be happy to adapt.
Then submit the EM340_in and EM340_out sensors to the energy wizard and after a few hours of running you can see the stats generating a nice energy graph.
Now I have to mimic the same RS485 > ESP8266 > MQTT > HA for my inverter