Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feature: V2 Autopilot API #1596

Open
wants to merge 35 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
1e52634
autopilot API
panaaj May 17, 2023
f200563
Register AutopilotProvider on interface start up.
panaaj May 17, 2023
80f7a3f
Mock autopilot provider for testing.
panaaj May 17, 2023
fbb31da
align docs and operation
panaaj May 22, 2023
fdbcf4c
Merge branch 'master' into v2_api_autopilot
panaaj Sep 27, 2023
cf0fddf
Align docs with server-guide
panaaj Aug 23, 2023
f8af97c
Pivot to a facade approach
panaaj Sep 28, 2023
8d12fd9
Align documentation
panaaj Oct 1, 2023
39dbd63
Merge branch 'master' into v2_api_autopilot
panaaj Oct 1, 2023
0efb4b3
fix documentation content
panaaj Oct 2, 2023
7c8cade
doc: updated diagram
panaaj Oct 8, 2023
1afaf3e
Revert to original approach.
panaaj Oct 31, 2023
5756833
convert to methods
tkurki Nov 2, 2023
55abaa3
use ts-auto-guard for isAutopilotprovider
tkurki Nov 2, 2023
ae0fa94
simplify: primaryProvider & primaryProviderId
tkurki Nov 2, 2023
4022aab
simplify routes
tkurki Nov 2, 2023
7d395f7
Add updatePermissions check to PUT, POST requests.
panaaj Nov 4, 2023
5e3d7a3
Fix response formatting
panaaj Nov 5, 2023
80809d0
Plugin can update API with value changes.
panaaj Nov 7, 2023
6d5826f
Update the method to assign a defaultProvider.
panaaj Nov 14, 2023
1b69c18
Add Device to Provider map.
panaaj Nov 18, 2023
5298aaa
Added appCopy.autopilotUpdate() interface method.
panaaj Nov 19, 2023
8ae590a
Remove mock providers.
panaaj Nov 28, 2023
2a51707
chore: remove temporary test code
panaaj Dec 10, 2023
a99e7c1
Remove default $source delta.
panaaj Dec 12, 2023
5d1390e
Added autopilot alarm interface method.
panaaj Dec 21, 2023
f7494bc
chore: format
panaaj Dec 21, 2023
730a941
Fix typings
panaaj Dec 22, 2023
18da17a
chore: update docs
panaaj Dec 22, 2023
f5b5cb8
Remove unused references.
panaaj Jan 9, 2024
024538f
Add `dodge` endpoints.
panaaj Jan 9, 2024
432a622
Merge branch 'master' into v2_api_autopilot
panaaj Feb 3, 2024
5bea6a6
fix: duplicate import
panaaj Feb 3, 2024
4243bf0
Merge branch 'master' into v2_api_autopilot
panaaj May 8, 2024
b05e4c3
chore: formatting
panaaj May 8, 2024
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
451 changes: 445 additions & 6 deletions docs/src/develop/plugins/autopilot_provider_plugins.md

Large diffs are not rendered by default.

332 changes: 314 additions & 18 deletions docs/src/develop/rest-api/autopilot_api.md
Original file line number Diff line number Diff line change
@@ -1,38 +1,334 @@
# Autopilot API
# Working with the Autopilot API

#### (Under Development)

_Note: This API is currently under development and the information provided here is likely to change._
## Overview

The Signal K server Autopilot API will provide a common set of operations for interacting with autopilot devices and (like the Resources API) will rely on a "provider plugin" to facilitate communication with the autopilot device.
The Autopilot API defines the `autopilots` path under the `steering` schema group _(e.g. `/signalk/v2/api/vessels/self/steering/autopilots`)_ for representing information from one or more autopilot devices.

The Autopilot API will handle requests to `/steering/autopilot` paths and pass them to an Autopilot Provider plugin which will send the commands to the autopilot device.
The Autopilot API provides a mechanism for applications to issue requests to autopilot devices to perform common operations. Additionally, when multiple autopilot devices are present, each autopilot device is individually addressable.

The following operations are an example of the operations identified for implementation via HTTP `GET` and `PUT` requests:
_Note: Autopilot provider plugins are required to enable the API operation and provide communication with autopilot devices. See [Autopilot Provider Plugins](../plugins/autopilot_provider_plugins.md) for details._

PUT `/steering/autopilot/engage` (engage / activate the autopilot)
## The `Default` Autopilot

PUT `/steering/autopilot/disengage` (disengage / deactivate the autopilot)
To ensure a consistent API calling profile and to simplify client operations, the Autopilot API will assign a `default` autopilot device which is accessible using the path `./steering/autopilots/default`.

GET `/steering/autopilot/state` (retrieve the current autopilot state)
- When only one autopilot is present, it will be assigned as the `default`.

PUT `/steering/autopilot/state` (set the autopilot state)
- When multiple autopilots are present, and a `default` is yet to be assigned, one will be assigned when:
- An update is received from a provider plugin, the autopilot which is the source of the update will be assigned as the `default`.
- An API request is received, the first autopilot device registered, is assigned as the `default`.
- A request is sent to the `defaultPilot` API endpoint _(see [Setting the Default Autopilot](#setting-the-default-provider))_.

GET `/steering/autopilot/mode` (retrieve the current autopilot mode)
### Setting the Default Autopilot

PUT `/steering/autopilot/mode` (set autopilot mode)
To set / change the `default` autopilot, submit an HTTP `POST` request to `/signalk/v2/api/vessels/self/steering/autopilots/defaultPilot/{id}` where `{id}` is the identifier of the autopilot to use as the default.

GET `/steering/autopilot/target` (get currrent target value)
_Example:_
```typescript
HTTP POST "/signalk/v2/api/vessels/self/steering/autopilots/defaultPilot/raymarine-id"
```

PUT `/steering/autopilot/target` (set the target value based on the selected mode)
The autopilot with the supplied id will now be the target of requests made to `./steering/autopilots/default/*`.

PUT `/steering/autopilot/target/adjust` (increment / decrement target value)

PUT `/steering/autopilot/tack/port` (perform a port tack)
### Getting the Default Autopilot

PUT `/steering/autopilot/tack/starboard` (perform a starboard tack)
To get the id of the `default` autopilot, submit an HTTP `GET` request to `/signalk/v2/api/vessels/self/steering/autopilots/defaultPilot`.

_Example:_
```typescript
HTTP GET "/signalk/v2/api/vessels/self/steering/autopilots/defaultPilot"
```

_Response:_
```JSON
{
"id":"raymarine-id"
}
```

[View the PR](https://github.com/SignalK/signalk-server/pull/1596) for more details.
## Listing the available Autopilots

To retrieve a list of installed autopilot devices, submit an HTTP `GET` request to `/signalk/v2/api/vessels/self/steering/autopilots`.

The response will be an object containing all the registered autopilot devices, keyed by their identifier, detailing the `provider` it is registered by and whether it is assigned as the `default`.

```typescript
HTTP GET "/signalk/v2/api/vessels/self/steering/autopilots"
```
_Example response: list of registered autopilots showing that `pypilot-id` is assigned as the `default`._

```JSON
{
"pypilot-id": {
"provider":"pypilot-provider",
"isDefault": true
},
"raymarine-id": {
"provider":"raymarine-provider",
"isDefault": false
}
}
```

## Autopilot Deltas

Deltas emitted by the Autopilot API will have the base path `steering.autopilot` with the `$source` containing the autopilot device identifier.

_Example: Deltas for `autopilot.engaged` from two autopilots (`raymarine-id`)._
```JSON
{
"context":"vessels.self",
"updates":[
{
"$source":"pypilot-id",
"timestamp":"2023-11-19T06:12:47.820Z",
"values":[
{"path":"steering.autopilot.engaged","value":false}
]
},
{
"$source":"raymarine-id",
"timestamp":"2023-11-19T06:12:47.820Z",
"values":[
{"path":"steering.autopilot.engaged","value":true}
]
}
]
}
```


## Autopilot Notifications

The Autopilot API will provide notifications under the path `notifications.steering.autopilot` with the `$source` containing the autopilot device identifier.

A set of normalised notification paths are defined to provide a consistant way for client apps to receive and process alarm messages.

- `waypointAdvance`
- `waypointArrival`
- `routeComplete`
- `xte`
- `heading`
- `wind`

_Example:_
```JSON
{
"context":"vessels.self",
"updates":[
{
"$source":"pypilot-id",
"timestamp":"2023-11-19T06:12:47.820Z",
"values":[
{
"path": "notifications.steering.autopilot.waypointAdvance",
"value": {
"state": "alert",
"method": ["sound"],
"message": "Waypoint Advance"
}
}
]
}
]
}

```

## Autopilot offline / unreachable

If an autopilot device is not connected or unreachable, the provider for that autopilot device will set the `state` of the device to `off-line`.


## Autopilot Operations

All API operations are invoked by issuing a request to:
1. `/signalk/v2/api/vessels/self/steering/autopilots/default`
2. `/signalk/v2/api/vessels/self/steering/autopilots/{id}`

_Example:_
```typescript
HTTP GET "/signalk/v2/api/vessels/self/steering/autopilots/default/state"

HTTP GET "/signalk/v2/api/vessels/self/steering/autopilots/pypilot-id/mode"
```

### Retrieving Autopilot Status

To retrieve the current autopilot configuration as well as a list of available options for `state` and `mode` selections, submit an HTTP `GET` request to `/signalk/v2/api/vessels/self/steering/autopilots/{id}`.

```typescript
HTTP GET "/signalk/v2/api/vessels/self/steering/autopilots/{id}"
```
_Response:_

```JSON
{
"options":{
"state":["enabled","disabled"],
"mode":["gps","compass","wind"]
},
"state":"disabled",
"mode":"gps",
"target": 0,
"engaged": false
}
```

Where:
- `options` contains arrays of valid `state` and `mode` selection options
- `state` represents the current state of the device
- `mode` represents the current mode of the device
- `target` represents the current target value with respect to the selected `mode`
- `engaged` will be true when the autopilot is actively steering the vessel.


### Setting the Autopilot State

Autopilot state can be set by submitting an HTTP `PUT` request to the `state` endpoint containing a value from the list of available states.

```typescript
HTTP PUT "/signalk/v2/api/vessels/self/steering/autopilots/{id}/state" {"value": "disabled"}
```

### Getting the Autopilot State

The current autopilot state can be retrieved by submitting an HTTP `GET` request to the `state` endpoint.

```typescript
HTTP GET "/signalk/v2/api/vessels/self/steering/autopilots/{id}/state"
```

_Response:_

```JSON
{
"value":"enabled",
}
```

### Setting the Autopilot Mode

Autopilot mode can be set by submitting an HTTP `PUT` request to the `mode` endpoint containing a value from the list of available modes.

```typescript
HTTP PUT "/signalk/v2/api/vessels/self/steering/autopilots/{id}/mode" {"value": "gps"}
```

### Getting the Autopilot Mode

The current autopilot mode can be retrieved by submitting an HTTP `GET` request to the `mode` endpoint.

```typescript
HTTP GET "/signalk/v2/api/vessels/self/steering/autopilots/{id}/mode"
```

_Response:_

```JSON
{
"value":"gps",
}
```

### Setting the Target value

Autopilot target value can be set by submitting an HTTP `PUT` request to the `target` endpoint containing the desired value in radians.

_Note: The value supplied should be a number within the valid range for the selected `mode`._

```typescript
HTTP PUT "signalk/v2/api/vessels/self/steering/autopilots/{id}/target" {"value": 1.1412}
```

The target value can be adjusted a +/- value by submitting an HTTP `PUT` request to the `target/adjust` endpoint with the value to add to the current `target` value in radians.

```typescript
HTTP PUT "signalk/v2/api/vessels/self/steering/autopilots/{id}/target/adjust" {"value": -0.1412}
```

### Getting the current Target value

The current autopilot target value _(in radians)_ can be retrieved by submitting an HTTP `GET` request to the `target` endpoint.

```typescript
HTTP GET "/signalk/v2/api/vessels/self/steering/autopilots/{id}/target"
```

_Response:_

```JSON
{
"value":"3.14",
}
```

### Engaging / Disengaging the Autopilot

#### Engaging the autopilot

An autopilot can be engaged by [setting it to a speciifc `state`](#setting-the-state) but it can also be engaged more generically by submitting an HTTP `POST` request to the `engage` endpoint.

```typescript
HTTP POST "/signalk/v2/api/vessels/self/steering/autopilots/{id}/engage"
```

_Note: The resultant `state` into which the autopilot is placed will be determined by the **provider plugin** and the autopilot device it is communicating with._

#### Disengaging the autopilot

An autopilot can be disengaged by [setting it to a speciifc `state`](#setting-the-state) but it can also be disengaged more generically by submitting an HTTP `POST` request to the `disengage` endpoint.

```typescript
HTTP POST "/signalk/v2/api/vessels/self/steering/autopilots/{id}/disengage"
```

_Note: The resultant `state` into which the autopilot is placed will be determined by the **provider plugin** and the autopilot device it is communicating with._

### Perform a Tack

To send a command to the autopilot to perform a tack in the required direction, submit an HTTP `POST` request to `/tack/{direction}` where _direction_ is either `port` or `starboard`.

_Example: Tack to Port_
```typescript
HTTP POST "/signalk/v2/api/vessels/self/steering/autopilots/{id}/tack/port"
```

_Example: Tack to Starboard_
```typescript
HTTP POST "/signalk/v2/api/vessels/self/steering/autopilots/{id}/tack/starboard"
```


### Perform a Gybe

To send a command to the autopilot to perform a gybe in the required direction, submit an HTTP `POST` request to `/gybe/{direction}` where _direction_ is either `port` or `starboard`.

_Example: Gybe to Port_
```typescript
HTTP POST "/signalk/v2/api/vessels/self/steering/autopilots/{id}/gybe/port"
```

_Example: Gybe to Starboard_
```typescript
HTTP POST "/signalk/v2/api/vessels/self/steering/autopilots/{id}/gybe/starboard"
```



### Dodging / overriding

To send a command to the autopilot to manually override the rudder position two (2) degrees in the requested direction in order to avoid an obstacle,
submit an HTTP `POST` request to `/dodge/{direction}` where _direction_ is either `port` or `starboard`.

_Example: Dodge to Port_
```typescript
HTTP POST "/signalk/v2/api/vessels/self/steering/autopilots/{id}/dodge/port"
```

_Example: Gybe to Starboard_
```typescript
HTTP POST "/signalk/v2/api/vessels/self/steering/autopilots/{id}/dodge/starboard"
```
Binary file added docs/src/img/autopilot_provider.dia
Binary file not shown.
Loading