RWTH-EBC/FiLiP

ENTITY_GENERIC_ERROR when updating an existing device

Closed this issue · 4 comments

RCX112 commented

After I created a service group and provisioned a motion sensor device I get an error when I update the device by using a PUT-request with the IoT-Agent endpoint:

from filip.models.ngsi_v2.iot import ServiceGroup, Device, DeviceAttribute
from filip.clients.ngsi_v2 import IoTAClient
from filip.models.base import FiwareHeader

fiware_header = FiwareHeader(service="openiot", service_path="/")

iota_client = IoTAClient(url="http://localhost:4041", fiware_header=fiware_header)

service_group = ServiceGroup(service="openiot",
                             subservice="/", apikey="4jggokgpepnvsb2uv4s40d59ov",
                             cbHost="http://localhost:1026", entity_type="Thing",
                             resource="")

motion_sensor_device = Device(service="openiot", service_path="/", device_id="motion001",
                              entity_name="urn:ngsi-ld:Motion:001", entity_type="Motion",
                              protocol="PDI-IoTA-UltraLight", transport="MQTT", timezone="Europe/Berlin",
                              attributes=[DeviceAttribute(object_id="c", name="count", type="Integer")])

motion_sensor_device_updated = Device(service="openiot", service_path="/", device_id="motion001",
                                      entity_name="urn:ngsi-ld:Motion:001", entity_type="Motion",
                                      protocol="PDI-IoTA-UltraLight", transport="MQTT", timezone="Europe/Berlin",
                                      attributes=[DeviceAttribute(object_id="c", name="count", type="Integer"),
                                                  DeviceAttribute(object_id="c2", name="count2", type="Integer")])

iota_client.post_group(service_group, update=True)
iota_client.post_device(device=motion_sensor_device, update=True)
print(iota_client.get_device(device_id="motion001").attributes)
iota_client.update_device(device=motion_sensor_device_updated)
print(iota_client.get_device(device_id="motion001").attributes)

The program exits with an

requests.exceptions.HTTPError: 409 Client Error: Conflict for url: http://localhost:4041/iot/devices

When I looked at the response content of the PUT-request of the IoTAClient, I get the error

{"name":"ENTITY_GENERIC_ERROR","message":"Error accesing entity data for device: motion001 of type: Motion"}

I fixed this problem for me by including the attribute "entity_name" in the PUT-request of the "update_device" method:

res = self.put(url=url, headers=headers, json=device.dict(
                include={'entity_name', 'attributes', 'lazy', 'commands', 'static_attributes'},
                exclude_none=True))

I again used the FIWARE setup from the Git-Repo https://github.com/FIWARE/tutorials.IoT-over-MQTT.git

Similar to #204 , try to change your code for the provisioning:

  1. remove cbHost
  2. specify resource, here /iot/ul

Besides, I also recommend:

  1. service and subservice in your code, because it is the same with the fiware-header

Please let me know if it solves your problem.

RCX112 commented

I edited the code as you mentioned, so now it looks like that:

from filip.models.ngsi_v2.iot import ServiceGroup, Device, DeviceAttribute
from filip.clients.ngsi_v2 import IoTAClient
from filip.models.base import FiwareHeader

fiware_header = FiwareHeader(service="openiot", service_path="/")

iota_client = IoTAClient(url="http://localhost:4041", fiware_header=fiware_header)

service_group = ServiceGroup(apikey="4jggokgpepnvsb2uv4s40d59ov",
                             entity_type="Thing",
                             resource="/iot/ul")

motion_sensor_device = Device(device_id="motion001",
                              entity_name="urn:ngsi-ld:Motion:001", entity_type="Motion",
                              protocol="PDI-IoTA-UltraLight", transport="MQTT", timezone="Europe/Berlin",
                              attributes=[DeviceAttribute(object_id="c", name="count", type="Integer")])

motion_sensor_device_updated = Device(device_id="motion001",
                                      entity_name="urn:ngsi-ld:Motion:001", entity_type="Motion",
                                      protocol="PDI-IoTA-UltraLight", transport="MQTT", timezone="Europe/Berlin",
                                      attributes=[DeviceAttribute(object_id="c", name="count", type="Integer"),
                                                  DeviceAttribute(object_id="c2", name="count2", type="Integer")])

iota_client.post_group(service_group, update=True)
iota_client.post_device(device=motion_sensor_device, update=True)
print(iota_client.get_device(device_id="motion001").attributes)
iota_client.update_device(device=motion_sensor_device_updated)
print(iota_client.get_device(device_id="motion001").attributes)

But I still get the same error. The problem here is, I cannot update the motion sensor device before I published the first MQTT message. When I set an attribute via MQTT for the first time, an entity of the motion sensor will be created and the update_device function will work for me. But I sometimes have the case that I want to update my device via a PUT-request before I publish my first MQTT message. For that reason I included the attribute entity_name in the PUT-request.

Okay, I just find these changes from telefonicaid/iotagent-node-lib#1413. The error is not caused by FiLiP but the IoTagent.

I think the solution is not to rely on the initial creation of IoTagent anymore but to create the corresponding entity in context broker actively. That will surely increase the stability of your IoT service and the compatibility for the long term.