HAP-python
HAP-python copied to clipboard
Adaptive lighting support
(For those out of the loop: adaptive lighting is a new HomeKit feature pretty much similar to what Circadian Lighting offers, or so it sounds) As far as I understood, the new Adaptive Lighting feature in HomeKit on iOS 14 is something that needs to be supported in the bridge. Hue has announced support for it later this year, IKEA hasn’t officially pronounced themselves about it. Doing it from HAP-python would bring support for all the supported lights at the moment.
If I understand the stack correctly this should be possible. Also, for anyone who can offer me some pointers, I’d like to look into the pieces of code that would enable something like this.
Btw, I haven’t found any documentation about Adaptive Lighting so I’m only working from assumptions on how it all works.
I'm happy to help, looks like it's already implemented in HAP-NodeJS: https://github.com/homebridge/HAP-NodeJS/blob/experimental/src/lib/controller/AdaptiveLightingController.ts
Great. So this should work on any light, even if the manufacturer does not offer it? How do I activate it?
How to get this work started? I think the first step is to update the characteristics.json to include the new characteristics from iOS14. Is that file generated or manually edited?
Looks like Homebridge 1.3 is coming with Apple Adaptive Lighting support (https://github.com/homebridge/homebridge/issues/2765). Any update on this?
Hello @ikalchev Can you please elaborate how to update the characteristics.json to include the new ones from iOS14? Is this a manual task?
Wondering if people are still interested in getting this implemented. The HAP-NodeJS Adaptive Lighting Controller is now located at https://github.com/homebridge/HAP-NodeJS/blob/master/src/lib/controller/AdaptiveLightingController.ts
This is slowly becoming standard in homebridge plugins. I'd rather not run my lights through homebridge to get AL support though
Are any news about this feature?
There isn't anyone working on this. It's not likely to happen any time soon.
Maybe we could set a bounty for an implementation?
To implement this, I would need help by the maintainers for some basic questions. See my posts above. Since I never got an answer, I couldn't proceed further, regardless of a bounty.
@ikalchev mind chiming in?
Jumping in as I'm migrating my Hue lights over to Zigbee2MQTT and hitting this limitation.
It looks like the last modifications to characteristics.json
were done by @maximkulkin & @adrum for TV support. Any chance you guys could help point us in the right direction?
There is nothing preventing manual edits to this file. Homebridge has already figured this out. I'm sure the community would be happy to share.
@crazyfx1, what's missing from characteristics.json
? Found this doc -- https://developers.homebridge.io/HAP-NodeJS/classes/adaptivelightingcontroller.html
Seems to suggest that the characteristics needed are ColorTemperature
, and Brightness
. Optionally Hue
and Saturation
. All of these seem to already exist.
For example SupportedCharacteristicValueTransitionConfiguration
is missing, which shows what type of adaptive lighting is supported.
Since the characteristics of Homebridge are generated, I was hoping that there is a generator here aswell.
Bumping for progress?
@crazyfx1 Looks like there is a generator of sorts. I found this python script which makes reference to characteristics.json
as an output file.
https://github.com/ikalchev/HAP-python/blob/6c2b95cc6457ea9c8dbee1759455a6954bb14092/scripts/gen_hap_types.py
Which looks like its dependent on Apple's HomeKit Accessory Simulator. Not sure if that's the entirety of what needs to be done here but probably a fair starting point as characteristics.json
hasn't been updated in about 2 years now.
I tried the generator last year and it didn't output the correct characteristics.json.
I just had a run of trying it myself. It looks like several entries have been removed based on the latest Homekit Accessory Simulator;
{
"AccessoryFlags": {
"Format": "uint32",
"Permissions": [
"pr",
"ev"
],
"UUID": "000000A6-0000-1000-8000-0026BB765291",
"ValidBits": {
"0": "Requires Additional Setup"
}
},
"Active": {
"Format": "uint8",
"Permissions": [
"pr",
"pw",
"ev"
],
"UUID": "000000B0-0000-1000-8000-0026BB765291",
"ValidValues": {
"Active": 1,
"Inactive": 0
}
},
"AdministratorOnlyAccess": {
"Format": "bool",
"Permissions": [
"pr",
"pw",
"ev"
],
"UUID": "00000001-0000-1000-8000-0026BB765291"
},
"AirParticulateDensity": {
"Format": "float",
"Permissions": [
"pr",
"ev"
],
"UUID": "00000064-0000-1000-8000-0026BB765291",
"maxValue": 1000,
"minStep": 1,
"minValue": 0
},
"AirParticulateSize": {
"Format": "uint8",
"Permissions": [
"pr",
"ev"
],
"UUID": "00000065-0000-1000-8000-0026BB765291",
"ValidValues": {
"10\u03bcm": 1,
"2.5\u03bcm": 0
}
},
"AirQuality": {
"Format": "uint8",
"Permissions": [
"pr",
"ev"
],
"UUID": "00000095-0000-1000-8000-0026BB765291",
"ValidValues": {
"Excellent": 1,
"Fair": 3,
"Good": 2,
"Inferior": 4,
"Poor": 5,
"Unknown": 0
}
},
"AudioFeedback": {
"Format": "bool",
"Permissions": [
"pr",
"pw",
"ev"
],
"UUID": "00000005-0000-1000-8000-0026BB765291"
},
"BatteryLevel": {
"Format": "uint8",
"Permissions": [
"pr",
"ev"
],
"UUID": "00000068-0000-1000-8000-0026BB765291",
"maxValue": 100,
"minStep": 1,
"minValue": 0,
"unit": "percentage"
},
"Brightness": {
"Format": "int",
"Permissions": [
"pr",
"pw",
"ev"
],
"UUID": "00000008-0000-1000-8000-0026BB765291",
"maxValue": 100,
"minStep": 1,
"minValue": 0,
"unit": "percentage"
},
"CarbonDioxideDetected": {
"Format": "uint8",
"Permissions": [
"pr",
"ev"
],
"UUID": "00000092-0000-1000-8000-0026BB765291",
"ValidValues": {
"CO2LevelsAbnormal": 1,
"CO2LevelsNormal": 0
}
},
"CarbonDioxideLevel": {
"Format": "float",
"Permissions": [
"pr",
"ev"
],
"UUID": "00000093-0000-1000-8000-0026BB765291",
"maxValue": 100000,
"minValue": 0
},
"CarbonDioxidePeakLevel": {
"Format": "float",
"Permissions": [
"pr",
"ev"
],
"UUID": "00000094-0000-1000-8000-0026BB765291",
"maxValue": 100000,
"minValue": 0
},
"CarbonMonoxideDetected": {
"Format": "uint8",
"Permissions": [
"pr",
"ev"
],
"UUID": "00000069-0000-1000-8000-0026BB765291",
"ValidValues": {
"COLevelsAbnormal": 1,
"COLevelsNormal": 0
}
},
"CarbonMonoxideLevel": {
"Format": "float",
"Permissions": [
"pr",
"ev"
],
"UUID": "00000090-0000-1000-8000-0026BB765291",
"maxValue": 100,
"minValue": 0
},
"CarbonMonoxidePeakLevel": {
"Format": "float",
"Permissions": [
"pr",
"ev"
],
"UUID": "00000091-0000-1000-8000-0026BB765291",
"maxValue": 100,
"minValue": 0
},
"ChargingState": {
"Format": "uint8",
"Permissions": [
"pr",
"ev"
],
"UUID": "0000008F-0000-1000-8000-0026BB765291",
"ValidValues": {
"Charging": 1,
"NotChargeable": 2,
"NotCharging": 0
}
},
"ColorTemperature": {
"Format": "uint32",
"Permissions": [
"pr",
"pw",
"ev"
],
"UUID": "000000CE-0000-1000-8000-0026BB765291",
"maxValue": 500,
"minStep": 1,
"minValue": 140
},
"ContactSensorState": {
"Format": "uint8",
"Permissions": [
"pr",
"ev"
],
"UUID": "0000006A-0000-1000-8000-0026BB765291",
"ValidValues": {
"ContactDetected": 0,
"ContactNotDetected": 1
}
},
"CoolingThresholdTemperature": {
"Format": "float",
"Permissions": [
"pr",
"pw",
"ev"
],
"UUID": "0000000D-0000-1000-8000-0026BB765291",
"maxValue": 35,
"minStep": 0.1,
"minValue": 10,
"unit": "celsius"
},
"CurrentAirPurifierState": {
"Format": "uint8",
"Permissions": [
"pr",
"ev"
],
"UUID": "000000A9-0000-1000-8000-0026BB765291",
"ValidValues": {
"Idle": 1,
"Inactive": 0,
"PurifyingAir": 2
}
},
"CurrentAmbientLightLevel": {
"Format": "float",
"Permissions": [
"pr",
"ev"
],
"UUID": "0000006B-0000-1000-8000-0026BB765291",
"maxValue": 100000,
"minValue": 0.0001,
"unit": "lux"
},
"CurrentDoorState": {
"Format": "uint8",
"Permissions": [
"pr",
"ev"
],
"UUID": "0000000E-0000-1000-8000-0026BB765291",
"ValidValues": {
"Closed": 1,
"Closing": 3,
"Open": 0,
"Opening": 2,
"Stopped": 4
}
},
"CurrentFanState": {
"Format": "uint8",
"Permissions": [
"pr",
"ev"
],
"UUID": "000000AF-0000-1000-8000-0026BB765291",
"ValidValues": {
"BlowingAir": 2,
"Idle": 1,
"Inactive": 0
}
},
"CurrentHeaterCoolerState": {
"Format": "uint8",
"Permissions": [
"pr",
"ev"
],
"UUID": "000000B1-0000-1000-8000-0026BB765291",
"ValidValues": {
"Cooling": 3,
"Heating": 2,
"Idle": 1,
"Inactive": 0
}
},
"CurrentHeatingCoolingState": {
"Format": "uint8",
"Permissions": [
"pr",
"ev"
],
"UUID": "0000000F-0000-1000-8000-0026BB765291",
"ValidValues": {
"Cool": 2,
"Heat": 1,
"Off": 0
}
},
"CurrentHorizontalTiltAngle": {
"Format": "int",
"Permissions": [
"pr",
"ev"
],
"UUID": "0000006C-0000-1000-8000-0026BB765291",
"maxValue": 90,
"minStep": 1,
"minValue": -90,
"unit": "arcdegrees"
},
"CurrentHumidifierDehumidifierState": {
"Format": "uint8",
"Permissions": [
"pr",
"ev"
],
"UUID": "000000B3-0000-1000-8000-0026BB765291",
"ValidValues": {
"Dehumidifying": 3,
"Humidifying": 2,
"Idle": 1,
"Inactive": 0
}
},
"CurrentPosition": {
"Format": "uint8",
"Permissions": [
"pr",
"ev"
],
"UUID": "0000006D-0000-1000-8000-0026BB765291",
"maxValue": 100,
"minStep": 1,
"minValue": 0,
"unit": "percentage"
},
"CurrentRelativeHumidity": {
"Format": "float",
"Permissions": [
"pr",
"ev"
],
"UUID": "00000010-0000-1000-8000-0026BB765291",
"maxValue": 100,
"minStep": 1,
"minValue": 0,
"unit": "percentage"
},
"CurrentSlatState": {
"Format": "uint8",
"Permissions": [
"pr",
"ev"
],
"UUID": "000000AA-0000-1000-8000-0026BB765291",
"ValidValues": {
"Fixed": 0,
"Jammed": 1,
"Swinging": 2
}
},
"CurrentTemperature": {
"Format": "float",
"Permissions": [
"pr",
"ev"
],
"UUID": "00000011-0000-1000-8000-0026BB765291",
"maxValue": 100,
"minStep": 0.1,
"minValue": 0,
"unit": "celsius"
},
"CurrentTiltAngle": {
"Format": "int",
"Permissions": [
"pr",
"ev"
],
"UUID": "000000C1-0000-1000-8000-0026BB765291",
"maxValue": 90,
"minStep": 1,
"minValue": -90,
"unit": "arcdegrees"
},
"CurrentVerticalTiltAngle": {
"Format": "int",
"Permissions": [
"pr",
"ev"
],
"UUID": "0000006E-0000-1000-8000-0026BB765291",
"maxValue": 90,
"minStep": 1,
"minValue": -90,
"unit": "arcdegrees"
},
"DigitalZoom": {
"Format": "float",
"Permissions": [
"pr",
"pw",
"ev"
],
"UUID": "0000011D-0000-1000-8000-0026BB765291"
},
"FilterChangeIndication": {
"Format": "uint8",
"Permissions": [
"pr",
"ev"
],
"UUID": "000000AC-0000-1000-8000-0026BB765291",
"ValidValues": {
"ChangeFilter": 1,
"FilterOK": 0
}
},
"FilterLifeLevel": {
"Format": "float",
"Permissions": [
"pr",
"ev"
],
"UUID": "000000AB-0000-1000-8000-0026BB765291",
"maxValue": 100,
"minValue": 0,
"stepValue": 1
},
"FirmwareRevision": {
"Format": "string",
"Permissions": [
"pr"
],
"UUID": "00000052-0000-1000-8000-0026BB765291"
},
"HardwareRevision": {
"Format": "string",
"Permissions": [
"pr"
],
"UUID": "00000053-0000-1000-8000-0026BB765291"
},
"HeatingThresholdTemperature": {
"Format": "float",
"Permissions": [
"pr",
"pw",
"ev"
],
"UUID": "00000012-0000-1000-8000-0026BB765291",
"maxValue": 25,
"minStep": 0.1,
"minValue": 0,
"unit": "celsius"
},
"HoldPosition": {
"Format": "bool",
"Permissions": [
"pw"
],
"UUID": "0000006F-0000-1000-8000-0026BB765291"
},
"Hue": {
"Format": "float",
"Permissions": [
"pr",
"pw",
"ev"
],
"UUID": "00000013-0000-1000-8000-0026BB765291",
"maxValue": 360,
"minStep": 1,
"minValue": 0,
"unit": "arcdegrees"
},
"Identify": {
"Format": "bool",
"Permissions": [
"pw"
],
"UUID": "00000014-0000-1000-8000-0026BB765291"
},
"ImageMirroring": {
"Format": "bool",
"Permissions": [
"pr",
"pw",
"ev"
],
"UUID": "0000011F-0000-1000-8000-0026BB765291"
},
"ImageRotation": {
"Format": "float",
"Permissions": [
"pr",
"pw",
"ev"
],
"UUID": "0000011E-0000-1000-8000-0026BB765291",
"maxValue": 270,
"minStep": 90,
"minValue": 0,
"unit": "arcdegrees"
},
"InUse": {
"Format": "uint8",
"Permissions": [
"pr",
"ev"
],
"UUID": "000000D2-0000-1000-8000-0026BB765291",
"ValidValues": {
"Inuse": 1,
"Notinuse": 0
}
},
"IsConfigured": {
"Format": "uint8",
"Permissions": [
"pr",
"pw",
"ev"
],
"UUID": "000000D6-0000-1000-8000-0026BB765291",
"ValidValues": {
"Configured": 1,
"NotConfigured": 0
}
},
"LeakDetected": {
"Format": "uint8",
"Permissions": [
"pr",
"ev"
],
"UUID": "00000070-0000-1000-8000-0026BB765291",
"ValidValues": {
"LeakDetected": 1,
"LeakNotDetected": 0
}
},
"LockControlPoint": {
"Format": "tlv8",
"Permissions": [
"pw"
],
"UUID": "00000019-0000-1000-8000-0026BB765291"
},
"LockCurrentState": {
"Format": "uint8",
"Permissions": [
"pr",
"ev"
],
"UUID": "0000001D-0000-1000-8000-0026BB765291",
"ValidValues": {
"Jammed": 2,
"Secured": 1,
"Unknown": 3,
"Unsecured": 0
}
},
"LockLastKnownAction": {
"Format": "uint8",
"Permissions": [
"pr",
"ev"
],
"UUID": "0000001C-0000-1000-8000-0026BB765291",
"ValidValues": {
"SecuredPhysically,Exterior": 2,
"SecuredPhysically,Interior": 0,
"SecuredRemotely": 6,
"SecuredbyAutoSecureTimeout": 8,
"SecuredbyKeypad": 4,
"UnsecuredPhysically,Exterior": 3,
"UnsecuredPhysically,Interior": 1,
"UnsecuredRemotely": 7,
"UnsecuredbyKeypad": 5
}
},
"LockManagementAutoSecurityTimeout": {
"Format": "uint32",
"Permissions": [
"pr",
"pw",
"ev"
],
"UUID": "0000001A-0000-1000-8000-0026BB765291",
"unit": "seconds"
},
"LockPhysicalControls": {
"Format": "uint8",
"Permissions": [
"pr",
"pw",
"ev"
],
"UUID": "000000A7-0000-1000-8000-0026BB765291",
"ValidValues": {
"ControlLockDisabled": 0,
"ControlLockEnabled": 1
}
},
"LockTargetState": {
"Format": "uint8",
"Permissions": [
"pr",
"pw",
"ev"
],
"UUID": "0000001E-0000-1000-8000-0026BB765291",
"ValidValues": {
"Secured": 1,
"Unsecured": 0
}
},
"Logs": {
"Format": "tlv8",
"Permissions": [
"pr",
"ev"
],
"UUID": "0000001F-0000-1000-8000-0026BB765291"
},
"Manufacturer": {
"Format": "string",
"Permissions": [
"pr"
],
"UUID": "00000020-0000-1000-8000-0026BB765291"
},
"Model": {
"Format": "string",
"Permissions": [
"pr"
],
"UUID": "00000021-0000-1000-8000-0026BB765291"
},
"MotionDetected": {
"Format": "bool",
"Permissions": [
"pr",
"ev"
],
"UUID": "00000022-0000-1000-8000-0026BB765291"
},
"Mute": {
"Format": "bool",
"Permissions": [
"pr",
"pw",
"ev"
],
"UUID": "0000011A-0000-1000-8000-0026BB765291"
},
"Name": {
"Format": "string",
"Permissions": [
"pr"
],
"UUID": "00000023-0000-1000-8000-0026BB765291"
},
"NightVision": {
"Format": "bool",
"Permissions": [
"pr",
"pw",
"ev"
],
"UUID": "0000011B-0000-1000-8000-0026BB765291"
},
"NitrogenDioxideDensity": {
"Format": "float",
"Permissions": [
"pr",
"ev"
],
"UUID": "000000C4-0000-1000-8000-0026BB765291",
"maxValue": 1000,
"minStep": 1,
"minValue": 0
},
"ObstructionDetected": {
"Format": "bool",
"Permissions": [
"pr",
"ev"
],
"UUID": "00000024-0000-1000-8000-0026BB765291"
},
"OccupancyDetected": {
"Format": "uint8",
"Permissions": [
"pr",
"ev"
],
"UUID": "00000071-0000-1000-8000-0026BB765291",
"ValidValues": {
"OccupancyDetected": 1,
"OccupancyNotDetected": 0
}
},
"On": {
"Format": "bool",
"Permissions": [
"pr",
"pw",
"ev"
],
"UUID": "00000025-0000-1000-8000-0026BB765291"
},
"OpticalZoom": {
"Format": "float",
"Permissions": [
"pr",
"pw",
"ev"
],
"UUID": "0000011C-0000-1000-8000-0026BB765291"
},
"OutletInUse": {
"Format": "bool",
"Permissions": [
"pr",
"ev"
],
"UUID": "00000026-0000-1000-8000-0026BB765291"
},
"OzoneDensity": {
"Format": "float",
"Permissions": [
"pr",
"ev"
],
"UUID": "000000C3-0000-1000-8000-0026BB765291",
"maxValue": 1000,
"minStep": 1,
"minValue": 0
},
"PM10Density": {
"Format": "float",
"Permissions": [
"pr",
"ev"
],
"UUID": "000000C7-0000-1000-8000-0026BB765291",
"maxValue": 1000,
"minStep": 1,
"minValue": 0
},
"PM2.5Density": {
"Format": "float",
"Permissions": [
"pr",
"ev"
],
"UUID": "000000C6-0000-1000-8000-0026BB765291",
"maxValue": 1000,
"minStep": 1,
"minValue": 0
},
"PairSetup": {
"Format": "tlv8",
"Permissions": [
"pr",
"pw"
],
"UUID": "0000004C-0000-1000-8000-0026BB765291"
},
"PairVerify": {
"Format": "tlv8",
"Permissions": [
"pr",
"pw"
],
"UUID": "0000004E-0000-1000-8000-0026BB765291"
},
"PairingFeatures": {
"Format": "uint8",
"Permissions": [
"pr"
],
"UUID": "0000004F-0000-1000-8000-0026BB765291"
},
"PairingPairings": {
"Format": "tlv8",
"Permissions": [
"pr",
"pw"
],
"UUID": "00000050-0000-1000-8000-0026BB765291"
},
"PositionState": {
"Format": "uint8",
"Permissions": [
"pr",
"ev"
],
"UUID": "00000072-0000-1000-8000-0026BB765291",
"ValidValues": {
"Decreasing": 0,
"Increasing": 1,
"Stopped": 2
}
},
"ProgramMode": {
"Format": "uint8",
"Permissions": [
"pr",
"ev"
],
"UUID": "000000D1-0000-1000-8000-0026BB765291",
"ValidValues": {
"Noprogramscheduled": 0,
"Programscheduled": 1,
"Programscheduled(ManualMode)": 2
}
},
"ProgrammableSwitchEvent": {
"Format": "uint8",
"Permissions": [
"pr",
"ev"
],
"UUID": "00000073-0000-1000-8000-0026BB765291",
"ValidValues": {
"DoublePress": 1,
"LongPress": 2,
"SinglePress": 0
}
},
"RelativeHumidityDehumidifierThreshold": {
"Format": "float",
"Permissions": [
"pr",
"pw",
"ev"
],
"UUID": "000000C9-0000-1000-8000-0026BB765291",
"maxValue": 100,
"minStep": 1,
"minValue": 0,
"unit": "percentage"
},
"RelativeHumidityHumidifierThreshold": {
"Format": "float",
"Permissions": [
"pr",
"pw",
"ev"
],
"UUID": "000000CA-0000-1000-8000-0026BB765291",
"maxValue": 100,
"minStep": 1,
"minValue": 0,
"unit": "percentage"
},
"RemainingDuration": {
"Format": "uint32",
"Permissions": [
"pr",
"ev"
],
"UUID": "000000D4-0000-1000-8000-0026BB765291",
"maxValue": 3600,
"minStep": 1,
"minValue": 0
},
"ResetFilterIndication": {
"Format": "uint8",
"Permissions": [
"pw"
],
"UUID": "000000AD-0000-1000-8000-0026BB765291",
"maxValue": 1,
"minStep": 1,
"minValue": 1
},
"RotationDirection": {
"Format": "int",
"Permissions": [
"pr",
"pw",
"ev"
],
"UUID": "00000028-0000-1000-8000-0026BB765291",
"ValidValues": {
"Clockwise": 0,
"Counter-clockwise": 1
}
},
"RotationSpeed": {
"Format": "float",
"Permissions": [
"pr",
"pw",
"ev"
],
"UUID": "00000029-0000-1000-8000-0026BB765291",
"maxValue": 100,
"minStep": 1,
"minValue": 0,
"unit": "percentage"
},
"Saturation": {
"Format": "float",
"Permissions": [
"pr",
"pw",
"ev"
],
"UUID": "0000002F-0000-1000-8000-0026BB765291",
"maxValue": 100,
"minStep": 1,
"minValue": 0,
"unit": "percentage"
},
"SecuritySystemAlarmType": {
"Format": "uint8",
"Permissions": [
"pr",
"ev"
],
"UUID": "0000008E-0000-1000-8000-0026BB765291",
"maxValue": 1,
"minStep": 1,
"minValue": 0
},
"SecuritySystemCurrentState": {
"Format": "uint8",
"Permissions": [
"pr",
"ev"
],
"UUID": "00000066-0000-1000-8000-0026BB765291",
"ValidValues": {
"AlarmTriggered": 4,
"AwayArm": 1,
"Disarmed": 3,
"NightArm": 2,
"StayArm": 0
}
},
"SecuritySystemTargetState": {
"Format": "uint8",
"Permissions": [
"pr",
"pw",
"ev"
],
"UUID": "00000067-0000-1000-8000-0026BB765291",
"ValidValues": {
"AwayArm": 1,
"Disarm": 3,
"NightArm": 2,
"StayArm": 0
}
},
"SelectedRTPStreamConfiguration": {
"Format": "tlv8",
"Permissions": [
"pr",
"pw"
],
"UUID": "00000117-0000-1000-8000-0026BB765291"
},
"SerialNumber": {
"Format": "string",
"MaximumLength": 64,
"Permissions": [
"pr"
],
"UUID": "00000030-0000-1000-8000-0026BB765291"
},
"ServiceLabelIndex": {
"Format": "uint8",
"Permissions": [
"pr"
],
"UUID": "000000CB-0000-1000-8000-0026BB765291",
"maxValue": 255,
"minStep": 1,
"minValue": 1
},
"ServiceLabelNamespace": {
"Format": "uint8",
"Permissions": [
"pr"
],
"UUID": "000000CD-0000-1000-8000-0026BB765291",
"ValidValues": {
"ArabicNumerals": 1,
"Dots": 0
}
},
"SetDuration": {
"Format": "uint32",
"Permissions": [
"pr",
"pw",
"ev"
],
"UUID": "000000D3-0000-1000-8000-0026BB765291",
"maxValue": 3600,
"minStep": 1,
"minValue": 0
},
"SetupEndpoints": {
"Format": "tlv8",
"Permissions": [
"pr",
"pw"
],
"UUID": "00000118-0000-1000-8000-0026BB765291"
},
"SlatType": {
"Format": "uint8",
"Permissions": [
"pr"
],
"UUID": "000000C0-0000-1000-8000-0026BB765291",
"ValidValues": {
"Horizontal": 0,
"Vertical": 1
}
},
"SmokeDetected": {
"Format": "uint8",
"Permissions": [
"pr",
"ev"
],
"UUID": "00000076-0000-1000-8000-0026BB765291",
"ValidValues": {
"SmokeDetected": 1,
"SmokeNotDetected": 0
}
},
"StatusActive": {
"Format": "bool",
"Permissions": [
"pr",
"ev"
],
"UUID": "00000075-0000-1000-8000-0026BB765291"
},
"StatusFault": {
"Format": "uint8",
"Permissions": [
"pr",
"ev"
],
"UUID": "00000077-0000-1000-8000-0026BB765291",
"ValidValues": {
"GeneralFault": 1,
"NoFault": 0
}
},
"StatusJammed": {
"Format": "uint8",
"Permissions": [
"pr",
"ev"
],
"UUID": "00000078-0000-1000-8000-0026BB765291",
"ValidValues": {
"Jammed": 1,
"NotJammed": 0
}
},
"StatusLowBattery": {
"Format": "uint8",
"Permissions": [
"pr",
"ev"
],
"UUID": "00000079-0000-1000-8000-0026BB765291",
"ValidValues": {
"BatteryLevelLow": 1,
"BatteryLevelNormal": 0
}
},
"StatusTampered": {
"Format": "uint8",
"Permissions": [
"pr",
"ev"
],
"UUID": "0000007A-0000-1000-8000-0026BB765291",
"ValidValues": {
"NotTampered": 0,
"Tampered": 1
}
},
"StreamingStatus": {
"Format": "tlv8",
"Permissions": [
"pr",
"ev"
],
"UUID": "00000120-0000-1000-8000-0026BB765291"
},
"SulphurDioxideDensity": {
"Format": "float",
"Permissions": [
"pr",
"ev"
],
"UUID": "000000C5-0000-1000-8000-0026BB765291",
"maxValue": 1000,
"minStep": 1,
"minValue": 0
},
"SupportedAudioStreamConfiguration": {
"Format": "tlv8",
"Permissions": [
"pr"
],
"UUID": "00000115-0000-1000-8000-0026BB765291"
},
"SupportedRTPConfiguration": {
"Format": "tlv8",
"Permissions": [
"pr"
],
"UUID": "00000116-0000-1000-8000-0026BB765291"
},
"SupportedVideoStreamConfiguration": {
"Format": "tlv8",
"Permissions": [
"pr"
],
"UUID": "00000114-0000-1000-8000-0026BB765291"
},
"SwingMode": {
"Format": "uint8",
"Permissions": [
"pr",
"pw",
"ev"
],
"UUID": "000000B6-0000-1000-8000-0026BB765291",
"ValidValues": {
"SwingDisabled": 0,
"SwingEnabled": 1
}
},
"TargetAirPurifierState": {
"Format": "uint8",
"Permissions": [
"pr",
"pw",
"ev"
],
"UUID": "000000A8-0000-1000-8000-0026BB765291",
"ValidValues": {
"Auto": 1,
"Manual": 0
}
},
"TargetAirQuality": {
"Format": "uint8",
"Permissions": [
"pr",
"pw",
"ev"
],
"UUID": "000000AE-0000-1000-8000-0026BB765291",
"ValidValues": {
"Excellent": 0,
"Fair": 2,
"Good": 1
}
},
"TargetDoorState": {
"Format": "uint8",
"Permissions": [
"pr",
"pw",
"ev"
],
"UUID": "00000032-0000-1000-8000-0026BB765291",
"ValidValues": {
"Closed": 1,
"Open": 0
}
},
"TargetFanState": {
"Format": "uint8",
"Permissions": [
"pr",
"pw",
"ev"
],
"UUID": "000000BF-0000-1000-8000-0026BB765291",
"ValidValues": {
"Auto": 1,
"Manual": 0
}
},
"TargetHeaterCoolerState": {
"Format": "uint8",
"Permissions": [
"pr",
"pw",
"ev"
],
"UUID": "000000B2-0000-1000-8000-0026BB765291",
"ValidValues": {
"Auto": 0,
"Cool": 2,
"Heat": 1
}
},
"TargetHeatingCoolingState": {
"Format": "uint8",
"Permissions": [
"pr",
"pw",
"ev"
],
"UUID": "00000033-0000-1000-8000-0026BB765291",
"ValidValues": {
"Auto": 3,
"Cool": 2,
"Heat": 1,
"Off": 0
}
},
"TargetHorizontalTiltAngle": {
"Format": "int",
"Permissions": [
"pr",
"pw",
"ev"
],
"UUID": "0000007B-0000-1000-8000-0026BB765291",
"maxValue": 90,
"minStep": 1,
"minValue": -90,
"unit": "arcdegrees"
},
"TargetHumidifierDehumidifierState": {
"Format": "uint8",
"Permissions": [
"pr",
"pw",
"ev"
],
"UUID": "000000B4-0000-1000-8000-0026BB765291",
"ValidValues": {
"Dehumidifier": 2,
"Humidifier": 1,
"HumidifierorDehumidifier": 0
}
},
"TargetPosition": {
"Format": "uint8",
"Permissions": [
"pr",
"pw",
"ev"
],
"UUID": "0000007C-0000-1000-8000-0026BB765291",
"maxValue": 100,
"minStep": 1,
"minValue": 0,
"unit": "percentage"
},
"TargetRelativeHumidity": {
"Format": "float",
"Permissions": [
"pr",
"pw",
"ev"
],
"UUID": "00000034-0000-1000-8000-0026BB765291",
"maxValue": 100,
"minStep": 1,
"minValue": 0,
"unit": "percentage"
},
"TargetSlatState": {
"Format": "uint8",
"Permissions": [
"pr",
"pw",
"ev"
],
"UUID": "000000BE-0000-1000-8000-0026BB765291",
"ValidValues": {
"Auto": 1,
"Manual": 0
}
},
"TargetTemperature": {
"Format": "float",
"Permissions": [
"pr",
"pw",
"ev"
],
"UUID": "00000035-0000-1000-8000-0026BB765291",
"maxValue": 38,
"minStep": 0.1,
"minValue": 10,
"unit": "celsius"
},
"TargetTiltAngle": {
"Format": "int",
"Permissions": [
"pr",
"pw",
"ev"
],
"UUID": "000000C2-0000-1000-8000-0026BB765291",
"maxValue": 90,
"minStep": 1,
"minValue": -90,
"unit": "arcdegrees"
},
"TargetVerticalTiltAngle": {
"Format": "int",
"Permissions": [
"pr",
"pw",
"ev"
],
"UUID": "0000007D-0000-1000-8000-0026BB765291",
"maxValue": 90,
"minStep": 1,
"minValue": -90,
"unit": "arcdegrees"
},
"TemperatureDisplayUnits": {
"Format": "uint8",
"Permissions": [
"pr",
"pw",
"ev"
],
"UUID": "00000036-0000-1000-8000-0026BB765291",
"ValidValues": {
"Celsius": 0,
"Fahrenheit": 1
}
},
"VOCDensity": {
"Format": "float",
"Permissions": [
"pr",
"ev"
],
"UUID": "000000C8-0000-1000-8000-0026BB765291",
"maxValue": 1000,
"minStep": 1,
"minValue": 0
},
"ValveType": {
"Format": "uint8",
"Permissions": [
"pr",
"ev"
],
"UUID": "000000D5-0000-1000-8000-0026BB765291",
"ValidValues": {
"Genericvalve": 0,
"Irrigation": 1,
"Showerhead": 2,
"Waterfaucet": 3
}
},
"Version": {
"Format": "string",
"MaximumLength": 64,
"Permissions": [
"pr",
"ev"
],
"UUID": "00000037-0000-1000-8000-0026BB765291"
},
"Volume": {
"Format": "uint8",
"Permissions": [
"pr",
"pw",
"ev"
],
"UUID": "00000119-0000-1000-8000-0026BB765291",
"maxValue": 100,
"minStep": 1,
"minValue": 0,
"unit": "percentage"
},
"WaterLevel": {
"Format": "float",
"Permissions": [
"pr",
"ev"
],
"UUID": "000000B5-0000-1000-8000-0026BB765291",
"maxValue": 100,
"minValue": 0,
"unit": "percentage"
}
}
PictureMode for example isn't in the latest simulator but is in the characteristics.json file.
There are entries in the HomeBridge version (here) that aren't from the HomeKit Accessory Simulator either. Next step I'll take is to look at how Homebridge are generating it and see if this project needs to use a different source for generating it
@ikalchev Have you got any pointers in what we need to do to enable this other than potentially updating the characteristics.json file?
Any updates with this?
@ikalchev I'm also very interested in adding this feature. Thanks!
I know I’m not going to help by commenting, but what is the issue here or how could we make it happen? Is HomeKit Accessory Simulator’s output not sufficient or are we waiting for other things to happen? This is a feature that is very important to me and maybe many others. I’ve gotten into the whole smart home ecosystem because of smart lights and to be able to automatically adjust color temperature, but current hacky integrations are not sufficient and based on what I see, Adaptive Lightning is exactly what I am looking for.
From what I can tell in the NodeJS implementation, Adaptive Lighting only requires the brightness and color temperature properties. I think that both of those are implemented at this point in time. Devices that implement Adaptive Lighting seem to implement an Adaptive Lighting controller on top of that, which would implement the functionality.
Homebridge-Hue implements a brightnessAdjustment factor for Adaptive Lightning. The brightness seems to get fed into the Adaptive Lighting controller to adjust the color temperature.
Homebridge-z2m also uses a controller. It's easiest to see by scrolling to the bottom and then back up to src/converters/lights.ts. As I get into below, it first implements the service for the light itself and then adds an adaptive lighting controller on top of it.
All of these implementations are relying on the HAP-NodeJS implementation. Based on a quick look there, it's not just a property to add to the device. It's a controller that receives information from the HomeKit hub/controller in order for it to perform adaptive lighting transitions itself.
In the code, it mentions that a new Adaptive Lighting schedule will be transmitted from the controller every 24 hours. The most important property seems to be the supported transitions so that all of the transitions can be implemented. There is also mention of an iid for Adaptive Lighting transitions themselves. The write up for how adaptive lighting works starts on line 320 of the AdaptiveLightingController.ts file (linked above with a blob to keep the line number constant). The 24-hour transition schedule cache, control, and communication would most likely be the most difficult part to implement.
The section on line 448 seems to me that it’s adding a controller to an already existing light. This seems to be confirmed in their Adaptive Lighting device example where they add a light as a service and then they add Adaptive Lighting as a controller to that service at the end of the script. This implies to me that the characteristics.json file wouldn’t be the proper starting place. It would instead require some sort of HomeKit controller built into the “device” or in this case, the HAP implementation. The implication seems to be that Apple wants to limit the number of HomeKit calls being made by the Adaptive Lighting service, so the transitions get kicked over to the device side, and only the initial 24-hour transition schedule gets handled by the hub / iDevice.
Per the HAP-NodeJS implementation on line 470, it seems that whatever controller gets added should have an id of DefaultControllerType.CHARACTERISTIC_TRANSITION + "-" + this.lightbulb.getServiceId(); So it seems that the controller gets associated to the lightbulb by adding characteristic-transition- to the front of the light's serivice ID. If HomeKit sees a characteristic-transition- controller associated with the ID, then it should at least attempt to enable adaptive lighting on that device.
From what I can tell, the structure is: Driver -> Bridge (optional) -> Accessory -> Service -> Characteristics In the HomeKit heirarchy, it seems to be laid out as Home -> Acessory -> Service -> Characteristic. Each layer has its own properties, but characteristics have value cells instead of continued nesting. It seems that controllers in HAP-NodeJS are either the accessory layer as they mention that the controller is a collection of services that make up an accessory, or it is a layer under the accessory as it mentions that a "controller can choose to return the same identifier for all controllers of the same type. This will result in the user only being able to add ONE instance of an Controller to an accessory"
Based on the documentation, it could be implying that a controller just sets up a bunch of services at the same time. If this is the case, then it would act like a service itself once initialized. If anyone has more insight, please let us know.
I also have a hue bridge that I could read a configuration from. Is there a way to output device information from a homekit device?
Any update on this? While adding some third-party lights to Home Assistant (to homekit-ify them) I was surprised to see this functionality absent.
Hello,
Based on the documentation, it could be implying that a controller just sets up a bunch of services at the same time. If this is the case, then it would act like a service itself once initialized. If anyone has more insight, please let us know.
According to my understanding of the HAP-NodeJS architecture "a controller" is indeed just a functionality on accessory that might, but also might not extend the Service with new characteristics. What is important here I think is this function. Notice that it adds three new characteristics to the lightbulb (supportedTransitionConfiguration, transitionControl and activeTransitionCount). Add these three characteristics to your lightbulb and I believe you will see the magic happen. Without a "controller" concept in the HAP-python however, the code is going to be located in the main Bulb accesory class.
I'll hopefully test it soon, but so far this is my observation.
EDIT: Add these three characteristics WITH PROPER DEFAULT VALUES.
Ok, so with proper default values I am able to advertise a LightBulb that is recognized by an iPhone as having AdaptiveLightning. This however probably was the easier part, because now it's somehow needed to implement the actual functionality :/