import json, strutils, options, algorithm import coapClient import gatewayTypes, deviceTypes import mappings, helpers proc parseDevice (data: JsonNode): TradfriDevice = let deviceType = TradfriDeviceType(data[ParameterType].getInt) var state: TradfriDeviceState case deviceType: of Remote: state = TradfriDeviceState( kind: deviceType, remoteSupported: false ) of slaveRemote: state = TradfriDeviceState( kind: deviceType, slaveRemoteSupported: false ) of Lightbulb: state = TradfriDeviceState( kind: deviceType, lightPowered: parseBool($data[DeviceLightbulb][0][ParameterPowerState].getInt), lightBrightness: data[DeviceLightbulb][0][ParameterDimmerValue].getInt ) #get hue and saturation (only for RGB-bulbs) if data[DeviceLightbulb][0].hasKey(ParameterHue): state.lightHue = some(data[DeviceLightbulb][0][ParameterHue].getInt) state.lightSaturation = some(data[DeviceLightbulb][0][ParameterSaturation].getInt) else: state.lightHue = none(int) state.lightSaturation = none(int) #get color hex-value (for white-spectrum and RGB, but only some presets) if data[DeviceLightbulb][0].hasKey(ParameterColorHex): state.lightColorHex = some(data[DeviceLightbulb][0][ParameterColorHex].getStr) else: state.lightColorHex = none(string) #get colorX and colorY values (can be used to set any color on RGB bulbs) if data[DeviceLightbulb][0].hasKey(ParameterColorX): state.lightColorX = some(data[DeviceLightbulb][0][ParameterColorX].getFloat) state.lightColorY = some(data[DeviceLightbulb][0][ParameterColorY].getFloat) else: state.lightColorX = none(float) state.lightColorY = none(float) #get color-specturm value if data[DeviceLightbulb][0].hasKey(ParameterColorTemperature): state.lightColorTemperature = some(data[DeviceLightbulb][0][ParameterColorTemperature].getInt) else: state.lightColorTemperature = none(int) #determine type of bulb if state.lightHue.isSome: state.lightSpectrum = RGB elif state.lightColorTemperature.isSome: state.lightSpectrum = White else: state.lightSpectrum = None of Plug: state = TradfriDeviceState( kind: deviceType, plugPowered: parseBool($data[DevicePlug][0][ParameterPowerState].getInt), plugDimmer: data[DevicePlug][0][ParameterDimmerValue].getInt ) of motionSensor: state = TradfriDeviceState( kind: deviceType, motionSensorSupported: false ) of signalRepeater: state = TradfriDeviceState( kind: deviceType, signalRepeaterSupported: false ) of Blind: state = TradfriDeviceState( kind: deviceType, blindPosition: data["3"][ParameterBlindPosition].getFloat, blindTrigger: data["3"][ParameterBlindTrigger].getFloat ) of soundRemote: state = TradfriDeviceState( kind: deviceType, soundRemoteSupported: false ) return TradfriDevice( `type`: deviceType, id: data[ParameterId].getInt, name: data[ParameterName].getStr, alive: intToBool(data[ParameterAlive].getInt), createdAt: data[ParameterCreatedAt].getInt, lastSeen: data[ParameterLastSeen].getInt, state: state, info: TradfriDeviceInfo( manufacturer: data["3"]["0"].getStr, modelNumber: data["3"]["1"].getStr, serialNumber: data["3"]["2"].getStr, firmwareVersion: data["3"]["3"].getStr, power: TradfriPowerSource(data["3"]["6"].getInt), battery: data["3"]{"9"}.getInt ) ) proc operateDevice* (device: TradfriDevice, action: TradfriDeviceAction): bool = var requestParams = %* {} template CheckDeviceType(typeId: TradfriDeviceType) = if device.`type` != TradfriDeviceType(typeId): raise newException(ValueError, "Wrong action for this Devicetype") case action.kind: of DeviceRename: requestParams.add(ParameterName, %action.deviceName) of LightSetPowerState: CheckDeviceType(Lightbulb) requestParams.add(DeviceLightbulb, %* [{ ParameterPowerState: boolToInt(action.lightPowerState), ParameterTransitionTime: action.transitionTime }]) of LightSetBrightness: CheckDeviceType(Lightbulb) requestParams.add(DeviceLightbulb, %* [{ ParameterDimmerValue: action.lightBrightness, ParameterTransitionTime: action.transitionTime }]) of LightSetColorHex: CheckDeviceType(Lightbulb) requestParams.add(DeviceLightbulb, %* [{ ParameterColorHex: action.lightColorHex, ParameterTransitionTime: action.transitionTime }]) of LightSetColorXY: CheckDeviceType(Lightbulb) requestParams.add(DeviceLightbulb, %* [{ ParameterColorX: action.lightColorX, ParameterColorY: action.lightColorY, ParameterTransitionTime: action.transitionTime }]) of LightSetHueSaturation: CheckDeviceType(Lightbulb) requestParams.add(DeviceLightbulb, %* [{ ParameterHue: action.lightHue, ParameterSaturation: action.lightSaturation, ParameterTransitionTime: action.transitionTime }]) of LightSetColorTemperature: CheckDeviceType(Lightbulb) requestParams.add(DeviceLightbulb, %* [{ ParameterColorTemperature: action.lightColorTemperature, ParameterTransitionTime: action.transitionTime }]) of PlugSetPowerState: CheckDeviceType(Plug) requestParams.add(DevicePlug, %* [{ ParameterPowerState: boolToInt(action.plugPowerState), }]) of PlugSetDimmerValue: CheckDeviceType(Plug) requestParams.add(DevicePlug, %* [{ ParameterDimmerValue: action.plugDimmerValue, }]) discard makeCoapRequest(device.gatewayRef.host, device.gatewayRef.port, "put", device.gatewayRef.user, device.gatewayRef.pass, EndpointDevices & $device.id, requestParams) proc getDevice* (gatewayRef: TradfriGatewayRef, deviceId: int): TradfriDevice = let request = makeCoapRequest(gatewayRef.host, gatewayRef.port, "get", gatewayRef.user, gatewayRef.pass, EndpointDevices & $deviceId, %* {}) result = parseDevice(request) result.gatewayRef = gatewayRef proc getDevices* (gatewayRef: TradfriGatewayRef): seq[TradfriDevice] = let request = makeCoapRequest(gatewayRef.host, gatewayRef.port, "get", gatewayRef.user, gatewayRef.pass, EndpointDevices, %* {}) result = newSeq[TradfriDevice]() for id in request: result.add(getDevice(gatewayRef, id.getInt)) result.sort do (x, y: TradfriDevice) -> int: result = cmp(x.id, y.id)