commit a0d4508a39c273990fc3826d1188e0f89fd4e8a3
parent 3f32d9cc93b3117f6ef1c0a9baff2fb28dfde00c
Author: ctucx <c@ctu.cx>
Date: Tue, 15 Sep 2020 14:06:52 +0200
parent 3f32d9cc93b3117f6ef1c0a9baff2fb28dfde00c
Author: ctucx <c@ctu.cx>
Date: Tue, 15 Sep 2020 14:06:52 +0200
update
9 files changed, 329 insertions(+), 221 deletions(-)
diff --git a/coapClient.nim b/coapClient.nim @@ -12,7 +12,7 @@ proc makeCoapRequest* (host: string, port: int, reqMethod: string, user: string, arguments.add($reqPayload) arguments.add("coaps://" & host & ":" & $port & endpoint) - + let reqResult = execProcess("coap-client", args = arguments, options = {poUsePath}) try:
diff --git a/device.nim b/device.nim @@ -1,212 +0,0 @@ -import json, strutils, options - -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: 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))
diff --git a/deviceHelpers.nim b/deviceHelpers.nim @@ -1,5 +1,12 @@ import colors -import deviceTypes, helpers, device +import deviceTypes, helpers, devices + +proc renameDevice* (device: TradfriDevice, name: string): bool = + return device.operateDevice(TradfriDeviceAction( + kind: DeviceRename, + deviceName: name + )) + proc setPowerState* (device: TradfriDevice, state: bool): bool = if device.`type` == Lightbulb:
diff --git a/devices.nim b/devices.nim @@ -0,0 +1,215 @@ +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)
diff --git a/groupTypes.nim b/groupTypes.nim @@ -0,0 +1,24 @@ +import gatewayTypes, deviceTypes + +type + TradfriGroupActionType* = enum + GroupRename, GroupSetPowerState + + TradfriGroup* = object + gatewayRef*: TradfriGatewayRef + `type`*: int + name*: string + createdAt*: int + id*: int + powerState*: bool + dimmerValue*: int + sceneId*: int + devices*: seq[TradfriDevice] + + TradfriGroupAction* = object + case kind*: TradfriGroupActionType + of GroupRename: + groupName*: string + + of GroupSetPowerState: + groupPowerState*: bool
diff --git a/groups.nim b/groups.nim @@ -0,0 +1,55 @@ +import json, strutils, sequtils, options, algorithm + +import coapClient +import gatewayTypes, groupTypes, deviceTypes +import mappings, helpers, devices + +proc operateGroup* (group: TradfriGroup, action: TradfriGroupAction): bool = + var requestParams = %* {} + + case action.kind: + of GroupRename: + requestParams.add(ParameterName, %action.groupName) + + of GroupSetPowerState: + requestParams.add(DeviceLightbulb, %* [{ + ParameterPowerState: boolToInt(action.groupPowerState), + }]) + + + discard makeCoapRequest(group.gatewayRef.host, group.gatewayRef.port, "put", group.gatewayRef.user, group.gatewayRef.pass, EndpointGroups & $group.id, requestParams) + + +proc getGroup* (gatewayRef: TradfriGatewayRef, groupId: int): TradfriGroup = + let request = makeCoapRequest(gatewayRef.host, gatewayRef.port, "get", gatewayRef.user, gatewayRef.pass, EndpointGroups & $groupId, %* {}) + + var devices = newSeq[TradfriDevice]() + for deviceId in request[ParameterDeviceIds]["15002"]["9003"]: + devices.add(gatewayRef.getDevice(deviceId.getInt)) + + devices.sort do (x, y: TradfriDevice) -> int: + result = cmp(x.id, y.id) + + result = TradfriGroup( + gatewayRef: gatewayRef, + name: request[ParameterName].getStr, + createdAt: request[ParameterCreatedAt].getInt, + id: request[ParameterId].getInt, + powerState: intToBool(request[ParameterPowerState].getInt), + dimmerValue: request[ParameterDimmerValue].getInt, + sceneId: request[ParameterSceneId].getInt, + devices: devices + ) + + +proc getGroups* (gatewayRef: TradfriGatewayRef): seq[TradfriGroup] = + let request = makeCoapRequest(gatewayRef.host, gatewayRef.port, "get", gatewayRef.user, gatewayRef.pass, EndpointGroups, %* {}) + + result = newSeq[TradfriGroup]() + + for id in request: + result.add(getGroup(gatewayRef, id.getInt)) + + result.sort do (x, y: TradfriGroup) -> int: + result = cmp(x.id, y.id) +
diff --git a/listGroups.nim b/listGroups.nim @@ -0,0 +1,13 @@ +import json, os, strutils +import tradfri + +let tradfriGateway = newTradfriGateway( + host = "192.168.100.225", + port = 5684, + user = "ctucx", + pass = "JrSGx6WkAVJUl53b" + ) + +let groups = %* tradfriGateway.getGroups() + +echo pretty groups
diff --git a/mappings.nim b/mappings.nim @@ -17,12 +17,13 @@ const DeviceBlind* = "15015" const ParameterName* = "9001" const ParameterCreatedAt* = "9002" const ParameterId* = "9003" +const ParameterDeviceIds* = "9018" const ParameterAlive* = "9019" const ParameterLastSeen* = "9020" -const ParameterType* = "5750" +const ParameterSceneId* = "9039" -const ParameterPowerState* = "5850" -const ParameterDimmerValue* = "5851" +const ParameterBlindTrigger* = "5523" +const ParameterBlindPosition* = "5536" const ParameterColorHex* = "5706" const ParameterHue* = "5707" @@ -31,9 +32,10 @@ const ParameterColorX* = "5709" const ParameterColorY* = "5710" const ParameterColorTemperature* = "5711" const ParameterTransitionTime* = "5712" +const ParameterType* = "5750" -const ParameterBlindTrigger* = "5523" -const ParameterBlindPosition* = "5536" +const ParameterPowerState* = "5850" +const ParameterDimmerValue* = "5851" const ParameterGatewayNtpServerUrl* = "9023" const ParameterGatewayVersion* = "9029"
diff --git a/tradfri.nim b/tradfri.nim @@ -1,6 +1,6 @@ -import gatewayTypes, deviceTypes, mappings, helpers import gateway -import device, deviceHelpers +import devices, deviceHelpers +import groups #gateway related stuff export newTradfriGateway @@ -18,3 +18,7 @@ export setBrightness export setColorHex export setColorXY export setColorXYfromHex + +#group related stuff +export getGroups +export getGroup