@rhizomatics/signalk-einklabel-plugin 0.5.1 → 0.6.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +10 -0
- package/README.md +46 -4
- package/dist/render/assets.d.ts +15 -0
- package/dist/render/assets.js +33 -0
- package/dist/render/binding.d.ts +7 -3
- package/dist/render/binding.js +14 -9
- package/dist/render/svgRenderer.d.ts +8 -0
- package/dist/render/svgRenderer.js +47 -0
- package/docs/assets/screenshots/example_tidal_clock.png +0 -0
- package/package.json +6 -4
- package/resources/svg/lunar_phases/first_quarter.svg +51 -0
- package/resources/svg/lunar_phases/full_moon.svg +46 -0
- package/resources/svg/lunar_phases/new_moon.svg +43 -0
- package/resources/svg/lunar_phases/third_quarter.svg +52 -0
- package/resources/svg/lunar_phases/waning_crescent.svg +51 -0
- package/resources/svg/lunar_phases/waning_gibbous.svg +51 -0
- package/resources/svg/lunar_phases/waxing_crescent.svg +51 -0
- package/resources/svg/lunar_phases/waxing_gibbous.svg +51 -0
- package/templates/tide.svg +66 -80
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,13 @@
|
|
|
1
|
+
# 0.6.1
|
|
2
|
+
- Corrected tide lunar phase path from `environment.moonPhase.name` to `environment.moon.phaseName`
|
|
3
|
+
# 0.6.0
|
|
4
|
+
- Added ability to select images for inclusion in SVG templates based on SignalK path value
|
|
5
|
+
- Pass a directory of assets, and it will pick the SVG file matching the SignalK value
|
|
6
|
+
- Matching will cope with "Waning Gibbous" -> `waning_gibbous.svg`
|
|
7
|
+
- If no match, image will be blank
|
|
8
|
+
- New image selection used to add lunar phase to tide clock example
|
|
9
|
+
- Requires a source for `environment.moon.phaseName`, for example the `dervived-data` plugin
|
|
10
|
+
- New `resources` directory for composable SVG assets
|
|
1
11
|
# 0.5.1
|
|
2
12
|
- Work around `resvg-wasm` font limitations by overriding generic font family with matching font name prior to rendering
|
|
3
13
|
# 0.5.0
|
package/README.md
CHANGED
|
@@ -1,15 +1,42 @@
|
|
|
1
1
|
# eInk Labels for SignalK
|
|
2
2
|
|
|
3
|
-
**
|
|
3
|
+
** Fully working but limited vendor/product support **
|
|
4
4
|
|
|
5
|
-
A SignalK plugin to display data from SignalK paths, APIs and plugins on Electronic Shelf Labels over a Bluetooth Low Energy (BLE) connection using simple SVG templates.
|
|
5
|
+
A SignalK plugin to display data from SignalK paths, APIs and plugins on Electronic Shelf Labels (ESL) over a Bluetooth Low Energy (BLE) connection using simple SVG templates.
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
## What is an ESL?
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
Electronic Shelf Labels are [eInk](https://en.wikipedia.org/wiki/E_Ink) devices that consume very little battery energy, presuming they are not constantly updated - the battery is used only when the display changes, and a periodic BLE check for incoming changes. Perfect for info that changes only once or twice a day, like tidal information.
|
|
10
|
+
|
|
11
|
+
Since they are designed to be used in large quantity in small shops, they are cheap and simple devices. Earlier models required dedicated controllers, or updates over Wifi or NFC, whereas many modern ones are standalone BLE devices that can be updated from a phone or server.
|
|
12
|
+
|
|
13
|
+
Being battery operated, they can be stuck on anywhere without wiring - the only constraints are bluetooth range, visibility (they need ambient light since the display is more like paper than a traditional lit-up electronic display) and out of the weather since the devices are intended for indoor use.
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
## Pre-requisites
|
|
10
17
|
|
|
11
18
|
Unlike some eInk projects, this plugin doesn't require any physical modification to the labels, or loading any new firmware. It can send an image to a supported shelf label fresh out of the box.
|
|
12
19
|
|
|
20
|
+
Most of these requirements are about making SignalK work with Bluetooth Low Energy, which is good thing to have anyway, since vendors like Victron, Switchbot, Ruuvi and others have BLE enabled hardware that's useful to have on a boat. [Direct BLE support](https://github.com/SignalK/signalk-server/issues/2411) in SignalK is being planned in 2026.
|
|
21
|
+
|
|
22
|
+
1. A SignalK server, preferably running Linux (MacOS does weird things with bluetooth)
|
|
23
|
+
2. A Bluetooth adapter, that can handle BLE (Bluetooth Low Energy), which is Bluetooth v4.0 or higher
|
|
24
|
+
- Bluetooth adapters for Linux can be tricky, TP-Link UB400 and Asus USB-BT500 are two well-known and available ones
|
|
25
|
+
- Some Raspberry Pi models come with suitable Bluetooth it built-in
|
|
26
|
+
- Don't worry about the very latest Bluetooth versions, 4.0 is basic, 5.0 is nice
|
|
27
|
+
- Home Assistant is massively more popular than SignalK, and often also run on Raspberry Pi and similar, so good source of advice
|
|
28
|
+
3. `bluez` package installed in Linux
|
|
29
|
+
- No need to do this if you have a Raspberry Pi with recent Raspian version, since bluez comes built in.
|
|
30
|
+
- If you're not running a Raspberry Pi, then ensure that the `dbus` package is installed
|
|
31
|
+
4. One or more supported Electronic Shelf Labels
|
|
32
|
+
- The label used for testing this is the [ZhunyCo 3.7 BRWY](https://www.aliexpress.com/item/1005010050104435.html)
|
|
33
|
+
5. Correct time zone set on server if local time is to be shown on display
|
|
34
|
+
- Use `raspi-config` on a Raspberry Pi, or `timedatectl` on a Linux server
|
|
35
|
+
- If not set, everything will work, but you may see the wrong zone or not have daylight savings applied
|
|
36
|
+
|
|
37
|
+
Once you have all of that, it may be worth also installing [signalk-victron-ble](https://github.com/stefanor/signalk-victron-ble) or [bt-sensors-plugin](https://github.com/naugehyde/bt-sensors-plugin-sk) to pull in data from other sensors and equipment.
|
|
38
|
+
|
|
39
|
+
|
|
13
40
|
## Installation
|
|
14
41
|
|
|
15
42
|
Look for **eInk Label Instrument** in the [SignalK AppStore]() on your
|
|
@@ -31,6 +58,9 @@ npm install @rhizomatics/signalk-einklabel-plugin
|
|
|
31
58
|
|
|
32
59
|
The tide clock needs the [signalk-tides](https://github.com/openwatersio/signalk-tides) plugin to be installed and publishing tides to the Resources API. The [tide.svg](https://github.com/rhizomatics/signalk-einklabel-plugin/blob/main/templates/tide.svg) can be customized to run with other APIs or take data only from SignalK data paths.
|
|
33
60
|
|
|
61
|
+
To show the lunar phase, the `environment.moon.phaseName` path is required, which can
|
|
62
|
+
be easily achieved by installing and configuring the `derived-data` plugin.
|
|
63
|
+
|
|
34
64
|
## Templating
|
|
35
65
|
|
|
36
66
|
Templates are simply SVG files, to which expressions can be added to use SignalK data, with options to make it easier to read, like rounding or simplifying dates and times. The template can have sample data in the placeholder, so is easy to layout and visualize.
|
|
@@ -79,6 +109,18 @@ Additionally, `round=n` can be used to round to limited decimal places.
|
|
|
79
109
|
|
|
80
110
|
These can all be combined as in `source=resources,resource=tides,path=extremes[2].level,category=depth,round=2`
|
|
81
111
|
|
|
112
|
+
### Non-Textual Fields (Images)
|
|
113
|
+
|
|
114
|
+
The same `<desc>` mechanism works on an `<image>` element instead of a `<text>` element, for a value that's better shown as a picture than as text - a moon phase icon, a wind direction arrow, a weather condition glyph, and so on. Rather than substituting text, the resolved value picks one of a directory of `.svg` files to embed, by an extra required `assets=` key naming that directory (resolved relative to the template file itself, so a bundled template and a user override both work the same way). For example, the tide clock's moon phase icon uses:
|
|
115
|
+
|
|
116
|
+
```
|
|
117
|
+
path=environment.moon.phaseName,assets=../resources/svg/lunar_phases
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
The resolved value (e.g. `"Waning Gibbous"`, as published by the [derived-data](https://www.npmjs.com/package/signalk-derived-data) plugin) is normalized to match a filename - lower-cased, punctuation and spaces collapsed to underscores - so `"Waning Gibbous"` picks `waning_gibbous.svg` out of that directory. If the underlying path has no value at all (e.g. the `derived-data` plugin isn't installed), or the value doesn't normalize to any file in the directory, the `<image>` element is simply omitted from that render - no broken image, no placeholder, nothing shown.
|
|
121
|
+
|
|
122
|
+
This is a general mechanism, not specific to moon phases - any `source`/`context`/`path`/`format` combination valid for a `<text>` binding works here too (a `source=resources` value, an explicit `category=`, etc.), the only difference is the required `assets=` directory and the "no match -> no image" behaviour instead of substituted text. To add your own, put a directory of `<value>.svg` files somewhere relative to your template, add an `<image>` element in your SVG editor at the size/position you want, and give it a `<desc>` the same way you would a text field.
|
|
123
|
+
|
|
82
124
|
### Fonts
|
|
83
125
|
|
|
84
126
|
Three font types are loaded by default, use the generic font family, or exact font name, in the SVG editor and choose size and weight (bold, semi-bold etc). Some labels will make a decent attempt to gray scale. Use the simple pure red, yellow, white, black to match the label's limited colour choice (some labels only offer black and white, or black/white/red). If a font can't be matched it will default to (sans-serif) Roboto.
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Turns a resolved binding value into a filename stem, e.g. `"Waning Gibbous"` -> `"waning_gibbous"` -
|
|
3
|
+
* so a `signalk`/`resources` value using SignalK's own display casing (title case, spaces) can match a
|
|
4
|
+
* file named the conventional snake_case way. Returns `undefined` for anything that can't sensibly name
|
|
5
|
+
* a file (non-string, empty, or all-punctuation), which callers treat as "no image".
|
|
6
|
+
*/
|
|
7
|
+
export declare function normalizeAssetKey(value: unknown): string | undefined;
|
|
8
|
+
/**
|
|
9
|
+
* Resolves an `assets=` binding to an actual `.svg` file, looked up as `<key>.svg` inside `assetsDir`
|
|
10
|
+
* resolved relative to the template's own directory (mirroring how a bundled template's relative asset
|
|
11
|
+
* references keep working whether the template itself is the bundled copy or a user override elsewhere) -
|
|
12
|
+
* `undefined` if no matching file exists, which callers treat as "no image" rather than an error, since an
|
|
13
|
+
* unmapped value (e.g. a phase name the asset set doesn't cover) is an expected, not exceptional, case.
|
|
14
|
+
*/
|
|
15
|
+
export declare function resolveAssetPath(templatePath: string, assetsDir: string, key: string): string | undefined;
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.normalizeAssetKey = normalizeAssetKey;
|
|
4
|
+
exports.resolveAssetPath = resolveAssetPath;
|
|
5
|
+
const fs_1 = require("fs");
|
|
6
|
+
const path_1 = require("path");
|
|
7
|
+
/**
|
|
8
|
+
* Turns a resolved binding value into a filename stem, e.g. `"Waning Gibbous"` -> `"waning_gibbous"` -
|
|
9
|
+
* so a `signalk`/`resources` value using SignalK's own display casing (title case, spaces) can match a
|
|
10
|
+
* file named the conventional snake_case way. Returns `undefined` for anything that can't sensibly name
|
|
11
|
+
* a file (non-string, empty, or all-punctuation), which callers treat as "no image".
|
|
12
|
+
*/
|
|
13
|
+
function normalizeAssetKey(value) {
|
|
14
|
+
if (typeof value !== 'string')
|
|
15
|
+
return undefined;
|
|
16
|
+
const normalized = value
|
|
17
|
+
.trim()
|
|
18
|
+
.toLowerCase()
|
|
19
|
+
.replace(/[^a-z0-9]+/g, '_')
|
|
20
|
+
.replace(/^_+|_+$/g, '');
|
|
21
|
+
return normalized || undefined;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Resolves an `assets=` binding to an actual `.svg` file, looked up as `<key>.svg` inside `assetsDir`
|
|
25
|
+
* resolved relative to the template's own directory (mirroring how a bundled template's relative asset
|
|
26
|
+
* references keep working whether the template itself is the bundled copy or a user override elsewhere) -
|
|
27
|
+
* `undefined` if no matching file exists, which callers treat as "no image" rather than an error, since an
|
|
28
|
+
* unmapped value (e.g. a phase name the asset set doesn't cover) is an expected, not exceptional, case.
|
|
29
|
+
*/
|
|
30
|
+
function resolveAssetPath(templatePath, assetsDir, key) {
|
|
31
|
+
const candidate = (0, path_1.join)((0, path_1.dirname)(templatePath), assetsDir, `${key}.svg`);
|
|
32
|
+
return (0, fs_1.existsSync)(candidate) ? candidate : undefined;
|
|
33
|
+
}
|
package/dist/render/binding.d.ts
CHANGED
|
@@ -17,6 +17,8 @@ export interface Binding {
|
|
|
17
17
|
/** Explicit unit-preferences category (e.g. `depth`, `speed`, `temperature`) for a numeric value with no path metadata of its own, e.g. a `source=resources` value - see `../unitCategories.ts`. */
|
|
18
18
|
category?: string;
|
|
19
19
|
round?: number;
|
|
20
|
+
/** Only meaningful on an `<image>` element's binding (see `SvgRenderer`) - a directory, resolved relative to the template file, of `<value>.svg` files to pick from by the resolved value (see `../assets.ts`'s `normalizeAssetKey`). */
|
|
21
|
+
assets?: string;
|
|
20
22
|
}
|
|
21
23
|
/**
|
|
22
24
|
* Parses a `<desc>` element's text content into a `Binding`, e.g.
|
|
@@ -29,9 +31,11 @@ export interface Binding {
|
|
|
29
31
|
*/
|
|
30
32
|
export declare function parseBinding(desc: string): Binding;
|
|
31
33
|
/**
|
|
32
|
-
* Parses every `<text>` element's `<desc>` binding out of raw SVG source - lets a caller
|
|
33
|
-
* data a template needs before fetching anything, with no separate config declaring it
|
|
34
|
-
* `assembleRawContext` in repaintScheduler.ts).
|
|
34
|
+
* Parses every `<text>` and `<image>` element's `<desc>` binding out of raw SVG source - lets a caller
|
|
35
|
+
* discover what data a template needs before fetching anything, with no separate config declaring it
|
|
36
|
+
* (see `assembleRawContext` in repaintScheduler.ts). `<image>` bindings (see `SvgRenderer`) resolve to a
|
|
37
|
+
* picked asset file rather than substituted text, but still need their underlying value fetched the same
|
|
38
|
+
* way as a `<text>` binding.
|
|
35
39
|
*/
|
|
36
40
|
export declare function findBindings(svgSource: string): Binding[];
|
|
37
41
|
/** Resolves a parsed `Binding` against the render context assembled by `assembleRawContext`. */
|
package/dist/render/binding.js
CHANGED
|
@@ -7,7 +7,7 @@ exports.renderBinding = renderBinding;
|
|
|
7
7
|
const xmldom_1 = require("@xmldom/xmldom");
|
|
8
8
|
const formatters_1 = require("./formatters");
|
|
9
9
|
const SOURCES = ['signalk', 'resources', 'einklabel'];
|
|
10
|
-
const KNOWN_KEYS = new Set(['source', 'context', 'resource', 'path', 'format', 'category', 'round']);
|
|
10
|
+
const KNOWN_KEYS = new Set(['source', 'context', 'resource', 'path', 'format', 'category', 'round', 'assets']);
|
|
11
11
|
/**
|
|
12
12
|
* Parses a `<desc>` element's text content into a `Binding`, e.g.
|
|
13
13
|
* `source=resources,resource=tides,path=extremes[0].level,category=depth,round=2` or, using the
|
|
@@ -56,21 +56,26 @@ function parseBinding(desc) {
|
|
|
56
56
|
format: fields.format,
|
|
57
57
|
category: fields.category,
|
|
58
58
|
round: fields.round !== undefined ? Number(fields.round) : undefined,
|
|
59
|
+
assets: fields.assets,
|
|
59
60
|
};
|
|
60
61
|
}
|
|
61
62
|
/**
|
|
62
|
-
* Parses every `<text>` element's `<desc>` binding out of raw SVG source - lets a caller
|
|
63
|
-
* data a template needs before fetching anything, with no separate config declaring it
|
|
64
|
-
* `assembleRawContext` in repaintScheduler.ts).
|
|
63
|
+
* Parses every `<text>` and `<image>` element's `<desc>` binding out of raw SVG source - lets a caller
|
|
64
|
+
* discover what data a template needs before fetching anything, with no separate config declaring it
|
|
65
|
+
* (see `assembleRawContext` in repaintScheduler.ts). `<image>` bindings (see `SvgRenderer`) resolve to a
|
|
66
|
+
* picked asset file rather than substituted text, but still need their underlying value fetched the same
|
|
67
|
+
* way as a `<text>` binding.
|
|
65
68
|
*/
|
|
66
69
|
function findBindings(svgSource) {
|
|
67
70
|
const doc = new xmldom_1.DOMParser().parseFromString(svgSource, 'image/svg+xml');
|
|
68
|
-
const elements = doc.getElementsByTagName('text');
|
|
69
71
|
const bindings = [];
|
|
70
|
-
for (
|
|
71
|
-
const
|
|
72
|
-
|
|
73
|
-
|
|
72
|
+
for (const tagName of ['text', 'image']) {
|
|
73
|
+
const elements = doc.getElementsByTagName(tagName);
|
|
74
|
+
for (let i = 0; i < elements.length; i++) {
|
|
75
|
+
const desc = elements.item(i)?.getElementsByTagName('desc').item(0);
|
|
76
|
+
if (desc?.textContent) {
|
|
77
|
+
bindings.push(parseBinding(desc.textContent));
|
|
78
|
+
}
|
|
74
79
|
}
|
|
75
80
|
}
|
|
76
81
|
return bindings;
|
|
@@ -16,6 +16,14 @@ import { Bitmap, Renderer, TemplateContext } from './types';
|
|
|
16
16
|
* `getElementsByTagName` is a live NodeList, so that previously truncated the
|
|
17
17
|
* whole tree and rendered blank.
|
|
18
18
|
*
|
|
19
|
+
* Non-textual inclusion: an `<image>` element with a `<desc>` child works the same way, except the
|
|
20
|
+
* resolved value picks one of a directory of `.svg` files (an `assets=` key, required, names that
|
|
21
|
+
* directory - see `./assets.ts`) rather than substituting text, and the element is dropped entirely
|
|
22
|
+
* (rather than showing an error placeholder) whenever the value is unavailable or doesn't map to a
|
|
23
|
+
* file - e.g. a device without the `derived-data` plugin installed simply shows no moon-phase icon.
|
|
24
|
+
* The matched file's contents are inlined as a `data:image/svg+xml;base64,...` URI so no filesystem
|
|
25
|
+
* access happens at resvg-wasm's render step.
|
|
26
|
+
*
|
|
19
27
|
* resvg-wasm cannot see the host's installed fonts (`loadSystemFonts`/`fontFiles`
|
|
20
28
|
* are silently no-ops under plain Node) - it only renders text if given font
|
|
21
29
|
* bytes directly via `fontBuffers`, read from disk by us. Without at least one
|
|
@@ -5,6 +5,7 @@ const promises_1 = require("fs/promises");
|
|
|
5
5
|
const xmldom_1 = require("@xmldom/xmldom");
|
|
6
6
|
const resvg_wasm_1 = require("@resvg/resvg-wasm");
|
|
7
7
|
const binding_1 = require("./binding");
|
|
8
|
+
const assets_1 = require("./assets");
|
|
8
9
|
const fonts_1 = require("./fonts");
|
|
9
10
|
let wasmReady;
|
|
10
11
|
function ensureWasmInitialized() {
|
|
@@ -51,6 +52,14 @@ function expandGenericFontFamilies(svgSource) {
|
|
|
51
52
|
* `getElementsByTagName` is a live NodeList, so that previously truncated the
|
|
52
53
|
* whole tree and rendered blank.
|
|
53
54
|
*
|
|
55
|
+
* Non-textual inclusion: an `<image>` element with a `<desc>` child works the same way, except the
|
|
56
|
+
* resolved value picks one of a directory of `.svg` files (an `assets=` key, required, names that
|
|
57
|
+
* directory - see `./assets.ts`) rather than substituting text, and the element is dropped entirely
|
|
58
|
+
* (rather than showing an error placeholder) whenever the value is unavailable or doesn't map to a
|
|
59
|
+
* file - e.g. a device without the `derived-data` plugin installed simply shows no moon-phase icon.
|
|
60
|
+
* The matched file's contents are inlined as a `data:image/svg+xml;base64,...` URI so no filesystem
|
|
61
|
+
* access happens at resvg-wasm's render step.
|
|
62
|
+
*
|
|
54
63
|
* resvg-wasm cannot see the host's installed fonts (`loadSystemFonts`/`fontFiles`
|
|
55
64
|
* are silently no-ops under plain Node) - it only renders text if given font
|
|
56
65
|
* bytes directly via `fontBuffers`, read from disk by us. Without at least one
|
|
@@ -94,6 +103,44 @@ class SvgRenderer {
|
|
|
94
103
|
element.textContent = 'ERROR';
|
|
95
104
|
}
|
|
96
105
|
}
|
|
106
|
+
// Collected up front, rather than iterated live like the `<text>` loop above - some of these get
|
|
107
|
+
// removed outright (see below), and removing from a live NodeList while iterating it by index would
|
|
108
|
+
// skip whatever shifts into the removed slot.
|
|
109
|
+
const imageElements = [];
|
|
110
|
+
const rawImageElements = doc.getElementsByTagName('image');
|
|
111
|
+
for (let i = 0; i < rawImageElements.length; i++) {
|
|
112
|
+
const element = rawImageElements.item(i);
|
|
113
|
+
if (element)
|
|
114
|
+
imageElements.push(element);
|
|
115
|
+
}
|
|
116
|
+
for (const element of imageElements) {
|
|
117
|
+
const descElement = element.getElementsByTagName('desc').item(0);
|
|
118
|
+
if (!descElement)
|
|
119
|
+
continue;
|
|
120
|
+
// Same one-field-at-a-time isolation as the `<text>` loop - and the same "no value" outcome
|
|
121
|
+
// (here, dropping the element rather than blanking to 'ERROR' text) for a value that isn't
|
|
122
|
+
// available at all as for one that doesn't map to any asset file, per the binding's contract.
|
|
123
|
+
try {
|
|
124
|
+
const binding = (0, binding_1.parseBinding)(descElement.textContent ?? '');
|
|
125
|
+
if (!binding.assets) {
|
|
126
|
+
throw new Error('an <image> binding requires an "assets" key naming the directory to pick a file from');
|
|
127
|
+
}
|
|
128
|
+
const key = (0, assets_1.normalizeAssetKey)((0, binding_1.resolveBinding)(binding, context));
|
|
129
|
+
const assetPath = key && (0, assets_1.resolveAssetPath)(svgTemplatePath, binding.assets, key);
|
|
130
|
+
if (!assetPath) {
|
|
131
|
+
element.parentNode?.removeChild(element);
|
|
132
|
+
continue;
|
|
133
|
+
}
|
|
134
|
+
const assetSource = await (0, promises_1.readFile)(assetPath, 'utf-8');
|
|
135
|
+
const dataUri = `data:image/svg+xml;base64,${Buffer.from(assetSource).toString('base64')}`;
|
|
136
|
+
const hrefAttr = element.getAttribute('href') !== null ? 'href' : 'xlink:href';
|
|
137
|
+
element.setAttribute(hrefAttr, dataUri);
|
|
138
|
+
}
|
|
139
|
+
catch (err) {
|
|
140
|
+
console.error(`image "${descElement.textContent}" failed to render: ${err.message}`);
|
|
141
|
+
element.parentNode?.removeChild(element);
|
|
142
|
+
}
|
|
143
|
+
}
|
|
97
144
|
const svgOutput = new xmldom_1.XMLSerializer().serializeToString(doc);
|
|
98
145
|
const resvg = new resvg_wasm_1.Resvg(svgOutput, {
|
|
99
146
|
fitTo: { mode: 'width', value: width },
|
|
Binary file
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rhizomatics/signalk-einklabel-plugin",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "
|
|
3
|
+
"version": "0.6.1",
|
|
4
|
+
"description": "Display SignalK data on eInk Electronic Shelf Labels",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
7
7
|
"bin": {
|
|
@@ -10,6 +10,7 @@
|
|
|
10
10
|
"files": [
|
|
11
11
|
"dist",
|
|
12
12
|
"templates",
|
|
13
|
+
"resources",
|
|
13
14
|
"docs",
|
|
14
15
|
"CHANGELOG.md",
|
|
15
16
|
"README.md"
|
|
@@ -22,7 +23,7 @@
|
|
|
22
23
|
"prepublishOnly": "npm run build"
|
|
23
24
|
},
|
|
24
25
|
"signalk": {
|
|
25
|
-
"displayName": "eInk Label
|
|
26
|
+
"displayName": "eInk Label Displays",
|
|
26
27
|
"appIcon": "docs/assets/icons/icon_tmp.png",
|
|
27
28
|
"screenshots": [
|
|
28
29
|
"docs/assets/screenshots/example_tidal_clock.png"
|
|
@@ -37,7 +38,8 @@
|
|
|
37
38
|
"esl",
|
|
38
39
|
"display",
|
|
39
40
|
"instrument",
|
|
40
|
-
"ble"
|
|
41
|
+
"ble",
|
|
42
|
+
"tides"
|
|
41
43
|
],
|
|
42
44
|
"engines": {
|
|
43
45
|
"node": ">=18"
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
|
2
|
+
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
|
3
|
+
|
|
4
|
+
<svg
|
|
5
|
+
version="1.0"
|
|
6
|
+
width="400"
|
|
7
|
+
height="400"
|
|
8
|
+
id="svg2"
|
|
9
|
+
sodipodi:docname="first_quarter.svg"
|
|
10
|
+
inkscape:version="1.3.2 (091e20e, 2023-11-25)"
|
|
11
|
+
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
|
12
|
+
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
|
13
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
14
|
+
xmlns:svg="http://www.w3.org/2000/svg">
|
|
15
|
+
<sodipodi:namedview
|
|
16
|
+
id="namedview1"
|
|
17
|
+
pagecolor="#ffffff"
|
|
18
|
+
bordercolor="#000000"
|
|
19
|
+
borderopacity="0.25"
|
|
20
|
+
inkscape:showpageshadow="2"
|
|
21
|
+
inkscape:pageopacity="0.0"
|
|
22
|
+
inkscape:pagecheckerboard="0"
|
|
23
|
+
inkscape:deskcolor="#d1d1d1"
|
|
24
|
+
inkscape:zoom="0.59"
|
|
25
|
+
inkscape:cx="200.84746"
|
|
26
|
+
inkscape:cy="200"
|
|
27
|
+
inkscape:window-width="1312"
|
|
28
|
+
inkscape:window-height="449"
|
|
29
|
+
inkscape:window-x="0"
|
|
30
|
+
inkscape:window-y="33"
|
|
31
|
+
inkscape:window-maximized="0"
|
|
32
|
+
inkscape:current-layer="svg2" />
|
|
33
|
+
<defs
|
|
34
|
+
id="defs4" />
|
|
35
|
+
<g
|
|
36
|
+
id="layer2">
|
|
37
|
+
<path
|
|
38
|
+
d="M 749.07161 200.5305 A 168.70027 168.70027 0 1 1 411.67107,200.5305 A 168.70027 168.70027 0 1 1 749.07161 200.5305 z"
|
|
39
|
+
transform="translate(-380.37134,-0.5305023)"
|
|
40
|
+
style="fill:#000000;fill-opacity:1;stroke:none;stroke-width:3.54330707;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
|
41
|
+
id="path6166" />
|
|
42
|
+
</g>
|
|
43
|
+
<g
|
|
44
|
+
id="layer3"
|
|
45
|
+
style="fill:#ffff00">
|
|
46
|
+
<path
|
|
47
|
+
d="M 199.86125,368.70045 C 292.83638,368.70045 368.20758,293.17071 368.20758,199.99995 C 368.20758,106.82922 292.83638,31.29945 199.86125,31.29945 C 199.12886,143.76656 199.72222,256.23321 199.86125,368.70045 z "
|
|
48
|
+
style="fill:#ffff00;fill-opacity:1;stroke:none"
|
|
49
|
+
id="path7307" />
|
|
50
|
+
</g>
|
|
51
|
+
</svg>
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
|
2
|
+
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
|
3
|
+
|
|
4
|
+
<svg
|
|
5
|
+
version="1.0"
|
|
6
|
+
width="400"
|
|
7
|
+
height="400"
|
|
8
|
+
id="svg2"
|
|
9
|
+
sodipodi:docname="full_moon.svg"
|
|
10
|
+
inkscape:version="1.3.2 (091e20e, 2023-11-25)"
|
|
11
|
+
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
|
12
|
+
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
|
13
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
14
|
+
xmlns:svg="http://www.w3.org/2000/svg">
|
|
15
|
+
<sodipodi:namedview
|
|
16
|
+
id="namedview1"
|
|
17
|
+
pagecolor="#ffffff"
|
|
18
|
+
bordercolor="#000000"
|
|
19
|
+
borderopacity="0.25"
|
|
20
|
+
inkscape:showpageshadow="2"
|
|
21
|
+
inkscape:pageopacity="0.0"
|
|
22
|
+
inkscape:pagecheckerboard="0"
|
|
23
|
+
inkscape:deskcolor="#d1d1d1"
|
|
24
|
+
inkscape:zoom="0.59"
|
|
25
|
+
inkscape:cx="200.84746"
|
|
26
|
+
inkscape:cy="200"
|
|
27
|
+
inkscape:window-width="1312"
|
|
28
|
+
inkscape:window-height="449"
|
|
29
|
+
inkscape:window-x="0"
|
|
30
|
+
inkscape:window-y="33"
|
|
31
|
+
inkscape:window-maximized="0"
|
|
32
|
+
inkscape:current-layer="svg2" />
|
|
33
|
+
<defs
|
|
34
|
+
id="defs4" />
|
|
35
|
+
<g
|
|
36
|
+
id="layer2"
|
|
37
|
+
style="fill:#ffff00">
|
|
38
|
+
<path
|
|
39
|
+
d="M 749.07161 200.5305 A 168.70027 168.70027 0 1 1 411.67107,200.5305 A 168.70027 168.70027 0 1 1 749.07161 200.5305 z"
|
|
40
|
+
transform="translate(-380.37134,-0.5305023)"
|
|
41
|
+
style="fill:#ffff00;fill-opacity:1;stroke:none;stroke-width:3.54330707;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
|
42
|
+
id="path6166" />
|
|
43
|
+
</g>
|
|
44
|
+
<g
|
|
45
|
+
id="layer3" />
|
|
46
|
+
</svg>
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
|
2
|
+
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
|
3
|
+
|
|
4
|
+
<svg
|
|
5
|
+
version="1.0"
|
|
6
|
+
width="400"
|
|
7
|
+
height="400"
|
|
8
|
+
id="svg2"
|
|
9
|
+
sodipodi:docname="new_moon.svg"
|
|
10
|
+
inkscape:version="1.3.2 (091e20e, 2023-11-25)"
|
|
11
|
+
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
|
12
|
+
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
|
13
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
14
|
+
xmlns:svg="http://www.w3.org/2000/svg">
|
|
15
|
+
<sodipodi:namedview
|
|
16
|
+
id="namedview1"
|
|
17
|
+
pagecolor="#ffffff"
|
|
18
|
+
bordercolor="#000000"
|
|
19
|
+
borderopacity="0.25"
|
|
20
|
+
inkscape:showpageshadow="2"
|
|
21
|
+
inkscape:pageopacity="0.0"
|
|
22
|
+
inkscape:pagecheckerboard="0"
|
|
23
|
+
inkscape:deskcolor="#d1d1d1"
|
|
24
|
+
inkscape:zoom="0.59"
|
|
25
|
+
inkscape:cx="200.84746"
|
|
26
|
+
inkscape:cy="200"
|
|
27
|
+
inkscape:window-width="1312"
|
|
28
|
+
inkscape:window-height="449"
|
|
29
|
+
inkscape:window-x="0"
|
|
30
|
+
inkscape:window-y="33"
|
|
31
|
+
inkscape:window-maximized="0"
|
|
32
|
+
inkscape:current-layer="svg2" />
|
|
33
|
+
<defs
|
|
34
|
+
id="defs4" />
|
|
35
|
+
<g
|
|
36
|
+
id="layer2">
|
|
37
|
+
<path
|
|
38
|
+
d="M 749.07161 200.5305 A 168.70027 168.70027 0 1 1 411.67107,200.5305 A 168.70027 168.70027 0 1 1 749.07161 200.5305 z"
|
|
39
|
+
transform="translate(-380.37134,-0.5305023)"
|
|
40
|
+
style="fill:#000000;fill-opacity:1;stroke:none;stroke-width:3.54330707;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
|
41
|
+
id="path6166" />
|
|
42
|
+
</g>
|
|
43
|
+
</svg>
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
|
2
|
+
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
|
3
|
+
|
|
4
|
+
<svg
|
|
5
|
+
version="1.0"
|
|
6
|
+
width="400"
|
|
7
|
+
height="400"
|
|
8
|
+
id="svg2"
|
|
9
|
+
sodipodi:docname="third_quarter.svg"
|
|
10
|
+
inkscape:version="1.3.2 (091e20e, 2023-11-25)"
|
|
11
|
+
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
|
12
|
+
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
|
13
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
14
|
+
xmlns:svg="http://www.w3.org/2000/svg">
|
|
15
|
+
<sodipodi:namedview
|
|
16
|
+
id="namedview1"
|
|
17
|
+
pagecolor="#ffffff"
|
|
18
|
+
bordercolor="#000000"
|
|
19
|
+
borderopacity="0.25"
|
|
20
|
+
inkscape:showpageshadow="2"
|
|
21
|
+
inkscape:pageopacity="0.0"
|
|
22
|
+
inkscape:pagecheckerboard="0"
|
|
23
|
+
inkscape:deskcolor="#d1d1d1"
|
|
24
|
+
inkscape:zoom="0.59"
|
|
25
|
+
inkscape:cx="200.84746"
|
|
26
|
+
inkscape:cy="200"
|
|
27
|
+
inkscape:window-width="1312"
|
|
28
|
+
inkscape:window-height="449"
|
|
29
|
+
inkscape:window-x="0"
|
|
30
|
+
inkscape:window-y="33"
|
|
31
|
+
inkscape:window-maximized="0"
|
|
32
|
+
inkscape:current-layer="svg2" />
|
|
33
|
+
<defs
|
|
34
|
+
id="defs4" />
|
|
35
|
+
<g
|
|
36
|
+
id="layer2">
|
|
37
|
+
<path
|
|
38
|
+
d="M 749.07161,200.5305 C 749.07161,293.70109 673.54193,369.23077 580.37134,369.23077 C 487.20075,369.23077 411.67107,293.70109 411.67107,200.5305 C 411.67107,107.35991 487.20075,31.83023 580.37134,31.83023 C 673.54193,31.83023 749.07161,107.35991 749.07161,200.5305 z "
|
|
39
|
+
transform="translate(-380.37134,-0.5305023)"
|
|
40
|
+
style="fill:#000000;fill-opacity:1;stroke:none;stroke-width:3.54330707;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
|
41
|
+
id="path6166" />
|
|
42
|
+
</g>
|
|
43
|
+
<g
|
|
44
|
+
transform="matrix(-1,0,0,1,399.50816,0)"
|
|
45
|
+
id="layer3"
|
|
46
|
+
style="fill:#ffff00">
|
|
47
|
+
<path
|
|
48
|
+
d="M 199.86125,368.70045 C 292.83638,368.70045 368.20758,293.17071 368.20758,199.99995 C 368.20758,106.82922 292.83638,31.29945 199.86125,31.29945 C 199.12886,143.76656 199.72222,256.23321 199.86125,368.70045 z "
|
|
49
|
+
style="fill:#ffff00;fill-opacity:1;stroke:none"
|
|
50
|
+
id="path7307" />
|
|
51
|
+
</g>
|
|
52
|
+
</svg>
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
|
2
|
+
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
|
3
|
+
|
|
4
|
+
<svg
|
|
5
|
+
version="1.0"
|
|
6
|
+
width="400"
|
|
7
|
+
height="400"
|
|
8
|
+
id="svg2"
|
|
9
|
+
sodipodi:docname="waning_crescent.svg"
|
|
10
|
+
inkscape:version="1.3.2 (091e20e, 2023-11-25)"
|
|
11
|
+
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
|
12
|
+
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
|
13
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
14
|
+
xmlns:svg="http://www.w3.org/2000/svg">
|
|
15
|
+
<sodipodi:namedview
|
|
16
|
+
id="namedview1"
|
|
17
|
+
pagecolor="#ffffff"
|
|
18
|
+
bordercolor="#000000"
|
|
19
|
+
borderopacity="0.25"
|
|
20
|
+
inkscape:showpageshadow="2"
|
|
21
|
+
inkscape:pageopacity="0.0"
|
|
22
|
+
inkscape:pagecheckerboard="0"
|
|
23
|
+
inkscape:deskcolor="#d1d1d1"
|
|
24
|
+
inkscape:zoom="0.59"
|
|
25
|
+
inkscape:cx="200.84746"
|
|
26
|
+
inkscape:cy="200"
|
|
27
|
+
inkscape:window-width="1312"
|
|
28
|
+
inkscape:window-height="449"
|
|
29
|
+
inkscape:window-x="0"
|
|
30
|
+
inkscape:window-y="33"
|
|
31
|
+
inkscape:window-maximized="0"
|
|
32
|
+
inkscape:current-layer="svg2" />
|
|
33
|
+
<defs
|
|
34
|
+
id="defs4" />
|
|
35
|
+
<g
|
|
36
|
+
id="layer2">
|
|
37
|
+
<path
|
|
38
|
+
d="M 749.07161,200.5305 C 749.07161,293.70109 673.54193,369.23077 580.37134,369.23077 C 487.20075,369.23077 411.67107,293.70109 411.67107,200.5305 C 411.67107,107.35991 487.20075,31.83023 580.37134,31.83023 C 673.54193,31.83023 749.07161,107.35991 749.07161,200.5305 z "
|
|
39
|
+
transform="translate(-380.37134,-0.5305023)"
|
|
40
|
+
style="fill:#00000f;fill-opacity:0.94117647;stroke:none;stroke-width:3.54330707;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
|
41
|
+
id="path6166" />
|
|
42
|
+
</g>
|
|
43
|
+
<g
|
|
44
|
+
id="layer3"
|
|
45
|
+
style="fill:#ffff00">
|
|
46
|
+
<path
|
|
47
|
+
d="M 199.97697,368.70045 C 106.80628,368.70045 31.27656,293.17073 31.27656,200 C 31.27656,106.8293 106.80628,31.299555 199.97697,31.299555 C 153.39106,31.299555 115.62676,106.8293 115.62676,200 C 115.62676,293.17073 153.39106,368.70045 199.97697,368.70045 z "
|
|
48
|
+
style="fill:#ffff00;fill-opacity:1;stroke:none"
|
|
49
|
+
id="path7307" />
|
|
50
|
+
</g>
|
|
51
|
+
</svg>
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
|
2
|
+
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
|
3
|
+
|
|
4
|
+
<svg
|
|
5
|
+
version="1.0"
|
|
6
|
+
width="400"
|
|
7
|
+
height="400"
|
|
8
|
+
id="svg2"
|
|
9
|
+
sodipodi:docname="waning_gibbous.svg"
|
|
10
|
+
inkscape:version="1.3.2 (091e20e, 2023-11-25)"
|
|
11
|
+
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
|
12
|
+
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
|
13
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
14
|
+
xmlns:svg="http://www.w3.org/2000/svg">
|
|
15
|
+
<sodipodi:namedview
|
|
16
|
+
id="namedview1"
|
|
17
|
+
pagecolor="#ffffff"
|
|
18
|
+
bordercolor="#000000"
|
|
19
|
+
borderopacity="0.25"
|
|
20
|
+
inkscape:showpageshadow="2"
|
|
21
|
+
inkscape:pageopacity="0.0"
|
|
22
|
+
inkscape:pagecheckerboard="0"
|
|
23
|
+
inkscape:deskcolor="#d1d1d1"
|
|
24
|
+
inkscape:zoom="0.59"
|
|
25
|
+
inkscape:cx="200.84746"
|
|
26
|
+
inkscape:cy="200"
|
|
27
|
+
inkscape:window-width="1312"
|
|
28
|
+
inkscape:window-height="449"
|
|
29
|
+
inkscape:window-x="0"
|
|
30
|
+
inkscape:window-y="33"
|
|
31
|
+
inkscape:window-maximized="0"
|
|
32
|
+
inkscape:current-layer="svg2" />
|
|
33
|
+
<defs
|
|
34
|
+
id="defs4" />
|
|
35
|
+
<g
|
|
36
|
+
id="layer2"
|
|
37
|
+
style="fill:#ffff00">
|
|
38
|
+
<path
|
|
39
|
+
d="M 749.07161 200.5305 A 168.70027 168.70027 0 1 1 411.67107,200.5305 A 168.70027 168.70027 0 1 1 749.07161 200.5305 z"
|
|
40
|
+
transform="translate(-380.37134,-0.5305023)"
|
|
41
|
+
style="fill:#ffff00;fill-opacity:1;stroke:none;stroke-width:3.54330707;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
|
42
|
+
id="path6166" />
|
|
43
|
+
</g>
|
|
44
|
+
<g
|
|
45
|
+
id="layer3">
|
|
46
|
+
<path
|
|
47
|
+
d="M 200.0278,368.70045 C 293.19849,368.70045 368.72822,293.17073 368.72822,200 C 368.72822,106.8293 293.19849,31.299555 200.0278,31.299555 C 246.61371,31.299555 284.37801,106.8293 284.37801,200 C 284.37801,293.17073 246.61371,368.70045 200.0278,368.70045 z "
|
|
48
|
+
style="fill:#00000f;fill-opacity:0.94117647;stroke:none"
|
|
49
|
+
id="path7307" />
|
|
50
|
+
</g>
|
|
51
|
+
</svg>
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
|
2
|
+
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
|
3
|
+
|
|
4
|
+
<svg
|
|
5
|
+
version="1.0"
|
|
6
|
+
width="400"
|
|
7
|
+
height="400"
|
|
8
|
+
id="svg2"
|
|
9
|
+
sodipodi:docname="waxing_crescent.svg"
|
|
10
|
+
inkscape:version="1.3.2 (091e20e, 2023-11-25)"
|
|
11
|
+
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
|
12
|
+
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
|
13
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
14
|
+
xmlns:svg="http://www.w3.org/2000/svg">
|
|
15
|
+
<sodipodi:namedview
|
|
16
|
+
id="namedview1"
|
|
17
|
+
pagecolor="#ffffff"
|
|
18
|
+
bordercolor="#000000"
|
|
19
|
+
borderopacity="0.25"
|
|
20
|
+
inkscape:showpageshadow="2"
|
|
21
|
+
inkscape:pageopacity="0.0"
|
|
22
|
+
inkscape:pagecheckerboard="0"
|
|
23
|
+
inkscape:deskcolor="#d1d1d1"
|
|
24
|
+
inkscape:zoom="0.59"
|
|
25
|
+
inkscape:cx="200.84746"
|
|
26
|
+
inkscape:cy="200"
|
|
27
|
+
inkscape:window-width="1312"
|
|
28
|
+
inkscape:window-height="449"
|
|
29
|
+
inkscape:window-x="0"
|
|
30
|
+
inkscape:window-y="33"
|
|
31
|
+
inkscape:window-maximized="0"
|
|
32
|
+
inkscape:current-layer="svg2" />
|
|
33
|
+
<defs
|
|
34
|
+
id="defs4" />
|
|
35
|
+
<g
|
|
36
|
+
id="layer2">
|
|
37
|
+
<path
|
|
38
|
+
d="M 749.07161 200.5305 A 168.70027 168.70027 0 1 1 411.67107,200.5305 A 168.70027 168.70027 0 1 1 749.07161 200.5305 z"
|
|
39
|
+
transform="translate(-380.37134,-0.5305023)"
|
|
40
|
+
style="fill:#000000;fill-opacity:1;stroke:none;stroke-width:3.54330707;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
|
41
|
+
id="path6166" />
|
|
42
|
+
</g>
|
|
43
|
+
<g
|
|
44
|
+
id="layer3"
|
|
45
|
+
style="fill:#ffff00">
|
|
46
|
+
<path
|
|
47
|
+
d="M 199.862,368.70045 C 293.03269,368.70045 368.56242,293.17073 368.56242,200 C 368.56242,106.8293 293.03269,31.299555 199.862,31.299555 C 246.44791,31.299555 284.21221,106.8293 284.21221,200 C 284.21221,293.17073 246.44791,368.70045 199.862,368.70045 z "
|
|
48
|
+
style="fill:#ffff00;fill-opacity:1;stroke:none"
|
|
49
|
+
id="path7307" />
|
|
50
|
+
</g>
|
|
51
|
+
</svg>
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
|
2
|
+
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
|
3
|
+
|
|
4
|
+
<svg
|
|
5
|
+
version="1.0"
|
|
6
|
+
width="400"
|
|
7
|
+
height="400"
|
|
8
|
+
id="svg2"
|
|
9
|
+
sodipodi:docname="waxing_gibbous.svg"
|
|
10
|
+
inkscape:version="1.3.2 (091e20e, 2023-11-25)"
|
|
11
|
+
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
|
12
|
+
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
|
13
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
14
|
+
xmlns:svg="http://www.w3.org/2000/svg">
|
|
15
|
+
<sodipodi:namedview
|
|
16
|
+
id="namedview1"
|
|
17
|
+
pagecolor="#ffffff"
|
|
18
|
+
bordercolor="#000000"
|
|
19
|
+
borderopacity="0.25"
|
|
20
|
+
inkscape:showpageshadow="2"
|
|
21
|
+
inkscape:pageopacity="0.0"
|
|
22
|
+
inkscape:pagecheckerboard="0"
|
|
23
|
+
inkscape:deskcolor="#d1d1d1"
|
|
24
|
+
inkscape:zoom="0.59"
|
|
25
|
+
inkscape:cx="200.84746"
|
|
26
|
+
inkscape:cy="200"
|
|
27
|
+
inkscape:window-width="1312"
|
|
28
|
+
inkscape:window-height="449"
|
|
29
|
+
inkscape:window-x="0"
|
|
30
|
+
inkscape:window-y="33"
|
|
31
|
+
inkscape:window-maximized="0"
|
|
32
|
+
inkscape:current-layer="svg2" />
|
|
33
|
+
<defs
|
|
34
|
+
id="defs4" />
|
|
35
|
+
<g
|
|
36
|
+
id="layer2"
|
|
37
|
+
style="fill:#ffff00">
|
|
38
|
+
<path
|
|
39
|
+
d="M 749.07161 200.5305 A 168.70027 168.70027 0 1 1 411.67107,200.5305 A 168.70027 168.70027 0 1 1 749.07161 200.5305 z"
|
|
40
|
+
transform="translate(-380.37134,-0.5305023)"
|
|
41
|
+
style="fill:#ffff00;fill-opacity:1;stroke:none;stroke-width:3.54330707;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
|
42
|
+
id="path6166" />
|
|
43
|
+
</g>
|
|
44
|
+
<g
|
|
45
|
+
id="layer3">
|
|
46
|
+
<path
|
|
47
|
+
d="M 199.97697,368.70045 C 106.80628,368.70045 31.27656,293.17073 31.27656,200 C 31.27656,106.8293 106.80628,31.299555 199.97697,31.299555 C 153.39106,31.299555 115.62676,106.8293 115.62676,200 C 115.62676,293.17073 153.39106,368.70045 199.97697,368.70045 z "
|
|
48
|
+
style="fill:#00000f;fill-opacity:0.94117647;stroke:none"
|
|
49
|
+
id="path7307" />
|
|
50
|
+
</g>
|
|
51
|
+
</svg>
|
package/templates/tide.svg
CHANGED
|
@@ -7,13 +7,13 @@
|
|
|
7
7
|
id="svg1"
|
|
8
8
|
sodipodi:docname="tide.svg"
|
|
9
9
|
inkscape:version="1.3.2 (091e20e, 2023-11-25)"
|
|
10
|
+
xml:space="preserve"
|
|
10
11
|
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
|
11
12
|
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
|
13
|
+
xmlns:xlink="http://www.w3.org/1999/xlink"
|
|
12
14
|
xmlns="http://www.w3.org/2000/svg"
|
|
13
|
-
xmlns:svg="http://www.w3.org/2000/svg"
|
|
14
|
-
|
|
15
|
-
id="defs1" />
|
|
16
|
-
<sodipodi:namedview
|
|
15
|
+
xmlns:svg="http://www.w3.org/2000/svg"><defs
|
|
16
|
+
id="defs1" /><sodipodi:namedview
|
|
17
17
|
id="namedview1"
|
|
18
18
|
pagecolor="#ffffff"
|
|
19
19
|
bordercolor="#000000"
|
|
@@ -23,16 +23,16 @@
|
|
|
23
23
|
inkscape:pagecheckerboard="0"
|
|
24
24
|
inkscape:deskcolor="#d1d1d1"
|
|
25
25
|
inkscape:zoom="1.3906433"
|
|
26
|
-
inkscape:cx="
|
|
27
|
-
inkscape:cy="
|
|
26
|
+
inkscape:cx="249.88435"
|
|
27
|
+
inkscape:cy="101.03238"
|
|
28
28
|
inkscape:window-width="1488"
|
|
29
29
|
inkscape:window-height="674"
|
|
30
30
|
inkscape:window-x="24"
|
|
31
31
|
inkscape:window-y="33"
|
|
32
32
|
inkscape:window-maximized="0"
|
|
33
33
|
inkscape:current-layer="svg1"
|
|
34
|
-
showgrid="true"
|
|
35
|
-
|
|
34
|
+
showgrid="true"
|
|
35
|
+
showguides="true"><inkscape:grid
|
|
36
36
|
id="grid1"
|
|
37
37
|
units="px"
|
|
38
38
|
originx="0"
|
|
@@ -47,24 +47,20 @@
|
|
|
47
47
|
dotted="false"
|
|
48
48
|
gridanglex="30"
|
|
49
49
|
gridanglez="30"
|
|
50
|
-
visible="true"
|
|
51
|
-
</sodipodi:namedview>
|
|
52
|
-
<rect
|
|
50
|
+
visible="true" /></sodipodi:namedview><rect
|
|
53
51
|
x="1.0169492"
|
|
54
52
|
y="2.0798673e-08"
|
|
55
53
|
width="416"
|
|
56
54
|
height="240"
|
|
57
55
|
fill="#ffffff"
|
|
58
|
-
id="rect1"
|
|
59
|
-
<rect
|
|
56
|
+
id="rect1" /><rect
|
|
60
57
|
style="fill:#ffff00;stroke:#000000;stroke-width:0.614045"
|
|
61
58
|
id="rect2"
|
|
62
59
|
width="416.94916"
|
|
63
60
|
height="18.410578"
|
|
64
61
|
x="-24.928873"
|
|
65
62
|
y="-242.40596"
|
|
66
|
-
transform="matrix(1,0,-0.1068988,-0.99426991,0,0)"
|
|
67
|
-
<text
|
|
63
|
+
transform="matrix(1,0,-0.1068988,-0.99426991,0,0)" /><text
|
|
68
64
|
id="station.name"
|
|
69
65
|
x="11.235578"
|
|
70
66
|
y="26.851856"
|
|
@@ -73,8 +69,7 @@
|
|
|
73
69
|
fill="yellow"
|
|
74
70
|
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:32px;font-family:serif;-inkscape-font-specification:'Roboto Serif 20pt';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;fill:#ffff00;stroke:#000000;stroke-width:1.2278;stroke-opacity:1"
|
|
75
71
|
transform="scale(0.89274878,1.1201359)">Tidal Station Name<desc
|
|
76
|
-
id="desc1">source=resources,resource=tides,path=station.name</desc></text
|
|
77
|
-
<text
|
|
72
|
+
id="desc1">source=resources,resource=tides,path=station.name</desc></text><text
|
|
78
73
|
id="source"
|
|
79
74
|
x="347.95166"
|
|
80
75
|
y="226.1548"
|
|
@@ -88,8 +83,7 @@
|
|
|
88
83
|
id="tspan20"
|
|
89
84
|
x="347.95166"
|
|
90
85
|
y="226.1548"
|
|
91
|
-
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:13.3332995px;font-family:sans-serif;-inkscape-font-specification:'Roboto',sans-serif;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;stroke-width:3.80045">SOURCE</tspan></text
|
|
92
|
-
<text
|
|
86
|
+
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:13.3332995px;font-family:sans-serif;-inkscape-font-specification:'Roboto',sans-serif;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;stroke-width:3.80045">SOURCE</tspan></text><text
|
|
93
87
|
id="last_repaint"
|
|
94
88
|
x="4.3477793"
|
|
95
89
|
y="201.9895"
|
|
@@ -100,8 +94,7 @@
|
|
|
100
94
|
transform="scale(0.85412558,1.170788)"><desc
|
|
101
95
|
id="desc12">source=einklabel,path=repainted,format=local_datetime_short</desc><tspan
|
|
102
96
|
sodipodi:role="line"
|
|
103
|
-
id="tspan3">27 Jun 26 18:05</tspan></text
|
|
104
|
-
<text
|
|
97
|
+
id="tspan3">27 Jun 26 18:05</tspan></text><text
|
|
105
98
|
id="extremes.0"
|
|
106
99
|
x="8.6851931"
|
|
107
100
|
y="57.123634"
|
|
@@ -109,8 +102,7 @@
|
|
|
109
102
|
font-family="monospace"
|
|
110
103
|
fill="black"
|
|
111
104
|
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:22.6667px;font-family:sans-serif;-inkscape-font-specification:'Roboto, Normal',sans-serif;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;fill:#ff0000"><desc
|
|
112
|
-
id="desc13">source=resources,resource=tides,path=extremes[0].label</desc>High or Low</text
|
|
113
|
-
<text
|
|
105
|
+
id="desc13">source=resources,resource=tides,path=extremes[0].label</desc>High or Low</text><text
|
|
114
106
|
id="extremes.1"
|
|
115
107
|
x="7.6000967"
|
|
116
108
|
y="117.85719"
|
|
@@ -118,8 +110,7 @@
|
|
|
118
110
|
font-family="monospace"
|
|
119
111
|
fill="black"
|
|
120
112
|
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:22.6667px;font-family:sans-serif;-inkscape-font-specification:'Roboto, Normal',sans-serif;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;fill:#ff0000"><desc
|
|
121
|
-
id="desc14">source=resources,resource=tides,path=extremes[1].label</desc>High or Low</text
|
|
122
|
-
<text
|
|
113
|
+
id="desc14">source=resources,resource=tides,path=extremes[1].label</desc>High or Low</text><text
|
|
123
114
|
id="extremes.2"
|
|
124
115
|
x="7.2470098"
|
|
125
116
|
y="176.12112"
|
|
@@ -127,20 +118,18 @@
|
|
|
127
118
|
font-family="monospace"
|
|
128
119
|
fill="red"
|
|
129
120
|
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:22.6667px;font-family:sans-serif;-inkscape-font-specification:'Roboto, Normal',sans-serif;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;fill:#ff0000"><desc
|
|
130
|
-
id="desc15">source=resources,resource=tides,path=extremes[2].label</desc>High or Low</text
|
|
131
|
-
<text
|
|
121
|
+
id="desc15">source=resources,resource=tides,path=extremes[2].label</desc>High or Low</text><text
|
|
132
122
|
id="environment.time.timezoneRegion"
|
|
133
|
-
x="
|
|
123
|
+
x="239.09819"
|
|
134
124
|
y="204.67754"
|
|
135
125
|
font-size="10.373px"
|
|
136
126
|
font-family="sans-serif"
|
|
137
127
|
fill="#ffff00"
|
|
138
128
|
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:13.3333px;font-family:sans-serif;-inkscape-font-specification:'Roboto, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;direction:rtl;fill:#000000;stroke-width:0.864419"
|
|
139
129
|
transform="scale(0.86441854,1.156847)">UTC+01:00<desc
|
|
140
|
-
id="desc11">source=einklabel,path=local_zone</desc></text
|
|
141
|
-
<text
|
|
130
|
+
id="desc11">source=einklabel,path=local_zone</desc></text><text
|
|
142
131
|
id="lat"
|
|
143
|
-
x="
|
|
132
|
+
x="282.65424"
|
|
144
133
|
y="24.967674"
|
|
145
134
|
font-size="12px"
|
|
146
135
|
font-family="sans-serif"
|
|
@@ -149,12 +138,11 @@
|
|
|
149
138
|
id="desc18">source=resources,resource=tides,path=station.datums.LAT,category=depth,round=1</desc><tspan
|
|
150
139
|
sodipodi:role="line"
|
|
151
140
|
id="tspan17"
|
|
152
|
-
x="
|
|
153
|
-
y="24.967674">0.
|
|
154
|
-
<text
|
|
141
|
+
x="282.65424"
|
|
142
|
+
y="24.967674">0.0m</tspan></text><text
|
|
155
143
|
id="hat"
|
|
156
|
-
x="
|
|
157
|
-
y="
|
|
144
|
+
x="360.77148"
|
|
145
|
+
y="24.967674"
|
|
158
146
|
font-size="12px"
|
|
159
147
|
font-family="sans-serif"
|
|
160
148
|
fill="#ffff00"
|
|
@@ -162,26 +150,24 @@
|
|
|
162
150
|
id="desc19">source=resources,resource=tides,path=station.datums.HAT,category=depth,round=1</desc><tspan
|
|
163
151
|
sodipodi:role="line"
|
|
164
152
|
id="tspan18"
|
|
165
|
-
x="
|
|
166
|
-
y="
|
|
167
|
-
<text
|
|
153
|
+
x="360.77148"
|
|
154
|
+
y="24.967674">9.9m</tspan></text><text
|
|
168
155
|
id="extremes.2.level"
|
|
169
|
-
x="
|
|
170
|
-
y="
|
|
156
|
+
x="322.52386"
|
|
157
|
+
y="158.08005"
|
|
171
158
|
font-size="14"
|
|
172
159
|
font-family="monospace"
|
|
173
160
|
fill="red"
|
|
174
|
-
style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:37.3333px;font-family:monospace;-inkscape-font-specification:'Roboto Mono, Bold',monospace;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;fill:#000000;stroke-width:1.78893"
|
|
161
|
+
style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:37.3333px;font-family:monospace;-inkscape-font-specification:'\'Roboto Mono, Bold\', monospace';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;fill:#000000;stroke-width:1.78893"
|
|
175
162
|
transform="scale(0.7732368,1.2932649)"
|
|
176
163
|
inkscape:transform-center-x="11.578953"
|
|
177
164
|
inkscape:transform-center-y="-96.464172"><tspan
|
|
178
165
|
sodipodi:role="line"
|
|
179
166
|
id="tspan2-0"
|
|
180
|
-
x="
|
|
181
|
-
y="
|
|
182
|
-
style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:37.3333px;font-family:monospace;-inkscape-font-specification:'Roboto Mono, Bold',monospace;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;stroke-width:1.78893">3.3m</tspan><desc
|
|
183
|
-
id="desc6">source=resources,resource=tides,path=extremes[2].level,category=depth</desc></text
|
|
184
|
-
<text
|
|
167
|
+
x="322.52386"
|
|
168
|
+
y="158.08005"
|
|
169
|
+
style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:37.3333px;font-family:monospace;-inkscape-font-specification:'\'Roboto Mono, Bold\', monospace';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;stroke-width:1.78893">3.3m</tspan><desc
|
|
170
|
+
id="desc6">source=resources,resource=tides,path=extremes[2].level,category=depth</desc></text><text
|
|
185
171
|
id="extremes.2.time"
|
|
186
172
|
x="194.47879"
|
|
187
173
|
y="146.1584"
|
|
@@ -190,25 +176,23 @@
|
|
|
190
176
|
fill="red"
|
|
191
177
|
style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:37.3333px;font-family:monospace;-inkscape-font-specification:'Roboto Mono, Bold',monospace;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;fill:#000000;stroke-width:1.51352"
|
|
192
178
|
transform="scale(0.70226239,1.4239692)">15:53<desc
|
|
193
|
-
id="desc10">source=resources,resource=tides,path=extremes[2].time,format=local_time</desc></text
|
|
194
|
-
<text
|
|
179
|
+
id="desc10">source=resources,resource=tides,path=extremes[2].time,format=local_time</desc></text><text
|
|
195
180
|
id="extremes.1.level"
|
|
196
|
-
x="
|
|
197
|
-
y="
|
|
181
|
+
x="328.79895"
|
|
182
|
+
y="109.17664"
|
|
198
183
|
font-size="14"
|
|
199
184
|
font-family="monospace"
|
|
200
185
|
fill="red"
|
|
201
|
-
style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:37.3333px;font-family:monospace;-inkscape-font-specification:'Roboto Mono, Bold',monospace;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;fill:#000000;stroke-width:1.701"
|
|
186
|
+
style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:37.3333px;font-family:monospace;-inkscape-font-specification:'\'Roboto Mono, Bold\', monospace';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;fill:#000000;stroke-width:1.701"
|
|
202
187
|
transform="scale(0.75163533,1.3304324)"
|
|
203
188
|
inkscape:transform-center-y="-140.38618"
|
|
204
189
|
inkscape:transform-center-x="-0.00038058817"><tspan
|
|
205
190
|
sodipodi:role="line"
|
|
206
191
|
id="tspan2-1"
|
|
207
|
-
x="
|
|
208
|
-
y="
|
|
209
|
-
style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:37.3333px;font-family:monospace;-inkscape-font-specification:'Roboto Mono, Bold',monospace;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;stroke-width:1.701">1.6m</tspan><desc
|
|
210
|
-
id="desc5">source=resources,resource=tides,path=extremes[1].level,category=depth</desc></text
|
|
211
|
-
<text
|
|
192
|
+
x="328.79895"
|
|
193
|
+
y="109.17664"
|
|
194
|
+
style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:37.3333px;font-family:monospace;-inkscape-font-specification:'\'Roboto Mono, Bold\', monospace';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;stroke-width:1.701">1.6m</tspan><desc
|
|
195
|
+
id="desc5">source=resources,resource=tides,path=extremes[1].level,category=depth</desc></text><text
|
|
212
196
|
id="extremes.1.time"
|
|
213
197
|
x="187.55594"
|
|
214
198
|
y="108.65867"
|
|
@@ -217,8 +201,7 @@
|
|
|
217
201
|
fill="red"
|
|
218
202
|
style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:37.3333px;font-family:monospace;-inkscape-font-specification:'Roboto Mono, Bold',monospace;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;fill:#000000;stroke-width:1.48364"
|
|
219
203
|
transform="scale(0.7345432,1.3613903)">09:36<desc
|
|
220
|
-
id="desc8">source=resources,resource=tides,path=extremes[1].time,format=local_time</desc></text
|
|
221
|
-
<text
|
|
204
|
+
id="desc8">source=resources,resource=tides,path=extremes[1].time,format=local_time</desc></text><text
|
|
222
205
|
id="extremes.0.time"
|
|
223
206
|
x="184.40854"
|
|
224
207
|
y="64.242691"
|
|
@@ -227,8 +210,7 @@
|
|
|
227
210
|
fill="red"
|
|
228
211
|
style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:37.3333px;font-family:monospace;-inkscape-font-specification:'Roboto Mono, Bold',monospace;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;fill:#000000;stroke-width:1.55397"
|
|
229
212
|
transform="scale(0.74654856,1.3394976)">03:27<desc
|
|
230
|
-
id="desc3">source=resources,resource=tides,path=extremes[0].time,format=local_time</desc></text
|
|
231
|
-
<text
|
|
213
|
+
id="desc3">source=resources,resource=tides,path=extremes[0].time,format=local_time</desc></text><text
|
|
232
214
|
id="extremes.0.time-8"
|
|
233
215
|
x="10.326324"
|
|
234
216
|
y="74.630478"
|
|
@@ -237,8 +219,7 @@
|
|
|
237
219
|
fill="red"
|
|
238
220
|
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:22.6667px;font-family:sans-serif;-inkscape-font-specification:'Roboto, Normal',sans-serif;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;fill:#666666;stroke-width:1.32646"
|
|
239
221
|
transform="scale(0.82428216,1.2131768)"><desc
|
|
240
|
-
id="desc2">source=resources,resource=tides,path=extremes[0].time,format=day_mon</desc>27 Jun</text
|
|
241
|
-
<text
|
|
222
|
+
id="desc2">source=resources,resource=tides,path=extremes[0].time,format=day_mon</desc>27 Jun</text><text
|
|
242
223
|
id="extremes.0.time-8-5"
|
|
243
224
|
x="9.9649849"
|
|
244
225
|
y="123.34451"
|
|
@@ -247,8 +228,7 @@
|
|
|
247
228
|
fill="red"
|
|
248
229
|
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:22.6667px;font-family:sans-serif;-inkscape-font-specification:'Roboto, Normal',sans-serif;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;fill:#666666;stroke-width:1.32646"
|
|
249
230
|
transform="scale(0.82428216,1.2131768)"><desc
|
|
250
|
-
id="desc7">source=resources,resource=tides,path=extremes[1].time,format=day_mon</desc>27 Jun</text
|
|
251
|
-
<text
|
|
231
|
+
id="desc7">source=resources,resource=tides,path=extremes[1].time,format=day_mon</desc>27 Jun</text><text
|
|
252
232
|
id="extremes.0.time-8-9"
|
|
253
233
|
x="12.934491"
|
|
254
234
|
y="156.77794"
|
|
@@ -257,30 +237,36 @@
|
|
|
257
237
|
fill="red"
|
|
258
238
|
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:22.6667px;font-family:sans-serif;-inkscape-font-specification:'Roboto, Normal',sans-serif;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;fill:#666666;stroke-width:1.4652"
|
|
259
239
|
transform="scale(0.74623156,1.3400666)"><desc
|
|
260
|
-
id="desc9">source=resources,resource=tides,path=extremes[2].time,format=day_mon</desc>27 Jun</text
|
|
261
|
-
<text
|
|
240
|
+
id="desc9">source=resources,resource=tides,path=extremes[2].time,format=day_mon</desc>27 Jun</text><text
|
|
262
241
|
id="extremes.0.level"
|
|
263
|
-
x="
|
|
264
|
-
y="
|
|
242
|
+
x="322.34219"
|
|
243
|
+
y="64.82357"
|
|
265
244
|
font-size="14"
|
|
266
245
|
font-family="monospace"
|
|
267
246
|
fill="red"
|
|
268
|
-
style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:37.3333px;font-family:monospace;-inkscape-font-specification:'Roboto Mono, Bold',monospace;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;fill:#000000;stroke-width:1.71992"
|
|
247
|
+
style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:37.3333px;font-family:monospace;-inkscape-font-specification:'\'Roboto Mono, Bold\', monospace';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;fill:#000000;stroke-width:1.71992"
|
|
269
248
|
transform="scale(0.7703174,1.2981662)"><tspan
|
|
270
249
|
sodipodi:role="line"
|
|
271
250
|
id="tspan2"
|
|
272
|
-
x="
|
|
273
|
-
y="
|
|
274
|
-
style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:37.3333px;font-family:monospace;-inkscape-font-specification:'Roboto Mono, Bold',monospace;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;stroke-width:1.71992">3.4m</tspan><desc
|
|
275
|
-
id="desc4">source=resources,resource=tides,path=extremes[0].level,category=depth</desc></text
|
|
276
|
-
<text
|
|
251
|
+
x="322.34219"
|
|
252
|
+
y="64.82357"
|
|
253
|
+
style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:37.3333px;font-family:monospace;-inkscape-font-specification:'\'Roboto Mono, Bold\', monospace';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;stroke-width:1.71992">3.4m</tspan><desc
|
|
254
|
+
id="desc4">source=resources,resource=tides,path=extremes[0].level,category=depth</desc></text><text
|
|
277
255
|
xml:space="preserve"
|
|
278
256
|
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:21.3333px;font-family:sans-serif;-inkscape-font-specification:'\'Roboto, Normal\', sans-serif';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;fill:#1a1a1a;stroke:#fefe54;stroke-width:0.612283;stroke-opacity:1"
|
|
279
|
-
x="
|
|
280
|
-
y="25.
|
|
257
|
+
x="337.254"
|
|
258
|
+
y="25.327612"
|
|
281
259
|
id="text19"><tspan
|
|
282
260
|
sodipodi:role="line"
|
|
283
261
|
id="tspan19"
|
|
284
|
-
x="
|
|
285
|
-
y="25.
|
|
286
|
-
|
|
262
|
+
x="337.254"
|
|
263
|
+
y="25.327612">-></tspan></text><image
|
|
264
|
+
preserveAspectRatio="none"
|
|
265
|
+
inkscape:svg-dpi="96"
|
|
266
|
+
width="71.375114"
|
|
267
|
+
height="70.656021"
|
|
268
|
+
xlink:href="data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiIHN0YW5kYWxvbmU9Im5vIj8+Cjwh LS0gQ3JlYXRlZCB3aXRoIElua3NjYXBlIChodHRwOi8vd3d3Lmlua3NjYXBlLm9yZy8pIC0tPgo8 c3ZnCiAgIHhtbG5zOnN2Zz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciCiAgIHhtbG5zPSJo dHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIKICAgdmVyc2lvbj0iMS4wIgogICB3aWR0aD0iNDAw IgogICBoZWlnaHQ9IjQwMCIKICAgaWQ9InN2ZzIiPgogIDxkZWZzCiAgICAgaWQ9ImRlZnM0IiAv PgogIDxnCiAgICAgaWQ9ImxheWVyMSI+CiAgICA8cmVjdAogICAgICAgd2lkdGg9IjQwMCIKICAg ICAgIGhlaWdodD0iNDAwIgogICAgICAgeD0iMCIKICAgICAgIHk9Ii0xLjU0NTQ0MzVlLTAxNCIK ICAgICAgIHN0eWxlPSJmaWxsOiMwMDAwYmI7ZmlsbC1vcGFjaXR5OjE7c3Ryb2tlOm5vbmU7c3Ry b2tlLXdpZHRoOjMuNTQzMzA3MDc7c3Ryb2tlLW1pdGVybGltaXQ6NDtzdHJva2UtZGFzaGFycmF5 Om5vbmU7c3Ryb2tlLW9wYWNpdHk6MSIKICAgICAgIGlkPSJyZWN0MzIzOSIgLz4KICA8L2c+CiAg PGcKICAgICBpZD0ibGF5ZXIyIj4KICAgIDxwYXRoCiAgICAgICBkPSJNIDc0OS4wNzE2MSAyMDAu NTMwNSBBIDE2OC43MDAyNyAxNjguNzAwMjcgMCAxIDEgIDQxMS42NzEwNywyMDAuNTMwNSBBIDE2 OC43MDAyNyAxNjguNzAwMjcgMCAxIDEgIDc0OS4wNzE2MSAyMDAuNTMwNSB6IgogICAgICAgdHJh bnNmb3JtPSJ0cmFuc2xhdGUoLTM4MC4zNzEzNCwtMC41MzA1MDIzKSIKICAgICAgIHN0eWxlPSJm aWxsOiNmZmZmZmY7ZmlsbC1vcGFjaXR5OjE7c3Ryb2tlOm5vbmU7c3Ryb2tlLXdpZHRoOjMuNTQz MzA3MDc7c3Ryb2tlLW1pdGVybGltaXQ6NDtzdHJva2UtZGFzaGFycmF5Om5vbmU7c3Ryb2tlLW9w YWNpdHk6MSIKICAgICAgIGlkPSJwYXRoNjE2NiIgLz4KICA8L2c+CiAgPGcKICAgICBpZD0ibGF5 ZXIzIj4KICAgIDxwYXRoCiAgICAgICBkPSJNIDIwMC4wMjc4LDM2OC43MDA0NSBDIDI5My4xOTg0 OSwzNjguNzAwNDUgMzY4LjcyODIyLDI5My4xNzA3MyAzNjguNzI4MjIsMjAwIEMgMzY4LjcyODIy LDEwNi44MjkzIDI5My4xOTg0OSwzMS4yOTk1NTUgMjAwLjAyNzgsMzEuMjk5NTU1IEMgMjQ2LjYx MzcxLDMxLjI5OTU1NSAyODQuMzc4MDEsMTA2LjgyOTMgMjg0LjM3ODAxLDIwMCBDIDI4NC4zNzgw MSwyOTMuMTcwNzMgMjQ2LjYxMzcxLDM2OC43MDA0NSAyMDAuMDI3OCwzNjguNzAwNDUgeiAiCiAg ICAgICBzdHlsZT0iZmlsbDojMDAwMDBmO2ZpbGwtb3BhY2l0eTowLjk0MTE3NjQ3O3N0cm9rZTpu b25lIgogICAgICAgaWQ9InBhdGg3MzA3IiAvPgogIDwvZz4KPC9zdmc+Cg== "
|
|
269
|
+
id="moon_phase"
|
|
270
|
+
x="340.3974"
|
|
271
|
+
y="90.153488"><desc
|
|
272
|
+
id="desc22">path=environment.moon.phaseName,assets=../resources/svg/lunar_phases</desc></image></svg>
|