Subscribing to an entity without specifying attributes - fiware-orion

I'm trying to subscribe to an entity to get notifications using ONCHANGE.
The thing is that I'd like to get notified when new attributes get added or removed from the entity, otherwise said, I want a notification whenever anything changes on that entity.
Is that possible? I tried setting an empty condValues list in the query like this:
{
"entities": [
{
"type": "case",
"isPattern": "false",
"id": "Case1"
}
],
"reference": "http://localhost:1028/accumulate",
"duration": "P1M",
"notifyConditions": [
{
"type": "ONCHANGE",
"condValues": [
"Test Node 1"
]
}
],
"throttling": "PT5S"
}
But it didn't work.
PS: Note that I omitted the attributes Array to receive all the attributes on notification, this does work.

Current Orion version (0.19.0) doesn't implement such feature. However, it is planed to be done in the future (see this issue at Orion github repository).
EDIT: since Orion 0.27.0 you can subscribe to changes in any attribute. In order to do so, do the subscription omitting the condValues field (or use an empty array [] as value).

Related

How to use roomHint and structureHint with smarthome actions on Google

We are currently setting un a Smarthome action, and we would like to provide roomHint on the first sync (not on request sync) as it's really tedious to set up rooms on the first sync, but it does not work.
We tried to name rooms in english and also in italian, (as it's not really clear from the documentation if there is a list on room names that we can use?) but no way.
So can you please give us a hint how to use the roomHint field?
Also in the API doc we've found structureHint, does it work? The documentation for SYNC intent does not mention this field.
Here is our SYNC intent with one device and room, we took office from the example JSON:
{
"requestId": "3582198904737125163",
"payload": {
"agentUserId": "xyz#qwertyz.com",
"devices": [
{
"id": "deviceID",
"type": "action.devices.types.LIGHT",
"traits": [
"action.devices.traits.OnOff"
],
"name": {
"name": "Lampadina",
"defaultNames": [
"Lampadina_XYZ"
],
"nicknames": [
"Lampadina"
]
},
"willReportState": false,
"customData": {
"modelType": "DEVICE"
},
"roomHint": "office"
}
]
}
}
Thanks
Unfortunately, I believe the structureHint is only in the HomeGraph API sync response.
It cannot be used in the Sync intent.
If someone can tell me I'm wrong and how to use it, you'd be a hero.

Validate referential integrity of object arrays with Joi

I'm trying to validate that the data I am returned it sensible. Validating data types is done. Now I want to validate that I've received all of the data needed to perform a task.
Here's a representative example:
{
"things": [
{
"id": "00fb60c7-520e-4228-96c7-13a1f7a82749",
"name": "Thing 1",
"url": "https://lolagons.com"
},
{
"id": "709b85a3-98be-4c02-85a5-e3f007ce4bbf",
"name": "Thing 2",
"url": "https://lolfacts.com"
}
],
"layouts": {
"sections": [
{
"id": "34f10988-bb3d-4c38-86ce-ed819cb6daee",
"name": "Section 1",
"content:" [
{
"type": 2,
"id": "00fb60c7-520e-4228-96c7-13a1f7a82749" //Ref to Thing 1
}
]
}
]
}
}
So every Section references 0+ Things, and I want to validate that every id value returned in the Content of Sections also exists as an id in Things.
The docs for Object.assert(..) implies that I need a concrete reference. Even if I do the validation within the Object.keys or Array.items, I can't resolve the reference at the other end.
Not that it matters, but my context is that I'm validating HTTP responses within IcedFrisby, a Frisby.js fork.
This wasn't really solveable in the way I asked (i.e. with Joi).
I solved this for my context by writing a plugin for icedfrisby (published on npm here) which uses jsonpath to fetch each id in Content and each id in Things. The plugin will then assert that all of the first set exist within the second.

REST: update a resource with different fields requiring different user permissions

I have an endpoint /groups
I can create a group by POSTing some info to /groups
A single group can be read by /groups/{id}
I can update some fields in the group by POSTing to /group/{id}
HOWEVER I have different fields that are needed to be updated by users with different permissions, for instance: A group might have the structure
{
"id": 1,
"name": "some name",
"members": [
{
"user_id": 456,
"known_as": "Name 1",
"user": { /* some user object */},
"status": "accepted",
"role": "admin",
"shared": "something"
},
{
"user_id": 999227,
"known_as": "Name 1",
"user": { /* some user object */},
"status": "accepted",
"role": "basic",
"shared": "something"
},
{
"user_id": 9883,
"known_as": "Name 1",
"user": { /* some user object */},
"status": "requested",
"role": "basic",
"shared": "something"
}
],
"link": "https://some-link"
}
As an example I have the following 3 operations for the /group/{id}/members/{id} endpoint:
I want only the user to be able to update his own known_as field
I want only group admins to be able to update each member's role and status fields.
I want both the user and the admin to be able to update the shared field
My options are this:
Should I allow all updates to be done by POSTing to /group/{id}/members/{id} with a subset of the fields for a member and throw an unauthorized error if they try to update a field that they aren't allowed to update?
Or should I break each operation into say /group/{id}/members/{id}/role, /group/{id}/members/{id}/shared and /group/{id}/members/{id}/status? The problem with this is that I don't want to have to make lots of requests to update all the fields (I imagine that there will end up being quite a lot of them).
So just for clarification my question is: Is it considered proper REST to do my option 1 where I can post updates to an endpoint that may fail if you try to change a field that you aren't allowed to?
In my opinion, option 1 is much better than option 2.
As you said option 2 is a waste of bandwidth.
More importantly, with option 1 you can easily implement an atomic update (update "all-or-nothing"). It should either complete successfully or fail entirely. There should never be a partial update.
With option 2 it's very likely the update can be implemented to complete some request successfully and reject another request, even if the two requests are considered a single operation.

Old notifications pushed immediately when subscription is created

I'm using Fiware Orion Context Broker version 0.20.
I notice that when I create a context subscription, my provided endpoint immediately gets notified about changes to the corresponding context elements that happened before I created the subscription.
To clarify: (note: I used these steps with a clean database)
I started the accumulator from the test package /usr/share/contextBroker/tests/accumulator-server.py 1028 /accumulate on
Created a context element using http://localhost:1026/v1/updateContext
{
"contextElements": [
{
"type": "Room",
"isPattern": "false",
"id": "Room1",
"attributes": [
{
"name": "temperature",
"value": "20"
}
]
}
],
"updateAction": "APPEND"
}
Then I created the subscription using http://localhost:1026/v1/subscribeContext
{
"entities": [
{
"type": "Room",
"isPattern": "true",
"id": ".*"
}
],
"attributes": [
"temperature"
],
"reference": "http://localhost:1028/accumulate",
"duration": "P1M",
"notifyConditions": [
{
"type": "ONCHANGE",
"condValues": [
"temperature"
]
}
],
"throttling": "PT5S"
}
I immediately receive the following content in the accumulator
POST http://localhost:1028/accumulate
Content-Length: 472
User-Agent: orion/0.20.0 libcurl/7.19.7
Host: localhost:1028
Accept: application/xml, application/json
Content-Type: application/json
{
"subscriptionId" : "55521671985dc3976b879780",
"originator" : "localhost",
"contextResponses" : [
{
"contextElement" : {
"type" : "Room",
"isPattern" : "false",
"id" : "Room1",
"attributes" : [
{
"name" : "temperature",
"type" : "",
"value" : "20"
}
]
},
"statusCode" : {
"code" : "200",
"reasonPhrase" : "OK"
}
}
]
}
Furthermore, if I create multiple contextElements before adding the subscription, they are all part to the contextResponses in the notification.
For my use case, this behavior is undesirable. The subscriptions are very dynamic (they come and go often throughout the lifecycle of the application) and I do not want the entire history every time I create a subscription. I only want to be notified about changes starting from the moment T created the subscription. (Not a history)
Did I overlook something in the documentation and can I resolve this by changing the contents of the subscription request? If not, is this generally accepted behavior for the context broker or just a plain bug?
It is the expected behaviour, as described in the manual:
You may wonder why accumulator-server.py is getting this message if you don't actually do any update. This is because the Orion Context Broker considers the transition from "non existing subscription" to "subscribed" as a change.
We understand that for some uses cases this is not convenient. However, behaving in the opossite way ruins another uses cases which need to know the "inicial state" before starting getting notifications corresponding to actual changes. The best solution to make everybody happy is to make this configurable, so each client can chose what it prefers. This feature is currently in our roadmap (see this issue in github.com).
While this gets implemented in Orion, in your case maybe a possible workaround is just ignore the first received nofitication belonging to a subscription (you can identify the subscription to which one notification belongs by the subscriptionId field in the notification payload). All the following notifications beloning to that subscription will correspond to actual changes.
EDIT: the posibility of avoiding initial notification has been finally implemented at Orion. Details are at this section of the documentation. It is now in the master branch (so if you use fiware/orion:latest docker you will get it) and will be include in next Orion version (2.2.0).

Update an entire resource collection in a REST way

I have a REST URI for a list of resources, something like:
http://foo.com/group/users
Each of these users has a sequence number and I want to expose a way to renumber those values for all the users in the collection and make this change available to everyone who accesses the list. Since this is an action on the collection as a whole, I'm not sure how to accomplish this.
I can envision a URL like http://foo.com/group/users?sequence=normalize but neither a PUT nor a POST really makes sense for the whole list, unless I submit the whole collection with the new numbers as the message data.
How can I make an update to an entire collection like this in a RESTful way without having to resend all the updated resources in the collection?
After the raffian's comment on my initial response, I reworked my answer to be more RESTful...
Use the method PATCH
This method is typically designed to update partially the state of a resource. In the case of a list resource, we could send a list with only the elements to update and the identifiers of elements in the list. The following request would be:
PATCH /group/users
[
{ "id": "userId1", "sequence": "newSequenceNumber1" },
{ "id": "userId2", "sequence": "newSequenceNumber2" },
(...)
]
Use the method POST on the list resource
This method is commonly used to add an element in the list managed by the resource. So if you want to leverage it for this action, we need to pass within the request an hint regarding the action to execute. We have the choice to add this either in a dedicated header or within the payload.
With the header approach, you will have something like that:
POST /group/users
X-Action: renumbering
[
{ "id": "userId1", "sequence": "newSequenceNumber1" },
{ "id": "userId2", "sequence": "newSequenceNumber2" },
(...)
]
With the payload approach, you will have something like that:
POST /group/users
{
"action": "renumbering",
"list": {
[
{ "id": "userId1", "sequence": "newSequenceNumber1" },
{ "id": "userId2", "sequence": "newSequenceNumber2" },
(...)
]
}
}
Hope it helps you,
Thierry
Semantically speaking, the HTTP PATCH method is the right way to go. This is also described in the currently chosen answer.
PATCH /group/users
[
{ "id": "userId1", "sequence": "newSequenceNumber1" },
{ "id": "userId2", "sequence": "newSequenceNumber2" },
...
]
However, the second method described in the chosen answer is not restful, because you invented new verbs inside a POST request. This is SOAP, not REST.
You can use both PATCH and POST on the URIs. I'd use PATCH if I were you. It's the best solution for bulk updates.