1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253 |
- class AsyncModbusTCPMeter(ModbusTCPMeter):
- def __init__(self, *args, **kwargs):
- super().__init__(*args, **kwargs)
- self.reader = self.writer = None
- async def _connect(self):
- self.reader, self.writer = await asyncio.open_connection(host=self.port, port=self.tcp_port)
- async def read(self, regnames=None):
- if regnames is None:
- registers = self.REGS
- return await self._read_multiple(registers)
- if isinstance(regnames, str):
- registers = [register for register in self.REGS if register['name'] == regnames]
- if len(registers) == 0:
- return "Register not found on device."
- return await self._read_single(registers[0])
- if isinstance(regnames, Iterable):
- registers = [register for register in self.REGS if register['name'] in regnames]
- return await self._read_multiple(registers)
- async def _read_single(self, register):
- num_regs = register['length']
- message = self._modbus_message(register['start'], num_regs)
- if self.writer is None:
- await self._connect()
- self.writer.write(message)
- await self.writer.drain()
- data = await self.reader.readexactly(9 + 2 * num_regs)
- return self._convert_value(data[9:], signed=register['signed'], decimals=register['decimals'], isFloat=register['isFloat']|False)
- async def _read_multiple(self, registers):
- registers.sort(key=lambda reg: reg['start'])
- results = {}
- for reg_range in self._split_ranges(registers):
- # Prepare the request
- first_reg = min([register['start'] for register in reg_range])
- num_regs = max([register['start'] + register['length'] for register in reg_range]) - first_reg
- if self.writer is None:
- await self._connect()
- self.writer.write(self._modbus_message(first_reg, num_regs))
- await self.writer.drain()
- # Receive the response
- data = await self.reader.readexactly(9 + 2 * num_regs)
- results.update(self._interpret_result(data[9:], reg_range))
- return results
|