node-red-contrib-homekit-bridged 1.7.3 → 2.0.0-dev.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/build/lib/HAPHostNode.js +9 -37
- package/build/lib/HAPServiceNode.js +1 -1
- package/build/lib/HAPServiceNode2.js +1 -1
- package/build/lib/Storage.d.ts +1 -1
- package/build/lib/api.js +4 -1
- package/build/lib/hap/HAPCharacteristic.d.ts +1 -1
- package/build/lib/hap/HAPCharacteristic.js +1 -1
- package/build/lib/hap/HAPService.d.ts +1 -1
- package/build/lib/hap/HAPService.js +1 -1
- package/build/lib/types/CustomCharacteristicType.d.ts +1 -1
- package/build/lib/types/HAPHostConfigType.d.ts +1 -9
- package/build/lib/types/HAPHostNodeType.d.ts +1 -3
- package/build/lib/types/HAPServiceConfigType.d.ts +1 -1
- package/build/lib/types/HAPServiceNodeType.d.ts +5 -4
- package/build/lib/types/storage/SerializedHostType.d.ts +1 -1
- package/build/lib/utils/AccessoryUtils.js +1 -1
- package/build/lib/utils/CharacteristicUtils.js +1 -1
- package/build/lib/utils/CharacteristicUtils2.js +1 -1
- package/build/lib/utils/ServiceUtils.js +4 -6
- package/build/lib/utils/ServiceUtils2.js +4 -6
- package/build/lib/utils/index.js +0 -2
- package/build/nodes/nrchkb.js +1 -1
- package/build/nodes/status.js +1 -1
- package/package.json +15 -15
- package/build/lib/cameraSource/index.d.ts +0 -1
- package/build/lib/cameraSource/index.js +0 -477
- package/build/lib/types/hap-nodejs/BonjourMulticastOptions.d.ts +0 -10
- package/build/lib/types/hap-nodejs/BonjourMulticastOptions.js +0 -2
- package/build/lib/utils/MdnsUtils.d.ts +0 -1
- package/build/lib/utils/MdnsUtils.js +0 -93
package/build/lib/HAPHostNode.js
CHANGED
|
@@ -12,17 +12,16 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
12
12
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
13
13
|
};
|
|
14
14
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
|
+
const hap_nodejs_1 = require("@homebridge/hap-nodejs");
|
|
15
16
|
const logger_1 = require("@nrchkb/logger");
|
|
16
|
-
const hap_nodejs_1 = require("hap-nodejs");
|
|
17
17
|
const semver_1 = require("semver");
|
|
18
18
|
const preload_1 = __importDefault(require("semver/preload"));
|
|
19
19
|
const NRCHKBError_1 = __importDefault(require("./NRCHKBError"));
|
|
20
20
|
const HapCategories_1 = __importDefault(require("./types/hap-nodejs/HapCategories"));
|
|
21
21
|
const HostType_1 = __importDefault(require("./types/HostType"));
|
|
22
22
|
module.exports = (RED, hostType) => {
|
|
23
|
-
const MdnsUtils = require('./utils/MdnsUtils')();
|
|
24
23
|
const init = function (config) {
|
|
25
|
-
var _a, _b, _c
|
|
24
|
+
var _a, _b, _c;
|
|
26
25
|
const self = this;
|
|
27
26
|
const log = (0, logger_1.logger)('NRCHKB', 'HAPHostNode', config.bridgeName, self);
|
|
28
27
|
self.hostType = hostType;
|
|
@@ -36,31 +35,6 @@ module.exports = (RED, hostType) => {
|
|
|
36
35
|
if (preload_1.default.parse(config.firmwareRev) == null) {
|
|
37
36
|
config.firmwareRev = new semver_1.SemVer('0.0.0');
|
|
38
37
|
}
|
|
39
|
-
if (!((_a = config.bind) === null || _a === void 0 ? void 0 : _a.length) && config.customMdnsConfig) {
|
|
40
|
-
log.error('Custom mdns config is deprecated, use bind instead!');
|
|
41
|
-
self.mdnsConfig = {};
|
|
42
|
-
if (MdnsUtils.checkMulticast(config.mdnsMulticast)) {
|
|
43
|
-
self.mdnsConfig.multicast = config.mdnsMulticast;
|
|
44
|
-
}
|
|
45
|
-
if (MdnsUtils.checkInterface(config.mdnsInterface)) {
|
|
46
|
-
self.mdnsConfig.interface = config.mdnsInterface;
|
|
47
|
-
}
|
|
48
|
-
if (MdnsUtils.checkPort(config.mdnsPort)) {
|
|
49
|
-
self.mdnsConfig.port = parseInt((_b = config.mdnsPort) === null || _b === void 0 ? void 0 : _b.toString());
|
|
50
|
-
}
|
|
51
|
-
if (MdnsUtils.checkIp(config.mdnsIp)) {
|
|
52
|
-
self.mdnsConfig.ip = config.mdnsIp;
|
|
53
|
-
}
|
|
54
|
-
if (MdnsUtils.checkTtl(config.mdnsTtl)) {
|
|
55
|
-
self.mdnsConfig.ttl = parseInt((_c = config.mdnsTtl) === null || _c === void 0 ? void 0 : _c.toString());
|
|
56
|
-
}
|
|
57
|
-
if (MdnsUtils.checkLoopback(config.mdnsLoopback)) {
|
|
58
|
-
self.mdnsConfig.loopback = config.mdnsLoopback;
|
|
59
|
-
}
|
|
60
|
-
if (MdnsUtils.checkReuseAddr(config.mdnsReuseAddr)) {
|
|
61
|
-
self.mdnsConfig.reuseAddr = config.mdnsReuseAddr;
|
|
62
|
-
}
|
|
63
|
-
}
|
|
64
38
|
self.accessoryCategory = (self.hostType == HostType_1.default.BRIDGE
|
|
65
39
|
? HapCategories_1.default.BRIDGE
|
|
66
40
|
: self.config.accessoryCategory);
|
|
@@ -82,15 +56,14 @@ module.exports = (RED, hostType) => {
|
|
|
82
56
|
self.host = new hap_nodejs_1.Accessory(self.name, hostUUID);
|
|
83
57
|
}
|
|
84
58
|
self.publish = function () {
|
|
85
|
-
var _a, _b
|
|
59
|
+
var _a, _b;
|
|
86
60
|
if (self.hostType == HostType_1.default.BRIDGE) {
|
|
87
61
|
log.debug(`Publishing ${hostTypeName} with pin code ${self.config.pinCode} and ${self.host.bridgedAccessories.length} accessories`);
|
|
88
62
|
}
|
|
89
63
|
else {
|
|
90
64
|
log.debug(`Publishing ${hostTypeName} with pin code ${self.config.pinCode}`);
|
|
91
65
|
}
|
|
92
|
-
if (
|
|
93
|
-
(((_a = self.mdnsConfig) === null || _a === void 0 ? void 0 : _a.port) && ((_b = self.mdnsConfig) === null || _b === void 0 ? void 0 : _b.port) == 1880)) {
|
|
66
|
+
if (self.config.port && self.config.port == 1880) {
|
|
94
67
|
log.error(`Cannot publish on ${hostTypeName} port 1880 as it is reserved for node-red`);
|
|
95
68
|
self.published = false;
|
|
96
69
|
return false;
|
|
@@ -101,7 +74,7 @@ module.exports = (RED, hostType) => {
|
|
|
101
74
|
oldPinCode = `${oldPinCode.slice(0, 3)}-${oldPinCode.slice(3, 5)}-${oldPinCode.slice(5, 8)}`;
|
|
102
75
|
}
|
|
103
76
|
let bind;
|
|
104
|
-
if (((
|
|
77
|
+
if (((_a = self.config.bind) === null || _a === void 0 ? void 0 : _a.length) && self.config.bindType) {
|
|
105
78
|
if (self.config.bindType == 'str') {
|
|
106
79
|
bind = self.config.bind;
|
|
107
80
|
}
|
|
@@ -116,9 +89,8 @@ module.exports = (RED, hostType) => {
|
|
|
116
89
|
: 0,
|
|
117
90
|
pincode: oldPinCode,
|
|
118
91
|
category: self.accessoryCategory,
|
|
119
|
-
mdns: self.mdnsConfig,
|
|
120
92
|
bind: bind,
|
|
121
|
-
advertiser: (
|
|
93
|
+
advertiser: (_b = self.config.advertiser) !== null && _b !== void 0 ? _b : "bonjour-hap",
|
|
122
94
|
}, self.config.allowInsecureRequest);
|
|
123
95
|
self.published = true;
|
|
124
96
|
return true;
|
|
@@ -152,9 +124,9 @@ module.exports = (RED, hostType) => {
|
|
|
152
124
|
.setCharacteristic(hap_nodejs_1.Characteristic.Manufacturer, self.config.manufacturer)
|
|
153
125
|
.setCharacteristic(hap_nodejs_1.Characteristic.SerialNumber, self.config.serialNo)
|
|
154
126
|
.setCharacteristic(hap_nodejs_1.Characteristic.Model, self.config.model)
|
|
155
|
-
.setCharacteristic(hap_nodejs_1.Characteristic.FirmwareRevision, (
|
|
156
|
-
.setCharacteristic(hap_nodejs_1.Characteristic.HardwareRevision, (
|
|
157
|
-
.setCharacteristic(hap_nodejs_1.Characteristic.SoftwareRevision, (
|
|
127
|
+
.setCharacteristic(hap_nodejs_1.Characteristic.FirmwareRevision, (_a = self.config.firmwareRev) === null || _a === void 0 ? void 0 : _a.toString())
|
|
128
|
+
.setCharacteristic(hap_nodejs_1.Characteristic.HardwareRevision, (_b = self.config.hardwareRev) === null || _b === void 0 ? void 0 : _b.toString())
|
|
129
|
+
.setCharacteristic(hap_nodejs_1.Characteristic.SoftwareRevision, (_c = self.config.softwareRev) === null || _c === void 0 ? void 0 : _c.toString());
|
|
158
130
|
};
|
|
159
131
|
const macify = (nodeId) => {
|
|
160
132
|
if (nodeId) {
|
|
@@ -3,8 +3,8 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
3
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
const hap_nodejs_1 = require("@homebridge/hap-nodejs");
|
|
6
7
|
const logger_1 = require("@nrchkb/logger");
|
|
7
|
-
const hap_nodejs_1 = require("hap-nodejs");
|
|
8
8
|
const NRCHKBError_1 = __importDefault(require("./NRCHKBError"));
|
|
9
9
|
const HostType_1 = __importDefault(require("./types/HostType"));
|
|
10
10
|
const NodeStatusUtils_1 = require("./utils/NodeStatusUtils");
|
|
@@ -3,8 +3,8 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
3
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
const hap_nodejs_1 = require("@homebridge/hap-nodejs");
|
|
6
7
|
const logger_1 = require("@nrchkb/logger");
|
|
7
|
-
const hap_nodejs_1 = require("hap-nodejs");
|
|
8
8
|
const NRCHKBError_1 = __importDefault(require("./NRCHKBError"));
|
|
9
9
|
const HostType_1 = __importDefault(require("./types/HostType"));
|
|
10
10
|
const NodeStatusUtils_1 = require("./utils/NodeStatusUtils");
|
package/build/lib/Storage.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { CharacteristicEventTypes, SerializedAccessory, SerializedService } from 'hap-nodejs';
|
|
1
|
+
import { CharacteristicEventTypes, SerializedAccessory, SerializedService } from '@homebridge/hap-nodejs';
|
|
2
2
|
import storage, { InitOptions } from 'node-persist';
|
|
3
3
|
import { SerializedHostType } from './types/storage/SerializedHostType';
|
|
4
4
|
import { StorageType } from './types/storage/StorageType';
|
package/build/lib/api.js
CHANGED
|
@@ -23,8 +23,8 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
23
23
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
24
24
|
};
|
|
25
25
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
26
|
+
const hap_nodejs_1 = require("@homebridge/hap-nodejs");
|
|
26
27
|
const logger_1 = require("@nrchkb/logger");
|
|
27
|
-
const hap_nodejs_1 = require("hap-nodejs");
|
|
28
28
|
const EveCharacteristics_1 = __importDefault(require("./hap/eve-app/EveCharacteristics"));
|
|
29
29
|
const Storage_1 = require("./Storage");
|
|
30
30
|
const HapCategories_1 = __importDefault(require("./types/hap-nodejs/HapCategories"));
|
|
@@ -43,6 +43,9 @@ module.exports = function (RED) {
|
|
|
43
43
|
BridgingState: {
|
|
44
44
|
nrchkbDisabledText: 'BridgingState (deprecated, unused)',
|
|
45
45
|
},
|
|
46
|
+
CameraControl: {
|
|
47
|
+
nrchkbDisabledText: 'CameraControl (deprecated, replaced by)',
|
|
48
|
+
},
|
|
46
49
|
CameraEventRecordingManagement: {
|
|
47
50
|
nrchkbDisabledText: 'CameraEventRecordingManagement (deprecated, replaced by CameraRecordingManagement)',
|
|
48
51
|
},
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Characteristic } from 'hap-nodejs';
|
|
1
|
+
import { Characteristic } from '@homebridge/hap-nodejs';
|
|
2
2
|
import { EveS2R1, EveS2R2, EveS2W1, EveS2W2 } from './eve-app/EveCharacteristics';
|
|
3
3
|
declare class HAPCharacteristic extends Characteristic {
|
|
4
4
|
static EveS2R1: typeof EveS2R1;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
const hap_nodejs_1 = require("hap-nodejs");
|
|
3
|
+
const hap_nodejs_1 = require("@homebridge/hap-nodejs");
|
|
4
4
|
class HAPCharacteristic extends hap_nodejs_1.Characteristic {
|
|
5
5
|
}
|
|
6
6
|
exports.default = HAPCharacteristic;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
const hap_nodejs_1 = require("hap-nodejs");
|
|
3
|
+
const hap_nodejs_1 = require("@homebridge/hap-nodejs");
|
|
4
4
|
class HAPService extends hap_nodejs_1.Service {
|
|
5
5
|
}
|
|
6
6
|
exports.default = HAPService;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { MDNSAdvertiser } from 'hap-nodejs';
|
|
1
|
+
import { MDNSAdvertiser } from '@homebridge/hap-nodejs';
|
|
2
2
|
import { NodeDef } from 'node-red';
|
|
3
3
|
import { SemVer } from 'semver';
|
|
4
4
|
import HapCategories from './hap-nodejs/HapCategories';
|
|
@@ -15,14 +15,6 @@ type HAPHostConfigType = NodeDef & {
|
|
|
15
15
|
softwareRev: SemVer;
|
|
16
16
|
bind?: string;
|
|
17
17
|
bindType?: 'json' | 'str';
|
|
18
|
-
customMdnsConfig: boolean;
|
|
19
|
-
mdnsMulticast: boolean;
|
|
20
|
-
mdnsInterface: string;
|
|
21
|
-
mdnsPort: number;
|
|
22
|
-
mdnsIp: string;
|
|
23
|
-
mdnsTtl: number;
|
|
24
|
-
mdnsLoopback: boolean;
|
|
25
|
-
mdnsReuseAddr: boolean;
|
|
26
18
|
allowMessagePassthrough: boolean;
|
|
27
19
|
accessoryCategory: HapCategories;
|
|
28
20
|
advertiser: MDNSAdvertiser;
|
|
@@ -1,11 +1,9 @@
|
|
|
1
|
-
import { Accessory, Categories } from 'hap-nodejs';
|
|
2
|
-
import BonjourMulticastOptions from './hap-nodejs/BonjourMulticastOptions';
|
|
1
|
+
import { Accessory, Categories } from '@homebridge/hap-nodejs';
|
|
3
2
|
import HAPHostConfigType from './HAPHostConfigType';
|
|
4
3
|
import HostType from './HostType';
|
|
5
4
|
import NodeType from './NodeType';
|
|
6
5
|
type HAPHostNodeType = NodeType & {
|
|
7
6
|
config: HAPHostConfigType;
|
|
8
|
-
mdnsConfig: BonjourMulticastOptions;
|
|
9
7
|
accessoryCategory: Categories;
|
|
10
8
|
published: boolean;
|
|
11
9
|
bridgeUsername: string;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { AdaptiveLightingControllerMode } from 'hap-nodejs/dist/lib/controller/AdaptiveLightingController';
|
|
1
|
+
import { AdaptiveLightingControllerMode } from '@homebridge/hap-nodejs/dist/lib/controller/AdaptiveLightingController';
|
|
2
2
|
import { NodeDef } from 'node-red';
|
|
3
3
|
import CameraConfigType from './CameraConfigType';
|
|
4
4
|
type HAPServiceConfigType = NodeDef & {
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import { Accessory, AdaptiveLightingController, Characteristic, CharacteristicChange, CharacteristicGetCallback, CharacteristicProps, CharacteristicSetCallback, CharacteristicValue, Service } from 'hap-nodejs';
|
|
2
|
-
import {
|
|
1
|
+
import { Accessory, AdaptiveLightingController, Characteristic, CharacteristicChange, CharacteristicGetCallback, CharacteristicProps, CharacteristicSetCallback, CharacteristicValue, Service } from '@homebridge/hap-nodejs';
|
|
2
|
+
import { CharacteristicContext } from '@homebridge/hap-nodejs/dist/lib/Characteristic';
|
|
3
|
+
import { HAPConnection } from '@homebridge/hap-nodejs/dist/lib/util/eventedhttp';
|
|
3
4
|
import { NodeAPI } from 'node-red';
|
|
4
5
|
import { NodeStatusUtils } from '../utils/NodeStatusUtils';
|
|
5
6
|
import HAPHostNodeType from './HAPHostNodeType';
|
|
@@ -26,8 +27,8 @@ type HAPServiceNodeType = NodeType & {
|
|
|
26
27
|
supported: string[];
|
|
27
28
|
publishTimers: PublishTimersType;
|
|
28
29
|
topic_in: string;
|
|
29
|
-
onCharacteristicGet: (this: Characteristic, callback: CharacteristicGetCallback, context:
|
|
30
|
-
onCharacteristicSet: (this: Characteristic,
|
|
30
|
+
onCharacteristicGet: (this: Characteristic, callback: CharacteristicGetCallback, context: CharacteristicContext, connection?: HAPConnection) => void;
|
|
31
|
+
onCharacteristicSet: (this: Characteristic, value: CharacteristicValue, callback: CharacteristicSetCallback, context: CharacteristicContext, connection?: HAPConnection) => void;
|
|
31
32
|
onCharacteristicChange: (this: Characteristic, change: CharacteristicChange) => void;
|
|
32
33
|
uniqueIdentifier: string;
|
|
33
34
|
reachable?: boolean;
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
const logger_1 = require("@nrchkb/logger");
|
|
4
4
|
module.exports = function (node) {
|
|
5
|
-
const HapNodeJS = require('hap-nodejs');
|
|
5
|
+
const HapNodeJS = require('@homebridge/hap-nodejs');
|
|
6
6
|
const Accessory = HapNodeJS.Accessory;
|
|
7
7
|
const Service = HapNodeJS.Service;
|
|
8
8
|
const Characteristic = HapNodeJS.Characteristic;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const hap_nodejs_1 = require("@homebridge/hap-nodejs");
|
|
3
4
|
const logger_1 = require("@nrchkb/logger");
|
|
4
|
-
const hap_nodejs_1 = require("hap-nodejs");
|
|
5
5
|
module.exports = function (node) {
|
|
6
6
|
const log = (0, logger_1.logger)('NRCHKB', 'CharacteristicUtils', node.config.name, node);
|
|
7
7
|
const ServiceUtils = require('./ServiceUtils')(node);
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const hap_nodejs_1 = require("@homebridge/hap-nodejs");
|
|
3
4
|
const logger_1 = require("@nrchkb/logger");
|
|
4
|
-
const hap_nodejs_1 = require("hap-nodejs");
|
|
5
5
|
module.exports = function (node) {
|
|
6
6
|
const log = (0, logger_1.logger)('NRCHKB', 'CharacteristicUtils', node.config.name, node);
|
|
7
7
|
const ServiceUtils = require('./ServiceUtils2')(node);
|
|
@@ -37,15 +37,14 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
37
37
|
};
|
|
38
38
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
39
|
const util = __importStar(require("node:util"));
|
|
40
|
+
const hap_nodejs_1 = require("@homebridge/hap-nodejs");
|
|
40
41
|
const logger_1 = require("@nrchkb/logger");
|
|
41
|
-
const hap_nodejs_1 = require("hap-nodejs");
|
|
42
42
|
const NRCHKBError_1 = __importDefault(require("../NRCHKBError"));
|
|
43
43
|
module.exports = function (node) {
|
|
44
44
|
const log = (0, logger_1.logger)('NRCHKB', 'ServiceUtils', node.config.name, node);
|
|
45
|
-
const HapNodeJS = require('hap-nodejs');
|
|
45
|
+
const HapNodeJS = require('@homebridge/hap-nodejs');
|
|
46
46
|
const Service = HapNodeJS.Service;
|
|
47
47
|
const Characteristic = HapNodeJS.Characteristic;
|
|
48
|
-
const CameraSource = require('../cameraSource').Camera;
|
|
49
48
|
const NO_RESPONSE_MSG = 'NO_RESPONSE';
|
|
50
49
|
const prepareHapData = (context, connection) => {
|
|
51
50
|
const hap = {};
|
|
@@ -198,7 +197,7 @@ module.exports = function (node) {
|
|
|
198
197
|
parentNode.reachable = value !== NO_RESPONSE_MSG;
|
|
199
198
|
const characteristic = node.service.getCharacteristic(Characteristic[key]);
|
|
200
199
|
if (context !== null) {
|
|
201
|
-
characteristic.setValue(value,
|
|
200
|
+
characteristic.setValue(value, context);
|
|
202
201
|
}
|
|
203
202
|
else {
|
|
204
203
|
characteristic.setValue(value);
|
|
@@ -266,14 +265,13 @@ module.exports = function (node) {
|
|
|
266
265
|
}
|
|
267
266
|
return service;
|
|
268
267
|
};
|
|
269
|
-
const configureCameraSource = function (
|
|
268
|
+
const configureCameraSource = function (_accessory, _service, config) {
|
|
270
269
|
if (config.cameraConfigSource) {
|
|
271
270
|
log.debug('Configuring Camera Source');
|
|
272
271
|
if (!config.cameraConfigVideoProcessor) {
|
|
273
272
|
log.error('Missing configuration for CameraControl: videoProcessor cannot be empty!');
|
|
274
273
|
}
|
|
275
274
|
else {
|
|
276
|
-
accessory.configureCameraSource(new CameraSource(service, config, node));
|
|
277
275
|
}
|
|
278
276
|
}
|
|
279
277
|
else {
|
|
@@ -3,17 +3,16 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
3
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
const hap_nodejs_1 = require("@homebridge/hap-nodejs");
|
|
6
7
|
const logger_1 = require("@nrchkb/logger");
|
|
7
|
-
const hap_nodejs_1 = require("hap-nodejs");
|
|
8
8
|
const NRCHKBError_1 = __importDefault(require("../NRCHKBError"));
|
|
9
9
|
const Storage_1 = require("../Storage");
|
|
10
10
|
module.exports = function (node) {
|
|
11
11
|
const log = (0, logger_1.logger)('NRCHKB', 'ServiceUtils2', node.config.name, node);
|
|
12
12
|
const ServiceUtilsLegacy = require('./ServiceUtils')(node);
|
|
13
|
-
const HapNodeJS = require('hap-nodejs');
|
|
13
|
+
const HapNodeJS = require('@homebridge/hap-nodejs');
|
|
14
14
|
const Service = HapNodeJS.Service;
|
|
15
15
|
const Characteristic = HapNodeJS.Characteristic;
|
|
16
|
-
const CameraSource = require('../cameraSource').Camera;
|
|
17
16
|
const NO_RESPONSE_MSG = 'NO_RESPONSE';
|
|
18
17
|
const output = function (allCharacteristics, event, { oldValue, newValue }, connection) {
|
|
19
18
|
var _a, _b, _c, _d, _e;
|
|
@@ -185,7 +184,7 @@ module.exports = function (node) {
|
|
|
185
184
|
parentNode.reachable = value !== NO_RESPONSE_MSG;
|
|
186
185
|
const characteristic = node.service.getCharacteristic(Characteristic[key]);
|
|
187
186
|
if (context !== null) {
|
|
188
|
-
characteristic.setValue(value,
|
|
187
|
+
characteristic.setValue(value, context);
|
|
189
188
|
}
|
|
190
189
|
else {
|
|
191
190
|
characteristic.setValue(value);
|
|
@@ -253,14 +252,13 @@ module.exports = function (node) {
|
|
|
253
252
|
}
|
|
254
253
|
return service;
|
|
255
254
|
};
|
|
256
|
-
const configureCameraSource = function (
|
|
255
|
+
const configureCameraSource = function (_accessory, _service, config) {
|
|
257
256
|
if (config.cameraConfigSource) {
|
|
258
257
|
log.debug('Configuring Camera Source');
|
|
259
258
|
if (!config.cameraConfigVideoProcessor) {
|
|
260
259
|
log.error('Missing configuration for CameraControl: videoProcessor cannot be empty!');
|
|
261
260
|
}
|
|
262
261
|
else {
|
|
263
|
-
accessory.configureCameraSource(new CameraSource(service, config, node));
|
|
264
262
|
}
|
|
265
263
|
}
|
|
266
264
|
else {
|
package/build/lib/utils/index.js
CHANGED
|
@@ -5,12 +5,10 @@ module.exports = function (node) {
|
|
|
5
5
|
const BridgeUtils = require('./BridgeUtils')();
|
|
6
6
|
const AccessoryUtils = require('./AccessoryUtils')(node);
|
|
7
7
|
const CharacteristicUtils = require('./CharacteristicUtils')(node);
|
|
8
|
-
const MdnsUtils = require('./MdnsUtils')();
|
|
9
8
|
return {
|
|
10
9
|
ServiceUtils,
|
|
11
10
|
BridgeUtils,
|
|
12
11
|
AccessoryUtils,
|
|
13
12
|
CharacteristicUtils,
|
|
14
|
-
MdnsUtils,
|
|
15
13
|
};
|
|
16
14
|
};
|
package/build/nodes/nrchkb.js
CHANGED
|
@@ -36,8 +36,8 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
36
36
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
37
37
|
};
|
|
38
38
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
|
+
const hap_nodejs_1 = require("@homebridge/hap-nodejs");
|
|
39
40
|
const logger_1 = require("@nrchkb/logger");
|
|
40
|
-
const hap_nodejs_1 = require("hap-nodejs");
|
|
41
41
|
const path = __importStar(require("path"));
|
|
42
42
|
const semver_1 = __importDefault(require("semver"));
|
|
43
43
|
const Storage_1 = require("../lib/Storage");
|
package/build/nodes/status.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const hap_nodejs_1 = require("@homebridge/hap-nodejs");
|
|
3
4
|
const logger_1 = require("@nrchkb/logger");
|
|
4
|
-
const hap_nodejs_1 = require("hap-nodejs");
|
|
5
5
|
const NodeStatusUtils_1 = require("../lib/utils/NodeStatusUtils");
|
|
6
6
|
const log = (0, logger_1.logger)('NRCHKB', 'HAPStatusNode');
|
|
7
7
|
module.exports = (RED) => {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "node-red-contrib-homekit-bridged",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "2.0.0-dev.0",
|
|
4
4
|
"description": "Node-RED nodes to simulate Apple HomeKit devices.",
|
|
5
5
|
"main": "build/nodes/nrchkb.js",
|
|
6
6
|
"scripts": {
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
"clean": "del-cli \"build/lib\" \"build/**/*.js\"",
|
|
9
9
|
"test": "mocha -r ts-node/register './src/**/*.test.[tj]s' --exit --timeout 30000",
|
|
10
10
|
"prettier": "prettier --write \"**/*.{js,ts}\"",
|
|
11
|
-
"eslint": "eslint \"src/**/*.ts\"",
|
|
11
|
+
"eslint": "eslint \"src/**/*.ts\" --fix",
|
|
12
12
|
"prepare": "husky install"
|
|
13
13
|
},
|
|
14
14
|
"repository": {
|
|
@@ -43,20 +43,20 @@
|
|
|
43
43
|
"homepage": "https://github.com/NRCHKB/node-red-contrib-homekit-bridged#readme",
|
|
44
44
|
"dependencies": {
|
|
45
45
|
"@nrchkb/logger": "~3.1.1",
|
|
46
|
-
"hap-nodejs": "0.
|
|
46
|
+
"@homebridge/hap-nodejs": "2.0.2",
|
|
47
47
|
"node-persist": "^3.1.3",
|
|
48
|
-
"semver": "~7.
|
|
48
|
+
"semver": "~7.7.3",
|
|
49
49
|
"uuid": "~11.0.5"
|
|
50
50
|
},
|
|
51
51
|
"devDependencies": {
|
|
52
|
-
"@homebridge/ciao": "~1.3.
|
|
53
|
-
"@node-red/registry": "^4.
|
|
52
|
+
"@homebridge/ciao": "~1.3.4",
|
|
53
|
+
"@node-red/registry": "^4.1.1",
|
|
54
54
|
"@types/mocha": "^10.0.10",
|
|
55
|
-
"@types/node": "^
|
|
55
|
+
"@types/node": "^20",
|
|
56
56
|
"@types/node-persist": "^3.1.8",
|
|
57
57
|
"@types/node-red": "^1.3.5",
|
|
58
|
-
"@types/node-red-node-test-helper": "^0.3.
|
|
59
|
-
"@types/semver": "^7.
|
|
58
|
+
"@types/node-red-node-test-helper": "^0.3.5",
|
|
59
|
+
"@types/semver": "^7.7.1",
|
|
60
60
|
"@types/uuid": "^10.0.0",
|
|
61
61
|
"@typescript-eslint/eslint-plugin": "^7.16.0",
|
|
62
62
|
"@typescript-eslint/parser": "^7.16.0",
|
|
@@ -64,18 +64,18 @@
|
|
|
64
64
|
"del-cli": "^5.1.0",
|
|
65
65
|
"eslint": "^8",
|
|
66
66
|
"eslint-config-prettier": "^9.1.0",
|
|
67
|
-
"eslint-plugin-prettier": "^5.
|
|
67
|
+
"eslint-plugin-prettier": "^5.5.4",
|
|
68
68
|
"eslint-plugin-simple-import-sort": "^12.1.1",
|
|
69
|
-
"husky": "^9.
|
|
69
|
+
"husky": "^9.1.7",
|
|
70
70
|
"mocha": "^10.6.0",
|
|
71
|
-
"node-red": "^4.
|
|
72
|
-
"node-red-node-test-helper": "^0.3.
|
|
73
|
-
"prettier": "^3.
|
|
71
|
+
"node-red": "^4.1.1",
|
|
72
|
+
"node-red-node-test-helper": "^0.3.5",
|
|
73
|
+
"prettier": "^3.6.2",
|
|
74
74
|
"ts-node": "^10.9.2",
|
|
75
75
|
"typescript": "^5.7.3"
|
|
76
76
|
},
|
|
77
77
|
"engines": {
|
|
78
|
-
"node": "
|
|
78
|
+
"node": "^20 || ^22 || ^24"
|
|
79
79
|
},
|
|
80
80
|
"files": [
|
|
81
81
|
"/build",
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|
|
@@ -1,477 +0,0 @@
|
|
|
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 () {
|
|
19
|
-
var ownKeys = function(o) {
|
|
20
|
-
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
-
var ar = [];
|
|
22
|
-
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
-
return ar;
|
|
24
|
-
};
|
|
25
|
-
return ownKeys(o);
|
|
26
|
-
};
|
|
27
|
-
return function (mod) {
|
|
28
|
-
if (mod && mod.__esModule) return mod;
|
|
29
|
-
var result = {};
|
|
30
|
-
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
-
__setModuleDefault(result, mod);
|
|
32
|
-
return result;
|
|
33
|
-
};
|
|
34
|
-
})();
|
|
35
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
-
const logger_1 = require("@nrchkb/logger");
|
|
37
|
-
const util = __importStar(require("util"));
|
|
38
|
-
const HapNodeJS = require('hap-nodejs');
|
|
39
|
-
const uuid = HapNodeJS.uuid;
|
|
40
|
-
const StreamController = HapNodeJS.StreamController;
|
|
41
|
-
const crypto = require('crypto');
|
|
42
|
-
const fs = require('fs');
|
|
43
|
-
const os = require('os');
|
|
44
|
-
const spawn = require('child_process').spawn;
|
|
45
|
-
const log = (0, logger_1.logger)('CameraSource');
|
|
46
|
-
module.exports = {
|
|
47
|
-
Camera: Camera,
|
|
48
|
-
};
|
|
49
|
-
function Camera(cameraControlService, config, cameraNode) {
|
|
50
|
-
this.configure(config, cameraControlService);
|
|
51
|
-
this.cameraNode = cameraNode;
|
|
52
|
-
}
|
|
53
|
-
Camera.prototype.configure = function (config, cameraControlService) {
|
|
54
|
-
this.name = config.name;
|
|
55
|
-
this.vcodec = config.cameraConfigVideoCodec;
|
|
56
|
-
this.videoProcessor = config.cameraConfigVideoProcessor;
|
|
57
|
-
this.audio = config.cameraConfigAudio;
|
|
58
|
-
this.acodec = config.cameraConfigAudioCodec;
|
|
59
|
-
this.packetsize = config.cameraConfigPacketSize;
|
|
60
|
-
this.fps = config.cameraConfigMaxFPS;
|
|
61
|
-
this.maxBitrate = config.cameraConfigMaxBitrate;
|
|
62
|
-
this.debug = config.cameraConfigDebug;
|
|
63
|
-
this.additionalCommandline = config.cameraConfigAdditionalCommandLine;
|
|
64
|
-
this.vflip = config.cameraConfigVerticalFlip;
|
|
65
|
-
this.hflip = config.cameraConfigHorizontalFlip;
|
|
66
|
-
this.mapvideo = config.cameraConfigMapVideo;
|
|
67
|
-
this.mapaudio = config.cameraConfigMapAudio;
|
|
68
|
-
this.videoFilter = config.cameraConfigVideoFilter;
|
|
69
|
-
this.uploader = config.cameraConfigSnapshotOutput;
|
|
70
|
-
this.interfaceName = config.cameraConfigInterfaceName;
|
|
71
|
-
if (!config.cameraConfigSource) {
|
|
72
|
-
throw new NRCHKBError('Missing source for camera.');
|
|
73
|
-
}
|
|
74
|
-
if (this.interfaceName !== '') {
|
|
75
|
-
if (!Object.keys(require('os').networkInterfaces()).includes(this.interfaceName)) {
|
|
76
|
-
throw new NRCHKBError('Incorrect interface name for camera.');
|
|
77
|
-
}
|
|
78
|
-
}
|
|
79
|
-
this.ffmpegSource = config.cameraConfigSource;
|
|
80
|
-
this.ffmpegImageSource = config.cameraConfigStillImageSource;
|
|
81
|
-
this.services = [];
|
|
82
|
-
this.streamControllers = [];
|
|
83
|
-
this.pendingSessions = {};
|
|
84
|
-
this.ongoingSessions = {};
|
|
85
|
-
const numberOfStreams = config.cameraConfigMaxStreams;
|
|
86
|
-
const videoResolutions = [];
|
|
87
|
-
this.maxWidth = config.cameraConfigMaxWidth;
|
|
88
|
-
this.maxHeight = config.cameraConfigMaxHeight;
|
|
89
|
-
const maxFPS = this.fps > 30 ? 30 : this.fps;
|
|
90
|
-
if (this.maxWidth >= 320) {
|
|
91
|
-
if (this.maxHeight >= 240) {
|
|
92
|
-
videoResolutions.push([320, 240, maxFPS]);
|
|
93
|
-
if (maxFPS > 15) {
|
|
94
|
-
videoResolutions.push([320, 240, 15]);
|
|
95
|
-
}
|
|
96
|
-
}
|
|
97
|
-
if (this.maxHeight >= 180) {
|
|
98
|
-
videoResolutions.push([320, 180, maxFPS]);
|
|
99
|
-
if (maxFPS > 15) {
|
|
100
|
-
videoResolutions.push([320, 180, 15]);
|
|
101
|
-
}
|
|
102
|
-
}
|
|
103
|
-
}
|
|
104
|
-
if (this.maxWidth >= 480) {
|
|
105
|
-
if (this.maxHeight >= 360) {
|
|
106
|
-
videoResolutions.push([480, 360, maxFPS]);
|
|
107
|
-
}
|
|
108
|
-
if (this.maxHeight >= 270) {
|
|
109
|
-
videoResolutions.push([480, 270, maxFPS]);
|
|
110
|
-
}
|
|
111
|
-
}
|
|
112
|
-
if (this.maxWidth >= 640) {
|
|
113
|
-
if (this.maxHeight >= 480) {
|
|
114
|
-
videoResolutions.push([640, 480, maxFPS]);
|
|
115
|
-
}
|
|
116
|
-
if (this.maxHeight >= 360) {
|
|
117
|
-
videoResolutions.push([640, 360, maxFPS]);
|
|
118
|
-
}
|
|
119
|
-
}
|
|
120
|
-
if (this.maxWidth >= 1280) {
|
|
121
|
-
if (this.maxHeight >= 960) {
|
|
122
|
-
videoResolutions.push([1280, 960, maxFPS]);
|
|
123
|
-
}
|
|
124
|
-
if (this.maxHeight >= 720) {
|
|
125
|
-
videoResolutions.push([1280, 720, maxFPS]);
|
|
126
|
-
}
|
|
127
|
-
}
|
|
128
|
-
if (this.maxWidth >= 1920) {
|
|
129
|
-
if (this.maxHeight >= 1080) {
|
|
130
|
-
videoResolutions.push([1920, 1080, maxFPS]);
|
|
131
|
-
}
|
|
132
|
-
}
|
|
133
|
-
let options = {
|
|
134
|
-
proxy: false,
|
|
135
|
-
srtp: true,
|
|
136
|
-
video: {
|
|
137
|
-
resolutions: videoResolutions,
|
|
138
|
-
codec: {
|
|
139
|
-
profiles: [0, 1, 2],
|
|
140
|
-
levels: [0, 1, 2],
|
|
141
|
-
},
|
|
142
|
-
},
|
|
143
|
-
audio: {
|
|
144
|
-
codecs: [
|
|
145
|
-
{
|
|
146
|
-
type: 'OPUS',
|
|
147
|
-
samplerate: 24,
|
|
148
|
-
},
|
|
149
|
-
{
|
|
150
|
-
type: 'AAC-eld',
|
|
151
|
-
samplerate: 16,
|
|
152
|
-
},
|
|
153
|
-
],
|
|
154
|
-
},
|
|
155
|
-
};
|
|
156
|
-
if (cameraControlService) {
|
|
157
|
-
this._createStreamControllers(cameraControlService, numberOfStreams, options);
|
|
158
|
-
}
|
|
159
|
-
else {
|
|
160
|
-
log.error('Camera reconfigure on the fly is not yet supported. ' +
|
|
161
|
-
'Please restart node-red to apply all changes to the Camera.');
|
|
162
|
-
}
|
|
163
|
-
};
|
|
164
|
-
Camera.prototype.handleCloseConnection = function (connectionID) {
|
|
165
|
-
this.streamControllers.forEach(function (controller) {
|
|
166
|
-
controller.handleCloseConnection(connectionID);
|
|
167
|
-
});
|
|
168
|
-
};
|
|
169
|
-
Camera.prototype.handleSnapshotRequest = function (request, callback) {
|
|
170
|
-
let resolution = request.width + 'x' + request.height;
|
|
171
|
-
let imageSource = this.ffmpegImageSource;
|
|
172
|
-
if (imageSource === undefined || !imageSource.trim()) {
|
|
173
|
-
imageSource = this.ffmpegSource;
|
|
174
|
-
}
|
|
175
|
-
let ffmpeg = spawn(this.videoProcessor, (imageSource + ' -t 1 -s ' + resolution + ' -f image2 -').split(' '), { env: process.env });
|
|
176
|
-
let imageBuffer = Buffer.alloc(0);
|
|
177
|
-
log.debug('Snapshot from ' + this.name + ' at ' + resolution);
|
|
178
|
-
log.debug('ffmpeg ' + imageSource + ' -t 1 -s ' + resolution + ' -f image2 -');
|
|
179
|
-
ffmpeg.stdout.on('data', function (data) {
|
|
180
|
-
imageBuffer = Buffer.concat([imageBuffer, data]);
|
|
181
|
-
});
|
|
182
|
-
ffmpeg.on('error', function (error) {
|
|
183
|
-
log.error('An error occurs while making snapshot request');
|
|
184
|
-
log.error(util.inspect(error));
|
|
185
|
-
});
|
|
186
|
-
ffmpeg.on('close', function (code) {
|
|
187
|
-
let msg;
|
|
188
|
-
if (this.cameraNode) {
|
|
189
|
-
const topic = this.cameraNode.topic
|
|
190
|
-
? this.cameraNode.topic
|
|
191
|
-
: this.cameraNode.topic_in;
|
|
192
|
-
msg = { payload: {}, name: this.cameraNode.name, topic: topic };
|
|
193
|
-
}
|
|
194
|
-
if (this.uploader !== 'disabled' && !this.cameraNode) {
|
|
195
|
-
log.error('Node required for camera to send snapshot!');
|
|
196
|
-
}
|
|
197
|
-
else if (this.uploader === 'path') {
|
|
198
|
-
const filePath = __dirname + '/../../cameraSnapshots/' + new Date().getTime();
|
|
199
|
-
log.debug('Saving camera snapshot to: ' + filePath);
|
|
200
|
-
const self = this;
|
|
201
|
-
fs.writeFile(filePath, imageBuffer, function (err) {
|
|
202
|
-
if (err) {
|
|
203
|
-
log.error('Camera snapshot file failed to save due to: ' + err);
|
|
204
|
-
return;
|
|
205
|
-
}
|
|
206
|
-
msg.payload['cameraSnapshot'] = filePath;
|
|
207
|
-
log.debug('Camera snapshot file has been saved! Sending to output... ' +
|
|
208
|
-
JSON.stringify(msg));
|
|
209
|
-
self.cameraNode.send([null, msg]);
|
|
210
|
-
});
|
|
211
|
-
}
|
|
212
|
-
else if (this.uploader === 'content') {
|
|
213
|
-
msg.payload['cameraSnapshot'] = imageBuffer;
|
|
214
|
-
log.debug('Sending camera snapshot buffer to output...' +
|
|
215
|
-
JSON.stringify(msg));
|
|
216
|
-
this.cameraNode.send([null, null, msg]);
|
|
217
|
-
}
|
|
218
|
-
callback(undefined, imageBuffer);
|
|
219
|
-
}.bind(this));
|
|
220
|
-
};
|
|
221
|
-
Camera.prototype.prepareStream = function (request, callback) {
|
|
222
|
-
const sessionInfo = {};
|
|
223
|
-
let sessionID = request['sessionID'];
|
|
224
|
-
sessionInfo['address'] = request['targetAddress'];
|
|
225
|
-
const response = {};
|
|
226
|
-
let videoInfo = request['video'];
|
|
227
|
-
if (videoInfo) {
|
|
228
|
-
let targetPort = videoInfo['port'];
|
|
229
|
-
let srtp_key = videoInfo['srtp_key'];
|
|
230
|
-
let srtp_salt = videoInfo['srtp_salt'];
|
|
231
|
-
let ssrcSource = crypto.randomBytes(4);
|
|
232
|
-
ssrcSource[0] = 0;
|
|
233
|
-
let ssrc = ssrcSource.readInt32BE(0, true);
|
|
234
|
-
response['video'] = {
|
|
235
|
-
port: targetPort,
|
|
236
|
-
ssrc: ssrc,
|
|
237
|
-
srtp_key: srtp_key,
|
|
238
|
-
srtp_salt: srtp_salt,
|
|
239
|
-
};
|
|
240
|
-
sessionInfo['video_port'] = targetPort;
|
|
241
|
-
sessionInfo['video_srtp'] = Buffer.concat([srtp_key, srtp_salt]);
|
|
242
|
-
sessionInfo['video_ssrc'] = ssrc;
|
|
243
|
-
}
|
|
244
|
-
let audioInfo = request['audio'];
|
|
245
|
-
if (audioInfo) {
|
|
246
|
-
let targetPort = audioInfo['port'];
|
|
247
|
-
let srtp_key = audioInfo['srtp_key'];
|
|
248
|
-
let srtp_salt = audioInfo['srtp_salt'];
|
|
249
|
-
let ssrcSource = crypto.randomBytes(4);
|
|
250
|
-
ssrcSource[0] = 0;
|
|
251
|
-
let ssrc = ssrcSource.readInt32BE(0, true);
|
|
252
|
-
response['audio'] = {
|
|
253
|
-
port: targetPort,
|
|
254
|
-
ssrc: ssrc,
|
|
255
|
-
srtp_key: srtp_key,
|
|
256
|
-
srtp_salt: srtp_salt,
|
|
257
|
-
};
|
|
258
|
-
sessionInfo['audio_port'] = targetPort;
|
|
259
|
-
sessionInfo['audio_srtp'] = Buffer.concat([srtp_key, srtp_salt]);
|
|
260
|
-
sessionInfo['audio_ssrc'] = ssrc;
|
|
261
|
-
}
|
|
262
|
-
const networkInterfaces = os.networkInterfaces();
|
|
263
|
-
if (this.interfaceName && networkInterfaces[this.interfaceName]) {
|
|
264
|
-
const currentAddress = networkInterfaces[this.interfaceName];
|
|
265
|
-
if (currentAddress === null || currentAddress === void 0 ? void 0 : currentAddress[0]) {
|
|
266
|
-
response['address'] = {
|
|
267
|
-
address: currentAddress[0].address,
|
|
268
|
-
type: currentAddress[0].family === 'IPv4' ? 'v4' : 'v6',
|
|
269
|
-
};
|
|
270
|
-
}
|
|
271
|
-
}
|
|
272
|
-
this.pendingSessions[uuid.unparse(sessionID)] = sessionInfo;
|
|
273
|
-
callback(response);
|
|
274
|
-
};
|
|
275
|
-
Camera.prototype.handleStreamRequest = function (request) {
|
|
276
|
-
const sessionID = request['sessionID'];
|
|
277
|
-
const requestType = request['type'];
|
|
278
|
-
if (sessionID) {
|
|
279
|
-
let sessionIdentifier = uuid.unparse(sessionID);
|
|
280
|
-
log.debug('Request type: ' + requestType);
|
|
281
|
-
if (requestType === 'start') {
|
|
282
|
-
const sessionInfo = this.pendingSessions[sessionIdentifier];
|
|
283
|
-
if (sessionInfo) {
|
|
284
|
-
let width = 1280;
|
|
285
|
-
let height = 720;
|
|
286
|
-
let fps = this.fps || 30;
|
|
287
|
-
let vbitrate = this.maxBitrate;
|
|
288
|
-
let abitrate = 32;
|
|
289
|
-
let asamplerate = 16;
|
|
290
|
-
const vcodec = this.vcodec;
|
|
291
|
-
const acodec = this.acodec;
|
|
292
|
-
const packetsize = this.packetsize || 1316;
|
|
293
|
-
const additionalCommandline = this.additionalCommandline;
|
|
294
|
-
const mapvideo = this.mapvideo;
|
|
295
|
-
const mapaudio = this.mapaudio;
|
|
296
|
-
let videoInfo = request['video'];
|
|
297
|
-
if (videoInfo) {
|
|
298
|
-
width = videoInfo['width'];
|
|
299
|
-
height = videoInfo['height'];
|
|
300
|
-
let expectedFPS = videoInfo['fps'];
|
|
301
|
-
if (expectedFPS < fps) {
|
|
302
|
-
fps = expectedFPS;
|
|
303
|
-
}
|
|
304
|
-
if (videoInfo['max_bit_rate'] < vbitrate) {
|
|
305
|
-
vbitrate = videoInfo['max_bit_rate'];
|
|
306
|
-
}
|
|
307
|
-
}
|
|
308
|
-
let audioInfo = request['audio'];
|
|
309
|
-
if (audioInfo) {
|
|
310
|
-
abitrate = audioInfo['max_bit_rate'];
|
|
311
|
-
asamplerate = audioInfo['sample_rate'];
|
|
312
|
-
}
|
|
313
|
-
let targetAddress = sessionInfo['address'];
|
|
314
|
-
let targetVideoPort = sessionInfo['video_port'];
|
|
315
|
-
let videoKey = sessionInfo['video_srtp'];
|
|
316
|
-
let videoSsrc = sessionInfo['video_ssrc'];
|
|
317
|
-
let targetAudioPort = sessionInfo['audio_port'];
|
|
318
|
-
let audioKey = sessionInfo['audio_srtp'];
|
|
319
|
-
let audioSsrc = sessionInfo['audio_ssrc'];
|
|
320
|
-
let vf = [];
|
|
321
|
-
if (this.videoFilter !== null && this.videoFilter !== '') {
|
|
322
|
-
vf.push(this.videoFilter);
|
|
323
|
-
if (this.hflip)
|
|
324
|
-
vf.push('hflip');
|
|
325
|
-
if (this.vflip)
|
|
326
|
-
vf.push('vflip');
|
|
327
|
-
}
|
|
328
|
-
let fcmd = this.ffmpegSource;
|
|
329
|
-
let ffmpegVideoArgs = ' -map ' +
|
|
330
|
-
mapvideo +
|
|
331
|
-
' -vcodec ' +
|
|
332
|
-
vcodec +
|
|
333
|
-
' -pix_fmt yuv420p' +
|
|
334
|
-
' -r ' +
|
|
335
|
-
fps +
|
|
336
|
-
' -f rawvideo' +
|
|
337
|
-
(additionalCommandline ? ' ' + additionalCommandline : '') +
|
|
338
|
-
(vf.length > 0 ? ' -vf ' + vf.join(',') : '') +
|
|
339
|
-
' -b:v ' +
|
|
340
|
-
vbitrate +
|
|
341
|
-
'k' +
|
|
342
|
-
' -bufsize ' +
|
|
343
|
-
vbitrate +
|
|
344
|
-
'k' +
|
|
345
|
-
' -maxrate ' +
|
|
346
|
-
vbitrate +
|
|
347
|
-
'k' +
|
|
348
|
-
' -payload_type 99';
|
|
349
|
-
let ffmpegVideoStream = ' -ssrc ' +
|
|
350
|
-
videoSsrc +
|
|
351
|
-
' -f rtp' +
|
|
352
|
-
' -srtp_out_suite AES_CM_128_HMAC_SHA1_80' +
|
|
353
|
-
' -srtp_out_params ' +
|
|
354
|
-
videoKey.toString('base64') +
|
|
355
|
-
' srtp://' +
|
|
356
|
-
targetAddress +
|
|
357
|
-
':' +
|
|
358
|
-
targetVideoPort +
|
|
359
|
-
'?rtcpport=' +
|
|
360
|
-
targetVideoPort +
|
|
361
|
-
'&localrtcpport=' +
|
|
362
|
-
targetVideoPort +
|
|
363
|
-
'&pkt_size=' +
|
|
364
|
-
packetsize;
|
|
365
|
-
fcmd += ffmpegVideoArgs;
|
|
366
|
-
fcmd += ffmpegVideoStream;
|
|
367
|
-
if (this.audio) {
|
|
368
|
-
let ffmpegAudioArgs = ' -map ' +
|
|
369
|
-
mapaudio +
|
|
370
|
-
' -acodec ' +
|
|
371
|
-
acodec +
|
|
372
|
-
' -profile:a aac_eld' +
|
|
373
|
-
' -flags +global_header' +
|
|
374
|
-
' -f null' +
|
|
375
|
-
' -ar ' +
|
|
376
|
-
asamplerate +
|
|
377
|
-
'k' +
|
|
378
|
-
' -b:a ' +
|
|
379
|
-
abitrate +
|
|
380
|
-
'k' +
|
|
381
|
-
' -bufsize ' +
|
|
382
|
-
abitrate +
|
|
383
|
-
'k' +
|
|
384
|
-
' -ac 1' +
|
|
385
|
-
' -payload_type 110';
|
|
386
|
-
let ffmpegAudioStream = ' -ssrc ' +
|
|
387
|
-
audioSsrc +
|
|
388
|
-
' -f rtp' +
|
|
389
|
-
' -srtp_out_suite AES_CM_128_HMAC_SHA1_80' +
|
|
390
|
-
' -srtp_out_params ' +
|
|
391
|
-
audioKey.toString('base64') +
|
|
392
|
-
' srtp://' +
|
|
393
|
-
targetAddress +
|
|
394
|
-
':' +
|
|
395
|
-
targetAudioPort +
|
|
396
|
-
'?rtcpport=' +
|
|
397
|
-
targetAudioPort +
|
|
398
|
-
'&localrtcpport=' +
|
|
399
|
-
targetAudioPort +
|
|
400
|
-
'&pkt_size=' +
|
|
401
|
-
packetsize;
|
|
402
|
-
fcmd += ffmpegAudioArgs;
|
|
403
|
-
fcmd += ffmpegAudioStream;
|
|
404
|
-
}
|
|
405
|
-
if (this.debug) {
|
|
406
|
-
fcmd += ' -loglevel debug';
|
|
407
|
-
}
|
|
408
|
-
let ffmpeg = spawn(this.videoProcessor, fcmd.split(' '), {
|
|
409
|
-
env: process.env,
|
|
410
|
-
});
|
|
411
|
-
log.debug('Start streaming video from ' +
|
|
412
|
-
this.name +
|
|
413
|
-
' with ' +
|
|
414
|
-
width +
|
|
415
|
-
'x' +
|
|
416
|
-
height +
|
|
417
|
-
'@' +
|
|
418
|
-
vbitrate +
|
|
419
|
-
'kBit');
|
|
420
|
-
log.debug('ffmpeg ' + fcmd);
|
|
421
|
-
ffmpeg.stderr.on('data', function (data) {
|
|
422
|
-
log.debug('ffmpeg data: ' + data.toString());
|
|
423
|
-
}.bind(this));
|
|
424
|
-
let self = this;
|
|
425
|
-
ffmpeg.on('error', function (error) {
|
|
426
|
-
log.error('An error occurred while making stream request');
|
|
427
|
-
log.error(util.inspect(error));
|
|
428
|
-
});
|
|
429
|
-
ffmpeg.on('close', (code) => {
|
|
430
|
-
if (code == null || code === 0 || code === 255) {
|
|
431
|
-
log.debug('Stopped streaming');
|
|
432
|
-
}
|
|
433
|
-
else {
|
|
434
|
-
log.error('ERROR: FFmpeg exited with code ' + code);
|
|
435
|
-
for (let i = 0; i < self.streamControllers.length; i++) {
|
|
436
|
-
const controller = self.streamControllers[i];
|
|
437
|
-
if (controller.sessionIdentifier === sessionID) {
|
|
438
|
-
controller.forceStop();
|
|
439
|
-
}
|
|
440
|
-
}
|
|
441
|
-
}
|
|
442
|
-
});
|
|
443
|
-
this.ongoingSessions[sessionIdentifier] = ffmpeg;
|
|
444
|
-
}
|
|
445
|
-
delete this.pendingSessions[sessionIdentifier];
|
|
446
|
-
}
|
|
447
|
-
else if (requestType === 'stop') {
|
|
448
|
-
const ffmpegProcess = this.ongoingSessions[sessionIdentifier];
|
|
449
|
-
if (ffmpegProcess) {
|
|
450
|
-
ffmpegProcess.kill('SIGTERM');
|
|
451
|
-
}
|
|
452
|
-
delete this.ongoingSessions[sessionIdentifier];
|
|
453
|
-
}
|
|
454
|
-
else if (requestType === 'reconfigure') {
|
|
455
|
-
}
|
|
456
|
-
}
|
|
457
|
-
};
|
|
458
|
-
Camera.prototype._createStreamControllers = function (cameraControlService, maxStreams, options) {
|
|
459
|
-
let self = this;
|
|
460
|
-
log.debug('Configuring services for Camera...');
|
|
461
|
-
self.services.push(cameraControlService);
|
|
462
|
-
log.debug('...added CameraControl Service');
|
|
463
|
-
if (self.audio) {
|
|
464
|
-
log.debug('...audio available');
|
|
465
|
-
}
|
|
466
|
-
else {
|
|
467
|
-
log.debug('...audio not available');
|
|
468
|
-
}
|
|
469
|
-
log.debug('Creating Camera Stream Controllers: ' + maxStreams + ' - Started');
|
|
470
|
-
log.debug('Camera options: ' + JSON.stringify(options));
|
|
471
|
-
for (let i = 0; i < maxStreams; i++) {
|
|
472
|
-
const streamController = new StreamController(i, options, self);
|
|
473
|
-
self.services.push(streamController.service);
|
|
474
|
-
self.streamControllers.push(streamController);
|
|
475
|
-
}
|
|
476
|
-
log.debug('Creating Camera Stream Controllers - Finished');
|
|
477
|
-
};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|
|
@@ -1,93 +0,0 @@
|
|
|
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 () {
|
|
19
|
-
var ownKeys = function(o) {
|
|
20
|
-
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
-
var ar = [];
|
|
22
|
-
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
-
return ar;
|
|
24
|
-
};
|
|
25
|
-
return ownKeys(o);
|
|
26
|
-
};
|
|
27
|
-
return function (mod) {
|
|
28
|
-
if (mod && mod.__esModule) return mod;
|
|
29
|
-
var result = {};
|
|
30
|
-
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
-
__setModuleDefault(result, mod);
|
|
32
|
-
return result;
|
|
33
|
-
};
|
|
34
|
-
})();
|
|
35
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
-
const net = __importStar(require("net"));
|
|
37
|
-
const os = __importStar(require("os"));
|
|
38
|
-
const MdnsUtils = () => {
|
|
39
|
-
let availableInterfaces;
|
|
40
|
-
const checkIp = function (value) {
|
|
41
|
-
return value.length > 0 && net.isIP(value);
|
|
42
|
-
};
|
|
43
|
-
const checkInterface = function (value) {
|
|
44
|
-
if (value.length < 1) {
|
|
45
|
-
return false;
|
|
46
|
-
}
|
|
47
|
-
if (!availableInterfaces) {
|
|
48
|
-
availableInterfaces = [];
|
|
49
|
-
const networkInterfaces = os.networkInterfaces();
|
|
50
|
-
Object.keys(networkInterfaces).forEach((key) => {
|
|
51
|
-
var _a;
|
|
52
|
-
return (_a = networkInterfaces[key]) === null || _a === void 0 ? void 0 : _a.forEach((networkInterface) => availableInterfaces.push(networkInterface.address));
|
|
53
|
-
});
|
|
54
|
-
}
|
|
55
|
-
return availableInterfaces.indexOf(value) > -1;
|
|
56
|
-
};
|
|
57
|
-
const checkMulticast = function (value) {
|
|
58
|
-
return checkBoolean(value);
|
|
59
|
-
};
|
|
60
|
-
const checkPort = function (value) {
|
|
61
|
-
return value.length > 0 && checkNumber(value);
|
|
62
|
-
};
|
|
63
|
-
const checkLoopback = function (value) {
|
|
64
|
-
return checkBoolean(value);
|
|
65
|
-
};
|
|
66
|
-
const checkReuseAddr = function (value) {
|
|
67
|
-
return checkBoolean(value);
|
|
68
|
-
};
|
|
69
|
-
const checkTtl = function (value) {
|
|
70
|
-
if (value.length > 0 && checkNumber(value)) {
|
|
71
|
-
const ttlInt = parseInt(value);
|
|
72
|
-
return ttlInt >= 0 && ttlInt <= 255;
|
|
73
|
-
}
|
|
74
|
-
else
|
|
75
|
-
return false;
|
|
76
|
-
};
|
|
77
|
-
const checkBoolean = function (value) {
|
|
78
|
-
return typeof value === 'boolean';
|
|
79
|
-
};
|
|
80
|
-
const checkNumber = function (value) {
|
|
81
|
-
return !isNaN(value);
|
|
82
|
-
};
|
|
83
|
-
return {
|
|
84
|
-
checkInterface,
|
|
85
|
-
checkIp,
|
|
86
|
-
checkMulticast,
|
|
87
|
-
checkPort,
|
|
88
|
-
checkLoopback,
|
|
89
|
-
checkReuseAddr,
|
|
90
|
-
checkTtl,
|
|
91
|
-
};
|
|
92
|
-
};
|
|
93
|
-
module.exports = MdnsUtils;
|