Beispiel #1
0
    def test_metadata(self):
        """
        Test for metadata works but the api of iot agent-json seems not
        working correctly
        Returns:
            None
        """
        metadata = {"accuracy": {"type": "Text",
                                 "value": "+-5%"}}
        attr = DeviceAttribute(name="temperature",
                               object_id="temperature",
                               type="Number",
                               metadata=metadata)
        device = Device(**self.device)
        device.device_id = "device_with_meta"
        device.add_attribute(attribute=attr)
        logger.info(device.json(indent=2))

        with IoTAClient(
                url=settings.IOTA_JSON_URL,
                fiware_header=self.fiware_header) as client:
            client.post_device(device=device)
            logger.info(client.get_device(device_id=device.device_id).json(
                indent=2, exclude_unset=True))

        with ContextBrokerClient(
                url=settings.CB_URL,
                fiware_header=self.fiware_header) as client:
            logger.info(client.get_entity(entity_id=device.entity_name).json(
                indent=2))
Beispiel #2
0
    def setUp(self) -> None:
        self.fiware_header = FiwareHeader(
            service=settings.FIWARE_SERVICE,
            service_path=settings.FIWARE_SERVICEPATH)
        self.service_group_json = ServiceGroup(
            apikey=settings.FIWARE_SERVICEPATH.strip('/'),
            resource="/iot/json")
        self.service_group_ul = ServiceGroup(
            apikey=settings.FIWARE_SERVICEPATH.strip('/'), resource="/iot/d")

        # create a device configuration
        device_attr = DeviceAttribute(name='temperature',
                                      object_id='t',
                                      type="Number")
        device_command = DeviceCommand(name='heater', type="Boolean")

        self.device_json = Device(device_id='my_json_device',
                                  entity_name='my_json_device',
                                  entity_type='Thing',
                                  protocol='IoTA-JSON',
                                  transport='MQTT',
                                  apikey=self.service_group_json.apikey,
                                  attributes=[device_attr],
                                  commands=[device_command])

        self.device_ul = Device(device_id='my_ul_device',
                                entity_name='my_ul_device',
                                entity_type='Thing',
                                protocol='PDI-IoTA-UltraLight',
                                transport='MQTT',
                                apikey=self.service_group_ul.apikey,
                                attributes=[device_attr],
                                commands=[device_command])

        self.mqttc = IoTAMQTTClient()

        def on_connect(mqttc, obj, flags, rc):
            mqttc.logger.info("rc: " + str(rc))

        def on_connect_fail(mqttc, obj):
            mqttc.logger.info("Connect failed")

        def on_publish(mqttc, obj, mid):
            mqttc.logger.info("mid: " + str(mid))

        def on_subscribe(mqttc, obj, mid, granted_qos):
            mqttc.logger.info("Subscribed: " + str(mid) + " " +
                              str(granted_qos))

        def on_log(mqttc, obj, level, string):
            mqttc.logger.info(string)

        self.mqttc.on_connect = on_connect
        self.mqttc.on_connect_fail = on_connect_fail
        self.mqttc.on_publish = on_publish
        self.mqttc.on_subscribe = on_subscribe
        self.mqttc.on_log = on_log
Beispiel #3
0
    def test_device_endpoints(self):
        """
        Test device creation
        """
        with IoTAClient(
                url=settings.IOTA_JSON_URL,
                fiware_header=self.fiware_header) as client:
            client.get_device_list()
            device = Device(**self.device)

            attr = DeviceAttribute(name='temperature',
                                   object_id='t',
                                   type='Number',
                                   entity_name='test')
            attr_command = DeviceCommand(name='open')
            attr_lazy = LazyDeviceAttribute(name='pressure',
                                            object_id='p',
                                            type='Text',
                                            entity_name='pressure')
            attr_static = StaticDeviceAttribute(name='hasRoom',
                                                type='Relationship',
                                                value='my_partner_id')
            device.add_attribute(attr)
            device.add_attribute(attr_command)
            device.add_attribute(attr_lazy)
            device.add_attribute(attr_static)

            client.post_device(device=device)
            device_res = client.get_device(device_id=device.device_id)
            self.assertEqual(device.dict(exclude={'service',
                                                  'service_path',
                                                  'timezone'}),
                             device_res.dict(exclude={'service',
                                                      'service_path',
                                                      'timezone'}))
            self.assertEqual(self.fiware_header.service, device_res.service)
            self.assertEqual(self.fiware_header.service_path,
                             device_res.service_path)
Beispiel #4
0
    # These attributes represent static information (as names) and are
    # mirrored 1:1
    device2.add_attribute(
        StaticDeviceAttribute(name="address",
                              type=DataType.TEXT,
                              value="Lichtenhof 3"))
    # ### 2.2.2 DeviceAttribute
    #
    # These attributes represent a live information of the device.
    # The value can be read by accessing the mirrored attribute in the
    # context entity.
    # It is differentiated between two kinds:
    #
    # DeviceAttributes, always keep the value in the context entity up-to-date
    # (polling)
    device2.add_attribute(DeviceAttribute(name="temperature", object_id="t"))
    # LazyDeviceAttributes, only update the value in the entity if it is
    # accessed (event based)
    device2.add_attribute(LazyDeviceAttribute(name="temperature"))

    # ### 2.2.3 Commands
    #
    # Commands can be executed to let the device execute some action
    device2.add_attribute(DeviceCommand(name="on"))
    # In the context entity three attributes are added for a command:
    #   -   Command (name): used to execute
    #   -   Status (name_status): used to inform about execution status
    #   -   Info/Result (name_info): used to inform about the final result

    # # 3 Interact with Fiware
    #
    #
    # ## 2.1 Device creation
    #
    # First we create our device configuration using the models provided for
    # filip.models.ngsi_v2.iot

    # creating an attribute for incoming measurements from e.g. a sensor we do
    # add the metadata for units here using the unit models. You will later
    # notice that the library automatically will augment the provided
    # information about units.
    device_attr1 = DeviceAttribute(name='temperature',
                                   object_id='t',
                                   type="Number",
                                   metadata={
                                       "unit": {
                                           "type": "Unit",
                                           "value": {
                                               "name": "degree Celsius"
                                           }
                                       }
                                   })

    # creating a static attribute that holds additional information
    static_device_attr = StaticDeviceAttribute(name='info',
                                               type="Text",
                                               value="Filip example for "
                                               "virtual IoT device")
    # creating a command that the IoT device will liston to
    device_command = DeviceCommand(name='heater')

    # NOTE: You need to know that if you define an apikey for a single device it
Beispiel #6
0
    def test_patch_device(self):
        """
            Test the methode: patch_device of the iota client
        """

        device = Device(**self.device)
        device.endpoint = "http://test.com"
        device.transport = "MQTT"

        device.add_attribute(DeviceAttribute(
            name="Att1", object_id="o1", type=DataType.STRUCTUREDVALUE))
        device.add_attribute(StaticDeviceAttribute(
            name="Stat1", value="test", type=DataType.STRUCTUREDVALUE))
        device.add_attribute(StaticDeviceAttribute(
            name="Stat2", value="test", type=DataType.STRUCTUREDVALUE))
        device.add_command(DeviceCommand(name="Com1"))

        # use patch_device to post
        self.client.patch_device(device=device)

        cb_client = ContextBrokerClient(url=settings.CB_URL,
                                        fiware_header=self.fiware_header)

        # test if attributes exists correctly
        live_entity = cb_client.get_entity(entity_id=device.entity_name)
        live_entity.get_attribute("Att1")
        live_entity.get_attribute("Com1")
        live_entity.get_attribute("Com1_info")
        live_entity.get_attribute("Com1_status")
        self.assertEqual(live_entity.get_attribute("Stat1").value, "test")

        # change device attributes and update
        device.get_attribute("Stat1").value = "new_test"
        device.delete_attribute(device.get_attribute("Stat2"))
        device.delete_attribute(device.get_attribute("Att1"))
        device.delete_attribute(device.get_attribute("Com1"))
        device.add_attribute(DeviceAttribute(
            name="Att2", object_id="o1", type=DataType.STRUCTUREDVALUE))
        device.add_attribute(StaticDeviceAttribute(
            name="Stat3", value="test3", type=DataType.STRUCTUREDVALUE))
        device.add_command(DeviceCommand(name="Com2"))

        self.client.patch_device(device=device, cb_url=settings.CB_URL)

        # test if update does what it should, for the device. It does not
        # change the entity completely:
        live_entity = cb_client.get_entity(entity_id=device.entity_name)
        with self.assertRaises(KeyError):
            live_entity.get_attribute("Att1")
        with self.assertRaises(KeyError):
            live_entity.get_attribute("Com1_info")
        with self.assertRaises(KeyError):
            live_entity.get_attribute("Stat2")
        self.assertEqual(live_entity.get_attribute("Stat1").value, "new_test")
        live_entity.get_attribute("Stat3")
        live_entity.get_attribute("Com2_info")
        live_entity.get_attribute("Att2")

        # test update where device information were changed
        device_settings = {"endpoint": "http://localhost:7071",
                           "device_id": "new_id",
                           "entity_name": "new_name",
                           "entity_type": "new_type",
                           "timestamp": False,
                           "apikey": "zuiop",
                           "protocol": "HTTP",
                           "transport": "HTTP"}

        for key, value in device_settings.items():
            device.__setattr__(key, value)
            self.client.patch_device(device=device)
            live_device = self.client.get_device(device_id=device.device_id)
            self.assertEqual(live_device.__getattribute__(key), value)
            cb_client.close()
Beispiel #7
0
    def test_update_device(self):
        """
        Test the methode: update_device of the iota client
        """

        device = Device(**self.device)
        device.endpoint = "http://test.com"
        device.transport = "MQTT"

        device.add_attribute(DeviceAttribute(
            name="Att1", object_id="o1", type=DataType.STRUCTUREDVALUE))
        device.add_attribute(StaticDeviceAttribute(
            name="Stat1", value="test", type=DataType.STRUCTUREDVALUE))
        device.add_attribute(StaticDeviceAttribute(
            name="Stat2", value="test", type=DataType.STRUCTUREDVALUE))
        device.add_command(DeviceCommand(name="Com1"))

        # use update_device to post
        self.client.update_device(device=device, add=True)

        cb_client = ContextBrokerClient(url=settings.CB_URL,
                                        fiware_header=self.fiware_header)

        # test if attributes exists correctly
        live_entity = cb_client.get_entity(entity_id=device.entity_name)
        live_entity.get_attribute("Att1")
        live_entity.get_attribute("Com1")
        live_entity.get_attribute("Com1_info")
        live_entity.get_attribute("Com1_status")
        self.assertEqual(live_entity.get_attribute("Stat1").value, "test")

        # change device attributes and update
        device.get_attribute("Stat1").value = "new_test"
        device.delete_attribute(device.get_attribute("Stat2"))
        device.delete_attribute(device.get_attribute("Att1"))
        device.delete_attribute(device.get_attribute("Com1"))
        device.add_attribute(DeviceAttribute(
            name="Att2", object_id="o1", type=DataType.STRUCTUREDVALUE))
        device.add_attribute(StaticDeviceAttribute(
            name="Stat3", value="test3", type=DataType.STRUCTUREDVALUE))
        device.add_command(DeviceCommand(name="Com2"))

        # device.endpoint = "http://localhost:8080"
        self.client.update_device(device=device)

        # test if update does what it should, for the device. It does not
        # change the entity completely:

        live_device = self.client.get_device(device_id=device.device_id)

        with self.assertRaises(KeyError):
            live_device.get_attribute("Att1")
        with self.assertRaises(KeyError):
            live_device.get_attribute("Com1_info")
        with self.assertRaises(KeyError):
            live_device.get_attribute("Stat2")
        self.assertEqual(live_device.get_attribute("Stat1").value, "new_test")
        live_device.get_attribute("Stat3")
        live_device.get_command("Com2")
        live_device.get_attribute("Att2")

        cb_client.close()
    #
    # ## 1.1 FiwareHeader
    #
    # Since we want to use the multi-tenancy concept of fiware we always start
    # with create a fiware header
    fiware_header = FiwareHeader(service=SERVICE, service_path=SERVICE_PATH)

    # ## 1.2 Device configuration
    #
    service_group_json = ServiceGroup(apikey=SERVICE_PATH.strip('/'),
                                      resource="/iot/json")
    service_group_ul = ServiceGroup(apikey=SERVICE_PATH.strip('/'),
                                    resource="/iot/d")

    device_attr = DeviceAttribute(name='temperature',
                                  object_id='t',
                                  type="Number")
    device_command = DeviceCommand(name='heater', type="Boolean")

    device_json = Device(device_id='my_json_device',
                         entity_name='my_json_device',
                         entity_type='Thing',
                         protocol='IoTA-JSON',
                         transport='MQTT',
                         apikey=service_group_json.apikey,
                         attributes=[device_attr],
                         commands=[device_command])

    device_ul = Device(device_id='my_ul_device',
                       entity_name='my_ul_device',
                       entity_type='Thing',
    iotac = IoTAClient(url=IOTA_URL, fiware_header=fiware_header)
    iotac.post_groups(service_groups=groups)
    iotac.post_devices(devices=devices)

    # ToDo: Get the device configurations from the server
    weather_station = iotac.get_device(device_id="device:001")
    zone_temperature_sensor = iotac.get_device(device_id="device:002")

    # ToDo: Get the service group configurations from the server
    group = iotac.get_group(resource="/iot/json", apikey=APIKEY)

    # ToDo: Create and additional device holding a command attribute and
    #  post it to the IoT-Agent. It should be mapped to the `type` heater
    # create the simtime attribute and add during device creation
    t_sim = DeviceAttribute(name='simtime',
                            object_id='t_sim',
                            type="Number")

    # ToDo: create the command attribute of name `heater_on` (currently it is
    #  not possible to add metadata here)
    cmd = DeviceCommand(name="heater_on",
                        type=DataType.BOOLEAN)

    # ToDo: create the device configuration and send it to the server
    heater = Device(device_id="device:003",
                    entity_name="urn:ngsi-ld:Heater:001",
                    entity_type="Heater",
                    apikey=APIKEY,
                    attributes=[t_sim],
                    commands=[cmd],
                    transport='MQTT',
                                temp_start=TEMPERATURE_ZONE_START)

    # define lists to store historical data
    history_weather_station = []
    history_zone_temperature_sensor = []

    # Create a service group and add it to your
    service_group = ServiceGroup(apikey=APIKEY, resource="/iot/json")

    # ToDo: create two IoTA-MQTT devices for the weather station and the zone
    #  temperature sensor. Also add the simulation time as `active attribute`
    #  to each device!
    #
    # create the weather station device
    # create the simtime attribute and add during device creation
    t_sim = DeviceAttribute(name='simtime', object_id='t_sim', type="Number")

    weather_station = Device(device_id='device:001',
                             entity_name='urn:ngsi-ld:WeatherStation:001',
                             entity_type='WeatherStation',
                             protocol='IoTA-JSON',
                             transport='MQTT',
                             apikey=APIKEY,
                             attributes=[t_sim],
                             commands=[])

    # create a temperature attribute and add it via the api of the
    # `device`-model. Use the 't_amb' as `object_id`. `object_id` specifies
    # what key will be used in the MQTT Message payload
    t_amb = DeviceAttribute(name='temperature',
                            object_id='t_amb',
Beispiel #11
0
    def test_command_with_mqtt(self):
        """
        Test if a command can be send to a device in FIWARE

        To test this a virtual device is created and provisioned to FIWARE and
        a hosted MQTT Broker

        This test only works if the address of a running MQTT Broker is given in
        the environment ('MQTT_BROKER_URL')

        The main part of this test was taken out of the iot_mqtt_example, see
        there for a complete documentation
        """
        mqtt_broker_url = settings.MQTT_BROKER_URL

        device_attr1 = DeviceAttribute(name='temperature',
                                       object_id='t',
                                       type="Number",
                                       metadata={
                                           "unit":
                                               {"type": "Unit",
                                                "value": {
                                                    "name": {
                                                        "type": "Text",
                                                        "value": "degree "
                                                                 "Celsius"
                                                    }
                                                }}
                                       })

        # creating a static attribute that holds additional information
        static_device_attr = StaticDeviceAttribute(name='info',
                                                   type="Text",
                                                   value="Filip example for "
                                                         "virtual IoT device")
        # creating a command that the IoT device will liston to
        device_command = DeviceCommand(name='heater', type="Boolean")

        device = Device(device_id='MyDevice',
                        entity_name='MyDevice',
                        entity_type='Thing2',
                        protocol='IoTA-JSON',
                        transport='MQTT',
                        apikey=settings.FIWARE_SERVICEPATH.strip('/'),
                        attributes=[device_attr1],
                        static_attributes=[static_device_attr],
                        commands=[device_command])

        device_attr2 = DeviceAttribute(name='humidity',
                                       object_id='h',
                                       type="Number",
                                       metadata={
                                           "unitText":
                                               {"value": "percent",
                                                "type": "Text"}})

        device.add_attribute(attribute=device_attr2)

        # Send device configuration to FIWARE via the IoT-Agent. We use the
        # general ngsiv2 httpClient for this.
        service_group = ServiceGroup(
            service=self.fiware_header.service,
            subservice=self.fiware_header.service_path,
            apikey=settings.FIWARE_SERVICEPATH.strip('/'),
            resource='/iot/json')

        # create the Http client node that once sent the device cannot be posted
        # again and you need to use the update command
        config = HttpClientConfig(cb_url=settings.CB_URL,
                                  iota_url=settings.IOTA_JSON_URL)
        client = HttpClient(fiware_header=self.fiware_header, config=config)
        client.iota.post_group(service_group=service_group, update=True)
        client.iota.post_device(device=device, update=True)

        time.sleep(0.5)

        # check if the device is correctly configured. You will notice that
        # unfortunately the iot API does not return all the metadata. However,
        # it will still appear in the context-entity
        device = client.iota.get_device(device_id=device.device_id)

        # check if the data entity is created in the context broker
        entity = client.cb.get_entity(entity_id=device.device_id,
                                      entity_type=device.entity_type)

        # create a mqtt client that we use as representation of an IoT device
        # following the official documentation of Paho-MQTT.
        # https://www.eclipse.org/paho/index.php?page=clients/python/
        # docs/index.php

        # The callback for when the mqtt client receives a CONNACK response from
        # the server. All callbacks need to have this specific arguments,
        # Otherwise the client will not be able to execute them.
        def on_connect(client, userdata, flags, reasonCode, properties=None):
            client.subscribe(f"/{device.apikey}/{device.device_id}/cmd")

        # Callback when the command topic is succesfully subscribed
        def on_subscribe(client, userdata, mid, granted_qos, properties=None):
            pass

        # NOTE: We need to use the apikey of the service-group to send the
        # message to the platform
        def on_message(client, userdata, msg):
            data = json.loads(msg.payload)
            res = {k: v for k, v in data.items()}
            client.publish(topic=f"/json/{service_group.apikey}"
                                 f"/{device.device_id}/cmdexe",
                           payload=json.dumps(res))

        def on_disconnect(client, userdata, reasonCode, properties=None):
            pass

        mqtt_client = mqtt.Client(client_id="filip-test",
                                  userdata=None,
                                  protocol=mqtt.MQTTv5,
                                  transport="tcp")

        # add our callbacks to the client
        mqtt_client.on_connect = on_connect
        mqtt_client.on_subscribe = on_subscribe
        mqtt_client.on_message = on_message
        mqtt_client.on_disconnect = on_disconnect

        # extract the form the environment
        mqtt_broker_url = urlparse(mqtt_broker_url)

        mqtt_client.connect(host=mqtt_broker_url.hostname,
                            port=mqtt_broker_url.port,
                            keepalive=60,
                            bind_address="",
                            bind_port=0,
                            clean_start=mqtt.MQTT_CLEAN_START_FIRST_ONLY,
                            properties=None)
        # create a non-blocking thread for mqtt communication
        mqtt_client.loop_start()

        for attr in device.attributes:
            mqtt_client.publish(
                topic=f"/json/{service_group.apikey}/{device.device_id}/attrs",
                payload=json.dumps({attr.object_id: random.randint(0, 9)}))

        time.sleep(5)
        entity = client.cb.get_entity(entity_id=device.device_id,
                                      entity_type=device.entity_type)

        # create and send a command via the context broker
        context_command = NamedCommand(name=device_command.name,
                                       value=False)
        client.cb.post_command(entity_id=entity.id,
                               entity_type=entity.type,
                               command=context_command)

        time.sleep(5)
        # check the entity the command attribute should now show OK
        entity = client.cb.get_entity(entity_id=device.device_id,
                                      entity_type=device.entity_type)

        # The main part of this test, for all this setup was done
        self.assertEqual("OK", entity.heater_status.value)

        # close the mqtt listening thread
        mqtt_client.loop_stop()
        # disconnect the mqtt device
        mqtt_client.disconnect()