mirror of
https://github.com/koush/scrypted.git
synced 2026-06-21 00:50:30 +01:00
Merge branch 'main' of github.com:koush/scrypted
This commit is contained in:
119
plugins/homekit/src/types/airpurifier.ts
Normal file
119
plugins/homekit/src/types/airpurifier.ts
Normal file
@@ -0,0 +1,119 @@
|
||||
import { ScryptedDevice, ScryptedDeviceType, ScryptedInterface, AirPurifierStatus, AirPurifierMode, AirPurifier, FilterMaintenance } from '@scrypted/sdk';
|
||||
import { addSupportedType, bindCharacteristic, DummyDevice, } from '../common';
|
||||
import { Characteristic, CharacteristicEventTypes, CharacteristicSetCallback, CharacteristicValue, Service } from '../hap';
|
||||
import { makeAccessory } from './common';
|
||||
import type { HomeKitPlugin } from "../main";
|
||||
|
||||
addSupportedType({
|
||||
type: ScryptedDeviceType.AirPurifier,
|
||||
probe(device: DummyDevice): boolean {
|
||||
return device.interfaces.includes(ScryptedInterface.AirPurifier);
|
||||
},
|
||||
getAccessory: async (device: ScryptedDevice & AirPurifier & FilterMaintenance, homekitPlugin: HomeKitPlugin) => {
|
||||
const accessory = makeAccessory(device, homekitPlugin);
|
||||
|
||||
const service = accessory.addService(Service.AirPurifier, device.name);
|
||||
const nightModeService = accessory.addService(Service.Switch, `${device.name} Night Mode`)
|
||||
|
||||
/* On/Off AND mode toggle */
|
||||
bindCharacteristic(device, ScryptedInterface.AirPurifier, service, Characteristic.Active,
|
||||
() => {
|
||||
switch(device.airPurifierState.status) {
|
||||
case AirPurifierStatus.Active:
|
||||
return Characteristic.Active.ACTIVE;
|
||||
case AirPurifierStatus.ActiveNightMode:
|
||||
return Characteristic.Active.ACTIVE;
|
||||
}
|
||||
return Characteristic.Active.INACTIVE;
|
||||
});
|
||||
|
||||
service.getCharacteristic(Characteristic.Active)
|
||||
.on(CharacteristicEventTypes.SET, (value: CharacteristicValue, callback: CharacteristicSetCallback) => {
|
||||
callback();
|
||||
device.setAirPurifierState({
|
||||
status: (value as boolean) ? AirPurifierStatus.Active : AirPurifierStatus.Inactive,
|
||||
})
|
||||
});
|
||||
|
||||
/* Current State */
|
||||
bindCharacteristic(device, ScryptedInterface.AirPurifier, service, Characteristic.CurrentAirPurifierState,
|
||||
() => {
|
||||
switch (device.airPurifierState.status) {
|
||||
case AirPurifierStatus.Inactive:
|
||||
return Characteristic.CurrentAirPurifierState.INACTIVE;
|
||||
case AirPurifierStatus.Idle:
|
||||
return Characteristic.CurrentAirPurifierState.IDLE;
|
||||
}
|
||||
return Characteristic.CurrentAirPurifierState.PURIFYING_AIR;
|
||||
});
|
||||
|
||||
/* Fan Speed */
|
||||
bindCharacteristic(device, ScryptedInterface.AirPurifier, service, Characteristic.RotationSpeed,
|
||||
() => device.airPurifierState.speed);
|
||||
|
||||
service.getCharacteristic(Characteristic.RotationSpeed)
|
||||
.on(CharacteristicEventTypes.SET, (value: CharacteristicValue, callback: CharacteristicSetCallback) => {
|
||||
callback();
|
||||
device.setAirPurifierState({
|
||||
speed: value,
|
||||
})
|
||||
})
|
||||
|
||||
/* i.e. Mode: Manual/Auto slider */
|
||||
bindCharacteristic(device, ScryptedInterface.AirPurifier, service, Characteristic.TargetAirPurifierState,
|
||||
() => {
|
||||
if (device.airPurifierState.mode == AirPurifierMode.Automatic)
|
||||
return Characteristic.TargetAirPurifierState.AUTO;
|
||||
return Characteristic.TargetAirPurifierState.MANUAL;
|
||||
});
|
||||
|
||||
service.getCharacteristic(Characteristic.TargetAirPurifierState)
|
||||
.on(CharacteristicEventTypes.SET, (value: CharacteristicValue, callback: CharacteristicSetCallback) => {
|
||||
callback();
|
||||
device.setAirPurifierState({
|
||||
mode: value === Characteristic.TargetAirPurifierState.AUTO ? AirPurifierMode.Automatic : AirPurifierMode.Manual,
|
||||
})
|
||||
});
|
||||
|
||||
/* LockPhysicalControls i.e. "Child Lock: Unlocked/Locked" */
|
||||
bindCharacteristic(device, ScryptedInterface.AirPurifier, service, Characteristic.LockPhysicalControls,
|
||||
() => !!device.airPurifierState.lockPhysicalControls);
|
||||
|
||||
service.getCharacteristic(Characteristic.LockPhysicalControls)
|
||||
.on(CharacteristicEventTypes.SET, (value: CharacteristicValue, callback: CharacteristicSetCallback) => {
|
||||
callback();
|
||||
device.setAirPurifierState({
|
||||
lockPhysicalControls: (value as boolean),
|
||||
})
|
||||
})
|
||||
|
||||
/* Night mode switch */
|
||||
bindCharacteristic(device, ScryptedInterface.AirPurifier, nightModeService, Characteristic.On,
|
||||
() => !!(device.airPurifierState.status === AirPurifierStatus.ActiveNightMode));
|
||||
|
||||
nightModeService.getCharacteristic(Characteristic.On)
|
||||
.on(CharacteristicEventTypes.SET, (value: CharacteristicValue, callback: CharacteristicSetCallback) => {
|
||||
callback();
|
||||
device.setAirPurifierState({
|
||||
status: value ? AirPurifierStatus.ActiveNightMode : AirPurifierStatus.Active,
|
||||
})
|
||||
})
|
||||
|
||||
/* Optional: Filter Maintenance Service */
|
||||
if (device.interfaces.includes(ScryptedInterface.FilterMaintenance)) {
|
||||
const filterMaintenanceService = accessory.addService(Service.FilterMaintenance, device.name);
|
||||
|
||||
bindCharacteristic(device, ScryptedInterface.FilterMaintenance, filterMaintenanceService, Characteristic.FilterLifeLevel,
|
||||
() => device.filterLifeLevel)
|
||||
|
||||
bindCharacteristic(device, ScryptedInterface.FilterMaintenance, filterMaintenanceService, Characteristic.FilterChangeIndication,
|
||||
() => {
|
||||
if (device.filterChangeIndication)
|
||||
return Characteristic.FilterChangeIndication.CHANGE_FILTER;
|
||||
return Characteristic.FilterChangeIndication.FILTER_OK;
|
||||
})
|
||||
}
|
||||
|
||||
return accessory;
|
||||
}
|
||||
});
|
||||
@@ -15,3 +15,4 @@ import './vacuum';
|
||||
import './outlet';
|
||||
import './notifier';
|
||||
import './windowcovering'
|
||||
import './airpurifier'
|
||||
|
||||
@@ -1418,7 +1418,7 @@ class PrebufferMixin extends SettingsMixinDeviceBase<VideoCamera> implements Vid
|
||||
const cloud = msos?.find(mso => mso.source === 'cloud');
|
||||
if (cloud) {
|
||||
this.storage.setItem('warnedCloud', 'true');
|
||||
log.a(`${this.name} is a cloud camera. Prebuffering maintains a persistent stream and will not enabled by default. You must enable the Prebuffer stream manually.`)
|
||||
log.a(`${this.name} is a cloud camera. Prebuffering maintains a persistent stream and will not be enabled by default. You must enable the Prebuffer stream manually.`)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -9,6 +9,16 @@ from typing import Union, Any, Callable
|
||||
from .other import *
|
||||
|
||||
|
||||
class AirPurifierMode(Enum):
|
||||
Automatic = "Automatic"
|
||||
Manual = "Manual"
|
||||
|
||||
class AirPurifierStatus(Enum):
|
||||
Active = "Active"
|
||||
ActiveNightMode = "ActiveNightMode"
|
||||
Idle = "Idle"
|
||||
Inactive = "Inactive"
|
||||
|
||||
class AirQuality(Enum):
|
||||
Excellent = "Excellent"
|
||||
Fair = "Fair"
|
||||
@@ -49,6 +59,7 @@ class PanTiltZoomMovement(Enum):
|
||||
|
||||
class ScryptedDeviceType(Enum):
|
||||
API = "API"
|
||||
AirPurifier = "AirPurifier"
|
||||
Automation = "Automation"
|
||||
Builtin = "Builtin"
|
||||
Camera = "Camera"
|
||||
@@ -83,6 +94,7 @@ class ScryptedDeviceType(Enum):
|
||||
WindowCovering = "WindowCovering"
|
||||
|
||||
class ScryptedInterface(Enum):
|
||||
AirPurifier = "AirPurifier"
|
||||
AirQualitySensor = "AirQualitySensor"
|
||||
AmbientLightSensor = "AmbientLightSensor"
|
||||
AudioSensor = "AudioSensor"
|
||||
@@ -106,6 +118,7 @@ class ScryptedInterface(Enum):
|
||||
EntrySensor = "EntrySensor"
|
||||
EventRecorder = "EventRecorder"
|
||||
Fan = "Fan"
|
||||
FilterMaintenance = "FilterMaintenance"
|
||||
FloodSensor = "FloodSensor"
|
||||
HttpRequestHandler = "HttpRequestHandler"
|
||||
HumiditySensor = "HumiditySensor"
|
||||
@@ -319,6 +332,13 @@ class AdoptDevice(TypedDict):
|
||||
settings: DeviceCreatorSettings
|
||||
pass
|
||||
|
||||
class AirPurifierState(TypedDict):
|
||||
lockPhysicalControls: bool
|
||||
mode: AirPurifierMode
|
||||
speed: float
|
||||
status: AirPurifierStatus
|
||||
pass
|
||||
|
||||
class ColorHsv(TypedDict):
|
||||
h: float
|
||||
s: float
|
||||
@@ -733,6 +753,12 @@ class VideoFrameGeneratorOptions(TypedDict):
|
||||
class TamperState(TypedDict):
|
||||
pass
|
||||
|
||||
class AirPurifier:
|
||||
airPurifierState: AirPurifierState
|
||||
async def setAirPurifierState(self, state: AirPurifierState) -> None:
|
||||
pass
|
||||
pass
|
||||
|
||||
class AirQualitySensor:
|
||||
airQuality: AirQuality
|
||||
pass
|
||||
@@ -864,6 +890,11 @@ class Fan:
|
||||
pass
|
||||
pass
|
||||
|
||||
class FilterMaintenance:
|
||||
filterChangeIndication: bool
|
||||
filterLifeLevel: float
|
||||
pass
|
||||
|
||||
class FloodSensor:
|
||||
flooded: bool
|
||||
pass
|
||||
@@ -1400,6 +1431,9 @@ class ScryptedInterfaceProperty(Enum):
|
||||
noxDensity = "noxDensity"
|
||||
co2ppm = "co2ppm"
|
||||
airQuality = "airQuality"
|
||||
airPurifierState = "airPurifierState"
|
||||
filterChangeIndication = "filterChangeIndication"
|
||||
filterLifeLevel = "filterLifeLevel"
|
||||
humiditySetting = "humiditySetting"
|
||||
fan = "fan"
|
||||
applicationInfo = "applicationInfo"
|
||||
@@ -1481,6 +1515,7 @@ class ScryptedInterfaceMethods(Enum):
|
||||
putSetting = "putSetting"
|
||||
armSecuritySystem = "armSecuritySystem"
|
||||
disarmSecuritySystem = "disarmSecuritySystem"
|
||||
setAirPurifierState = "setAirPurifierState"
|
||||
getReadmeMarkdown = "getReadmeMarkdown"
|
||||
getOauthUrl = "getOauthUrl"
|
||||
onOauthCallback = "onOauthCallback"
|
||||
@@ -1912,6 +1947,27 @@ class DeviceState:
|
||||
def airQuality(self, value: AirQuality):
|
||||
self.setScryptedProperty("airQuality", value)
|
||||
|
||||
@property
|
||||
def airPurifierState(self) -> AirPurifierState:
|
||||
return self.getScryptedProperty("airPurifierState")
|
||||
@airPurifierState.setter
|
||||
def airPurifierState(self, value: AirPurifierState):
|
||||
self.setScryptedProperty("airPurifierState", value)
|
||||
|
||||
@property
|
||||
def filterChangeIndication(self) -> bool:
|
||||
return self.getScryptedProperty("filterChangeIndication")
|
||||
@filterChangeIndication.setter
|
||||
def filterChangeIndication(self, value: bool):
|
||||
self.setScryptedProperty("filterChangeIndication", value)
|
||||
|
||||
@property
|
||||
def filterLifeLevel(self) -> float:
|
||||
return self.getScryptedProperty("filterLifeLevel")
|
||||
@filterLifeLevel.setter
|
||||
def filterLifeLevel(self, value: float):
|
||||
self.setScryptedProperty("filterLifeLevel", value)
|
||||
|
||||
@property
|
||||
def humiditySetting(self) -> HumiditySettingStatus:
|
||||
return self.getScryptedProperty("humiditySetting")
|
||||
@@ -2431,6 +2487,23 @@ ScryptedInterfaceDescriptors = {
|
||||
"airQuality"
|
||||
]
|
||||
},
|
||||
"AirPurifier": {
|
||||
"name": "AirPurifier",
|
||||
"methods": [
|
||||
"setAirPurifierState"
|
||||
],
|
||||
"properties": [
|
||||
"airPurifierState"
|
||||
]
|
||||
},
|
||||
"FilterMaintenance": {
|
||||
"name": "FilterMaintenance",
|
||||
"methods": [],
|
||||
"properties": [
|
||||
"filterChangeIndication",
|
||||
"filterLifeLevel"
|
||||
]
|
||||
},
|
||||
"Readme": {
|
||||
"name": "Readme",
|
||||
"methods": [
|
||||
|
||||
@@ -131,6 +131,7 @@ export enum ScryptedDeviceType {
|
||||
SecuritySystem = "SecuritySystem",
|
||||
WindowCovering = "WindowCovering",
|
||||
Siren = "Siren",
|
||||
AirPurifier = "AirPurifier",
|
||||
Unknown = "Unknown",
|
||||
}
|
||||
/**
|
||||
@@ -1181,6 +1182,36 @@ export interface Position {
|
||||
export interface PositionSensor {
|
||||
position?: Position;
|
||||
}
|
||||
export enum AirPurifierStatus {
|
||||
Inactive = "Inactive",
|
||||
Idle = "Idle",
|
||||
Active = "Active",
|
||||
ActiveNightMode = "ActiveNightMode",
|
||||
}
|
||||
|
||||
export enum AirPurifierMode {
|
||||
Manual = "Manual",
|
||||
Automatic = "Automatic",
|
||||
}
|
||||
|
||||
export interface AirPurifierState {
|
||||
speed?: number;
|
||||
status?: AirPurifierStatus,
|
||||
mode?: AirPurifierMode,
|
||||
lockPhysicalControls?: boolean,
|
||||
}
|
||||
|
||||
export interface AirPurifier {
|
||||
airPurifierState?: AirPurifierState;
|
||||
|
||||
setAirPurifierState(state: AirPurifierState): Promise<void>;
|
||||
}
|
||||
|
||||
export interface FilterMaintenance {
|
||||
filterLifeLevel?: number,
|
||||
filterChangeIndication?: boolean,
|
||||
}
|
||||
|
||||
export interface PM10Sensor {
|
||||
pm10Density?: number;
|
||||
}
|
||||
@@ -1950,6 +1981,8 @@ export enum ScryptedInterface {
|
||||
NOXSensor = "NOXSensor",
|
||||
CO2Sensor = "CO2Sensor",
|
||||
AirQualitySensor = "AirQualitySensor",
|
||||
AirPurifier = "AirPurifier",
|
||||
FilterMaintenance = "FilterMaintenance",
|
||||
Readme = "Readme",
|
||||
OauthClient = "OauthClient",
|
||||
MixinProvider = "MixinProvider",
|
||||
|
||||
Reference in New Issue
Block a user