VOL-1021: Convert rx binary attribute data to python object

 and a small typo fix in deferred cleanup in capabilties state machine

Change-Id: Icfee1c4347368b5776a0d2f59bc83294cb445970
diff --git a/voltha/extensions/omci/database/mib_db_dict.py b/voltha/extensions/omci/database/mib_db_dict.py
index ae2f3a5..daadc68 100644
--- a/voltha/extensions/omci/database/mib_db_dict.py
+++ b/voltha/extensions/omci/database/mib_db_dict.py
@@ -255,11 +255,27 @@
 
             changed = False
 
+            me_map = self._omci_agent.get_device(device_id).me_map
+            entity = me_map.get(class_id)
+
             for attribute, value in attributes.items():
                 assert isinstance(attribute, basestring)
                 assert value is not None, "Attribute '{}' value cannot be 'None'".\
                     format(attribute)
 
+                if entity is not None and isinstance(value, basestring):
+                    from scapy.fields import StrFixedLenField
+                    attr_index = entity.attribute_name_to_index_map[attribute]
+                    eca = entity.attributes[attr_index]
+                    field = eca.field
+
+                    if isinstance(field, StrFixedLenField):
+                        from scapy.base_classes import Packet_metaclass
+                        if isinstance(field.default, Packet_metaclass) \
+                                and hasattr(field.default, 'json_from_value'):
+                            # Value/hex of Packet Class to string
+                            value = field.default.json_from_value(value)
+
                 # Complex packet types may have an attribute encoded as an object, this
                 # can be check by seeing if there is a to_json() conversion callable
                 # defined
diff --git a/voltha/extensions/omci/database/mib_db_ext.py b/voltha/extensions/omci/database/mib_db_ext.py
index 0c8b179..3d1f78c 100644
--- a/voltha/extensions/omci/database/mib_db_ext.py
+++ b/voltha/extensions/omci/database/mib_db_ext.py
@@ -111,9 +111,15 @@
                 field = StrFixedLenField(UNKNOWN_CLASS_ATTRIBUTE_KEY, None, 24)
 
             if isinstance(field, StrFixedLenField):
-                #  For StrFixedLenField, value is an str already (or possibly JSON encoded object)
+                from scapy.base_classes import Packet_metaclass
+                #  For StrFixedLenField, value is a str already (or possibly JSON encoded)
                 if hasattr(value, 'to_json'):
+                    # Packet Class to string
                     str_value = value.to_json()
+                elif isinstance(field.default, Packet_metaclass) \
+                        and hasattr(field.default, 'json_from_value'):
+                    # Value/hex of Packet Class to string
+                    str_value = field.default.json_from_value(value)
                 else:
                     str_value = str(value)
 
@@ -225,6 +231,7 @@
         now = datetime.utcnow()
         found = False
         root_proxy = self._core.get_proxy('/')
+
         data = MibDeviceData(device_id=device_id,
                              created=self._time_to_string(now),
                              last_sync_time='',
@@ -647,8 +654,13 @@
                 new_attributes = []
 
                 for k, v in attributes.items():
-                    str_value = self._attribute_to_string(device_id, class_id, k, v)
-                    new_attributes.append(MibAttributeData(name=k, value=str_value))
+                    try:
+                        str_value = self._attribute_to_string(device_id, class_id, k, v)
+                        new_attributes.append(MibAttributeData(name=k, value=str_value))
+
+                    except Exception as e:
+                        self.log.exception('save-error', e=e, class_id=class_id,
+                                           attr=k, value_type=type(v))
 
                     if k not in exist_attr_indexes or \
                             inst_data.attributes[exist_attr_indexes[k]].value != str_value:
@@ -666,7 +678,6 @@
 
                 self.log.debug('set-complete', device_id=device_id, class_id=class_id,
                                entity_id=instance_id, attributes=attributes, modified=modified)
-
                 return modified
 
             except KeyError:
diff --git a/voltha/extensions/omci/omci_entities.py b/voltha/extensions/omci/omci_entities.py
index 665e21c..66c4bda 100644
--- a/voltha/extensions/omci/omci_entities.py
+++ b/voltha/extensions/omci/omci_entities.py
@@ -17,6 +17,7 @@
 
 import sys
 from binascii import hexlify
+from bitstring import BitArray
 import json
 from scapy.fields import ByteField, ShortField, MACField, BitField, IPField
 from scapy.fields import IntField, StrFixedLenField, LongField, FieldListField
@@ -558,6 +559,31 @@
     def to_json(self):
         return json.dumps(self.fields, separators=(',', ':'))
 
+    @staticmethod
+    def json_from_value(value):
+        bits = BitArray(hex=hexlify(value))
+        temp = VlanTaggingOperation(
+            filter_outer_priority=bits[0:4].uint,         # 4  <-size
+            filter_outer_vid=bits[4:17].uint,             # 13
+            filter_outer_tpid_de=bits[17:20].uint,        # 3
+                                                          # pad 12
+            filter_inner_priority=bits[32:36].uint,       # 4
+            filter_inner_vid=bits[36:49].uint,            # 13
+            filter_inner_tpid_de=bits[49:52].uint,        # 3
+                                                          # pad 8
+            filter_ether_type=bits[60:64].uint,           # 4
+            treatment_tags_to_remove=bits[64:66].uint,    # 2
+                                                          # pad 10
+            treatment_outer_priority=bits[76:80].uint,    # 4
+            treatment_outer_vid=bits[80:93].uint,         # 13
+            treatment_outer_tpid_de=bits[93:96].uint,     # 3
+                                                          # pad 12
+            treatment_inner_priority=bits[108:112].uint,  # 4
+            treatment_inner_vid=bits[112:125].uint,       # 13
+            treatment_inner_tpid_de=bits[125:128].uint,   # 3
+        )
+        return json.dumps(temp.fields, separators=(',', ':'))
+
 
 class ExtendedVlanTaggingOperationConfigurationData(EntityClass):
     class_id = 171
diff --git a/voltha/extensions/omci/state_machines/omci_onu_capabilities.py b/voltha/extensions/omci/state_machines/omci_onu_capabilities.py
index 291999f..45145c7 100644
--- a/voltha/extensions/omci/state_machines/omci_onu_capabilities.py
+++ b/voltha/extensions/omci/state_machines/omci_onu_capabilities.py
@@ -91,7 +91,7 @@
         d1, self._deferred = self._deferred, None
         d2, self._task_deferred = self._task_deferred, None
 
-        for d in [d1, d1]:
+        for d in [d1, d2]:
             try:
                 if d is not None and not d.called:
                     d.cancel()