homebridge-smartsystem 6.6.0 → 6.7.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/config.json +28 -32
- package/duotecno/types.js +33 -11
- package/duotecno/types.ts +100 -50
- package/package.json +1 -1
- package/server/HA-API.js +125 -0
- package/server/HA-API.ts +99 -0
- package/server/HB.js +169 -0
- package/server/HB.ts +161 -0
- package/server/powerbase.ts +1 -1
- package/server/smartapp.js +197 -184
- package/server/smartapp.ts +212 -173
- package/server/views/link-details.ejs +109 -0
- package/server/views/link-list.ejs +58 -0
- package/server/views/nav.ejs +1 -0
- package/server/views/scripts.ejs +6 -0
- package/server/webapp.js +2 -2
- package/server/webapp.ts +2 -2
package/config.json
CHANGED
|
@@ -134,7 +134,7 @@
|
|
|
134
134
|
}
|
|
135
135
|
]
|
|
136
136
|
},
|
|
137
|
-
"
|
|
137
|
+
"p11": {
|
|
138
138
|
"debug": false,
|
|
139
139
|
"rules": [],
|
|
140
140
|
"bindings": [
|
|
@@ -247,27 +247,25 @@
|
|
|
247
247
|
"method": "GET",
|
|
248
248
|
"type": "smappee",
|
|
249
249
|
"plug": "1"
|
|
250
|
-
}
|
|
250
|
+
}
|
|
251
|
+
],
|
|
252
|
+
"debug": false,
|
|
253
|
+
"username": "pi",
|
|
254
|
+
"password": "GMTecno",
|
|
255
|
+
"links": [
|
|
251
256
|
{
|
|
252
257
|
"logicalNodeAddress": 3,
|
|
253
|
-
"logicalAddress":
|
|
258
|
+
"logicalAddress": 30,
|
|
254
259
|
"masterAddress": "192.168.0.97",
|
|
255
260
|
"masterPort": 5001,
|
|
256
|
-
"name": "
|
|
257
|
-
"displayName": "
|
|
261
|
+
"name": "Blue LEDje",
|
|
262
|
+
"displayName": "Blue LEDje",
|
|
258
263
|
"extendedType": 0,
|
|
259
|
-
"
|
|
260
|
-
"
|
|
261
|
-
"
|
|
262
|
-
"value": 0,
|
|
263
|
-
"data": "{CurrentPosition: $}",
|
|
264
|
-
"header": "Pi:GMTecn",
|
|
265
|
-
"method": "PUT",
|
|
266
|
-
"type": "ohapi",
|
|
267
|
-
"plug": "http://Pi:GMTecno@192.168.0.99:8581/api/accessory/06e5b66f78fe0136ea075e742a7fb388587329a4717393b21aaa180083305704"
|
|
264
|
+
"accId": "986b901a30d92cb7bd0205be90f65786c2d87c9a95d8a0a60cb4c048deda5ce6",
|
|
265
|
+
"accName": "Tim Klein",
|
|
266
|
+
"type": "accessory"
|
|
268
267
|
}
|
|
269
|
-
]
|
|
270
|
-
"debug": false
|
|
268
|
+
]
|
|
271
269
|
},
|
|
272
270
|
"system": {
|
|
273
271
|
"language": "EN",
|
|
@@ -290,21 +288,6 @@
|
|
|
290
288
|
"252": " 20211003"
|
|
291
289
|
},
|
|
292
290
|
"debug": false
|
|
293
|
-
},
|
|
294
|
-
{
|
|
295
|
-
"address": "192.168.0.5",
|
|
296
|
-
"port": 5005,
|
|
297
|
-
"password": "duotecno",
|
|
298
|
-
"name": "GM",
|
|
299
|
-
"active": true,
|
|
300
|
-
"nodenames": {
|
|
301
|
-
"3": "IP Server",
|
|
302
|
-
"4": "Sonos",
|
|
303
|
-
"16": "Smartbox Living",
|
|
304
|
-
"17": "Switch Living",
|
|
305
|
-
"252": " 20220925"
|
|
306
|
-
},
|
|
307
|
-
"debug": false
|
|
308
291
|
}
|
|
309
292
|
],
|
|
310
293
|
"cunits": [
|
|
@@ -392,6 +375,18 @@
|
|
|
392
375
|
"used": "Y",
|
|
393
376
|
"group": 0
|
|
394
377
|
},
|
|
378
|
+
{
|
|
379
|
+
"logicalNodeAddress": 3,
|
|
380
|
+
"logicalAddress": 29,
|
|
381
|
+
"masterAddress": "192.168.0.97",
|
|
382
|
+
"masterPort": 5001,
|
|
383
|
+
"name": "Red LED",
|
|
384
|
+
"displayName": "Red LED",
|
|
385
|
+
"extendedType": 0,
|
|
386
|
+
"active": "N",
|
|
387
|
+
"used": "Y",
|
|
388
|
+
"group": 0
|
|
389
|
+
},
|
|
395
390
|
{
|
|
396
391
|
"logicalNodeAddress": 3,
|
|
397
392
|
"logicalAddress": 34,
|
|
@@ -466,5 +461,6 @@
|
|
|
466
461
|
"ip2": "",
|
|
467
462
|
"gateway2": ""
|
|
468
463
|
}
|
|
469
|
-
}
|
|
464
|
+
},
|
|
465
|
+
"p1": false
|
|
470
466
|
}
|
package/duotecno/types.js
CHANGED
|
@@ -14,7 +14,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
14
14
|
});
|
|
15
15
|
};
|
|
16
16
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
-
exports.makeInt = exports.now = exports.datetime = exports.time = exports.date = exports.watt = exports.hex = exports.two = exports.char = exports.ascii = exports.wait = exports.Sanitizers = exports.actionValueStr = exports.actionValue = exports.
|
|
17
|
+
exports.makeInt = exports.now = exports.datetime = exports.time = exports.date = exports.watt = exports.hex = exports.two = exports.char = exports.ascii = exports.wait = exports.Sanitizers = exports.actionValueStr = exports.actionValue = exports.kEmptyBinding = exports.kEmptyLink = exports.LinkType = exports.kEmptySwitch = exports.SwitchType = exports.kEmptyRule = exports.kEmptyAction = exports.RuleType = exports.Boundaries = exports.kEmptyCommRecord = exports.WriteError = exports.kEmptySettings = exports.kEmptyNetworkConfig = exports.kEmptyGroup = exports.kEmptyScene = exports.kEmptyUnitScene = exports.kEmptyUnit = exports.UnitExtendedType = exports.UnitType = exports.UnitMotorCmd = exports.UnitState = exports.NodeType = void 0;
|
|
18
18
|
// Node types
|
|
19
19
|
var NodeType;
|
|
20
20
|
(function (NodeType) {
|
|
@@ -126,6 +126,13 @@ var RuleType;
|
|
|
126
126
|
RuleType["kWater"] = "water";
|
|
127
127
|
})(RuleType = exports.RuleType || (exports.RuleType = {}));
|
|
128
128
|
;
|
|
129
|
+
exports.kEmptyAction = Object.assign(Object.assign({}, exports.kEmptyUnit), { value: false });
|
|
130
|
+
;
|
|
131
|
+
exports.kEmptyRule = {
|
|
132
|
+
type: "power", channel: "0", low: 30, high: 900,
|
|
133
|
+
actions: [Object.assign(Object.assign({}, exports.kEmptyUnit), { value: false }), Object.assign(Object.assign({}, exports.kEmptyUnit), { value: 50 }), Object.assign(Object.assign({}, exports.kEmptyUnit), { value: true })]
|
|
134
|
+
};
|
|
135
|
+
// Switches
|
|
129
136
|
var SwitchType;
|
|
130
137
|
(function (SwitchType) {
|
|
131
138
|
SwitchType["kNoType"] = "";
|
|
@@ -137,21 +144,19 @@ var SwitchType;
|
|
|
137
144
|
SwitchType["kOhSwitch"] = "oswitch";
|
|
138
145
|
SwitchType["kOhDimmer"] = "odimmer";
|
|
139
146
|
SwitchType["kOhUpDown"] = "oupdown";
|
|
140
|
-
SwitchType["kohAPI"] = "ohapi";
|
|
141
147
|
SwitchType["kSomfy"] = "somfy";
|
|
142
148
|
})(SwitchType = exports.SwitchType || (exports.SwitchType = {}));
|
|
143
|
-
;
|
|
149
|
+
exports.kEmptySwitch = Object.assign(Object.assign({}, exports.kEmptyUnit), { plug: 0, type: SwitchType.kNoType, unitName: "", name: "", data: "", method: "GET", header: "", username: "", password: "", nomacro: "N", nostop: "N" });
|
|
150
|
+
// Links
|
|
151
|
+
var LinkType;
|
|
152
|
+
(function (LinkType) {
|
|
153
|
+
LinkType["kNoType"] = "";
|
|
154
|
+
LinkType["kAccessory"] = "accessory";
|
|
155
|
+
})(LinkType = exports.LinkType || (exports.LinkType = {}));
|
|
156
|
+
exports.kEmptyLink = Object.assign(Object.assign({}, exports.kEmptyUnit), { type: LinkType.kAccessory, accName: "acc", accId: "" });
|
|
144
157
|
exports.kEmptyBinding = {
|
|
145
158
|
channel: "0", masterAddress: "0.0.0.0", masterPort: 5001, register: 0
|
|
146
159
|
};
|
|
147
|
-
exports.kEmptyAction = Object.assign(Object.assign({}, exports.kEmptyUnit), { value: false });
|
|
148
|
-
;
|
|
149
|
-
exports.kEmptyRule = {
|
|
150
|
-
type: "power", channel: "0", low: 30, high: 900,
|
|
151
|
-
actions: [Object.assign(Object.assign({}, exports.kEmptyUnit), { value: false }), Object.assign(Object.assign({}, exports.kEmptyUnit), { value: 50 }), Object.assign(Object.assign({}, exports.kEmptyUnit), { value: true })]
|
|
152
|
-
};
|
|
153
|
-
;
|
|
154
|
-
exports.kEmptySwitch = Object.assign(Object.assign({}, exports.kEmptyUnit), { plug: 0, type: SwitchType.kNoType, unitName: "", name: "", data: "", method: "GET", header: "", username: "", password: "", nomacro: "N", nostop: "N" });
|
|
155
160
|
;
|
|
156
161
|
;
|
|
157
162
|
;
|
|
@@ -249,9 +254,13 @@ exports.Sanitizers = {
|
|
|
249
254
|
config.port = config.port || 5002;
|
|
250
255
|
config.switches = config.switches || [];
|
|
251
256
|
config.switches = config.switches.map(sw => exports.Sanitizers.switchConfig(sw));
|
|
257
|
+
config.links = config.links || [];
|
|
258
|
+
config.links = config.links.map(sw => exports.Sanitizers.linkConfig(sw));
|
|
252
259
|
config.debug = config.debug || false;
|
|
253
260
|
config.apiHost = config.apiHost || "localhost";
|
|
254
261
|
config.apiPort = config.apiPort || 8581;
|
|
262
|
+
config.username = config.username || "admin";
|
|
263
|
+
config.password = config.password || "";
|
|
255
264
|
return config;
|
|
256
265
|
},
|
|
257
266
|
powerbase: function (config) {
|
|
@@ -285,6 +294,13 @@ exports.Sanitizers = {
|
|
|
285
294
|
cfg.addresses = (config === null || config === void 0 ? void 0 : config.addresses) || "";
|
|
286
295
|
return cfg;
|
|
287
296
|
},
|
|
297
|
+
linkConfig: function (aLink) {
|
|
298
|
+
const link = exports.Sanitizers.unitDef(aLink);
|
|
299
|
+
link.accId = aLink.accId || "";
|
|
300
|
+
link.accName = aLink.accName || "";
|
|
301
|
+
link.type = aLink.type || LinkType.kNoType;
|
|
302
|
+
return link;
|
|
303
|
+
},
|
|
288
304
|
switchConfig: function (aSwitch) {
|
|
289
305
|
const sw = exports.Sanitizers.unitDef(aSwitch);
|
|
290
306
|
sw.nomacro = aSwitch.nomacro || "N";
|
|
@@ -309,6 +325,12 @@ exports.Sanitizers = {
|
|
|
309
325
|
type: aSwitch.type, plug: aSwitch.plug,
|
|
310
326
|
data: aSwitch.data, method: aSwitch.method, header: aSwitch.header });
|
|
311
327
|
},
|
|
328
|
+
makeLinkConfig: function (aLink) {
|
|
329
|
+
return exports.Sanitizers.linkConfig({ name: aLink.name, unitName: aLink.unitName,
|
|
330
|
+
masterAddress: aLink.masterAddress, masterPort: aLink.masterPort,
|
|
331
|
+
logicalAddress: aLink.logicalAddress, logicalNodeAddress: aLink.logicalNodeAddress,
|
|
332
|
+
accName: aLink.accName, accId: aLink.accId, type: aLink.type });
|
|
333
|
+
},
|
|
312
334
|
ruleConfig(rule) {
|
|
313
335
|
rule = Object.assign({}, rule);
|
|
314
336
|
rule.channel = rule.channel || "0";
|
package/duotecno/types.ts
CHANGED
|
@@ -193,38 +193,17 @@ export const kEmptyCommRecord = { status: false, cmd: -1, message: [-1,0,0], res
|
|
|
193
193
|
export enum Boundaries {kLow = 0, kMid = 1, kHigh = 2};
|
|
194
194
|
export enum RuleType {kPower = "power", kCurrent = "current", kWater = "water"};
|
|
195
195
|
|
|
196
|
-
export enum SwitchType {
|
|
197
|
-
kNoType = "",
|
|
198
|
-
kSmappee = "smappee",
|
|
199
|
-
kRF = "RF",
|
|
200
|
-
kHTTPSwitch = "http",
|
|
201
|
-
kHTTPDimmer = "httpdim",
|
|
202
|
-
kHTTPUpDown = "httpupdown",
|
|
203
|
-
kOhSwitch = "oswitch",
|
|
204
|
-
kOhDimmer = "odimmer",
|
|
205
|
-
kOhUpDown = "oupdown",
|
|
206
|
-
kohAPI = "ohapi",
|
|
207
|
-
kSomfy = "somfy"
|
|
208
|
-
};
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
export interface Binding {
|
|
212
|
-
masterAddress: string;
|
|
213
|
-
masterPort: number;
|
|
214
|
-
register: number;
|
|
215
|
-
channel: string;
|
|
216
|
-
value?: number;
|
|
217
|
-
}
|
|
218
|
-
export const kEmptyBinding: Binding = {
|
|
219
|
-
channel: "0", masterAddress: "0.0.0.0", masterPort: 5001, register: 0
|
|
220
|
-
} as const;
|
|
221
196
|
|
|
222
197
|
|
|
198
|
+
///////////
|
|
199
|
+
// Rules //
|
|
200
|
+
///////////
|
|
223
201
|
export interface Action extends UnitDef {
|
|
224
202
|
value: number | boolean;
|
|
225
203
|
}
|
|
226
|
-
export const kEmptyAction: Action = {
|
|
227
|
-
|
|
204
|
+
export const kEmptyAction: Action = {
|
|
205
|
+
...kEmptyUnit, value: false
|
|
206
|
+
} as const;
|
|
228
207
|
|
|
229
208
|
export interface Rule {
|
|
230
209
|
type: string;
|
|
@@ -240,44 +219,78 @@ export const kEmptyRule: Rule = {
|
|
|
240
219
|
actions: [{...kEmptyUnit, value: false}, {...kEmptyUnit, value: 50}, {...kEmptyUnit, value: true}]
|
|
241
220
|
};
|
|
242
221
|
|
|
222
|
+
|
|
223
|
+
// Switches
|
|
224
|
+
|
|
225
|
+
export enum SwitchType {
|
|
226
|
+
kNoType = "",
|
|
227
|
+
kSmappee = "smappee",
|
|
228
|
+
kRF = "RF",
|
|
229
|
+
kHTTPSwitch = "http",
|
|
230
|
+
kHTTPDimmer = "httpdim",
|
|
231
|
+
kHTTPUpDown = "httpupdown",
|
|
232
|
+
kOhSwitch = "oswitch",
|
|
233
|
+
kOhDimmer = "odimmer",
|
|
234
|
+
kOhUpDown = "oupdown",
|
|
235
|
+
kSomfy = "somfy"
|
|
236
|
+
}
|
|
237
|
+
|
|
243
238
|
export interface Switch extends UnitDef {
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
method: string,
|
|
239
|
+
unitName: string;
|
|
240
|
+
type: SwitchType;
|
|
241
|
+
plug: number | string;
|
|
242
|
+
data: string;
|
|
243
|
+
header: string;
|
|
244
|
+
method: string;
|
|
251
245
|
username?: string;
|
|
252
246
|
password?: string;
|
|
253
247
|
unit?: Unit;
|
|
254
|
-
status?: number | boolean
|
|
255
|
-
value?: number | boolean | string
|
|
248
|
+
status?: number | boolean;
|
|
249
|
+
value?: number | boolean | string;
|
|
256
250
|
nomacro: string;
|
|
257
251
|
nostop: string;
|
|
258
|
-
}
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
export const kEmptySwitch: Switch = {
|
|
255
|
+
...kEmptyUnit, plug: 0, type: SwitchType.kNoType, unitName: "", name: "", data: "", method: "GET",
|
|
256
|
+
header: "", username: "", password: "", nomacro: "N", nostop: "N"
|
|
257
|
+
} as const;
|
|
262
258
|
|
|
263
259
|
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
switches: Array<Switch>;
|
|
260
|
+
// Links
|
|
261
|
+
export enum LinkType {
|
|
262
|
+
kNoType = "",
|
|
263
|
+
kAccessory = "accessory"
|
|
269
264
|
}
|
|
270
265
|
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
266
|
+
export interface Link extends UnitDef{
|
|
267
|
+
accName: string;
|
|
268
|
+
accId: string;
|
|
269
|
+
type: LinkType;
|
|
270
|
+
unit?: Unit;
|
|
271
|
+
status?: number | boolean;
|
|
272
|
+
value?: number | boolean | string
|
|
276
273
|
}
|
|
277
274
|
|
|
275
|
+
export const kEmptyLink: Link = {
|
|
276
|
+
...kEmptyUnit, type: LinkType.kAccessory, accName: "acc", accId: ""
|
|
277
|
+
} as const;
|
|
278
|
+
|
|
279
|
+
|
|
278
280
|
///////////
|
|
279
281
|
// Power //
|
|
280
282
|
///////////
|
|
283
|
+
export interface Binding {
|
|
284
|
+
masterAddress: string;
|
|
285
|
+
masterPort: number;
|
|
286
|
+
register: number;
|
|
287
|
+
channel: string;
|
|
288
|
+
value?: number;
|
|
289
|
+
}
|
|
290
|
+
export const kEmptyBinding: Binding = {
|
|
291
|
+
channel: "0", masterAddress: "0.0.0.0", masterPort: 5001, register: 0
|
|
292
|
+
} as const;
|
|
293
|
+
|
|
281
294
|
export interface PowerBaseConfig extends BaseConfig {
|
|
282
295
|
address: string;
|
|
283
296
|
rules: Array<Rule>;
|
|
@@ -292,6 +305,24 @@ export interface ShellyConfig extends PowerBaseConfig {
|
|
|
292
305
|
addresses: string;
|
|
293
306
|
}
|
|
294
307
|
|
|
308
|
+
|
|
309
|
+
/////////////////////
|
|
310
|
+
// Smartapp config //
|
|
311
|
+
/////////////////////
|
|
312
|
+
export interface BaseConfig {
|
|
313
|
+
debug?: boolean;
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
export interface SmartAppConfig extends BaseConfig {
|
|
317
|
+
port: number;
|
|
318
|
+
apiHost: string;
|
|
319
|
+
apiPort: number;
|
|
320
|
+
username: string; password: string;
|
|
321
|
+
switches: Array<Switch>;
|
|
322
|
+
links: Array<Link>;
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
|
|
295
326
|
////////////////
|
|
296
327
|
// Homebridge //
|
|
297
328
|
////////////////
|
|
@@ -434,9 +465,13 @@ export const Sanitizers = {
|
|
|
434
465
|
config.port = config.port || 5002;
|
|
435
466
|
config.switches = config.switches || [];
|
|
436
467
|
config.switches = config.switches.map(sw => Sanitizers.switchConfig(sw));
|
|
468
|
+
config.links = config.links || [];
|
|
469
|
+
config.links = config.links.map(sw => Sanitizers.linkConfig(sw));
|
|
437
470
|
config.debug = config.debug || false;
|
|
438
471
|
config.apiHost = config.apiHost || "localhost";
|
|
439
472
|
config.apiPort = config.apiPort || 8581;
|
|
473
|
+
config.username = config.username || "admin";
|
|
474
|
+
config.password = config.password || "";
|
|
440
475
|
|
|
441
476
|
return config;
|
|
442
477
|
},
|
|
@@ -476,6 +511,14 @@ export const Sanitizers = {
|
|
|
476
511
|
return cfg;
|
|
477
512
|
},
|
|
478
513
|
|
|
514
|
+
linkConfig: function(aLink): Link {
|
|
515
|
+
const link = <Link>Sanitizers.unitDef(aLink);
|
|
516
|
+
link.accId = aLink.accId || "";
|
|
517
|
+
link.accName = aLink.accName || "";
|
|
518
|
+
link.type = aLink.type || LinkType.kNoType;
|
|
519
|
+
return link;
|
|
520
|
+
},
|
|
521
|
+
|
|
479
522
|
switchConfig: function(aSwitch): Switch {
|
|
480
523
|
const sw = <Switch>Sanitizers.unitDef(aSwitch);
|
|
481
524
|
sw.nomacro = aSwitch.nomacro || "N";
|
|
@@ -503,6 +546,13 @@ export const Sanitizers = {
|
|
|
503
546
|
data: aSwitch.data, method: aSwitch.method, header: aSwitch.header });
|
|
504
547
|
},
|
|
505
548
|
|
|
549
|
+
makeLinkConfig: function(aLink): Link {
|
|
550
|
+
return Sanitizers.linkConfig({ name: aLink.name, unitName: aLink.unitName,
|
|
551
|
+
masterAddress: aLink.masterAddress, masterPort: aLink.masterPort,
|
|
552
|
+
logicalAddress: aLink.logicalAddress, logicalNodeAddress: aLink.logicalNodeAddress,
|
|
553
|
+
accName: aLink.accName, accId: aLink.accId, type: aLink.type });
|
|
554
|
+
},
|
|
555
|
+
|
|
506
556
|
ruleConfig(rule): Rule {
|
|
507
557
|
rule = {... rule};
|
|
508
558
|
rule.channel = rule.channel || "0";
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "homebridge-smartsystem",
|
|
3
3
|
"displayname": "Duotecno Bridge",
|
|
4
|
-
"version": "6.
|
|
4
|
+
"version": "6.7.0",
|
|
5
5
|
"description": "SmartServer (Proxy Websockets to TCP sockets, Smappee MQTT, Duotecno IP Nodes, Homekit interface)",
|
|
6
6
|
"main": "index.js",
|
|
7
7
|
"author": "Johan Coppieters",
|
package/server/HA-API.js
ADDED
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
+
});
|
|
10
|
+
};
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
exports.httpRequest = exports.ContentType = void 0;
|
|
13
|
+
const logger_1 = require("../duotecno/logger");
|
|
14
|
+
const http = require("http");
|
|
15
|
+
//////////////////////////////////
|
|
16
|
+
// Home Assistant API //
|
|
17
|
+
// and other http based APIs //
|
|
18
|
+
//////////////////////////////////
|
|
19
|
+
var ContentType;
|
|
20
|
+
(function (ContentType) {
|
|
21
|
+
ContentType[ContentType["form"] = 0] = "form";
|
|
22
|
+
ContentType[ContentType["plain"] = 1] = "plain";
|
|
23
|
+
ContentType[ContentType["none"] = 2] = "none";
|
|
24
|
+
ContentType[ContentType["json"] = 3] = "json";
|
|
25
|
+
})(ContentType = exports.ContentType || (exports.ContentType = {}));
|
|
26
|
+
;
|
|
27
|
+
function httpRequest(url, method = "GET", formdata = "", contentType = ContentType.form, header = "") {
|
|
28
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
29
|
+
if (url.indexOf("://") === -1)
|
|
30
|
+
url = "http://" + url;
|
|
31
|
+
return new Promise((resolve, reject) => {
|
|
32
|
+
try {
|
|
33
|
+
// const data = querystring.stringify(formdata);
|
|
34
|
+
const options = { method };
|
|
35
|
+
if (formdata) {
|
|
36
|
+
if (contentType === ContentType.form) {
|
|
37
|
+
options.headers = {
|
|
38
|
+
'Content-Type': 'application/x-www-form-urlencoded',
|
|
39
|
+
'Content-Length': Buffer.byteLength(formdata)
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
else if (contentType === ContentType.plain) {
|
|
43
|
+
options.headers = {
|
|
44
|
+
'Content-Type': 'text/plain',
|
|
45
|
+
'Accept': 'application/json'
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
else if (contentType === ContentType.json) {
|
|
49
|
+
options.headers = {
|
|
50
|
+
'Content-Type': 'application/json',
|
|
51
|
+
'Accept': '*/*'
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
;
|
|
56
|
+
// header provide as string or object
|
|
57
|
+
if (header) {
|
|
58
|
+
if (!options.headers)
|
|
59
|
+
options.headers = {};
|
|
60
|
+
if (typeof header === "string") {
|
|
61
|
+
if (header.substring(0, 1) === "{") {
|
|
62
|
+
try {
|
|
63
|
+
options.headers = Object.assign(Object.assign({}, options.headers), JSON.parse(header));
|
|
64
|
+
}
|
|
65
|
+
catch (e) {
|
|
66
|
+
(0, logger_1.err)("smartapp", "error parsing :" + header + " -> " + JSON.stringify(e));
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
else {
|
|
70
|
+
const s = header.split(":");
|
|
71
|
+
options.headers[s[0]] = s[1];
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
else {
|
|
75
|
+
// header is an object
|
|
76
|
+
options.headers = Object.assign(Object.assign({}, options.headers), header);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
(0, logger_1.debug)("smartapp", "Sending to " + url + " with options: " + JSON.stringify(options));
|
|
80
|
+
const req = http.request(url, options, res => {
|
|
81
|
+
let resp = "";
|
|
82
|
+
// res.setEncoding('utf8');
|
|
83
|
+
res.on('error', error => {
|
|
84
|
+
(0, logger_1.log)("smartapp", "The request to " + url + ", error: " + (error ? error.message : "unknown"));
|
|
85
|
+
reject(error);
|
|
86
|
+
});
|
|
87
|
+
res.on('data', chunk => {
|
|
88
|
+
resp += chunk;
|
|
89
|
+
});
|
|
90
|
+
res.on('end', () => {
|
|
91
|
+
// try to make something out of it...
|
|
92
|
+
try {
|
|
93
|
+
const x = JSON.parse(resp);
|
|
94
|
+
if ((x.type === "Buffer") && x.data)
|
|
95
|
+
x.data = x.data.toString();
|
|
96
|
+
(0, logger_1.debug)("smartapp", "http " + method + " -> " + res.statusCode + ": " + url + " = " + JSON.stringify(x).substring(0, 200) + "...");
|
|
97
|
+
resolve(x);
|
|
98
|
+
}
|
|
99
|
+
catch (e) {
|
|
100
|
+
(0, logger_1.err)("smartapp", "http " + method + " -> " + res.statusCode + ": " + url + " = " + resp);
|
|
101
|
+
resolve({ status: "NOK", result: resp });
|
|
102
|
+
}
|
|
103
|
+
;
|
|
104
|
+
});
|
|
105
|
+
});
|
|
106
|
+
if (formdata) {
|
|
107
|
+
req.write(formdata);
|
|
108
|
+
}
|
|
109
|
+
req.on("error", (e) => {
|
|
110
|
+
(0, logger_1.log)("smartapp", "The request to " + url + ", error: " + (e ? e.message : "unknown"));
|
|
111
|
+
});
|
|
112
|
+
req.on("timeout", (e) => {
|
|
113
|
+
(0, logger_1.log)("smartapp", "The request to " + url + ", timeout: " + (e ? e.message : "unknown"));
|
|
114
|
+
});
|
|
115
|
+
req.end();
|
|
116
|
+
}
|
|
117
|
+
catch (e) {
|
|
118
|
+
(0, logger_1.log)("smartapp", "** http error ** " + (e ? e.message : "unknown") + " **");
|
|
119
|
+
reject(e);
|
|
120
|
+
}
|
|
121
|
+
});
|
|
122
|
+
});
|
|
123
|
+
}
|
|
124
|
+
exports.httpRequest = httpRequest;
|
|
125
|
+
//# sourceMappingURL=HA-API.js.map
|
package/server/HA-API.ts
ADDED
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
import { debug, err, log } from "../duotecno/logger";
|
|
2
|
+
import * as http from "http";
|
|
3
|
+
|
|
4
|
+
//////////////////////////////////
|
|
5
|
+
// Home Assistant API //
|
|
6
|
+
// and other http based APIs //
|
|
7
|
+
//////////////////////////////////
|
|
8
|
+
export enum ContentType {form, plain, none, json};
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
export async function httpRequest(url: string, method = "GET", formdata = "",
|
|
12
|
+
contentType = ContentType.form, header: string | object = ""): Promise<Record<string, any>> {
|
|
13
|
+
if (url.indexOf("://") === -1) url = "http://" + url;
|
|
14
|
+
|
|
15
|
+
return new Promise((resolve, reject) => {
|
|
16
|
+
try {
|
|
17
|
+
// const data = querystring.stringify(formdata);
|
|
18
|
+
const options: {method: string, [key: string]: object | string} = { method };
|
|
19
|
+
|
|
20
|
+
if (formdata) {
|
|
21
|
+
if (contentType === ContentType.form) {
|
|
22
|
+
options.headers = {
|
|
23
|
+
'Content-Type': 'application/x-www-form-urlencoded',
|
|
24
|
+
'Content-Length': Buffer.byteLength(formdata)
|
|
25
|
+
}
|
|
26
|
+
} else if (contentType === ContentType.plain) {
|
|
27
|
+
options.headers = {
|
|
28
|
+
'Content-Type': 'text/plain',
|
|
29
|
+
'Accept': 'application/json'
|
|
30
|
+
};
|
|
31
|
+
} else if (contentType === ContentType.json) {
|
|
32
|
+
options.headers = {
|
|
33
|
+
'Content-Type': 'application/json',
|
|
34
|
+
'Accept': '*/*'
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
// header provide as string or object
|
|
40
|
+
if (header) {
|
|
41
|
+
if (!options.headers) options.headers = {};
|
|
42
|
+
if (typeof header === "string") {
|
|
43
|
+
if (header.substring(0,1) === "{") {
|
|
44
|
+
try {
|
|
45
|
+
options.headers = { ...<object>options.headers, ...JSON.parse(header)};
|
|
46
|
+
} catch(e) {
|
|
47
|
+
err("smartapp", "error parsing :" + header + " -> " + JSON.stringify(e));
|
|
48
|
+
}
|
|
49
|
+
} else {
|
|
50
|
+
const s = header.split(":");
|
|
51
|
+
options.headers[s[0]] = s[1];
|
|
52
|
+
}
|
|
53
|
+
} else {
|
|
54
|
+
// header is an object
|
|
55
|
+
options.headers = { ...<object>options.headers, ...header };
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
debug("smartapp", "Sending to " + url + " with options: " + JSON.stringify(options));
|
|
60
|
+
const req = http.request(url, options, res => {
|
|
61
|
+
let resp = "";
|
|
62
|
+
// res.setEncoding('utf8');
|
|
63
|
+
res.on('error', error => {
|
|
64
|
+
log("smartapp", "The request to " + url + ", error: " + (error ? error.message : "unknown"));
|
|
65
|
+
reject(error);
|
|
66
|
+
});
|
|
67
|
+
res.on('data', chunk => {
|
|
68
|
+
resp += chunk;
|
|
69
|
+
});
|
|
70
|
+
res.on('end', () => {
|
|
71
|
+
// try to make something out of it...
|
|
72
|
+
try {
|
|
73
|
+
const x = JSON.parse(resp);
|
|
74
|
+
if ((x.type === "Buffer") && x.data) x.data = x.data.toString();
|
|
75
|
+
debug("smartapp", "http " + method + " -> " + res.statusCode + ": " + url + " = " + JSON.stringify(x).substring(0, 200) + "...");
|
|
76
|
+
resolve(x)
|
|
77
|
+
} catch(e) {
|
|
78
|
+
err("smartapp", "http " + method + " -> " + res.statusCode + ": " + url + " = " + resp);
|
|
79
|
+
resolve({status: "NOK", result: resp});
|
|
80
|
+
};
|
|
81
|
+
});
|
|
82
|
+
});
|
|
83
|
+
if (formdata) {
|
|
84
|
+
req.write(formdata);
|
|
85
|
+
}
|
|
86
|
+
req.on("error", (e) => {
|
|
87
|
+
log("smartapp", "The request to " + url + ", error: " + (e ? e.message : "unknown"));
|
|
88
|
+
});
|
|
89
|
+
req.on("timeout", (e) => {
|
|
90
|
+
log("smartapp", "The request to " + url + ", timeout: " + (e ? e.message : "unknown"));
|
|
91
|
+
});
|
|
92
|
+
req.end();
|
|
93
|
+
|
|
94
|
+
} catch(e) {
|
|
95
|
+
log("smartapp", "** http error ** " + (e ? e.message : "unknown") + " **");
|
|
96
|
+
reject(e);
|
|
97
|
+
}
|
|
98
|
+
});
|
|
99
|
+
}
|