diff --git a/platypush/backend/http/webapp/src/components/panels/Entities/Modal.vue b/platypush/backend/http/webapp/src/components/panels/Entities/Modal.vue index 9db443f1e3..b2d6f183b7 100644 --- a/platypush/backend/http/webapp/src/components/panels/Entities/Modal.vue +++ b/platypush/backend/http/webapp/src/components/panels/Entities/Modal.vue @@ -76,6 +76,20 @@
+
+
External URL
+
+ +
+
+ +
+
Image
+
+ +
+
+
@@ -314,5 +328,15 @@ export default { } } } + + .value { + &.url { + text-align: right; + } + + .entity-image { + max-height: 5em; + } + } } diff --git a/platypush/entities/_base.py b/platypush/entities/_base.py index 86567aa729..7893342c1a 100644 --- a/platypush/entities/_base.py +++ b/platypush/entities/_base.py @@ -54,6 +54,9 @@ if 'entity' not in Base.metadata: is_write_only = Column(Boolean, default=False) is_query_disabled = Column(Boolean, default=False) is_configuration = Column(Boolean, default=False) + external_url = Column(String) + image_url = Column(String) + created_at = Column( DateTime(timezone=False), default=datetime.utcnow(), nullable=False ) diff --git a/platypush/plugins/zigbee/mqtt/__init__.py b/platypush/plugins/zigbee/mqtt/__init__.py index 1089b20dc5..862bf396af 100644 --- a/platypush/plugins/zigbee/mqtt/__init__.py +++ b/platypush/plugins/zigbee/mqtt/__init__.py @@ -292,6 +292,8 @@ class ZigbeeMqttPlugin(MqttPlugin): # lgtm [py/missing-call-to-init] id=dev['ieee_address'], name=dev.get('friendly_name'), description=dev_def.get('description'), + external_url=self._get_device_url(dev), + image_url=self._get_image_url(dev), reachable=reachable, ) @@ -303,6 +305,22 @@ class ZigbeeMqttPlugin(MqttPlugin): # lgtm [py/missing-call-to-init] return super().transform_entities(compatible_entities) # type: ignore + @staticmethod + def _get_device_url(device_info: dict) -> Optional[str]: + model = device_info.get('definition', {}).get('model') + if not model: + return + + return f'https://www.zigbee2mqtt.io/devices/{model}.html' + + @staticmethod + def _get_image_url(device_info: dict) -> Optional[str]: + model = device_info.get('definition', {}).get('model') + if not model: + return + + return f'https://www.zigbee2mqtt.io/images/devices/{model}.jpg' + def _get_network_info(self, **kwargs) -> dict: self.logger.info('Fetching Zigbee network information') client = None diff --git a/platypush/plugins/zwave/mqtt/__init__.py b/platypush/plugins/zwave/mqtt/__init__.py index 0330d99bba..14d8a5940c 100644 --- a/platypush/plugins/zwave/mqtt/__init__.py +++ b/platypush/plugins/zwave/mqtt/__init__.py @@ -767,6 +767,7 @@ class ZwaveMqttPlugin(MqttPlugin, ZwaveBasePlugin): parent = parent_entities[node_id] = Device( id=node['device_id'], name=node.get('name'), + external_url=self._build_external_url(node), reachable=( node.get('is_available', False) and node.get('is_ready', False) ), @@ -777,6 +778,20 @@ class ZwaveMqttPlugin(MqttPlugin, ZwaveBasePlugin): entity.parent = parent entity.reachable = parent.reachable + @staticmethod + def _build_external_url(node: dict) -> Optional[str]: + manufacturer_id = node.get('manufacturer_id') + product_id = node.get('product_id') + product_type = node.get('product_type') + firmware_version = node.get('firmware_version', '0.0') + if not (manufacturer_id and product_id and product_type): + return + + return ( + 'https://devices.zwave-js.io/?jumpTo=' + f'{manufacturer_id}:{product_type}:{product_id}:{firmware_version}' + ) + @classmethod def _merge_current_and_target_values(cls, values: Iterable[dict]) -> List[dict]: values_by_id = OrderedDict({v.get('id'): v for v in values})