@deconz-community/ddf-validator 2.13.0 → 2.15.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.
- package/dist/ddf-schema.json +1 -1
- package/dist/ddf-validator.cjs +1 -1
- package/dist/ddf-validator.d.ts +9 -9
- package/dist/ddf-validator.mjs +226 -224
- package/package.json +16 -19
package/dist/ddf-validator.mjs
CHANGED
|
@@ -1,64 +1,62 @@
|
|
|
1
1
|
import { z as e } from "zod";
|
|
2
|
-
const E = "2.
|
|
2
|
+
const E = "2.15.0", y = {
|
|
3
3
|
"devcap1.schema.json": [
|
|
4
4
|
O,
|
|
5
5
|
_,
|
|
6
6
|
$,
|
|
7
|
-
|
|
7
|
+
w,
|
|
8
8
|
C
|
|
9
9
|
],
|
|
10
10
|
"constants2.schema.json": [
|
|
11
|
-
|
|
11
|
+
T
|
|
12
12
|
]
|
|
13
13
|
};
|
|
14
|
-
function O(t,
|
|
15
|
-
const
|
|
16
|
-
if (
|
|
14
|
+
function O(t, a, d) {
|
|
15
|
+
const o = typeof t.manufacturername == "string" && typeof t.modelid == "string";
|
|
16
|
+
if (o)
|
|
17
17
|
return;
|
|
18
|
-
const
|
|
19
|
-
if (
|
|
20
|
-
|
|
18
|
+
const c = Array.isArray(t.manufacturername) && Array.isArray(t.modelid);
|
|
19
|
+
if (c && t.manufacturername.length !== t.modelid.length) {
|
|
20
|
+
a.addIssue({
|
|
21
21
|
code: e.ZodIssueCode.invalid_intersection_types,
|
|
22
22
|
message: "When 'manufacturername' and 'modelid' are both arrays they should be the same length",
|
|
23
23
|
path: ["manufacturername", "modelid"]
|
|
24
24
|
});
|
|
25
25
|
return;
|
|
26
26
|
}
|
|
27
|
-
(
|
|
27
|
+
(o || c) === !1 && a.addIssue({
|
|
28
28
|
code: e.ZodIssueCode.invalid_intersection_types,
|
|
29
29
|
message: "Invalid properties 'manufacturername' and 'modelid' should have the same type",
|
|
30
30
|
path: ["manufacturername", "modelid"]
|
|
31
31
|
});
|
|
32
32
|
}
|
|
33
|
-
function _(t,
|
|
33
|
+
function _(t, a, d) {
|
|
34
34
|
if (!t.bindings)
|
|
35
35
|
return;
|
|
36
|
-
const
|
|
37
|
-
t.bindings.forEach((
|
|
38
|
-
|
|
39
|
-
|
|
36
|
+
const o = (s) => `0x${(typeof s == "number" ? s : Number.parseInt(s, 16)).toString(16)}`, c = {};
|
|
37
|
+
t.bindings.forEach((s) => {
|
|
38
|
+
s.bind === "unicast" && s.report && s.report.forEach((n) => {
|
|
39
|
+
n.max !== 65535 && (c[`${o(s["src.ep"])}.${o(s.cl)}.${o(n.at)}`] = n.max);
|
|
40
40
|
});
|
|
41
|
-
}), t.subdevices.forEach((
|
|
42
|
-
|
|
43
|
-
var
|
|
41
|
+
}), t.subdevices.forEach((s, n) => {
|
|
42
|
+
s.items.forEach((i, u) => {
|
|
43
|
+
var m;
|
|
44
44
|
if (i["refresh.interval"] && i.read && i.read.fn === "zcl") {
|
|
45
|
-
const h =
|
|
45
|
+
const h = o(i.read.ep ?? ((m = s.fingerprint) == null ? void 0 : m.endpoint) ?? s.uuid[1]), b = Array.isArray(i.read.at) ? i.read.at : [i.read.at];
|
|
46
46
|
for (let v = 0; v < b.length; v++) {
|
|
47
|
-
const g = `${h}.${
|
|
48
|
-
|
|
47
|
+
const g = `${h}.${o(i.read.cl)}.${o(b[v])}`;
|
|
48
|
+
c[g] !== void 0 && i["refresh.interval"] - 60 < c[g] && a.addIssue({
|
|
49
49
|
code: e.ZodIssueCode.custom,
|
|
50
|
-
message: `The refresh interval (${i["refresh.interval"]} - 60 = ${i["refresh.interval"] - 60}) should be greater than the binding max refresh value (${
|
|
51
|
-
path: ["subdevices",
|
|
50
|
+
message: `The refresh interval (${i["refresh.interval"]} - 60 = ${i["refresh.interval"] - 60}) should be greater than the binding max refresh value (${c[g]}) with a margin of 60 seconds`,
|
|
51
|
+
path: ["subdevices", n, "items", u, "refresh.interval"]
|
|
52
52
|
});
|
|
53
53
|
}
|
|
54
54
|
}
|
|
55
55
|
});
|
|
56
56
|
});
|
|
57
57
|
}
|
|
58
|
-
function $(t,
|
|
59
|
-
|
|
60
|
-
return;
|
|
61
|
-
const n = [
|
|
58
|
+
function $(t, a, d) {
|
|
59
|
+
const o = [
|
|
62
60
|
/*
|
|
63
61
|
{
|
|
64
62
|
description: 'a device should always have basic attributes.',
|
|
@@ -73,42 +71,40 @@ function $(t, r, c) {
|
|
|
73
71
|
},
|
|
74
72
|
*/
|
|
75
73
|
{
|
|
76
|
-
description: 'a
|
|
74
|
+
description: 'a device with "state/ct" need the "min" and "max" values for capability.',
|
|
77
75
|
if: {
|
|
78
|
-
|
|
79
|
-
// TODO Use the constants file to resolve the types too
|
|
80
|
-
"$TYPE_COLOR_TEMPERATURE_LIGHT",
|
|
81
|
-
"Color Temperature Light",
|
|
82
|
-
"$TYPE_EXTENDED_COLOR_LIGHT",
|
|
83
|
-
"Extended Color Light"
|
|
84
|
-
]
|
|
76
|
+
item: "state/ct"
|
|
85
77
|
},
|
|
86
78
|
need: {
|
|
87
79
|
item: [
|
|
88
|
-
"
|
|
80
|
+
"cap/color/ct/min",
|
|
81
|
+
"cap/color/ct/max"
|
|
82
|
+
// 'config/color/ct/startup',
|
|
89
83
|
]
|
|
90
84
|
}
|
|
91
85
|
},
|
|
92
86
|
{
|
|
93
|
-
description: 'a device with "
|
|
87
|
+
description: 'a device with "cap/color/ct/computes_xy" need the corresponding state/{x,y} items',
|
|
94
88
|
if: {
|
|
95
|
-
item:
|
|
89
|
+
item: "cap/color/ct/computes_xy"
|
|
96
90
|
},
|
|
97
91
|
need: {
|
|
98
92
|
item: [
|
|
99
|
-
"
|
|
100
|
-
"
|
|
101
|
-
|
|
93
|
+
"state/x",
|
|
94
|
+
"state/y",
|
|
95
|
+
"state/ct"
|
|
102
96
|
]
|
|
103
97
|
}
|
|
104
98
|
},
|
|
105
99
|
{
|
|
106
|
-
description: 'a device with "state/x" or "state/y" need the corresponding red,
|
|
100
|
+
description: 'a device with "state/x" or "state/y" need the corresponding cap/color/xy/{red,green,blue}/{x,y} items',
|
|
107
101
|
if: {
|
|
108
|
-
item:
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
102
|
+
item: {
|
|
103
|
+
or: [
|
|
104
|
+
"state/x",
|
|
105
|
+
"state/y"
|
|
106
|
+
]
|
|
107
|
+
}
|
|
112
108
|
},
|
|
113
109
|
need: {
|
|
114
110
|
item: [
|
|
@@ -120,107 +116,113 @@ function $(t, r, c) {
|
|
|
120
116
|
"cap/color/xy/red_y",
|
|
121
117
|
"cap/color/xy/green_y",
|
|
122
118
|
"cap/color/xy/blue_y"
|
|
123
|
-
// 'cap/color/ct/computes_xy',
|
|
124
119
|
]
|
|
125
120
|
}
|
|
126
121
|
},
|
|
127
122
|
{
|
|
128
|
-
description: 'a
|
|
123
|
+
description: 'a "(Extended) Color light" need ("state/x" and "state/y") or/and ("state/hue" and "state/sat") .',
|
|
129
124
|
if: {
|
|
130
|
-
type:
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
125
|
+
type: {
|
|
126
|
+
or: [
|
|
127
|
+
"$TYPE_EXTENDED_COLOR_LIGHT",
|
|
128
|
+
"Extended color light",
|
|
129
|
+
"$TYPE_COLOR_LIGHT",
|
|
130
|
+
"Color light"
|
|
131
|
+
]
|
|
132
|
+
}
|
|
134
133
|
},
|
|
135
134
|
need: {
|
|
136
|
-
item:
|
|
137
|
-
|
|
138
|
-
|
|
135
|
+
item: {
|
|
136
|
+
or: [
|
|
137
|
+
[
|
|
138
|
+
"state/x",
|
|
139
|
+
"state/y"
|
|
140
|
+
],
|
|
141
|
+
[
|
|
142
|
+
"state/hue",
|
|
143
|
+
"state/sat"
|
|
144
|
+
]
|
|
145
|
+
]
|
|
146
|
+
}
|
|
139
147
|
}
|
|
140
148
|
}
|
|
141
|
-
];
|
|
142
|
-
t.subdevices.forEach((
|
|
143
|
-
const
|
|
144
|
-
|
|
145
|
-
(Object.keys(
|
|
146
|
-
|
|
147
|
-
switch (u) {
|
|
149
|
+
], c = (s, n) => typeof s == "string" ? n(s) : Array.isArray(s) ? s.every((i) => c(i, n)) : "and" in s ? s.and.every((i) => c(i, n)) : "or" in s ? s.or.some((i) => c(i, n)) : !1;
|
|
150
|
+
t.subdevices.forEach((s, n) => {
|
|
151
|
+
const i = s.items.map((u) => u.name);
|
|
152
|
+
o.forEach((u) => {
|
|
153
|
+
(Object.keys(u.if).length === 0 || Object.entries(u.if).some(([m, h]) => {
|
|
154
|
+
switch (m) {
|
|
148
155
|
case "type":
|
|
149
|
-
return (
|
|
156
|
+
return c(h, (b) => b === s.type);
|
|
150
157
|
case "item":
|
|
151
|
-
return
|
|
152
|
-
var b;
|
|
153
|
-
return (b = i.if[u]) == null ? void 0 : b.includes(h);
|
|
154
|
-
});
|
|
158
|
+
return c(h, (b) => i.includes(b));
|
|
155
159
|
default:
|
|
156
160
|
return !1;
|
|
157
161
|
}
|
|
158
|
-
})) &&
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
});
|
|
164
|
-
});
|
|
162
|
+
})) && (c(u.need.item, (m) => i.includes(m)) || a.addIssue({
|
|
163
|
+
code: e.ZodIssueCode.custom,
|
|
164
|
+
message: `The device is missing some items because ${u.description}`,
|
|
165
|
+
path: ["subdevices", n, "items"]
|
|
166
|
+
}));
|
|
165
167
|
});
|
|
166
168
|
});
|
|
167
169
|
}
|
|
168
|
-
function
|
|
169
|
-
const
|
|
170
|
-
t.subdevices.forEach((
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
const
|
|
174
|
-
|
|
170
|
+
function w(t, a, d) {
|
|
171
|
+
const o = ["parse", "write"];
|
|
172
|
+
t.subdevices.forEach((c, s) => {
|
|
173
|
+
c.items.forEach((n, i) => {
|
|
174
|
+
o.forEach((u) => {
|
|
175
|
+
const m = n[u];
|
|
176
|
+
m !== void 0 && (m.fn === void 0 || m.fn === "zcl" || m.fn === "zcl:attr" || m.fn === "zcl:cmd") && (m.eval === void 0 && m.script === void 0 && a.addIssue({
|
|
175
177
|
code: e.ZodIssueCode.custom,
|
|
176
178
|
message: `The '${u}' function is missing 'eval' or 'script' option.`,
|
|
177
|
-
path: ["subdevices",
|
|
178
|
-
}),
|
|
179
|
+
path: ["subdevices", s, "items", i, u]
|
|
180
|
+
}), m.eval !== void 0 && m.script !== void 0 && a.addIssue({
|
|
179
181
|
code: e.ZodIssueCode.custom,
|
|
180
182
|
message: `The '${u}' function is having both 'eval' and 'script' option.`,
|
|
181
|
-
path: ["subdevices",
|
|
183
|
+
path: ["subdevices", s, "items", i, u]
|
|
182
184
|
}));
|
|
183
185
|
});
|
|
184
186
|
});
|
|
185
187
|
});
|
|
186
188
|
}
|
|
187
|
-
function
|
|
188
|
-
const
|
|
189
|
-
Object.keys(t).forEach((
|
|
190
|
-
if (!Object.keys(
|
|
191
|
-
if (!["$MF_", "$TYPE_"].some((
|
|
192
|
-
|
|
189
|
+
function T(t, a, d) {
|
|
190
|
+
const o = I();
|
|
191
|
+
Object.keys(t).forEach((c) => {
|
|
192
|
+
if (!Object.keys(o.shape).includes(c)) {
|
|
193
|
+
if (!["$MF_", "$TYPE_"].some((s) => c.startsWith(s))) {
|
|
194
|
+
a.addIssue({
|
|
193
195
|
code: e.ZodIssueCode.custom,
|
|
194
196
|
message: "The constant key should start with '$MF_' or '$TYPE_'",
|
|
195
|
-
path: [
|
|
197
|
+
path: [c]
|
|
196
198
|
});
|
|
197
199
|
return;
|
|
198
200
|
}
|
|
199
|
-
typeof t[
|
|
201
|
+
typeof t[c] != "string" && a.addIssue({
|
|
200
202
|
code: e.ZodIssueCode.custom,
|
|
201
203
|
message: "The constant value should be a string",
|
|
202
|
-
path: [
|
|
204
|
+
path: [c]
|
|
203
205
|
});
|
|
204
206
|
}
|
|
205
207
|
});
|
|
206
208
|
}
|
|
207
|
-
function C(t,
|
|
208
|
-
t.
|
|
209
|
-
const
|
|
210
|
-
if (!
|
|
211
|
-
|
|
209
|
+
function C(t, a, d) {
|
|
210
|
+
t.subdevices.forEach((o, c) => {
|
|
211
|
+
const s = d.subDevices[o.type];
|
|
212
|
+
if (!s) {
|
|
213
|
+
a.addIssue({
|
|
212
214
|
code: e.ZodIssueCode.custom,
|
|
213
|
-
message: `The device is missing the device definition for the type "${
|
|
214
|
-
path: ["subdevices",
|
|
215
|
+
message: `The device is missing the device definition for the type "${o.type}"`,
|
|
216
|
+
path: ["subdevices", c, "items"]
|
|
215
217
|
});
|
|
216
218
|
return;
|
|
217
219
|
}
|
|
218
|
-
let
|
|
219
|
-
|
|
220
|
-
|
|
220
|
+
let n = s.items;
|
|
221
|
+
s.items_optional && (n = n.filter((i) => !s.items_optional.includes(i))), n.forEach((i) => {
|
|
222
|
+
o.items.find((u) => u.name === i) || a.addIssue({
|
|
221
223
|
code: e.ZodIssueCode.custom,
|
|
222
|
-
message: `The device should have the item "${i}" because it is mandatory for devices of type "${
|
|
223
|
-
path: ["subdevices",
|
|
224
|
+
message: `The device should have the item "${i}" because it is mandatory for devices of type "${o.type}"`,
|
|
225
|
+
path: ["subdevices", c, "items"]
|
|
224
226
|
});
|
|
225
227
|
});
|
|
226
228
|
});
|
|
@@ -246,13 +248,13 @@ function M() {
|
|
|
246
248
|
"Invalid date value"
|
|
247
249
|
);
|
|
248
250
|
}
|
|
249
|
-
function
|
|
250
|
-
const
|
|
251
|
-
return t === void 0 ? e.string().regex(/^0x[0-9a-fA-F]+$/,
|
|
251
|
+
function r(t = void 0) {
|
|
252
|
+
const a = "Invalid hexadecimal value";
|
|
253
|
+
return t === void 0 ? e.string().regex(/^0x[0-9a-fA-F]+$/, a) : e.string().regex(new RegExp(`^0x[0-9a-fA-F]{${t}}$`), a);
|
|
252
254
|
}
|
|
253
255
|
function l() {
|
|
254
256
|
return e.union([
|
|
255
|
-
|
|
257
|
+
r(2),
|
|
256
258
|
e.number().min(0).max(255)
|
|
257
259
|
]);
|
|
258
260
|
}
|
|
@@ -260,9 +262,9 @@ function S() {
|
|
|
260
262
|
return e.custom((t) => {
|
|
261
263
|
if (!Array.isArray(t) || t.length % 2 !== 0)
|
|
262
264
|
return !1;
|
|
263
|
-
for (let
|
|
264
|
-
const
|
|
265
|
-
if (typeof
|
|
265
|
+
for (let a = 0; a < t.length; a += 2) {
|
|
266
|
+
const d = t[a], o = t[a + 1];
|
|
267
|
+
if (typeof d != "number" || typeof o != "string")
|
|
266
268
|
return !1;
|
|
267
269
|
}
|
|
268
270
|
return !0;
|
|
@@ -272,19 +274,19 @@ function j() {
|
|
|
272
274
|
return e.union([
|
|
273
275
|
e.tuple([
|
|
274
276
|
e.literal("$address.ext"),
|
|
275
|
-
|
|
277
|
+
r(2)
|
|
276
278
|
]),
|
|
277
279
|
e.tuple([
|
|
278
280
|
e.literal("$address.ext"),
|
|
279
|
-
|
|
280
|
-
|
|
281
|
+
r(2),
|
|
282
|
+
r(4)
|
|
281
283
|
])
|
|
282
284
|
]);
|
|
283
285
|
}
|
|
284
286
|
function f() {
|
|
285
287
|
return e.string();
|
|
286
288
|
}
|
|
287
|
-
function
|
|
289
|
+
function p() {
|
|
288
290
|
return e.string();
|
|
289
291
|
}
|
|
290
292
|
function J() {
|
|
@@ -294,37 +296,38 @@ function J() {
|
|
|
294
296
|
}),
|
|
295
297
|
e.strictObject({
|
|
296
298
|
fn: e.undefined().describe("Generic function to read ZCL attributes."),
|
|
297
|
-
at:
|
|
298
|
-
cl:
|
|
299
|
+
at: r(4).or(e.array(r(4))).describe("Attribute ID."),
|
|
300
|
+
cl: r(4).describe("Cluster ID."),
|
|
299
301
|
ep: e.optional(l()).describe("Endpoint, 255 means any endpoint, 0 means auto selected from subdevice."),
|
|
300
|
-
mf: e.optional(
|
|
301
|
-
eval: e.optional(
|
|
302
|
+
mf: e.optional(r(4)).describe("Manufacturer code, must be set to 0x0000 for non manufacturer specific commands."),
|
|
303
|
+
eval: e.optional(p()).describe("Javascript expression to transform the raw value.")
|
|
302
304
|
}),
|
|
303
305
|
e.strictObject({
|
|
304
306
|
fn: e.literal("zcl").describe("Generic function to read ZCL attributes."),
|
|
305
|
-
at:
|
|
306
|
-
cl:
|
|
307
|
+
at: r(4).or(e.array(r(4))).describe("Attribute ID."),
|
|
308
|
+
cl: r(4).describe("Cluster ID."),
|
|
307
309
|
ep: e.optional(l()).describe("Endpoint, 255 means any endpoint, 0 means auto selected from subdevice."),
|
|
308
|
-
mf: e.optional(
|
|
309
|
-
eval: e.optional(
|
|
310
|
+
mf: e.optional(r(4)).describe("Manufacturer code, must be set to 0x0000 for non manufacturer specific commands."),
|
|
311
|
+
eval: e.optional(p()).describe("Javascript expression to transform the raw value."),
|
|
310
312
|
script: e.optional(f()).describe("Relative path of a Javascript .js file.")
|
|
311
313
|
}).describe("Deprecated"),
|
|
312
314
|
e.strictObject({
|
|
313
315
|
fn: e.literal("zcl:attr").describe("Generic function to parse ZCL values from read/report commands."),
|
|
314
|
-
at:
|
|
315
|
-
cl:
|
|
316
|
+
at: r(4).or(e.array(r(4))).describe("String hex value or array of string hex values."),
|
|
317
|
+
cl: r(4).describe("Cluster ID."),
|
|
316
318
|
ep: e.optional(l()).describe("Endpoint, 255 means any endpoint, 0 means auto selected from subdevice."),
|
|
317
|
-
mf: e.optional(
|
|
318
|
-
eval: e.optional(
|
|
319
|
+
mf: e.optional(r(4)).describe("Manufacturer code, must be set to 0x0000 for non manufacturer specific commands."),
|
|
320
|
+
eval: e.optional(p()).describe("Javascript expression to transform the attribute value to the Item value."),
|
|
319
321
|
script: e.optional(f()).describe("Relative path of a Javascript .js file.")
|
|
320
322
|
}),
|
|
321
323
|
e.strictObject({
|
|
322
324
|
fn: e.literal("zcl:cmd").describe("Generic function to parse ZCL values from read/report commands."),
|
|
323
|
-
cl:
|
|
325
|
+
cl: r(4).describe("Cluster ID."),
|
|
324
326
|
ep: e.optional(l()).describe("Endpoint, 255 means any endpoint, 0 means auto selected from subdevice."),
|
|
325
|
-
mf: e.optional(
|
|
326
|
-
cmd: e.optional(
|
|
327
|
-
eval: e.optional(
|
|
327
|
+
mf: e.optional(r(4)).describe("Manufacturer code, must be set to 0x0000 for non manufacturer specific commands."),
|
|
328
|
+
cmd: e.optional(r(2)).describe("Zigbee command."),
|
|
329
|
+
eval: e.optional(p()).describe("Javascript expression to transform the attribute value to the Item value."),
|
|
330
|
+
fc: e.optional(r(2).or(e.number())).describe("Zigbee command frame control."),
|
|
328
331
|
script: e.optional(f()).describe("Relative path of a Javascript .js file.")
|
|
329
332
|
}),
|
|
330
333
|
e.strictObject({
|
|
@@ -338,42 +341,42 @@ function Z() {
|
|
|
338
341
|
return e.discriminatedUnion("fn", [
|
|
339
342
|
e.strictObject({
|
|
340
343
|
fn: e.undefined().describe("Generic function to parse ZCL attributes and commands."),
|
|
341
|
-
at: e.optional(
|
|
342
|
-
cl:
|
|
344
|
+
at: e.optional(r(4).or(e.array(r(4)))).describe("Attribute ID."),
|
|
345
|
+
cl: r(4).describe("Cluster ID."),
|
|
343
346
|
cppsrc: e.optional(e.string()),
|
|
344
347
|
ep: e.optional(l()).describe("Endpoint, 255 means any endpoint, 0 means auto selected from subdevice."),
|
|
345
|
-
cmd: e.optional(
|
|
346
|
-
mf: e.optional(
|
|
347
|
-
eval: e.optional(
|
|
348
|
+
cmd: e.optional(r(2)).describe("Zigbee command."),
|
|
349
|
+
mf: e.optional(r(4)).describe("Manufacturer code, must be set to 0x0000 for non manufacturer specific commands."),
|
|
350
|
+
eval: e.optional(p()).describe("Javascript expression to transform the raw value."),
|
|
348
351
|
script: e.optional(f()).describe("Relative path of a Javascript .js file.")
|
|
349
352
|
}),
|
|
350
353
|
e.strictObject({
|
|
351
354
|
fn: e.literal("zcl").describe("Generic function to parse ZCL attributes and commands."),
|
|
352
|
-
at: e.optional(
|
|
353
|
-
cl:
|
|
355
|
+
at: e.optional(r(4).or(e.array(r(4)))).describe("Attribute ID."),
|
|
356
|
+
cl: r(4).describe("Cluster ID."),
|
|
354
357
|
cppsrc: e.optional(e.string()),
|
|
355
358
|
ep: e.optional(l()).describe("Endpoint, 255 means any endpoint, 0 means auto selected from subdevice."),
|
|
356
|
-
cmd: e.optional(
|
|
357
|
-
mf: e.optional(
|
|
358
|
-
eval: e.optional(
|
|
359
|
+
cmd: e.optional(r(2)).describe("Zigbee command."),
|
|
360
|
+
mf: e.optional(r(4)).describe("Manufacturer code, must be set to 0x0000 for non manufacturer specific commands."),
|
|
361
|
+
eval: e.optional(p()).describe("Javascript expression to transform the raw value."),
|
|
359
362
|
script: e.optional(f()).describe("Relative path of a Javascript .js file.")
|
|
360
363
|
}).describe("Deprecated"),
|
|
361
364
|
e.strictObject({
|
|
362
365
|
fn: e.literal("zcl:attr").describe("Generic function to parse ZCL values from read/report commands."),
|
|
363
|
-
at:
|
|
364
|
-
cl:
|
|
366
|
+
at: r(4).or(e.array(r(4))).describe("String hex value or array of string hex values."),
|
|
367
|
+
cl: r(4).describe("Cluster ID."),
|
|
365
368
|
ep: e.optional(l()).describe("Endpoint, 255 means any endpoint, 0 means auto selected from subdevice."),
|
|
366
|
-
mf: e.optional(
|
|
367
|
-
eval: e.optional(
|
|
369
|
+
mf: e.optional(r(4)).describe("Manufacturer code, must be set to 0x0000 for non manufacturer specific commands."),
|
|
370
|
+
eval: e.optional(p()).describe("Javascript expression to transform the attribute value to the Item value."),
|
|
368
371
|
script: e.optional(f()).describe("Relative path of a Javascript .js file.")
|
|
369
372
|
}),
|
|
370
373
|
e.strictObject({
|
|
371
374
|
fn: e.literal("zcl:cmd").describe("Generic function to parse ZCL values from read/report commands."),
|
|
372
|
-
cl:
|
|
375
|
+
cl: r(4).describe("Cluster ID."),
|
|
373
376
|
ep: e.optional(l()).describe("Endpoint, 255 means any endpoint, 0 means auto selected from subdevice."),
|
|
374
|
-
mf: e.optional(
|
|
375
|
-
cmd: e.optional(
|
|
376
|
-
eval: e.optional(
|
|
377
|
+
mf: e.optional(r(4)).describe("Manufacturer code, must be set to 0x0000 for non manufacturer specific commands."),
|
|
378
|
+
cmd: e.optional(r(2)).describe("Zigbee command."),
|
|
379
|
+
eval: e.optional(p()).describe("Javascript expression to transform the attribute value to the Item value."),
|
|
377
380
|
script: e.optional(f()).describe("Relative path of a Javascript .js file.")
|
|
378
381
|
}),
|
|
379
382
|
e.strictObject({
|
|
@@ -393,16 +396,16 @@ function Z() {
|
|
|
393
396
|
e.strictObject({
|
|
394
397
|
fn: e.literal("xiaomi:special").describe("Generic function to parse custom Xiaomi attributes and commands."),
|
|
395
398
|
ep: e.optional(l()).describe("Endpoint, 255 means any endpoint, 0 means auto selected from subdevice."),
|
|
396
|
-
mf: e.optional(
|
|
397
|
-
at: e.optional(
|
|
398
|
-
idx:
|
|
399
|
-
eval: e.optional(
|
|
399
|
+
mf: e.optional(r(4)).describe("Manufacturer code, must be set to 0x0000 for non manufacturer specific commands."),
|
|
400
|
+
at: e.optional(r(4)).describe("Attribute ID. The attribute to parse, shall be 0xff01, 0xff02 or 0x00f7"),
|
|
401
|
+
idx: r(2).describe("A 8-bit string hex value."),
|
|
402
|
+
eval: e.optional(p()).describe("Javascript expression to transform the raw value."),
|
|
400
403
|
script: e.optional(f()).describe("Relative path of a Javascript .js file.")
|
|
401
404
|
}),
|
|
402
405
|
e.strictObject({
|
|
403
406
|
fn: e.literal("tuya").describe("Generic function to parse Tuya data."),
|
|
404
407
|
dpid: e.number().describe("Data point ID. 1-255 the datapoint ID."),
|
|
405
|
-
eval: e.optional(
|
|
408
|
+
eval: e.optional(p()).describe("Javascript expression to transform the raw value."),
|
|
406
409
|
script: e.optional(f()).describe("Relative path of a Javascript .js file.")
|
|
407
410
|
})
|
|
408
411
|
]).refine((t) => !("eval" in t && "script" in t), {
|
|
@@ -416,55 +419,54 @@ function R() {
|
|
|
416
419
|
}),
|
|
417
420
|
e.strictObject({
|
|
418
421
|
fn: e.undefined(),
|
|
419
|
-
at: e.optional(
|
|
422
|
+
at: e.optional(r(4).or(e.array(r(4)))).describe("Attribute ID."),
|
|
420
423
|
"state.timeout": e.optional(e.number()),
|
|
421
424
|
"change.timeout": e.optional(e.number()),
|
|
422
|
-
cl:
|
|
423
|
-
dt:
|
|
425
|
+
cl: r(4).describe("Cluster ID."),
|
|
426
|
+
dt: r(2).describe("Data type."),
|
|
424
427
|
ep: e.optional(l()).describe("Endpoint, 255 means any endpoint, 0 means auto selected from subdevice."),
|
|
425
|
-
mf: e.optional(
|
|
426
|
-
eval: e.optional(
|
|
428
|
+
mf: e.optional(r(4)).describe("Manufacturer code, must be set to 0x0000 for non manufacturer specific commands."),
|
|
429
|
+
eval: e.optional(p()).describe("Javascript expression to transform the raw value."),
|
|
427
430
|
script: e.optional(f()).describe("Relative path of a Javascript .js file.")
|
|
428
431
|
}),
|
|
429
432
|
e.strictObject({
|
|
430
433
|
fn: e.literal("zcl"),
|
|
431
|
-
at: e.optional(
|
|
434
|
+
at: e.optional(r(4).or(e.array(r(4)))).describe("Attribute ID."),
|
|
432
435
|
"state.timeout": e.optional(e.number()),
|
|
433
436
|
"change.timeout": e.optional(e.number()),
|
|
434
|
-
cl:
|
|
435
|
-
dt:
|
|
437
|
+
cl: r(4).describe("Cluster ID."),
|
|
438
|
+
dt: r(2).describe("Data type."),
|
|
436
439
|
ep: e.optional(l()).describe("Endpoint, 255 means any endpoint, 0 means auto selected from subdevice."),
|
|
437
|
-
mf: e.optional(
|
|
438
|
-
eval: e.optional(
|
|
440
|
+
mf: e.optional(r(4)).describe("Manufacturer code, must be set to 0x0000 for non manufacturer specific commands."),
|
|
441
|
+
eval: e.optional(p()).describe("Javascript expression to transform the raw value."),
|
|
439
442
|
script: e.optional(f()).describe("Relative path of a Javascript .js file.")
|
|
440
443
|
}).describe("Deprecated"),
|
|
441
444
|
e.strictObject({
|
|
442
445
|
fn: e.literal("zcl:attr").describe("Generic function to parse ZCL values from read/report commands."),
|
|
443
|
-
at:
|
|
446
|
+
at: r(4).or(e.array(r(4))).describe("String hex value or array of string hex values."),
|
|
444
447
|
"state.timeout": e.optional(e.number()),
|
|
445
448
|
"change.timeout": e.optional(e.number()),
|
|
446
|
-
cl:
|
|
447
|
-
dt:
|
|
449
|
+
cl: r(4).describe("Cluster ID."),
|
|
450
|
+
dt: r(2).describe("Data type."),
|
|
448
451
|
ep: e.optional(l()).describe("Endpoint, 255 means any endpoint, 0 means auto selected from subdevice."),
|
|
449
|
-
mf: e.optional(
|
|
450
|
-
eval: e.optional(
|
|
452
|
+
mf: e.optional(r(4)).describe("Manufacturer code, must be set to 0x0000 for non manufacturer specific commands."),
|
|
453
|
+
eval: e.optional(p()).describe("Javascript expression to transform the attribute value to the Item value."),
|
|
451
454
|
script: e.optional(f()).describe("Relative path of a Javascript .js file.")
|
|
452
455
|
}),
|
|
453
456
|
e.strictObject({
|
|
454
457
|
fn: e.literal("zcl:cmd").describe("Generic function to parse ZCL values from read/report commands."),
|
|
455
|
-
cl:
|
|
456
|
-
dt: a(2).describe("Data type."),
|
|
458
|
+
cl: r(4).describe("Cluster ID."),
|
|
457
459
|
ep: e.optional(l()).describe("Endpoint, 255 means any endpoint, 0 means auto selected from subdevice."),
|
|
458
|
-
mf: e.optional(
|
|
459
|
-
cmd: e.optional(
|
|
460
|
-
eval: e.optional(
|
|
460
|
+
mf: e.optional(r(4)).describe("Manufacturer code, must be set to 0x0000 for non manufacturer specific commands."),
|
|
461
|
+
cmd: e.optional(r(2)).describe("Zigbee command."),
|
|
462
|
+
eval: e.optional(p()).describe("Javascript expression to transform the attribute value to the Item value."),
|
|
461
463
|
script: e.optional(f()).describe("Relative path of a Javascript .js file.")
|
|
462
464
|
}),
|
|
463
465
|
e.strictObject({
|
|
464
466
|
fn: e.literal("tuya").describe("Generic function to write Tuya data."),
|
|
465
467
|
dpid: e.number().describe("Data point ID. 1-255 the datapoint ID."),
|
|
466
|
-
dt:
|
|
467
|
-
eval: e.optional(
|
|
468
|
+
dt: r(2).describe("Data type."),
|
|
469
|
+
eval: e.optional(p()).describe("Javascript expression to transform the raw value."),
|
|
468
470
|
script: e.optional(f()).describe("Relative path of a Javascript .js file.")
|
|
469
471
|
})
|
|
470
472
|
]).refine((t) => !("eval" in t && "script" in t), {
|
|
@@ -536,32 +538,32 @@ function G(t) {
|
|
|
536
538
|
modelid: e.string().or(e.array(e.string())).describe("Model ID from Basic Cluster."),
|
|
537
539
|
vendor: e.optional(e.string()).describe("Friendly name of the manufacturer."),
|
|
538
540
|
comment: e.optional(e.string()),
|
|
539
|
-
matchexpr: e.optional(
|
|
541
|
+
matchexpr: e.optional(p()).describe("Need to return true for the DDF be used."),
|
|
540
542
|
path: e.optional(f()).describe("DDF path, useless, can be removed."),
|
|
541
543
|
product: e.optional(e.string()).describe("Complements the model id to be shown in the UI."),
|
|
542
544
|
sleeper: e.optional(e.boolean()).describe("Sleeping devices can only receive when awake."),
|
|
543
545
|
supportsMgmtBind: e.optional(e.boolean()),
|
|
544
546
|
status: e.enum(["Draft", "Bronze", "Silver", "Gold"]).describe("The code quality of the DDF file."),
|
|
545
547
|
subdevices: e.array(F(t)).describe("Devices section."),
|
|
546
|
-
bindings: e.optional(e.array(
|
|
548
|
+
bindings: e.optional(e.array(k())).describe("Bindings section.")
|
|
547
549
|
});
|
|
548
550
|
}
|
|
549
551
|
function F(t) {
|
|
550
552
|
return e.strictObject({
|
|
551
553
|
type: e.union([
|
|
552
554
|
e.enum(Object.keys(t.deviceTypes), {
|
|
553
|
-
errorMap: (
|
|
555
|
+
errorMap: (a, d) => a.code === "invalid_enum_value" ? { message: `Invalid enum value. Expected type from generic attributes definition, received '${a.received}'` } : { message: d.defaultError }
|
|
554
556
|
}),
|
|
555
557
|
e.string().regex(/^(?!\$TYPE_).*/g, "The type start with $TYPE_ but is not present in constants.json")
|
|
556
558
|
]),
|
|
557
559
|
restapi: e.enum(["/lights", "/sensors"]),
|
|
558
560
|
uuid: j(),
|
|
559
561
|
fingerprint: e.optional(e.strictObject({
|
|
560
|
-
profile:
|
|
561
|
-
device:
|
|
562
|
+
profile: r(4),
|
|
563
|
+
device: r(4),
|
|
562
564
|
endpoint: l(),
|
|
563
|
-
in: e.optional(e.array(
|
|
564
|
-
out: e.optional(e.array(
|
|
565
|
+
in: e.optional(e.array(r(4))),
|
|
566
|
+
out: e.optional(e.array(r(4)))
|
|
565
567
|
})),
|
|
566
568
|
meta: e.optional(e.strictObject({
|
|
567
569
|
// TODO validate this
|
|
@@ -572,51 +574,51 @@ function F(t) {
|
|
|
572
574
|
buttons: e.optional(e.any()),
|
|
573
575
|
// TODO validate this
|
|
574
576
|
buttonevents: e.optional(e.any()),
|
|
575
|
-
items: e.array(
|
|
577
|
+
items: e.array(z(t)),
|
|
576
578
|
example: e.optional(e.unknown())
|
|
577
579
|
});
|
|
578
580
|
}
|
|
579
|
-
function
|
|
581
|
+
function z(t) {
|
|
580
582
|
return D().omit({
|
|
581
583
|
$schema: !0,
|
|
582
584
|
schema: !0,
|
|
583
585
|
id: !0
|
|
584
586
|
}).extend({
|
|
585
587
|
name: e.enum(t.attributes, {
|
|
586
|
-
errorMap: (
|
|
588
|
+
errorMap: (a, d) => a.code === "invalid_enum_value" ? { message: `Invalid enum value. Expected item from generic attributes definition, received '${a.received}'` } : { message: d.defaultError }
|
|
587
589
|
}).describe("Item name.")
|
|
588
590
|
});
|
|
589
591
|
}
|
|
590
|
-
function
|
|
592
|
+
function k(t) {
|
|
591
593
|
return e.discriminatedUnion("bind", [
|
|
592
594
|
e.strictObject({
|
|
593
595
|
bind: e.literal("unicast"),
|
|
594
596
|
"src.ep": l().describe("Source endpoint."),
|
|
595
597
|
"dst.ep": e.optional(l()).describe("Destination endpoint, generaly 0x01."),
|
|
596
|
-
cl:
|
|
598
|
+
cl: r(4).describe("Cluster."),
|
|
597
599
|
report: e.optional(e.array(
|
|
598
600
|
e.strictObject({
|
|
599
|
-
at:
|
|
600
|
-
dt:
|
|
601
|
-
mf: e.optional(
|
|
601
|
+
at: r(4),
|
|
602
|
+
dt: r(2),
|
|
603
|
+
mf: e.optional(r(4)),
|
|
602
604
|
min: e.number(),
|
|
603
605
|
max: e.number(),
|
|
604
|
-
change: e.optional(
|
|
605
|
-
}).refine((
|
|
606
|
+
change: e.optional(r().or(e.number()))
|
|
607
|
+
}).refine((a) => a.min <= a.max, { message: "invalid report time, min should be smaller than max" })
|
|
606
608
|
))
|
|
607
609
|
}),
|
|
608
610
|
e.strictObject({
|
|
609
611
|
bind: e.literal("groupcast"),
|
|
610
612
|
"src.ep": l().describe("Source endpoint."),
|
|
611
|
-
cl:
|
|
613
|
+
cl: r(4).describe("Cluster."),
|
|
612
614
|
"config.group": e.number().min(0).max(255)
|
|
613
615
|
})
|
|
614
616
|
]);
|
|
615
617
|
}
|
|
616
618
|
function L(t) {
|
|
617
|
-
const
|
|
619
|
+
const a = e.array(
|
|
618
620
|
e.enum(t.attributes, {
|
|
619
|
-
errorMap: (
|
|
621
|
+
errorMap: (d, o) => d.code === "invalid_enum_value" ? { message: `Invalid enum value. Expected item from generic attributes definition, received '${d.received}'` } : { message: o.defaultError }
|
|
620
622
|
})
|
|
621
623
|
);
|
|
622
624
|
return e.strictObject({
|
|
@@ -624,7 +626,7 @@ function L(t) {
|
|
|
624
626
|
schema: e.literal("subdevice1.schema.json"),
|
|
625
627
|
type: e.union([
|
|
626
628
|
e.enum(Object.keys(t.deviceTypes), {
|
|
627
|
-
errorMap: (
|
|
629
|
+
errorMap: (d, o) => d.code === "invalid_enum_value" ? { message: `Invalid enum value. Expected type from generic attributes definition, received '${d.received}'` } : { message: o.defaultError }
|
|
628
630
|
}),
|
|
629
631
|
e.string().regex(/^(?!\$TYPE_).*/g, "The type start with $TYPE_ but is not present in constants.json")
|
|
630
632
|
]),
|
|
@@ -632,8 +634,8 @@ function L(t) {
|
|
|
632
634
|
restapi: e.enum(["/lights", "/sensors"]),
|
|
633
635
|
order: e.number(),
|
|
634
636
|
uuid: j(),
|
|
635
|
-
items:
|
|
636
|
-
items_optional: e.optional(
|
|
637
|
+
items: a,
|
|
638
|
+
items_optional: e.optional(a)
|
|
637
639
|
});
|
|
638
640
|
}
|
|
639
641
|
function x(t) {
|
|
@@ -643,64 +645,64 @@ function x(t) {
|
|
|
643
645
|
I(),
|
|
644
646
|
D(),
|
|
645
647
|
L(t)
|
|
646
|
-
]).superRefine((
|
|
647
|
-
switch (
|
|
648
|
+
]).superRefine((a, d) => {
|
|
649
|
+
switch (a.schema) {
|
|
648
650
|
case "devcap1.schema.json":
|
|
649
|
-
y[
|
|
651
|
+
y[a.schema].map((o) => o(a, d, t));
|
|
650
652
|
break;
|
|
651
653
|
case "constants2.schema.json":
|
|
652
|
-
y[
|
|
654
|
+
y[a.schema].map((o) => o(a, d, t));
|
|
653
655
|
break;
|
|
654
656
|
}
|
|
655
657
|
});
|
|
656
658
|
}
|
|
657
|
-
function
|
|
659
|
+
function P(t = {
|
|
658
660
|
attributes: [],
|
|
659
661
|
manufacturers: {},
|
|
660
662
|
deviceTypes: {},
|
|
661
663
|
resources: {},
|
|
662
664
|
subDevices: {}
|
|
663
665
|
}) {
|
|
664
|
-
let
|
|
665
|
-
const
|
|
666
|
-
|
|
666
|
+
let a = x(t);
|
|
667
|
+
const d = () => {
|
|
668
|
+
a = x(t);
|
|
667
669
|
};
|
|
668
|
-
return { generics: t, loadGeneric: (
|
|
669
|
-
const
|
|
670
|
-
switch (
|
|
670
|
+
return { generics: t, loadGeneric: (s) => {
|
|
671
|
+
const n = a.parse(s);
|
|
672
|
+
switch (n.schema) {
|
|
671
673
|
case "constants1.schema.json":
|
|
672
674
|
t.manufacturers = {
|
|
673
675
|
...t.manufacturers,
|
|
674
|
-
...
|
|
676
|
+
...n.manufacturers
|
|
675
677
|
}, t.deviceTypes = {
|
|
676
678
|
...t.deviceTypes,
|
|
677
|
-
...
|
|
679
|
+
...n["device-types"]
|
|
678
680
|
};
|
|
679
681
|
break;
|
|
680
682
|
case "constants2.schema.json": {
|
|
681
|
-
Object.keys(
|
|
682
|
-
t.manufacturers[i] =
|
|
683
|
-
}), Object.keys(
|
|
684
|
-
t.deviceTypes[i] =
|
|
683
|
+
Object.keys(n).filter((i) => i.startsWith("$MF_")).forEach((i) => {
|
|
684
|
+
t.manufacturers[i] = n[i];
|
|
685
|
+
}), Object.keys(n).filter((i) => i.startsWith("$TYPE_")).forEach((i) => {
|
|
686
|
+
t.deviceTypes[i] = n[i];
|
|
685
687
|
});
|
|
686
688
|
break;
|
|
687
689
|
}
|
|
688
690
|
case "resourceitem1.schema.json": {
|
|
689
|
-
if (t.attributes.includes(
|
|
690
|
-
throw new Error(`Got duplicate resource item with attribute id '${
|
|
691
|
-
const i =
|
|
691
|
+
if (t.attributes.includes(n.id))
|
|
692
|
+
throw new Error(`Got duplicate resource item with attribute id '${n.id}'.`);
|
|
693
|
+
const i = n, u = n.id;
|
|
692
694
|
delete i.$schema, delete i.schema, delete i.id, t.resources[u] = i, t.attributes.push(u);
|
|
693
695
|
break;
|
|
694
696
|
}
|
|
695
697
|
case "subdevice1.schema.json":
|
|
696
|
-
t.subDevices[
|
|
698
|
+
t.subDevices[n.type] = n, t.subDevices[n.name] = n;
|
|
697
699
|
break;
|
|
698
700
|
case "devcap1.schema.json":
|
|
699
701
|
throw new Error("Got invalid generic file, got data with schema 'devcap1.schema.json'.");
|
|
700
702
|
}
|
|
701
|
-
return
|
|
702
|
-
}, validate: (
|
|
703
|
+
return d(), !0;
|
|
704
|
+
}, validate: (s) => a.parse(s), getSchema: () => a, version: E };
|
|
703
705
|
}
|
|
704
706
|
export {
|
|
705
|
-
|
|
707
|
+
P as createValidator
|
|
706
708
|
};
|