signalk-gpio-beeper-plugin 1.0.0 → 1.1.0

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.
Files changed (2) hide show
  1. package/package.json +1 -1
  2. package/plugin/index.js +49 -35
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "signalk-gpio-beeper-plugin",
3
- "version": "1.0.0",
3
+ "version": "1.1.0",
4
4
  "description": "A Signal K plugin that activates a Raspberry Pi GPIO beeper when a Signal K alarm condition exists",
5
5
  "keywords": [
6
6
  "signalk-node-server-plugin",
package/plugin/index.js CHANGED
@@ -1,35 +1,20 @@
1
1
  module.exports = (app) => {
2
+ const pkg = require("../package.json");
2
3
  const Gpio = require("onoff").Gpio;
3
4
  let buzzer = null;
4
5
  let notificationTimer;
5
-
6
- function walkNotifications(node, pathPrefix, map) {
7
- if (!node || typeof node !== "object") return;
8
-
9
- if (
10
- node.value &&
11
- typeof node.value.state === "string" &&
12
- node.value.method?.includes("sound") &&
13
- node.value.status?.silenced !== true
14
- ) {
15
- map.set(pathPrefix, node.value.state);
16
- }
17
-
18
- for (const key of Object.keys(node)) {
19
- if (["meta", "timestamp", "$source", "value"].includes(key)) continue;
20
- walkNotifications(node[key], `${pathPrefix}.${key}`, map);
21
- }
22
- }
6
+ let unsubscribes = [];
23
7
 
24
8
  function beep(duration = 150) {
9
+ app.debug("BEEP");
25
10
  if (!buzzer) return;
26
11
  buzzer.writeSync(1);
27
12
  setTimeout(() => buzzer.writeSync(0), duration);
28
13
  }
29
14
 
30
15
  const plugin = {
31
- id: "gpio-beeper-plugin",
32
- name: "GPIO Beeper",
16
+ id: pkg.name,
17
+ name: pkg.signalk.description,
33
18
 
34
19
  start: (settings, restartPlugin) => {
35
20
  app.debug("Plugin started");
@@ -37,32 +22,61 @@ module.exports = (app) => {
37
22
 
38
23
  if (Gpio.accessible) buzzer = new Gpio(17, "out");
39
24
 
25
+ const shadowState = new Map(); // path -> state
40
26
  const severity = { emergency: 3, alarm: 2, warn: 1 };
41
27
 
42
- notificationTimer = setInterval(() => {
43
- const tree = app.getSelfPath("notifications");
44
- const active = new Map();
45
- if (tree) walkNotifications(tree, "notifications", active);
28
+ app.subscriptionmanager.subscribe(
29
+ {
30
+ context: "*",
31
+ subscribe: [
32
+ {
33
+ path: "notifications.*",
34
+ period: 1000,
35
+ },
36
+ ],
37
+ },
38
+ unsubscribes,
39
+ (err) => app.error(err),
40
+ (delta) => {
41
+ delta.updates.forEach((update) => {
42
+ update.values.forEach(({ path, value }) => {
43
+ const state = value && value.state;
44
+ if (
45
+ !state ||
46
+ state === "normal" ||
47
+ !value.method?.includes("sound") ||
48
+ value.status?.silenced === true
49
+ ) {
50
+ shadowState.delete(path);
51
+ } else {
52
+ shadowState.set(path, state);
53
+ }
54
+ });
55
+ });
56
+ },
57
+ );
46
58
 
59
+ notificationTimer = setInterval(() => {
60
+ app.debug(shadowState);
47
61
  let worst = null;
48
-
49
- for (const state of active.values()) {
50
- if (severity[state] === undefined) continue; // skip 'normal' and any unrecognized state
62
+ for (const state of shadowState.values()) {
63
+ if (severity[state] === undefined) continue;
51
64
  if (worst === null || severity[state] > severity[worst])
52
65
  worst = state;
53
66
  }
54
-
55
- if (worst === "alarm" || worst === "emergency") {
56
- app.debug("BEEP", worst);
67
+ app.debug({ worst });
68
+ if (worst === "alarm" || worst === "emergency")
57
69
  beep(settings.duration || 300);
58
- } else if (worst === "warn") {
59
- app.debug("BEEP", worst);
60
- beep(settings.duration / 3 || 100);
61
- }
62
- }, settings.interval || 1000);
70
+ else if (worst === "warn") beep(settings.duration / 3 || 100);
71
+ }, settings.interval || 3000);
63
72
  },
64
73
 
65
74
  stop: () => {
75
+ app.debug("Plugin stopped");
76
+ if (unsubscribes) {
77
+ unsubscribes.forEach((f) => f());
78
+ unsubscribes = [];
79
+ }
66
80
  if (notificationTimer) {
67
81
  clearInterval(notificationTimer);
68
82
  notificationTimer = null;