add Modbus and AT command handler

This commit is contained in:
Stefan Allius
2024-05-05 20:13:51 +02:00
parent 3dbcee63f6
commit eda8ef1db6

View File

@@ -48,6 +48,8 @@ class Sequence():
class SolarmanV5(Message):
AT_CMD = 1
MB_RTU_CMD = 2
def __init__(self, server_side: bool):
super().__init__(server_side)
@@ -59,7 +61,7 @@ class SolarmanV5(Message):
self.db = InfosG3P()
self.time_ofs = 0
self.mb = Modbus()
self.forward_modbus_rep = False
self.forward_modbus_resp = False
self.switch = {
0x4210: self.msg_data_ind, # real time data
@@ -88,7 +90,7 @@ class SolarmanV5(Message):
#
# MODbus or AT cmd
0x4510: self.msg_command_req, # from server
0x1510: self.msg_response, # from inverter
0x1510: self.msg_command_rsp, # from inverter
}
'''
@@ -298,23 +300,48 @@ class SolarmanV5(Message):
self.__finish_send_msg()
async def send_modbus_cmd(self, func, addr, val) -> None:
self.forward_modbus_rep = False
self.forward_modbus_resp = False
self.__build_header(0x4510)
self._send_buffer += struct.pack('<BHLLL', 2, 0x2b0, 0, 0, 0)
self._send_buffer += self.mb.build_msg(1, func, addr, val)
self._send_buffer += struct.pack('<BHLLL', self.MB_RTU_CMD,
0x2b0, 0, 0, 0)
self._send_buffer += self.mb.build_msg(Modbus.INV_ADDR,
func, addr, val)
self.__finish_send_msg()
await self.async_write('Send Modbus Command:')
try:
await self.async_write('Send Modbus Command:')
except Exception:
self._send_buffer = bytearray(0)
def send_at_cmd(self, AT_cmd: str) -> None:
async def send_at_cmd(self, AT_cmd: str) -> None:
self.__build_header(0x4510)
self._send_buffer += struct.pack(f'<BHLLL{len(AT_cmd)}sc', 1, 2,
0, 0, 0, AT_cmd.encode('utf-8'),
self._send_buffer += struct.pack(f'<BHLLL{len(AT_cmd)}sc', self.AT_CMD,
2, 0, 0, 0, AT_cmd.encode('utf-8'),
b'\r')
self.__finish_send_msg()
try:
await self.async_write('Send AT Command:')
except Exception:
self._send_buffer = bytearray(0)
def __forward_msg(self):
self.forward(self._recv_buffer, self.header_len+self.data_len+2)
def __build_model_name(self):
db = self.db
MaxPow = db.get_db_value(Register.MAX_DESIGNED_POWER, 0)
Rated = db.get_db_value(Register.RATED_POWER, 0)
Model = None
if MaxPow == 2000:
if Rated == 800 or Rated == 600:
Model = f'TSOL-MS{MaxPow}({Rated})'
else:
Model = f'TSOL-MS{MaxPow}'
elif MaxPow == 1800 or MaxPow == 1600:
Model = f'TSOL-MS{MaxPow}'
if Model:
logger.info(f'Model: {Model}')
self.db.set_db_def_value(Register.EQUIPMENT_MODEL, Model)
def __process_data(self, ftype):
inv_update = False
msg_type = self.control >> 8
@@ -325,21 +352,7 @@ class SolarmanV5(Message):
self.new_data[key] = True
if inv_update:
db = self.db
MaxPow = db.get_db_value(Register.MAX_DESIGNED_POWER, 0)
Rated = db.get_db_value(Register.RATED_POWER, 0)
Model = None
if MaxPow == 2000:
if Rated == 800 or Rated == 600:
Model = f'TSOL-MS{MaxPow}({Rated})'
else:
Model = f'TSOL-MS{MaxPow}'
elif MaxPow == 1800 or MaxPow == 1600:
Model = f'TSOL-MS{MaxPow}'
if Model:
logger.info(f'Model: {Model}')
self.db.set_db_def_value(Register.EQUIPMENT_MODEL, Model)
self.__build_model_name()
'''
Message handler methods
'''
@@ -402,11 +415,42 @@ class SolarmanV5(Message):
data = self._recv_buffer[self.header_len:]
result = struct.unpack_from('<B', data, 0)
ftype = result[0]
if ftype == self.AT_CMD:
self.inc_counter('AT_Command')
elif ftype == self.MB_RTU_CMD:
if not self.mb.recv_req(data[15:-2]):
return
self.forward_modbus_resp = True
self.inc_counter('Modbus_Command')
self.inc_counter('AT_Command')
self.__forward_msg()
self.__send_ack_rsp(0x1510, ftype)
def msg_command_rsp(self):
data = self._recv_buffer[self.header_len:]
ftype = data[0]
if ftype == self.AT_CMD:
pass
elif ftype == self.MB_RTU_CMD:
valid = data[1]
modbus_msg_len = self.data_len - 14
logger.info(f'modbus_len:{modbus_msg_len} accepted:{valid}')
if valid == 1 and modbus_msg_len > 4:
logger.info(f'first byte modbus:{data[14]}')
inv_update = False
for key, update in self.mb.recv_resp(self.db, data[14:-2]):
if update:
if key == 'inverter':
inv_update = True
self.new_data[key] = True
if inv_update:
self.__build_model_name()
if not self.forward_modbus_resp:
return
self.__forward_msg()
def msg_hbeat_ind(self):
data = self._recv_buffer[self.header_len:]
result = struct.unpack_from('<B', data, 0)
@@ -435,8 +479,9 @@ class SolarmanV5(Message):
valid = result[1] == 1 # status
ts = result[2]
set_hb = result[3] # always 60 or 120
logger.info(f'ftype:{ftype} accepted:{valid}'
f' ts:{ts:08x} nextHeartbeat: {set_hb}s')
logger.debug(f'ftype:{ftype} accepted:{valid}'
f' ts:{ts:08x} nextHeartbeat: {set_hb}s')
dt = datetime.fromtimestamp(ts)
logger.info(f'ts: {dt.strftime("%Y-%m-%d %H:%M:%S")}')
logger.debug(f'ts: {dt.strftime("%Y-%m-%d %H:%M:%S")}')
self.__forward_msg()