Exemple #1
0
 def __parse(sml_frame: SmlFrame) -> tp.Optional[Sample]:
     """
     Internal helper to extract relevant information
     :param sml_frame: SmlFrame from parser
     """
     sample = None
     for sml_mesage in sml_frame:
         if 'messageBody' in sml_mesage:
             sml_list: tp.List[SmlListEntry] = sml_mesage[
                 'messageBody'].get('valList', [])
             for sml_entry in sml_list:
                 if sample is None:
                     sample = Sample()
                 obis_code: str = sml_entry.get('objName', '')
                 value = sml_entry.get('value', '')
                 # Differentiate SML Messages based on whether they contain a unit
                 if 'unit' in sml_entry:
                     sample.channels.append(
                         ChannelValue(obis_code, value,
                                      sml_entry.get('unit')))
                 else:
                     # Determine the meter_id from OBIS code
                     if obis_code in SmlReader.OBIS_CODES_METER_ID:
                         sample.meter_id = value
                     # Add Channels without unit
                     else:
                         sample.channels.append(
                             ChannelValue(obis_code, value))
     return sample
Exemple #2
0
 def __init__(self) -> None:
     test_data = SerialTestData(
         binary=
         b'\x1b\x1b\x1b\x1b\x01\x01\x01\x01v\x07\x00\x07\r\xf8\xb2\xd7b\x00b\x00rc\x01\x01v\x01\x01\x07\x00\x07\x0b?;\x9d\x0b\t\x01EMH\x00\x00K\x18\xe2\x01\x01cXk\x00v\x07\x00\x07\r\xf8\xb2\xd8b\x00b\x00rc\x07\x01w\x01\x0b\t\x01EMH\x00\x00K\x18\xe2\x07\x01\x00b\n\xff\xffrb\x01e\x0b?\xeejzw\x07\x81\x81\xc7\x82\x03\xff\x01\x01\x01\x01\x04EMH\x01w\x07\x01\x00\x00\x00\t\xff\x01\x01\x01\x01\x0b\t\x01EMH\x00\x00K\x18\xe2\x01w\x07\x01\x00\x01\x08\x00\xffd\x01\x01\xa2\x01b\x1eR\xffV\x00\x10T\xf2\xfe\x01w\x07\x01\x00\x02\x08\x00\xffd\x01\x01\xa2\x01b\x1eR\xffV\x00\x0bHz\xf0\x01w\x07\x01\x00\x01\x08\x01\xff\x01\x01b\x1eR\xffV\x00\x10T\xf2\xfe\x01w\x07\x01\x00\x02\x08\x01\xff\x01\x01b\x1eR\xffV\x00\x0bHz\xf0\x01w\x07\x01\x00\x01\x08\x02\xff\x01\x01b\x1eR\xffV\x00\x00\x00\x00\x00\x01w\x07\x01\x00\x02\x08\x02\xff\x01\x01b\x1eR\xffV\x00\x00\x00\x00\x00\x01w\x07\x01\x00\x10\x07\x00\xff\x01\x01b\x1bR\xffU\xff\xff\xf3\xfa\x01w\x07\x81\x81\xc7\x82\x05\xff\x01rb\x01e\x0b?\xeej\x01\x01\x83\x02X\xaf(\x9aa\x13R\x98L\xf8R\x95#~\xf2fp\xcb=6~!\x8bH\xd9Rx\x9f\xc4\xa5\x88\x86\x04\x01+24\x90\xce\xd3\xd9m4\x1c\x9e\x9c\xcfw\x01\x01\x01c[\x12\x00v\x07\x00\x07\r\xf8\xb2\xdbb\x00b\x00rc\x02\x01q\x01c;\x15\x00\x00\x1b\x1b\x1b\x1b\x1a\x01\x1b\xe1',
         meter_id='1 EMH 00 4921570',
         channels=[
             ChannelValue(channel_name='129-129:199.130.3*255',
                          value='EMH',
                          unit=None),
             ChannelValue(channel_name='1-0:1.8.0*255',
                          value=27400268.6,
                          unit='Wh'),
             ChannelValue(channel_name='1-0:2.8.0*255',
                          value=18929944.0,
                          unit='Wh'),
             ChannelValue(channel_name='1-0:1.8.1*255',
                          value=27400268.6,
                          unit='Wh'),
             ChannelValue(channel_name='1-0:2.8.1*255',
                          value=18929944.0,
                          unit='Wh'),
             ChannelValue(channel_name='1-0:1.8.2*255', value=0, unit='Wh'),
             ChannelValue(channel_name='1-0:2.8.2*255', value=0, unit='Wh'),
             ChannelValue(channel_name='1-0:16.7.0*255',
                          value=-307.8,
                          unit='W'),
             ChannelValue(
                 channel_name='129-129:199.130.5*255',
                 value=
                 '58af289a611352984cf85295237ef26670cb3d367e218b48d952789fc4a5888604012b323490ced3d96d341c9e9ccf77',
                 unit=None)
         ])
     super().__init__(test_data)
 def __init__(self) -> None:
     start_sequence = b"/?!\x0D\x0A"
     test_frame = b'\x026.8(0006047*kWh)6.26(00428.35*m3)9.21(99999999)\r\n'
     test_data = SerialTestData(binary=start_sequence + test_frame,
                                meter_id='99999999',
                                channels=[
                                    ChannelValue(channel_name='6.8',
                                                 value=6047.0,
                                                 unit='kWh'),
                                    ChannelValue(channel_name='6.26',
                                                 value=428.35,
                                                 unit='m3')
                                ])
     super().__init__(test_data)
Exemple #4
0
 def _fetch_untracked(self) -> tp.Optional[Sample]:
     with self.__access_lock:
         if self.__fetch_possible:
             self.counter += 1
             return Sample(meter_id=self.sample_meter_id,
                           channels=[ChannelValue("COUNTER", self.counter)])
     return None
Exemple #5
0
 def __init__(self) -> None:
     test_data = SerialTestData(
         binary=
         b'\x1b\x1b\x1b\x1b\x01\x01\x01\x01v\x05\tLN\x1db\x00b\x00rc\x01\x01v\x01\x01\x05\x03\x19o_\x0b\n\x01ISK\x00\x045\xa9.rb\x01e\x03\x19p#b\x01c\xfe\x90\x00v\x05\tLN\x1eb\x00b\x00rc\x07\x01w\x01\x0b\n\x01ISK\x00\x045\xa9.\x07\x01\x00b\n\xff\xffrb\x01e\x03\x19p#uw\x07\x01\x00`2\x01\x01\x01\x01\x01\x01\x04ISK\x01w\x07\x01\x00`\x01\x00\xff\x01\x01\x01\x01\x0b\n\x01ISK\x00\x045\xa9.\x01w\x07\x01\x00\x01\x08\x00\xffe\x00\x1c)\x04\x01b\x1eR\xffe\x01"\xd9\x15\x01w\x07\x01\x00\x02\x08\x00\xff\x01\x01b\x1eR\xffe\x02\x8d\x94\x85\x01w\x07\x01\x00\x10\x07\x00\xff\x01\x01b\x1bR\x00S\xfe\xe4\x01\x01\x01c\xd6\xd5\x00v\x05\tLN\x1fb\x00b\x00rc\x02\x01q\x01cW\xe6\x00\x00\x1b\x1b\x1b\x1b\x1a\x01\x0b\x83',
         meter_id='1 ISK 00 70625582',
         channels=[
             ChannelValue(channel_name='1-0:96.50.1*1',
                          value=b'ISK',
                          unit=None),
             ChannelValue(channel_name='1-0:1.8.0*255',
                          value=1906101.3,
                          unit='Wh'),
             ChannelValue(channel_name='1-0:2.8.0*255',
                          value=4283302.9,
                          unit='Wh'),
             ChannelValue(channel_name='1-0:16.7.0*255',
                          value=-284,
                          unit='W')
         ])
     super().__init__(test_data)
Exemple #6
0
 def __parse(response: str) -> tp.Optional[Sample]:
     """
     Internal helper to extract relevant information
     :param response: decoded line
     """
     parsed = None
     for ident, value, unit in re.findall(r"([\d.]+)\(([\d.]+)\*?([\w\d.]+)?\)", response):
         if parsed is None:
             parsed = Sample()
         if not unit and ident == "9.21":
             parsed.meter_id = value
         else:
             parsed.channels.append(ChannelValue(ident, float(value), unit))
     return parsed
    def __exit__(self, exit_type, value, traceback) -> None:
        self.open = False


REG_ADDR_CHIP_ID = 0xD0
REG_ADDR_MEASUREMENT_START = 0xF7
REG_ADDR_CALIBRATION1_START = 0x88
REG_ADDR_CALIBRATION2_START = 0xE1
REG_ADDR_STATUS = 0xF3

bm280_testdata = I2CTestData(
    meter_id=
    "BME280-078fc53ee157b535d787a94e8ac2f05ed6083c8d21ef77389021ae97961d7d0a",
    channels=[
        ChannelValue(channel_name="TEMPERATURE",
                     value=19.272266477266385,
                     unit="°C"),
        ChannelValue(channel_name="PRESSURE",
                     value=99855.59723964224,
                     unit="Pa"),
        ChannelValue(channel_name="HUMIDITY",
                     value=50.935725617532256,
                     unit="%")
    ],
    static_registers={
        REG_ADDR_CHIP_ID: 0x60,
        REG_ADDR_STATUS: 0b00000000,
        REG_ADDR_MEASUREMENT_START + 0: 83,
        REG_ADDR_MEASUREMENT_START + 1: 224,
        REG_ADDR_MEASUREMENT_START + 2: 0,
        REG_ADDR_MEASUREMENT_START + 3: 126,
Exemple #8
0
                }
            },
            'id': 118,
            'protocol': 'BME280'
        }
    },
    'middleware': {
        'type': 'volkszaehler',
        'middleware_url': 'http://localhost/middleware.php'
    }
}

SAMPLE_BME = Sample()
SAMPLE_BME.meter_id = '0x76'
SAMPLE_BME.channels = [
    ChannelValue('TEMPERATURE', 20.0, 'C'),
    ChannelValue('HUMIDITY', 50.0, '%'),
    ChannelValue('PRESSURE', 1000.0, 'hPa')
]

SAMPLE_SML = Sample()
SAMPLE_SML.meter_id = '1 EMH00 12345678'
SAMPLE_SML.channels = [ChannelValue('1.8.0*255', 10000, 'kWh')]

SAMPLE_PLAIN = Sample()
SAMPLE_PLAIN.meter_id = '888777666'
SAMPLE_PLAIN.channels = [ChannelValue('6.8', 20000, 'kWh')]


class MockedGateway(VolkszaehlerGateway):
    def post(self, channel, value, sample_timestamp, poll_timestamp):
 def _fetch_untracked(self) -> tp.Optional[Sample]:
     # pylint: disable=too-many-locals
     try:
         with Bme280Reader.I2C_BUS_LOCK:
             with SMBus(self.i2c_bus) as bus:
                 # Read Chip ID
                 chip_id = bus.read_byte_data(self.i2c_address, Bme280Reader.REG_ADDR_CHIP_ID)
                 if self.__calibration_data is None or not self.cache_calibration:
                     self.__calibration_data = self.__read_calibration_data(bus)
                 else:
                     logger.debug("Using cached calibration data")
                 calibration_data = self.__calibration_data
                 # Reconfigure sensor
                 if self.__reconfiguration_required or self.mode is Bme280SensorMode.FORCED:
                     # Reset sensor to sleep mode for reconfiguration
                     self.__reset(bus)
                     logger.debug("Reconfiguring sensor")
                     # Configure humidity
                     self.__set_register_ctrl_hum(bus, self.humidity_oversampling)
                     # Configure other measurement parameters
                     self.__set_register_config(bus, self.standby_time, self.irr_filter_coefficient)
                     # Activate configuration
                     self.__set_register_ctrl_meas(bus, self.mode, self.temperature_oversampling,
                                                   self.pressure_oversampling)
                     self.__reconfiguration_required = False
                 # Wait for the measurement if running in forced mode
                 if self.mode is Bme280SensorMode.FORCED:
                     logger.debug("Waiting for measurement to complete in forced mode")
                     osrs_t_time = 2.3 * self.temperature_oversampling
                     osrs_p_time = 2.3 * self.pressure_oversampling + 0.575
                     osrs_h_time = 2.3 * self.humidity_oversampling + 0.575
                     measurement_time = 1.25 + osrs_t_time + osrs_p_time + osrs_h_time
                     # Wait for measurement to complete
                     time.sleep(measurement_time / 1000)
                     # Read measuring status
                     measuring, _ = self.__read_status(bus)
                     if measuring:
                         logger.error("Measurement is still in progress after maximum measurement time! Aborting...")
                         return None
                 # Read measurement registers
                 logger.debug("Reading measurement registers")
                 measurement = bus.read_i2c_block_data(self.i2c_address, Bme280Reader.REG_ADDR_MEASUREMENT_START, 8)
         # Parse measurement
         logger.debug("Parsing measurement")
         measurement_container = Bme280Reader.STRUCT_MEASUREMENT.parse(bytes(measurement))
         # Calculate fine temperature to enable temperature compensation for the other measurements
         fine_temperature = Bme280Reader.calculate_fine_temperature(calibration_data, measurement_container.temp_raw)
         # Calculate measurement results
         temperature = Bme280Reader.calculate_temperature(fine_temperature)
         pressure = Bme280Reader.calculate_pressure(calibration_data, measurement_container.press_raw,
                                            fine_temperature)
         humidity = Bme280Reader.calculate_humidity(calibration_data, measurement_container.hum_raw,
                                                    fine_temperature)
         # Determine meter_id
         meter_id = Bme280Reader.derive_meter_id(calibration_data, chip_id)
         # Return Sample
         return Sample(meter_id=meter_id, channels=[ChannelValue('TEMPERATURE', temperature, '°C'),
                                                    ChannelValue('PRESSURE', pressure, 'Pa'),
                                                    ChannelValue('HUMIDITY', humidity, '%')])
     except OSError as err:
         logger.error(f"Accessing the smbus faild: {err}")
     except ConstructError as err:
         logger.error(f"Parsing the binary data failed: {err}")
     return None