SignalK / specification

Signal K is a JSON-based format for storing and sharing marine data from different sources (e.g. nmea 0183, 2000, seatalk, etc)
Other
91 stars 69 forks source link

feature: add resources section #540

Open panaaj opened 5 years ago

panaaj commented 5 years ago

The specification could benefit from the addition of a Resources section to describe the way in which to work with these data items. (Noted: that #218 has a similar subject)

I have included below an example of possible content that is modelled on existing specification content and aligns with the current PUT section to help start the conversation.

Resources

Resources are collections of objects that are used to represent data that serves as additional information to aid with navigation etc.

Resources are:

Making a Request to Create, Update or Delete a Resource Entry

Requests are sent to a server to create, update or delete resource entries.

See Request/Response for more details on request/response in Signal K.

CREATING a Resource Entry

To create a resource entry, a POST request should be sent via HTTP or using a Signal K put delta.

The source field is optional. If a request is sent without the source and there is more than one source for the value, the server should respond with a 400 (Bad Request) HTTP status code.

Via HTTP

POST http://localhost:3000/signalk/v1/api/vessels/resources/notes/36f9b6b5-959f-46a1-8a68-82159742aadd
{
  "value": {
      "position":{
          "latitude":-35.02577800787516,"longitude":138.02825595260182
        },
        "title":"My Note",
        "description":"My note description","url":"http://mynote/url","mimeType":"text/html"
  },
  "source": "myApp",
}

Via a Delta

{
  "context": "vessels.self",
  "requestId": "6b0e776f-811a-4b35-980e-b93405371bc5",
  "put": [{
        "path": "resources.notes.36f9b6b5-959f-46a1-8a68-82159742aadd",
        "value": {
            "position":{
                "latitude":-35.02577800787516,"longitude":138.02825595260182
            },
            "title":"My Note",
            "description":"My note description","url":"http://mynote/url","mimeType":"text/html"
        }
  }]
}

The context key is optional, and defaults to vessels.self, which is the usual case. You can include it to be able to set values on other vessels.

UPDATING a Resource Entry

To update a resource entry, a PUT request should be sent via HTTP or using a Signal K put delta.

Via HTTP

PUT http://localhost:3000/signalk/v1/api/vessels/resources/notes/36f9b6b5-959f-46a1-8a68-82159742aadd
{
  "value": {
      "position":{
          "latitude":-35.02577800787516,"longitude":138.02825595260182
        },
        "title":"My Note",
        "description":"My note description","url":"http://mynote/url","mimeType":"text/html"
  },
  "source": "myApp",
}

Via a Delta

{
  "context": "vessels.self",
  "requestId": "6b0e776f-811a-4b35-980e-b93405371bc5",
  "put": [{
        "path": "resources.notes.36f9b6b5-959f-46a1-8a68-82159742aadd",
        "value": {
            "position":{
                "latitude":-35.02577800787516,"longitude":138.02825595260182
            },
            "title":"My Note",
            "description":"My note description","url":"http://mynote/url","mimeType":"text/html"
        }
  }]
}

DELETING a Resource Entry

To delete a resource entry, a DELETE request should be sent via HTTP or using a Signal K put delta with a value of null.

Via HTTP

DELETE http://localhost:3000/signalk/v1/api/vessels/resources/notes/36f9b6b5-959f-46a1-8a68-82159742aadd

Via a Delta

{
  "context": "vessels.self",
  "requestId": "6b0e776f-811a-4b35-980e-b93405371bc5",
  "put": [{
        "path": "resources.notes.36f9b6b5-959f-46a1-8a68-82159742aadd",
        "value": null
  }]
}

Querying Resource Entries

_As resource groups can potentially hold a large number of entries there needs to be a way of returning a subset of entries from the relevant /resources/<resource_group> path._

rob42 commented 5 years ago

You have several instances of /signalk/v1/api/vessels/resources/, since resources are in the top level they should be /signalk/v1/api/resources/.

panaaj commented 5 years ago

It seems (according to #218) that resources have been moved to a top level path from under vessels/self. Does this imply that all resources have a context of vessels.self? Is the context the vessel or possibly the signal k server itself... What if there is more than one server on a vessel? What about resources that are from other vessels, how does one access those?

Should there be something like /resources/self/routes & /resources/_vessel_uuid_/routes?

rob42 commented 5 years ago

See https://stackoverflow.com/questions/630453/put-vs-post-in-rest which discusses the convention that POST creates, so POST a note (body) to /signalk/v1/api/resources/notes and it should insert at `/signalk/v1/api/resources/notes/[uuid]/body_of_message.

So convention says a POST to /signalk/v1/api/resources/notes/[uuid] is an error, you must PUT to a specific address.

Given we have [uuid]s at various branches of the ever growing signalk data model, there is some complexity in trying to decide if a path is valid for a POST, and supporting all the paths potentially used by an app.

In a simple implementation you just append at path. But what happens if a note is POSTed to /signalk/v1/api/resources/, do you get /signalk/v1/api/resources/[uuid]/note_body, or POST to/signalk/v1/api/resources/[uuid], do you get/signalk/v1/api/resources/[uuid][uuid]`?

rob42 commented 5 years ago

Typically the signalk db will be on a vessel, eg on self. Hence the resources are resources known to the vessel (or server actually). When you consider sharing resources between vessels and other publishers it becomes difficult to search and share effectively if they are not in the root. There is nothing to stop you making all or some of your resources private, or sharing in a limited way.

rob42 commented 5 years ago

eg consider when cruising notes for a bay are scattered across potentially dozens of vessels.[uuid], and then you want to reshare them. Then some-one else reshares the note back...much simpler at the top level. Same with charts etc

rob42 commented 5 years ago

What about resources that are from other vessels, how does one access those? They are in the top level, but have the other vessel as the source

panaaj commented 5 years ago

So if they are made public should they appear under a separate path? Resource data is significantly different in nature to sensor data (less frequently updated, more record based than individual values) so the way it will want to be used will also differ.

panaaj commented 5 years ago

So for resources then:

Then can /resources be considered an alias for /vessels/self/resources and either path be used interchangeably?

rob42 commented 5 years ago

public and private resources use same path, just apply security rules to filter the results. Artemis server applies security at the branch/key level so this can be enabled, hence you see a different query result depending on user (or anonymous)

tkurki commented 5 years ago

What do you mean with context when you are talking about resources? A waypoint for example - how would a waypoint be different depending on the context?

In what cases would context matter here? Why should it be self?

rob42 commented 5 years ago

There is no context needed for resources. I dont think an alias vessels.self.resources is useful when you can simply use resources. Do you have a use case?

panaaj commented 5 years ago

I guess that's my question... does context actually apply here? Currently the spec wants you to use a context when using PUT via Delta but when using http the path does not contain context. It seems unnecessarily inconsistent.

I'd like to see it as straight forward as possible.

rob42 commented 5 years ago

Getting back to my post above:

So convention says a POST to /signalk/v1/api/resources/notes/[uuid] is an error, you must PUT to a specific address.

I would prefer we just use POST (with no path) to post a full signalk message same as we use in websockets, and use PUT for create/edit via http. It avoids a very complex area of uuids that is bound to give lots of pain to everyone.

rob42 commented 5 years ago

Currently the spec wants you to use a context when using PUT via Delta but when using http the path does not contain context. It seems unnecessarily inconsistent

I agree. The path should include /vessels/self/.., the idea that /vessels/self is a default is another can of worms when you start to use /resources, /aircraft, etc. One more complex bit of code and lots of implementation errors

panaaj commented 5 years ago

So something like

POST http://localhost:3000/signalk/v1/api/resources/notes
{
  "value": {
       "36f9b6b5-959f-46a1-8a68-82159742aadd" : {
               "position":{
                       "latitude":-35.02577800787516,"longitude":138.02825595260182
                },
                "title":"My Note",
                "description":"My note description","url":"http://mynote/url","mimeType":"text/html"
       }
  },
  "source": "myApp",
}
rob42 commented 5 years ago

What if someone does this:

POST http://localhost:3000/signalk/v1/api/resources/notes
{
  "value": {
  },
  "source": "evilAs",
}

Actually PUT has the same issue...security rules will be needed...

panaaj commented 5 years ago

That's why I feel there needs to be a specific resources section to spell out how to use them and how these cases are expected to be handled, as has been done in request/response.

rob42 commented 5 years ago

Use the original post you have above, edit for this discussion and add it as a gitbook page. Make a pull request. And write what works for you - if any-one disagrees they can comment on the PR.

panaaj commented 5 years ago

Will do

panaaj commented 5 years ago

I cannot push the Resources branch I have made to create the PR ... I'm guessing I do not have the privilege to do so.

tkurki commented 5 years ago

Doesn’t normal push to fork then PR work?

panaaj commented 5 years ago

Success... PR created.. #541