Advertisement
cjcharles

W1 and R swapped in H801 DH

Mar 17th, 2017
250
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Groovy 29.96 KB | None | 0 0
  1. /**
  2.  *  Copyright 2016 Eric Maycock
  3.  *
  4.  *  Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
  5.  *  in compliance with the License. You may obtain a copy of the License at:
  6.  *
  7.  *      http://www.apache.org/licenses/LICENSE-2.0
  8.  *
  9.  *  Unless required by applicable law or agreed to in writing, software distributed under the License is distributed
  10.  *  on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License
  11.  *  for the specific language governing permissions and limitations under the License.
  12.  *
  13.  *  SmartLife RGBW Controller
  14.  *
  15.  *  Author: Eric Maycock (erocm123)
  16.  *  Date: 2016-12-10
  17.  */
  18.  
  19. import groovy.json.JsonSlurper
  20.  
  21. metadata {
  22.     definition (name: "SmartLife RGBW Controller", namespace: "erocm123", author: "Eric Maycock") {
  23.         capability "Switch Level"
  24.         capability "Actuator"
  25.         capability "Color Control"
  26.         capability "Switch"
  27.         capability "Refresh"
  28.         capability "Sensor"
  29.         capability "Configuration"
  30.         capability "Health Check"
  31.        
  32.         (1..6).each { n ->
  33.             attribute "switch$n", "enum", ["on", "off"]
  34.             command "on$n"
  35.             command "off$n"
  36.         }
  37.        
  38.         command "reset"
  39.         command "setProgram"
  40.         command "setWhiteLevel"
  41.        
  42.         command "redOn"
  43.         command "redOff"
  44.         command "greenOn"
  45.         command "greenOff"
  46.         command "blueOn"
  47.         command "blueOff"
  48.         command "white2On"
  49.         command "white2Off"
  50.        
  51.         command "setRedLevel"
  52.         command "setGreenLevel"
  53.         command "setBlueLevel"
  54.         command "setWhite1Level"
  55.         command "setWhite2Level"
  56.     }
  57.  
  58.     simulator {
  59.     }
  60.    
  61.     preferences {
  62.        
  63.         input("password", "password", title:"Password", required:false, displayDuringSetup:true)
  64.         input("transition", "enum", title:"Default Transition", required:false, displayDuringSetup:true, options:
  65.         [["true":"fade"],["false":"flash"]])
  66.         input("channels", "boolean", title:"Mutually Exclusive RGB & White.\nOnly allow one or the other", required:false, displayDuringSetup:true)
  67.         input("powerOnState", "enum", title:"Boot Up State", description: "State when power is applied", required: false, displayDuringSetup: false, options: [[0:"Off"],[1:"On"]/*,[2:"Previous State"]*/])
  68.        
  69.         input("color", "enum", title: "Default Color", required: false, multiple:false, value: "Previous", options: [
  70.                     ["Previous":"Previous"],
  71.                     ["Soft White":"Soft White - Default"],
  72.                     ["White":"White - Concentrate"],
  73.                     ["Daylight":"Daylight - Energize"],
  74.                     ["Warm White":"Warm White - Relax"],
  75.                     "Red","Green","Blue","Yellow","Orange","Purple","Pink","Cyan","Random","Custom"])
  76.  
  77.         //if (color == "Custom"){            
  78.         input "custom", "text", title: "Custom Color in Hex (ie ffffff)\r\nIf \"Custom\" is chosen above", submitOnChange: false, required: false
  79.         //} else {
  80.         input("level", "enum", title: "Default Level", required: false, value: 100, options: [[0:"Previous"],[10:"10%"],[20:"20%"],[30:"30%"],[40:"40%"],[50:"50%"],[60:"60%"],[70:"70%"],[80:"80%"],[90:"90%"],[100:"100%"]])
  81.         //}
  82.  
  83.         //input("override", "boolean", title:"Override detected IP Address", required: false, displayDuringSetup: false)
  84.         //input("ip", "string", title:"IP Address", description: "192.168.1.150", required: false, displayDuringSetup: false)
  85.     }
  86.  
  87.     tiles (scale: 2){      
  88.         multiAttributeTile(name:"switch", type: "lighting", width: 6, height: 4, canChangeIcon: true){
  89.             tileAttribute ("device.switch", key: "PRIMARY_CONTROL") {
  90.                 attributeState "off", label:'${name}', action:"switch.on", icon:"st.lights.philips.hue-single", backgroundColor:"#ffffff", nextState:"turningOn"
  91.                 attributeState "on", label:'${name}', action:"switch.off", icon:"st.lights.philips.hue-single", backgroundColor:"#79b821", nextState:"turningOff"
  92.                 attributeState "turningOn", label:'${name}', action:"switch.off", icon:"st.lights.philips.hue-single", backgroundColor:"#79b821", nextState:"turningOff"
  93.                 attributeState "turningOff", label:'${name}', action:"switch.on", icon:"st.lights.philips.hue-single", backgroundColor:"#ffffff", nextState:"turningOn"
  94.             }
  95.             tileAttribute ("device.level", key: "SLIDER_CONTROL") {
  96.                 attributeState "level", action:"switch level.setLevel"
  97.             }
  98.             tileAttribute ("device.color", key: "COLOR_CONTROL") {
  99.                 attributeState "color", action:"setColor"
  100.             }
  101.         }
  102.  
  103.         standardTile("refresh", "device.switch", inactiveLabel: false, decoration: "flat", width: 2, height: 2) {
  104.             state "default", label:"", action:"refresh.refresh", icon:"st.secondary.refresh"
  105.         }
  106.         standardTile("configure", "device.configure", inactiveLabel: false, width: 2, height: 2, decoration: "flat") {
  107.             state "configure", label:'', action:"configuration.configure", icon:"st.secondary.configure"
  108.         }
  109.        
  110.         standardTile("red", "device.red", height: 1, width: 1, inactiveLabel: false, canChangeIcon: false) {
  111.             state "off", label:"R", action:"redOn", icon:"st.illuminance.illuminance.dark", backgroundColor:"#D8D8D8"
  112.             state "on", label:"R", action:"redOff", icon:"st.illuminance.illuminance.bright", backgroundColor:"#FF0000"
  113.         }
  114.         controlTile("redSliderControl", "device.redLevel", "slider", height: 1, width: 4, inactiveLabel: false) {
  115.             state "redLevel", action:"setRedLevel"
  116.         }
  117.         valueTile("redValueTile", "device.redLevel", decoration: "flat", height: 1, width: 1) {
  118.             state "redLevel", label:'${currentValue}%'
  119.         }    
  120.        
  121.         standardTile("green", "device.green", height: 1, width: 1, inactiveLabel: false, canChangeIcon: false) {
  122.             state "off", label:"G", action:"greenOn", icon:"st.illuminance.illuminance.dark", backgroundColor:"#D8D8D8"
  123.             state "on", label:"G", action:"greenOff", icon:"st.illuminance.illuminance.bright", backgroundColor:"#00FF00"
  124.         }
  125.         controlTile("greenSliderControl", "device.greenLevel", "slider", height: 1, width: 4, inactiveLabel: false) {
  126.             state "greenLevel", action:"setGreenLevel"
  127.         }
  128.         valueTile("greenValueTile", "device.greenLevel", decoration: "flat", height: 1, width: 1) {
  129.             state "greenLevel", label:'${currentValue}%'
  130.         }    
  131.        
  132.         standardTile("blue", "device.blue", height: 1, width:1, inactiveLabel: false, canChangeIcon: false) {
  133.             state "off", label:"B", action:"blueOn", icon:"st.illuminance.illuminance.dark", backgroundColor:"#D8D8D8"
  134.             state "on", label:"B", action:"blueOff", icon:"st.illuminance.illuminance.bright", backgroundColor:"#0000FF"
  135.         }
  136.         controlTile("blueSliderControl", "device.blueLevel", "slider", height: 1, width: 4, inactiveLabel: false) {
  137.             state "blueLevel", action:"setBlueLevel"
  138.         }
  139.         valueTile("blueValueTile", "device.blueLevel", decoration: "flat", height: 1, width: 1) {
  140.             state "blueLevel", label:'${currentValue}%'
  141.         }  
  142.        
  143.         standardTile("white2", "device.white2", height: 1, width: 1, inactiveLabel: false, canChangeIcon: false) {
  144.             state "off", label:"W2", action:"white2On", icon:"st.illuminance.illuminance.dark", backgroundColor:"#D8D8D8"
  145.             state "on", label:"W2", action:"white2Off", icon:"st.illuminance.illuminance.bright", backgroundColor:"#FFFFFF"
  146.         }
  147.         controlTile("white2SliderControl", "device.white2Level", "slider", height: 1, width: 4, inactiveLabel: false) {
  148.             state "white2Level", action:"setWhite2Level"
  149.         }
  150.         valueTile("white2ValueTile", "device.white2Level", decoration: "flat", height: 1, width: 1) {
  151.             state "white2Level", label:'${currentValue}%'
  152.         }
  153.         valueTile("ip", "ip", decoration: "flat", width: 2, height: 1) {
  154.             state "ip", label:'IP Address\r\n${currentValue}'
  155.         }
  156.         valueTile("firmware", "firmware", decoration: "flat", width: 2, height: 1) {
  157.             state "firmware", label:'Firmware ${currentValue}'
  158.         }
  159.        
  160.        
  161.         (1..6).each { n ->
  162.             standardTile("switch$n", "switch$n", canChangeIcon: true, width: 2, height: 2) {
  163.                 state "off", label: "$n", action: "on$n", icon: "st.switches.switch.off", backgroundColor: "#ffffff"
  164.                 state "on", label: "$n", action: "off$n", icon: "st.switches.switch.on", backgroundColor: "#79b821"
  165.             }
  166.         }
  167.     }
  168.  
  169.     main(["switch"])
  170.     details(["switch", "levelSliderControl",
  171.              "red", "redSliderControl", "redValueTile",
  172.              "green", "greenSliderControl", "greenValueTile",
  173.              "blue", "blueSliderControl", "blueValueTile",
  174.              "white2", "white2SliderControl", "white2ValueTile",
  175.              "switch1", "switch2", "switch3",
  176.              "switch4", "switch5", "switch6",
  177.              "refresh", "configure", "ip", "firmware" ])
  178. }
  179.  
  180. def installed() {
  181.     log.debug "installed()"
  182.     configure()
  183. }
  184.  
  185. def updated() {
  186.     log.debug "updated()"
  187.     configure()
  188. }
  189.  
  190. def configure() {
  191.     log.debug "configure()"
  192.     log.debug "Configuring Device For SmartThings Use"
  193.     sendEvent(name: "checkInterval", value: 12 * 60, data: [protocol: "lan", hubHardwareId: device.hub.hardwareID], displayed: false)
  194.     def responses = []
  195.     if (ip != null) state.dni = setDeviceNetworkId(ip, "80")
  196.     state.hubIP = device.hub.getDataValue("localIP")
  197.     state.hubPort = device.hub.getDataValue("localSrvPortTCP")
  198.     responses << configureInstant(state.hubIP, state.hubPort, powerOnState)
  199.     responses << configureDefault()
  200.     return response(responses)
  201. }
  202.  
  203. def configureDefault(){
  204.     if(settings.color == "Previous") {
  205.         return postAction("/config?dcolor=Previous")
  206.     } else if(settings.color == "Random") {
  207.         return postAction("/config?dcolor=${transition == "false"? "d~" : "f~"}${getHexColor(settings.color)}")
  208.     } else if(settings.color == "Custom") {
  209.         return postAction("/config?dcolor=${transition == "false"? "d~" : "f~"}${settings.custom}")
  210.     } else if(settings.color == "Soft White" || settings.color == "Warm White") {
  211.         if (settings.level == null || settings.level == "0") {
  212.             return postAction("/config?dcolor=${transition == "false"? "x~" : "w~"}${getDimmedColor(getHexColor(settings.color), "100")}")
  213.         } else {
  214.             return postAction("/config?dcolor=${transition == "false"? "x~" : "w~"}${getDimmedColor(getHexColor(settings.color), settings.level)}")
  215.         }
  216.     } else {
  217.         if (settings.level == null || settings.color == null){
  218.            return postAction("/config?dcolor=Previous")
  219.         } else if (settings.level == null || settings.level == "0") {
  220.             return postAction("/config?dcolor=${transition == "false"? "d~" : "f~"}${getDimmedColor(getHexColor(settings.color), "100")}")
  221.         } else {
  222.             return postAction("/config?dcolor=${transition == "false"? "d~" : "f~"}${getDimmedColor(getHexColor(settings.color), settings.level)}")
  223.         }
  224.     }
  225. }
  226.  
  227. def configureInstant(ip, port, pos){
  228.     return postAction("/config?haip=${ip}&haport=${port}&pos=${pos}")
  229. }
  230.  
  231. def parse(description) {
  232.     def map = [:]
  233.     def events = []
  234.     def cmds = []
  235.    
  236.     if(description == "updated") return
  237.     def descMap = parseDescriptionAsMap(description)
  238.    
  239.     if (!state.configSuccess || state.configSuccess == "false") cmds << configureInstant(device.hub.getDataValue("localIP"), device.hub.getDataValue("localSrvPortTCP"), powerOnState)
  240.    
  241.     if (!device.currentValue("ip") || (device.currentValue("ip") != getDataValue("ip"))) sendEvent(name: 'ip', value: getDataValue("ip"))
  242.  
  243.     if (!state.mac || state.mac != descMap["mac"]) {
  244.         log.debug "Mac address of device found ${descMap["mac"]}"
  245.         updateDataValue("mac", descMap["mac"])
  246.     }
  247.     if (state.mac != null && state.dni != state.mac) state.dni = setDeviceNetworkId(state.mac)
  248.    
  249.     def body = new String(descMap["body"].decodeBase64())
  250.     log.debug body
  251.    
  252.     def slurper = new JsonSlurper()
  253.     def result = slurper.parseText(body)
  254.    
  255.     if (result.containsKey("power")) {
  256.         events << createEvent(name: "switch", value: result.power)
  257.         toggleTiles("all")
  258.     }
  259.     if (result.containsKey("rgb")) {
  260.        events << createEvent(name:"color", value:"#$result.rgb")
  261.  
  262.        // only store the previous value if the response did not come from a power-off command
  263.        if (result.power != "off")
  264.          state.previousRGB = result.rgb
  265.     }
  266.     if (result.containsKey("w1")) {
  267.        events << createEvent(name:"redLevel", value: Integer.parseInt(result.r,16)/255 * 100 as Integer, displayed: false)
  268.        if ((Integer.parseInt(result.r,16)/255 * 100 as Integer) > 0 ) {
  269.           events << createEvent(name:"red", value: "on", displayed: false)
  270.        } else {
  271.           events << createEvent(name:"red", value: "off", displayed: false)
  272.        }
  273.     }
  274.     if (result.containsKey("g")) {
  275.        events << createEvent(name:"greenLevel", value: Integer.parseInt(result.g,16)/255 * 100 as Integer, displayed: false)
  276.        if ((Integer.parseInt(result.g,16)/255 * 100 as Integer) > 0 ) {
  277.           events << createEvent(name:"green", value: "on", displayed: false)
  278.        } else {
  279.           events << createEvent(name:"green", value: "off", displayed: false)
  280.        }
  281.     }
  282.     if (result.containsKey("b")) {
  283.        events << createEvent(name:"blueLevel", value: Integer.parseInt(result.b,16)/255 * 100 as Integer, displayed: false)
  284.        if ((Integer.parseInt(result.b,16)/255 * 100 as Integer) > 0 ) {
  285.           events << createEvent(name:"blue", value: "on", displayed: false)
  286.        } else {
  287.           events << createEvent(name:"blue", value: "off", displayed: false)
  288.        }
  289.     }
  290.     if (result.containsKey("w2")) {
  291.        events << createEvent(name:"white2Level", value: Integer.parseInt(result.w2,16)/255 * 100 as Integer, displayed: false)
  292.        if ((Integer.parseInt(result.w2,16)/255 * 100 as Integer) > 0 ) {
  293.           events << createEvent(name:"white2", value: "on", displayed: false)
  294.        } else {
  295.           events << createEvent(name:"white2", value: "off", displayed: false)
  296.        }
  297.  
  298.        // only store the previous value if the response did not come from a power-off command
  299.        if (result.power != "off")
  300.           state.previousW2 = result.w2
  301.     }
  302.     if (result.containsKey("version")) {
  303.        events << createEvent(name:"firmware", value: result.version + "\r\n" + result.date, displayed: false)
  304.     }
  305.  
  306.     if (result.containsKey("success")) {
  307.        if (result.success == "true") state.configSuccess = "true" else state.configSuccess = "false"
  308.     }
  309.     if (result.containsKey("program")) {
  310.         if (result.running == "false") {
  311.             toggleTiles("all")
  312.         }
  313.         else {
  314.             toggleTiles("switch$result.program")
  315.             events << createEvent(name:"switch$result.program", value: "on")
  316.         }
  317.     }
  318.     //if (cmds != [] && events != null) return [events, response(cmds)] else if (cmds != []) return response(cmds) else return events
  319.     return events
  320. }
  321.  
  322. private toggleTiles(value) {
  323.    def tiles = ["switch1", "switch2", "switch3", "switch4", "switch5", "switch6"]
  324.    tiles.each {tile ->
  325.       if (tile != value) sendEvent(name: tile, value: "off")
  326.    }
  327. }
  328.  
  329. private getScaledColor(color) {
  330.    def rgb = color.findAll(/[0-9a-fA-F]{2}/).collect { Integer.parseInt(it, 16) }
  331.    def maxNumber = 1
  332.    for (int i = 0; i < 3; i++){
  333.      if (rgb[i] > maxNumber) {
  334.         maxNumber = rgb[i]
  335.      }
  336.    }
  337.    def scale = 255/maxNumber
  338.    for (int i = 0; i < 3; i++){
  339.      rgb[i] = rgb[i] * scale
  340.    }
  341.    def myred = rgb[0]
  342.    def mygreen = rgb[1]
  343.    def myblue = rgb[2]
  344.    return rgbToHex([r:myred, g:mygreen, b:myblue])
  345. }
  346.  
  347. def on() {
  348.     log.debug "on()"
  349.     postAction("/on?transition=$transition")
  350. }
  351.  
  352. def off() {
  353.     log.debug "off()"
  354.     postAction("/off?transition=$transition")
  355. }
  356.  
  357. def setLevel(level) {
  358.     setLevel(level, 1)
  359. }
  360.  
  361. def setLevel(level, duration) {
  362.     log.debug "setLevel() level = ${level}"
  363.     if(level > 100) level = 100
  364.     if (level == 0) { off() }
  365.     else if (device.latestValue("switch") == "off") { on() }
  366.     sendEvent(name: "level", value: level)
  367.     sendEvent(name: "setLevel", value: level, displayed: false)
  368.     setColor(aLevel: level)
  369. }
  370. def setSaturation(percent) {
  371.     log.debug "setSaturation($percent)"
  372.     setColor(saturation: percent)
  373. }
  374. def setHue(value) {
  375.     log.debug "setHue($value)"
  376.     setColor(hue: value)
  377. }
  378. def getWhite(value) {
  379.     log.debug "getWhite($value)"
  380.     def level = Math.min(value as Integer, 99)    
  381.     level = 255 * level/99 as Integer
  382.     log.debug "level: ${level}"
  383.     return hex(level)
  384. }
  385. def setColor(value) {
  386.     log.debug "setColor being called with ${value}"
  387.     def uri
  388.     def validValue = true
  389.  
  390.     if ( !(value.hex) && ((value.saturation) && (value.hue))) {
  391.         def hue = (value.hue != null) ? value.hue : 13
  392.         def saturation = (value.saturation != null) ? value.saturation : 13
  393.         def rgb = huesatToRGB(hue as Integer, saturation as Integer)
  394.         value.hex = rgbToHex([r:rgb[0], g:rgb[1], b:rgb[2]])
  395.     }
  396.    
  397.     if (value.hue == 23 && value.saturation == 56) {
  398.        log.debug "setting color Soft White"
  399.        def whiteLevel = getWhite(value.level)
  400.        uri = "/w1?value=${whiteLevel}"
  401.        state.previousColor = "${whiteLevel}"
  402.     }
  403.     else if (value.hue == 52 && value.saturation == 19) {
  404.        log.debug "setting color White"
  405.        def whiteLevel = getWhite(value.level)
  406.        uri = "/w1?value=${whiteLevel}"
  407.        state.previousColor = "${whiteLevel}"
  408.     }
  409.     else if (value.hue == 53 && value.saturation == 91) {
  410.        log.debug "setting color Daylight"
  411.        def whiteLevel = getWhite(value.level)
  412.        uri = "/w2?value=${whiteLevel}"
  413.        state.previousColor = "${whiteLevel}"
  414.     }
  415.     else if (value.hue == 20 && value.saturation == 80) {
  416.        log.debug "setting color Warm White"
  417.        def whiteLevel = getWhite(value.level)
  418.        uri = "/w1?value=${whiteLevel}"
  419.        state.previousColor = "${whiteLevel}"
  420.     }
  421.     else if (value.colorTemperature) {
  422.        log.debug "setting color with color temperature"
  423.        def whiteLevel = getWhite(value.level)
  424.        uri = "/w1?value=${whiteLevel}"
  425.        state.previousColor = "${whiteLevel}"
  426.     }
  427.     else if (value.hex) {
  428.        log.debug "setting color with hex"
  429.        if (!value.hex ==~ /^\#([A-Fa-f0-9]){6}$/) {
  430.            log.debug "$value.hex is not valid"
  431.            validValue = false
  432.        } else {
  433.            def rgb = value.hex.findAll(/[0-9a-fA-F]{2}/).collect { Integer.parseInt(it, 16) }
  434.            def myred = rgb[0] < 40 ? 0 : rgb[0]
  435.            def mygreen = rgb[1] < 40 ? 0 : rgb[1]
  436.            def myblue = rgb[2] < 40 ? 0 : rgb[2]
  437.            def dimmedColor = getDimmedColor(rgbToHex([r:myred, g:mygreen, b:myblue]))
  438.            uri = "/rgb?value=${dimmedColor.substring(1)}"
  439.        }
  440.     }
  441.     else if (value.white) {
  442.        uri = "/w1?value=${value.white}"
  443.     }
  444.     else if (value.aLevel) {
  445.         def actions = []
  446.         if (channels == "true") {
  447.            def skipColor = false
  448.            // Handle white channel dimmers if they're on or were not previously off (excluding power-off command)
  449.            if (device.currentValue("white1") == "on" || state.previousW1 != "00") {
  450.               actions.push(setWhite1Level(value.aLevel))
  451.               skipColor = true
  452.            }
  453.            if (device.currentValue("white2") == "on" || state.previousW2 != "00") {
  454.               actions.push(setWhite2Level(value.aLevel))
  455.               skipColor = true
  456.            }
  457.         if (skipColor == false) {
  458.         log.debug state.previousRGB
  459.            // if the device is currently on, scale the current RGB values; otherwise scale the previous setting
  460.            uri = "/rgb?value=${getDimmedColor(device.latestValue("switch") == "on" ? device.currentValue("color").substring(1) : state.previousRGB)}"
  461.            actions.push(postAction("$uri&channels=$channels&transition=$transition"))
  462.         }
  463.         } else {
  464.            // Handle white channel dimmers if they're on or were not previously off (excluding power-off command)
  465.            if (device.currentValue("white1") == "on" || state.previousW1 != "00")
  466.               actions.push(setWhite1Level(value.aLevel))
  467.            if (device.currentValue("white2") == "on" || state.previousW2 != "00")
  468.               actions.push(setWhite2Level(value.aLevel))
  469.        
  470.            // if the device is currently on, scale the current RGB values; otherwise scale the previous setting
  471.            uri = "/rgb?value=${getDimmedColor(device.latestValue("switch") == "on" ? device.currentValue("color").substring(1) : state.previousRGB)}"
  472.            actions.push(postAction("$uri&channels=$channels&transition=$transition"))
  473.         }
  474.         return actions
  475.     }
  476.     else {
  477.        // A valid color was not chosen. Setting to white
  478.        uri = "/w1?value=ff"
  479.     }
  480.    
  481.     if (uri != null && validValue != false) postAction("$uri&channels=$channels&transition=$transition")
  482.  
  483. }
  484.  
  485. private getDimmedColor(color, level) {
  486.    if(color.size() > 2){
  487.       def scaledColor = getScaledColor(color)
  488.       def rgb = scaledColor.findAll(/[0-9a-fA-F]{2}/).collect { Integer.parseInt(it, 16) }
  489.    
  490.       def r = hex(rgb[0] * (level.toInteger()/100))
  491.       def g = hex(rgb[1] * (level.toInteger()/100))
  492.       def b = hex(rgb[2] * (level.toInteger()/100))
  493.  
  494.       return "${r + g + b}"
  495.    }else{
  496.       color = Integer.parseInt(color, 16)
  497.       return hex(color * (level.toInteger()/100))
  498.    }
  499. }
  500.  
  501. private getDimmedColor(color) {
  502.    if (device.latestValue("level")) {
  503.       getDimmedColor(color, device.latestValue("level"))
  504.    } else {
  505.       return color
  506.    }
  507. }
  508.  
  509. def reset() {
  510.     log.debug "reset()"
  511.     setColor(white: "ff")
  512. }
  513.  
  514. def refresh() {
  515.     log.debug "refresh()"
  516.     postAction("/status")
  517. }
  518.  
  519. def ping() {
  520.     log.debug "ping()"
  521.     refresh()
  522. }
  523.  
  524. def setWhiteLevel(value) {
  525.     log.debug "setwhiteLevel: ${value}"
  526.     def level = Math.min(value as Integer, 99)    
  527.     level = 255 * level/99 as Integer
  528.     log.debug "level: ${level}"
  529.     if ( value > 0 ) {
  530.         if (device.latestValue("switch") == "off") { on() }
  531.         sendEvent(name: "white", value: "on")
  532.     } else {
  533.         sendEvent(name: "white", value: "off")
  534.     }
  535.     def whiteLevel = hex(level)
  536.     setColor(white: whiteLevel)
  537. }
  538.  
  539. def hexToRgb(colorHex) {
  540.     def rrInt = Integer.parseInt(colorHex.substring(1,3),16)
  541.     def ggInt = Integer.parseInt(colorHex.substring(3,5),16)
  542.     def bbInt = Integer.parseInt(colorHex.substring(5,7),16)
  543.    
  544.     def colorData = [:]
  545.     colorData = [r: rrInt, g: ggInt, b: bbInt]
  546.     colorData
  547. }
  548.  
  549. def huesatToRGB(float hue, float sat) {
  550.     while(hue >= 100) hue -= 100
  551.     int h = (int)(hue / 100 * 6)
  552.     float f = hue / 100 * 6 - h
  553.     int p = Math.round(255 * (1 - (sat / 100)))
  554.     int q = Math.round(255 * (1 - (sat / 100) * f))
  555.     int t = Math.round(255 * (1 - (sat / 100) * (1 - f)))
  556.     switch (h) {
  557.         case 0: return [255, t, p]
  558.         case 1: return [q, 255, p]
  559.         case 2: return [p, 255, t]
  560.         case 3: return [p, q, 255]
  561.         case 4: return [t, p, 255]
  562.         case 5: return [255, p, q]
  563.     }
  564. }
  565.  
  566. private hex(value, width=2) {
  567.     def s = new BigInteger(Math.round(value).toString()).toString(16)
  568.     while (s.size() < width) {
  569.         s = "0" + s
  570.     }
  571.     s
  572. }
  573. def rgbToHex(rgb) {
  574.     def r = hex(rgb.r)
  575.     def g = hex(rgb.g)
  576.     def b = hex(rgb.b)
  577.     def hexColor = "#${r}${g}${b}"
  578.    
  579.     hexColor
  580. }
  581.  
  582. def sync(ip, port) {
  583.     def existingIp = getDataValue("ip")
  584.     def existingPort = getDataValue("port")
  585.     if (ip && ip != existingIp) {
  586.         updateDataValue("ip", ip)
  587.         sendEvent(name: 'ip', value: ip)
  588.     }
  589.     if (port && port != existingPort) {
  590.         updateDataValue("port", port)
  591.     }
  592. }
  593.  
  594. private encodeCredentials(username, password){
  595.     def userpassascii = "${username}:${password}"
  596.     def userpass = "Basic " + userpassascii.encodeAsBase64().toString()
  597.     return userpass
  598. }
  599.  
  600. private postAction(uri){
  601.   log.debug "uri ${uri}"
  602.   updateDNI()
  603.  
  604.   def userpass
  605.  
  606.   if(password != null && password != "")
  607.     userpass = encodeCredentials("admin", password)
  608.    
  609.   def headers = getHeader(userpass)
  610.  
  611.   def hubAction = new physicalgraph.device.HubAction(
  612.     method: "GET",
  613.     path: uri,
  614.     headers: headers
  615.   )
  616.   hubAction    
  617. }
  618.  
  619. private setDeviceNetworkId(ip, port = null){
  620.     def myDNI
  621.     if (port == null) {
  622.         myDNI = ip
  623.     } else {
  624.         def iphex = convertIPtoHex(ip)
  625.         def porthex = convertPortToHex(port)
  626.        
  627.         myDNI = "$iphex:$porthex"
  628.     }
  629.     log.debug "Device Network Id set to ${myDNI}"
  630.     return myDNI
  631. }
  632.  
  633. private updateDNI() {
  634.     if (state.dni != null && state.dni != "" && device.deviceNetworkId != state.dni) {
  635.        device.deviceNetworkId = state.dni
  636.     }
  637. }
  638.  
  639. private getHostAddress() {
  640.     if(getDeviceDataByName("ip") && getDeviceDataByName("port")){
  641.         return "${getDeviceDataByName("ip")}:${getDeviceDataByName("port")}"
  642.     }else{
  643.         return "${ip}:80"
  644.     }
  645. }
  646.  
  647. private String convertIPtoHex(ipAddress) {
  648.     String hex = ipAddress.tokenize( '.' ).collect {  String.format( '%02x', it.toInteger() ) }.join()
  649.     return hex
  650. }
  651.  
  652. private String convertPortToHex(port) {
  653.     String hexport = port.toString().format( '%04x', port.toInteger() )
  654.     return hexport
  655. }
  656.  
  657. def parseDescriptionAsMap(description) {
  658.     description.split(",").inject([:]) { map, param ->
  659.         def nameAndValue = param.split(":")
  660.         map += [(nameAndValue[0].trim()):nameAndValue[1].trim()]
  661.     }
  662. }
  663.  
  664. private getHeader(userpass = null){
  665.     def headers = [:]
  666.     headers.put("Host", getHostAddress())
  667.     headers.put("Content-Type", "application/x-www-form-urlencoded")
  668.     if (userpass != null)
  669.        headers.put("Authorization", userpass)
  670.     return headers
  671. }
  672.  
  673. def toAscii(s){
  674.         StringBuilder sb = new StringBuilder();
  675.         String ascString = null;
  676.         long asciiInt;
  677.                 for (int i = 0; i < s.length(); i++){
  678.                     sb.append((int)s.charAt(i));
  679.                     sb.append("|");
  680.                     char c = s.charAt(i);
  681.                 }
  682.                 ascString = sb.toString();
  683.                 asciiInt = Long.parseLong(ascString);
  684.                 return asciiInt;
  685. }
  686.  
  687. def on1() { onOffCmd(1, 1) }
  688. def on2() { onOffCmd(1, 2) }
  689. def on3() { onOffCmd(1, 3) }
  690. def on4() { onOffCmd(1, 4) }
  691. def on5() { onOffCmd(1, 5) }
  692. def on6() { onOffCmd(1, 6) }
  693.  
  694. def off1(p=null) { onOffCmd((p == null ? 0 : p), 1) }
  695. def off2(p=null) { onOffCmd((p == null ? 0 : p), 2) }
  696. def off3(p=null) { onOffCmd((p == null ? 0 : p), 3) }
  697. def off4(p=null) { onOffCmd((p == null ? 0 : p), 4) }
  698. def off5(p=null) { onOffCmd((p == null ? 0 : p), 5) }
  699. def off6(p=null) { onOffCmd((p == null ? 0 : p), 6) }
  700.  
  701. def onOffCmd(value, program) {
  702.     log.debug "onOffCmd($value, $program)"
  703.     def uri
  704.     if (value == 1){
  705.        if(state."program${program}" != null) {
  706.           uri = "/program?value=${state."program${program}"}&number=$program"
  707.        }    
  708.     } else if(value == 0){
  709.        uri = "/stop"
  710.     } else {
  711.        uri = "/off"
  712.     }
  713.     if (uri != null) return postAction(uri)
  714. }
  715.  
  716. def setProgram(value, program){
  717.    state."program${program}" = value
  718. }
  719.  
  720. def hex2int(value){
  721.    return Integer.parseInt(value, 10)
  722. }
  723.  
  724.  
  725. def greenOn() {
  726.     log.debug "greenOn()"
  727.     postAction("/g?value=ff&channels=$channels&transition=$transition")
  728. }
  729. def greenOff() {
  730.     log.debug "greenOff()"
  731.     postAction("/g?value=00&channels=$channels&transition=$transition")
  732. }
  733.  
  734. def setGreenLevel(value) {
  735.     log.debug "setGreenLevel: ${value}"
  736.     def level = Math.min(value as Integer, 99)    
  737.     level = 255 * level/99 as Integer
  738.     log.debug "level: ${level}"
  739.     level = hex(level)
  740.     postAction("/g?value=$level&channels=$channels&transition=$transition")
  741. }
  742. def blueOn() {
  743.     log.debug "blueOn()"
  744.     postAction("/b?value=ff&channels=$channels&transition=$transition")
  745. }
  746. def blueOff() {
  747.     log.debug "blueOff()"
  748.     postAction("/b?value=00&channels=$channels&transition=$transition")
  749. }
  750.  
  751. def setBlueLevel(value) {
  752.     log.debug "setBlueLevel: ${value}"
  753.     def level = Math.min(value as Integer, 99)    
  754.     level = 255 * level/99 as Integer
  755.     log.debug "level: ${level}"
  756.     level = hex(level)
  757.     postAction("/b?value=$level&channels=$channels&transition=$transition")
  758. }
  759. def RedOn() {
  760.     log.debug "white1On()"
  761.     postAction("/w1?value=ff&channels=$channels&transition=$transition")
  762. }
  763. def RedOff() {
  764.     log.debug "white1Off()"
  765.     postAction("/w1?value=00&channels=$channels&transition=$transition")
  766. }
  767.  
  768. def setRedLevel(value) {
  769.     log.debug "setwhite1Level: ${value}"
  770.     def level = Math.min(value as Integer, 99)    
  771.     level = 255 * level/99 as Integer
  772.     log.debug "level: ${level}"
  773.     def whiteLevel = hex(level)
  774.     postAction("/w1?value=$whiteLevel&channels=$channels&transition=$transition")
  775. }
  776. def White2On() {
  777.     log.debug "white2On()"
  778.     postAction("/w2?value=ff&channels=$channels&transition=$transition")
  779. }
  780. def white2Off() {
  781.     log.debug "white2Off()"
  782.     postAction("/w2?value=00&channels=$channels&transition=$transition")
  783. }
  784.  
  785. def setWhite2Level(value) {
  786.     log.debug "setwhite2Level: ${value}"
  787.     def level = Math.min(value as Integer, 99)    
  788.     level = 255 * level/99 as Integer
  789.     log.debug "level: ${level}"
  790.     def whiteLevel = hex(level)
  791.     postAction("/w2?value=$whiteLevel&channels=$channels&transition=$transition")
  792. }
  793.  
  794. private getHexColor(value){
  795. def color = ""
  796.   switch(value){
  797.     case "Previous":
  798.     color = "Previous"
  799.     break;
  800.     case "White":
  801.     color = "ffffff"
  802.     break;
  803.     case "Daylight":
  804.     color = "ffffff"
  805.     break;
  806.     case "Soft White":
  807.     color = "ff"
  808.     break;
  809.     case "Warm White":
  810.     color = "ff"
  811.     break;
  812.     case "Blue":
  813.     color = "0000ff"
  814.     break;
  815.     case "Green":
  816.     color = "00ff00"
  817.     break;
  818.     case "Yellow":
  819.     color = "ffff00"
  820.     break;
  821.     case "Orange":
  822.     color = "ff5a00"
  823.     break;
  824.     case "Purple":
  825.     color = "5a00ff"
  826.     break;
  827.     case "Pink":
  828.     color = "ff00ff"
  829.     break;
  830.     case "Cyan":
  831.     color = "00ffff"
  832.     break;
  833.     case "Red":
  834.     color = "ff0000"
  835.     break;
  836.     case "Off":
  837.     color = "000000"
  838.     break;
  839.     case "Random":
  840.     color = "xxxxxx"
  841.     break;
  842. }
  843.    return color
  844. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement