def monitor_properties( cmd, device_id: str, app_id: str, token=None, central_dns_suffix=CENTRAL_ENDPOINT, ): monitor = PropertyMonitor( cmd=cmd, app_id=app_id, device_id=device_id, token=token, central_dns_suffix=central_dns_suffix, ) monitor.start_property_monitor()
def validate_properties( cmd, device_id: str, app_id: str, token=None, central_dns_suffix=CENTRAL_ENDPOINT, minimum_severity=Severity.warning.name, ): monitor = PropertyMonitor( cmd=cmd, app_id=app_id, device_id=device_id, token=token, central_dns_suffix=central_dns_suffix, ) monitor.start_validate_property_monitor(Severity[minimum_severity])
def test_validate_properties_severity_level(self, mock_device_svc, mock_device_template_svc): # setup mock_device_template_svc.get_device_template.return_value = Template( self._duplicate_property_template) monitor = PropertyMonitor( cmd=None, app_id=app_id, device_id=device_id, token=None, central_dns_suffix=None, ) # severity level info definition = {"definition": "test_definition"} issues = monitor._validate_payload_against_entities( definition, list(definition.keys())[0], Severity.info, ) assert ( issues[0].details == "Device is sending data that has not been defined in the device template. " "Following capabilities have NOT been defined in the device template " "'['definition']'. Following capabilities have been defined in the device template " "(grouped by interface) '{'urn:sampleApp:groupOne_bz:2': " "['addRootProperty', 'addRootPropertyReadOnly', 'addRootProperty2'], " "'urn:sampleApp:groupOne_bz:_rpgcmdpo:1': ['Model', 'Version', 'TotalStorage'], " "'urn:sampleApp:groupTwo_bz:myxqftpsr:2': ['Model', 'Manufacturer'], " "'urn:sampleApp:groupThree_bz:myxqftpsr:2': ['Manufacturer', 'Version', 'Model', 'OsName']}'. " ) # severity level error issues = monitor._validate_payload_against_entities( definition, list(definition.keys())[0], Severity.error, ) assert len(issues) == 0
def test_should_return_no_properties(self, mock_device_svc, mock_device_template_svc): # test to check that no property updates are reported when version is not upadted # setup device_twin_data = json.dumps(self._device_twin) raw_twin = ast.literal_eval( device_twin_data.replace("current_time", datetime.now().isoformat())) twin = DeviceTwin(raw_twin) twin_next = DeviceTwin(raw_twin) monitor = PropertyMonitor( cmd=None, app_id=app_id, device_id=device_id, token=None, central_dns_suffix=None, ) result = monitor._compare_properties(twin_next.reported_property, twin.reported_property) assert result is None
def test_validate_properties_declared_multiple_interfaces( self, mock_device_svc, mock_device_template_svc): # setup mock_device_template_svc.get_device_template.return_value = Template( self._duplicate_property_template) monitor = PropertyMonitor( cmd=None, app_id=app_id, device_id=device_id, token=None, central_dns_suffix=None, ) model = {"Model": "test_model"} issues = monitor._validate_payload_against_entities( model, list(model.keys())[0], Severity.warning, ) assert ( issues[0].details == "Duplicate property: 'Model' found under following " "interfaces ['urn:sampleApp:groupOne_bz:_rpgcmdpo:1', 'urn:sampleApp:groupTwo_bz:myxqftpsr:2', " "'urn:sampleApp:groupThree_bz:myxqftpsr:2'] " "in the device model. Either provide the interface name as part " "of the device payload or make the propery name unique in the device model" ) version = {"OsName": "test_osName"} issues = monitor._validate_payload_against_entities( version, list(version.keys())[0], Severity.warning, ) assert len(issues) == 0
def test_should_return_updated_properties( self, mock_device_svc, mock_device_template_svc ): # setup device_twin_data = json.dumps(self._device_twin) raw_twin = ast.literal_eval( device_twin_data.replace("current_time", datetime.now().isoformat()) ) twin = DeviceTwin(raw_twin) twin_next = DeviceTwin(raw_twin) twin_next.reported_property.version = twin.reported_property.version + 1 monitor = PropertyMonitor( cmd=None, app_id=app_id, device_id=device_id, token=None, central_dns_suffix=None, ) result = monitor._compare_properties( twin_next.reported_property, twin.reported_property ) assert len(result) == 3 assert len(result["$iotin:urn_azureiot_Client_SDKInformation"]) == 3 assert result["$iotin:urn_azureiot_Client_SDKInformation"]["language"] assert result["$iotin:urn_azureiot_Client_SDKInformation"]["version"] assert result["$iotin:urn_azureiot_Client_SDKInformation"]["vendor"] assert len(result["$iotin:deviceinfo"]) == 8 assert result["$iotin:deviceinfo"]["manufacturer"] assert result["$iotin:deviceinfo"]["model"] assert result["$iotin:deviceinfo"]["osName"] assert result["$iotin:deviceinfo"]["processorArchitecture"] assert result["$iotin:deviceinfo"]["swVersion"] assert result["$iotin:deviceinfo"]["processorManufacturer"] assert result["$iotin:deviceinfo"]["totalStorage"] assert result["$iotin:deviceinfo"]["totalMemory"] assert len(result["$iotin:settings"]) == 1 assert result["$iotin:settings"]["fanSpeed"]
def test_validate_properties_name_miss_under_component( self, mock_device_svc, mock_device_template_svc): # setup mock_device_template_svc.get_device_template.return_value = Template( self._duplicate_property_template) monitor = PropertyMonitor( cmd=None, app_id=app_id, device_id=device_id, token=None, central_dns_suffix=None, ) # invalid component property definition = { PNP_DTDLV2_COMPONENT_MARKER: "c", "data": { "definition": "test_definition" }, } issues = monitor._validate_payload_against_entities( definition, list(definition.keys())[0], Severity.warning, ) assert ( issues[0].details == "Device is sending data that has not been defined in the device template. " "Following capabilities have NOT been defined in the device template '['data']'. " "Following capabilities have been defined in the device template (grouped by components) " "'{'_rpgcmdpo': ['component1Prop', 'testComponent', 'component1PropReadonly', 'component1Prop2'], " "'RS40OccupancySensorV36fy': ['component2prop', 'testComponent', 'component2PropReadonly', " "'component2Prop2', 'component1Telemetry']}'. ")