def map_device_templates(cmd,
                         app_id: str,
                         token=None,
                         central_dns_suffix=CENTRAL_ENDPOINT):
    provider = CentralDeviceTemplateProvider(cmd=cmd,
                                             app_id=app_id,
                                             token=token)
    return provider.map_device_templates(central_dns_suffix=central_dns_suffix)
Ejemplo n.º 2
0
def delete_device_template(
    cmd,
    app_id: str,
    device_template_id: str,
    token=None,
    central_dns_suffix="azureiotcentral.com",
):
    provider = CentralDeviceTemplateProvider(cmd=cmd, app_id=app_id, token=token)
    return provider.delete_device_template(
        device_template_id=device_template_id, central_dns_suffix=central_dns_suffix
    )
def delete_device_template(
    cmd,
    app_id: str,
    device_template_id: str,
    token=None,
    central_dns_suffix=CENTRAL_ENDPOINT,
):
    provider = CentralDeviceTemplateProvider(cmd=cmd,
                                             app_id=app_id,
                                             token=token)
    return provider.delete_device_template(
        device_template_id=device_template_id,
        central_dns_suffix=central_dns_suffix)
def list_device_templates(cmd,
                          app_id: str,
                          token=None,
                          central_dns_suffix=CENTRAL_ENDPOINT):
    provider = CentralDeviceTemplateProvider(cmd=cmd,
                                             app_id=app_id,
                                             token=token)
    templates = provider.list_device_templates(
        central_dns_suffix=central_dns_suffix)
    return {
        template.id: template.raw_template
        for template in templates.values()
    }
Ejemplo n.º 5
0
 def _create_parser(self, device_template: Template, message: Message,
                    args: CommonParserArguments):
     device_provider = CentralDeviceProvider(cmd=None, app_id=None)
     template_provider = CentralDeviceTemplateProvider(cmd=None,
                                                       app_id=None)
     device_provider.get_device = mock.MagicMock(return_value=Device({}))
     template_provider.get_device_template = mock.MagicMock(
         return_value=device_template)
     return central_parser.CentralParser(
         message=message,
         central_device_provider=device_provider,
         central_template_provider=template_provider,
         common_parser_args=args,
     )
Ejemplo n.º 6
0
 def __init__(
     self,
     cmd: AzCliCommand,
     app_id: str,
     token: str,
     consumer_group: str,
     central_handler_args: CentralHandlerArguments,
     central_dns_suffix: str,
 ):
     central_device_provider = CentralDeviceProvider(cmd=cmd,
                                                     app_id=app_id,
                                                     token=token)
     central_template_provider = CentralDeviceTemplateProvider(
         cmd=cmd, app_id=app_id, token=token)
     self._targets = self._build_targets(
         cmd=cmd,
         app_id=app_id,
         token=token,
         consumer_group=consumer_group,
         central_dns_suffix=central_dns_suffix,
     )
     self._handler = self._build_handler(
         central_device_provider=central_device_provider,
         central_template_provider=central_template_provider,
         central_handler_args=central_handler_args,
     )
    def test_should_return_device_template(self, mock_device_svc,
                                           mock_device_template_svc):
        # setup
        provider = CentralDeviceTemplateProvider(cmd=None, app_id=app_id)
        mock_device_svc.get_device.return_value = self._device
        mock_device_template_svc.get_device_template.return_value = (
            self._device_template)

        # act
        template = provider.get_device_template("someDeviceTemplate")
        # check that caching is working
        template = provider.get_device_template("someDeviceTemplate")

        # verify
        # call counts should be at most 1 since the provider has a cache
        assert mock_device_template_svc.get_device_template.call_count == 1
        assert template == self._device_template
Ejemplo n.º 8
0
def create_device_template(
    cmd,
    app_id: str,
    device_template_id: str,
    content: str,
    token=None,
    central_dns_suffix="azureiotcentral.com",
):
    if not isinstance(content, str):
        raise CLIError("content must be a string: {}".format(content))

    payload = utility.process_json_arg(content, argument_name="content")

    provider = CentralDeviceTemplateProvider(cmd=cmd, app_id=app_id, token=token)
    return provider.create_device_template(
        device_template_id=device_template_id,
        payload=payload,
        central_dns_suffix=central_dns_suffix,
    )
Ejemplo n.º 9
0
 def __init__(
     self,
     cmd,
     app_id: str,
     device_id: str,
     token: str,
     central_dns_suffix=CENTRAL_ENDPOINT,
 ):
     self._cmd = cmd
     self._app_id = app_id
     self._device_id = device_id
     self._token = token
     self._central_dns_suffix = central_dns_suffix
     self._device_twin_provider = CentralDeviceTwinProvider(
         cmd=self._cmd,
         app_id=self._app_id,
         token=self._token,
         device_id=self._device_id,
     )
     self._central_device_provider = CentralDeviceProvider(
         cmd=self._cmd, app_id=self._app_id, token=self._token)
     self._central_template_provider = CentralDeviceTemplateProvider(
         cmd=self._cmd, app_id=self._app_id, token=self._token)
     self._template = self._get_device_template()
    def get_device_template_by_device_id(
        self,
        device_id,
        central_dns_suffix="azureiotcentral.com",
    ) -> dict:
        from azext_iot.central.providers import CentralDeviceTemplateProvider

        if not device_id:
            raise CLIError("Device id must be specified.")

        device = self.get_device(device_id, central_dns_suffix)
        if not device.instance_of:
            raise CLIError(
                "Device '{}' does not have a corresponding device template.".
                format(device_id))

        template = CentralDeviceTemplateProvider.get_device_template(
            self=self,
            device_template_id=device.instance_of,
            central_dns_suffix=central_dns_suffix,
        )
        return template
Ejemplo n.º 11
0
def map_device_templates(
    cmd, app_id: str, token=None, central_dns_suffix="azureiotcentral.com"
):
    provider = CentralDeviceTemplateProvider(cmd=cmd, app_id=app_id, token=token)
    return provider.map_device_templates(central_dns_suffix=central_dns_suffix)
Ejemplo n.º 12
0
class PropertyMonitor:
    def __init__(
        self,
        cmd,
        app_id: str,
        device_id: str,
        token: str,
        central_dns_suffix=CENTRAL_ENDPOINT,
    ):
        self._cmd = cmd
        self._app_id = app_id
        self._device_id = device_id
        self._token = token
        self._central_dns_suffix = central_dns_suffix
        self._device_twin_provider = CentralDeviceTwinProvider(
            cmd=self._cmd,
            app_id=self._app_id,
            token=self._token,
            device_id=self._device_id,
        )
        self._central_device_provider = CentralDeviceProvider(
            cmd=self._cmd, app_id=self._app_id, token=self._token)
        self._central_template_provider = CentralDeviceTemplateProvider(
            cmd=self._cmd, app_id=self._app_id, token=self._token)
        self._template = self._get_device_template()

    def _compare_properties(self, prev_prop: Property, prop: Property):
        if prev_prop.version == prop.version:
            return

        changes = {
            key: self._changed_props(
                prop.props[key],
                prop.metadata[key],
                key,
            )
            for key, val in prop.metadata.items()
            if self._is_relevant(key, val)
        }

        return changes

    def _is_relevant(self, key, val):
        if key in {"$lastUpdated", "$lastUpdatedVersion"}:
            return False

        updated_within = datetime.datetime.now() - datetime.timedelta(
            seconds=DEVICETWIN_MONITOR_TIME_SEC)

        last_updated = isodate.parse_datetime(val["$lastUpdated"])
        return last_updated.timestamp() >= updated_within.timestamp()

    def _changed_props(self, prop, metadata, property_name):

        # not an interface - whole thing is change log
        if not self._is_component(prop):
            return prop

        # iterate over properties in the component
        # if the property is not an exact match for what is present in the previous set of properties
        # track it as a change
        diff = {
            key: prop[key]
            for key, val in metadata.items() if self._is_relevant(key, val)
        }
        return diff

    def _is_component(self, prop):
        return type(prop) == dict and prop.get(
            PNP_DTDLV2_COMPONENT_MARKER) == "c"

    def _validate_payload(self, changes, minimum_severity):
        for value in changes:
            issues = self._validate_payload_against_entities(
                changes[value], value, minimum_severity)
            for issue in issues:
                issue.log()

    def _validate_payload_against_entities(self, payload: dict, name,
                                           minimum_severity):
        name_miss = []
        issues_handler = IssueHandler()

        if not self._is_component(payload):
            # update is not part of a component check under interfaces
            schema = self._template.get_schema(name=name)
            if not schema:
                name_miss.append(name)
                details = strings.invalid_field_name_mismatch_template(
                    name_miss, self._template.schema_names)

            interfaces_with_specified_property = self._template._get_interface_list_property(
                name)

            if len(interfaces_with_specified_property) > 1:
                details = strings.duplicate_property_name(
                    name, interfaces_with_specified_property)
                issues_handler.add_central_issue(
                    severity=Severity.warning,
                    details=details,
                    message=None,
                    device_id=self._device_id,
                    template_id=self._template.id,
                )
        else:
            # Property update is part of a component perform additional validations under component list.
            component_property_updates = [
                property_name for property_name in payload
                if property_name != PNP_DTDLV2_COMPONENT_MARKER
            ]
            for property_name in component_property_updates:
                schema = self._template.get_schema(name=property_name,
                                                   identifier=name,
                                                   is_component=True)
                if not schema:
                    name_miss.append(property_name)
                    details = strings.invalid_field_name_component_mismatch_template(
                        name_miss, self._template.component_schema_names)

        if name_miss:
            issues_handler.add_central_issue(
                severity=Severity.warning,
                details=details,
                message=None,
                device_id=self._device_id,
                template_id=self._template.id,
            )

        return issues_handler.get_issues_with_minimum_severity(
            minimum_severity)

    def _get_device_template(self):
        device = self._central_device_provider.get_device(self._device_id)
        template = self._central_template_provider.get_device_template(
            device_template_id=device.instance_of,
            central_dns_suffix=self._central_dns_suffix,
        )
        return template

    def start_property_monitor(self, ):
        prev_twin = None

        while True:
            raw_twin = self._device_twin_provider.get_device_twin(
                central_dns_suffix=self._central_dns_suffix)

            twin = DeviceTwin(raw_twin)
            if prev_twin:
                change_d = self._compare_properties(
                    prev_twin.desired_property,
                    twin.desired_property,
                )
                change_r = self._compare_properties(
                    prev_twin.reported_property, twin.reported_property)

                if change_d:
                    print("Changes in desired properties:")
                    print("version :", twin.desired_property.version)
                    print(change_d)

                if change_r:
                    print("Changes in reported properties:")
                    print("version :", twin.reported_property.version)
                    print(change_r)

            time.sleep(DEVICETWIN_POLLING_INTERVAL_SEC)

            prev_twin = twin

    def start_validate_property_monitor(self, minimum_severity):
        prev_twin = None

        while True:

            raw_twin = self._device_twin_provider.get_device_twin(
                central_dns_suffix=self._central_dns_suffix)

            twin = DeviceTwin(raw_twin)
            if prev_twin:
                change_r = self._compare_properties(
                    prev_twin.reported_property, twin.reported_property)
                if change_r:
                    self._validate_payload(change_r, minimum_severity)

            time.sleep(DEVICETWIN_POLLING_INTERVAL_SEC)

            prev_twin = twin