def mbus_probe_secondary_address(ser, mask): # False -> Collison # None -> No reply # True -> Single reply meterbus.send_select_frame(ser, mask) try: frame = meterbus.load(meterbus.recv_frame(ser, 1)) except meterbus.MBusFrameDecodeError as e: frame = e.value if isinstance(frame, meterbus.TelegramACK): meterbus.send_request_frame(ser, meterbus.ADDRESS_NETWORK_LAYER) time.sleep(0.5) frame = None try: frame = meterbus.load( meterbus.recv_frame(ser)) except meterbus.MBusFrameDecodeError: pass if isinstance(frame, meterbus.TelegramLong): return True, frame.secondary_address, frame.manufacturer return None, None, None return frame, None, None
def mbus_probe_secondary_address(ser, mask): # False -> Collison # None -> No reply # True -> Single reply meterbus.send_select_frame(ser, mask) try: frame = meterbus.load(meterbus.recv_frame(ser, 1)) except meterbus.MBusFrameDecodeError as e: frame = e.value if isinstance(frame, meterbus.TelegramACK): meterbus.send_request_frame(ser, meterbus.ADDRESS_NETWORK_LAYER) time.sleep(0.5) frame = None try: frame = meterbus.load(meterbus.recv_frame(ser)) except meterbus.MBusFrameDecodeError: pass if isinstance(frame, meterbus.TelegramLong): return True, frame.secondary_address, frame.manufacturer return None, None, None return frame, None, None
def do_char_dev(self, **kwargs): address = self.address device = self.device baudrate = self.baudrate try: address = int(address) if not (0 <= address <= 254): address = address except ValueError: address = address.upper() try: ibt = meterbus.inter_byte_timeout(baudrate) with serial.serial_for_url(device, baudrate, 8, 'E', 1, inter_byte_timeout=ibt, timeout=1) as ser: frame = None if meterbus.is_primary_address(address): self.ping_address(ser, meterbus.ADDRESS_NETWORK_LAYER, 0) meterbus.send_request_frame(ser, address) frame = meterbus.load( meterbus.recv_frame(ser, meterbus.FRAME_DATA_LENGTH)) elif meterbus.is_secondary_address(address): meterbus.send_select_frame(ser, address) try: frame = meterbus.load(meterbus.recv_frame(ser, 1)) except meterbus.MBusFrameDecodeError as e: frame = e.value assert isinstance(frame, meterbus.TelegramACK) frame = None # ping_address(ser, meterbus.ADDRESS_NETWORK_LAYER, 0) meterbus.send_request_frame(ser, meterbus.ADDRESS_NETWORK_LAYER) time.sleep(0.3) frame = meterbus.load( meterbus.recv_frame(ser, meterbus.FRAME_DATA_LENGTH)) if frame is not None: #print(frame.to_JSON()) return frame.to_JSON() except serial.serialutil.SerialException as e: print(e)
def do_char_dev(args): address = None try: address = int(args.address) if not (0 <= address <= 254): address = args.address except ValueError: address = args.address.upper() 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 ping_address(ser, address, args.retries, args.echofix): meterbus.send_request_frame(ser, address, read_echo=args.echofix) frame = meterbus.load( meterbus.recv_frame(ser, meterbus.FRAME_DATA_LENGTH)) elif meterbus.is_secondary_address(address): if ping_address(ser, meterbus.ADDRESS_NETWORK_LAYER, args.retries, args.echofix): meterbus.send_select_frame(ser, address, args.echofix) try: frame = meterbus.load(meterbus.recv_frame(ser, 1)) except meterbus.MBusFrameDecodeError as e: frame = e.value # Ensure that the select frame request was handled by the slave assert isinstance(frame, meterbus.TelegramACK) frame = None meterbus.send_request_frame( ser, meterbus.ADDRESS_NETWORK_LAYER, read_echo=args.echofix) time.sleep(0.3) frame = meterbus.load( meterbus.recv_frame(ser, meterbus.FRAME_DATA_LENGTH)) if frame is not None: return frame except serial.serialutil.SerialException as e: print(e) return None
def do_char_dev(args): address = None try: address = int(args.address) if not (0 <= address <= 254): address = args.address except ValueError: address = args.address.upper() 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): ping_address(ser, meterbus.ADDRESS_NETWORK_LAYER, 0) meterbus.send_request_frame(ser, address) frame = meterbus.load( meterbus.recv_frame(ser, meterbus.FRAME_DATA_LENGTH)) elif meterbus.is_secondary_address(address): meterbus.send_select_frame(ser, address) try: frame = meterbus.load(meterbus.recv_frame(ser, 1)) except meterbus.MBusFrameDecodeError as e: frame = e.value assert isinstance(frame, meterbus.TelegramACK) frame = None # ping_address(ser, meterbus.ADDRESS_NETWORK_LAYER, 0) meterbus.send_request_frame( ser, meterbus.ADDRESS_NETWORK_LAYER) time.sleep(0.3) frame = meterbus.load( meterbus.recv_frame(ser, meterbus.FRAME_DATA_LENGTH)) if frame is not None: print(frame.to_JSON()) except serial.serialutil.SerialException as e: print(e)
def test_send_select_frame(self): self.reset() meterbus.send_select_frame(self.master, "00000001DADAFA1B") reply = (b"\x68\x0b\x0b\x68\x73\xfd\x52\x01\x00" b"\x00\x00\xda\xda\xfa\x1b\x8c\x16") self.assertEqual(self.slave.read(len(reply)), reply) # Slave sends ACK reply self.slave.write(b'\xE5') frame_data = meterbus.recv_frame(self.master, 1) frame = meterbus.load(frame_data) self.assertIsInstance(frame, meterbus.TelegramACK)
def test_send_select_frame(self): self.reset() meterbus.send_select_frame(self.master, "00000001DADAFA1B") reply = (b"\x68\x0b\x0b\x68\x73\xfd\x52\x01\x00" b"\x00\x00\xda\xda\xfa\x1b\x8c\x16") self.assertEqual(self.slave.read(len(reply)), reply) # Slave sends ACK reply self.slave.write(b'\xE5') frame_data = meterbus.recv_frame(self.master, 1) frame = meterbus.load(frame_data) self.assertIsInstance(frame, meterbus.TelegramACK)
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: 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
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, 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
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)
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)) while 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)
def do_char_dev(args): address = None try: address = int(args.address) if not (0 <= address <= 254): address = args.address except ValueError: address = args.address.upper() 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 result = None if meterbus.is_primary_address(address): if ping_address(ser, address, args.retries, args.echofix): meterbus.send_request_frame(ser, address, read_echo=args.echofix) frame = meterbus.load( meterbus.recv_frame(ser, meterbus.FRAME_DATA_LENGTH)) else: print("no reply") elif meterbus.is_secondary_address(address): if ping_address(ser, meterbus.ADDRESS_NETWORK_LAYER, args.retries, args.echofix): meterbus.send_select_frame(ser, address, args.echofix) try: frame = meterbus.load(meterbus.recv_frame(ser, 1)) except meterbus.MBusFrameDecodeError as e: frame = e.value # Ensure that the select frame request was handled by the slave assert isinstance(frame, meterbus.TelegramACK) frame = None meterbus.send_request_frame(ser, meterbus.ADDRESS_NETWORK_LAYER, read_echo=args.echofix) time.sleep(0.3) frame = meterbus.load( meterbus.recv_frame(ser, meterbus.FRAME_DATA_LENGTH)) else: print("no reply") if frame is not None and args.output != 'dump': recs = [] for rec in frame.records: recs.append({'value': rec.value, 'unit': rec.unit}) ydata = { 'manufacturer': frame.body.bodyHeader.manufacturer_field. decodeManufacturer, 'identification': ''.join(map('{:02x}'.format, frame.body.bodyHeader.id_nr)), 'access_no': frame.body.bodyHeader.acc_nr_field.parts[0], 'medium': frame.body.bodyHeader.measure_medium_field.parts[0], 'records': recs } if args.output == 'json': result = json.dumps(ydata, indent=4, sort_keys=True) print(json.dumps(ydata, indent=4, sort_keys=True)) elif args.output == 'yaml': def float_representer(dumper, value): if int(value) == value: text = '{0:.4f}'.format(value).rstrip('0').rstrip( '.') return dumper.represent_scalar( u'tag:yaml.org,2002:int', text) else: text = '{0:.4f}'.format(value).rstrip('0').rstrip( '.') return dumper.represent_scalar( u'tag:yaml.org,2002:float', text) # Handle float and Decimal representation yaml.add_representer(float, float_representer) yaml.add_representer(Decimal, float_representer) result = yaml.dump(ydata, default_flow_style=False, allow_unicode=True, encoding=None) print( yaml.dump(ydata, default_flow_style=False, allow_unicode=True, encoding=None)) elif frame is not None: result = frame.to_JSON() print(frame.to_JSON()) return result except serial.serialutil.SerialException as e: print(e)
def do_char_dev(args): address = None try: address = int(args.address) if not (0 <= address <= 254): address = args.address except ValueError: address = args.address.upper() try: #vib_to_show = ['14:0','59:1','59:0','89:0', '93:0', '255.34:0'] #vib_to_show = ['14:0','59:0','89:0', '93:0'] filter = { ((14, ), 0, 0): "one", #((14,), 0, 1): "one_b", ((59, ), 0, 0): "FLOW", ((62, ), 0, 0): "FLOW", ((89, ), 0, 0): "FLOW_TEMPERATURE", ((91, ), 0, 0): "FLOW_TEMPERATURE", ((93, ), 0, 0): "RETURN_TEMPERATURE", ((95, ), 0, 0): "RETURN_TEMPERATURE", ((255, 34), 0, 0): "five", ((90, ), 0, 0): "FLOW_TEMPERATURE", ((94, ), 0, 0): "RETURN_TEMPERATURE", } ibt = meterbus.inter_byte_timeout(args.baudrate) parity = 'E' if args.monitor: parity = 'N' with serial.serial_for_url(args.device, args.baudrate, 8, parity, 1, inter_byte_timeout=ibt, timeout=1) as ser: if meterbus.is_primary_address(address): if not args.monitor: ping_address(ser, address, 0) #ping_address(ser, meterbus.ADDRESS_NETWORK_LAYER, 0) #setG4modern(ser, address) #print("Landis+Gyr needs time") #time.sleep(4) #print("done") t_start = time.time() - 3 try: #ser.read(1) while True: time.sleep(0.1) if not args.monitor: if (time.time() - t_start) <= int(args.sleep): continue t_start = time.time() meterbus.send_request_frame(ser, address) time.sleep(0.2) frame = None #print(ser.inWaiting(), end = ' ') if ser.inWaiting(): # >= 205: #ser.read() framedata = meterbus.recv_frame( ser, meterbus.FRAME_DATA_LENGTH) print("frame: ", framedata) if framedata: frame = meterbus.load(framedata) if not frame: continue records = frame.body.bodyPayload.records filtered = { "ts": '{:10.0f}'.format(time.time()), "records": [], "framedata": framedata.hex(), } for record in records: vib = tuple(record.vib.parts) func = record.dib.function_type.value storage_number = record.dib.storage_number key = (vib, func, storage_number) if key in filter: #name = filter.get(key,"value") filtered['records'].append(record.interpreted) # print(name) #record = records[vib] #print('{:10},{:30}:{}'.format(vib, record['type'], record['value'])) # value = record.value # if type(value) is int: # print(' {:8} '.format(value), end='') # else: # print(' {:10.8} '.format(value), end='') #print() import simplejson as json print( json.dumps(filtered, sort_keys=True, indent=4, use_decimal=True)) except KeyboardInterrupt: pass elif meterbus.is_secondary_address(address): meterbus.send_select_frame(ser, address) try: frame = meterbus.load(meterbus.recv_frame(ser, 1)) except meterbus.MBusFrameDecodeError as e: frame = e.value assert isinstance(frame, meterbus.TelegramACK) frame = None # ping_address(ser, meterbus.ADDRESS_NETWORK_LAYER, 0) meterbus.send_request_frame(ser, meterbus.ADDRESS_NETWORK_LAYER) time.sleep(0.3) frame = meterbus.load( meterbus.recv_frame(ser, meterbus.FRAME_DATA_LENGTH)) if frame is not None: print(frame.to_JSON()) except serial.serialutil.SerialException as e: print(e)