zwave-js-ui 9.3.2
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/LICENSE +21 -0
- package/README.md +48 -0
- package/dev-dist/registerSW.js +5 -0
- package/dist/apple-touch-icon-180x180.png +0 -0
- package/dist/assets/AssociationGroups-474358b5.js +1 -0
- package/dist/assets/BgRssiChart-3e7d7555.css +1 -0
- package/dist/assets/BgRssiChart-554c89ef.js +3 -0
- package/dist/assets/BlinkIcon-5407e2e0.js +1 -0
- package/dist/assets/ColumnFilter-378ec338.js +1 -0
- package/dist/assets/ColumnFilterBoolean-e0ff8ce6.js +1 -0
- package/dist/assets/ColumnFilterDate-b17871ea.js +1 -0
- package/dist/assets/ColumnFilterNumber-c07930a6.js +1 -0
- package/dist/assets/ColumnFilterString-079ac562.js +1 -0
- package/dist/assets/ControlPanel-3c3168d8.js +7 -0
- package/dist/assets/ControllerChart-f2fbb771.js +1 -0
- package/dist/assets/Debug-ea34e06e.js +98 -0
- package/dist/assets/DialogAdvanced-5f8c36c7.js +1 -0
- package/dist/assets/DialogAdvanced-eaabda04.css +1 -0
- package/dist/assets/DialogAssociation-6da4cd66.js +1 -0
- package/dist/assets/DialogGatewayValue-501b7bbe.js +1 -0
- package/dist/assets/DialogGatewayValue-911dd212.css +1 -0
- package/dist/assets/DialogHealthCheck-2228ed6c.css +1 -0
- package/dist/assets/DialogHealthCheck-9e90523a.js +1 -0
- package/dist/assets/DialogSceneValue-ff3081b9.js +1 -0
- package/dist/assets/ErrorPage-a4f837c6.js +1 -0
- package/dist/assets/ExpandedNode-9f727a42.css +1 -0
- package/dist/assets/ExpandedNode-a0bff765.js +3 -0
- package/dist/assets/HomeAssistant-974143e2.js +1 -0
- package/dist/assets/ListInput-d8c678f2.js +1 -0
- package/dist/assets/Login-1826b0a1.css +1 -0
- package/dist/assets/Login-5424b4df.js +1 -0
- package/dist/assets/MaterialIcons-Regular-11ec382a.woff +0 -0
- package/dist/assets/MaterialIcons-Regular-29c11fa5.ttf +0 -0
- package/dist/assets/MaterialIcons-Regular-5743ed3d.woff2 +0 -0
- package/dist/assets/MaterialIcons-Regular-e69d687a.eot +0 -0
- package/dist/assets/Mesh-1b8d31eb.css +1 -0
- package/dist/assets/Mesh-25b19dfe.js +1 -0
- package/dist/assets/NodeDetails-da00c417.css +1 -0
- package/dist/assets/NodeDetails-e9d8d566.js +5 -0
- package/dist/assets/NodePanel-3639f227.css +1 -0
- package/dist/assets/NodePanel-5cdb1b4a.js +1 -0
- package/dist/assets/NodeScheduler-e91e411b.js +1 -0
- package/dist/assets/OTAUpdates-066cbfed.js +7 -0
- package/dist/assets/QrReader-00dee3fb.css +1 -0
- package/dist/assets/QrReader-c320584c.js +1 -0
- package/dist/assets/ReinterviewBadge-a40fb19f.js +1 -0
- package/dist/assets/RichValue-3ea76a33.css +1 -0
- package/dist/assets/RichValue-3f78fa98.js +1 -0
- package/dist/assets/Scenes-4aea74b8.js +1 -0
- package/dist/assets/Settings-ac079344.css +1 -0
- package/dist/assets/Settings-d8e203ed.js +44 -0
- package/dist/assets/SmartStart-63c21be6.js +2 -0
- package/dist/assets/SmartView-f9259d20.js +1 -0
- package/dist/assets/StatisticsArrows-40c56587.js +1 -0
- package/dist/assets/StatisticsCard-a91596c0.js +1 -0
- package/dist/assets/Store-701d51c8.js +1 -0
- package/dist/assets/Store-a58f7130.css +1 -0
- package/dist/assets/UserCodeTable-c397703b.js +1 -0
- package/dist/assets/ValueId-b8e1e4a2.js +1 -0
- package/dist/assets/ValueId-ea679e64.css +1 -0
- package/dist/assets/ZwaveGraph-4fa851e3.js +98 -0
- package/dist/assets/ZwaveGraph-fe07d4ee.css +1 -0
- package/dist/assets/file-input-064e7979.js +1 -0
- package/dist/assets/index-058391ec.js +17 -0
- package/dist/assets/index-3c63af0b.js +112 -0
- package/dist/assets/index-468a52af.js +2 -0
- package/dist/assets/index-be785cef.css +9 -0
- package/dist/assets/index-d98f5afd.css +1 -0
- package/dist/assets/items-45b4c1f5.js +1 -0
- package/dist/assets/mdi-4fe99e39.js +1 -0
- package/dist/assets/prismeditor.esm-3002a813.js +7 -0
- package/dist/assets/qr-scanner-worker.min-5f44a019.js +98 -0
- package/dist/assets/vuedraggable.umd-441070b9.js +8 -0
- package/dist/favicon.ico +0 -0
- package/dist/index.html +47 -0
- package/dist/logo.png +0 -0
- package/dist/logo.svg +32 -0
- package/dist/manifest.webmanifest +1 -0
- package/dist/maskable-icon-512x512.png +0 -0
- package/dist/pwa-192x192.png +0 -0
- package/dist/pwa-512x512.png +0 -0
- package/dist/pwa-64x64.png +0 -0
- package/dist/registerSW.js +1 -0
- package/dist/star.svg +3 -0
- package/dist/sw.js +1232 -0
- package/package.json +217 -0
- package/public/apple-touch-icon-180x180.png +0 -0
- package/public/favicon.ico +0 -0
- package/public/logo.png +0 -0
- package/public/logo.svg +32 -0
- package/public/maskable-icon-512x512.png +0 -0
- package/public/pwa-192x192.png +0 -0
- package/public/pwa-512x512.png +0 -0
- package/public/pwa-64x64.png +0 -0
- package/public/star.svg +3 -0
- package/server/app.js +1201 -0
- package/server/bin/www.js +70 -0
- package/server/config/app.js +22 -0
- package/server/config/store.js +19 -0
- package/server/hass/configurations.js +195 -0
- package/server/hass/devices.js +397 -0
- package/server/lib/BackupManager.js +134 -0
- package/server/lib/Constants.js +705 -0
- package/server/lib/CustomPlugin.js +9 -0
- package/server/lib/EventEmitter.js +14 -0
- package/server/lib/Gateway.js +1986 -0
- package/server/lib/MqttClient.js +418 -0
- package/server/lib/SocketEvents.js +34 -0
- package/server/lib/SocketManager.js +71 -0
- package/server/lib/ZwaveClient.js +4261 -0
- package/server/lib/jsonStore.js +139 -0
- package/server/lib/logger.js +169 -0
- package/server/lib/utils.js +283 -0
- package/snippets/access-store-dir.js +12 -0
- package/snippets/clone-config.js +17 -0
- package/snippets/pingNodes.js +14 -0
- package/snippets/reinterview-nodes.js +64 -0
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || function (mod) {
|
|
19
|
+
if (mod && mod.__esModule) return mod;
|
|
20
|
+
var result = {};
|
|
21
|
+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
22
|
+
__setModuleDefault(result, mod);
|
|
23
|
+
return result;
|
|
24
|
+
};
|
|
25
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
26
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
27
|
+
};
|
|
28
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
29
|
+
exports.StorageHelper = exports.STORE_BACKUP_PREFIX = void 0;
|
|
30
|
+
const jsonfile_1 = require("jsonfile");
|
|
31
|
+
const app_1 = require("../config/app");
|
|
32
|
+
const logger_1 = require("./logger");
|
|
33
|
+
const utils = __importStar(require("./utils"));
|
|
34
|
+
const merge_1 = require("merge");
|
|
35
|
+
const archiver_1 = __importDefault(require("archiver"));
|
|
36
|
+
const fs_1 = require("fs");
|
|
37
|
+
const fs_extra_1 = require("fs-extra");
|
|
38
|
+
const logger = (0, logger_1.module)('Store');
|
|
39
|
+
exports.STORE_BACKUP_PREFIX = 'store-backup_';
|
|
40
|
+
/**
|
|
41
|
+
Constructor
|
|
42
|
+
**/
|
|
43
|
+
class StorageHelper {
|
|
44
|
+
_store;
|
|
45
|
+
config;
|
|
46
|
+
get store() {
|
|
47
|
+
return this._store;
|
|
48
|
+
}
|
|
49
|
+
constructor() {
|
|
50
|
+
this._store = {};
|
|
51
|
+
}
|
|
52
|
+
async init(config) {
|
|
53
|
+
this.config = config;
|
|
54
|
+
for (const model in config) {
|
|
55
|
+
const res = await this._getFile(config[model]);
|
|
56
|
+
this._store[res.file] = res.data;
|
|
57
|
+
}
|
|
58
|
+
return this._store;
|
|
59
|
+
}
|
|
60
|
+
async backup(res) {
|
|
61
|
+
const backupFile = `${exports.STORE_BACKUP_PREFIX}${utils.fileDate()}.zip`;
|
|
62
|
+
await (0, fs_extra_1.mkdirp)(app_1.storeBackupsDir);
|
|
63
|
+
const fileStream = (0, fs_1.createWriteStream)(utils.joinPath(app_1.storeBackupsDir, backupFile));
|
|
64
|
+
return new Promise((resolve, reject) => {
|
|
65
|
+
const archive = (0, archiver_1.default)('zip');
|
|
66
|
+
archive.on('error', (err) => {
|
|
67
|
+
reject(err);
|
|
68
|
+
});
|
|
69
|
+
// on stream closed we can end the request
|
|
70
|
+
archive.on('end', () => {
|
|
71
|
+
resolve(backupFile);
|
|
72
|
+
});
|
|
73
|
+
if (res) {
|
|
74
|
+
res.set({
|
|
75
|
+
'Content-Type': 'application/json',
|
|
76
|
+
'Content-Disposition': `attachment; filename="${backupFile}"`,
|
|
77
|
+
});
|
|
78
|
+
archive.pipe(res);
|
|
79
|
+
}
|
|
80
|
+
archive.pipe(fileStream);
|
|
81
|
+
// backup zwavejs files too
|
|
82
|
+
archive.glob('*.jsonl', {
|
|
83
|
+
cwd: app_1.storeDir,
|
|
84
|
+
});
|
|
85
|
+
for (const model in this.config) {
|
|
86
|
+
const config = this.config[model];
|
|
87
|
+
const filePath = utils.joinPath(app_1.storeDir, config.file);
|
|
88
|
+
if ((0, fs_extra_1.existsSync)(filePath)) {
|
|
89
|
+
archive.file(filePath, {
|
|
90
|
+
name: config.file,
|
|
91
|
+
});
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
void archive.finalize();
|
|
95
|
+
});
|
|
96
|
+
}
|
|
97
|
+
async _getFile(config) {
|
|
98
|
+
let err;
|
|
99
|
+
let data;
|
|
100
|
+
try {
|
|
101
|
+
data = await (0, jsonfile_1.readFile)(utils.joinPath(app_1.storeDir, config.file));
|
|
102
|
+
}
|
|
103
|
+
catch (error) {
|
|
104
|
+
err = error;
|
|
105
|
+
}
|
|
106
|
+
// ignore ENOENT error
|
|
107
|
+
if (err) {
|
|
108
|
+
if (err.code !== 'ENOENT') {
|
|
109
|
+
logger.error('Error reading file: ' + config.file, err);
|
|
110
|
+
}
|
|
111
|
+
else {
|
|
112
|
+
logger.warn(`${config.file} not found`);
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
// replace data with default
|
|
116
|
+
if (!data) {
|
|
117
|
+
data = config.default;
|
|
118
|
+
}
|
|
119
|
+
else {
|
|
120
|
+
data = Array.isArray(data) ? data : (0, merge_1.recursive)(config.default, data);
|
|
121
|
+
}
|
|
122
|
+
return { file: config.file, data: data };
|
|
123
|
+
}
|
|
124
|
+
get(model) {
|
|
125
|
+
if (this._store[model.file]) {
|
|
126
|
+
return this._store[model.file];
|
|
127
|
+
}
|
|
128
|
+
else {
|
|
129
|
+
throw Error('Requested file not present in store: ' + model.file);
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
async put(model, data) {
|
|
133
|
+
await (0, jsonfile_1.writeFile)(utils.joinPath(app_1.storeDir, model.file), data);
|
|
134
|
+
this._store[model.file] = data;
|
|
135
|
+
return data;
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
exports.StorageHelper = StorageHelper;
|
|
139
|
+
exports.default = new StorageHelper();
|
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || function (mod) {
|
|
19
|
+
if (mod && mod.__esModule) return mod;
|
|
20
|
+
var result = {};
|
|
21
|
+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
22
|
+
__setModuleDefault(result, mod);
|
|
23
|
+
return result;
|
|
24
|
+
};
|
|
25
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
26
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
27
|
+
};
|
|
28
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
29
|
+
exports.setupAll = exports.module = exports.setupLogger = exports.customTransports = exports.customFormat = exports.sanitizedConfig = exports.disableColors = exports.defaultLogFile = void 0;
|
|
30
|
+
const winston_daily_rotate_file_1 = __importDefault(require("@zwave-js/winston-daily-rotate-file"));
|
|
31
|
+
const fs_extra_1 = require("fs-extra");
|
|
32
|
+
const winston_1 = __importDefault(require("winston"));
|
|
33
|
+
const app_1 = require("../config/app");
|
|
34
|
+
const utils_1 = require("./utils");
|
|
35
|
+
const path = __importStar(require("path"));
|
|
36
|
+
const { format, transports, addColors } = winston_1.default;
|
|
37
|
+
const { combine, timestamp, label, printf, colorize, splat } = format;
|
|
38
|
+
exports.defaultLogFile = 'z-ui_%DATE%.log';
|
|
39
|
+
exports.disableColors = process.env.NO_LOG_COLORS === 'true';
|
|
40
|
+
// ensure store and logs directories exist
|
|
41
|
+
(0, fs_extra_1.ensureDirSync)(app_1.storeDir);
|
|
42
|
+
(0, fs_extra_1.ensureDirSync)(app_1.logsDir);
|
|
43
|
+
// custom colors for timestamp and module
|
|
44
|
+
addColors({
|
|
45
|
+
time: 'grey',
|
|
46
|
+
module: 'bold',
|
|
47
|
+
});
|
|
48
|
+
const colorizer = colorize();
|
|
49
|
+
/**
|
|
50
|
+
* Generate logger configuration starting from settings.gateway
|
|
51
|
+
*/
|
|
52
|
+
function sanitizedConfig(module, config) {
|
|
53
|
+
config = config || {};
|
|
54
|
+
const filePath = (0, utils_1.joinPath)(app_1.logsDir, config.logFileName || exports.defaultLogFile);
|
|
55
|
+
return {
|
|
56
|
+
module: module || '-',
|
|
57
|
+
enabled: config.logEnabled !== undefined ? config.logEnabled : true,
|
|
58
|
+
level: config.logLevel || 'info',
|
|
59
|
+
logToFile: config.logToFile !== undefined ? config.logToFile : false,
|
|
60
|
+
filePath: filePath,
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
exports.sanitizedConfig = sanitizedConfig;
|
|
64
|
+
/**
|
|
65
|
+
* Return a custom logger format
|
|
66
|
+
*/
|
|
67
|
+
function customFormat(config, noColor = false) {
|
|
68
|
+
noColor = noColor || exports.disableColors;
|
|
69
|
+
const formats = [
|
|
70
|
+
splat(),
|
|
71
|
+
timestamp({ format: 'YYYY-MM-DD HH:mm:ss.SSS' }),
|
|
72
|
+
format((info) => {
|
|
73
|
+
info.level = info.level.toUpperCase();
|
|
74
|
+
return info;
|
|
75
|
+
})(),
|
|
76
|
+
label({ label: config.module.toUpperCase() }),
|
|
77
|
+
];
|
|
78
|
+
if (!noColor) {
|
|
79
|
+
formats.push(colorize({ level: true }));
|
|
80
|
+
}
|
|
81
|
+
// must be added at last
|
|
82
|
+
formats.push(printf((info) => {
|
|
83
|
+
if (!noColor) {
|
|
84
|
+
info.timestamp = colorizer.colorize('time', info.timestamp);
|
|
85
|
+
info.label = colorizer.colorize('module', info.label || '-');
|
|
86
|
+
}
|
|
87
|
+
return `${info.timestamp} ${info.level} ${info.label}: ${info.message}${info.stack ? '\n' + info.stack : ''}`;
|
|
88
|
+
}));
|
|
89
|
+
return combine(...formats);
|
|
90
|
+
}
|
|
91
|
+
exports.customFormat = customFormat;
|
|
92
|
+
/**
|
|
93
|
+
* Create the base transports based on settings provided
|
|
94
|
+
*/
|
|
95
|
+
function customTransports(config) {
|
|
96
|
+
const transportsList = [];
|
|
97
|
+
if (process.env.ZUI_NO_CONSOLE !== 'true') {
|
|
98
|
+
transportsList.push(new transports.Console({
|
|
99
|
+
format: customFormat(config),
|
|
100
|
+
level: config.level,
|
|
101
|
+
stderrLevels: ['error'],
|
|
102
|
+
}));
|
|
103
|
+
}
|
|
104
|
+
if (config.logToFile) {
|
|
105
|
+
let fileTransport;
|
|
106
|
+
if (process.env.DISABLE_LOG_ROTATION === 'true') {
|
|
107
|
+
fileTransport = new transports.File({
|
|
108
|
+
format: customFormat(config, true),
|
|
109
|
+
filename: config.filePath,
|
|
110
|
+
level: config.level,
|
|
111
|
+
});
|
|
112
|
+
}
|
|
113
|
+
else {
|
|
114
|
+
fileTransport = new winston_daily_rotate_file_1.default({
|
|
115
|
+
filename: config.filePath,
|
|
116
|
+
auditFile: (0, utils_1.joinPath)(app_1.logsDir, 'zui-logs.audit.json'),
|
|
117
|
+
datePattern: 'YYYY-MM-DD',
|
|
118
|
+
createSymlink: true,
|
|
119
|
+
symlinkName: path
|
|
120
|
+
.basename(config.filePath)
|
|
121
|
+
.replace(`_%DATE%`, '_current'),
|
|
122
|
+
zippedArchive: true,
|
|
123
|
+
maxFiles: process.env.ZUI_LOG_MAXFILES || '7d',
|
|
124
|
+
maxSize: process.env.ZUI_LOG_MAXSIZE || '50m',
|
|
125
|
+
level: config.level,
|
|
126
|
+
format: customFormat(config, true),
|
|
127
|
+
});
|
|
128
|
+
}
|
|
129
|
+
transportsList.push(fileTransport);
|
|
130
|
+
}
|
|
131
|
+
return transportsList;
|
|
132
|
+
}
|
|
133
|
+
exports.customTransports = customTransports;
|
|
134
|
+
/**
|
|
135
|
+
* Setup a logger
|
|
136
|
+
*/
|
|
137
|
+
function setupLogger(container, module, config) {
|
|
138
|
+
const sanitized = sanitizedConfig(module, config);
|
|
139
|
+
// Winston automatically reuses an existing module logger
|
|
140
|
+
const logger = container.add(module);
|
|
141
|
+
logger.configure({
|
|
142
|
+
format: combine(format.errors({ stack: true }), format.json()),
|
|
143
|
+
silent: !sanitized.enabled,
|
|
144
|
+
level: sanitized.level,
|
|
145
|
+
transports: customTransports(sanitized),
|
|
146
|
+
});
|
|
147
|
+
logger.module = module;
|
|
148
|
+
logger.setup = (cfg) => setupLogger(container, module, cfg);
|
|
149
|
+
return logger;
|
|
150
|
+
}
|
|
151
|
+
exports.setupLogger = setupLogger;
|
|
152
|
+
const logContainer = new winston_1.default.Container();
|
|
153
|
+
/**
|
|
154
|
+
* Create a new logger for a specific module
|
|
155
|
+
*/
|
|
156
|
+
function module(module) {
|
|
157
|
+
return setupLogger(logContainer, module);
|
|
158
|
+
}
|
|
159
|
+
exports.module = module;
|
|
160
|
+
/**
|
|
161
|
+
* Setup all loggers starting from config
|
|
162
|
+
*/
|
|
163
|
+
function setupAll(config) {
|
|
164
|
+
logContainer.loggers.forEach((logger) => {
|
|
165
|
+
logger.setup(config);
|
|
166
|
+
});
|
|
167
|
+
}
|
|
168
|
+
exports.setupAll = setupAll;
|
|
169
|
+
exports.default = logContainer.loggers;
|
|
@@ -0,0 +1,283 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || function (mod) {
|
|
19
|
+
if (mod && mod.__esModule) return mod;
|
|
20
|
+
var result = {};
|
|
21
|
+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
22
|
+
__setModuleDefault(result, mod);
|
|
23
|
+
return result;
|
|
24
|
+
};
|
|
25
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
26
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
27
|
+
};
|
|
28
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
29
|
+
exports.parseJSON = exports.allSettled = exports.buffer2hex = exports.bufferFromHex = exports.isBufferAsHex = exports.verifyPsw = exports.hashPsw = exports.humanSize = exports.hasProperty = exports.removeSlash = exports.sanitizeTopic = exports.getVersion = exports.num2hex = exports.copy = exports.isValueId = exports.joinProps = exports.joinPath = exports.getPath = exports.basePath = exports.fileDate = exports.deepEqual = exports.padNumber = exports.applyMixin = exports.pkgJson = void 0;
|
|
30
|
+
const path_1 = __importStar(require("path"));
|
|
31
|
+
const crypto_1 = __importDefault(require("crypto"));
|
|
32
|
+
const fs_1 = require("fs");
|
|
33
|
+
// don't use import here, it will break the build
|
|
34
|
+
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
|
35
|
+
exports.pkgJson = require('../../package.json');
|
|
36
|
+
let VERSION;
|
|
37
|
+
function applyMixin(target, mixin, includeConstructor = false) {
|
|
38
|
+
// Figure out the inheritance chain of the mixin
|
|
39
|
+
const inheritanceChain = [mixin];
|
|
40
|
+
// eslint-disable-next-line no-constant-condition
|
|
41
|
+
while (true) {
|
|
42
|
+
const current = inheritanceChain[0];
|
|
43
|
+
const base = Object.getPrototypeOf(current);
|
|
44
|
+
if (base?.prototype) {
|
|
45
|
+
inheritanceChain.unshift(base);
|
|
46
|
+
}
|
|
47
|
+
else {
|
|
48
|
+
break;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
for (const ctor of inheritanceChain) {
|
|
52
|
+
for (const prop of Object.getOwnPropertyNames(ctor.prototype)) {
|
|
53
|
+
// Do not override the constructor
|
|
54
|
+
if (includeConstructor || prop !== 'constructor') {
|
|
55
|
+
Object.defineProperty(target.prototype, prop, Object.getOwnPropertyDescriptor(ctor.prototype, prop) ??
|
|
56
|
+
Object.create(null));
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
exports.applyMixin = applyMixin;
|
|
62
|
+
function padNumber(num, digits) {
|
|
63
|
+
return num ? num.toString().padStart(digits, '0') : 'unknown';
|
|
64
|
+
}
|
|
65
|
+
exports.padNumber = padNumber;
|
|
66
|
+
function deepEqual(a, b) {
|
|
67
|
+
return JSON.stringify(a) === JSON.stringify(b);
|
|
68
|
+
}
|
|
69
|
+
exports.deepEqual = deepEqual;
|
|
70
|
+
function fileDate(date) {
|
|
71
|
+
date = date || new Date();
|
|
72
|
+
return date.toISOString().slice(-24).replace(/\D/g, '').slice(0, 14);
|
|
73
|
+
}
|
|
74
|
+
exports.fileDate = fileDate;
|
|
75
|
+
/** Where package.json is */
|
|
76
|
+
exports.basePath = (0, path_1.resolve)(__dirname, '..', '..');
|
|
77
|
+
/**
|
|
78
|
+
* Get the base root path to application directory. When we are in a `pkg` environment
|
|
79
|
+
* the path of the snapshot is not writable
|
|
80
|
+
*/
|
|
81
|
+
function getPath(write) {
|
|
82
|
+
if (write && hasProperty(process, 'pkg'))
|
|
83
|
+
return process.cwd();
|
|
84
|
+
else
|
|
85
|
+
return exports.basePath;
|
|
86
|
+
}
|
|
87
|
+
exports.getPath = getPath;
|
|
88
|
+
/**
|
|
89
|
+
* path.join wrapper, the first option can be a boolean and it will automatically fetch the root path
|
|
90
|
+
* passing the boolean to getPath
|
|
91
|
+
*/
|
|
92
|
+
function joinPath(write, ...paths) {
|
|
93
|
+
if (typeof write === 'boolean') {
|
|
94
|
+
write = getPath(write);
|
|
95
|
+
}
|
|
96
|
+
return path_1.default.join(write, ...paths);
|
|
97
|
+
}
|
|
98
|
+
exports.joinPath = joinPath;
|
|
99
|
+
/**
|
|
100
|
+
* Join props with a `_` and skips undefined props
|
|
101
|
+
*/
|
|
102
|
+
function joinProps(...props) {
|
|
103
|
+
props = props || [];
|
|
104
|
+
let ret = props[0].toString() || '';
|
|
105
|
+
for (let i = 1; i < props.length; i++) {
|
|
106
|
+
const p = props[i];
|
|
107
|
+
if (p !== null && p !== undefined && p !== '') {
|
|
108
|
+
ret += '_' + (typeof p === 'number' ? p.toString() : p);
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
return ret;
|
|
112
|
+
}
|
|
113
|
+
exports.joinProps = joinProps;
|
|
114
|
+
/**
|
|
115
|
+
* Checks if an object is a valueId, returns error otherwise
|
|
116
|
+
*/
|
|
117
|
+
function isValueId(v) {
|
|
118
|
+
if (typeof v.commandClass !== 'number' || v.commandClass < 0) {
|
|
119
|
+
return 'invalid `commandClass`';
|
|
120
|
+
}
|
|
121
|
+
if (v.endpoint !== undefined && v.endpoint < 0) {
|
|
122
|
+
return 'invalid `endpoint`';
|
|
123
|
+
}
|
|
124
|
+
if (v.property === undefined ||
|
|
125
|
+
(typeof v.property !== 'string' && typeof v.property !== 'number')) {
|
|
126
|
+
return 'invalid `property`';
|
|
127
|
+
}
|
|
128
|
+
if (v.propertyKey !== undefined &&
|
|
129
|
+
typeof v.propertyKey !== 'string' &&
|
|
130
|
+
typeof v.propertyKey !== 'number') {
|
|
131
|
+
return 'invalid `propertyKey`';
|
|
132
|
+
}
|
|
133
|
+
return true;
|
|
134
|
+
}
|
|
135
|
+
exports.isValueId = isValueId;
|
|
136
|
+
/**
|
|
137
|
+
* Deep copy of an object
|
|
138
|
+
*/
|
|
139
|
+
function copy(obj) {
|
|
140
|
+
return JSON.parse(JSON.stringify(obj));
|
|
141
|
+
}
|
|
142
|
+
exports.copy = copy;
|
|
143
|
+
/**
|
|
144
|
+
* Converts a decimal to an hex number of 4 digits and `0x` as prefix
|
|
145
|
+
*/
|
|
146
|
+
function num2hex(num) {
|
|
147
|
+
const hex = num >= 0 ? num.toString(16) : 'XXXX';
|
|
148
|
+
return '0x' + '0'.repeat(4 - hex.length) + hex;
|
|
149
|
+
}
|
|
150
|
+
exports.num2hex = num2hex;
|
|
151
|
+
/**
|
|
152
|
+
* Gets the actual package.json version with also the git revision number at the end of it
|
|
153
|
+
*/
|
|
154
|
+
function getVersion() {
|
|
155
|
+
if (!VERSION) {
|
|
156
|
+
try {
|
|
157
|
+
// try to get short sha of last commit
|
|
158
|
+
let rev = (0, fs_1.readFileSync)('.git/HEAD').toString().trim();
|
|
159
|
+
if (rev.indexOf(':') !== -1) {
|
|
160
|
+
rev = (0, fs_1.readFileSync)('.git/' + rev.substring(5))
|
|
161
|
+
.toString()
|
|
162
|
+
.trim();
|
|
163
|
+
}
|
|
164
|
+
VERSION = `${exports.pkgJson.version}${rev ? '.' + rev.substring(0, 7) : ''}`;
|
|
165
|
+
}
|
|
166
|
+
catch {
|
|
167
|
+
VERSION = exports.pkgJson.version;
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
return VERSION;
|
|
171
|
+
}
|
|
172
|
+
exports.getVersion = getVersion;
|
|
173
|
+
/**
|
|
174
|
+
* Sanitize chars of a string to use in a topic
|
|
175
|
+
*
|
|
176
|
+
*/
|
|
177
|
+
function sanitizeTopic(str, sanitizeSlash = false) {
|
|
178
|
+
if (typeof str === 'number' || !str)
|
|
179
|
+
return str.toString();
|
|
180
|
+
if (sanitizeSlash) {
|
|
181
|
+
str = removeSlash(str);
|
|
182
|
+
}
|
|
183
|
+
// replace spaces with '_'
|
|
184
|
+
str = str.replace(/\s/g, '_');
|
|
185
|
+
// remove special chars
|
|
186
|
+
return str.replace(/[^A-Za-z0-9-_À-ÖØ-öø-ÿ/]/g, '');
|
|
187
|
+
}
|
|
188
|
+
exports.sanitizeTopic = sanitizeTopic;
|
|
189
|
+
/**
|
|
190
|
+
* Removes `/` chars from strings
|
|
191
|
+
*/
|
|
192
|
+
function removeSlash(str) {
|
|
193
|
+
return typeof str === 'number' ? str.toString() : str.replace(/\//g, '-');
|
|
194
|
+
}
|
|
195
|
+
exports.removeSlash = removeSlash;
|
|
196
|
+
/**
|
|
197
|
+
* Check if an object has a property
|
|
198
|
+
*/
|
|
199
|
+
// eslint-disable-next-line @typescript-eslint/ban-types
|
|
200
|
+
function hasProperty(obj, prop) {
|
|
201
|
+
return Object.prototype.hasOwnProperty.call(obj, prop);
|
|
202
|
+
}
|
|
203
|
+
exports.hasProperty = hasProperty;
|
|
204
|
+
/**
|
|
205
|
+
* Gets the size in a human readable form starting from bytes
|
|
206
|
+
*/
|
|
207
|
+
function humanSize(bytes) {
|
|
208
|
+
const sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB'];
|
|
209
|
+
if (bytes === 0) {
|
|
210
|
+
return 'n/a';
|
|
211
|
+
}
|
|
212
|
+
const i = Math.floor(Math.log(bytes) / Math.log(1024));
|
|
213
|
+
if (i === 0) {
|
|
214
|
+
return bytes + ' ' + sizes[i];
|
|
215
|
+
}
|
|
216
|
+
return (bytes / Math.pow(1024, i)).toFixed(1) + ' ' + sizes[i];
|
|
217
|
+
}
|
|
218
|
+
exports.humanSize = humanSize;
|
|
219
|
+
async function hashPsw(password) {
|
|
220
|
+
return new Promise((resolve, reject) => {
|
|
221
|
+
const salt = crypto_1.default.randomBytes(8).toString('hex');
|
|
222
|
+
crypto_1.default.scrypt(password, salt, 64, (err, derivedKey) => {
|
|
223
|
+
if (err)
|
|
224
|
+
reject(err);
|
|
225
|
+
resolve(salt + ':' + derivedKey.toString('hex'));
|
|
226
|
+
});
|
|
227
|
+
});
|
|
228
|
+
}
|
|
229
|
+
exports.hashPsw = hashPsw;
|
|
230
|
+
async function verifyPsw(password, hash) {
|
|
231
|
+
return new Promise((resolve, reject) => {
|
|
232
|
+
const [salt, key] = hash.split(':');
|
|
233
|
+
crypto_1.default.scrypt(password, salt, 64, (err, derivedKey) => {
|
|
234
|
+
if (err)
|
|
235
|
+
reject(err);
|
|
236
|
+
resolve(key === derivedKey.toString('hex'));
|
|
237
|
+
});
|
|
238
|
+
});
|
|
239
|
+
}
|
|
240
|
+
exports.verifyPsw = verifyPsw;
|
|
241
|
+
/**
|
|
242
|
+
* Checks if a string is a hex buffer
|
|
243
|
+
*/
|
|
244
|
+
function isBufferAsHex(str) {
|
|
245
|
+
return /^0x([a-fA-F0-9]{2})+$/.test(str);
|
|
246
|
+
}
|
|
247
|
+
exports.isBufferAsHex = isBufferAsHex;
|
|
248
|
+
/**
|
|
249
|
+
* Parses a buffer from a string has the form 0x[a-f0-9]+
|
|
250
|
+
*/
|
|
251
|
+
function bufferFromHex(hex) {
|
|
252
|
+
return Buffer.from(hex.substr(2), 'hex');
|
|
253
|
+
}
|
|
254
|
+
exports.bufferFromHex = bufferFromHex;
|
|
255
|
+
/**
|
|
256
|
+
* Converts a buffer to an hex string
|
|
257
|
+
*/
|
|
258
|
+
function buffer2hex(buffer) {
|
|
259
|
+
if (buffer.length === 0)
|
|
260
|
+
return '';
|
|
261
|
+
return `0x${buffer.toString('hex')}`;
|
|
262
|
+
}
|
|
263
|
+
exports.buffer2hex = buffer2hex;
|
|
264
|
+
function allSettled(promises) {
|
|
265
|
+
const wrappedPromises = promises.map((p) => Promise.resolve(p).then((val) => ({ status: 'fulfilled', value: val }), (err) => ({ status: 'rejected', reason: err })));
|
|
266
|
+
return Promise.all(wrappedPromises);
|
|
267
|
+
}
|
|
268
|
+
exports.allSettled = allSettled;
|
|
269
|
+
/** Parses a string to json with buffer decode support */
|
|
270
|
+
function parseJSON(str) {
|
|
271
|
+
return JSON.parse(str, (k, v) => {
|
|
272
|
+
if (v !== null &&
|
|
273
|
+
typeof v === 'object' &&
|
|
274
|
+
'type' in v &&
|
|
275
|
+
v.type === 'Buffer' &&
|
|
276
|
+
'data' in v &&
|
|
277
|
+
Array.isArray(v.data)) {
|
|
278
|
+
return Buffer.from(v.data);
|
|
279
|
+
}
|
|
280
|
+
return v;
|
|
281
|
+
});
|
|
282
|
+
}
|
|
283
|
+
exports.parseJSON = parseJSON;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
const { logger, zwaveClient, require } = this
|
|
2
|
+
const fs = require('fs')
|
|
3
|
+
const { join } = require('path')
|
|
4
|
+
const { storeDir } = require('../config/app')
|
|
5
|
+
// read file
|
|
6
|
+
const content = fs.readFileSync(join(storeDir, 'test.log'), 'utf8')
|
|
7
|
+
|
|
8
|
+
// write file
|
|
9
|
+
fs.writeFileSync(join(storeDir, 'test-copy.log'), content)
|
|
10
|
+
|
|
11
|
+
// read directory
|
|
12
|
+
const files = fs.readdirSync(storeDir)
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
// replace `undefined` with the id of the node you want to clone
|
|
2
|
+
const node = driver.controller.nodes.get(undefined);
|
|
3
|
+
|
|
4
|
+
// list here all the nodes ids you want to copy configuration to
|
|
5
|
+
const clonedNodes = [].map(n => driver.controller.nodes.get(n));
|
|
6
|
+
|
|
7
|
+
const values = node.getDefinedValueIDs()
|
|
8
|
+
|
|
9
|
+
for (const clonedNode of clonedNodes) {
|
|
10
|
+
for(const v of values) {
|
|
11
|
+
if(v.commandClass === 112) {
|
|
12
|
+
await clonedNode.setValue(v,
|
|
13
|
+
node.getValue(v)
|
|
14
|
+
)
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* This snippet can be used to ping dead nodes in your network
|
|
3
|
+
* ATTENTION: Be aware that this is not a good practise, if your nodes
|
|
4
|
+
* become dead, you should try to find out why as you will likely have connectivity
|
|
5
|
+
* issues. More info here: https://zwave-js.github.io/node-zwave-js/#/troubleshooting/connectivity-issues
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
driver.controller.nodes.forEach(async (node) => {
|
|
9
|
+
// if node is Dead
|
|
10
|
+
if (node.status === 3) {
|
|
11
|
+
// pinging it
|
|
12
|
+
await node.ping()
|
|
13
|
+
}
|
|
14
|
+
})
|