import type { Negative, StringKeyOf } from 'type-fest'; import { isNumberObject } from 'util/types'; import { type StringKeys, logStringify } from '../../Utils.js'; /** * Checks if a given string represents a valid number. * @param value - The string to check. * @returns True if the string is a valid number, false otherwise. */ function isNumberString(value: string): boolean { return !isNaN(Number(value)); } export namespace Category { export enum Insteon { Controller = 0, DimmableControl = 1, RelayControl = 2, NetworkBridge = 3, IrrigationControl = 4, ClimateControl = 5, PoolControl = 6, SensorActuator = 7, HomeEntertainment = 8, EnergyManagement = 9, ApplianceControl = 10, WindowShadeControl = 14, AccessControl = 15, SecurityHealthSafety = 16, A10X10 = 113, Virtual = 127, Unknown = 254, } export enum Domain { Home = 1, Outdoor = 2, Industrial = 3, Commercial = 4, } export namespace Home { export enum Category { DeviceID = 0, Alarm = 1, Controller = 2, Sensor = 3, Relay = 4, Remote = 5, AudioVisual = 6, DoorLock = 7, Doorbell = 8, Camera = 9, DateTime = 10, Weather = 11, HVAC = 12, Display = 13, Gateway = 14, PowerManagement = 15, Appliance = 16, HomeHealth = 17, Barrier = 18, Automotive = 19, } export enum Alarm { SecurityPanel = 1, Zone = 2, Partition = 3, Siren = 4, } export enum Controller { ClassAMotorControl = 1, ClassBMotorControl = 2, ClassCMotorControl = 3, MotorMultiposition = 4, EntryControl = 5, PCController = 6, SceneController = 7, SubsystemController = 8, DimmerSwitch = 9, MultilevelSwitch = 10, SceneSwitch = 11, Toggle = 12, NonDimmingLighting = 16, } export enum Sensor { BinarySensor = 1, MultilevelSensor = 2, ClimateSensor = 3, MotionSensor = 4, EnergyMeter = 5, PulseMeter = 6, WaterMeter = 7, GasMeter = 8, SmokeDetector = 9, TamperSensor = 10, TiltSensor = 11, WaterSensor = 12, DoorWindowSensor = 13, LowBatterySensor = 14, COEndOfLifeSensor = 15, OverheatSensor = 16, RapidTempRiseSensor = 17, UnderheatSensor = 18, LeakDetectedSensor = 19, LevelDropSensor = 20, FilterCloggedSensor = 21, IntrusionDetectSensor = 22, CO2Sensor = 23, COSensor = 24, FreezeSensor = 25, GlassBreakSensor = 26, HeatSensor = 27, } export enum Relay { OnOffPowerStrip = 1, OnOffPowerSwitch = 2, OnOffSceneSwitch = 3, BinarySwitch = 4, OpenCloseValve = 5, } export enum Remote { AVRemoteControl = 1, SimpleRemoteControl = 2, } export enum AudioVisual { AVControlPoint = 1, SatelliteReceiver = 2, Television = 3, SetTopBox = 4, } export enum DoorLock { Unknown = '*', } export enum Doorbell { DoorBell = 1, Chime = 2, } export enum Camera { Unknown = '*', } export enum DateTime { Timer = 1, } export enum Weather { WeatherStation = 0, Temperature = 1, Humidity = 2, BarometricPressure = 3, Wind = 4, Precipitation = 5, IlluminationLight = 6, Lightning = 7, } export enum HVAC { Thermostat = 1, ResidentialHRV = 2, } export enum Display { Unknown = '*', } export enum Gateway { Unknown = '*', } export enum PowerManagement { Unknown = '*', } export enum Appliance { Unknown = '*', } export enum HomeHealth { Unknown = '*', } export enum Barrier { Unknown = '*', } export enum Automotive { Tesla = 1, } } export namespace Commercial { export enum Category { Unknown = '*', } export enum Unknown { Unknown = '*', } } export namespace Outdoor { export enum Category { Unknown = '*', } export enum Unknown { Unknown = '*', } } export namespace Industrial { export enum Category { Unknown = '*', } export enum Unknown { Unknown = '*', } } } export type DeviceInfo< D extends keyof typeof Category.Domain, C extends keyof (typeof Category)[D], S extends keyof (typeof Category)[D][C], > = { domain: (typeof Category.Domain)[D]; category: (typeof Category)[D][C]; subcategory: (typeof Category)[D][C][S]; model: number; }; export type DeviceHinto< D extends 'Home' = 'Home', C extends StringKeys<(typeof Category)[D]> = StringKeys<(typeof Category)[D]>, S extends StringKeys<(typeof Category)[D][C]> = StringKeys<(typeof Category)[D][C]>, > = `${(typeof Category.Domain)[D]}.${StringKeys<(typeof Category)[D][C]>}.${S}.${number}`; function generateHints(): DeviceHint.Hints { //@ts-ignore const codes = {} as any; for (var x in Category) { if (x != 'Domain' && x != 'Insteon') { codes[x] = {}; for (var y in Category[x]) { if (y != 'Category' && typeof y == 'string' && isNaN(Number(y))) { codes[x][y] = {}; for (var z in Category[x][y]) { if (z != 'Category' && typeof z == 'string' && isNaN(Number(z))) { try { codes[x][y][z] = `${Category.Domain[x]}.${Category[x]['Category'][y]}.${Category[x][y][z]}`; } catch { console.log(`Error building: ${x}/${y}/${z}`); } } } } } } } console.log(logStringify(codes)); return codes; } type ValuesOf = X[keyof X]; export namespace DeviceHint { export type Hints = { [x in 'Home' | 'Industrial' | 'Outdoor' | 'Commercial']: { [y in keyof Omit<(typeof Category)[x], 'Category'>]: { [z in keyof Omit<(typeof Category)[x][y], ''>]: `${ (typeof Category.Domain)[x] //@ts-ignore }.${(typeof Category)[x]['Category'][y]}.${(typeof Category)[x][y][z]}`; }; }; }; type NegativeToNumber = T extends -1 ? number : T; type NumberToString = T extends number ? string : T; export const Hints = generateHints(); }