Skip to content

Commit 15568c1

Browse files
committed
feat: Notify systemd for start, stop, watchdog
1 parent 3d8f0fc commit 15568c1

File tree

5 files changed

+69
-1
lines changed

5 files changed

+69
-1
lines changed

lib/controller.ts

+11
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import utils from './util/utils';
88
import stringify from 'json-stable-stringify-without-jsonify';
99
import assert from 'assert';
1010
import bind from 'bind-decorator';
11+
import { optionalRequire } from 'optional-require';
1112

1213
// Extensions
1314
import ExtensionFrontend from './extension/frontend';
@@ -39,6 +40,8 @@ const AllExtensions = [
3940
type ExtensionArgs = [Zigbee, MQTT, State, PublishEntityState, EventBus,
4041
(enable: boolean, name: string) => Promise<void>, () => void, (extension: Extension) => Promise<void>];
4142

43+
const sdNotify = process.env.NOTIFY_SOCKET ? optionalRequire('sd-notify') : null;
44+
4245
export class Controller {
4346
private eventBus: EventBus;
4447
private zigbee: Zigbee;
@@ -165,6 +168,10 @@ export class Controller {
165168
(data) => utils.publishLastSeen(data, settings.get(), false, this.publishEntityState));
166169

167170
logger.info(`Zigbee2MQTT started!`);
171+
172+
if ((sdNotify?.watchdogInterval() || 0) > 0)
173+
sdNotify.startWatchdogMode(Math.floor(sdNotify.watchdogInterval() / 2));
174+
sdNotify?.ready();
168175
}
169176

170177
@bind async enableDisableExtension(enable: boolean, name: string): Promise<void> {
@@ -189,6 +196,8 @@ export class Controller {
189196
}
190197

191198
async stop(restart = false): Promise<void> {
199+
sdNotify?.stopping();
200+
192201
// Call extensions
193202
await this.callExtensions('stop', this.extensions);
194203
this.eventBus.removeListeners(this);
@@ -205,6 +214,8 @@ export class Controller {
205214
logger.error('Failed to stop Zigbee2MQTT');
206215
await this.exit(1, restart);
207216
}
217+
218+
sdNotify?.stopWatchdogMode();
208219
}
209220

210221
async exit(code: number, restart = false): Promise<void> {

package-lock.json

+41
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

+4
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@
5353
"moment": "^2.30.1",
5454
"mqtt": "^5.3.4",
5555
"object-assign-deep": "^0.4.0",
56+
"optional-require": "^1.1.8",
5657
"rimraf": "^5.0.5",
5758
"semver": "^7.5.4",
5859
"source-map-support": "^0.5.21",
@@ -111,5 +112,8 @@
111112
},
112113
"bin": {
113114
"zigbee2mqtt": "cli.js"
115+
},
116+
"optionalDependencies": {
117+
"sd-notify": "^2.8.0"
114118
}
115119
}

scripts/install.sh

+2-1
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,8 @@ Description=zigbee2mqtt
3636
After=network.target
3737
3838
[Service]
39-
ExecStart=/usr/bin/npm start
39+
Type=notify
40+
ExecStart=/usr/bin/node index.js
4041
WorkingDirectory=/opt/zigbee2mqtt
4142
StandardOutput=inherit
4243
StandardError=inherit

test/controller.test.js

+11
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
process.env.NOTIFY_SOCKET = "mocked";
12
const data = require('./stub/data');
23
const logger = require('./stub/logger');
34
const zigbeeHerdsman = require('./stub/zigbeeHerdsman');
@@ -16,6 +17,16 @@ const mocksClear = [
1617

1718
const fs = require('fs');
1819

20+
jest.mock('sd-notify', () => {
21+
return {
22+
watchdogInterval: () => {return 3000;},
23+
startWatchdogMode: (interval) => {},
24+
stopWatchdogMode: () => {},
25+
ready: () => {},
26+
stopping: () => {},
27+
};
28+
}, {virtual: true});
29+
1930
describe('Controller', () => {
2031
let controller;
2132
let mockExit;

0 commit comments

Comments
 (0)