Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Telegram __str__() and to_json() broken #122

Open
lowdef opened this issue Jan 16, 2023 · 1 comment
Open

Telegram __str__() and to_json() broken #122

lowdef opened this issue Jan 16, 2023 · 1 comment

Comments

@lowdef
Copy link
Contributor

lowdef commented Jan 16, 2023

Telegram to_str() and to_json() broken.

Both return empty results.

@lowdef lowdef changed the title Telegram to_str() and to_json() broken Telegram __str__() and to_json() broken Jan 16, 2023
@lowdef
Copy link
Contributor Author

lowdef commented Jan 17, 2023

Cause:

        self._item_names = self._get_item_names()

In __init__ does not have any effect anymore, because Telegram is filled after being created. So _item_names is always [].

To do a traversal of _telegram_data_items() for every print or to_json() seems very inefficient.

We could add to the add() method:

   setattr(self, _obis_name_mapping[obis_reference], value)

All the methods str(), to_json(), __get_item_names() can then work on the attributess of the Object itself:

  for attr, value in self:
     # do something with attr and value

__get_attr__() we do not need anymore then, as all items are true first class object attributes.

Following works again, not going to merge as changes are happening in parallel now:

class Telegram(object):
    """
    Container for parsed telegram data.

    Attributes can be accessed on a telegram object by addressing by their english name, for example:
        telegram.ELECTRICITY_USED_TARIFF_1

    All attributes in a telegram can be iterated over, for example:
        [k for k,v in telegram]
    yields:
    ['P1_MESSAGE_HEADER',  'P1_MESSAGE_TIMESTAMP', 'EQUIPMENT_IDENTIFIER', ...]
    """
    def __init__(self):
        self._telegram_data = defaultdict(list)
        self._obis_name_mapping = dsmr_parser.obis_name_mapping.EN
        self._reverse_obis_name_mapping = dsmr_parser.obis_name_mapping.REVERSE_EN
        self._item_names = []

    def add(self, obis_reference, value):
        self._telegram_data[obis_reference].append(value)
        name = self._obis_name_mapping[obis_reference]
        self._item_names.append(name)
        setattr(self, name, value)

    def get(self, obis_reference, channel):
        return next(filter(lambda x: x.channel == channel, self._telegram_data[obis_reference]))

    def __getitem__(self, obis_reference):
        return self._telegram_data[obis_reference][0]

    def __len__(self):
        return len(self._telegram_data)  #TODO: its nested now

    def _get_item_names(self):
        return self._item_names

    def __iter__(self):
        for attr in self._item_names:
            value = getattr(self, attr)
            yield attr, value

    def __str__(self):
        output = ""
        for attr, value in self:
            output += "{}: \t {}\n".format(attr, str(value))
        return output

    def to_json(self):
        return json.dumps(dict([[attr, json.loads(value.to_json())] for attr, value in self]))

Or as diff:

diff --git a/dsmr_parser/objects.py b/dsmr_parser/objects.py
index 15ed27e..b500f25 100644
--- a/dsmr_parser/objects.py
+++ b/dsmr_parser/objects.py
@@ -22,21 +22,17 @@ class Telegram(object):
         self._telegram_data = defaultdict(list)
         self._obis_name_mapping = dsmr_parser.obis_name_mapping.EN
         self._reverse_obis_name_mapping = dsmr_parser.obis_name_mapping.REVERSE_EN
-        self._item_names = self._get_item_names()
+        self._item_names = []
 
     def add(self, obis_reference, value):
         self._telegram_data[obis_reference].append(value)
+        name = self._obis_name_mapping[obis_reference]
+        self._item_names.append(name)
+        setattr(self, name, value)
 
     def get(self, obis_reference, channel):
         return next(filter(lambda x: x.channel == channel, self._telegram_data[obis_reference]))
 
-    def __getattr__(self, name):
-        """ will only get called for undefined attributes """
-        obis_reference = self._reverse_obis_name_mapping[name]
-        value = self._telegram_data[obis_reference][0]
-        setattr(self, name, value)
-        return value
-
     def __getitem__(self, obis_reference):
         return self._telegram_data[obis_reference][0]
 
@@ -44,7 +40,7 @@ class Telegram(object):
         return len(self._telegram_data)  #TODO: its nested now
 
     def _get_item_names(self):
-        return [self._obis_name_mapping[k] for k, v in self._telegram_data.items()]
+        return self._item_names
 
     def __iter__(self):
         for attr in self._item_names:

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant