summaryrefslogblamecommitdiffstats
path: root/devices.nim
blob: 7b206905e9c000f70c0eaf58eaf26e561a8f7e59 (plain) (tree)
1
                                         






















































































































































































                                                                                                      
                                                                     


























                                                                                                                                                                             


                                              
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)