Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
64 commits
Select commit Hold shift + click to select a range
13e91f2
Course and Resources API
tkurki Mar 22, 2022
e8a5712
chore: add resource-provider-plugin
tkurki Mar 22, 2022
866f544
chore: add ts project references
tkurki Mar 27, 2022
a8c9735
tweak chart definition
panaaj Mar 23, 2022
609e5c6
chore: remove resources plugin prepare
tkurki Mar 27, 2022
52e2f07
fix compile error
tkurki Mar 27, 2022
d333532
style: lint
tkurki Mar 27, 2022
0f5bd56
update resources-provider label as built-in
panaaj Apr 4, 2022
f917f92
fix resources plugin compile error
panaaj Apr 4, 2022
da2e3fc
chore: build docker image for this branch
tkurki Apr 4, 2022
537ff9c
chore: update link to resourses-provider-plugin
panaaj Apr 6, 2022
546387e
Merge branch 'resources_course_api' of https://github.com/SignalK/sig…
panaaj Apr 6, 2022
5b36979
chore: tweak chart definition
panaaj Apr 6, 2022
2d28bfe
Remove chart post api definition.
panaaj Apr 10, 2022
71eb3d4
feature: dynamic servers in openApis
tkurki Apr 18, 2022
6146739
improve error message when unable to set course.
panaaj Apr 19, 2022
9d39b6d
Use Freeboard beta
tkurki Apr 21, 2022
096bbdc
move `startTime` up a level
panaaj Apr 22, 2022
23d3642
update references to startTime
panaaj Apr 22, 2022
eeb6432
add startTime example
panaaj Apr 22, 2022
7ef6327
set pointIndex, pointTotal and reverse to null
panaaj Apr 22, 2022
9df7926
update catch error type
panaaj Apr 22, 2022
6a61f71
fix tests for null pointIndex, pointTotal, reverse
panaaj Apr 22, 2022
3101b30
fix: correct nulls in pointIndex|Total and reverse
tkurki Apr 23, 2022
17bcd52
fix: always set reverse when activating route
tkurki Apr 23, 2022
091adc0
fix startTime assertions
tkurki Apr 23, 2022
3c86ed2
linter
tkurki Apr 23, 2022
949be9e
add files for heroku demo setup
tkurki Apr 25, 2022
86d6b53
add course-provider plugin
tkurki Apr 25, 2022
0bd6423
add plugin settings files
tkurki Apr 25, 2022
32dac26
feature: add support for forcing https in openapi url
tkurki Apr 27, 2022
825a92c
Heroku build command as oneliner
tkurki Apr 27, 2022
726f055
Set previousPoint to vessel position for routes.
panaaj Apr 28, 2022
0a2695a
Update calculations to calcValues in openapi
panaaj Apr 28, 2022
86983e0
chore: beta.2 dependencies
panaaj Apr 28, 2022
1be1cd8
fix couese.calcValues openapi definition
panaaj May 5, 2022
dd88707
chore: update beta plugin dependencies
panaaj May 6, 2022
aa5d31b
OpenAPI: add pattern for timestamp values
panaaj May 18, 2022
be39cbe
Add OpenAPI definitions for notifications.
panaaj May 22, 2022
3bbc79e
Update server version to 2.0.0-beta
panaaj May 22, 2022
005106b
chore: fix openAPI definitions
panaaj Jun 4, 2022
2df9fd2
add targetArrivalTime and targetSpeed attributes
panaaj Jun 10, 2022
f716ac2
show webapp icons in admin-ui
panaaj Jun 12, 2022
9f204e2
chore: lint
panaaj Jun 14, 2022
b43445e
put handler for targetArrivalTime.
panaaj Jun 14, 2022
f11f096
chore: lint
panaaj Jun 14, 2022
43bb770
allow setting targetArrivalTime to null
panaaj Jun 17, 2022
384c228
chore: lint
panaaj Jun 17, 2022
a126b96
chore: fix typo
panaaj Jun 23, 2022
7444e54
add support for PGN129285
panaaj Jun 27, 2022
d5ab1b6
update calcMethod values to align with n2k-signalk
panaaj Jun 30, 2022
d072dc3
chore: add targetArrivalTime to course tests
panaaj Jul 4, 2022
b4e51cc
fix test for resource href value
panaaj Jul 13, 2022
2cb607c
add OpenApi definitions for authentication
panaaj Jul 18, 2022
990ed30
add securityScheme to course & resources defs.
panaaj Jul 18, 2022
fbb9fae
add parameters definition
panaaj Jul 18, 2022
a7b78a0
remove servers section from definition.
panaaj Jul 18, 2022
3b03950
chore: lint
panaaj Jul 18, 2022
d213c5a
add Apps api definition
panaaj Jul 18, 2022
72d0d0e
update openapi definitions
panaaj Jul 22, 2022
a0751e3
openapi: add servers url to fix validation issue
panaaj Aug 3, 2022
051d8ef
fix course api openApi definition
panaaj Sep 30, 2022
0b23b8d
fix clearing of activeRoute when dest is set
panaaj Sep 30, 2022
171dd95
fix openApi defnitions
panaaj Oct 3, 2022
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .github/workflows/build-docker.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ on:
branches:
- master
- "build-docker"
- "resources_course_api"
tags:
- '*'
- '!v*'
Expand Down
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
node_modules
!test/plugin-test-config/node_modules/

*.tsbuildinfo

lib/

.DS_Store
Expand Down
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,7 @@ Environment variables
- `SIGNALK_NODE_CONFIG_DIR` override the path to find server configuration files.
- `PORT` override the port for http/ws service (default is 3000).
- `SSLPORT` override the port for https/wss service. If defined activates ssl as forced, default protocol (default is 3443).
- `PROTOCOL` override http/https where the server is accessed via https but the server sees http (for example when Heroku handles https termination)
- `EXTERNALPORT` the port used in /signalk response and Bonjour advertisement. Has precedence over configuration file.
- `EXTERNALHOST` the host used in /signalk response and Bonjour advertisement. Has precedence over configuration file.
- `FILEUPLOADSIZELIMIT` override the file upload size limit (default is '10mb').
Expand Down
352 changes: 352 additions & 0 deletions RESOURCE_PROVIDER_PLUGINS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,352 @@
# Resource Provider plugins

_This document should be read in conjunction with [SERVERPLUGINS.md](./SERVERPLUGINS.md) as it contains additional information regarding the development of plugins that facilitate the storage and retrieval of resource data._

To see an example of a resource provider plugin see [resources-provider-plugin](https://github.com/SignalK/signalk-server/tree/master/packages/resources-provider-plugin)

---

## Overview

The SignalK specification defines the path `/signalk/v2/api/resources` for accessing resources to aid in navigation and operation of the vessel.

It also defines the schema for the following __Common__ resource types:
- routes
- waypoints
- notes
- regions
- charts

each with its own path under the root `resources` path _(e.g. `/signalk/v2/api/resources/routes`)_.

It should also be noted that the `/signalk/v2/api/resources` path can also host other types of resource data which can be grouped within a __Custom__ path name _(e.g. `/signalk/v2/api/resources/fishingZones`)_.

The SignalK server does not natively provide the ability to store or retrieve resource data for either __Common__ and __Custom__ resource types.
This functionality needs to be provided by one or more server plugins that handle the data for specific resource types.

These plugins are called __Resource Providers__.

The de-coupling of request handling and data storage provides flexibility to persist resource data in different types of storage to meet the needs of your SignalK implementation.

Requests for both __Common__ and __Custom__ resource types are handled by the SignalK server, the only difference being that the resource data contained in `POST` and `PUT` requests for __Common__ resource types is validated against the OpenApi schema.

_Note: A plugin can act as a provider for both __Common__ and __Custom__ resource types._

---
## Server Operation:

The Signal K server handles all requests to `/signalk/v2/api/resources` (and sub-paths), before passing on the request to the registered resource provider plugin.

The following operations are performed by the server when a request is received:
- Checks for a registered provider for the resource type
- Checks that the required ResourceProvider methods are defined
- Performs access control check
- For __Common__ resource types, checks the validity of the `resource id` and submitted `resource data`.

Only after successful completion of all these operations is the request passed on to the registered resource provider plugin.

---
## Resource Provider plugin:

For a plugin to be considered a Resource Provider it needs to register with the SignalK server the following:
- Each resource type provided for by the plugin
- The methods used to action requests. It is these methods that perform the writing, retrieval and deletion of resources from storage.


### Resource Provider Interface

---
The `ResourceProvider` interface is the means by which the plugin informs the SignalK server each of the resource type(s) it services and the endpoints to which requests should be passed.

The `ResourceProvider` interface is defined as follows in _`@signalk/server-api`_:

```typescript
interface ResourceProvider {
type: ResourceType
methods: ResourceProviderMethods
}
```
where:

- `type`: The resource type provided for by the plugin. These can be either __Common__ or __Custom__ resource types _(e.g. `routes`, `fishingZones`)_

- `methods`: An object implementing the `ResourceProviderMethods` interface defining the methods to which resource requests are passed by the SignalK server. _Note: The plugin __MUST__ implement each method, even if that operation is NOT supported by the plugin!_

The `ResourceProviderMethods` interface is defined as follows in _`@signalk/server-api`_:

```typescript
interface ResourceProviderMethods {
pluginId?: string
listResources: (query: { [key: string]: any }) => Promise<{[id: string]: any}>
getResource: (id: string) => Promise<object>
setResource: (
id: string,
value: { [key: string]: any }
) => Promise<void>
deleteResource: (id: string) => Promise<void>
}
```


#### Methods:

---

__`listResources(query)`__: This method is called when a request is made for resource entries that match a specific criteria.

_Note: It is the responsibility of the resource provider plugin to filter the resources returned as per the supplied query parameters._

- `query:` Object contining `key | value` pairs repesenting the parameters by which to filter the returned entries. _e.g. {region: 'fishing_zone'}_

returns: `Promise<{[id: string]: any}>`


_Example resource request:_
```
GET /signalk/v2/api/resources/waypoints?bbox=[5.4,25.7,6.9,31.2]
```
_ResourceProvider method invocation:_

```javascript
listResources(
{
bbox: '5.4,25.7,6.9,31.2'
}
);
```

---
__`getResource(id)`__: This method is called when a request is made for a specific resource entry with the supplied id. If there is no resource associated with the id the call should return Promise.reject.

- `id:` String containing the target resource entry id. _(e.g. 'urn:mrn:signalk:uuid:07894aba-f151-4099-aa4f-5e5773734b99')_

returns: `Promise<object>`

_Example resource request:_
```
GET /signalk/v2/api/resources/routes/urn:mrn:signalk:uuid:07894aba-f151-4099-aa4f-5e5773734b99
```
_ResourceProvider method invocation:_

```javascript
getResource(
'urn:mrn:signalk:uuid:07894aba-f151-4099-aa4f-5e5773734b99'
);
```

---
__`setResource(id, value)`__: This method is called when a request is made to save / update a resource entry with the supplied id. The supplied data is a complete resource record.

- `id:` String containing the id of the resource entry created / updated. _e.g. 'urn:mrn:signalk:uuid:07894aba-f151-4099-aa4f-5e5773734b99'_

- `value:` Resource data to be stored.

returns: `Promise<void>`

_Example PUT resource request:_
```
PUT /signalk/v2/api/resources/routes/urn:mrn:signalk:uuid:07894aba-f151-4099-aa4f-5e5773734b99 {resource_data}
```
_ResourceProvider method invocation:_

```javascript
setResource(
'urn:mrn:signalk:uuid:07894aba-f151-4099-aa4f-5e5773734b99',
{
name: 'test route',
distance': 8000,
feature: {
type: 'Feature',
geometry: {
type: 'LineString',
coordinates: [[138.5, -38.6], [138.7, -38.2], [138.9, -38.0]]
},
properties:{}
}
}
);
```

_Example POST resource request:_
```
POST /signalk/v2/api/resources/routes {resource_data}
```
_ResourceProvider method invocation:_

```javascript
setResource(
'<server_generated_id>',
{
name: 'test route',
distance': 8000,
feature: {
type: 'Feature',
geometry: {
type: 'LineString',
coordinates: [[138.5, -38.6], [138.7, -38.2], [138.9, -38.0]]
},
properties:{}
}
}
);
```

---
__`deleteResource(id)`__: This method is called when a request is made to remove the specific resource entry with the supplied resource id.

- `id:` String containing the target resource entry id. _e.g. 'urn:mrn:signalk:uuid:07894aba-f151-4099-aa4f-5e5773734b99'_

returns: `Promise<void>`

_Example resource request:_
```
DELETE /signalk/v2/api/resources/routes/urn:mrn:signalk:uuid:07894aba-f151-4099-aa4f-5e5773734b99
```
_ResourceProvider method invocation:_

```javascript
deleteResource(
'urn:mrn:signalk:uuid:07894aba-f151-4099-aa4f-5e5773734b99'
);
```

### Registering a Resource Provider:
---

To register a plugin as a provider for one or more resource types with the SignalK server, it must call the server's `registerResourceProvider` function for each resource type being serviced during plugin startup.

The function has the following signature:

```typescript
app.registerResourceProvider(resourceProvider: ResourceProvider)
```
where:
- `resourceProvider`: is a reference to a `ResourceProvider` object containing the __resource type__ and __methods__ to receive the requests.

_Note: If a plugin has already registered as a provider for a resource type, the method throws with an `Error`._

_Example:_
```javascript
import { ResourceProvider } from '@signalk/server-api'

module.exports = function (app) {

const plugin = {
id: 'mypluginid',
name: 'My Resource Providerplugin'
}

const routesProvider: ResourceProvider = {
type: 'routes',
methods: {
listResources: (params) => {
fetchRoutes(params)
...
},
getResource: (id) => {
getRoute(id)
...
},
setResource: (id, value )=> {
saveRoute(id, value)
...
},
deleteResource: (id) => {
deleteRoute(id, value)
...
}
}
}

const waypointsProvider: ResourceProvider = {
type: 'waypoints',
methods: {
listResources: (params) => {
fetchWaypoints(params)
...
},
getResource: (id) => {
getWaypoint(id)
...
},
setResource: (id, value )=> {
saveWaypoint(id, value)
...
},
deleteResource: (id) => {
deleteWaypoint(id, value)
...
}
}
}

plugin.start = function(options) {
...
try {
app.registerResourceProvider(routesProvider)
app.registerResourceProvider(waypointsProvider)
}
catch (error) {
// handle error
}
}

return plugin
}
```

### Methods

A Resource Provider plugin must implement methods to service the requests passed from the server.

All methods must be implemented even if the plugin does not provide for a specific request.

Each method should return a __Promise__ on success and `throw` on error or if a request is not serviced.



```javascript
// SignalK server plugin
module.exports = function (app) {

const plugin = {
id: 'mypluginid',
name: 'My Resource Providerplugin',
start: options => {
...
app.registerResourceProvider({
type: 'waypoints',
methods: {
listResources: (params) => {
return new Promise( (resolve, reject) => {
...
if (ok) {
resolve(resource_list)
} else {
reject( new Error('Error fetching resources!'))
}
})
},
getResource: (id) => {
return new Promise( (resolve, reject) => {
...
if (ok) {
resolve(resource_list)
} else {
reject( new Error('Error fetching resource with supplied id!'))
}
})
},
setResource: (id, value )=> {
throw( new Error('Not implemented!'))
},
deleteResource: (id) => {
throw( new Error('Not implemented!'))
}
}
})
}

}
}
```
Loading