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 setUp(self): self.frame = "\x68\x53\x53\x68\x08\x05\x72\x34\x08\x00\x54\x96\x15\x32" \ "\x00\xf2\x00\x00\x00\x01\xfd\x1b\x00\x02\xfc\x03\x48\x52" \ "\x25\x74\xd4\x11\x22\xfc\x03\x48\x52\x25\x74\xc8\x11\x12" \ "\xfc\x03\x48\x52\x25\x74\xb4\x16\x02\x65\xd0\x08\x22\x65" \ "\x70\x08\x12\x65\x23\x09\x01\x72\x18\x42\x65\xe4\x08\x82" \ "\x01\x65\xdd\x08\x0c\x78\x34\x08\x00\x54\x03\xfd\x0f\x00" \ "\x00\x04\x1f\x5d\x16" self.frame2 = "\x68\xD8\xD8\x68\x08\x00\x72\x92\x03\x00\x64\x96\x15" \ "\x14\x31\x04\x00\x00\x00\x0C\x78\x92\x03\x00\x64\x0D" \ "\xFD\x0F\x05\x33\x2E\x36\x2E\x31\x0D\x7C\x03\x79\x65" \ "\x6B\x10\x0A\xB3\xED\x14\xCD\x07\x58\xD7\xBA\xDE\x3B" \ "\x38\xB2\xE6\x96\x0C\x01\x7C\x03\x6F\x6D\x77\x04\x01" \ "\x7C\x03\x65\x73\x77\x00\x02\x7C\x03\x74\x69\x77\x3C" \ "\x00\x02\x7C\x03\x73\x69\x77\x3C\x00\x01\x7C\x03\x6D" \ "\x69\x77\x01\x02\x7C\x03\x65\x67\x61\xA0\x05\x04\x7C" \ "\x03\x66\x69\x77\xFF\xFF\xFF\xFF\x01\x7C\x03\x69\x63" \ "\x77\x01\x01\x7C\x03\x6F\x6D\x74\x00\x01\x7C\x03\x66" \ "\x64\x74\x03\x01\x7C\x03\x64\x63\x6C\x00\x01\x7C\x03" \ "\x6E\x61\x6C\x00\x01\x7C\x03\x65\x6C\x73\x05\x0A\xFD" \ "\x16\x00\x00\x04\xFD\x0B\x00\x00\x00\x00\x02\x7C\x03" \ "\x61\x66\x77\x00\x00\x01\x7C\x03\x66\x69\x61\x01\x04" \ "\x7C\x03\x63\x72\x72\xB3\x02\x00\x00\x01\x7C\x03\x61" \ "\x74\x73\x00\x01\x7C\x03\x6D\x61\x63\x00\x01\x7C\x03" \ "\x6D\x61\x6D\x00\x01\x7C\x03\x66\x63\x69\x01\x1F\x3A" \ "\x16" self.frame = meterbus.load(self.frame) self.frame2 = meterbus.load(self.frame2)
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 mbus_query(): ser = serial.Serial(serial_dev, baud_rate, 8, 'E', 1, 0.5) try: meterbus.send_ping_frame(ser, slave_address) frame = meterbus.load(meterbus.recv_frame(ser, 1)) assert isinstance(frame, meterbus.TelegramACK) meterbus.send_request_frame(ser, slave_address) frame = meterbus.load(meterbus.recv_frame(ser, meterbus.FRAME_DATA_LENGTH)) assert isinstance(frame, meterbus.TelegramLong) mbus_json = json.loads(frame.to_JSON()) manufacturer = mbus_json["body"]["header"]["manufacturer"] client.publish(post_topic, "manufacturer " + manufacturer) except: log('Failed to read data from slave at address %d' % slave_address) client.publish(post_topic, "failed")
def request(self): heatMeterList = [] #try: for addr in range(1,4): data = self.getAllData(addr) powerTs = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S") telegram = meterbus.load(data) #Instabilities/bugs of meterbus lib/package find3 = [float(x) for x in re.findall(self.match_number, str(telegram.records[13].interpreted) + str(telegram.records[13].interpreted))] if find3[0] == 3: replace = find3[1] else: replace = find3[0] powList = [float(x) for x in re.findall(self.match_number, str(telegram.records[12].interpreted) \ + str(telegram.records[13].interpreted) + str(telegram.records[9].interpreted) \ + str(telegram.records[10].interpreted))] heatMeterList.append("{:8.6f}, {:8.6f}, {:8.6f}, {:8.6f}".format(powList[0], replace, powList[3], powList[4])) self.dataStr = ','.join(heatMeterList) self.returnT = powList[4] #time.sleep(0.2) print(heatMeterList) self.data1 = heatMeterList[0] self.data2 = heatMeterList[1] self.data3 = heatMeterList[2]
def dvh5x_tarif(address, device, baudrate, tarif): try: ibt = meterbus.inter_byte_timeout(baudrate) with serial.Serial(device, baudrate, parity=serial.PARITY_EVEN, rtscts=False, timeout=0.2) as ser: frame = None ping_address(ser, meterbus.ADDRESS_NETWORK_LAYER, 0) if True: ret = ping_address(ser, address, 5) print("Ping status: %s " % ret) time.sleep(0.1) send_tarif_frame(ser, address, tarif) frame = meterbus.load(meterbus.recv_frame(ser, 1)) assert isinstance(frame, meterbus.TelegramACK) print("tarif set ok") ser.close() except serial.serialutil.SerialException as e: ser.close() print(e)
def dvh5x_read(address, device, baudrate): try: ibt = meterbus.inter_byte_timeout(baudrate) with serial.Serial(device, baudrate, parity=serial.PARITY_EVEN, rtscts=False, timeout=0.2) as ser: frame = None ping_address(ser, meterbus.ADDRESS_NETWORK_LAYER, 0) if True: ret = ping_address(ser, address, 5) print("Ping status: %s " % ret) if ret: check_reset(ret) else: ser.close() check_reset(ret) return time.sleep(0.1) send_mask_frame(ser, address) frame = meterbus.load(meterbus.recv_frame(ser, 1)) assert isinstance(frame, meterbus.TelegramACK) print("custom ok") ping_address(ser, meterbus.ADDRESS_NETWORK_LAYER, 0) meterbus.send_request_frame(ser, address) recv = meterbus.recv_frame(ser, meterbus.FRAME_DATA_LENGTH) # print("recv", recv) frame = meterbus.load(recv) ser.close() return frame if frame is not None: print(frame.body.interpreted['records'][0]['value']) ser.close() except serial.serialutil.SerialException as e: print("SerialException") print(e)
def setG4fast(address, enable=True): meterbus.send_request_setLUG_G4_fast_readout(ser, address, enable) try: frame = meterbus.load(meterbus.recv_frame(ser, 1)) if isinstance(frame, meterbus.TelegramACK): return True except meterbus.MBusFrameDecodeError: pass return False
def setG4modern(address): meterbus.send_request_setLUG_G4_readout_control(ser, address, 0x00) try: frame = meterbus.load(meterbus.recv_frame(ser, 1)) if isinstance(frame, meterbus.TelegramACK): return True except meterbus.MBusFrameDecodeError: pass return False
def ping_address(ser, address, retries=5): for i in range(0, retries + 1): meterbus.send_ping_frame(ser, address) try: frame = meterbus.load(meterbus.recv_frame(ser, 1)) if isinstance(frame, meterbus.TelegramACK): return True except meterbus.MBusFrameDecodeError: pass return False
def setPrimary(address, newAddress): meterbus.send_request_setPrimary(ser, address, newAddress) try: frame = meterbus.load(meterbus.recv_frame(ser, 1)) if isinstance(frame, meterbus.TelegramACK): return True except meterbus.MBusFrameDecodeError: pass return False
def test_ping_frame(self): self.reset() meterbus.send_ping_frame(self.master, 0) self.assertEqual(self.slave.read(5), b"\x10\x40\x00\x40\x16") # 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 ping_address(ser, address, retries=5, read_echo=False): for i in range(0, retries + 1): meterbus.send_ping_frame(ser, address, read_echo) try: frame = meterbus.load(meterbus.recv_frame(ser, 1)) if isinstance(frame, meterbus.TelegramACK): return True except meterbus.MBusFrameDecodeError as e: pass time.sleep(0.5) return False
def test_empty_reply(self): self.reset() meterbus.send_ping_frame(self.master, 0) self.assertEqual(self.slave.read(5), b"\x10\x40\x00\x40\x16") # Slave does not send anything frame_data = meterbus.recv_frame(self.master, 1) try: frame = meterbus.load(frame_data) except MBusFrameDecodeError as e: frame = e.value self.assertEqual(frame, None)
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 serial_request_single(): 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="dump", 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, URI or binary file') args = parser.parse_args() meterbus.debug(args.d) frame = None try: mode = os.stat(args.device).st_mode if stat.S_ISREG(mode): with open(args.device, 'rb') as f: frame = meterbus.load(f.read()) else: frame = do_char_dev(args) except OSError: frame = do_char_dev(args) if frame is not None: print(serialize_frame(frame, args.output))
def test_record15_unit(self): tele = meterbus.load(self.frame) records = tele.body.bodyPayload.records self.assertEqual(records[14].unit, "none")
def test_record4_value(self): tele = meterbus.load(self.frame) records = tele.body.bodyPayload.records self.assertAlmostEqual(float(records[3].parsed_value), 379716.8, 5)
def test_record11_value(self): tele = meterbus.load(self.frame) records = tele.body.bodyPayload.records self.assertEqual(records[10].parsed_value, 42.5)
def test_record1_value(self): tele = meterbus.load(self.frame) records = tele.body.bodyPayload.records self.assertEqual(records[0].parsed_value, "18.3.2016")
def test_record2_value(self): tele = meterbus.load(self.frame) records = tele.body.bodyPayload.records self.assertEqual(records[1].parsed_value, 5853400000000)
def test_record9_unit(self): tele = meterbus.load(self.frame) records = tele.body.bodyPayload.records self.assertEqual(records[8].unit, "m^3/h")
def test_short_frame(self): tele = meterbus.load(self.short_frame) self.assertIsInstance(tele, meterbus.TelegramShort)
def test_control_frame(self): tele = meterbus.load(self.control_frame) self.assertIsInstance(tele, meterbus.TelegramControl)
def test_record5_value(self): tele = meterbus.load(list(map(ord, self.frame))) records = tele.body.bodyPayload.records self.assertAlmostEqual(records[4].parsed_value, 53.1, 5)
def test_record4_value(self): tele = meterbus.load(list(map(ord, self.frame))) records = tele.body.bodyPayload.records self.assertEqual(records[3].parsed_value, 22)
def test_record14_value(self): tele = meterbus.load(self.frame) records = tele.body.bodyPayload.records self.assertEqual(records[13].parsed_value, 104688000)
def test_record13_value(self): tele = meterbus.load(self.frame) records = tele.body.bodyPayload.records self.assertEqual(records[12].parsed_value, 137055600)
def test_record12_value(self): tele = meterbus.load(self.frame) records = tele.body.bodyPayload.records self.assertAlmostEqual(float(records[11].parsed_value), 38.9, 5)
def test_record6_unit(self): tele = meterbus.load(list(map(ord, self.frame))) records = tele.body.bodyPayload.records self.assertEqual(records[5].unit, "none")
def test_long_frame(self): tele = meterbus.load(self.long_frame) self.assertIsInstance(tele, meterbus.TelegramLong)
def do_reg_file(args): with open(args.device, 'rb') as f: frame = meterbus.load(f.read()) if frame is not None: print(frame.to_JSON())
def test_record_count(self): tele = meterbus.load(self.frame) self.assertEquals(len(tele.body.bodyPayload.records), 6)
def test_record1_value(self): tele = meterbus.load(self.frame) records = tele.body.bodyPayload.records self.assertEqual(records[0].parsed_value, "2016-03-18")
def test_record14_unit(self): tele = meterbus.load(self.frame) records = tele.body.bodyPayload.records self.assertEqual(records[13].unit, "seconds")
def test_record_count(self): tele = meterbus.load(self.frame) self.assertEqual(len(tele.body.bodyPayload.records), 15)
def test_load_empty(self): with self.assertRaises(MBusFrameDecodeError): meterbus.load("INVALID_DATA")
def test_record10_value(self): tele = meterbus.load(list(map(ord, self.frame))) records = tele.body.bodyPayload.records self.assertAlmostEqual(float(records[9].parsed_value), 22.69, 5)
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: frame = meterbus.load(meterbus.recv_frame(ser)) except meterbus.MBusFrameDecodeError:
def test_record6_value(self): tele = meterbus.load(map(ord, self.frame)) records = tele.body.bodyPayload.records self.assertEquals(records[5].parsed_value, 0)
def test_ack_frame(self): tele = meterbus.load(self.ack_frame) self.assertIsInstance(tele, meterbus.TelegramACK)
def test_record4_unit(self): tele = meterbus.load(map(ord, self.frame)) records = tele.body.bodyPayload.records self.assertEquals(records[3].unit.name, "C")