hap-nodejs
Version:
HAP-NodeJS is a Node.js implementation of HomeKit Accessory Server.
1,623 lines (1,622 loc) • 87.5 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.Characteristic = exports.CharacteristicEventTypes = exports.ChangeReason = exports.Access = exports.Perms = exports.Units = exports.Formats = void 0;
const tslib_1 = require("tslib");
const assert_1 = tslib_1.__importDefault(require("assert"));
const debug_1 = tslib_1.__importDefault(require("debug"));
const events_1 = require("events");
const HAPServer_1 = require("./HAPServer");
const clone_1 = require("./util/clone");
const hapStatusError_1 = require("./util/hapStatusError");
const once_1 = require("./util/once");
const request_util_1 = require("./util/request-util");
const uuid_1 = require("./util/uuid");
const checkName_1 = require("./util/checkName");
const debug = (0, debug_1.default)("HAP-NodeJS:Characteristic");
/**
* @group Characteristic
*/
var Formats;
(function (Formats) {
Formats["BOOL"] = "bool";
/**
* Signed 32-bit integer
*/
Formats["INT"] = "int";
/**
* Signed 64-bit floating point
*/
Formats["FLOAT"] = "float";
/**
* String encoded in utf8
*/
Formats["STRING"] = "string";
/**
* Unsigned 8-bit integer.
*/
Formats["UINT8"] = "uint8";
/**
* Unsigned 16-bit integer.
*/
Formats["UINT16"] = "uint16";
/**
* Unsigned 32-bit integer.
*/
Formats["UINT32"] = "uint32";
/**
* Unsigned 64-bit integer.
*/
Formats["UINT64"] = "uint64";
/**
* Data is base64 encoded string.
*/
Formats["DATA"] = "data";
/**
* Base64 encoded tlv8 string.
*/
Formats["TLV8"] = "tlv8";
})(Formats || (exports.Formats = Formats = {}));
/**
* @group Characteristic
*/
var Units;
(function (Units) {
/**
* Celsius is the only temperature unit in the HomeKit Accessory Protocol.
* Unit conversion is always done on the client side e.g. on the iPhone in the Home App depending on
* the configured unit on the device itself.
*/
Units["CELSIUS"] = "celsius";
Units["PERCENTAGE"] = "percentage";
Units["ARC_DEGREE"] = "arcdegrees";
Units["LUX"] = "lux";
Units["SECONDS"] = "seconds";
})(Units || (exports.Units = Units = {}));
/**
* @group Characteristic
*/
var Perms;
(function (Perms) {
// eslint-disable-next-line @typescript-eslint/no-duplicate-enum-values
Perms["PAIRED_READ"] = "pr";
// eslint-disable-next-line @typescript-eslint/no-duplicate-enum-values
Perms["PAIRED_WRITE"] = "pw";
Perms["NOTIFY"] = "ev";
// eslint-disable-next-line @typescript-eslint/no-duplicate-enum-values
Perms["EVENTS"] = "ev";
Perms["ADDITIONAL_AUTHORIZATION"] = "aa";
Perms["TIMED_WRITE"] = "tw";
Perms["HIDDEN"] = "hd";
Perms["WRITE_RESPONSE"] = "wr";
})(Perms || (exports.Perms = Perms = {}));
/**
* Describes the abstract access to a {@link Characteristic}.
* It abstracts the more granular access described by {@link Perms}.
*
* It is used in {@link CharacteristicProps.adminOnlyAccess}.
*
* @group Characteristic
*/
var Access;
(function (Access) {
Access[Access["READ"] = 0] = "READ";
Access[Access["WRITE"] = 1] = "WRITE";
Access[Access["NOTIFY"] = 2] = "NOTIFY";
})(Access || (exports.Access = Access = {}));
/**
* @group Characteristic
*/
var ChangeReason;
(function (ChangeReason) {
/**
* Reason used when HomeKit writes a value or the API user calls {@link Characteristic.setValue}.
*/
ChangeReason["WRITE"] = "write";
/**
* Reason used when the API user calls the method {@link Characteristic.updateValue}.
*/
ChangeReason["UPDATE"] = "update";
/**
* Used when HomeKit reads a value or the API user calls the deprecated method `Characteristic.getValue`.
*/
ChangeReason["READ"] = "read";
/**
* Used when call to {@link Characteristic.sendEventNotification} was made.
*/
ChangeReason["EVENT"] = "event";
})(ChangeReason || (exports.ChangeReason = ChangeReason = {}));
/**
* @group Characteristic
*/
var CharacteristicEventTypes;
(function (CharacteristicEventTypes) {
/**
* This event is thrown when a HomeKit controller wants to read the current value of the characteristic.
* The event handler should call the supplied callback as fast as possible.
*
* HAP-NodeJS will complain about slow running get handlers after 3 seconds and terminate the request after 10 seconds.
*/
CharacteristicEventTypes["GET"] = "get";
/**
* This event is thrown when a HomeKit controller wants to write a new value to the characteristic.
* The event handler should call the supplied callback as fast as possible.
*
* HAP-NodeJS will complain about slow running set handlers after 3 seconds and terminate the request after 10 seconds.
*/
CharacteristicEventTypes["SET"] = "set";
/**
* Emitted after a new value is set for the characteristic.
* The new value can be set via a request by a HomeKit controller or via an API call.
*/
CharacteristicEventTypes["CHANGE"] = "change";
/**
* @private
*/
CharacteristicEventTypes["SUBSCRIBE"] = "subscribe";
/**
* @private
*/
CharacteristicEventTypes["UNSUBSCRIBE"] = "unsubscribe";
/**
* @private
*/
CharacteristicEventTypes["CHARACTERISTIC_WARNING"] = "characteristic-warning";
})(CharacteristicEventTypes || (exports.CharacteristicEventTypes = CharacteristicEventTypes = {}));
/**
* @group Characteristic
*/
class ValidValuesIterable {
props;
constructor(props) {
(0, assert_1.default)((0, request_util_1.isNumericFormat)(props.format), "Cannot instantiate valid values iterable when format is not numeric. Found " + props.format);
this.props = props;
}
*[Symbol.iterator]() {
if (this.props.validValues) {
for (const value of this.props.validValues) {
yield value;
}
}
else {
let min = 0; // default is zero for all the uint types
let max;
let stepValue = 1;
if (this.props.validValueRanges) {
min = this.props.validValueRanges[0];
max = this.props.validValueRanges[1];
}
else if (this.props.minValue != null && this.props.maxValue != null) {
min = this.props.minValue;
max = this.props.maxValue;
if (this.props.minStep != null) {
stepValue = this.props.minStep;
}
}
else if ((0, request_util_1.isUnsignedNumericFormat)(this.props.format)) {
max = (0, request_util_1.numericUpperBound)(this.props.format);
}
else {
throw new Error("Could not find valid iterator strategy for props: " + JSON.stringify(this.props));
}
for (let i = min; i <= max; i += stepValue) {
yield i;
}
}
}
}
const numberPattern = /^-?\d+$/;
function extractHAPStatusFromError(error) {
let errorValue = -70402 /* HAPStatus.SERVICE_COMMUNICATION_FAILURE */;
if (numberPattern.test(error.message)) {
const value = parseInt(error.message, 10);
if ((0, HAPServer_1.IsKnownHAPStatusError)(value)) {
errorValue = value;
}
}
return errorValue;
}
function maxWithUndefined(a, b) {
if (a == null) {
return b;
}
else if (b == null) {
return a;
}
else {
return Math.max(a, b);
}
}
function minWithUndefined(a, b) {
if (a == null) {
return b;
}
else if (b == null) {
return a;
}
else {
return Math.min(a, b);
}
}
/**
* Characteristic represents a particular typed variable that can be assigned to a Service. For instance, a
* "Hue" Characteristic might store a 'float' value of type 'arcdegrees'. You could add the Hue Characteristic
* to a {@link Service} in order to store that value. A particular Characteristic is distinguished from others by its
* UUID. HomeKit provides a set of known Characteristic UUIDs defined in HomeKit.ts along with a
* corresponding concrete subclass.
*
* You can also define custom Characteristics by providing your own UUID. Custom Characteristics can be added
* to any native or custom Services, but Siri will likely not be able to work with these.
*
* @group Characteristic
*/
// eslint-disable-next-line @typescript-eslint/no-unsafe-declaration-merging
class Characteristic extends events_1.EventEmitter {
// Pattern below is for automatic detection of the section of defined characteristics. Used by the generator
// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-
/**
* @group Characteristic Definitions
*/
static AccessCodeControlPoint;
/**
* @group Characteristic Definitions
*/
static AccessCodeSupportedConfiguration;
/**
* @group Characteristic Definitions
*/
static AccessControlLevel;
/**
* @group Characteristic Definitions
*/
static AccessoryFlags;
/**
* @group Characteristic Definitions
*/
static AccessoryIdentifier;
/**
* @group Characteristic Definitions
*/
static Active;
/**
* @group Characteristic Definitions
*/
static ActiveIdentifier;
/**
* @group Characteristic Definitions
*/
static ActivityInterval;
/**
* @group Characteristic Definitions
*/
static AdministratorOnlyAccess;
/**
* @group Characteristic Definitions
*/
static AirParticulateDensity;
/**
* @group Characteristic Definitions
*/
static AirParticulateSize;
/**
* @group Characteristic Definitions
*/
static AirPlayEnable;
/**
* @group Characteristic Definitions
*/
static AirQuality;
/**
* @group Characteristic Definitions
*/
static AppMatchingIdentifier;
/**
* @group Characteristic Definitions
*/
static AssetUpdateReadiness;
/**
* @group Characteristic Definitions
*/
static AudioFeedback;
/**
* @group Characteristic Definitions
*/
static BatteryLevel;
/**
* @group Characteristic Definitions
*/
static Brightness;
/**
* @group Characteristic Definitions
*/
static ButtonEvent;
/**
* @group Characteristic Definitions
*/
static CameraOperatingModeIndicator;
/**
* @group Characteristic Definitions
*/
static CarbonDioxideDetected;
/**
* @group Characteristic Definitions
*/
static CarbonDioxideLevel;
/**
* @group Characteristic Definitions
*/
static CarbonDioxidePeakLevel;
/**
* @group Characteristic Definitions
*/
static CarbonMonoxideDetected;
/**
* @group Characteristic Definitions
*/
static CarbonMonoxideLevel;
/**
* @group Characteristic Definitions
*/
static CarbonMonoxidePeakLevel;
/**
* @group Characteristic Definitions
*/
static CCAEnergyDetectThreshold;
/**
* @group Characteristic Definitions
*/
static CCASignalDetectThreshold;
/**
* @group Characteristic Definitions
*/
static CharacteristicValueActiveTransitionCount;
/**
* @group Characteristic Definitions
*/
static CharacteristicValueTransitionControl;
/**
* @group Characteristic Definitions
*/
static ChargingState;
/**
* @group Characteristic Definitions
*/
static ClosedCaptions;
/**
* @group Characteristic Definitions
*/
static ColorTemperature;
/**
* @group Characteristic Definitions
*/
static ConfigurationState;
/**
* @group Characteristic Definitions
*/
static ConfiguredName;
/**
* @group Characteristic Definitions
*/
static ContactSensorState;
/**
* @group Characteristic Definitions
*/
static CoolingThresholdTemperature;
/**
* @group Characteristic Definitions
*/
static CryptoHash;
/**
* @group Characteristic Definitions
*/
static CurrentAirPurifierState;
/**
* @group Characteristic Definitions
*/
static CurrentAmbientLightLevel;
/**
* @group Characteristic Definitions
*/
static CurrentDoorState;
/**
* @group Characteristic Definitions
*/
static CurrentFanState;
/**
* @group Characteristic Definitions
*/
static CurrentHeaterCoolerState;
/**
* @group Characteristic Definitions
*/
static CurrentHeatingCoolingState;
/**
* @group Characteristic Definitions
*/
static CurrentHorizontalTiltAngle;
/**
* @group Characteristic Definitions
*/
static CurrentHumidifierDehumidifierState;
/**
* @group Characteristic Definitions
*/
static CurrentMediaState;
/**
* @group Characteristic Definitions
*/
static CurrentPosition;
/**
* @group Characteristic Definitions
*/
static CurrentRelativeHumidity;
/**
* @group Characteristic Definitions
*/
static CurrentSlatState;
/**
* @group Characteristic Definitions
*/
static CurrentTemperature;
/**
* @group Characteristic Definitions
*/
static CurrentTiltAngle;
/**
* @group Characteristic Definitions
*/
static CurrentTransport;
/**
* @group Characteristic Definitions
*/
static CurrentVerticalTiltAngle;
/**
* @group Characteristic Definitions
*/
static CurrentVisibilityState;
/**
* @group Characteristic Definitions
*/
static DataStreamHAPTransport;
/**
* @group Characteristic Definitions
*/
static DataStreamHAPTransportInterrupt;
/**
* @group Characteristic Definitions
*/
static DiagonalFieldOfView;
/**
* @group Characteristic Definitions
*/
static DigitalZoom;
/**
* @group Characteristic Definitions
*/
static DisplayOrder;
/**
* @group Characteristic Definitions
*/
static EventRetransmissionMaximum;
/**
* @group Characteristic Definitions
*/
static EventSnapshotsActive;
/**
* @group Characteristic Definitions
*/
static EventTransmissionCounters;
/**
* @group Characteristic Definitions
*/
static FilterChangeIndication;
/**
* @group Characteristic Definitions
*/
static FilterLifeLevel;
/**
* @group Characteristic Definitions
*/
static FirmwareRevision;
/**
* @group Characteristic Definitions
*/
static FirmwareUpdateReadiness;
/**
* @group Characteristic Definitions
*/
static FirmwareUpdateStatus;
/**
* @group Characteristic Definitions
*/
static HardwareFinish;
/**
* @group Characteristic Definitions
*/
static HardwareRevision;
/**
* @group Characteristic Definitions
*/
static HeartBeat;
/**
* @group Characteristic Definitions
*/
static HeatingThresholdTemperature;
/**
* @group Characteristic Definitions
*/
static HoldPosition;
/**
* @group Characteristic Definitions
*/
static HomeKitCameraActive;
/**
* @group Characteristic Definitions
*/
static Hue;
/**
* @group Characteristic Definitions
*/
static Identifier;
/**
* @group Characteristic Definitions
*/
static Identify;
/**
* @group Characteristic Definitions
*/
static ImageMirroring;
/**
* @group Characteristic Definitions
*/
static ImageRotation;
/**
* @group Characteristic Definitions
*/
static InputDeviceType;
/**
* @group Characteristic Definitions
*/
static InputSourceType;
/**
* @group Characteristic Definitions
*/
static InUse;
/**
* @group Characteristic Definitions
*/
static IsConfigured;
/**
* @group Characteristic Definitions
*/
static LeakDetected;
/**
* @group Characteristic Definitions
*/
static ListPairings;
/**
* @group Characteristic Definitions
*/
static LockControlPoint;
/**
* @group Characteristic Definitions
*/
static LockCurrentState;
/**
* @group Characteristic Definitions
*/
static LockLastKnownAction;
/**
* @group Characteristic Definitions
*/
static LockManagementAutoSecurityTimeout;
/**
* @group Characteristic Definitions
*/
static LockPhysicalControls;
/**
* @group Characteristic Definitions
*/
static LockTargetState;
/**
* @group Characteristic Definitions
*/
static Logs;
/**
* @group Characteristic Definitions
*/
static MACRetransmissionMaximum;
/**
* @group Characteristic Definitions
*/
static MACTransmissionCounters;
/**
* @group Characteristic Definitions
*/
static ManagedNetworkEnable;
/**
* @group Characteristic Definitions
*/
static ManuallyDisabled;
/**
* @group Characteristic Definitions
*/
static Manufacturer;
/**
* @group Characteristic Definitions
*/
static MaximumTransmitPower;
/**
* @group Characteristic Definitions
*/
static MetricsBufferFullState;
/**
* @group Characteristic Definitions
*/
static Model;
/**
* @group Characteristic Definitions
*/
static MotionDetected;
/**
* @group Characteristic Definitions
*/
static MultifunctionButton;
/**
* @group Characteristic Definitions
*/
static Mute;
/**
* @group Characteristic Definitions
*/
static Name;
/**
* @group Characteristic Definitions
*/
static NetworkAccessViolationControl;
/**
* @group Characteristic Definitions
*/
static NetworkClientProfileControl;
/**
* @group Characteristic Definitions
*/
static NetworkClientStatusControl;
/**
* @group Characteristic Definitions
*/
static NFCAccessControlPoint;
/**
* @group Characteristic Definitions
*/
static NFCAccessSupportedConfiguration;
/**
* @group Characteristic Definitions
*/
static NightVision;
/**
* @group Characteristic Definitions
*/
static NitrogenDioxideDensity;
/**
* @group Characteristic Definitions
*/
static ObstructionDetected;
/**
* @group Characteristic Definitions
*/
static OccupancyDetected;
/**
* @group Characteristic Definitions
*/
static On;
/**
* @group Characteristic Definitions
*/
static OperatingStateResponse;
/**
* @group Characteristic Definitions
*/
static OpticalZoom;
/**
* @group Characteristic Definitions
*/
static OutletInUse;
/**
* @group Characteristic Definitions
*/
static OzoneDensity;
/**
* @group Characteristic Definitions
*/
static PairingFeatures;
/**
* @group Characteristic Definitions
*/
static PairSetup;
/**
* @group Characteristic Definitions
*/
static PairVerify;
/**
* @group Characteristic Definitions
*/
static PasswordSetting;
/**
* @group Characteristic Definitions
*/
static PeriodicSnapshotsActive;
/**
* @group Characteristic Definitions
*/
static PictureMode;
/**
* @group Characteristic Definitions
*/
static Ping;
/**
* @group Characteristic Definitions
*/
static PM10Density;
/**
* @group Characteristic Definitions
*/
static PM2_5Density;
/**
* @group Characteristic Definitions
*/
static PositionState;
/**
* @group Characteristic Definitions
*/
static PowerModeSelection;
/**
* @group Characteristic Definitions
*/
static ProductData;
/**
* @group Characteristic Definitions
*/
static ProgrammableSwitchEvent;
/**
* @group Characteristic Definitions
*/
static ProgrammableSwitchOutputState;
/**
* @group Characteristic Definitions
*/
static ProgramMode;
/**
* @group Characteristic Definitions
*/
static ReceivedSignalStrengthIndication;
/**
* @group Characteristic Definitions
*/
static ReceiverSensitivity;
/**
* @group Characteristic Definitions
*/
static RecordingAudioActive;
/**
* @group Characteristic Definitions
*/
static RelativeHumidityDehumidifierThreshold;
/**
* @group Characteristic Definitions
*/
static RelativeHumidityHumidifierThreshold;
/**
* @group Characteristic Definitions
*/
static RelayControlPoint;
/**
* @group Characteristic Definitions
*/
static RelayEnabled;
/**
* @group Characteristic Definitions
*/
static RelayState;
/**
* @group Characteristic Definitions
*/
static RemainingDuration;
/**
* @group Characteristic Definitions
*/
static RemoteKey;
/**
* @group Characteristic Definitions
*/
static ResetFilterIndication;
/**
* @group Characteristic Definitions
*/
static RotationDirection;
/**
* @group Characteristic Definitions
*/
static RotationSpeed;
/**
* @group Characteristic Definitions
*/
static RouterStatus;
/**
* @group Characteristic Definitions
*/
static Saturation;
/**
* @group Characteristic Definitions
*/
static SecuritySystemAlarmType;
/**
* @group Characteristic Definitions
*/
static SecuritySystemCurrentState;
/**
* @group Characteristic Definitions
*/
static SecuritySystemTargetState;
/**
* @group Characteristic Definitions
*/
static SelectedAudioStreamConfiguration;
/**
* @group Characteristic Definitions
*/
static SelectedCameraRecordingConfiguration;
/**
* @group Characteristic Definitions
*/
static SelectedDiagnosticsModes;
/**
* @group Characteristic Definitions
*/
static SelectedRTPStreamConfiguration;
/**
* @group Characteristic Definitions
*/
static SelectedSleepConfiguration;
/**
* @group Characteristic Definitions
*/
static SerialNumber;
/**
* @group Characteristic Definitions
*/
static ServiceLabelIndex;
/**
* @group Characteristic Definitions
*/
static ServiceLabelNamespace;
/**
* @group Characteristic Definitions
*/
static SetDuration;
/**
* @group Characteristic Definitions
*/
static SetupDataStreamTransport;
/**
* @group Characteristic Definitions
*/
static SetupEndpoints;
/**
* @group Characteristic Definitions
*/
static SetupTransferTransport;
/**
* @group Characteristic Definitions
*/
static SignalToNoiseRatio;
/**
* @group Characteristic Definitions
*/
static SiriEnable;
/**
* @group Characteristic Definitions
*/
static SiriEndpointSessionStatus;
/**
* @group Characteristic Definitions
*/
static SiriEngineVersion;
/**
* @group Characteristic Definitions
*/
static SiriInputType;
/**
* @group Characteristic Definitions
*/
static SiriLightOnUse;
/**
* @group Characteristic Definitions
*/
static SiriListening;
/**
* @group Characteristic Definitions
*/
static SiriTouchToUse;
/**
* @group Characteristic Definitions
*/
static SlatType;
/**
* @group Characteristic Definitions
*/
static SleepDiscoveryMode;
/**
* @group Characteristic Definitions
*/
static SleepInterval;
/**
* @group Characteristic Definitions
*/
static SmokeDetected;
/**
* @group Characteristic Definitions
*/
static SoftwareRevision;
/**
* @group Characteristic Definitions
*/
static StagedFirmwareVersion;
/**
* @group Characteristic Definitions
*/
static StatusActive;
/**
* @group Characteristic Definitions
*/
static StatusFault;
/**
* @group Characteristic Definitions
*/
static StatusJammed;
/**
* @group Characteristic Definitions
*/
static StatusLowBattery;
/**
* @group Characteristic Definitions
*/
static StatusTampered;
/**
* @group Characteristic Definitions
*/
static StreamingStatus;
/**
* @group Characteristic Definitions
*/
static SulphurDioxideDensity;
/**
* @group Characteristic Definitions
*/
static SupportedAssetTypes;
/**
* @group Characteristic Definitions
*/
static SupportedAudioRecordingConfiguration;
/**
* @group Characteristic Definitions
*/
static SupportedAudioStreamConfiguration;
/**
* @group Characteristic Definitions
*/
static SupportedCameraRecordingConfiguration;
/**
* @group Characteristic Definitions
*/
static SupportedCharacteristicValueTransitionConfiguration;
/**
* @group Characteristic Definitions
*/
static SupportedDataStreamTransportConfiguration;
/**
* @group Characteristic Definitions
*/
static SupportedDiagnosticsModes;
/**
* @group Characteristic Definitions
*/
static SupportedDiagnosticsSnapshot;
/**
* @group Characteristic Definitions
*/
static SupportedFirmwareUpdateConfiguration;
/**
* @group Characteristic Definitions
*/
static SupportedMetrics;
/**
* @group Characteristic Definitions
*/
static SupportedRouterConfiguration;
/**
* @group Characteristic Definitions
*/
static SupportedRTPConfiguration;
/**
* @group Characteristic Definitions
*/
static SupportedSleepConfiguration;
/**
* @group Characteristic Definitions
*/
static SupportedTransferTransportConfiguration;
/**
* @group Characteristic Definitions
*/
static SupportedVideoRecordingConfiguration;
/**
* @group Characteristic Definitions
*/
static SupportedVideoStreamConfiguration;
/**
* @group Characteristic Definitions
*/
static SwingMode;
/**
* @group Characteristic Definitions
*/
static TapType;
/**
* @group Characteristic Definitions
*/
static TargetAirPurifierState;
/**
* @group Characteristic Definitions
*/
static TargetControlList;
/**
* @group Characteristic Definitions
*/
static TargetControlSupportedConfiguration;
/**
* @group Characteristic Definitions
*/
static TargetDoorState;
/**
* @group Characteristic Definitions
*/
static TargetFanState;
/**
* @group Characteristic Definitions
*/
static TargetHeaterCoolerState;
/**
* @group Characteristic Definitions
*/
static TargetHeatingCoolingState;
/**
* @group Characteristic Definitions
*/
static TargetHorizontalTiltAngle;
/**
* @group Characteristic Definitions
*/
static TargetHumidifierDehumidifierState;
/**
* @group Characteristic Definitions
*/
static TargetMediaState;
/**
* @group Characteristic Definitions
*/
static TargetPosition;
/**
* @group Characteristic Definitions
*/
static TargetRelativeHumidity;
/**
* @group Characteristic Definitions
*/
static TargetTemperature;
/**
* @group Characteristic Definitions
*/
static TargetTiltAngle;
/**
* @group Characteristic Definitions
*/
static TargetVerticalTiltAngle;
/**
* @group Characteristic Definitions
*/
static TargetVisibilityState;
/**
* @group Characteristic Definitions
*/
static TemperatureDisplayUnits;
/**
* @group Characteristic Definitions
*/
static ThirdPartyCameraActive;
/**
* @group Characteristic Definitions
*/
static ThreadControlPoint;
/**
* @group Characteristic Definitions
*/
static ThreadNodeCapabilities;
/**
* @group Characteristic Definitions
*/
static ThreadOpenThreadVersion;
/**
* @group Characteristic Definitions
*/
static ThreadStatus;
/**
* @group Characteristic Definitions
*/
static Token;
/**
* @group Characteristic Definitions
*/
static TransmitPower;
/**
* @group Characteristic Definitions
*/
static TunnelConnectionTimeout;
/**
* @group Characteristic Definitions
*/
static TunneledAccessoryAdvertising;
/**
* @group Characteristic Definitions
*/
static TunneledAccessoryConnected;
/**
* @group Characteristic Definitions
*/
static TunneledAccessoryStateNumber;
/**
* @group Characteristic Definitions
*/
static ValveType;
/**
* @group Characteristic Definitions
*/
static Version;
/**
* @group Characteristic Definitions
*/
static VideoAnalysisActive;
/**
* @group Characteristic Definitions
*/
static VOCDensity;
/**
* @group Characteristic Definitions
*/
static Volume;
/**
* @group Characteristic Definitions
*/
static VolumeControlType;
/**
* @group Characteristic Definitions
*/
static VolumeSelector;
/**
* @group Characteristic Definitions
*/
static WakeConfiguration;
/**
* @group Characteristic Definitions
*/
static WANConfigurationList;
/**
* @group Characteristic Definitions
*/
static WANStatusList;
/**
* @group Characteristic Definitions
*/
static WaterLevel;
/**
* @group Characteristic Definitions
*/
static WiFiCapabilities;
/**
* @group Characteristic Definitions
*/
static WiFiConfigurationControl;
/**
* @group Characteristic Definitions
*/
static WiFiSatelliteStatus;
// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=
// NOTICE: when adding/changing properties, remember to possibly adjust the serialize/deserialize functions
displayName;
UUID;
iid = null;
value = null;
/**
* @private
*/
statusCode = 0 /* HAPStatus.SUCCESS */;
props;
/**
* The {@link Characteristic.onGet} handler
*/
getHandler;
/**
* The {@link Characteristic.onSet} handler
*/
setHandler;
subscriptions = 0;
/**
* @private
*/
additionalAuthorizationHandler;
constructor(displayName, UUID, props) {
super();
this.displayName = displayName;
this.UUID = UUID;
this.props = {
format: "int" /* Formats.INT */,
perms: ["ev" /* Perms.NOTIFY */],
};
this.setProps(props || {}); // ensure sanity checks are called
}
/**
* Accepts a function that will be called to retrieve the current value of a Characteristic.
* The function must return a valid Characteristic value for the Characteristic type.
* May optionally return a promise.
*
* @example
* ```ts
* Characteristic.onGet(async () => {
* return true;
* });
* ```
* @param handler
*/
onGet(handler) {
if (typeof handler !== "function") {
this.characteristicWarning(".onGet handler must be a function");
return this;
}
this.getHandler = handler;
return this;
}
/**
* Removes the {@link CharacteristicGetHandler} handler which was configured using {@link onGet}.
*/
removeOnGet() {
this.getHandler = undefined;
return this;
}
/**
* Accepts a function that will be called when setting the value of a Characteristic.
* If the characteristic supports {@link Perms.WRITE_RESPONSE} and the request requests a write-response value,
* the returned value will be used.
* May optionally return a promise.
*
* @example
* ```ts
* Characteristic.onSet(async (value: CharacteristicValue) => {
* console.log(value);
* });
* ```
* @param handler
*/
onSet(handler) {
if (typeof handler !== "function") {
this.characteristicWarning(".onSet handler must be a function");
return this;
}
this.setHandler = handler;
return this;
}
/**
* Removes the {@link CharacteristicSetHandler} which was configured using {@link onSet}.
*/
removeOnSet() {
this.setHandler = undefined;
return this;
}
/**
* Updates the properties of this characteristic.
* Properties passed via the parameter will be set. Any parameter set to null will be deleted.
* See {@link CharacteristicProps}.
*
* @param props - Partial properties object with the desired updates.
*/
setProps(props) {
(0, assert_1.default)(props, "props cannot be undefined when setting props");
// TODO calling setProps after publish doesn't lead to a increment in the current configuration number
let formatDidChange = false;
// for every value "null" can be used to reset props, except for required props
if (props.format) {
formatDidChange = this.props.format !== props.format;
this.props.format = props.format;
}
if (props.perms) {
(0, assert_1.default)(props.perms.length > 0, "characteristic prop perms cannot be empty array");
this.props.perms = props.perms;
}
if (props.unit !== undefined) {
this.props.unit = props.unit != null ? props.unit : undefined;
}
if (props.description !== undefined) {
this.props.description = props.description != null ? props.description : undefined;
}
// check minValue is valid for the format type
if (props.minValue !== undefined) {
if (props.minValue === null) {
props.minValue = undefined;
}
else if (!(0, request_util_1.isNumericFormat)(this.props.format)) {
this.characteristicWarning("Characteristic Property 'minValue' can only be set for characteristics with numeric format, but not for " + this.props.format, "error-message" /* CharacteristicWarningType.ERROR_MESSAGE */);
props.minValue = undefined;
}
else if (typeof props.minValue !== "number" || !Number.isFinite(props.minValue)) {
this.characteristicWarning(`Characteristic Property 'minValue' must be a finite number, received "${props.minValue}" (${typeof props.minValue})`, "error-message" /* CharacteristicWarningType.ERROR_MESSAGE */);
props.minValue = undefined;
}
else {
if (props.minValue < (0, request_util_1.numericLowerBound)(this.props.format)) {
this.characteristicWarning("Characteristic Property 'minValue' was set to " + props.minValue + ", but for numeric format " +
this.props.format + " minimum possible is " + (0, request_util_1.numericLowerBound)(this.props.format), "error-message" /* CharacteristicWarningType.ERROR_MESSAGE */);
props.minValue = (0, request_util_1.numericLowerBound)(this.props.format);
}
else if (props.minValue > (0, request_util_1.numericUpperBound)(this.props.format)) {
this.characteristicWarning("Characteristic Property 'minValue' was set to " + props.minValue + ", but for numeric format " +
this.props.format + " maximum possible is " + (0, request_util_1.numericUpperBound)(this.props.format), "error-message" /* CharacteristicWarningType.ERROR_MESSAGE */);
props.minValue = (0, request_util_1.numericLowerBound)(this.props.format);
}
}
this.props.minValue = props.minValue;
}
// check maxValue is valid for the format type
if (props.maxValue !== undefined) {
if (props.maxValue === null) {
props.maxValue = undefined;
}
else if (!(0, request_util_1.isNumericFormat)(this.props.format)) {
this.characteristicWarning("Characteristic Property 'maxValue' can only be set for characteristics with numeric format, but not for " + this.props.format, "error-message" /* CharacteristicWarningType.ERROR_MESSAGE */);
props.maxValue = undefined;
}
else if (typeof props.maxValue !== "number" || !Number.isFinite(props.maxValue)) {
this.characteristicWarning(`Characteristic Property 'maxValue' must be a finite number, received "${props.maxValue}" (${typeof props.maxValue})`, "error-message" /* CharacteristicWarningType.ERROR_MESSAGE */);
props.maxValue = undefined;
}
else {
if (props.maxValue > (0, request_util_1.numericUpperBound)(this.props.format)) {
this.characteristicWarning("Characteristic Property 'maxValue' was set to " + props.maxValue + ", but for numeric format " +
this.props.format + " maximum possible is " + (0, request_util_1.numericUpperBound)(this.props.format), "error-message" /* CharacteristicWarningType.ERROR_MESSAGE */);
props.maxValue = (0, request_util_1.numericUpperBound)(this.props.format);
}
else if (props.maxValue < (0, request_util_1.numericLowerBound)(this.props.format)) {
this.characteristicWarning("Characteristic Property 'maxValue' was set to " + props.maxValue + ", but for numeric format " +
this.props.format + " minimum possible is " + (0, request_util_1.numericLowerBound)(this.props.format), "error-message" /* CharacteristicWarningType.ERROR_MESSAGE */);
props.maxValue = (0, request_util_1.numericUpperBound)(this.props.format);
}
}
this.props.maxValue = props.maxValue;
}
if (props.minStep !== undefined) {
if (props.minStep === null) {
this.props.minStep = undefined;
}
else if (!(0, request_util_1.isNumericFormat)(this.props.format)) {
this.characteristicWarning("Characteristic Property `minStep` can only be set for characteristics with numeric format, but not for " + this.props.format, "error-message" /* CharacteristicWarningType.ERROR_MESSAGE */);
}
else {
if (props.minStep < 1 && (0, request_util_1.isIntegerNumericFormat)(this.props.format)) {
this.characteristicWarning("Characteristic Property `minStep` was set to a value lower than 1, " +
"this will have no effect on format `" + this.props.format);
}
this.props.minStep = props.minStep;
}
}
if (props.maxLen !== undefined) {
if (props.maxLen === null) {
this.props.maxLen = undefined;
}
else if (this.props.format !== "string" /* Formats.STRING */) {
this.characteristicWarning("Characteristic Property `maxLen` can only be set for characteristics with format `STRING`, but not for " + this.props.format, "error-message" /* CharacteristicWarningType.ERROR_MESSAGE */);
}
else {
if (props.maxLen > 256) {
this.characteristicWarning("Characteristic Property string `maxLen` cannot be bigger than 256");
props.maxLen = 256;
}
this.props.maxLen = props.maxLen;
}
}
if (props.maxDataLen !== undefined) {
if (props.maxDataLen === null) {
this.props.maxDataLen = undefined;
}
else if (this.props.format !== "data" /* Formats.DATA */) {
this.characteristicWarning("Characteristic Property `maxDataLen` can only be set for characteristics with format `DATA`, but not for " + this.props.format, "error-message" /* CharacteristicWarningType.ERROR_MESSAGE */);
}
else {
this.props.maxDataLen = props.maxDataLen;
}
}
if (props.validValues !== undefined) {
if (props.validValues === null) {
this.props.validValues = undefined;
}
else if (!(0, request_util_1.isNumericFormat)(this.props.format)) {
this.characteristicWarning("Characteristic Property `validValues` was supplied for non numeric format " + this.props.format);
}
else {
(0, assert_1.default)(props.validValues.length, "characteristic prop validValues cannot be empty array");
this.props.validValues = props.validValues;
}
}
if (props.validValueRanges !== undefined) {
if (props.validValueRanges === null) {
this.props.validValueRanges = undefined;
}
else if (!(0, request_util_1.isNumericFormat)(this.props.format)) {
this.characteristicWarning("Characteristic Property `validValueRanges` was supplied for non numeric format " + this.props.format);
}
else {
(0, assert_1.default)(props.validValueRanges.length === 2, "characteristic prop validValueRanges must have a length of 2");
this.props.validValueRanges = props.validValueRanges;
}
}
if (props.adminOnlyAccess !== undefined) {
this.props.adminOnlyAccess = props.adminOnlyAccess != null ? props.adminOnlyAccess : undefined;
}
if (this.props.minValue != null && this.props.maxValue != null) { // the eqeq instead of eqeqeq is important here
if (this.props.minValue > this.props.maxValue) { // see https://github.com/homebridge/HAP-NodeJS/issues/690
this.props.minValue = undefined;
this.props.maxValue = undefined;
throw new Error("Error setting CharacteristicsProps for '" + this.displayName + "': 'minValue' cannot be greater or equal the 'maxValue'!");
}
}
if (((0, request_util_1.isNumericFormat)(this.props.format) || this.props.format === "string" /* Formats.STRING */)
&& this.value != null
&& !formatDidChange
&& this.statusCode === 0 /* HAPStatus.SUCCESS */
&& this.UUID !== Characteristic.ProgrammableSwitchEvent.UUID) {
// explaining the if statement above:
// - We only do a check for numeric and string formats as they are the only ones affected by characteristic property restrictions.
// - There must be a value to begin with. Otherwise, it should just stay not having a value at all (anything else is guess work).
// - If the format is changed through `setProps` we rely on the user to supply a valid value after the `setProps` call!
// - If the characteristic is marked as erroneous the value is not considered valid anyway, and we must not remove the `statusCode`.
// - Special case for `ProgrammableSwitchEvent` where every change in value is considered an event which would result in ghost button presses
// validateUserInput when called from setProps is intended to clamp value withing allowed range. It is why warnings should not be displayed.
const correctedValue = this.validateUserInput(this.value, "debug-message" /* CharacteristicWarningType.DEBUG_MESSAGE */);
if (correctedValue !== this.value) {
// we don't want to emit a CHANGE event if the value didn't change at all!
this.updateValue(correctedValue);
}
}
return this;
}
/**
* This method can be used to gain an Iterator to loop over all valid values defined for this characteristic.
*
* The range of valid values can be defined using three different ways via the {@link CharacteristicProps} object
* (set via the {@link setProps} method):
* * First method is to specifically list every valid value inside {@link CharacteristicProps.validValues}
* * Second you can specify a range via {@link CharacteristicProps.minValue} and {@link CharacteristicProps.maxValue} (with optionally defining
* {@link CharacteristicProps.minStep})
* * And lastly you can specify a range via {@link CharacteristicProps.validValueRanges}
* * Implicitly a valid value range is predefined for characteristics with Format {@link Formats.UINT8}, {@link Formats.UINT16},
* {@link Formats.UINT32} and {@link Formats.UINT64}: starting by zero to their respective maximum number
*
* The method will automatically detect which type of valid values definition is used and provide
* the correct Iterator for that case.
*
* Note: This method is (obviously) only valid for numeric characteristics.
*
* @example
* ```ts
* // use the iterator to loop over every valid value...
* for (const value of characteristic.validValuesIterator()) {
* // Insert logic to run for every
* }
*
* // ... or collect them in an array for storage or manipulation
* const validValues = Array.from(characteristic.validValuesIterator());
* ```
*/
validValuesIterator() {
return new ValidValuesIterable(this.props);
}
// noinspection JSUnusedGlobalSymbols
/**
* This method can be used to set up additional authorization for a characteristic.
* For one, it adds the {@link Perms.ADDITIONAL_AUTHORIZATION} permission to the characteristic
* (if it wasn't already) to signal support for additional authorization to HomeKit.
* Additionally, an {@link AdditionalAuthorizationHandler} is set up which is called
* before a write request is performed.
*
* Additional Authorization Data can be added to SET request via a custom iOS App.
* Before hap-nodejs executes a write request it will call the {@link AdditionalAuthorizationHandler}
* with 'authData' supplied in the write request. The 'authData' is a base64 encoded string
* (or undefined if no authData was supplied).
* The {@link AdditionalAuthorizationHandler} must then return true or false to indicate if the write request
* is authorized and should be accepted.
*
* @param handler - Handler called to check additional authorization data.
*/
setupAdditionalAuthorization(handler) {
if (!this.props.perms.includes("aa" /* Perms.ADDITIONAL_AUTHORIZATION */)) {
this.props.perms.push("aa" /* Perms.ADDITIONAL_AUTHORIZATION */);
}
this.additionalAuthorizationHandler = handler;
}
setValue(value, callback, context) {
if (value instanceof Error) {
this.statusCode = value instanceof hapStatusError_1.HapStatusError ? value.hapStatus : extractHAPStatusFromError(value);
if (callback) {
callback();
}
return this;
}
if (callback && !context && typeof callback !== "function") {
context = callback;
callback = undefined;
}
try {
value = this.validateUserInput(value);
}
catch (error) {
this.characteristicWarning(error?.message + "", "error-message" /* CharacteristicWarningType.ERROR_MESSAGE */, error?.stack);
if (callback) {
callback(error);
}
return this;
}
this.handleSetRequest(value, undefined, context).then(value => {
if (callback) {
if (value) { // possible write response
callback(null, value);
}
else {
callback(null);
}
}
}, reason => {
if (callback) {
callback(reason);
}
});
return this;
}
updateValue(value, callback, context) {
if (value instanceof Error) {
this.statusCode = value instanceof hapStatusError_1.HapStatusError ? value.hapStatus : extractHAPStatusFromError(value);
if (callback) {
callback();
}
return this;
}
if (callback && !context && typeof callback !== "function") {
context = callback;
callback = undefined;
}
try {
value = this.validateUserInput(value);
}
catch (error) {
this.characteristicWarning(error?.message + "", "error-message" /* CharacteristicWarningType.ERROR_MESSAGE */, error?.stack);
if (callback) {
callback();
}
return this;
}
this.statusCode = 0 /* HAPStatus.SUCCESS */;
const oldValue = this.value;
this.value = value;
if (callback) {
callback();
}
this.emit("change" /* CharacteristicEventTypes.CHANGE */, { originator: undefined, oldValue: oldValue, newValue: value, reason: "update" /* ChangeReason.UPDATE */, context: context });
return this; // for chaining
}
/**
* This method acts similarly to {@link updateValue} by setting the current value of the characteristic