def test_multi_req_frame(self): self.reset() frame = meterbus.send_request_frame_multi(self.master, 0) self.assertEqual(self.slave.read(5), b"\x10\x7B\x00\x7B\x16") # Next frame frame.header.cField.parts[0] ^= meterbus.CONTROL_MASK_FCB frame = meterbus.send_request_frame_multi(self.master, req=frame) self.assertEqual(self.slave.read(5), b"\x10\x5B\x00\x5B\x16")
def test_invalid_multi_req_frame_address(self): self.reset() retval = meterbus.send_request_frame_multi(self.master, 600) self.assertEqual(retval, False)
except ValueError: pass try: ibt = meterbus.inter_byte_timeout(args.baudrate) with serial.serial_for_url(args.device, args.baudrate, 8, 'E', 1, inter_byte_timeout=ibt, timeout=1) as ser: frame = None if meterbus.is_primary_address(address): if False == ping_address(ser, address, 0): sys.exit(1) meterbus.send_request_frame_multi(ser, address) frame = meterbus.load( meterbus.recv_frame(ser)) elif meterbus.is_secondary_address(address): if False == ping_address(ser, meterbus.ADDRESS_NETWORK_LAYER, 0): ping_address(ser, meterbus.ADDRESS_BROADCAST_NOREPLY, 0) meterbus.send_select_frame(ser, address) frame = meterbus.load(meterbus.recv_frame(ser, 1)) assert isinstance(frame, meterbus.TelegramACK) req = meterbus.send_request_frame_multi( ser, meterbus.ADDRESS_NETWORK_LAYER) try:
with serial.serial_for_url(args.device, args.baudrate, 8, 'E', 1, inter_byte_timeout=ibt, timeout=1) as ser: frame = None if meterbus.is_primary_address(address): if False == ping_address(ser, address, args.retries, args.echofix): sys.exit(1) meterbus.send_request_frame_multi(ser, address, read_echo=args.echofix) frame = meterbus.load(meterbus.recv_frame(ser)) elif meterbus.is_secondary_address(address): if False == ping_address(ser, meterbus.ADDRESS_NETWORK_LAYER, args.retries, args.echofix): ping_address(ser, meterbus.ADDRESS_BROADCAST_NOREPLY, args.retries, args.echofix) meterbus.send_select_frame(ser, address, args.echofix) frame = meterbus.load(meterbus.recv_frame(ser, 1)) assert isinstance(frame, meterbus.TelegramACK) req = meterbus.send_request_frame_multi( ser,
def serial_request_multi(): parser = argparse.ArgumentParser( description='Request data over serial M-Bus for devices.') parser.add_argument('-d', action='store_true', help='Enable verbose debug') parser.add_argument('-b', '--baudrate', type=int, default=2400, help='Serial bus baudrate') parser.add_argument('-a', '--address', type=str, default=meterbus.ADDRESS_BROADCAST_REPLY, help='Primary or secondary address') parser.add_argument('-r', '--retries', type=int, default=5, help='Number of ping retries for each address') parser.add_argument('-o', '--output', default="json", help='Output format') parser.add_argument('--echofix', action='store_true', help='Read and ignore echoed data from target') parser.add_argument('device', type=str, help='Serial device or URI') args = parser.parse_args() meterbus.debug(args.d) address = args.address try: if 0 <= int(args.address) <= 254: address = int(args.address) except ValueError: pass try: ibt = meterbus.inter_byte_timeout(args.baudrate) with serial.serial_for_url(args.device, args.baudrate, 8, 'E', 1, inter_byte_timeout=ibt, timeout=1) as ser: frame = None if meterbus.is_primary_address(address): if False is ping_address(ser, address, args.retries): sys.exit(1) meterbus.send_request_frame_multi(ser, address, read_echo=args.echofix) frame = meterbus.load( meterbus.recv_frame(ser)) elif meterbus.is_secondary_address(address): if False is ping_address(ser, meterbus.ADDRESS_NETWORK_LAYER, args.retries, args.echofix): ping_address(ser, meterbus.ADDRESS_BROADCAST_NOREPLY, args.retries, args.echofix) meterbus.send_select_frame(ser, address, read_echo=args.echofix) frame = meterbus.load(meterbus.recv_frame(ser, 1)) # Ensure that the select frame request was handled by the slave assert isinstance(frame, meterbus.TelegramACK) req = meterbus.send_request_frame_multi( ser, meterbus.ADDRESS_NETWORK_LAYER, read_echo=args.echofix) try: frame = meterbus.load(meterbus.recv_frame(ser)) except meterbus.MBusFrameDecodeError: frame = None while frame and frame.more_records_follow: # toogle FCB on and off req.header.cField.parts[0] ^= meterbus.CONTROL_MASK_FCB req = meterbus.send_request_frame_multi( ser, meterbus.ADDRESS_NETWORK_LAYER, req, read_echo=args.echofix) next_frame = meterbus.load(meterbus.recv_frame(ser)) frame += next_frame if frame is not None: print(serialize_frame(frame, args.output)) except serial.serialutil.SerialException as e: print(e)
except ValueError: pass try: ibt = meterbus.inter_byte_timeout(args.baudrate) with serial.serial_for_url(args.device, args.baudrate, 8, 'E', 1, inter_byte_timeout=ibt, timeout=1) as ser: frame = None if meterbus.is_primary_address(address): if False == ping_address(ser, address, 0): sys.exit(1) meterbus.send_request_frame_multi(ser, address) frame = meterbus.load( meterbus.recv_frame(ser)) elif meterbus.is_secondary_address(address): if False == ping_address(ser, meterbus.ADDRESS_NETWORK_LAYER, 0): ping_address(ser, meterbus.ADDRESS_BROADCAST_NOREPLY, 0) meterbus.send_select_frame(ser, address) frame = meterbus.load(meterbus.recv_frame(ser, 1)) assert isinstance(frame, meterbus.TelegramACK) req = meterbus.send_request_frame_multi( ser, meterbus.ADDRESS_NETWORK_LAYER) frame = meterbus.load(meterbus.recv_frame(ser))