hap-nodejs 0.12.3-beta.27 → 0.12.3-beta.28
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/README.md +0 -1
- package/dist/BridgedCore.js +19 -18
- package/dist/BridgedCore.js.map +1 -1
- package/dist/Core.js +20 -17
- package/dist/Core.js.map +1 -1
- package/dist/accessories/AirConditioner_accessory.js +24 -24
- package/dist/accessories/AirConditioner_accessory.js.map +1 -1
- package/dist/accessories/AppleTVRemote_accessory.js +23 -23
- package/dist/accessories/AppleTVRemote_accessory.js.map +1 -1
- package/dist/accessories/Camera_accessory.js +373 -292
- package/dist/accessories/Camera_accessory.js.map +1 -1
- package/dist/accessories/Fan_accessory.js +21 -15
- package/dist/accessories/Fan_accessory.js.map +1 -1
- package/dist/accessories/GarageDoorOpener_accessory.js +12 -12
- package/dist/accessories/GarageDoorOpener_accessory.js.map +1 -1
- package/dist/accessories/Light-AdaptiveLighting_accessory.js +21 -31
- package/dist/accessories/Light-AdaptiveLighting_accessory.js.map +1 -1
- package/dist/accessories/Light_accessory.js +48 -45
- package/dist/accessories/Light_accessory.js.map +1 -1
- package/dist/accessories/Lock_accessory.js +11 -11
- package/dist/accessories/Lock_accessory.js.map +1 -1
- package/dist/accessories/MotionSensor_accessory.js +8 -8
- package/dist/accessories/MotionSensor_accessory.js.map +1 -1
- package/dist/accessories/Outlet_accessory.js +10 -10
- package/dist/accessories/Outlet_accessory.js.map +1 -1
- package/dist/accessories/SmartSpeaker_accessory.js +11 -11
- package/dist/accessories/SmartSpeaker_accessory.js.map +1 -1
- package/dist/accessories/Sprinkler_accessory.js +19 -19
- package/dist/accessories/Sprinkler_accessory.js.map +1 -1
- package/dist/accessories/TV_accessory.js +17 -17
- package/dist/accessories/TV_accessory.js.map +1 -1
- package/dist/accessories/TemperatureSensor_accessory.js +6 -6
- package/dist/accessories/TemperatureSensor_accessory.js.map +1 -1
- package/dist/accessories/Wi-FiRouter_accessory.js +3 -3
- package/dist/accessories/Wi-FiRouter_accessory.js.map +1 -1
- package/dist/accessories/Wi-FiSatellite_accessory.js +4 -4
- package/dist/accessories/Wi-FiSatellite_accessory.js.map +1 -1
- package/dist/accessories/gstreamer-audioProducer.js +47 -36
- package/dist/accessories/gstreamer-audioProducer.js.map +1 -1
- package/dist/accessories/types.js +2 -2
- package/dist/accessories/types.js.map +1 -1
- package/dist/index.js +5 -5
- package/dist/index.js.map +1 -1
- package/dist/lib/Accessory.d.ts.map +1 -1
- package/dist/lib/Accessory.js +1088 -780
- package/dist/lib/Accessory.js.map +1 -1
- package/dist/lib/AccessoryLoader.js +40 -40
- package/dist/lib/AccessoryLoader.js.map +1 -1
- package/dist/lib/Advertiser.js +524 -392
- package/dist/lib/Advertiser.js.map +1 -1
- package/dist/lib/Bridge.js +10 -6
- package/dist/lib/Bridge.js.map +1 -1
- package/dist/lib/Characteristic.d.ts.map +1 -1
- package/dist/lib/Characteristic.js +539 -1510
- package/dist/lib/Characteristic.js.map +1 -1
- package/dist/lib/HAPServer.js +265 -215
- package/dist/lib/HAPServer.js.map +1 -1
- package/dist/lib/Service.d.ts.map +1 -1
- package/dist/lib/Service.js +320 -519
- package/dist/lib/Service.js.map +1 -1
- package/dist/lib/camera/Camera.js +14 -14
- package/dist/lib/camera/Camera.js.map +1 -1
- package/dist/lib/camera/RTPProxy.js +104 -112
- package/dist/lib/camera/RTPProxy.js.map +1 -1
- package/dist/lib/camera/RTPStreamManagement.d.ts.map +1 -1
- package/dist/lib/camera/RTPStreamManagement.js +257 -286
- package/dist/lib/camera/RTPStreamManagement.js.map +1 -1
- package/dist/lib/camera/RecordingManagement.js +384 -319
- package/dist/lib/camera/RecordingManagement.js.map +1 -1
- package/dist/lib/camera/index.js +1 -1
- package/dist/lib/controller/AdaptiveLightingController.d.ts +3 -19
- package/dist/lib/controller/AdaptiveLightingController.d.ts.map +1 -1
- package/dist/lib/controller/AdaptiveLightingController.js +218 -217
- package/dist/lib/controller/AdaptiveLightingController.js.map +1 -1
- package/dist/lib/controller/CameraController.js +250 -191
- package/dist/lib/controller/CameraController.js.map +1 -1
- package/dist/lib/controller/DoorbellController.d.ts +1 -1
- package/dist/lib/controller/DoorbellController.js +40 -39
- package/dist/lib/controller/DoorbellController.js.map +1 -1
- package/dist/lib/controller/RemoteController.js +401 -343
- package/dist/lib/controller/RemoteController.js.map +1 -1
- package/dist/lib/controller/index.js +1 -1
- package/dist/lib/datastream/DataStreamManagement.js +57 -56
- package/dist/lib/datastream/DataStreamManagement.js.map +1 -1
- package/dist/lib/datastream/DataStreamParser.js +304 -259
- package/dist/lib/datastream/DataStreamParser.js.map +1 -1
- package/dist/lib/datastream/DataStreamServer.d.ts.map +1 -1
- package/dist/lib/datastream/DataStreamServer.js +269 -252
- package/dist/lib/datastream/DataStreamServer.js.map +1 -1
- package/dist/lib/datastream/index.js +1 -1
- package/dist/lib/definitions/CharacteristicDefinitions.js +2858 -2089
- package/dist/lib/definitions/CharacteristicDefinitions.js.map +1 -1
- package/dist/lib/definitions/ServiceDefinitions.js +1096 -864
- package/dist/lib/definitions/ServiceDefinitions.js.map +1 -1
- package/dist/lib/definitions/generate-definitions.js +679 -383
- package/dist/lib/definitions/generate-definitions.js.map +1 -1
- package/dist/lib/definitions/generator-configuration.js +29 -29
- package/dist/lib/definitions/generator-configuration.js.map +1 -1
- package/dist/lib/definitions/index.js +1 -1
- package/dist/lib/model/AccessoryInfo.js +136 -101
- package/dist/lib/model/AccessoryInfo.js.map +1 -1
- package/dist/lib/model/ControllerStorage.js +89 -86
- package/dist/lib/model/ControllerStorage.js.map +1 -1
- package/dist/lib/model/HAPStorage.js +16 -15
- package/dist/lib/model/HAPStorage.js.map +1 -1
- package/dist/lib/model/IdentifierCache.js +49 -49
- package/dist/lib/model/IdentifierCache.js.map +1 -1
- package/dist/lib/tv/AccessControlManagement.js +44 -40
- package/dist/lib/tv/AccessControlManagement.js.map +1 -1
- package/dist/lib/util/clone.js +27 -5
- package/dist/lib/util/clone.js.map +1 -1
- package/dist/lib/util/color-utils.js +12 -8
- package/dist/lib/util/color-utils.js.map +1 -1
- package/dist/lib/util/eventedhttp.d.ts.map +1 -1
- package/dist/lib/util/eventedhttp.js +409 -301
- package/dist/lib/util/eventedhttp.js.map +1 -1
- package/dist/lib/util/hapCrypto.js +32 -31
- package/dist/lib/util/hapCrypto.js.map +1 -1
- package/dist/lib/util/hapStatusError.js +12 -9
- package/dist/lib/util/hapStatusError.js.map +1 -1
- package/dist/lib/util/net-utils.js +53 -32
- package/dist/lib/util/net-utils.js.map +1 -1
- package/dist/lib/util/once.js +8 -3
- package/dist/lib/util/once.js.map +1 -1
- package/dist/lib/util/promise-utils.js +13 -8
- package/dist/lib/util/promise-utils.js.map +1 -1
- package/dist/lib/util/request-util.js +3 -2
- package/dist/lib/util/request-util.js.map +1 -1
- package/dist/lib/util/time.js +5 -5
- package/dist/lib/util/time.js.map +1 -1
- package/dist/lib/util/tlv.js +75 -57
- package/dist/lib/util/tlv.js.map +1 -1
- package/dist/lib/util/uuid.js +19 -15
- package/dist/lib/util/uuid.js.map +1 -1
- package/package.json +13 -13
- package/dist/lib/util/checkName.d.ts +0 -8
- package/dist/lib/util/checkName.d.ts.map +0 -1
- package/dist/lib/util/checkName.js +0 -17
- package/dist/lib/util/checkName.js.map +0 -1
|
@@ -1,22 +1,22 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.StreamController = exports.RTPStreamManagement = exports.StreamRequestTypes = exports.AudioStreamingSamplerate = exports.AudioStreamingCodecType = exports.SRTPCryptoSuites = exports.AudioSamplerate = exports.AudioBitrate = exports.VideoCodecPacketizationMode = exports.H264Level = exports.H264Profile = exports.VideoCodecType = void 0;
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
4
|
+
var tslib_1 = require("tslib");
|
|
5
|
+
var assert_1 = tslib_1.__importDefault(require("assert"));
|
|
6
|
+
var crypto_1 = tslib_1.__importDefault(require("crypto"));
|
|
7
|
+
var debug_1 = tslib_1.__importDefault(require("debug"));
|
|
8
|
+
var net_1 = tslib_1.__importDefault(require("net"));
|
|
9
|
+
var Characteristic_1 = require("../Characteristic");
|
|
10
|
+
var controller_1 = require("../controller");
|
|
11
|
+
var Service_1 = require("../Service");
|
|
12
|
+
var hapStatusError_1 = require("../util/hapStatusError");
|
|
13
|
+
var once_1 = require("../util/once");
|
|
14
|
+
var tlv = tslib_1.__importStar(require("../util/tlv"));
|
|
15
|
+
var uuid = tslib_1.__importStar(require("../util/uuid"));
|
|
16
16
|
// noinspection JSDeprecatedSymbols
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
17
|
+
var Camera_1 = require("./Camera");
|
|
18
|
+
var RTPProxy_1 = tslib_1.__importDefault(require("./RTPProxy"));
|
|
19
|
+
var debug = (0, debug_1.default)("HAP-NodeJS:Camera:RTPStreamManagement");
|
|
20
20
|
// ---------------------------------- TLV DEFINITIONS START ----------------------------------
|
|
21
21
|
var StreamingStatusTypes;
|
|
22
22
|
(function (StreamingStatusTypes) {
|
|
@@ -283,61 +283,16 @@ var StreamRequestTypes;
|
|
|
283
283
|
/**
|
|
284
284
|
* @group Camera
|
|
285
285
|
*/
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
static VideoCodecParamProfileIDTypes = H264Profile;
|
|
297
|
-
/**
|
|
298
|
-
* @deprecated won't be updated anymore. Please use the H264Level const enum above.
|
|
299
|
-
*/
|
|
300
|
-
static VideoCodecParamLevelTypes = Object.freeze({ TYPE3_1: 0, TYPE3_2: 1, TYPE4_0: 2 });
|
|
301
|
-
id;
|
|
302
|
-
delegate;
|
|
303
|
-
service;
|
|
304
|
-
stateChangeDelegate;
|
|
305
|
-
requireProxy;
|
|
306
|
-
disableAudioProxy;
|
|
307
|
-
supportedCryptoSuites;
|
|
308
|
-
videoOnly = false;
|
|
309
|
-
supportedRTPConfiguration;
|
|
310
|
-
supportedVideoStreamConfiguration;
|
|
311
|
-
supportedAudioStreamConfiguration;
|
|
312
|
-
/**
|
|
313
|
-
* @deprecated
|
|
314
|
-
*/
|
|
315
|
-
connectionID;
|
|
316
|
-
activeConnection;
|
|
317
|
-
activeConnectionClosedListener;
|
|
318
|
-
sessionIdentifier = undefined;
|
|
319
|
-
/**
|
|
320
|
-
* @private private API
|
|
321
|
-
*/
|
|
322
|
-
streamStatus = 0 /* StreamingStatus.AVAILABLE */; // use _updateStreamStatus to update this property
|
|
323
|
-
ipVersion; // ip version for the current session
|
|
324
|
-
selectedConfiguration = ""; // base64 representation of the currently selected configuration
|
|
325
|
-
setupEndpointsResponse = ""; // response of the SetupEndpoints Characteristic
|
|
326
|
-
/**
|
|
327
|
-
* @private deprecated API
|
|
328
|
-
*/
|
|
329
|
-
audioProxy;
|
|
330
|
-
/**
|
|
331
|
-
* @private deprecated API
|
|
332
|
-
*/
|
|
333
|
-
videoProxy;
|
|
334
|
-
/**
|
|
335
|
-
* A RTPStreamManagement is considered disabled if `HomeKitCameraActive` is set to false.
|
|
336
|
-
* We use a closure based approach to retrieve the value of this characteristic.
|
|
337
|
-
* The characteristic is managed by the RecordingManagement.
|
|
338
|
-
*/
|
|
339
|
-
disabledThroughOperatingMode;
|
|
340
|
-
constructor(id, options, delegate, service, disabledThroughOperatingMode) {
|
|
286
|
+
var RTPStreamManagement = /** @class */ (function () {
|
|
287
|
+
function RTPStreamManagement(id, options, delegate, service, disabledThroughOperatingMode) {
|
|
288
|
+
this.videoOnly = false;
|
|
289
|
+
this.sessionIdentifier = undefined;
|
|
290
|
+
/**
|
|
291
|
+
* @private private API
|
|
292
|
+
*/
|
|
293
|
+
this.streamStatus = 0 /* StreamingStatus.AVAILABLE */; // use _updateStreamStatus to update this property
|
|
294
|
+
this.selectedConfiguration = ""; // base64 representation of the currently selected configuration
|
|
295
|
+
this.setupEndpointsResponse = ""; // response of the SetupEndpoints Characteristic
|
|
341
296
|
this.id = id;
|
|
342
297
|
this.delegate = delegate;
|
|
343
298
|
this.requireProxy = options.proxy || false;
|
|
@@ -364,47 +319,48 @@ class RTPStreamManagement {
|
|
|
364
319
|
this.resetSelectedStreamConfiguration();
|
|
365
320
|
this.disabledThroughOperatingMode = disabledThroughOperatingMode;
|
|
366
321
|
}
|
|
367
|
-
forceStop() {
|
|
322
|
+
RTPStreamManagement.prototype.forceStop = function () {
|
|
368
323
|
this.handleSessionClosed();
|
|
369
|
-
}
|
|
370
|
-
getService() {
|
|
324
|
+
};
|
|
325
|
+
RTPStreamManagement.prototype.getService = function () {
|
|
371
326
|
return this.service;
|
|
372
|
-
}
|
|
327
|
+
};
|
|
373
328
|
// noinspection JSUnusedGlobalSymbols,JSUnusedLocalSymbols
|
|
374
329
|
/**
|
|
375
330
|
* @deprecated
|
|
376
331
|
*/
|
|
377
332
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
378
|
-
handleCloseConnection(connectionID) {
|
|
333
|
+
RTPStreamManagement.prototype.handleCloseConnection = function (connectionID) {
|
|
379
334
|
// This method is only here for legacy compatibility. It used to be called by legacy style CameraSource
|
|
380
335
|
// implementations to signal that the associated HAP connection was closed.
|
|
381
336
|
// This is now handled automatically. Thus, we don't need to do anything anymore.
|
|
382
|
-
}
|
|
383
|
-
handleFactoryReset() {
|
|
337
|
+
};
|
|
338
|
+
RTPStreamManagement.prototype.handleFactoryReset = function () {
|
|
384
339
|
this.resetSelectedStreamConfiguration();
|
|
385
340
|
this.resetSetupEndpointsResponse();
|
|
386
341
|
this.service.updateCharacteristic(Characteristic_1.Characteristic.Active, true);
|
|
387
342
|
// on a factory reset the assumption is that all connections were already terminated and thus "handleStopStream" was already called
|
|
388
|
-
}
|
|
389
|
-
destroy() {
|
|
343
|
+
};
|
|
344
|
+
RTPStreamManagement.prototype.destroy = function () {
|
|
390
345
|
if (this.activeConnection) {
|
|
391
346
|
this._handleStopStream();
|
|
392
347
|
}
|
|
393
|
-
}
|
|
394
|
-
constructService(id) {
|
|
395
|
-
|
|
348
|
+
};
|
|
349
|
+
RTPStreamManagement.prototype.constructService = function (id) {
|
|
350
|
+
var managementService = new Service_1.Service.CameraRTPStreamManagement("", id.toString());
|
|
396
351
|
// this service is required only when recording is enabled. We don't really have access to this info here,
|
|
397
352
|
// so we just add the characteristic. Doesn't really hurt.
|
|
398
353
|
managementService.setCharacteristic(Characteristic_1.Characteristic.Active, true);
|
|
399
354
|
return managementService;
|
|
400
|
-
}
|
|
401
|
-
setupServiceHandlers() {
|
|
355
|
+
};
|
|
356
|
+
RTPStreamManagement.prototype.setupServiceHandlers = function () {
|
|
357
|
+
var _this = this;
|
|
402
358
|
if (!this.service.testCharacteristic(Characteristic_1.Characteristic.Active)) {
|
|
403
359
|
// the active characteristic might not be present on some older configurations.
|
|
404
360
|
this.service.setCharacteristic(Characteristic_1.Characteristic.Active, true);
|
|
405
361
|
}
|
|
406
362
|
this.service.getCharacteristic(Characteristic_1.Characteristic.Active)
|
|
407
|
-
.on("change" /* CharacteristicEventTypes.CHANGE */, ()
|
|
363
|
+
.on("change" /* CharacteristicEventTypes.CHANGE */, function () { var _a; return (_a = _this.stateChangeDelegate) === null || _a === void 0 ? void 0 : _a.call(_this); })
|
|
408
364
|
.setProps({ adminOnlyAccess: [1 /* Access.WRITE */] });
|
|
409
365
|
// ensure that configurations are up-to-date and reflected in the characteristic values
|
|
410
366
|
this.service.setCharacteristic(Characteristic_1.Characteristic.SupportedRTPConfiguration, this.supportedRTPConfiguration);
|
|
@@ -413,37 +369,36 @@ class RTPStreamManagement {
|
|
|
413
369
|
this._updateStreamStatus(0 /* StreamingStatus.AVAILABLE */); // reset streaming status to available
|
|
414
370
|
this.service.setCharacteristic(Characteristic_1.Characteristic.SetupEndpoints, this.setupEndpointsResponse); // reset SetupEndpoints to default
|
|
415
371
|
this.service.getCharacteristic(Characteristic_1.Characteristic.SelectedRTPStreamConfiguration)
|
|
416
|
-
.on("get" /* CharacteristicEventTypes.GET */, callback
|
|
417
|
-
if (
|
|
372
|
+
.on("get" /* CharacteristicEventTypes.GET */, function (callback) {
|
|
373
|
+
if (_this.streamingIsDisabled()) {
|
|
418
374
|
callback(null, tlv.encode(1 /* SelectedRTPStreamConfigurationTypes.SESSION_CONTROL */, tlv.encode(2 /* SessionControlTypes.COMMAND */, SessionControlCommand.SUSPEND_SESSION)).toString("base64"));
|
|
419
375
|
return;
|
|
420
376
|
}
|
|
421
|
-
callback(null,
|
|
377
|
+
callback(null, _this.selectedConfiguration);
|
|
422
378
|
})
|
|
423
379
|
.on("set" /* CharacteristicEventTypes.SET */, this._handleSelectedStreamConfigurationWrite.bind(this));
|
|
424
380
|
this.service.getCharacteristic(Characteristic_1.Characteristic.SetupEndpoints)
|
|
425
|
-
.on("get" /* CharacteristicEventTypes.GET */, callback
|
|
426
|
-
if (
|
|
381
|
+
.on("get" /* CharacteristicEventTypes.GET */, function (callback) {
|
|
382
|
+
if (_this.streamingIsDisabled()) {
|
|
427
383
|
callback(null, tlv.encode(2 /* SetupEndpointsResponseTypes.STATUS */, 2 /* SetupEndpointsStatus.ERROR */).toString("base64"));
|
|
428
384
|
return;
|
|
429
385
|
}
|
|
430
|
-
callback(null,
|
|
386
|
+
callback(null, _this.setupEndpointsResponse);
|
|
431
387
|
})
|
|
432
|
-
.on("set" /* CharacteristicEventTypes.SET */, (value, callback, context, connection)
|
|
388
|
+
.on("set" /* CharacteristicEventTypes.SET */, function (value, callback, context, connection) {
|
|
433
389
|
if (!connection) {
|
|
434
390
|
debug("Set event handler for SetupEndpoints cannot be called from plugin. Connection undefined!");
|
|
435
391
|
callback(-70410 /* HAPStatus.INVALID_VALUE_IN_REQUEST */);
|
|
436
392
|
return;
|
|
437
393
|
}
|
|
438
|
-
|
|
394
|
+
_this.handleSetupEndpoints(value, callback, connection);
|
|
439
395
|
});
|
|
440
|
-
}
|
|
441
|
-
handleSessionClosed() {
|
|
396
|
+
};
|
|
397
|
+
RTPStreamManagement.prototype.handleSessionClosed = function () {
|
|
442
398
|
this.resetSelectedStreamConfiguration();
|
|
443
399
|
this.resetSetupEndpointsResponse();
|
|
444
400
|
if (this.activeConnection) {
|
|
445
401
|
this.activeConnection.removeListener("closed" /* HAPConnectionEvent.CLOSED */, this.activeConnectionClosedListener);
|
|
446
|
-
this.activeConnection.setMaxListeners(this.activeConnection.getMaxListeners() - 1);
|
|
447
402
|
this.activeConnection = undefined;
|
|
448
403
|
}
|
|
449
404
|
this._updateStreamStatus(0 /* StreamingStatus.AVAILABLE */);
|
|
@@ -459,49 +414,51 @@ class RTPStreamManagement {
|
|
|
459
414
|
this.audioProxy.destroy();
|
|
460
415
|
this.audioProxy = undefined;
|
|
461
416
|
}
|
|
462
|
-
}
|
|
463
|
-
streamingIsDisabled(callback) {
|
|
417
|
+
};
|
|
418
|
+
RTPStreamManagement.prototype.streamingIsDisabled = function (callback) {
|
|
419
|
+
var _a;
|
|
464
420
|
if (!this.service.getCharacteristic(Characteristic_1.Characteristic.Active).value) {
|
|
465
421
|
callback && callback(new hapStatusError_1.HapStatusError(-70412 /* HAPStatus.NOT_ALLOWED_IN_CURRENT_STATE */));
|
|
466
422
|
return true;
|
|
467
423
|
}
|
|
468
|
-
if (this.disabledThroughOperatingMode
|
|
424
|
+
if ((_a = this.disabledThroughOperatingMode) === null || _a === void 0 ? void 0 : _a.call(this)) {
|
|
469
425
|
callback && callback(new hapStatusError_1.HapStatusError(-70412 /* HAPStatus.NOT_ALLOWED_IN_CURRENT_STATE */));
|
|
470
426
|
return true;
|
|
471
427
|
}
|
|
472
428
|
return false;
|
|
473
|
-
}
|
|
474
|
-
_handleSelectedStreamConfigurationWrite(value, callback) {
|
|
429
|
+
};
|
|
430
|
+
RTPStreamManagement.prototype._handleSelectedStreamConfigurationWrite = function (value, callback) {
|
|
431
|
+
var _this = this;
|
|
475
432
|
if (this.streamingIsDisabled(callback)) {
|
|
476
433
|
return;
|
|
477
434
|
}
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
435
|
+
var data = Buffer.from(value, "base64");
|
|
436
|
+
var objects = tlv.decode(data);
|
|
437
|
+
var sessionControl = tlv.decode(objects[1 /* SelectedRTPStreamConfigurationTypes.SESSION_CONTROL */]);
|
|
438
|
+
var sessionIdentifier = uuid.unparse(sessionControl[1 /* SessionControlTypes.SESSION_IDENTIFIER */]);
|
|
439
|
+
var requestType = sessionControl[2 /* SessionControlTypes.COMMAND */][0];
|
|
483
440
|
if (sessionIdentifier !== this.sessionIdentifier) {
|
|
484
|
-
debug(
|
|
441
|
+
debug("Received unknown session Identifier with request to ".concat(SessionControlCommand[requestType]));
|
|
485
442
|
callback(-70410 /* HAPStatus.INVALID_VALUE_IN_REQUEST */);
|
|
486
443
|
return;
|
|
487
444
|
}
|
|
488
445
|
this.selectedConfiguration = value;
|
|
489
446
|
// intercept the callback chain to check if an error occurred.
|
|
490
|
-
|
|
447
|
+
var streamCallback = function (error, writeResponse) {
|
|
491
448
|
callback(error, writeResponse); // does not support writeResponse, but how knows what comes in the future.
|
|
492
449
|
if (error) {
|
|
493
|
-
|
|
450
|
+
_this.handleSessionClosed();
|
|
494
451
|
}
|
|
495
452
|
};
|
|
496
453
|
switch (requestType) {
|
|
497
454
|
case SessionControlCommand.START_SESSION: {
|
|
498
|
-
|
|
499
|
-
|
|
455
|
+
var selectedVideoParameters = tlv.decode(objects[2 /* SelectedRTPStreamConfigurationTypes.SELECTED_VIDEO_PARAMETERS */]);
|
|
456
|
+
var selectedAudioParameters = tlv.decode(objects[3 /* SelectedRTPStreamConfigurationTypes.SELECTED_AUDIO_PARAMETERS */]);
|
|
500
457
|
this._handleStartStream(selectedVideoParameters, selectedAudioParameters, streamCallback);
|
|
501
458
|
break;
|
|
502
459
|
}
|
|
503
460
|
case SessionControlCommand.RECONFIGURE_SESSION: {
|
|
504
|
-
|
|
461
|
+
var reconfiguredVideoParameters = tlv.decode(objects[2 /* SelectedRTPStreamConfigurationTypes.SELECTED_VIDEO_PARAMETERS */]);
|
|
505
462
|
this.handleReconfigureStream(reconfiguredVideoParameters, streamCallback);
|
|
506
463
|
break;
|
|
507
464
|
}
|
|
@@ -511,68 +468,68 @@ class RTPStreamManagement {
|
|
|
511
468
|
case SessionControlCommand.RESUME_SESSION:
|
|
512
469
|
case SessionControlCommand.SUSPEND_SESSION:
|
|
513
470
|
default:
|
|
514
|
-
debug(
|
|
471
|
+
debug("Unhandled request type ".concat(SessionControlCommand[requestType]));
|
|
515
472
|
callback(-70410 /* HAPStatus.INVALID_VALUE_IN_REQUEST */);
|
|
516
473
|
return;
|
|
517
474
|
}
|
|
518
|
-
}
|
|
519
|
-
_handleStartStream(videoConfiguration, audioConfiguration, callback) {
|
|
475
|
+
};
|
|
476
|
+
RTPStreamManagement.prototype._handleStartStream = function (videoConfiguration, audioConfiguration, callback) {
|
|
520
477
|
// selected video configuration
|
|
521
478
|
// noinspection JSUnusedLocalSymbols
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
479
|
+
var videoCodec = videoConfiguration[1 /* SelectedVideoParametersTypes.CODEC_TYPE */]; // always 0x00 for h264
|
|
480
|
+
var videoParametersTLV = videoConfiguration[2 /* SelectedVideoParametersTypes.CODEC_PARAMETERS */];
|
|
481
|
+
var videoAttributesTLV = videoConfiguration[3 /* SelectedVideoParametersTypes.ATTRIBUTES */];
|
|
482
|
+
var videoRTPParametersTLV = videoConfiguration[4 /* SelectedVideoParametersTypes.RTP_PARAMETERS */];
|
|
526
483
|
// video parameters
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
484
|
+
var videoParameters = tlv.decode(videoParametersTLV);
|
|
485
|
+
var h264Profile = videoParameters[1 /* VideoCodecParametersTypes.PROFILE_ID */][0];
|
|
486
|
+
var h264Level = videoParameters[2 /* VideoCodecParametersTypes.LEVEL */][0];
|
|
487
|
+
var packetizationMode = videoParameters[3 /* VideoCodecParametersTypes.PACKETIZATION_MODE */][0];
|
|
488
|
+
var cvoEnabled = videoParameters[4 /* VideoCodecParametersTypes.CVO_ENABLED */];
|
|
489
|
+
var cvoId = undefined;
|
|
533
490
|
if (cvoEnabled && cvoEnabled[0] === 1 /* VideoCodecCVO.SUPPORTED */) {
|
|
534
491
|
cvoId = videoParameters[5 /* VideoCodecParametersTypes.CVO_ID */].readUInt8(0);
|
|
535
492
|
}
|
|
536
493
|
// video attributes
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
494
|
+
var videoAttributes = tlv.decode(videoAttributesTLV);
|
|
495
|
+
var width = videoAttributes[1 /* VideoAttributesTypes.IMAGE_WIDTH */].readUInt16LE(0);
|
|
496
|
+
var height = videoAttributes[2 /* VideoAttributesTypes.IMAGE_HEIGHT */].readUInt16LE(0);
|
|
497
|
+
var frameRate = videoAttributes[3 /* VideoAttributesTypes.FRAME_RATE */].readUInt8(0);
|
|
541
498
|
// video rtp parameters
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
499
|
+
var videoRTPParameters = tlv.decode(videoRTPParametersTLV);
|
|
500
|
+
var videoPayloadType = videoRTPParameters[1 /* VideoRTPParametersTypes.PAYLOAD_TYPE */].readUInt8(0); // 99
|
|
501
|
+
var videoSSRC = videoRTPParameters[2 /* VideoRTPParametersTypes.SYNCHRONIZATION_SOURCE */].readUInt32LE(0);
|
|
502
|
+
var videoMaximumBitrate = videoRTPParameters[3 /* VideoRTPParametersTypes.MAX_BIT_RATE */].readUInt16LE(0);
|
|
503
|
+
var videoRTCPInterval = videoRTPParameters[4 /* VideoRTPParametersTypes.MIN_RTCP_INTERVAL */].readFloatLE(0);
|
|
504
|
+
var maxMTU = this.ipVersion === "ipv6" ? 1228 : 1378; // default values ipv4: 1378 bytes; ipv6: 1228 bytes
|
|
548
505
|
if (videoRTPParameters[5 /* VideoRTPParametersTypes.MAX_MTU */]) {
|
|
549
506
|
maxMTU = videoRTPParameters[5 /* VideoRTPParametersTypes.MAX_MTU */].readUInt16LE(0);
|
|
550
507
|
}
|
|
551
508
|
// selected audio configuration
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
509
|
+
var audioCodec = audioConfiguration[1 /* SelectedAudioParametersTypes.CODEC_TYPE */][0];
|
|
510
|
+
var audioParametersTLV = audioConfiguration[2 /* SelectedAudioParametersTypes.CODEC_PARAMETERS */];
|
|
511
|
+
var audioRTPParametersTLV = audioConfiguration[3 /* SelectedAudioParametersTypes.RTP_PARAMETERS */];
|
|
512
|
+
var comfortNoise = !!audioConfiguration[4 /* SelectedAudioParametersTypes.COMFORT_NOISE */].readUInt8(0);
|
|
556
513
|
// audio parameters
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
514
|
+
var audioParameters = tlv.decode(audioParametersTLV);
|
|
515
|
+
var channels = audioParameters[1 /* AudioCodecParametersTypes.CHANNEL */][0];
|
|
516
|
+
var audioBitrate = audioParameters[2 /* AudioCodecParametersTypes.BIT_RATE */][0];
|
|
517
|
+
var samplerate = audioParameters[3 /* AudioCodecParametersTypes.SAMPLE_RATE */][0];
|
|
518
|
+
var rtpPacketTime = audioParameters[4 /* AudioCodecParametersTypes.PACKET_TIME */].readUInt8(0);
|
|
562
519
|
// audio rtp parameters
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
520
|
+
var audioRTPParameters = tlv.decode(audioRTPParametersTLV);
|
|
521
|
+
var audioPayloadType = audioRTPParameters[1 /* AudioRTPParametersTypes.PAYLOAD_TYPE */].readUInt8(0); // 110
|
|
522
|
+
var audioSSRC = audioRTPParameters[2 /* AudioRTPParametersTypes.SYNCHRONIZATION_SOURCE */].readUInt32LE(0);
|
|
523
|
+
var audioMaximumBitrate = audioRTPParameters[3 /* AudioRTPParametersTypes.MAX_BIT_RATE */].readUInt16LE(0);
|
|
524
|
+
var audioRTCPInterval = audioRTPParameters[4 /* AudioRTPParametersTypes.MIN_RTCP_INTERVAL */].readFloatLE(0);
|
|
525
|
+
var comfortNoisePayloadType = audioRTPParameters[6 /* AudioRTPParametersTypes.COMFORT_NOISE_PAYLOAD_TYPE */].readUInt8(0); // 13
|
|
569
526
|
if (this.requireProxy) {
|
|
570
527
|
this.videoProxy.setOutgoingPayloadType(videoPayloadType);
|
|
571
528
|
if (!this.disableAudioProxy) {
|
|
572
529
|
this.audioProxy.setOutgoingPayloadType(audioPayloadType);
|
|
573
530
|
}
|
|
574
531
|
}
|
|
575
|
-
|
|
532
|
+
var videoInfo = {
|
|
576
533
|
codec: videoCodec.readUInt8(0),
|
|
577
534
|
profile: h264Profile,
|
|
578
535
|
level: h264Level,
|
|
@@ -587,8 +544,8 @@ class RTPStreamManagement {
|
|
|
587
544
|
rtcp_interval: videoRTCPInterval,
|
|
588
545
|
mtu: maxMTU,
|
|
589
546
|
};
|
|
590
|
-
|
|
591
|
-
|
|
547
|
+
var audioCodecName;
|
|
548
|
+
var samplerateNum;
|
|
592
549
|
switch (audioCodec) {
|
|
593
550
|
case 0 /* AudioCodecTypes.PCMU */:
|
|
594
551
|
audioCodecName = "PCMU" /* AudioStreamingCodecType.PCMU */;
|
|
@@ -612,7 +569,7 @@ class RTPStreamManagement {
|
|
|
612
569
|
audioCodecName = "AMR-WB" /* AudioStreamingCodecType.AMR_WB */;
|
|
613
570
|
break;
|
|
614
571
|
default:
|
|
615
|
-
throw new Error(
|
|
572
|
+
throw new Error("Encountered unknown selected audio codec ".concat(audioCodec));
|
|
616
573
|
}
|
|
617
574
|
switch (samplerate) {
|
|
618
575
|
case 0 /* AudioSamplerate.KHZ_8 */:
|
|
@@ -625,9 +582,9 @@ class RTPStreamManagement {
|
|
|
625
582
|
samplerateNum = 24;
|
|
626
583
|
break;
|
|
627
584
|
default:
|
|
628
|
-
throw new Error(
|
|
585
|
+
throw new Error("Encountered unknown selected audio samplerate ".concat(samplerate));
|
|
629
586
|
}
|
|
630
|
-
|
|
587
|
+
var audioInfo = {
|
|
631
588
|
codec: audioCodecName,
|
|
632
589
|
channel: channels,
|
|
633
590
|
bit_rate: audioBitrate,
|
|
@@ -640,57 +597,58 @@ class RTPStreamManagement {
|
|
|
640
597
|
comfort_pt: comfortNoisePayloadType,
|
|
641
598
|
comfortNoiseEnabled: comfortNoise,
|
|
642
599
|
};
|
|
643
|
-
|
|
600
|
+
var request = {
|
|
644
601
|
sessionID: this.sessionIdentifier,
|
|
645
602
|
type: "start" /* StreamRequestTypes.START */,
|
|
646
603
|
video: videoInfo,
|
|
647
604
|
audio: audioInfo,
|
|
648
605
|
};
|
|
649
|
-
this.delegate.handleStreamRequest(request, error
|
|
650
|
-
}
|
|
651
|
-
handleReconfigureStream(videoConfiguration, callback) {
|
|
606
|
+
this.delegate.handleStreamRequest(request, function (error) { return callback(error); });
|
|
607
|
+
};
|
|
608
|
+
RTPStreamManagement.prototype.handleReconfigureStream = function (videoConfiguration, callback) {
|
|
652
609
|
// selected video configuration
|
|
653
|
-
|
|
654
|
-
|
|
610
|
+
var videoAttributesTLV = videoConfiguration[3 /* SelectedVideoParametersTypes.ATTRIBUTES */];
|
|
611
|
+
var videoRTPParametersTLV = videoConfiguration[4 /* SelectedVideoParametersTypes.RTP_PARAMETERS */];
|
|
655
612
|
// video attributes
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
613
|
+
var videoAttributes = tlv.decode(videoAttributesTLV);
|
|
614
|
+
var width = videoAttributes[1 /* VideoAttributesTypes.IMAGE_WIDTH */].readUInt16LE(0);
|
|
615
|
+
var height = videoAttributes[2 /* VideoAttributesTypes.IMAGE_HEIGHT */].readUInt16LE(0);
|
|
616
|
+
var frameRate = videoAttributes[3 /* VideoAttributesTypes.FRAME_RATE */].readUInt8(0);
|
|
660
617
|
// video rtp parameters
|
|
661
|
-
|
|
662
|
-
|
|
618
|
+
var videoRTPParameters = tlv.decode(videoRTPParametersTLV);
|
|
619
|
+
var videoMaximumBitrate = videoRTPParameters[3 /* VideoRTPParametersTypes.MAX_BIT_RATE */].readUInt16LE(0);
|
|
663
620
|
// seems to be always zero, use default of 0.5
|
|
664
|
-
|
|
665
|
-
|
|
621
|
+
var videoRTCPInterval = videoRTPParameters[4 /* VideoRTPParametersTypes.MIN_RTCP_INTERVAL */].readFloatLE(0) || 0.5;
|
|
622
|
+
var reconfiguredVideoInfo = {
|
|
666
623
|
width: width,
|
|
667
624
|
height: height,
|
|
668
625
|
fps: frameRate,
|
|
669
626
|
max_bit_rate: videoMaximumBitrate,
|
|
670
627
|
rtcp_interval: videoRTCPInterval,
|
|
671
628
|
};
|
|
672
|
-
|
|
629
|
+
var request = {
|
|
673
630
|
sessionID: this.sessionIdentifier,
|
|
674
631
|
type: "reconfigure" /* StreamRequestTypes.RECONFIGURE */,
|
|
675
632
|
video: reconfiguredVideoInfo,
|
|
676
633
|
};
|
|
677
|
-
this.delegate.handleStreamRequest(request, error
|
|
678
|
-
}
|
|
679
|
-
_handleStopStream(callback) {
|
|
680
|
-
|
|
634
|
+
this.delegate.handleStreamRequest(request, function (error) { return callback(error); });
|
|
635
|
+
};
|
|
636
|
+
RTPStreamManagement.prototype._handleStopStream = function (callback) {
|
|
637
|
+
var request = {
|
|
681
638
|
sessionID: this.sessionIdentifier, // save sessionIdentifier before handleSessionClosed is called
|
|
682
639
|
type: "stop" /* StreamRequestTypes.STOP */,
|
|
683
640
|
};
|
|
684
641
|
this.handleSessionClosed();
|
|
685
|
-
this.delegate.handleStreamRequest(request, error
|
|
686
|
-
}
|
|
687
|
-
handleSetupEndpoints(value, callback, connection) {
|
|
642
|
+
this.delegate.handleStreamRequest(request, function (error) { return callback ? callback(error) : undefined; });
|
|
643
|
+
};
|
|
644
|
+
RTPStreamManagement.prototype.handleSetupEndpoints = function (value, callback, connection) {
|
|
645
|
+
var _this = this;
|
|
688
646
|
if (this.streamingIsDisabled(callback)) {
|
|
689
647
|
return;
|
|
690
648
|
}
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
649
|
+
var data = Buffer.from(value, "base64");
|
|
650
|
+
var objects = tlv.decode(data);
|
|
651
|
+
var sessionIdentifier = uuid.unparse(objects[1 /* SetupEndpointsTypes.SESSION_ID */]);
|
|
694
652
|
if (this.streamStatus !== 0 /* StreamingStatus.AVAILABLE */) {
|
|
695
653
|
this.setupEndpointsResponse = tlv.encode(1 /* SetupEndpointsResponseTypes.SESSION_ID */, uuid.write(sessionIdentifier), 2 /* SetupEndpointsResponseTypes.STATUS */, 1 /* SetupEndpointsStatus.BUSY */).toString("base64");
|
|
696
654
|
callback();
|
|
@@ -698,33 +656,32 @@ class RTPStreamManagement {
|
|
|
698
656
|
}
|
|
699
657
|
(0, assert_1.default)(this.activeConnection == null, "Found non-nil `activeConnection` when trying to setup streaming endpoints, even though streamStatus is reported to be AVAILABLE!");
|
|
700
658
|
this.activeConnection = connection;
|
|
701
|
-
this.activeConnection.setMaxListeners(this.activeConnection.getMaxListeners() + 1);
|
|
702
659
|
this.activeConnection.on("closed" /* HAPConnectionEvent.CLOSED */, this.activeConnectionClosedListener);
|
|
703
660
|
// noinspection JSDeprecatedSymbols
|
|
704
661
|
this.connectionID = connection.sessionID;
|
|
705
662
|
this.sessionIdentifier = sessionIdentifier;
|
|
706
663
|
this._updateStreamStatus(1 /* StreamingStatus.IN_USE */);
|
|
707
664
|
// Address
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
665
|
+
var targetAddressPayload = objects[3 /* SetupEndpointsTypes.CONTROLLER_ADDRESS */];
|
|
666
|
+
var processedAddressInfo = tlv.decode(targetAddressPayload);
|
|
667
|
+
var addressVersion = processedAddressInfo[1 /* AddressTypes.ADDRESS_VERSION */][0];
|
|
668
|
+
var controllerAddress = processedAddressInfo[2 /* AddressTypes.ADDRESS */].toString("utf8");
|
|
669
|
+
var targetVideoPort = processedAddressInfo[3 /* AddressTypes.VIDEO_RTP_PORT */].readUInt16LE(0);
|
|
670
|
+
var targetAudioPort = processedAddressInfo[4 /* AddressTypes.AUDIO_RTP_PORT */].readUInt16LE(0);
|
|
714
671
|
// Video SRTP Params
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
672
|
+
var videoSRTPPayload = objects[4 /* SetupEndpointsTypes.VIDEO_SRTP_PARAMETERS */];
|
|
673
|
+
var processedVideoInfo = tlv.decode(videoSRTPPayload);
|
|
674
|
+
var videoCryptoSuite = processedVideoInfo[1 /* SRTPParametersTypes.SRTP_CRYPTO_SUITE */][0];
|
|
675
|
+
var videoMasterKey = processedVideoInfo[2 /* SRTPParametersTypes.MASTER_KEY */];
|
|
676
|
+
var videoMasterSalt = processedVideoInfo[3 /* SRTPParametersTypes.MASTER_SALT */];
|
|
720
677
|
// Audio SRTP Params
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
678
|
+
var audioSRTPPayload = objects[5 /* SetupEndpointsTypes.AUDIO_SRTP_PARAMETERS */];
|
|
679
|
+
var processedAudioInfo = tlv.decode(audioSRTPPayload);
|
|
680
|
+
var audioCryptoSuite = processedAudioInfo[1 /* SRTPParametersTypes.SRTP_CRYPTO_SUITE */][0];
|
|
681
|
+
var audioMasterKey = processedAudioInfo[2 /* SRTPParametersTypes.MASTER_KEY */];
|
|
682
|
+
var audioMasterSalt = processedAudioInfo[3 /* SRTPParametersTypes.MASTER_SALT */];
|
|
726
683
|
debug("Session: ", sessionIdentifier, "\nControllerAddress: ", controllerAddress, "\nVideoPort: ", targetVideoPort, "\nAudioPort: ", targetAudioPort, "\nVideo Crypto: ", videoCryptoSuite, "\nVideo Master Key: ", videoMasterKey, "\nVideo Master Salt: ", videoMasterSalt, "\nAudio Crypto: ", audioCryptoSuite, "\nAudio Master Key: ", audioMasterKey, "\nAudio Master Salt: ", audioMasterSalt);
|
|
727
|
-
|
|
684
|
+
var prepareRequest = {
|
|
728
685
|
sessionID: sessionIdentifier,
|
|
729
686
|
sourceAddress: connection.localAddress,
|
|
730
687
|
targetAddress: controllerAddress,
|
|
@@ -742,7 +699,7 @@ class RTPStreamManagement {
|
|
|
742
699
|
srtp_salt: audioMasterSalt,
|
|
743
700
|
},
|
|
744
701
|
};
|
|
745
|
-
|
|
702
|
+
var promises = [];
|
|
746
703
|
if (this.requireProxy) {
|
|
747
704
|
prepareRequest.targetAddress = connection.getLocalAddress(addressVersion === 1 /* IPAddressVersion.IPV6 */ ? "ipv6" : "ipv4"); // ip versions must be the same
|
|
748
705
|
this.videoProxy = new RTPProxy_1.default({
|
|
@@ -751,9 +708,9 @@ class RTPStreamManagement {
|
|
|
751
708
|
outgoingSSRC: crypto_1.default.randomBytes(4).readUInt32LE(0), // videoSSRC
|
|
752
709
|
disabled: false,
|
|
753
710
|
});
|
|
754
|
-
promises.push(this.videoProxy.setup().then(()
|
|
755
|
-
prepareRequest.video.proxy_rtp =
|
|
756
|
-
prepareRequest.video.proxy_rtcp =
|
|
711
|
+
promises.push(this.videoProxy.setup().then(function () {
|
|
712
|
+
prepareRequest.video.proxy_rtp = _this.videoProxy.incomingRTPPort();
|
|
713
|
+
prepareRequest.video.proxy_rtcp = _this.videoProxy.incomingRTCPPort();
|
|
757
714
|
}));
|
|
758
715
|
if (!this.disableAudioProxy) {
|
|
759
716
|
this.audioProxy = new RTPProxy_1.default({
|
|
@@ -762,52 +719,52 @@ class RTPStreamManagement {
|
|
|
762
719
|
outgoingSSRC: crypto_1.default.randomBytes(4).readUInt32LE(0), // audioSSRC
|
|
763
720
|
disabled: this.videoOnly,
|
|
764
721
|
});
|
|
765
|
-
promises.push(this.audioProxy.setup().then(()
|
|
766
|
-
prepareRequest.audio.proxy_rtp =
|
|
767
|
-
prepareRequest.audio.proxy_rtcp =
|
|
722
|
+
promises.push(this.audioProxy.setup().then(function () {
|
|
723
|
+
prepareRequest.audio.proxy_rtp = _this.audioProxy.incomingRTPPort();
|
|
724
|
+
prepareRequest.audio.proxy_rtcp = _this.audioProxy.incomingRTCPPort();
|
|
768
725
|
}));
|
|
769
726
|
}
|
|
770
727
|
}
|
|
771
|
-
Promise.all(promises).then(()
|
|
772
|
-
|
|
728
|
+
Promise.all(promises).then(function () {
|
|
729
|
+
_this.delegate.prepareStream(prepareRequest, (0, once_1.once)(function (error, response) {
|
|
773
730
|
if (error || !response) {
|
|
774
|
-
debug(
|
|
775
|
-
|
|
776
|
-
|
|
731
|
+
debug("PrepareStream request encountered an error: ".concat(error ? error.message : undefined));
|
|
732
|
+
_this.setupEndpointsResponse = tlv.encode(1 /* SetupEndpointsResponseTypes.SESSION_ID */, uuid.write(sessionIdentifier), 2 /* SetupEndpointsResponseTypes.STATUS */, 2 /* SetupEndpointsStatus.ERROR */).toString("base64");
|
|
733
|
+
_this.handleSessionClosed();
|
|
777
734
|
callback(error);
|
|
778
735
|
}
|
|
779
736
|
else {
|
|
780
|
-
|
|
737
|
+
_this.generateSetupEndpointResponse(connection, sessionIdentifier, prepareRequest, response, callback);
|
|
781
738
|
}
|
|
782
739
|
}));
|
|
783
740
|
});
|
|
784
|
-
}
|
|
785
|
-
generateSetupEndpointResponse(connection, identifier, request, response, callback) {
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
741
|
+
};
|
|
742
|
+
RTPStreamManagement.prototype.generateSetupEndpointResponse = function (connection, identifier, request, response, callback) {
|
|
743
|
+
var address;
|
|
744
|
+
var addressVersion = request.addressVersion;
|
|
745
|
+
var videoPort;
|
|
746
|
+
var audioPort;
|
|
747
|
+
var videoCryptoSuite;
|
|
748
|
+
var videoSRTPKey;
|
|
749
|
+
var videoSRTPSalt;
|
|
750
|
+
var audioCryptoSuite;
|
|
751
|
+
var audioSRTPKey;
|
|
752
|
+
var audioSRTPSalt;
|
|
753
|
+
var videoSSRC;
|
|
754
|
+
var audioSSRC;
|
|
798
755
|
if (!this.videoOnly && !response.audio) {
|
|
799
756
|
throw new Error("Audio was enabled but not supplied in PrepareStreamResponse!");
|
|
800
757
|
}
|
|
801
758
|
// Provide default values if audio was not supplied
|
|
802
|
-
|
|
759
|
+
var audio = response.audio || {
|
|
803
760
|
port: request.audio.port,
|
|
804
761
|
ssrc: controller_1.CameraController.generateSynchronisationSource(),
|
|
805
762
|
srtp_key: request.audio.srtp_key,
|
|
806
763
|
srtp_salt: request.audio.srtp_salt,
|
|
807
764
|
};
|
|
808
765
|
if (!this.requireProxy) {
|
|
809
|
-
|
|
810
|
-
|
|
766
|
+
var videoInfo = response.video;
|
|
767
|
+
var audioInfo = audio;
|
|
811
768
|
if (response.addressOverride) {
|
|
812
769
|
addressVersion = net_1.default.isIPv4(response.addressOverride) ? "ipv4" : "ipv6";
|
|
813
770
|
address = response.addressOverride;
|
|
@@ -816,7 +773,7 @@ class RTPStreamManagement {
|
|
|
816
773
|
address = connection.getLocalAddress(addressVersion);
|
|
817
774
|
}
|
|
818
775
|
if (request.addressVersion !== addressVersion) {
|
|
819
|
-
throw new Error(
|
|
776
|
+
throw new Error("Incoming and outgoing ip address versions must match! Expected ".concat(request.addressVersion, " but got ").concat(addressVersion));
|
|
820
777
|
}
|
|
821
778
|
videoPort = videoInfo.port;
|
|
822
779
|
audioPort = audioInfo.port;
|
|
@@ -838,7 +795,7 @@ class RTPStreamManagement {
|
|
|
838
795
|
audioSSRC = audioInfo.ssrc;
|
|
839
796
|
}
|
|
840
797
|
else {
|
|
841
|
-
|
|
798
|
+
var videoInfo = response.video;
|
|
842
799
|
address = connection.getLocalAddress(request.addressVersion);
|
|
843
800
|
videoCryptoSuite = 2 /* SRTPCryptoSuites.NONE */;
|
|
844
801
|
videoSRTPKey = Buffer.alloc(0);
|
|
@@ -853,7 +810,7 @@ class RTPStreamManagement {
|
|
|
853
810
|
videoPort = this.videoProxy.outgoingLocalPort();
|
|
854
811
|
videoSSRC = this.videoProxy.outgoingSSRC;
|
|
855
812
|
if (!this.disableAudioProxy) {
|
|
856
|
-
|
|
813
|
+
var audioInfo = response.audio;
|
|
857
814
|
this.audioProxy.setIncomingPayloadType(audioInfo.proxy_pt);
|
|
858
815
|
this.audioProxy.setServerAddress(audioInfo.proxy_server_address);
|
|
859
816
|
this.audioProxy.setServerRTPPort(audioInfo.proxy_server_rtp);
|
|
@@ -862,66 +819,66 @@ class RTPStreamManagement {
|
|
|
862
819
|
audioSSRC = this.audioProxy.outgoingSSRC;
|
|
863
820
|
}
|
|
864
821
|
else {
|
|
865
|
-
|
|
822
|
+
var audioInfo = response.audio;
|
|
866
823
|
audioPort = audioInfo.port;
|
|
867
824
|
audioSSRC = audioInfo.ssrc;
|
|
868
825
|
}
|
|
869
826
|
}
|
|
870
827
|
this.ipVersion = addressVersion; // we need to save this in order to calculate some default mtu values later
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
828
|
+
var accessoryAddress = tlv.encode(1 /* AddressTypes.ADDRESS_VERSION */, addressVersion === "ipv4" ? 0 /* IPAddressVersion.IPV4 */ : 1 /* IPAddressVersion.IPV6 */, 2 /* AddressTypes.ADDRESS */, address, 3 /* AddressTypes.VIDEO_RTP_PORT */, tlv.writeUInt16(videoPort), 4 /* AddressTypes.AUDIO_RTP_PORT */, tlv.writeUInt16(audioPort));
|
|
829
|
+
var videoSRTPParameters = tlv.encode(1 /* SRTPParametersTypes.SRTP_CRYPTO_SUITE */, videoCryptoSuite, 2 /* SRTPParametersTypes.MASTER_KEY */, videoSRTPKey, 3 /* SRTPParametersTypes.MASTER_SALT */, videoSRTPSalt);
|
|
830
|
+
var audioSRTPParameters = tlv.encode(1 /* SRTPParametersTypes.SRTP_CRYPTO_SUITE */, audioCryptoSuite, 2 /* SRTPParametersTypes.MASTER_KEY */, audioSRTPKey, 3 /* SRTPParametersTypes.MASTER_SALT */, audioSRTPSalt);
|
|
874
831
|
this.setupEndpointsResponse = tlv.encode(1 /* SetupEndpointsResponseTypes.SESSION_ID */, uuid.write(identifier), 2 /* SetupEndpointsResponseTypes.STATUS */, 0 /* SetupEndpointsStatus.SUCCESS */, 3 /* SetupEndpointsResponseTypes.ACCESSORY_ADDRESS */, accessoryAddress, 4 /* SetupEndpointsResponseTypes.VIDEO_SRTP_PARAMETERS */, videoSRTPParameters, 5 /* SetupEndpointsResponseTypes.AUDIO_SRTP_PARAMETERS */, audioSRTPParameters, 6 /* SetupEndpointsResponseTypes.VIDEO_SSRC */, tlv.writeUInt32(videoSSRC), 7 /* SetupEndpointsResponseTypes.AUDIO_SSRC */, tlv.writeUInt32(audioSSRC)).toString("base64");
|
|
875
832
|
callback();
|
|
876
|
-
}
|
|
877
|
-
_updateStreamStatus(status) {
|
|
833
|
+
};
|
|
834
|
+
RTPStreamManagement.prototype._updateStreamStatus = function (status) {
|
|
878
835
|
this.streamStatus = status;
|
|
879
836
|
this.service.updateCharacteristic(Characteristic_1.Characteristic.StreamingStatus, tlv.encode(1 /* StreamingStatusTypes.STATUS */, this.streamStatus).toString("base64"));
|
|
880
|
-
}
|
|
881
|
-
|
|
837
|
+
};
|
|
838
|
+
RTPStreamManagement._supportedRTPConfiguration = function (supportedCryptoSuites) {
|
|
882
839
|
if (supportedCryptoSuites.length === 1 && supportedCryptoSuites[0] === 2 /* SRTPCryptoSuites.NONE */) {
|
|
883
840
|
debug("Client claims it doesn't support SRTP. The stream may stops working with future iOS releases.");
|
|
884
841
|
}
|
|
885
842
|
return tlv.encode(2 /* SupportedRTPConfigurationTypes.SRTP_CRYPTO_SUITE */, supportedCryptoSuites).toString("base64");
|
|
886
|
-
}
|
|
887
|
-
|
|
843
|
+
};
|
|
844
|
+
RTPStreamManagement._supportedVideoStreamConfiguration = function (videoOptions) {
|
|
888
845
|
if (!videoOptions.codec) {
|
|
889
846
|
throw new Error("Video codec cannot be undefined");
|
|
890
847
|
}
|
|
891
848
|
if (!videoOptions.resolutions) {
|
|
892
849
|
throw new Error("Video resolutions cannot be undefined");
|
|
893
850
|
}
|
|
894
|
-
|
|
851
|
+
var codecParameters = tlv.encode(1 /* VideoCodecParametersTypes.PROFILE_ID */, videoOptions.codec.profiles, 2 /* VideoCodecParametersTypes.LEVEL */, videoOptions.codec.levels, 3 /* VideoCodecParametersTypes.PACKETIZATION_MODE */, 0 /* VideoCodecPacketizationMode.NON_INTERLEAVED */);
|
|
895
852
|
if (videoOptions.cvoId != null) {
|
|
896
853
|
codecParameters = Buffer.concat([
|
|
897
854
|
codecParameters,
|
|
898
855
|
tlv.encode(4 /* VideoCodecParametersTypes.CVO_ENABLED */, 1 /* VideoCodecCVO.SUPPORTED */, 5 /* VideoCodecParametersTypes.CVO_ID */, videoOptions.cvoId),
|
|
899
856
|
]);
|
|
900
857
|
}
|
|
901
|
-
|
|
858
|
+
var videoStreamConfiguration = tlv.encode(1 /* VideoCodecConfigurationTypes.CODEC_TYPE */, 0 /* VideoCodecType.H264 */, 2 /* VideoCodecConfigurationTypes.CODEC_PARAMETERS */, codecParameters, 3 /* VideoCodecConfigurationTypes.ATTRIBUTES */, videoOptions.resolutions.map(function (resolution) {
|
|
902
859
|
if (resolution.length !== 3) {
|
|
903
860
|
throw new Error("Unexpected video resolution");
|
|
904
861
|
}
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
862
|
+
var width = Buffer.alloc(2);
|
|
863
|
+
var height = Buffer.alloc(2);
|
|
864
|
+
var frameRate = Buffer.alloc(1);
|
|
908
865
|
width.writeUInt16LE(resolution[0], 0);
|
|
909
866
|
height.writeUInt16LE(resolution[1], 0);
|
|
910
867
|
frameRate.writeUInt8(resolution[2], 0);
|
|
911
868
|
return tlv.encode(1 /* VideoAttributesTypes.IMAGE_WIDTH */, width, 2 /* VideoAttributesTypes.IMAGE_HEIGHT */, height, 3 /* VideoAttributesTypes.FRAME_RATE */, frameRate);
|
|
912
869
|
}));
|
|
913
870
|
return tlv.encode(1 /* SupportedVideoStreamConfigurationTypes.VIDEO_CODEC_CONFIGURATION */, videoStreamConfiguration).toString("base64");
|
|
914
|
-
}
|
|
915
|
-
checkForLegacyAudioCodecRepresentation(codecs) {
|
|
916
|
-
|
|
917
|
-
codecs.slice().forEach(codec
|
|
918
|
-
|
|
871
|
+
};
|
|
872
|
+
RTPStreamManagement.prototype.checkForLegacyAudioCodecRepresentation = function (codecs) {
|
|
873
|
+
var codecMap = {};
|
|
874
|
+
codecs.slice().forEach(function (codec) {
|
|
875
|
+
var previous = codecMap[codec.type];
|
|
919
876
|
if (previous) {
|
|
920
877
|
if (typeof previous.samplerate === "number") {
|
|
921
878
|
previous.samplerate = [previous.samplerate];
|
|
922
879
|
}
|
|
923
880
|
previous.samplerate = previous.samplerate.concat(codec.samplerate);
|
|
924
|
-
|
|
881
|
+
var index = codecs.indexOf(codec);
|
|
925
882
|
if (index >= 0) {
|
|
926
883
|
codecs.splice(index, 1);
|
|
927
884
|
}
|
|
@@ -930,12 +887,12 @@ class RTPStreamManagement {
|
|
|
930
887
|
codecMap[codec.type] = codec;
|
|
931
888
|
}
|
|
932
889
|
});
|
|
933
|
-
}
|
|
934
|
-
_supportedAudioStreamConfiguration(audioOptions) {
|
|
890
|
+
};
|
|
891
|
+
RTPStreamManagement.prototype._supportedAudioStreamConfiguration = function (audioOptions) {
|
|
935
892
|
// Only AAC-ELD and OPUS are accepted by iOS currently, and we need to give it something it will accept
|
|
936
893
|
// for it to start the video stream.
|
|
937
|
-
|
|
938
|
-
|
|
894
|
+
var comfortNoise = audioOptions && !!audioOptions.comfort_noise;
|
|
895
|
+
var supportedCodecs = (audioOptions && audioOptions.codecs) || [];
|
|
939
896
|
this.checkForLegacyAudioCodecRepresentation(supportedCodecs);
|
|
940
897
|
if (supportedCodecs.length === 0) { // Fake a Codec if we haven't got anything
|
|
941
898
|
debug("Client doesn't support any audio codec that HomeKit supports.");
|
|
@@ -945,8 +902,8 @@ class RTPStreamManagement {
|
|
|
945
902
|
samplerate: [16 /* AudioStreamingSamplerate.KHZ_16 */, 24 /* AudioStreamingSamplerate.KHZ_24 */], // 16 and 24 must be supported
|
|
946
903
|
});
|
|
947
904
|
}
|
|
948
|
-
|
|
949
|
-
|
|
905
|
+
var codecConfigurations = supportedCodecs.map(function (codec) {
|
|
906
|
+
var type;
|
|
950
907
|
switch (codec.type) {
|
|
951
908
|
case "OPUS" /* AudioStreamingCodecType.OPUS */:
|
|
952
909
|
type = 3 /* AudioCodecTypes.OPUS */;
|
|
@@ -972,8 +929,8 @@ class RTPStreamManagement {
|
|
|
972
929
|
default:
|
|
973
930
|
throw new Error("Unsupported codec: " + codec.type);
|
|
974
931
|
}
|
|
975
|
-
|
|
976
|
-
|
|
932
|
+
var providedSamplerates = (typeof codec.samplerate === "number" ? [codec.samplerate] : codec.samplerate).map(function (rate) {
|
|
933
|
+
var samplerate;
|
|
977
934
|
switch (rate) {
|
|
978
935
|
case 8 /* AudioStreamingSamplerate.KHZ_8 */:
|
|
979
936
|
samplerate = 0 /* AudioSamplerate.KHZ_8 */;
|
|
@@ -989,28 +946,28 @@ class RTPStreamManagement {
|
|
|
989
946
|
samplerate = -1;
|
|
990
947
|
}
|
|
991
948
|
return samplerate;
|
|
992
|
-
}).filter(rate
|
|
949
|
+
}).filter(function (rate) { return rate !== -1; });
|
|
993
950
|
if (providedSamplerates.length === 0) {
|
|
994
951
|
throw new Error("Audio samplerate cannot be empty!");
|
|
995
952
|
}
|
|
996
|
-
|
|
953
|
+
var audioParameters = tlv.encode(1 /* AudioCodecParametersTypes.CHANNEL */, Math.max(1, codec.audioChannels || 1), 2 /* AudioCodecParametersTypes.BIT_RATE */, codec.bitrate || 0 /* AudioBitrate.VARIABLE */, 3 /* AudioCodecParametersTypes.SAMPLE_RATE */, providedSamplerates);
|
|
997
954
|
return tlv.encode(1 /* AudioCodecConfigurationTypes.CODEC_TYPE */, type, 2 /* AudioCodecConfigurationTypes.CODEC_PARAMETERS */, audioParameters);
|
|
998
955
|
});
|
|
999
956
|
return tlv.encode(1 /* SupportedAudioStreamConfigurationTypes.AUDIO_CODEC_CONFIGURATION */, codecConfigurations, 2 /* SupportedAudioStreamConfigurationTypes.COMFORT_NOISE_SUPPORT */, comfortNoise ? 1 : 0).toString("base64");
|
|
1000
|
-
}
|
|
1001
|
-
resetSetupEndpointsResponse() {
|
|
957
|
+
};
|
|
958
|
+
RTPStreamManagement.prototype.resetSetupEndpointsResponse = function () {
|
|
1002
959
|
this.setupEndpointsResponse = tlv.encode(2 /* SetupEndpointsResponseTypes.STATUS */, 2 /* SetupEndpointsStatus.ERROR */).toString("base64");
|
|
1003
960
|
this.service.updateCharacteristic(Characteristic_1.Characteristic.SetupEndpoints, this.setupEndpointsResponse);
|
|
1004
|
-
}
|
|
1005
|
-
resetSelectedStreamConfiguration() {
|
|
961
|
+
};
|
|
962
|
+
RTPStreamManagement.prototype.resetSelectedStreamConfiguration = function () {
|
|
1006
963
|
this.selectedConfiguration = tlv.encode(1 /* SelectedRTPStreamConfigurationTypes.SESSION_CONTROL */, tlv.encode(2 /* SessionControlTypes.COMMAND */, SessionControlCommand.SUSPEND_SESSION)).toString("base64");
|
|
1007
964
|
this.service.updateCharacteristic(Characteristic_1.Characteristic.SelectedRTPStreamConfiguration, this.selectedConfiguration);
|
|
1008
|
-
}
|
|
965
|
+
};
|
|
1009
966
|
/**
|
|
1010
967
|
* @private
|
|
1011
968
|
*/
|
|
1012
|
-
serialize() {
|
|
1013
|
-
|
|
969
|
+
RTPStreamManagement.prototype.serialize = function () {
|
|
970
|
+
var characteristicValue = this.service.getCharacteristic(Characteristic_1.Characteristic.Active).value;
|
|
1014
971
|
if (characteristicValue === true) {
|
|
1015
972
|
return undefined;
|
|
1016
973
|
}
|
|
@@ -1018,36 +975,50 @@ class RTPStreamManagement {
|
|
|
1018
975
|
id: this.id,
|
|
1019
976
|
active: !!characteristicValue,
|
|
1020
977
|
};
|
|
1021
|
-
}
|
|
978
|
+
};
|
|
1022
979
|
/**
|
|
1023
980
|
* @private
|
|
1024
981
|
*/
|
|
1025
|
-
deserialize(serialized) {
|
|
1026
|
-
(0, assert_1.default)(serialized.id === this.id,
|
|
982
|
+
RTPStreamManagement.prototype.deserialize = function (serialized) {
|
|
983
|
+
(0, assert_1.default)(serialized.id === this.id, "Tried to initialize RTPStreamManagement ".concat(this.id, " with data from management with id ").concat(serialized.id, "!"));
|
|
1027
984
|
this.service.updateCharacteristic(Characteristic_1.Characteristic.Active, serialized.active);
|
|
1028
|
-
}
|
|
985
|
+
};
|
|
1029
986
|
/**
|
|
1030
987
|
* @private
|
|
1031
988
|
*/
|
|
1032
|
-
setupStateChangeDelegate(delegate) {
|
|
989
|
+
RTPStreamManagement.prototype.setupStateChangeDelegate = function (delegate) {
|
|
1033
990
|
this.stateChangeDelegate = delegate;
|
|
1034
|
-
}
|
|
1035
|
-
|
|
991
|
+
};
|
|
992
|
+
/**
|
|
993
|
+
* @deprecated Please use the SRTPCryptoSuites const enum above.
|
|
994
|
+
*/
|
|
995
|
+
// @ts-expect-error: forceConsistentCasingInFileNames compiler option
|
|
996
|
+
RTPStreamManagement.SRTPCryptoSuites = SRTPCryptoSuites;
|
|
997
|
+
/**
|
|
998
|
+
* @deprecated Please use the H264Profile const enum above.
|
|
999
|
+
*/
|
|
1000
|
+
// @ts-expect-error: forceConsistentCasingInFileNames compiler option
|
|
1001
|
+
RTPStreamManagement.VideoCodecParamProfileIDTypes = H264Profile;
|
|
1002
|
+
/**
|
|
1003
|
+
* @deprecated won't be updated anymore. Please use the H264Level const enum above.
|
|
1004
|
+
*/
|
|
1005
|
+
RTPStreamManagement.VideoCodecParamLevelTypes = Object.freeze({ TYPE3_1: 0, TYPE3_2: 1, TYPE4_0: 2 });
|
|
1006
|
+
return RTPStreamManagement;
|
|
1007
|
+
}());
|
|
1036
1008
|
exports.RTPStreamManagement = RTPStreamManagement;
|
|
1037
1009
|
/**
|
|
1038
1010
|
* @group Camera
|
|
1039
1011
|
* @deprecated - only there for backwards compatibility, please use {@link RTPStreamManagement} directly
|
|
1040
1012
|
*/
|
|
1041
|
-
|
|
1042
|
-
|
|
1043
|
-
* options get saved so we can still support {@link Accessory.configureCameraSource}
|
|
1044
|
-
*/
|
|
1045
|
-
options;
|
|
1013
|
+
var StreamController = /** @class */ (function (_super) {
|
|
1014
|
+
tslib_1.__extends(StreamController, _super);
|
|
1046
1015
|
// noinspection JSDeprecatedSymbols
|
|
1047
|
-
|
|
1048
|
-
|
|
1049
|
-
|
|
1016
|
+
function StreamController(id, options, delegate, service) {
|
|
1017
|
+
var _this = _super.call(this, id, options, new Camera_1.LegacyCameraSourceAdapter(delegate), service) || this;
|
|
1018
|
+
_this.options = options;
|
|
1019
|
+
return _this;
|
|
1050
1020
|
}
|
|
1051
|
-
|
|
1021
|
+
return StreamController;
|
|
1022
|
+
}(RTPStreamManagement));
|
|
1052
1023
|
exports.StreamController = StreamController;
|
|
1053
1024
|
//# sourceMappingURL=RTPStreamManagement.js.map
|