Skip to content

Commit

Permalink
Merge branch 'master' into v2_api_autopilot
Browse files Browse the repository at this point in the history
  • Loading branch information
panaaj committed Dec 2, 2024
2 parents 6df30a5 + d7aca71 commit 2caec45
Show file tree
Hide file tree
Showing 19 changed files with 643 additions and 112 deletions.
5 changes: 4 additions & 1 deletion bin/log2sk
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,13 @@ const app = {
handleMessage: (id, delta) => console.log(JSON.stringify(delta)),
propertyValues: {
onPropertyValues: () => undefined
},
wrappedEmitter: {
bindMethodsById: () => {}
}
}

new require('../lib/pipedproviders')(app).createPipedProvider({
new require('../lib/pipedproviders').pipedProviders(app).createPipedProvider({
pipeElements: [
{
type: 'providers/simple',
Expand Down
1 change: 1 addition & 0 deletions docs/src/SUMMARY.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
# Feature How Tos
* [Anchor Alarm](./features/anchoralarm/anchoralarm.md)
* [NMEA0183 Server](./features/navdataserver/navdataserver.md)
* [Data Logging](./features/datalogging/datalogging.md)
# Support
* [Help & Support](./support/help.md)
* [FAQs](./support/faq.md)
Expand Down
82 changes: 76 additions & 6 deletions docs/src/develop/rest-api/course_api.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,11 @@

The _Course API_ provides common course operations under the path `/signalk/v2/api/vessels/self/navigation/course` ensuring that all related Signal K data model values are maintained and consistent. This provides a set of data that can be confidently used for _course calculations_ and _autopilot operation_.

Additionally, the Course API persists course information on the server to ensure data is not lost in the event of a server restart.

Client applications use `HTTP` requests (`PUT`, `GET`,`DELETE`) to perform operations and retrieve course data.

Additionally, the Course API persists course information on the server to ensure data is not lost in the event of a server restart.
The Course API also listens for destination information in the NMEA stream and will set / clear the destination accordingly _(e.g. NMEA0183 RMB sentence, NMEA2000 PGN 129284)_. See [Configuration](#Configuration) for more details.

_Note: You can view the _Course API_ OpenAPI definition in the Admin UI (Documentation => OpenApi)._

Expand Down Expand Up @@ -125,6 +127,7 @@ HTTP GET 'http://hostname:3000/signalk/v2/api/vessels/self/navigation/course'

The contents of the response will reflect the operation used to set the current course. The `nextPoint` & `previousPoint` sections will always contain values but `activeRoute` will only contain values when a route is being followed.


#### 1. Operation: Navigate to a location _(lat, lon)_

_Example response:_
Expand Down Expand Up @@ -235,19 +238,86 @@ _Example response:_

## Cancelling navigation

To cancel the current course navigation and clear the course data
To cancel the current course navigation and clear the course data.

```typescript
HTTP DELETE 'http://hostname:3000/signalk/v2/api/vessels/self/navigation/course/'
HTTP DELETE 'http://hostname:3000/signalk/v2/api/vessels/self/navigation/course'
```

_Note: This operation will NOT change the destination information coming from the NMEA input stream! If the NMEA source device is still emitting destination data this will reappear as the current destination._

To ignore destination data from NMEA sources see [Configuration](#configuration) below.



## Configuration

The default configuration of the Course API will accept destination information from both API requests and NMEA stream data sources.

For NMEA sources, Course API monitors the the following Signal K paths populated by both the `nmea0183-to-signalk` and `n2k-to-signalk` plugins:
- _navigation.courseRhumbline.nextPoint.position_
- _navigation.courseGreatCircle.nextPoint.position_

HTTP requests are prioritised over NMEA data sources, so making an API request will overwrite the destination information received from and NMEA source.

Note: when the destination cleared using an API request, if the NMEA stream is emitting an active destination position, this will then be used by the Course API to populate course data.


#### Ignoring NMEA Destination Information

The Course API can be configured to ignore destination data in the NMEA stream by enabling `apiOnly` mode.

In `apiOnly` mode destination information can only be set / cleared using HTTP API requests.

- **`apiOnly` Mode = Off _(default)_**

- Destination data is accepted from both _HTTP API_ and _NMEA_ sources
- Setting a destination using the HTTP API will override the destination data received via NMEA
- When clearing the destination using the HTTP API, if destination data is received via NMEA this will then be used as the active destination.
- To clear destination sourced via NMEA, clear the destination on the source device.

- **`apiOnly` Mode = On**

- Course operations are only accepted via the HTTP API
- NMEA stream data is ignored
- Switching to `apiOnly` mode when an NMEA sourced destination is active will clear the destination.


#### Retrieving Course API Configuration

To retrieve the Course API configuration settings, submit a HTTP `GET` request to `/signalk/v2/api/vessels/self/navigation/course/_config`.

```typescript
HTTP GET 'http://hostname:3000/signalk/v2/api/vessels/self/navigation/course/_config'
```

_Example response:_
```JSON
{
"apiOnly": false
}
```

#### Enable / Disable `apiOnly` mode

To enable `apiOnly` mode, submit a HTTP `POST` request to `/signalk/v2/api/vessels/self/navigation/course/_config/apiOnly`.

_Enable apiOnly mode:_
```typescript
HTTP POST 'http://hostname:3000/signalk/v2/api/vessels/self/navigation/course/_config/apiOnly'
```

To disable `apiOnly` mode, submit a HTTP `DELETE` request to `/signalk/v2/api/vessels/self/navigation/course/_config/apiOnly`.

_Disable apiOnly mode:_
```typescript
HTTP DELETE 'http://hostname:3000/signalk/v2/api/vessels/self/navigation/course/_config/apiOnly'
```

---

## Course Calculations

Whilst not performing course calculations, the _Course API_ defines the paths to accommodate the values calculated during course navigation.

Click [here](./course_calculations.md) for details.



2 changes: 1 addition & 1 deletion docs/src/develop/webapps.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ You can also include the following section in `package.json` to control how your

where:
- `appIcon` is the path (relative to the `public` directory) to an image within the package to display in the webapp list. The image should be at least 72x72 pixels in size.
- `displayName` is the text you want to appear as the name in the webapp list. _(By default the _name_ attribute in the `package.json` is used.)_
- `displayName` is the text you want to appear as the name in the webapp list. _(By default the _name_ attribute in the `package.json` is used.)_. Displayname is also used in an automatic redirect from the root of the server: if you have a webapp with displayName `foo` and you access it using for example the url http://foo.bar.org:3000 the first part of the hostname matches the webapp's displayName and you will be redirected to it instead of the default landingPage, the Admin webapp. With this mechanism you can add easy to access DNS names to each webapp, including .local names.

See also [Working Offline](./developer_notes.md#offline-use).

Expand Down
13 changes: 13 additions & 0 deletions docs/src/features/datalogging/datalogging.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# Data Logging

Signal K server can log all input data from the configure input connections to a hourly data log files.

You can activate data logging for each connection by switching on Data Logging under Server / Data Connections, saving the connection settings. The setting takes effect after restarting the server.

The log files are downloadable in the Admin UI under Server / Server Logs.

The logs contain the data that the server has processed in the raw, original format (prior to conversion to Signal K) and each message is timestamped.

Log files can be used for archiving, to later play back the data or for debugging purposes. The server can play them back by creating a Data Connection with Data Type `File Stream` and secondary Data Type as `Multiplexed Log`.


8 changes: 4 additions & 4 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "signalk-server",
"version": "2.11.0",
"version": "2.12.0",
"description": "An implementation of a [Signal K](http://signalk.org) server for boats.",
"main": "index.js",
"scripts": {
Expand Down Expand Up @@ -74,9 +74,9 @@
"@signalk/course-provider": "^1.0.0",
"@signalk/n2k-signalk": "^3.0.0",
"@signalk/nmea0183-signalk": "^3.0.0",
"@signalk/resources-provider": "^1.0.0",
"@signalk/server-admin-ui": "2.10.x",
"@signalk/server-api": "2.4.x",
"@signalk/resources-provider": "^1.3.0",
"@signalk/server-admin-ui": "2.11.x",
"@signalk/server-api": "2.5.x",
"@signalk/signalk-schema": "^1.7.1",
"@signalk/streams": "^4.3.0",
"api-schema-builder": "^2.0.11",
Expand Down
4 changes: 2 additions & 2 deletions packages/resources-provider-plugin/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@signalk/resources-provider",
"version": "1.2.1",
"version": "1.3.0",
"description": "Resources provider plugin for Signal K server.",
"main": "plugin/index.js",
"keywords": [
Expand Down Expand Up @@ -33,7 +33,7 @@
"test": "npm run build && npm run build-declaration && npm run ci-lint"
},
"dependencies": {
"@signalk/server-api": "^2.1.0",
"@signalk/server-api": "^2.5.0",
"geojson-validation": "^0.2.0",
"geolib": "^3.3.3",
"ngeohash": "^0.6.3"
Expand Down
8 changes: 4 additions & 4 deletions packages/server-admin-ui/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@signalk/server-admin-ui",
"version": "2.10.0",
"version": "2.11.0",
"description": "Signal K server admin webapp",
"author": "Scott Bender, Teppo Kurki",
"contributors": [
Expand Down Expand Up @@ -38,7 +38,6 @@
"lodash.set": "^4.3.2",
"lodash.uniq": "^4.5.0",
"moment": "^2.29.1",
"node-sass": "^8.0.0",
"prettier": "^2.3.2",
"react": "^16.13.1",
"react-copy-to-clipboard": "^5.0.3",
Expand All @@ -53,10 +52,11 @@
"reconnecting-websocket": "^4.4.0",
"redux": "^3.7.2",
"redux-thunk": "2.3.0",
"sass-loader": "^13.2.0",
"sass": "^1.81.0",
"sass-loader": "^16.0.3",
"simple-line-icons": "^2.5.5",
"style-loader": "^2.0.0",
"webpack": "^5.0.0",
"webpack": "^5.96.1",
"webpack-bundle-analyzer": "^3.9.0",
"webpack-cli": "^4.2.0"
},
Expand Down
43 changes: 43 additions & 0 deletions packages/server-admin-ui/src/views/ServerConfig/Settings.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ class ServerSettings extends Component {
}
this.fetchSettings = fetchSettings.bind(this)
this.handleChange = this.handleChange.bind(this)
this.handleCourseApiChange = this.handleCourseApiChange.bind(this)
this.handleOptionChange = this.handleOptionChange.bind(this)
this.handleInterfaceChange = this.handleInterfaceChange.bind(this)
this.handleSaveSettings = this.handleSaveSettings.bind(this)
Expand All @@ -53,6 +54,15 @@ class ServerSettings extends Component {
this.setState({ [event.target.name]: value })
}

handleCourseApiChange(event) {
const value =
event.target.type === 'checkbox'
? event.target.checked
: event.target.value
this.state.courseApi[event.target.name] = value
this.setState({ courseApi: this.state.courseApi })
}

handleOptionChange(event) {
const value =
event.target.type === 'checkbox'
Expand Down Expand Up @@ -303,6 +313,39 @@ class ServerSettings extends Component {
</FormText>
</Col>
</FormGroup>
<FormGroup row>
<Col md="2">
<Label>
API Only Mode
<br />
<i>(Course API)</i>
</Label>
</Col>
<Col>
<FormGroup check>
<Label className="switch switch-text switch-primary">
<Input
type="checkbox"
name="apiOnly"
id="apiOnly"
className="switch-input"
onChange={this.handleCourseApiChange}
checked={this.state.courseApi.apiOnly}
/>
<span
className="switch-label"
data-on="On"
data-off="Off"
/>
<span className="switch-handle" />
</Label>
<FormText color="muted">
Accept course operations only via HTTP requests.
Destination data from NMEA sources is not used.
</FormText>
</FormGroup>
</Col>
</FormGroup>
</Form>
</CardBody>
<CardFooter>
Expand Down
26 changes: 25 additions & 1 deletion packages/server-admin-ui/src/views/appstore/Apps/Apps.js
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,22 @@ const Apps = function (props) {
</span>
)}
</Button>
{props.appStore.installing.length > 0 && (
<>
<Button
color={view === 'Installing' ? 'primary' : 'secondary'}
onClick={() => setSelectedView('Installing')}
>
Installs & Removes
{installingCount(props.appStore) > 0 && (
<span className="badge__update">
{installingCount(props.appStore)}
</span>
)}
</Button>
{props.appStore.installing.length > 0 && '(Pending restart)'}
</>
)}
</div>
</div>

Expand Down Expand Up @@ -176,11 +192,19 @@ const Apps = function (props) {
)
}

const installingCount = (appStore) => {
return appStore.installing.filter((app) => {
return app.isWaiting || app.isInstalling
}).length
}

const selectedViewToFilter = (selectedView, appStore) => {
if (selectedView === 'Installed') {
return (app) => app.installing || app.installedVersion
return (app) => app.installedVersion || app.installing
} else if (selectedView === 'Updates') {
return (app) => updateAvailable(app, appStore)
} else if (selectedView === 'Installing') {
return (app) => app.installing
}
return () => true
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,11 @@ function ActionCellRenderer(props) {
// If the app has progressed we show the status

if (app.isInstalling || app.isRemoving || app.isWaiting) {
status = app.isRemove ? 'Removing' : 'Installing'
status = app.isRemove
? 'Removing'
: app.isWaiting
? 'Waiting..'
: 'Installing'
progress = (
<Progress
className="progress-sm progress__bar"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,10 @@ export default function NameCellRenderer(props) {
<div className="cell__renderer cell-version center">
<div className="version__container">
<span className="version">
v{props.data.installedVersion || props.data.version}
v
{props.data.newVersion
? props.data.installedVersion
: props.data.version}
</span>

{/*
Expand Down
2 changes: 1 addition & 1 deletion packages/server-api/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@signalk/server-api",
"version": "2.4.0",
"version": "2.5.0",
"description": "signalk-server Typescript API for plugins etc with relevant implementation classes",
"main": "dist/index.js",
"types": "dist/index.d.ts",
Expand Down
8 changes: 8 additions & 0 deletions packages/server-api/src/deltas.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,14 @@ export type Update = {
$source?: SourceRef
} & ({ values: PathValue[] } | { meta: Meta[] }) // require either values or meta or both

export function hasValues(u: Update): u is Update & { values: PathValue[] } {
return 'values' in u && Array.isArray(u.values)
}

export function hasMeta(u: Update): u is Update & { meta: Meta[] } {
return 'meta' in u && Array.isArray(u.meta)
}

// Update delta
export interface PathValue {
path: Path
Expand Down
Loading

0 comments on commit 2caec45

Please sign in to comment.