コード例 #1
0
ファイル: socket_.py プロジェクト: lowdef/dsmr_parser
    def __init__(self, host, port, telegram_specification):
        self.host = host
        self.port = port

        self.telegram_parser = TelegramParser(telegram_specification)
        self.telegram_buffer = TelegramBuffer()
        self.telegram_specification = telegram_specification
コード例 #2
0
ファイル: decrypt.py プロジェクト: svrooij/smarty_dsmr_proxy
    def analyze(self):
        key = binascii.unhexlify(self._args.key)
        additional_data = binascii.unhexlify(self._args.aad)
        iv = binascii.unhexlify(self._system_title + self._frame_counter)
        payload = binascii.unhexlify(self._payload)
        gcm_tag = binascii.unhexlify(self._gcm_tag)

        try:
            decryption = self.decrypt(key, additional_data, iv, payload,
                                      gcm_tag)
            if has_dsmr_parser and self._args.parse:

                try:
                    parser = TelegramParser(telegram_specifications.V5)

                    telegram = parser.parse(decryption.decode())
                    for key in telegram:
                        print("%s: %s" %
                              (dsmr_parser.obis_name_mapping.EN[key],
                               telegram[key]))
                except:
                    print("ERROR: Cannot parse DSMR Telegram")
                    print(decryption)
            else:
                print(decryption)

            if self._args.serial_output_port:
                self.write_to_serial_port(decryption)
        except InvalidTag:
            print("ERROR: Invalid Tag.")
コード例 #3
0
ファイル: serial_.py プロジェクト: lowdef/dsmr_parser
    def __init__(self, device, serial_settings, telegram_specification):
        self.serial_settings = serial_settings
        self.serial_settings[self.PORT_KEY] = device

        self.telegram_parser = TelegramParser(telegram_specification)
        self.telegram_buffer = TelegramBuffer()
        self.telegram_specification = telegram_specification
コード例 #4
0
ファイル: test_parse_v5.py プロジェクト: Smeedy/dsmr_parser
    def test_checksum_invalid(self):
        # Remove the electricty used data value. This causes the checksum to
        # not match anymore.
        corrupted_telegram = TELEGRAM_V5.replace(
            '1-0:1.8.1(000004.426*kWh)\r\n', '')

        with self.assertRaises(InvalidChecksumError):
            TelegramParser.validate_checksum(corrupted_telegram)
コード例 #5
0
ファイル: serial_.py プロジェクト: stefvra/dsmr_parser
class SerialReader(object):
    PORT_KEY = 'port'

    def __init__(self, device, serial_settings, telegram_specification):
        self.serial_settings = serial_settings
        self.serial_settings[self.PORT_KEY] = device

        self.telegram_parser = TelegramParser(telegram_specification)
        self.telegram_buffer = TelegramBuffer()

    def read_continuously(self):
        """
        Read complete DSMR telegram's from the serial interface and parse it
        into CosemObject's and MbusObject's

        :rtype: generator
        """
        with serial.Serial(**self.serial_settings) as serial_handle:
            while True:
                data = serial_handle.read(
                    max(1, min(1024, serial_handle.in_waiting)))
                self.telegram_buffer.append(data.decode('ascii'))

                for telegram in self.telegram_buffer.get_all():
                    try:
                        yield self.telegram_parser.parse(telegram)
                    except InvalidChecksumError as e:
                        logger.warning(str(e))
                    except ParseError as e:
                        logger.error('Failed to parse telegram: %s', e)

    def read(self):
        """
            Read complete DSMR telegram's from the serial interface and parse it
            into CosemObject's and MbusObject's

            :rtype: generator
            """
        with serial.Serial(**self.serial_settings) as serial_handle:
            data = serial_handle.read(
                max(1, min(1024, serial_handle.in_waiting)))
            self.telegram_buffer.append(data.decode('ascii'))

            for telegram in self.telegram_buffer.get_all():
                try:
                    yield self.telegram_parser.parse(telegram)
                except InvalidChecksumError as e:
                    logger.warning(str(e))
                except ParseError as e:
                    logger.error('Failed to parse telegram: %s', e)
コード例 #6
0
def parse(user, telegram):
    """
    Parse a DSMR telegram and log the values in the appropriate places in the
    database.

    :param django.contrib.auth.models.User user:
    :param str telegram:
    """
    parser = TelegramParser(SPECIFICATION)
    parsed_telegram = parser.parse(telegram.split("\r\n"))

    log_consumed_electricity(user=user, parsed_telegram=parsed_telegram)
    log_produced_energy(user=user, parsed_telegram=parsed_telegram)
    log_consumed_gas(user=user, parsed_telegram=parsed_telegram)
コード例 #7
0
def telegram_to_reading(data: str) -> DsmrReading:
    """ Converts a P1 telegram to a DSMR reading, which will be stored in database. """
    params = get_dsmr_connection_parameters()
    parser = TelegramParser(params['specifications'])
    logger.debug("Received telegram:\n%s", data)

    try:
        parsed_telegram = parser.parse(data)
    except (InvalidChecksumError, ParseError) as error:
        # Hook to keep track of failed readings count.
        MeterStatistics.objects.all().update(
            rejected_telegrams=F('rejected_telegrams') + 1)
        logger.warning('Rejected telegram: %s', error)
        raise InvalidTelegramError(error) from error

    return _map_telegram_to_model(parsed_telegram=parsed_telegram, data=data)
コード例 #8
0
def create_dsmr_protocol(dsmr_version, telegram_callback, loop=None):
    """Creates a DSMR asyncio protocol."""

    if dsmr_version == '2.2':
        specification = telegram_specifications.V2_2
        serial_settings = SERIAL_SETTINGS_V2_2
    elif dsmr_version == '4':
        specification = telegram_specifications.V4
        serial_settings = SERIAL_SETTINGS_V4
    elif dsmr_version == '5':
        specification = telegram_specifications.V5
        serial_settings = SERIAL_SETTINGS_V5
    elif dsmr_version == '5B':
        specification = telegram_specifications.BELGIUM_FLUVIUS
        serial_settings = SERIAL_SETTINGS_V5
    elif dsmr_version == "5L":
        specification = telegram_specifications.LUXEMBOURG_SMARTY
        serial_settings = SERIAL_SETTINGS_V5
    else:
        raise NotImplementedError("No telegram parser found for version: %s",
                                  dsmr_version)

    protocol = partial(DSMRProtocol,
                       loop,
                       TelegramParser(specification),
                       telegram_callback=telegram_callback)

    return protocol, serial_settings
コード例 #9
0
    def test_instantiate(self):
        parser = TelegramParser(telegram_specifications.V4)
        telegram = Telegram(TELEGRAM_V4_2, parser, telegram_specifications.V4)

        # P1_MESSAGE_HEADER (1-3:0.2.8)
        testitem = telegram.P1_MESSAGE_HEADER
        assert isinstance(testitem, CosemObject)
        assert testitem.unit is None
        assert testitem.value == '42'
コード例 #10
0
    def initialize(self, *args, **kwargs):
        try:
            self.log("Using hass logger!")
        except Exception:
            self.log = self._logme
            self.log("Using test logger!")
        self.mode = 'tcp'
        self.host = 'homeassistant.fritz.box'
        self.port = 3333
        self.device = 'COM3'
        self.dsmr_version = '5'
        self.terminal_name = 'test'
        self.stop = False
        self.transport = None
        self.log("Starting thread...")
        self.log("P1 test started")
        parser = self.test_serial
        # parser = self.tcp

        dsmr_version = self.dsmr_version
        if dsmr_version == '2.2':
            specification = telegram_specifications.V2_2
            serial_settings = SERIAL_SETTINGS_V2_2
        elif dsmr_version == '4':
            specification = telegram_specifications.V4
            serial_settings = SERIAL_SETTINGS_V4
        elif dsmr_version == '5':
            specification = telegram_specifications.V5
            serial_settings = SERIAL_SETTINGS_V5
        elif dsmr_version == '5B':
            specification = telegram_specifications.BELGIUM_FLUVIUS
            serial_settings = SERIAL_SETTINGS_V5
        else:
            raise NotImplementedError(
                "No telegram parser found for version: %s", dsmr_version)
        self.telegram_parser = TelegramParser(specification)
        self.serial_settings = serial_settings
        # buffer to keep incomplete incoming data
        self.telegram_buffer = TelegramBuffer()

        self.thr = threading.Thread(target=parser, daemon=True)
        self.thr.start()
        self.log("Started!")
コード例 #11
0
    def analyze(self):
        key = binascii.unhexlify(self._args.key)
        additional_data = binascii.unhexlify(self._args.aad)
        iv = binascii.unhexlify(self._system_title + self._frame_counter)
        payload = binascii.unhexlify(self._payload)
        gcm_tag = binascii.unhexlify(self._gcm_tag)

        try:
            decryption = self.decrypt(key, additional_data, iv, payload,
                                      gcm_tag)
            if has_dsmr_parser and self._args.parse:

                try:
                    parser = TelegramParser(telegram_specifications.V5)

                    telegram = parser.parse(decryption.decode())
                    for key in telegram:
                        if key in dsmr_parser.obis_name_mapping.EN:
                            print("%s: %s" %
                                  (dsmr_parser.obis_name_mapping.EN[key],
                                   telegram[key]))
                            if has_mqtt:
                                try:
                                    self._mqtt_client.publish(
                                        self._args.topic_prefix + '/' +
                                        dsmr_parser.obis_name_mapping.EN[key],
                                        str(telegram[key].value))
                                except:
                                    print("ERROR: cannot publish to MQTT")
                        else:
                            print("%s: %s" % (key, telegram[key]))
                except Exception as e:
                    print("ERROR: Cannot parse DSMR Telegram")
                    print("Exception: ", sys.exc_info()[0])
                    print(decryption)
            else:
                print(decryption)

            if self._args.serial_output_port:
                self.write_to_serial_port(decryption)
        except InvalidTag:
            print("ERROR: Invalid Tag.")
コード例 #12
0
ファイル: terminal.py プロジェクト: tharealmb/omnikdatalogger
 def _get_dsmr_parser(self):
     dsmr_version = self.dsmr_version
     if dsmr_version == '2.2':
         specification = telegram_specifications.V2_2
         serial_settings = SERIAL_SETTINGS_V2_2
     elif dsmr_version == '4':
         specification = telegram_specifications.V4
         serial_settings = SERIAL_SETTINGS_V4
     elif dsmr_version == '5':
         specification = telegram_specifications.V5
         serial_settings = SERIAL_SETTINGS_V5
     elif dsmr_version == '5B':
         specification = telegram_specifications.BELGIUM_FLUVIUS
         serial_settings = SERIAL_SETTINGS_V5
     else:
         raise NotImplementedError(
             "No telegram parser found for version: %s", dsmr_version)
     self.telegram_parser = TelegramParser(specification)
     serial_settings['timeout'] = 10
     self.serial_settings = serial_settings
コード例 #13
0
    def test_power_event_log_empty_1(self):
        # POWER_EVENT_FAILURE_LOG (1-0:99.97.0)
        parser = TelegramParser(telegram_specifications.V5)
        telegram = Telegram(TELEGRAM_V5, parser, telegram_specifications.V5)

        object_type = ProfileGenericObject
        testitem = telegram.POWER_EVENT_FAILURE_LOG
        assert isinstance(testitem, object_type)
        assert testitem.buffer_length == 0
        assert testitem.buffer_type == '0-0:96.7.19'
        buffer = testitem.buffer
        assert isinstance(testitem.buffer, list)
        assert len(buffer) == 0
コード例 #14
0
def telegram_to_reading(data):
    """ Converts a P1 telegram to a DSMR reading, which will be stored in database. """
    params = get_dsmr_connection_parameters()
    parser = TelegramParser(params['specifications'])

    # We will log the telegrams in base64 for convenience and debugging.
    base64_data = base64.b64encode(data.encode())

    if settings.DSMRREADER_LOG_TELEGRAMS:
        dsmrreader_logger.info('Received telegram (base64 encoded): %s',
                               base64_data)

    try:
        parsed_telegram = parser.parse(data)
    except (InvalidChecksumError, ParseError) as error:
        # Hook to keep track of failed readings count.
        MeterStatistics.objects.all().update(
            rejected_telegrams=F('rejected_telegrams') + 1)
        dsmrreader_logger.warning(
            'Rejected telegram (%s) (base64 encoded): %s', error, base64_data)
        dsmrreader_logger.exception(error)
        raise InvalidTelegramError(error)

    return _map_telegram_to_model(parsed_telegram=parsed_telegram, data=data)
コード例 #15
0
ファイル: test_parse_v5.py プロジェクト: Smeedy/dsmr_parser
    def test_parse(self):
        parser = TelegramParser(telegram_specifications.V5)
        result = parser.parse(TELEGRAM_V5)

        # P1_MESSAGE_HEADER (1-3:0.2.8)
        assert isinstance(result[obis.P1_MESSAGE_HEADER], CosemObject)
        assert result[obis.P1_MESSAGE_HEADER].unit is None
        assert isinstance(result[obis.P1_MESSAGE_HEADER].value, str)
        assert result[obis.P1_MESSAGE_HEADER].value == '50'

        # P1_MESSAGE_TIMESTAMP (0-0:1.0.0)
        assert isinstance(result[obis.P1_MESSAGE_TIMESTAMP], CosemObject)
        assert result[obis.P1_MESSAGE_TIMESTAMP].unit is None
        assert isinstance(result[obis.P1_MESSAGE_TIMESTAMP].value,
                          datetime.datetime)
        assert result[obis.P1_MESSAGE_TIMESTAMP].value == \
            datetime.datetime(2017, 1, 2, 18, 20, 2, tzinfo=datetime.timezone.utc)

        # ELECTRICITY_USED_TARIFF_1 (1-0:1.8.1)
        assert isinstance(result[obis.ELECTRICITY_USED_TARIFF_1], CosemObject)
        assert result[obis.ELECTRICITY_USED_TARIFF_1].unit == 'kWh'
        assert isinstance(result[obis.ELECTRICITY_USED_TARIFF_1].value,
                          Decimal)
        assert result[obis.ELECTRICITY_USED_TARIFF_1].value == Decimal('4.426')

        # ELECTRICITY_USED_TARIFF_2 (1-0:1.8.2)
        assert isinstance(result[obis.ELECTRICITY_USED_TARIFF_2], CosemObject)
        assert result[obis.ELECTRICITY_USED_TARIFF_2].unit == 'kWh'
        assert isinstance(result[obis.ELECTRICITY_USED_TARIFF_2].value,
                          Decimal)
        assert result[obis.ELECTRICITY_USED_TARIFF_2].value == Decimal('2.399')

        # ELECTRICITY_DELIVERED_TARIFF_1 (1-0:2.8.1)
        assert isinstance(result[obis.ELECTRICITY_DELIVERED_TARIFF_1],
                          CosemObject)
        assert result[obis.ELECTRICITY_DELIVERED_TARIFF_1].unit == 'kWh'
        assert isinstance(result[obis.ELECTRICITY_DELIVERED_TARIFF_1].value,
                          Decimal)
        assert result[obis.ELECTRICITY_DELIVERED_TARIFF_1].value == Decimal(
            '2.444')

        # ELECTRICITY_DELIVERED_TARIFF_2 (1-0:2.8.2)
        assert isinstance(result[obis.ELECTRICITY_DELIVERED_TARIFF_2],
                          CosemObject)
        assert result[obis.ELECTRICITY_DELIVERED_TARIFF_2].unit == 'kWh'
        assert isinstance(result[obis.ELECTRICITY_DELIVERED_TARIFF_2].value,
                          Decimal)
        assert result[obis.ELECTRICITY_DELIVERED_TARIFF_2].value == Decimal(
            '0')

        # ELECTRICITY_ACTIVE_TARIFF (0-0:96.14.0)
        assert isinstance(result[obis.ELECTRICITY_ACTIVE_TARIFF], CosemObject)
        assert result[obis.ELECTRICITY_ACTIVE_TARIFF].unit is None
        assert isinstance(result[obis.ELECTRICITY_ACTIVE_TARIFF].value, str)
        assert result[obis.ELECTRICITY_ACTIVE_TARIFF].value == '0002'

        # EQUIPMENT_IDENTIFIER (0-0:96.1.1)
        assert isinstance(result[obis.EQUIPMENT_IDENTIFIER], CosemObject)
        assert result[obis.EQUIPMENT_IDENTIFIER].unit is None
        assert isinstance(result[obis.EQUIPMENT_IDENTIFIER].value, str)
        assert result[
            obis.
            EQUIPMENT_IDENTIFIER].value == '4B384547303034303436333935353037'

        # CURRENT_ELECTRICITY_USAGE (1-0:1.7.0)
        assert isinstance(result[obis.CURRENT_ELECTRICITY_USAGE], CosemObject)
        assert result[obis.CURRENT_ELECTRICITY_USAGE].unit == 'kW'
        assert isinstance(result[obis.CURRENT_ELECTRICITY_USAGE].value,
                          Decimal)
        assert result[obis.CURRENT_ELECTRICITY_USAGE].value == Decimal('0.244')

        # CURRENT_ELECTRICITY_DELIVERY (1-0:2.7.0)
        assert isinstance(result[obis.CURRENT_ELECTRICITY_DELIVERY],
                          CosemObject)
        assert result[obis.CURRENT_ELECTRICITY_DELIVERY].unit == 'kW'
        assert isinstance(result[obis.CURRENT_ELECTRICITY_DELIVERY].value,
                          Decimal)
        assert result[obis.CURRENT_ELECTRICITY_DELIVERY].value == Decimal('0')

        # LONG_POWER_FAILURE_COUNT (96.7.9)
        assert isinstance(result[obis.LONG_POWER_FAILURE_COUNT], CosemObject)
        assert result[obis.LONG_POWER_FAILURE_COUNT].unit is None
        assert isinstance(result[obis.LONG_POWER_FAILURE_COUNT].value, int)
        assert result[obis.LONG_POWER_FAILURE_COUNT].value == 0

        # VOLTAGE_SAG_L1_COUNT (1-0:32.32.0)
        assert isinstance(result[obis.VOLTAGE_SAG_L1_COUNT], CosemObject)
        assert result[obis.VOLTAGE_SAG_L1_COUNT].unit is None
        assert isinstance(result[obis.VOLTAGE_SAG_L1_COUNT].value, int)
        assert result[obis.VOLTAGE_SAG_L1_COUNT].value == 0

        # VOLTAGE_SAG_L2_COUNT (1-0:52.32.0)
        assert isinstance(result[obis.VOLTAGE_SAG_L2_COUNT], CosemObject)
        assert result[obis.VOLTAGE_SAG_L2_COUNT].unit is None
        assert isinstance(result[obis.VOLTAGE_SAG_L2_COUNT].value, int)
        assert result[obis.VOLTAGE_SAG_L2_COUNT].value == 0

        # VOLTAGE_SAG_L3_COUNT (1-0:72.32.0)
        assert isinstance(result[obis.VOLTAGE_SAG_L3_COUNT], CosemObject)
        assert result[obis.VOLTAGE_SAG_L3_COUNT].unit is None
        assert isinstance(result[obis.VOLTAGE_SAG_L3_COUNT].value, int)
        assert result[obis.VOLTAGE_SAG_L3_COUNT].value == 0

        # VOLTAGE_SWELL_L1_COUNT (1-0:32.36.0)
        assert isinstance(result[obis.VOLTAGE_SWELL_L1_COUNT], CosemObject)
        assert result[obis.VOLTAGE_SWELL_L1_COUNT].unit is None
        assert isinstance(result[obis.VOLTAGE_SWELL_L1_COUNT].value, int)
        assert result[obis.VOLTAGE_SWELL_L1_COUNT].value == 0

        # VOLTAGE_SWELL_L2_COUNT (1-0:52.36.0)
        assert isinstance(result[obis.VOLTAGE_SWELL_L2_COUNT], CosemObject)
        assert result[obis.VOLTAGE_SWELL_L2_COUNT].unit is None
        assert isinstance(result[obis.VOLTAGE_SWELL_L2_COUNT].value, int)
        assert result[obis.VOLTAGE_SWELL_L2_COUNT].value == 0

        # VOLTAGE_SWELL_L3_COUNT (1-0:72.36.0)
        assert isinstance(result[obis.VOLTAGE_SWELL_L3_COUNT], CosemObject)
        assert result[obis.VOLTAGE_SWELL_L3_COUNT].unit is None
        assert isinstance(result[obis.VOLTAGE_SWELL_L3_COUNT].value, int)
        assert result[obis.VOLTAGE_SWELL_L3_COUNT].value == 0

        # TEXT_MESSAGE (0-0:96.13.0)
        assert isinstance(result[obis.TEXT_MESSAGE], CosemObject)
        assert result[obis.TEXT_MESSAGE].unit is None
        assert result[obis.TEXT_MESSAGE].value is None

        # DEVICE_TYPE (0-x:24.1.0)
        assert isinstance(result[obis.TEXT_MESSAGE], CosemObject)
        assert result[obis.DEVICE_TYPE].unit is None
        assert isinstance(result[obis.DEVICE_TYPE].value, int)
        assert result[obis.DEVICE_TYPE].value == 3

        # INSTANTANEOUS_ACTIVE_POWER_L1_POSITIVE (1-0:21.7.0)
        assert isinstance(result[obis.INSTANTANEOUS_ACTIVE_POWER_L1_POSITIVE],
                          CosemObject)
        assert result[obis.INSTANTANEOUS_ACTIVE_POWER_L1_POSITIVE].unit == 'kW'
        assert isinstance(
            result[obis.INSTANTANEOUS_ACTIVE_POWER_L1_POSITIVE].value, Decimal)
        assert result[
            obis.INSTANTANEOUS_ACTIVE_POWER_L1_POSITIVE].value == Decimal(
                '0.070')

        # INSTANTANEOUS_ACTIVE_POWER_L2_POSITIVE (1-0:41.7.0)
        assert isinstance(result[obis.INSTANTANEOUS_ACTIVE_POWER_L2_POSITIVE],
                          CosemObject)
        assert result[obis.INSTANTANEOUS_ACTIVE_POWER_L2_POSITIVE].unit == 'kW'
        assert isinstance(
            result[obis.INSTANTANEOUS_ACTIVE_POWER_L2_POSITIVE].value, Decimal)
        assert result[
            obis.INSTANTANEOUS_ACTIVE_POWER_L2_POSITIVE].value == Decimal(
                '0.032')

        # INSTANTANEOUS_ACTIVE_POWER_L3_POSITIVE (1-0:61.7.0)
        assert isinstance(result[obis.INSTANTANEOUS_ACTIVE_POWER_L3_POSITIVE],
                          CosemObject)
        assert result[obis.INSTANTANEOUS_ACTIVE_POWER_L3_POSITIVE].unit == 'kW'
        assert isinstance(
            result[obis.INSTANTANEOUS_ACTIVE_POWER_L3_POSITIVE].value, Decimal)
        assert result[
            obis.INSTANTANEOUS_ACTIVE_POWER_L3_POSITIVE].value == Decimal(
                '0.142')

        # INSTANTANEOUS_ACTIVE_POWER_L1_NEGATIVE (1-0:22.7.0)
        assert isinstance(result[obis.INSTANTANEOUS_ACTIVE_POWER_L1_NEGATIVE],
                          CosemObject)
        assert result[obis.INSTANTANEOUS_ACTIVE_POWER_L1_NEGATIVE].unit == 'kW'
        assert isinstance(
            result[obis.INSTANTANEOUS_ACTIVE_POWER_L1_NEGATIVE].value, Decimal)
        assert result[
            obis.INSTANTANEOUS_ACTIVE_POWER_L1_NEGATIVE].value == Decimal('0')

        # INSTANTANEOUS_ACTIVE_POWER_L2_NEGATIVE (1-0:42.7.0)
        assert isinstance(result[obis.INSTANTANEOUS_ACTIVE_POWER_L2_NEGATIVE],
                          CosemObject)
        assert result[obis.INSTANTANEOUS_ACTIVE_POWER_L2_NEGATIVE].unit == 'kW'
        assert isinstance(
            result[obis.INSTANTANEOUS_ACTIVE_POWER_L2_NEGATIVE].value, Decimal)
        assert result[
            obis.INSTANTANEOUS_ACTIVE_POWER_L2_NEGATIVE].value == Decimal('0')

        # INSTANTANEOUS_ACTIVE_POWER_L3_NEGATIVE (1-0:62.7.0)
        assert isinstance(result[obis.INSTANTANEOUS_ACTIVE_POWER_L3_NEGATIVE],
                          CosemObject)
        assert result[obis.INSTANTANEOUS_ACTIVE_POWER_L3_NEGATIVE].unit == 'kW'
        assert isinstance(
            result[obis.INSTANTANEOUS_ACTIVE_POWER_L3_NEGATIVE].value, Decimal)
        assert result[
            obis.INSTANTANEOUS_ACTIVE_POWER_L3_NEGATIVE].value == Decimal('0')

        # EQUIPMENT_IDENTIFIER_GAS (0-x:96.1.0)
        assert isinstance(result[obis.EQUIPMENT_IDENTIFIER_GAS], CosemObject)
        assert result[obis.EQUIPMENT_IDENTIFIER_GAS].unit is None
        assert isinstance(result[obis.EQUIPMENT_IDENTIFIER_GAS].value, str)
        assert result[
            obis.
            EQUIPMENT_IDENTIFIER_GAS].value == '3232323241424344313233343536373839'

        # HOURLY_GAS_METER_READING (0-1:24.2.1)
        assert isinstance(result[obis.HOURLY_GAS_METER_READING], MBusObject)
        assert result[obis.HOURLY_GAS_METER_READING].unit == 'm3'
        assert isinstance(result[obis.HOURLY_GAS_METER_READING].value, Decimal)
        assert result[obis.HOURLY_GAS_METER_READING].value == Decimal('0.107')
コード例 #16
0
    def test_instantiate(self):
        parser = TelegramParser(telegram_specifications.V4)
        telegram = Telegram(TELEGRAM_V4_2, parser, telegram_specifications.V4)

        # P1_MESSAGE_HEADER (1-3:0.2.8)
        self.verify_telegram_item(telegram,
                                  'P1_MESSAGE_HEADER',
                                  object_type=CosemObject,
                                  unit_val=None,
                                  value_type=str,
                                  value_val='42')

        # P1_MESSAGE_TIMESTAMP (0-0:1.0.0)
        self.verify_telegram_item(telegram,
                                  'P1_MESSAGE_TIMESTAMP',
                                  CosemObject,
                                  unit_val=None,
                                  value_type=datetime.datetime,
                                  value_val=datetime.datetime(2016,
                                                              11,
                                                              13,
                                                              19,
                                                              57,
                                                              57,
                                                              tzinfo=pytz.UTC))

        # ELECTRICITY_USED_TARIFF_1 (1-0:1.8.1)
        self.verify_telegram_item(telegram,
                                  'ELECTRICITY_USED_TARIFF_1',
                                  object_type=CosemObject,
                                  unit_val='kWh',
                                  value_type=Decimal,
                                  value_val=Decimal('1581.123'))

        # ELECTRICITY_USED_TARIFF_2 (1-0:1.8.2)
        self.verify_telegram_item(telegram,
                                  'ELECTRICITY_USED_TARIFF_2',
                                  object_type=CosemObject,
                                  unit_val='kWh',
                                  value_type=Decimal,
                                  value_val=Decimal('1435.706'))

        # ELECTRICITY_DELIVERED_TARIFF_1 (1-0:2.8.1)
        self.verify_telegram_item(telegram,
                                  'ELECTRICITY_DELIVERED_TARIFF_1',
                                  object_type=CosemObject,
                                  unit_val='kWh',
                                  value_type=Decimal,
                                  value_val=Decimal('0'))

        # ELECTRICITY_DELIVERED_TARIFF_2 (1-0:2.8.2)
        self.verify_telegram_item(telegram,
                                  'ELECTRICITY_DELIVERED_TARIFF_2',
                                  object_type=CosemObject,
                                  unit_val='kWh',
                                  value_type=Decimal,
                                  value_val=Decimal('0'))

        # ELECTRICITY_ACTIVE_TARIFF (0-0:96.14.0)
        self.verify_telegram_item(telegram,
                                  'ELECTRICITY_ACTIVE_TARIFF',
                                  object_type=CosemObject,
                                  unit_val=None,
                                  value_type=str,
                                  value_val='0002')

        # EQUIPMENT_IDENTIFIER (0-0:96.1.1)
        self.verify_telegram_item(
            telegram,
            'EQUIPMENT_IDENTIFIER',
            object_type=CosemObject,
            unit_val=None,
            value_type=str,
            value_val='3960221976967177082151037881335713')

        # CURRENT_ELECTRICITY_USAGE (1-0:1.7.0)
        self.verify_telegram_item(telegram,
                                  'CURRENT_ELECTRICITY_USAGE',
                                  object_type=CosemObject,
                                  unit_val='kW',
                                  value_type=Decimal,
                                  value_val=Decimal('2.027'))

        # CURRENT_ELECTRICITY_DELIVERY (1-0:2.7.0)
        self.verify_telegram_item(telegram,
                                  'CURRENT_ELECTRICITY_DELIVERY',
                                  object_type=CosemObject,
                                  unit_val='kW',
                                  value_type=Decimal,
                                  value_val=Decimal('0'))

        # SHORT_POWER_FAILURE_COUNT (1-0:96.7.21)
        self.verify_telegram_item(telegram,
                                  'SHORT_POWER_FAILURE_COUNT',
                                  object_type=CosemObject,
                                  unit_val=None,
                                  value_type=int,
                                  value_val=15)

        # LONG_POWER_FAILURE_COUNT (96.7.9)
        self.verify_telegram_item(telegram,
                                  'LONG_POWER_FAILURE_COUNT',
                                  object_type=CosemObject,
                                  unit_val=None,
                                  value_type=int,
                                  value_val=7)

        # VOLTAGE_SAG_L1_COUNT (1-0:32.32.0)
        self.verify_telegram_item(telegram,
                                  'VOLTAGE_SAG_L1_COUNT',
                                  object_type=CosemObject,
                                  unit_val=None,
                                  value_type=int,
                                  value_val=0)

        # VOLTAGE_SAG_L2_COUNT (1-0:52.32.0)
        self.verify_telegram_item(telegram,
                                  'VOLTAGE_SAG_L2_COUNT',
                                  object_type=CosemObject,
                                  unit_val=None,
                                  value_type=int,
                                  value_val=0)

        # VOLTAGE_SAG_L3_COUNT (1-0:72.32.0)
        self.verify_telegram_item(telegram,
                                  'VOLTAGE_SAG_L3_COUNT',
                                  object_type=CosemObject,
                                  unit_val=None,
                                  value_type=int,
                                  value_val=0)

        # VOLTAGE_SWELL_L1_COUNT (1-0:32.36.0)
        self.verify_telegram_item(telegram,
                                  'VOLTAGE_SWELL_L1_COUNT',
                                  object_type=CosemObject,
                                  unit_val=None,
                                  value_type=int,
                                  value_val=0)

        # VOLTAGE_SWELL_L2_COUNT (1-0:52.36.0)
        self.verify_telegram_item(telegram,
                                  'VOLTAGE_SWELL_L2_COUNT',
                                  object_type=CosemObject,
                                  unit_val=None,
                                  value_type=int,
                                  value_val=0)

        # VOLTAGE_SWELL_L3_COUNT (1-0:72.36.0)
        self.verify_telegram_item(telegram,
                                  'VOLTAGE_SWELL_L3_COUNT',
                                  object_type=CosemObject,
                                  unit_val=None,
                                  value_type=int,
                                  value_val=0)

        # TEXT_MESSAGE_CODE (0-0:96.13.1)
        self.verify_telegram_item(telegram,
                                  'TEXT_MESSAGE_CODE',
                                  object_type=CosemObject,
                                  unit_val=None,
                                  value_type=type(None),
                                  value_val=None)

        # TEXT_MESSAGE (0-0:96.13.0)
        self.verify_telegram_item(telegram,
                                  'TEXT_MESSAGE',
                                  object_type=CosemObject,
                                  unit_val=None,
                                  value_type=type(None),
                                  value_val=None)

        # INSTANTANEOUS_CURRENT_L1 (1-0:31.7.0)
        self.verify_telegram_item(telegram,
                                  'INSTANTANEOUS_CURRENT_L1',
                                  object_type=CosemObject,
                                  unit_val='A',
                                  value_type=Decimal,
                                  value_val=Decimal('0'))

        # INSTANTANEOUS_CURRENT_L2 (1-0:51.7.0)
        self.verify_telegram_item(telegram,
                                  'INSTANTANEOUS_CURRENT_L2',
                                  object_type=CosemObject,
                                  unit_val='A',
                                  value_type=Decimal,
                                  value_val=Decimal('6'))

        # INSTANTANEOUS_CURRENT_L3 (1-0:71.7.0)
        self.verify_telegram_item(telegram,
                                  'INSTANTANEOUS_CURRENT_L3',
                                  object_type=CosemObject,
                                  unit_val='A',
                                  value_type=Decimal,
                                  value_val=Decimal('2'))

        # DEVICE_TYPE (0-x:24.1.0)
        self.verify_telegram_item(telegram,
                                  'DEVICE_TYPE',
                                  object_type=CosemObject,
                                  unit_val=None,
                                  value_type=int,
                                  value_val=3)

        # INSTANTANEOUS_ACTIVE_POWER_L1_POSITIVE (1-0:21.7.0)
        self.verify_telegram_item(telegram,
                                  'INSTANTANEOUS_ACTIVE_POWER_L1_POSITIVE',
                                  object_type=CosemObject,
                                  unit_val='kW',
                                  value_type=Decimal,
                                  value_val=Decimal('0.170'))

        # INSTANTANEOUS_ACTIVE_POWER_L2_POSITIVE (1-0:41.7.0)
        self.verify_telegram_item(telegram,
                                  'INSTANTANEOUS_ACTIVE_POWER_L2_POSITIVE',
                                  object_type=CosemObject,
                                  unit_val='kW',
                                  value_type=Decimal,
                                  value_val=Decimal('1.247'))

        # INSTANTANEOUS_ACTIVE_POWER_L3_POSITIVE (1-0:61.7.0)
        self.verify_telegram_item(telegram,
                                  'INSTANTANEOUS_ACTIVE_POWER_L3_POSITIVE',
                                  object_type=CosemObject,
                                  unit_val='kW',
                                  value_type=Decimal,
                                  value_val=Decimal('0.209'))

        # INSTANTANEOUS_ACTIVE_POWER_L1_NEGATIVE (1-0:22.7.0)
        self.verify_telegram_item(telegram,
                                  'INSTANTANEOUS_ACTIVE_POWER_L1_NEGATIVE',
                                  object_type=CosemObject,
                                  unit_val='kW',
                                  value_type=Decimal,
                                  value_val=Decimal('0'))

        # INSTANTANEOUS_ACTIVE_POWER_L2_NEGATIVE (1-0:42.7.0)
        self.verify_telegram_item(telegram,
                                  'INSTANTANEOUS_ACTIVE_POWER_L2_NEGATIVE',
                                  object_type=CosemObject,
                                  unit_val='kW',
                                  value_type=Decimal,
                                  value_val=Decimal('0'))

        # INSTANTANEOUS_ACTIVE_POWER_L3_NEGATIVE (1-0:62.7.0)
        self.verify_telegram_item(telegram,
                                  'INSTANTANEOUS_ACTIVE_POWER_L3_NEGATIVE',
                                  object_type=CosemObject,
                                  unit_val='kW',
                                  value_type=Decimal,
                                  value_val=Decimal('0'))

        # EQUIPMENT_IDENTIFIER_GAS (0-x:96.1.0)
        self.verify_telegram_item(
            telegram,
            'EQUIPMENT_IDENTIFIER_GAS',
            object_type=CosemObject,
            unit_val=None,
            value_type=str,
            value_val='4819243993373755377509728609491464')

        # HOURLY_GAS_METER_READING (0-1:24.2.1)
        self.verify_telegram_item(telegram,
                                  'HOURLY_GAS_METER_READING',
                                  object_type=MBusObject,
                                  unit_val='m3',
                                  value_type=Decimal,
                                  value_val=Decimal('981.443'))

        # POWER_EVENT_FAILURE_LOG (1-0:99.97.0)
        testitem_name = 'POWER_EVENT_FAILURE_LOG'
        object_type = ProfileGenericObject
        testitem = eval("telegram.{}".format(testitem_name))
        assert isinstance(testitem, object_type)
        assert testitem.buffer_length == 3
        assert testitem.buffer_type == '0-0:96.7.19'
        buffer = testitem.buffer
        assert isinstance(testitem.buffer, list)
        assert len(buffer) == 3
        assert all([isinstance(item, MBusObject) for item in buffer])
        date0 = datetime.datetime(2000,
                                  1,
                                  4,
                                  17,
                                  3,
                                  20,
                                  tzinfo=datetime.timezone.utc)
        date1 = datetime.datetime(1999,
                                  12,
                                  31,
                                  23,
                                  0,
                                  1,
                                  tzinfo=datetime.timezone.utc)
        date2 = datetime.datetime(2000,
                                  1,
                                  1,
                                  23,
                                  0,
                                  3,
                                  tzinfo=datetime.timezone.utc)
        assert buffer[0].datetime == date0
        assert buffer[1].datetime == date1
        assert buffer[2].datetime == date2
        assert buffer[0].value == 237126
        assert buffer[1].value == 2147583646
        assert buffer[2].value == 2317482647
        assert all([isinstance(item.value, int) for item in buffer])
        assert all([isinstance(item.unit, str) for item in buffer])
        assert all([(item.unit == 's') for item in buffer])
        self.item_names_tested.append(testitem_name)

        # check if all items in telegram V4 specification are covered
        V4_name_list = [
            obis_name_mapping.EN[signature] for signature, parser in
            telegram_specifications.V4['objects'].items()
        ]
        V4_name_set = set(V4_name_list)
        item_names_tested_set = set(self.item_names_tested)

        assert item_names_tested_set == V4_name_set
コード例 #17
0
ファイル: test_protocol.py プロジェクト: vavdb/dsmr_parser
 def setUp(self):
     telegram_parser = TelegramParser(telegram_specifications.V2_2)
     self.protocol = DSMRProtocol(None,
                                  telegram_parser,
                                  telegram_callback=Mock())
コード例 #18
0
 def __init__(self, file, telegram_specification):
     self._file = file
     self.telegram_parser = TelegramParser(telegram_specification)
     self.telegram_buffer = TelegramBuffer()
     self.telegram_specification = telegram_specification
コード例 #19
0
ファイル: test_parse_v5.py プロジェクト: Smeedy/dsmr_parser
    def test_checksum_missing(self):
        # Remove the checksum value causing a ParseError.
        corrupted_telegram = TELEGRAM_V5.replace('!87B3\r\n', '')

        with self.assertRaises(ParseContentError):
            TelegramParser.validate_checksum(corrupted_telegram)
コード例 #20
0
    def test_parse(self):
        parser = TelegramParser(telegram_specifications.V4)
        result = parser.parse(TELEGRAM_V4_2)

        # P1_MESSAGE_HEADER (1-3:0.2.8)
        assert isinstance(result[obis.P1_MESSAGE_HEADER], CosemObject)
        assert result[obis.P1_MESSAGE_HEADER].unit is None
        assert isinstance(result[obis.P1_MESSAGE_HEADER].value, str)
        assert result[obis.P1_MESSAGE_HEADER].value == '42'

        # P1_MESSAGE_TIMESTAMP (0-0:1.0.0)
        assert isinstance(result[obis.P1_MESSAGE_TIMESTAMP], CosemObject)
        assert result[obis.P1_MESSAGE_TIMESTAMP].unit is None
        assert isinstance(result[obis.P1_MESSAGE_TIMESTAMP].value, datetime.datetime)
        assert result[obis.P1_MESSAGE_TIMESTAMP].value == \
            datetime.datetime(2016, 11, 13, 19, 57, 57, tzinfo=pytz.UTC)

        # ELECTRICITY_USED_TARIFF_1 (1-0:1.8.1)
        assert isinstance(result[obis.ELECTRICITY_USED_TARIFF_1], CosemObject)
        assert result[obis.ELECTRICITY_USED_TARIFF_1].unit == 'kWh'
        assert isinstance(result[obis.ELECTRICITY_USED_TARIFF_1].value, Decimal)
        assert result[obis.ELECTRICITY_USED_TARIFF_1].value == Decimal('1511.267')

        # ELECTRICITY_USED_TARIFF_2 (1-0:1.8.2)
        assert isinstance(result[obis.ELECTRICITY_USED_TARIFF_2], CosemObject)
        assert result[obis.ELECTRICITY_USED_TARIFF_2].unit == 'kWh'
        assert isinstance(result[obis.ELECTRICITY_USED_TARIFF_2].value, Decimal)
        assert result[obis.ELECTRICITY_USED_TARIFF_2].value == Decimal('1265.173')

        # ELECTRICITY_DELIVERED_TARIFF_1 (1-0:2.8.1)
        assert isinstance(result[obis.ELECTRICITY_DELIVERED_TARIFF_1], CosemObject)
        assert result[obis.ELECTRICITY_DELIVERED_TARIFF_1].unit == 'kWh'
        assert isinstance(result[obis.ELECTRICITY_DELIVERED_TARIFF_1].value, Decimal)
        assert result[obis.ELECTRICITY_DELIVERED_TARIFF_1].value == Decimal('0')

        # ELECTRICITY_DELIVERED_TARIFF_2 (1-0:2.8.2)
        assert isinstance(result[obis.ELECTRICITY_DELIVERED_TARIFF_2], CosemObject)
        assert result[obis.ELECTRICITY_DELIVERED_TARIFF_2].unit == 'kWh'
        assert isinstance(result[obis.ELECTRICITY_DELIVERED_TARIFF_2].value, Decimal)
        assert result[obis.ELECTRICITY_DELIVERED_TARIFF_2].value == Decimal('0')

        # ELECTRICITY_ACTIVE_TARIFF (0-0:96.14.0)
        assert isinstance(result[obis.ELECTRICITY_ACTIVE_TARIFF], CosemObject)
        assert result[obis.ELECTRICITY_ACTIVE_TARIFF].unit is None
        assert isinstance(result[obis.ELECTRICITY_ACTIVE_TARIFF].value, str)
        assert result[obis.ELECTRICITY_ACTIVE_TARIFF].value == '0001'

        # EQUIPMENT_IDENTIFIER (0-0:96.1.1)
        assert isinstance(result[obis.EQUIPMENT_IDENTIFIER], CosemObject)
        assert result[obis.EQUIPMENT_IDENTIFIER].unit is None
        assert isinstance(result[obis.EQUIPMENT_IDENTIFIER].value, str)
        assert result[obis.EQUIPMENT_IDENTIFIER].value == '1231231231231231231231231231231231'

        # CURRENT_ELECTRICITY_USAGE (1-0:1.7.0)
        assert isinstance(result[obis.CURRENT_ELECTRICITY_USAGE], CosemObject)
        assert result[obis.CURRENT_ELECTRICITY_USAGE].unit == 'kW'
        assert isinstance(result[obis.CURRENT_ELECTRICITY_USAGE].value, Decimal)
        assert result[obis.CURRENT_ELECTRICITY_USAGE].value == Decimal('0.235')

        # CURRENT_ELECTRICITY_DELIVERY (1-0:2.7.0)
        assert isinstance(result[obis.CURRENT_ELECTRICITY_DELIVERY], CosemObject)
        assert result[obis.CURRENT_ELECTRICITY_DELIVERY].unit == 'kW'
        assert isinstance(result[obis.CURRENT_ELECTRICITY_DELIVERY].value, Decimal)
        assert result[obis.CURRENT_ELECTRICITY_DELIVERY].value == Decimal('0')

        # LONG_POWER_FAILURE_COUNT (96.7.9)
        assert isinstance(result[obis.LONG_POWER_FAILURE_COUNT], CosemObject)
        assert result[obis.LONG_POWER_FAILURE_COUNT].unit is None
        assert isinstance(result[obis.LONG_POWER_FAILURE_COUNT].value, int)
        assert result[obis.LONG_POWER_FAILURE_COUNT].value == 7

        # VOLTAGE_SAG_L1_COUNT (1-0:32.32.0)
        assert isinstance(result[obis.VOLTAGE_SAG_L1_COUNT], CosemObject)
        assert result[obis.VOLTAGE_SAG_L1_COUNT].unit is None
        assert isinstance(result[obis.VOLTAGE_SAG_L1_COUNT].value, int)
        assert result[obis.VOLTAGE_SAG_L1_COUNT].value == 0

        # VOLTAGE_SAG_L2_COUNT (1-0:52.32.0)
        assert isinstance(result[obis.VOLTAGE_SAG_L2_COUNT], CosemObject)
        assert result[obis.VOLTAGE_SAG_L2_COUNT].unit is None
        assert isinstance(result[obis.VOLTAGE_SAG_L2_COUNT].value, int)
        assert result[obis.VOLTAGE_SAG_L2_COUNT].value == 0

        # VOLTAGE_SAG_L3_COUNT (1-0:72.32.0)
        assert isinstance(result[obis.VOLTAGE_SAG_L3_COUNT], CosemObject)
        assert result[obis.VOLTAGE_SAG_L3_COUNT].unit is None
        assert isinstance(result[obis.VOLTAGE_SAG_L3_COUNT].value, int)
        assert result[obis.VOLTAGE_SAG_L3_COUNT].value == 0

        # VOLTAGE_SWELL_L1_COUNT (1-0:32.36.0)
        assert isinstance(result[obis.VOLTAGE_SWELL_L1_COUNT], CosemObject)
        assert result[obis.VOLTAGE_SWELL_L1_COUNT].unit is None
        assert isinstance(result[obis.VOLTAGE_SWELL_L1_COUNT].value, int)
        assert result[obis.VOLTAGE_SWELL_L1_COUNT].value == 0

        # VOLTAGE_SWELL_L2_COUNT (1-0:52.36.0)
        assert isinstance(result[obis.VOLTAGE_SWELL_L2_COUNT], CosemObject)
        assert result[obis.VOLTAGE_SWELL_L2_COUNT].unit is None
        assert isinstance(result[obis.VOLTAGE_SWELL_L2_COUNT].value, int)
        assert result[obis.VOLTAGE_SWELL_L2_COUNT].value == 0

        # VOLTAGE_SWELL_L3_COUNT (1-0:72.36.0)
        assert isinstance(result[obis.VOLTAGE_SWELL_L3_COUNT], CosemObject)
        assert result[obis.VOLTAGE_SWELL_L3_COUNT].unit is None
        assert isinstance(result[obis.VOLTAGE_SWELL_L3_COUNT].value, int)
        assert result[obis.VOLTAGE_SWELL_L3_COUNT].value == 0

        # TEXT_MESSAGE_CODE (0-0:96.13.1)
        assert isinstance(result[obis.TEXT_MESSAGE_CODE], CosemObject)
        assert result[obis.TEXT_MESSAGE_CODE].unit is None
        assert result[obis.TEXT_MESSAGE_CODE].value is None

        # TEXT_MESSAGE (0-0:96.13.0)
        assert isinstance(result[obis.TEXT_MESSAGE], CosemObject)
        assert result[obis.TEXT_MESSAGE].unit is None
        assert result[obis.TEXT_MESSAGE].value is None

        # DEVICE_TYPE (0-x:24.1.0)
        assert isinstance(result[obis.TEXT_MESSAGE], CosemObject)
        assert result[obis.DEVICE_TYPE].unit is None
        assert isinstance(result[obis.DEVICE_TYPE].value, int)
        assert result[obis.DEVICE_TYPE].value == 3

        # INSTANTANEOUS_ACTIVE_POWER_L1_POSITIVE (1-0:21.7.0)
        assert isinstance(result[obis.INSTANTANEOUS_ACTIVE_POWER_L1_POSITIVE], CosemObject)
        assert result[obis.INSTANTANEOUS_ACTIVE_POWER_L1_POSITIVE].unit == 'kW'
        assert isinstance(result[obis.INSTANTANEOUS_ACTIVE_POWER_L1_POSITIVE].value, Decimal)
        assert result[obis.INSTANTANEOUS_ACTIVE_POWER_L1_POSITIVE].value == Decimal('0.095')

        # INSTANTANEOUS_ACTIVE_POWER_L2_POSITIVE (1-0:41.7.0)
        assert isinstance(result[obis.INSTANTANEOUS_ACTIVE_POWER_L2_POSITIVE], CosemObject)
        assert result[obis.INSTANTANEOUS_ACTIVE_POWER_L2_POSITIVE].unit == 'kW'
        assert isinstance(result[obis.INSTANTANEOUS_ACTIVE_POWER_L2_POSITIVE].value, Decimal)
        assert result[obis.INSTANTANEOUS_ACTIVE_POWER_L2_POSITIVE].value == Decimal('0.025')

        # INSTANTANEOUS_ACTIVE_POWER_L3_POSITIVE (1-0:61.7.0)
        assert isinstance(result[obis.INSTANTANEOUS_ACTIVE_POWER_L3_POSITIVE], CosemObject)
        assert result[obis.INSTANTANEOUS_ACTIVE_POWER_L3_POSITIVE].unit == 'kW'
        assert isinstance(result[obis.INSTANTANEOUS_ACTIVE_POWER_L3_POSITIVE].value, Decimal)
        assert result[obis.INSTANTANEOUS_ACTIVE_POWER_L3_POSITIVE].value == Decimal('0.115')

        # INSTANTANEOUS_ACTIVE_POWER_L1_NEGATIVE (1-0:22.7.0)
        assert isinstance(result[obis.INSTANTANEOUS_ACTIVE_POWER_L1_NEGATIVE], CosemObject)
        assert result[obis.INSTANTANEOUS_ACTIVE_POWER_L1_NEGATIVE].unit == 'kW'
        assert isinstance(result[obis.INSTANTANEOUS_ACTIVE_POWER_L1_NEGATIVE].value, Decimal)
        assert result[obis.INSTANTANEOUS_ACTIVE_POWER_L1_NEGATIVE].value == Decimal('0')

        # INSTANTANEOUS_ACTIVE_POWER_L2_NEGATIVE (1-0:42.7.0)
        assert isinstance(result[obis.INSTANTANEOUS_ACTIVE_POWER_L2_NEGATIVE], CosemObject)
        assert result[obis.INSTANTANEOUS_ACTIVE_POWER_L2_NEGATIVE].unit == 'kW'
        assert isinstance(result[obis.INSTANTANEOUS_ACTIVE_POWER_L2_NEGATIVE].value, Decimal)
        assert result[obis.INSTANTANEOUS_ACTIVE_POWER_L2_NEGATIVE].value == Decimal('0')

        # INSTANTANEOUS_ACTIVE_POWER_L3_NEGATIVE (1-0:62.7.0)
        assert isinstance(result[obis.INSTANTANEOUS_ACTIVE_POWER_L3_NEGATIVE], CosemObject)
        assert result[obis.INSTANTANEOUS_ACTIVE_POWER_L3_NEGATIVE].unit == 'kW'
        assert isinstance(result[obis.INSTANTANEOUS_ACTIVE_POWER_L3_NEGATIVE].value, Decimal)
        assert result[obis.INSTANTANEOUS_ACTIVE_POWER_L3_NEGATIVE].value == Decimal('0')

        # EQUIPMENT_IDENTIFIER_GAS (0-x:96.1.0)
        assert isinstance(result[obis.EQUIPMENT_IDENTIFIER_GAS], CosemObject)
        assert result[obis.EQUIPMENT_IDENTIFIER_GAS].unit is None
        assert isinstance(result[obis.EQUIPMENT_IDENTIFIER_GAS].value, str)
        assert result[obis.EQUIPMENT_IDENTIFIER_GAS].value == '3404856892390357246729543587524029'

        # HOURLY_GAS_METER_READING (0-1:24.2.1)
        assert isinstance(result[obis.HOURLY_GAS_METER_READING], MBusObject)
        assert result[obis.HOURLY_GAS_METER_READING].unit == 'm3'
        assert isinstance(result[obis.HOURLY_GAS_METER_READING].value, Decimal)
        assert result[obis.HOURLY_GAS_METER_READING].value == Decimal('915.219')
コード例 #21
0
    def test_parse(self):
        parser = TelegramParser(telegram_specifications.V4)
        result = parser.parse(TELEGRAM_V4_2)

        # P1_MESSAGE_HEADER (1-3:0.2.8)
        assert isinstance(result[obis.P1_MESSAGE_HEADER], CosemObject)
        assert result[obis.P1_MESSAGE_HEADER].unit is None
        assert isinstance(result[obis.P1_MESSAGE_HEADER].value, str)
        assert result[obis.P1_MESSAGE_HEADER].value == '42'

        # P1_MESSAGE_TIMESTAMP (0-0:1.0.0)
        assert isinstance(result[obis.P1_MESSAGE_TIMESTAMP], CosemObject)
        assert result[obis.P1_MESSAGE_TIMESTAMP].unit is None
        assert isinstance(result[obis.P1_MESSAGE_TIMESTAMP].value,
                          datetime.datetime)
        assert result[obis.P1_MESSAGE_TIMESTAMP].value == \
            datetime.datetime(2016, 11, 13, 19, 57, 57, tzinfo=pytz.UTC)

        # ELECTRICITY_USED_TARIFF_1 (1-0:1.8.1)
        assert isinstance(result[obis.ELECTRICITY_USED_TARIFF_1], CosemObject)
        assert result[obis.ELECTRICITY_USED_TARIFF_1].unit == 'kWh'
        assert isinstance(result[obis.ELECTRICITY_USED_TARIFF_1].value,
                          Decimal)
        assert result[obis.ELECTRICITY_USED_TARIFF_1].value == Decimal(
            '1581.123')

        # ELECTRICITY_USED_TARIFF_2 (1-0:1.8.2)
        assert isinstance(result[obis.ELECTRICITY_USED_TARIFF_2], CosemObject)
        assert result[obis.ELECTRICITY_USED_TARIFF_2].unit == 'kWh'
        assert isinstance(result[obis.ELECTRICITY_USED_TARIFF_2].value,
                          Decimal)
        assert result[obis.ELECTRICITY_USED_TARIFF_2].value == Decimal(
            '1435.706')

        # ELECTRICITY_DELIVERED_TARIFF_1 (1-0:2.8.1)
        assert isinstance(result[obis.ELECTRICITY_DELIVERED_TARIFF_1],
                          CosemObject)
        assert result[obis.ELECTRICITY_DELIVERED_TARIFF_1].unit == 'kWh'
        assert isinstance(result[obis.ELECTRICITY_DELIVERED_TARIFF_1].value,
                          Decimal)
        assert result[obis.ELECTRICITY_DELIVERED_TARIFF_1].value == Decimal(
            '0')

        # ELECTRICITY_DELIVERED_TARIFF_2 (1-0:2.8.2)
        assert isinstance(result[obis.ELECTRICITY_DELIVERED_TARIFF_2],
                          CosemObject)
        assert result[obis.ELECTRICITY_DELIVERED_TARIFF_2].unit == 'kWh'
        assert isinstance(result[obis.ELECTRICITY_DELIVERED_TARIFF_2].value,
                          Decimal)
        assert result[obis.ELECTRICITY_DELIVERED_TARIFF_2].value == Decimal(
            '0')

        # ELECTRICITY_ACTIVE_TARIFF (0-0:96.14.0)
        assert isinstance(result[obis.ELECTRICITY_ACTIVE_TARIFF], CosemObject)
        assert result[obis.ELECTRICITY_ACTIVE_TARIFF].unit is None
        assert isinstance(result[obis.ELECTRICITY_ACTIVE_TARIFF].value, str)
        assert result[obis.ELECTRICITY_ACTIVE_TARIFF].value == '0002'

        # EQUIPMENT_IDENTIFIER (0-0:96.1.1)
        assert isinstance(result[obis.EQUIPMENT_IDENTIFIER], CosemObject)
        assert result[obis.EQUIPMENT_IDENTIFIER].unit is None
        assert isinstance(result[obis.EQUIPMENT_IDENTIFIER].value, str)
        assert result[
            obis.
            EQUIPMENT_IDENTIFIER].value == '3960221976967177082151037881335713'

        # CURRENT_ELECTRICITY_USAGE (1-0:1.7.0)
        assert isinstance(result[obis.CURRENT_ELECTRICITY_USAGE], CosemObject)
        assert result[obis.CURRENT_ELECTRICITY_USAGE].unit == 'kW'
        assert isinstance(result[obis.CURRENT_ELECTRICITY_USAGE].value,
                          Decimal)
        assert result[obis.CURRENT_ELECTRICITY_USAGE].value == Decimal('2.027')

        # CURRENT_ELECTRICITY_DELIVERY (1-0:2.7.0)
        assert isinstance(result[obis.CURRENT_ELECTRICITY_DELIVERY],
                          CosemObject)
        assert result[obis.CURRENT_ELECTRICITY_DELIVERY].unit == 'kW'
        assert isinstance(result[obis.CURRENT_ELECTRICITY_DELIVERY].value,
                          Decimal)
        assert result[obis.CURRENT_ELECTRICITY_DELIVERY].value == Decimal('0')

        # LONG_POWER_FAILURE_COUNT (96.7.9)
        assert isinstance(result[obis.LONG_POWER_FAILURE_COUNT], CosemObject)
        assert result[obis.LONG_POWER_FAILURE_COUNT].unit is None
        assert isinstance(result[obis.LONG_POWER_FAILURE_COUNT].value, int)
        assert result[obis.LONG_POWER_FAILURE_COUNT].value == 7

        # VOLTAGE_SAG_L1_COUNT (1-0:32.32.0)
        assert isinstance(result[obis.VOLTAGE_SAG_L1_COUNT], CosemObject)
        assert result[obis.VOLTAGE_SAG_L1_COUNT].unit is None
        assert isinstance(result[obis.VOLTAGE_SAG_L1_COUNT].value, int)
        assert result[obis.VOLTAGE_SAG_L1_COUNT].value == 0

        # VOLTAGE_SAG_L2_COUNT (1-0:52.32.0)
        assert isinstance(result[obis.VOLTAGE_SAG_L2_COUNT], CosemObject)
        assert result[obis.VOLTAGE_SAG_L2_COUNT].unit is None
        assert isinstance(result[obis.VOLTAGE_SAG_L2_COUNT].value, int)
        assert result[obis.VOLTAGE_SAG_L2_COUNT].value == 0

        # VOLTAGE_SAG_L3_COUNT (1-0:72.32.0)
        assert isinstance(result[obis.VOLTAGE_SAG_L3_COUNT], CosemObject)
        assert result[obis.VOLTAGE_SAG_L3_COUNT].unit is None
        assert isinstance(result[obis.VOLTAGE_SAG_L3_COUNT].value, int)
        assert result[obis.VOLTAGE_SAG_L3_COUNT].value == 0

        # VOLTAGE_SWELL_L1_COUNT (1-0:32.36.0)
        assert isinstance(result[obis.VOLTAGE_SWELL_L1_COUNT], CosemObject)
        assert result[obis.VOLTAGE_SWELL_L1_COUNT].unit is None
        assert isinstance(result[obis.VOLTAGE_SWELL_L1_COUNT].value, int)
        assert result[obis.VOLTAGE_SWELL_L1_COUNT].value == 0

        # VOLTAGE_SWELL_L2_COUNT (1-0:52.36.0)
        assert isinstance(result[obis.VOLTAGE_SWELL_L2_COUNT], CosemObject)
        assert result[obis.VOLTAGE_SWELL_L2_COUNT].unit is None
        assert isinstance(result[obis.VOLTAGE_SWELL_L2_COUNT].value, int)
        assert result[obis.VOLTAGE_SWELL_L2_COUNT].value == 0

        # VOLTAGE_SWELL_L3_COUNT (1-0:72.36.0)
        assert isinstance(result[obis.VOLTAGE_SWELL_L3_COUNT], CosemObject)
        assert result[obis.VOLTAGE_SWELL_L3_COUNT].unit is None
        assert isinstance(result[obis.VOLTAGE_SWELL_L3_COUNT].value, int)
        assert result[obis.VOLTAGE_SWELL_L3_COUNT].value == 0

        # TEXT_MESSAGE_CODE (0-0:96.13.1)
        assert isinstance(result[obis.TEXT_MESSAGE_CODE], CosemObject)
        assert result[obis.TEXT_MESSAGE_CODE].unit is None
        assert result[obis.TEXT_MESSAGE_CODE].value is None

        # TEXT_MESSAGE (0-0:96.13.0)
        assert isinstance(result[obis.TEXT_MESSAGE], CosemObject)
        assert result[obis.TEXT_MESSAGE].unit is None
        assert result[obis.TEXT_MESSAGE].value is None

        # DEVICE_TYPE (0-x:24.1.0)
        assert isinstance(result[obis.TEXT_MESSAGE], CosemObject)
        assert result[obis.DEVICE_TYPE].unit is None
        assert isinstance(result[obis.DEVICE_TYPE].value, int)
        assert result[obis.DEVICE_TYPE].value == 3

        # INSTANTANEOUS_ACTIVE_POWER_L1_POSITIVE (1-0:21.7.0)
        assert isinstance(result[obis.INSTANTANEOUS_ACTIVE_POWER_L1_POSITIVE],
                          CosemObject)
        assert result[obis.INSTANTANEOUS_ACTIVE_POWER_L1_POSITIVE].unit == 'kW'
        assert isinstance(
            result[obis.INSTANTANEOUS_ACTIVE_POWER_L1_POSITIVE].value, Decimal)
        assert result[
            obis.INSTANTANEOUS_ACTIVE_POWER_L1_POSITIVE].value == Decimal(
                '0.170')

        # INSTANTANEOUS_ACTIVE_POWER_L2_POSITIVE (1-0:41.7.0)
        assert isinstance(result[obis.INSTANTANEOUS_ACTIVE_POWER_L2_POSITIVE],
                          CosemObject)
        assert result[obis.INSTANTANEOUS_ACTIVE_POWER_L2_POSITIVE].unit == 'kW'
        assert isinstance(
            result[obis.INSTANTANEOUS_ACTIVE_POWER_L2_POSITIVE].value, Decimal)
        assert result[
            obis.INSTANTANEOUS_ACTIVE_POWER_L2_POSITIVE].value == Decimal(
                '1.247')

        # INSTANTANEOUS_ACTIVE_POWER_L3_POSITIVE (1-0:61.7.0)
        assert isinstance(result[obis.INSTANTANEOUS_ACTIVE_POWER_L3_POSITIVE],
                          CosemObject)
        assert result[obis.INSTANTANEOUS_ACTIVE_POWER_L3_POSITIVE].unit == 'kW'
        assert isinstance(
            result[obis.INSTANTANEOUS_ACTIVE_POWER_L3_POSITIVE].value, Decimal)
        assert result[
            obis.INSTANTANEOUS_ACTIVE_POWER_L3_POSITIVE].value == Decimal(
                '0.209')

        # INSTANTANEOUS_ACTIVE_POWER_L1_NEGATIVE (1-0:22.7.0)
        assert isinstance(result[obis.INSTANTANEOUS_ACTIVE_POWER_L1_NEGATIVE],
                          CosemObject)
        assert result[obis.INSTANTANEOUS_ACTIVE_POWER_L1_NEGATIVE].unit == 'kW'
        assert isinstance(
            result[obis.INSTANTANEOUS_ACTIVE_POWER_L1_NEGATIVE].value, Decimal)
        assert result[
            obis.INSTANTANEOUS_ACTIVE_POWER_L1_NEGATIVE].value == Decimal('0')

        # INSTANTANEOUS_ACTIVE_POWER_L2_NEGATIVE (1-0:42.7.0)
        assert isinstance(result[obis.INSTANTANEOUS_ACTIVE_POWER_L2_NEGATIVE],
                          CosemObject)
        assert result[obis.INSTANTANEOUS_ACTIVE_POWER_L2_NEGATIVE].unit == 'kW'
        assert isinstance(
            result[obis.INSTANTANEOUS_ACTIVE_POWER_L2_NEGATIVE].value, Decimal)
        assert result[
            obis.INSTANTANEOUS_ACTIVE_POWER_L2_NEGATIVE].value == Decimal('0')

        # INSTANTANEOUS_ACTIVE_POWER_L3_NEGATIVE (1-0:62.7.0)
        assert isinstance(result[obis.INSTANTANEOUS_ACTIVE_POWER_L3_NEGATIVE],
                          CosemObject)
        assert result[obis.INSTANTANEOUS_ACTIVE_POWER_L3_NEGATIVE].unit == 'kW'
        assert isinstance(
            result[obis.INSTANTANEOUS_ACTIVE_POWER_L3_NEGATIVE].value, Decimal)
        assert result[
            obis.INSTANTANEOUS_ACTIVE_POWER_L3_NEGATIVE].value == Decimal('0')

        # EQUIPMENT_IDENTIFIER_GAS (0-x:96.1.0)
        assert isinstance(result[obis.EQUIPMENT_IDENTIFIER_GAS], CosemObject)
        assert result[obis.EQUIPMENT_IDENTIFIER_GAS].unit is None
        assert isinstance(result[obis.EQUIPMENT_IDENTIFIER_GAS].value, str)
        assert result[
            obis.
            EQUIPMENT_IDENTIFIER_GAS].value == '4819243993373755377509728609491464'

        # HOURLY_GAS_METER_READING (0-1:24.2.1)
        assert isinstance(result[obis.HOURLY_GAS_METER_READING], MBusObject)
        assert result[obis.HOURLY_GAS_METER_READING].unit == 'm3'
        assert isinstance(result[obis.HOURLY_GAS_METER_READING].value, Decimal)
        assert result[obis.HOURLY_GAS_METER_READING].value == Decimal(
            '981.443')
コード例 #22
0
async def async_setup_entry(hass: HomeAssistantType, entry: ConfigEntry,
                            async_add_entities):
    """set up entities based on a config entry"""

    _version = entry.data[DSMRVERSION]
    _precision = entry.data[PRECISION]
    _timezone = pytz.timezone(entry.data[TIMEZONE])

    # Protocol version specific obis
    if _version in "4":
        _gas_obis = obis_ref.HOURLY_GAS_METER_READING
        _parser = TelegramParser(telegram_specifications.V4)
    elif _version in "5":
        _gas_obis = obis_ref.HOURLY_GAS_METER_READING
        _parser = TelegramParser(telegram_specifications.V5)
    elif _version in ("5B", ):
        _gas_obis = obis_ref.BELGIUM_HOURLY_GAS_METER_READING
        _parser = TelegramParser(telegram_specifications.BELGIUM_FLUVIUS)
    else:
        _gas_obis = obis_ref.GAS_METER_READING
        _parser = TelegramParser(telegram_specifications.V2_2)

    # Define mapping for electricity mappings
    elements = ENTITIES
    elements += [
        [GAS_CONSUMPTION_NAME, 'mdi:fire', _gas_obis],
    ]

    # generate smart entities
    entities = [
        ElecticityEntity(name, icon, obis, _precision, _timezone, _parser)
        for name, icon, obis in elements
    ]

    elements = [
        [GAS_HOURLY_CONSUMPTION_NAME, 'mdi:fire', _gas_obis],
        [GAS_HOURLY_LAST_UPDATE_NAME, 'mdi:update', _gas_obis],
    ]

    # generate gas entities
    entities += [
        GasEntity(name, icon, obis, _precision, _timezone, _parser)
        for name, icon, obis in elements
    ]

    # Set up the sensor platform
    async_add_entities(entities)

    async def async_consume_service(call):
        """handle calls to the service."""
        telegram = call.data.get('telegram')
        telegram = telegram.replace(" ", "")
        telegram = telegram.replace("\\r\\n", "\r\n")

        for entity in entities:
            entity.set_consumed(telegram)

    hass.services.async_register(
        DOMAIN,
        SERVICE,
        async_consume_service,
        schema=ENTITIES_SCHEMA,
    )
コード例 #23
0
ファイル: test_parse_v5.py プロジェクト: Smeedy/dsmr_parser
 def test_checksum_valid(self):
     # No exception is raised.
     TelegramParser.validate_checksum(TELEGRAM_V5)
コード例 #24
0
 def test_instantiate(self):
     parser = TelegramParser(telegram_specifications.V4)
     #result = parser.parse(TELEGRAM_V4_2)
     telegram = Telegram(TELEGRAM_V4_2, parser, telegram_specifications.V4)
コード例 #25
0
ファイル: socket_.py プロジェクト: lowdef/dsmr_parser
class SocketReader(object):

    BUFFER_SIZE = 256

    def __init__(self, host, port, telegram_specification):
        self.host = host
        self.port = port

        self.telegram_parser = TelegramParser(telegram_specification)
        self.telegram_buffer = TelegramBuffer()
        self.telegram_specification = telegram_specification

    def read(self):
        """
        Read complete DSMR telegram's from remote interface and parse it
        into CosemObject's and MbusObject's

        :rtype: generator
        """
        buffer = b""

        with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as socket_handle:

            socket_handle.connect((self.host, self.port))

            while True:
                buffer += socket_handle.recv(self.BUFFER_SIZE)

                lines = buffer.splitlines(keepends=True)

                if len(lines) == 0:
                    continue

                for data in lines:
                    self.telegram_buffer.append(data.decode('ascii'))

                for telegram in self.telegram_buffer.get_all():
                    try:
                        yield self.telegram_parser.parse(telegram)
                    except InvalidChecksumError as e:
                        logger.warning(str(e))
                    except ParseError as e:
                        logger.error('Failed to parse telegram: %s', e)

                buffer = b""

    def read_as_object(self):
        """
        Read complete DSMR telegram's from remote and return a Telegram object.

        :rtype: generator
        """
        buffer = b""

        with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as socket_handle:

            socket_handle.connect((self.host, self.port))

            while True:
                buffer += socket_handle.recv(self.BUFFER_SIZE)

                lines = buffer.splitlines(keepends=True)

                if len(lines) == 0:
                    continue

                for data in lines:
                    self.telegram_buffer.append(data.decode('ascii'))

                    for telegram in self.telegram_buffer.get_all():
                        try:
                            yield Telegram(telegram, self.telegram_parser, self.telegram_specification)
                        except InvalidChecksumError as e:
                            logger.warning(str(e))
                        except ParseError as e:
                            logger.error('Failed to parse telegram: %s', e)

                buffer = b""
コード例 #26
0
    def test_parse(self):
        parser = TelegramParser(telegram_specifications.V3)
        result = parser.parse(TELEGRAM_V3)

        # ELECTRICITY_USED_TARIFF_1 (1-0:1.8.1)
        assert isinstance(result[obis.ELECTRICITY_USED_TARIFF_1], CosemObject)
        assert result[obis.ELECTRICITY_USED_TARIFF_1].unit == 'kWh'
        assert isinstance(result[obis.ELECTRICITY_USED_TARIFF_1].value,
                          Decimal)
        assert result[obis.ELECTRICITY_USED_TARIFF_1].value == Decimal(
            '12345.678')

        # ELECTRICITY_USED_TARIFF_2 (1-0:1.8.2)
        assert isinstance(result[obis.ELECTRICITY_USED_TARIFF_2], CosemObject)
        assert result[obis.ELECTRICITY_USED_TARIFF_2].unit == 'kWh'
        assert isinstance(result[obis.ELECTRICITY_USED_TARIFF_2].value,
                          Decimal)
        assert result[obis.ELECTRICITY_USED_TARIFF_2].value == Decimal(
            '12345.678')

        # ELECTRICITY_DELIVERED_TARIFF_1 (1-0:2.8.1)
        assert isinstance(result[obis.ELECTRICITY_DELIVERED_TARIFF_1],
                          CosemObject)
        assert result[obis.ELECTRICITY_DELIVERED_TARIFF_1].unit == 'kWh'
        assert isinstance(result[obis.ELECTRICITY_DELIVERED_TARIFF_1].value,
                          Decimal)
        assert result[obis.ELECTRICITY_DELIVERED_TARIFF_1].value == Decimal(
            '12345.678')

        # ELECTRICITY_DELIVERED_TARIFF_2 (1-0:2.8.2)
        assert isinstance(result[obis.ELECTRICITY_DELIVERED_TARIFF_2],
                          CosemObject)
        assert result[obis.ELECTRICITY_DELIVERED_TARIFF_2].unit == 'kWh'
        assert isinstance(result[obis.ELECTRICITY_DELIVERED_TARIFF_2].value,
                          Decimal)
        assert result[obis.ELECTRICITY_DELIVERED_TARIFF_2].value == Decimal(
            '12345.678')

        # ELECTRICITY_ACTIVE_TARIFF (0-0:96.14.0)
        assert isinstance(result[obis.ELECTRICITY_ACTIVE_TARIFF], CosemObject)
        assert result[obis.ELECTRICITY_ACTIVE_TARIFF].unit is None
        assert isinstance(result[obis.ELECTRICITY_ACTIVE_TARIFF].value, str)
        assert result[obis.ELECTRICITY_ACTIVE_TARIFF].value == '0002'

        # EQUIPMENT_IDENTIFIER (0-0:96.1.1)
        assert isinstance(result[obis.EQUIPMENT_IDENTIFIER], CosemObject)
        assert result[obis.EQUIPMENT_IDENTIFIER].unit is None
        assert isinstance(result[obis.EQUIPMENT_IDENTIFIER].value, str)
        assert result[
            obis.
            EQUIPMENT_IDENTIFIER].value == '4B384547303034303436333935353037'

        # CURRENT_ELECTRICITY_USAGE (1-0:1.7.0)
        assert isinstance(result[obis.CURRENT_ELECTRICITY_USAGE], CosemObject)
        assert result[obis.CURRENT_ELECTRICITY_USAGE].unit == 'kW'
        assert isinstance(result[obis.CURRENT_ELECTRICITY_USAGE].value,
                          Decimal)
        assert result[obis.CURRENT_ELECTRICITY_USAGE].value == Decimal('1.19')

        # CURRENT_ELECTRICITY_DELIVERY (1-0:2.7.0)
        assert isinstance(result[obis.CURRENT_ELECTRICITY_DELIVERY],
                          CosemObject)
        assert result[obis.CURRENT_ELECTRICITY_DELIVERY].unit == 'kW'
        assert isinstance(result[obis.CURRENT_ELECTRICITY_DELIVERY].value,
                          Decimal)
        assert result[obis.CURRENT_ELECTRICITY_DELIVERY].value == Decimal('0')

        # TEXT_MESSAGE_CODE (0-0:96.13.1)
        assert isinstance(result[obis.TEXT_MESSAGE_CODE], CosemObject)
        assert result[obis.TEXT_MESSAGE_CODE].unit is None
        assert isinstance(result[obis.TEXT_MESSAGE_CODE].value, int)
        assert result[obis.TEXT_MESSAGE_CODE].value == 303132333435363738

        # TEXT_MESSAGE (0-0:96.13.0)
        assert isinstance(result[obis.TEXT_MESSAGE], CosemObject)
        assert result[obis.TEXT_MESSAGE].unit is None
        assert isinstance(result[obis.TEXT_MESSAGE].value, str)
        assert result[obis.TEXT_MESSAGE].value == \
            '303132333435363738393A3B3C3D3E3F303132333435363738393A3B3C3D3E3F' \
            '303132333435363738393A3B3C3D3E3F303132333435363738393A3B3C3D3E3F' \
            '303132333435363738393A3B3C3D3E3F'

        # DEVICE_TYPE (0-x:24.1.0)
        assert isinstance(result[obis.TEXT_MESSAGE], CosemObject)
        assert result[obis.DEVICE_TYPE].unit is None
        assert isinstance(result[obis.DEVICE_TYPE].value, str)
        assert result[obis.DEVICE_TYPE].value == '03'

        # EQUIPMENT_IDENTIFIER_GAS (0-x:96.1.0)
        assert isinstance(result[obis.EQUIPMENT_IDENTIFIER_GAS], CosemObject)
        assert result[obis.EQUIPMENT_IDENTIFIER_GAS].unit is None
        assert isinstance(result[obis.EQUIPMENT_IDENTIFIER_GAS].value, str)
        assert result[
            obis.
            EQUIPMENT_IDENTIFIER_GAS].value == '3232323241424344313233343536373839'

        # GAS_METER_READING (0-1:24.3.0)
        assert isinstance(result[obis.GAS_METER_READING], MBusObject)
        assert result[obis.GAS_METER_READING].unit == 'm3'
        assert isinstance(result[obis.GAS_METER_READING].value, Decimal)
        assert result[obis.GAS_METER_READING].value == Decimal('1.001')
コード例 #27
0
class Terminal(object):
    def __init__(
        self,
        config,
        logger,
        hass_api,
        terminal_name,
        dsmr_serial_callback,
        dsmr_version,
    ):
        self.config = config
        self.logger = logger
        self.hass_api = hass_api
        self.terminal_name = terminal_name
        self.dsmr_serial_callback = dsmr_serial_callback
        self.mode = self.config.get(f"dsmr.{self.terminal_name}", "mode", "device")
        if self.mode not in ["tcp", "device"]:
            hybridlogger.ha_log(
                self.logger,
                self.hass_api,
                "ERROR",
                f"DSMR terminal {self.terminal_name} mode {self.mode} is not valid. "
                "Should be tcp or device. Ignoring DSMR configuration!",
            )
            return
        self.device = self.config.get(
            f"dsmr.{self.terminal_name}", "device", "/dev/ttyUSB0"
        )
        self.host = self.config.get(f"dsmr.{self.terminal_name}", "host", "localhost")
        self.port = self.config.get(f"dsmr.{self.terminal_name}", "port", "3333")
        self.dsmr_version = dsmr_version
        # start terminal
        self.stop = False
        hybridlogger.ha_log(
            self.logger,
            self.hass_api,
            "INFO",
            f"Initializing DSMR termimal '{terminal_name}'. Mode: {self.mode}.",
        )
        if self.mode == "tcp":
            self.thr = threading.Thread(
                target=self._run_tcp_terminal, name=self.terminal_name
            )
        elif self.mode == "device":
            self.thr = threading.Thread(
                target=self._run_serial_terminal, name=self.terminal_name
            )
        self.thr.start()

    def terminate(self):
        self.stop = True
        # Wait for Thread to shutdown
        self.thr.join()

    def _get_dsmr_parser(self):
        dsmr_version = self.dsmr_version
        if dsmr_version == "2.2":
            specification = telegram_specifications.V2_2
            serial_settings = SERIAL_SETTINGS_V2_2
        elif dsmr_version == "4":
            specification = telegram_specifications.V4
            serial_settings = SERIAL_SETTINGS_V4
        elif dsmr_version == "5":
            specification = telegram_specifications.V5
            serial_settings = SERIAL_SETTINGS_V5
        elif dsmr_version == "5B":
            specification = telegram_specifications.BELGIUM_FLUVIUS
            serial_settings = SERIAL_SETTINGS_V5
        else:
            raise NotImplementedError(
                "No telegram parser found for version: %s", dsmr_version
            )
        self.telegram_parser = TelegramParser(specification)
        serial_settings["timeout"] = 10
        self.serial_settings = serial_settings

    def _dsmr_data_received(self, data):
        """Add incoming data to buffer."""
        data = data.decode("ascii")
        self.telegram_buffer.append(data)

        for telegram in self.telegram_buffer.get_all():
            self._handle_telegram(telegram)

    def _handle_telegram(self, telegram):
        """Send off parsed telegram to handling callback."""
        try:
            parsed_telegram = self.telegram_parser.parse(telegram)
        except InvalidChecksumError as e:
            self.logger.warning(str(e))
        except ParseError:
            self.logger.exception("failed to parse telegram")
        else:
            self.dsmr_serial_callback(parsed_telegram)

    def _run_tcp_terminal(self):
        self._get_dsmr_parser()
        # buffer to keep incomplete incoming data
        while not self.stop:
            hybridlogger.ha_log(
                self.logger,
                self.hass_api,
                "INFO",
                f"DSMR terminal {self.terminal_name} was started.",
            )
            try:
                self.telegram_buffer = TelegramBuffer()
                server_address = (self.host, self.port)
                self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
                self.sock.settimeout(5)
                self.sock.connect(server_address)
                while not self.stop:
                    data = self.sock.recv(1024)
                    if not data and not self.stop:
                        hybridlogger.ha_log(
                            self.logger,
                            self.hass_api,
                            "INFO",
                            f"DSMR terminal {self.terminal_name} was interrupted and will be restarted.",
                        )
                        time.sleep(5)
                        break
                    elif data:
                        self._dsmr_data_received(data)

            except Exception as e:
                if not self.stop:
                    hybridlogger.ha_log(
                        self.logger,
                        self.hass_api,
                        "WARNING",
                        f"DSMR terminal {self.terminal_name} was interrupted "
                        f"and will be restarted in a few moments: {e}",
                    )
                    traceback.print_exception(*sys.exc_info())
                    time.sleep(5)
            finally:
                self.sock.close()

    def _run_serial_terminal(self):
        self._get_dsmr_parser()
        # buffer to keep incomplete incoming data
        while not self.stop:
            hybridlogger.ha_log(
                self.logger,
                self.hass_api,
                "INFO",
                f"DSMR terminal {self.terminal_name} was started.",
            )
            try:
                self.telegram_buffer = TelegramBuffer()
                self.sock = serial.Serial(port=self.device, **self.serial_settings)
                while not self.stop:
                    data = self.sock.read_until()
                    if not data and not self.stop:
                        hybridlogger.ha_log(
                            self.logger,
                            self.hass_api,
                            "INFO",
                            f"DSMR terminal {self.terminal_name} was interrupted and will be restarted.",
                        )
                        time.sleep(5)
                        break
                    elif data:
                        self._dsmr_data_received(data)

            except Exception as e:
                if not self.stop:
                    hybridlogger.ha_log(
                        self.logger,
                        self.hass_api,
                        "WARNING",
                        f"DSMR terminal {self.terminal_name} was interrupted "
                        f"and will be restarted in a few moments: {e.args}",
                    )
                    time.sleep(5)
            finally:
                self.sock.close()
コード例 #28
0
 def test_checksum_valid(self):
     # ParseErrorV4 should be raised.
     with self.assertRaises(NoChecksumError):
         TelegramParser.validate_checksum(TELEGRAM_V3)
コード例 #29
0
from dsmr_parser import telegram_specifications
from dsmr_parser.objects import Telegram
from dsmr_parser.parsers import TelegramParser
from example_telegrams import TELEGRAM_V4_2
parser = TelegramParser(telegram_specifications.V4)
telegram = Telegram(TELEGRAM_V4_2, parser, telegram_specifications.V4)

print(telegram)
コード例 #30
0
class P1test(hass.Hass):
    def _logme(self, line):
        print(line)

    def initialize(self, *args, **kwargs):
        try:
            self.log("Using hass logger!")
        except Exception:
            self.log = self._logme
            self.log("Using test logger!")
        self.mode = 'tcp'
        self.host = 'homeassistant.fritz.box'
        self.port = 3333
        self.device = 'COM3'
        self.dsmr_version = '5'
        self.terminal_name = 'test'
        self.stop = False
        self.transport = None
        self.log("Starting thread...")
        self.log("P1 test started")
        parser = self.test_serial
        # parser = self.tcp

        dsmr_version = self.dsmr_version
        if dsmr_version == '2.2':
            specification = telegram_specifications.V2_2
            serial_settings = SERIAL_SETTINGS_V2_2
        elif dsmr_version == '4':
            specification = telegram_specifications.V4
            serial_settings = SERIAL_SETTINGS_V4
        elif dsmr_version == '5':
            specification = telegram_specifications.V5
            serial_settings = SERIAL_SETTINGS_V5
        elif dsmr_version == '5B':
            specification = telegram_specifications.BELGIUM_FLUVIUS
            serial_settings = SERIAL_SETTINGS_V5
        else:
            raise NotImplementedError(
                "No telegram parser found for version: %s", dsmr_version)
        self.telegram_parser = TelegramParser(specification)
        self.serial_settings = serial_settings
        # buffer to keep incomplete incoming data
        self.telegram_buffer = TelegramBuffer()

        self.thr = threading.Thread(target=parser, daemon=True)
        self.thr.start()
        self.log("Started!")
        # logging.basicConfig(level=logging.DEBUG)

    def dsmr_serial_callback(self, telegram):
        self.log('Telegram received')

    def terminate(self):
        self.stop = True
        self.log("Closing transport...")
        if self.transport:
            self.transport.close()
        self.thr.join(10)
        # Stopping loop the hard
        if self.thr.is_alive():
            self.log(
                "Stopping the loop unfortunally did not stop the thread, waiting for completion..."
            )
        else:
            self.log("Thread exited nicely")
        self.thr.join()
        self.log("Thread has stopped!")

    def test_serial(self):
        s = serial.Serial(port=self.device, **self.serial_settings)
        while not self.stop:
            data = s.read_until()
            print(f'{data}')
            self.data_received(data)
        s.close()

    def test_tcp(self):
        server_address = (self.host, self.port)
        sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        sock.connect(server_address)
        while not self.stop:
            data = sock.recv(1024)
            self.data_received(data)

        sock.close()

    def data_received(self, data):
        """Add incoming data to buffer."""
        data = data.decode('ascii')
        self.telegram_buffer.append(data)

        for telegram in self.telegram_buffer.get_all():
            self.handle_telegram(telegram)

    def handle_telegram(self, telegram):
        """Send off parsed telegram to handling callback."""
        try:
            parsed_telegram = self.telegram_parser.parse(telegram)
        except InvalidChecksumError as e:
            self.log.warning(str(e))
        except ParseError:
            self.log.exception("failed to parse telegram")
        else:
            self.dsmr_serial_callback(parsed_telegram)