├── _devices.php ├── README.md ├── index.html └── govee-device-handler.groovy /_devices.php: -------------------------------------------------------------------------------- 1 |
';
 4 | 	print_r($_REQUEST);
 5 | 	print '
'; 6 | die; 7 | //*/ 8 | 9 | $curl = curl_init(); 10 | 11 | curl_setopt_array($curl, array( 12 | CURLOPT_URL => 'https://developer-api.govee.com/v1/devices', 13 | CURLOPT_RETURNTRANSFER => true, 14 | CURLOPT_ENCODING => '', 15 | CURLOPT_MAXREDIRS => 10, 16 | CURLOPT_TIMEOUT => 0, 17 | CURLOPT_FOLLOWLOCATION => true, 18 | CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, 19 | CURLOPT_CUSTOMREQUEST => 'GET', 20 | CURLOPT_HTTPHEADER => array( 21 | 'Govee-API-Key: ' . trim($_REQUEST['Govee-API-Key']), 22 | ), 23 | )); 24 | 25 | $response = curl_exec($curl); 26 | 27 | curl_close($curl); 28 | 29 | header('Content-Type: application/json; charset=utf-8'); 30 | print json_encode($response); 31 | exit; 32 | ?> -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # smartthings-govee-led-lights 2 | Govee LED Light Strips integration for Samsung SmartThings 3 | 4 | ## UPDATED AS OF 2022-10-04 5 | Govee has began limiteding the number of API calls an account is allotted to have. This happened back in May 2022, however it is being fully implemented now and is affecting users with multiple Govee devices accessing the API. 6 | So this release (v2) updates with a parameter setting that allows the user to set their own "polling" time (in seconds). 7 | 8 | ### Pre-requisites 9 | Must have a Samsung SmartThings account setup (https://account.smartthings.com) 10 | Govee LED Light Strips 11 | Govee API Key (generated from the Govee mobile app) 12 | 13 | ### To integrate this into SmartThings, you'll follow these steps: 14 | ![#f03c15](https://via.placeholder.com/15/f03c15/000000?text=+) To properly integration into Samsung SmartThings, please go to the following URL: https://www.deanberman.com/govee/smartthings/ 15 | This page will provide you step-by-step procedures on add the device and device type handlers into your SmartThings account. You provide it your Govee API Key and it will retrieve the list of device ids, names, and models for the device preferences. 16 | 17 | If you are more comfortable running the file(s) locally and have a webservice and php enabled locally, then you may download the index.html and the \_devices.php file and implement them locally (just update the index.html file for the URL reference location). 18 | 19 | #### The following list of model numbers are currently supported (according to Govee API document): 20 | Lights, Plugs, Switches: 21 | H6160, H6163, H6104, H6109, H6110, H6117, H6159, H7022, H6086, 22 | H6089, H6182, H6085, H7014, H5081, H6188, H6135, H6137, H6141, 23 | H6142, H6195, H7005, H6083, H6002, H6003, H6148, H6052, H6143, 24 | H6144, H6050, H6199, H6054, H5001, H6154, H6072, H6121, H611A, 25 | H5080, H6062, H614C, H615A, H615B, H7020, H7021, H614D, H611Z, 26 | H611B, H611C, H615C, H615D, H7006, H7007, H7008, H7012, H7013, 27 | H7050, H6051, H6056, H6061, H6058, H6073, H6076, H619A, H619C, 28 | H618A, H618C, H6008, H6071, H6075, H614A, H614B, H614E, H618E, 29 | H619E, H605B, H6087, H6172, H619B, H619D, H619Z, H61A0, H7060, 30 | H610A, H6059, H7028, H6198, H6049, H7031, H7032, H61A1, H61A2, 31 | H61B2, H7061, H6067, H6066, H6009, H7041, H7042, H604A, H6173, 32 | H615E, H604B, H6091, H7051, H7062, H618F, H605D, H6046, H601A, 33 | H61A3, H610B, H6047, H7065, H61E1, H6057, H604C, H6065, H605C, 34 | H705A, H705B, H7055, H61A5, H6078, H604D, H6168, H6601, H70B1, 35 | H61A8 36 | 37 | Appliances: 38 | H7121, H7122, H7123, H7120, H7141, H7142, H7130, H7131, H7132, 39 | H7150, H7160, H7101, H7111 40 | 41 | ### DEBUGGING/TROUBLESHOOTING 42 | If you edit the device type handler in your Samsung SmartThings account, search for the "refresh()" function and enable debugging by setting the following: 43 | ```groovy 44 | set_DEBUG("off") 45 | ...to... 46 | set_DEBUG("on") 47 | ``` 48 | 49 | ### DTH DISCLAIMER 50 | After further testing, the API call for getting the device state may not work for all supported Govee models listed above. Determing if it's a problem with the Govee API or if it's not supported due to the nature of the device model. 51 | 52 | ### DISCLOSURE 53 | I am not SmartThings developer, I just did this because I wanted to be able to integrate my multiple Govee LED Light strips into my Smart home network, so I created this myself. It works well for me and this isn't for sale, so feel free to use it, tweak it, whatever you want! 54 | Just a heads up, this isn't perfect by any means, so feel free to provide me some input and updates, I'll be happy to make them! 55 | 56 | ### SPECIAL THANKS 57 | Those who have downloaded the DTH and are testing with it, thanks so much and please reach out to me with any questions or comments, I'm using this DTH daily so updating it will make me very happy with new features! 58 | 59 | And an even more thanks to **@jc73uk** for your contribution to the app integration! Your support will help further the development and integration of this DTH and other devices which may/may not be supported as of yet with Govee! 60 | 61 | Enjoy! 62 | 63 | -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | Govee LED Lights - Device Configuration 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 92 | 93 | 94 |
95 |

Govee LED Lights - Device Configuration

96 |

DB Development - Dean Berman

97 |
Created/Last Updated: 2020-11-09
98 |
99 | 100 |
IMPORTANT: This is not sponsered or paid for or supported by Govee, this was generated to help anyone else [other than just myself] to get the amazing WiFi Govee LED Lights into Samsung SmartThings for integration, automation, smart panels, ActionTiles, SharpTools, etc.
101 |
102 | 103 | 108 | 109 |
110 |
111 |
112 |
113 | The Govee LED Lights SmartThings Device Type Handler was generated to fill a need with accessing the WiFi connected Govee LED Lights. 114 |

115 | The Device Type Handler is built to handle any of the existing WiFi connected Govee LED Lights that are accesible through their API. 116 |

117 | The following list of model numbers are currently supported: 118 |
    119 |
  • H6160
  • 120 |
  • H6163
  • 121 |
  • H6104
  • 122 |
  • H6109
  • 123 |
  • H6110
  • 124 |
  • H6117
  • 125 |
  • H6159
  • 126 |
  • H7021
  • 127 |
  • H7022
  • 128 |
  • H6086
  • 129 |
  • H6089
  • 130 |
  • H6182
  • 131 |
  • H6085
  • 132 |
  • H7014
  • 133 |
  • H5081
  • 134 |
  • H6188
  • 135 |
  • H6135
  • 136 |
  • H6137
  • 137 |
  • H6141
  • 138 |
  • H6142
  • 139 |
  • H6195
  • 140 |
  • H6196
  • 141 |
  • H7005
  • 142 |
  • H6083
  • 143 |
  • H6002
  • 144 |
  • H6003
  • 145 |
  • H6148
  • 146 |
147 |
148 | To get your Govee LED Lights device setup properly within Samsung SmartThings, please follow the steps below. 149 |
150 |

Govee API Key

151 |
    152 |
  1. Open the Govee Home app on your mobile device.
  2. 153 |
  3. In the navigation, go to the user/profile page by clicking on the user icon.
  4. 154 |
  5. In the My Profile page, select About Us.
  6. 155 |
  7. In the About Us page, select Apply for API Key.
  8. 156 |
  9. Fill in the form on the Apply for API Key page to retrieve a unique API key for your Govee user account.
  10. 157 |
  11. 158 | Click [Submit] to apply. 159 |
    160 | You will receive an email from Govee soon with your unique API key. 161 |
  12. 162 |
163 | 164 |

Device Type Handler

165 |
    166 |
  1. 167 | Login to the Samsung SmartThings account management interface: 168 | https://account.smartthings.com/login 169 |
  2. 170 |
  3. In the SmartThings Groovy IDE, navigate to the My Device Handlers link/page.
  4. 171 |
  5. In the Device Handlers page, click the [+ Create New Device Handler] button.
  6. 172 |
  7. In the Create New Device Handler page, select the From Code tab.
  8. 173 |
  9. From the DB Development Govee LED Strips (DBDEV) GitHub page, copy-and-paste in the code for the Device Type Handler in this form/page.
  10. 174 |
  11. Click [Create] to save and continue.
  12. 175 |
176 | 177 |

Device

178 |
    179 |
  1. 180 | Login to the Samsung SmartThings account management interface: 181 | https://account.smartthings.com/login 182 |
  2. 183 |
  3. In the SmartThings Groovy IDE, navigate to the My Devices link/page.
  4. 184 |
  5. In the Devices page, click the [+ New Device] button.
  6. 185 |
  7. 186 | In the Create Device page, setup the following settings: 187 |
      188 |
    • Name: Setup your device name accordingly
    • 189 |
    • Label: I usually just use the same Name
    • 190 |
    • Zigbee Id: <leave blank>
    • 191 |
    • Device Network Id: Use something that is only characters and dashes or underscores (something unique)
    • 192 |
    • Type: Select Govee LED Strips (DBDEV) from the dropdown list
    • 193 |
    • Version: Select Self-Published
    • 194 |
    • Location: Select Home (or whatever your location name is)
    • 195 |
    • Hub: Select SmartThings Hub (or whatever your hub name is)
    • 196 |
    • Group: <leave blank>
    • 197 |
    198 | Once completed, click [Create]. 199 |
  8. 200 |
  9. Once the page reloads, in the left column, for Preferences, click edit.
  10. 201 |
  11. 202 | In the edit preferences page, 3 form fields will be preset. Set each of these form fields accordingly below: 203 |
      204 |
    • Govee API Key - Designated Govee API Key for accessing their system - this value is given to you by Govee from their app (should be found on the Configuration tab)
    • 205 |
    • Govee KED Device ID - Device ID for the Govee LED Lights - can be found on the Configuration tab
    • 206 |
    • Govee LED Model - Model number of the Govee LED Lights - can be found on the Configuration tab
    • 207 |
    208 |
  12. 209 |
  13. Once completed, click [Save].
  14. 210 |
211 |
212 |
213 |
214 |
215 |
216 |
217 | The following form/details below will allow you to confirm your Samsung SmartThings Device preferences accordingly. 218 |

219 | 220 | Designated Govee API Key for accessing their system 221 |

222 | 223 |
224 |
225 |
226 |
227 |
228 |
229 | 230 | 231 | -------------------------------------------------------------------------------- /govee-device-handler.groovy: -------------------------------------------------------------------------------- 1 | /** 2 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except 3 | * in compliance with the License. You may obtain a copy of the License at: 4 | * 5 | * http://www.apache.org/licenses/LICENSE-2.0 6 | * 7 | * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed 8 | * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License 9 | * for the specific language governing permissions and limitations under the License. 10 | * 11 | */ 12 | metadata { 13 | definition ( 14 | name: "Govee LED Strips (DBDEV)", 15 | version: "v2", 16 | namespace: "dbdevelopment", 17 | author: "Dean Berman", 18 | description: "Govee LED Strips Integration", 19 | category: "My Apps", 20 | ) { 21 | 22 | capability "Switch Level" 23 | capability "Actuator" 24 | capability "Color Control" 25 | // capability "Power Meter" 26 | capability "Switch" 27 | capability "Refresh" 28 | capability "Sensor" 29 | 30 | command "setAdjustedColor" 31 | command "reset" 32 | command "refresh" 33 | } 34 | 35 | tiles(scale: 2) { 36 | multiAttributeTile(name:"switch", type: "lighting", width: 6, height: 4, canChangeIcon: true) { 37 | tileAttribute ("device.switch", key: "PRIMARY_CONTROL") { 38 | attributeState "on", label:'${name}', action:"switch.off", icon:"st.lights.philips.hue-single", backgroundColor:"#00A0DC", nextState:"turningOff" 39 | attributeState "off", label:'${name}', action:"switch.on", icon:"st.lights.philips.hue-single", backgroundColor:"#ffffff", nextState:"turningOn" 40 | attributeState "turningOn", label:'${name}', action:"switch.off", icon:"st.lights.philips.hue-single", backgroundColor:"#00A0DC", nextState:"turningOff" 41 | attributeState "turningOff", label:'${name}', action:"switch.on", icon:"st.lights.philips.hue-single", backgroundColor:"#ffffff", nextState:"turningOn" 42 | } 43 | tileAttribute ("device.power", key: "SECONDARY_CONTROL") { 44 | attributeState "power", label:'Power level: ${currentValue}W', icon: "st.Appliances.appliances17" 45 | } 46 | tileAttribute ("device.level", key: "SLIDER_CONTROL") { 47 | attributeState "level", action:"switch level.setLevel" 48 | } 49 | tileAttribute ("device.color", key: "COLOR_CONTROL") { 50 | attributeState "color", action:"setAdjustedColor" 51 | } 52 | } 53 | 54 | multiAttributeTile(name:"switchNoPower", type: "lighting", width: 6, height: 4, canChangeIcon: true) { 55 | tileAttribute ("device.switch", key: "PRIMARY_CONTROL") { 56 | attributeState "on", label:'${name}', action:"switch.off", icon:"st.lights.philips.hue-single", backgroundColor:"#00A0DC", nextState:"turningOff" 57 | attributeState "off", label:'${name}', action:"switch.on", icon:"st.lights.philips.hue-single", backgroundColor:"#ffffff", nextState:"turningOn" 58 | attributeState "turningOn", label:'${name}', action:"switch.off", icon:"st.lights.philips.hue-single", backgroundColor:"#00A0DC", nextState:"turningOff" 59 | attributeState "turningOff", label:'${name}', action:"switch.on", icon:"st.lights.philips.hue-single", backgroundColor:"#ffffff", nextState:"turningOn" 60 | } 61 | tileAttribute ("device.level", key: "SLIDER_CONTROL") { 62 | attributeState "level", action:"switch level.setLevel" 63 | } 64 | tileAttribute ("device.color", key: "COLOR_CONTROL") { 65 | attributeState "color", action:"setAdjustedColor" 66 | } 67 | } 68 | 69 | multiAttributeTile(name:"switchNoSlider", type: "lighting", width: 6, height: 4, canChangeIcon: true) { 70 | tileAttribute ("device.switch", key: "PRIMARY_CONTROL") { 71 | attributeState "on", label:'${name}', action:"switch.off", icon:"st.lights.philips.hue-single", backgroundColor:"#00A0DC", nextState:"turningOff" 72 | attributeState "off", label:'${name}', action:"switch.on", icon:"st.lights.philips.hue-single", backgroundColor:"#ffffff", nextState:"turningOn" 73 | attributeState "turningOn", label:'${name}', action:"switch.off", icon:"st.lights.philips.hue-single", backgroundColor:"#00A0DC", nextState:"turningOff" 74 | attributeState "turningOff", label:'${name}', action:"switch.on", icon:"st.lights.philips.hue-single", backgroundColor:"#ffffff", nextState:"turningOn" 75 | } 76 | tileAttribute ("device.power", key: "SECONDARY_CONTROL") { 77 | attributeState "power", label:'The power level is currently: ${currentValue}W', icon: "st.Appliances.appliances17" 78 | } 79 | tileAttribute ("device.color", key: "COLOR_CONTROL") { 80 | attributeState "color", action:"setAdjustedColor" 81 | } 82 | } 83 | 84 | multiAttributeTile(name:"switchNoSliderOrColor", type: "lighting", width: 6, height: 4, canChangeIcon: true) { 85 | tileAttribute ("device.switch", key: "PRIMARY_CONTROL") { 86 | attributeState "on", label:'${name}', action:"switch.off", icon:"st.lights.philips.hue-single", backgroundColor:"#00A0DC", nextState:"turningOff" 87 | attributeState "off", label:'${name}', action:"switch.on", icon:"st.lights.philips.hue-single", backgroundColor:"#ffffff", nextState:"turningOn" 88 | attributeState "turningOn", label:'${name}', action:"switch.off", icon:"st.lights.philips.hue-single", backgroundColor:"#00A0DC", nextState:"turningOff" 89 | attributeState "turningOff", label:'${name}', action:"switch.on", icon:"st.lights.philips.hue-single", backgroundColor:"#ffffff", nextState:"turningOn" 90 | } 91 | tileAttribute ("device.power", key: "SECONDARY_CONTROL") { 92 | attributeState "power", label:'The light is currently consuming this amount of power: ${currentValue}W', icon: "st.Appliances.appliances17" 93 | } 94 | } 95 | 96 | valueTile("color", "device.color", inactiveLabel: false, decoration: "flat", width: 2, height: 2) { 97 | state "color", label: '${currentValue}' 98 | } 99 | 100 | standardTile("reset", "device.reset", inactiveLabel: false, decoration: "flat", width: 2, height: 2) { 101 | state "reset", label:"Reset Color", action:"reset", icon:"st.lights.philips.hue-single", defaultState: true 102 | } 103 | standardTile("refresh", "device.switch", inactiveLabel: false, decoration: "flat", width: 2, height: 2) { 104 | state "refresh", label:"", action:"refresh.refresh", icon:"st.secondary.refresh", defaultState: true 105 | } 106 | 107 | main(["switch"]) 108 | details(["switch", "switchNoPower", "switchNoSlider", "switchNoSliderOrColor", "color", "refresh", "reset"]) 109 | } 110 | } 111 | 112 | preferences { 113 | section("Govee LED Device") { 114 | // TODO: put inputs here 115 | input("apikey", "apikey", title: "Govee API Key", description: "Designated Govee API Key for accessing their system", required: true) 116 | input("deviceID", "deviceid", title: "Govee KED Device ID", description: "Device ID for the Govee LED Lights", required: true) 117 | input("modelNum", "modelnum", title: "Govee LED Model", description: "Model number of the Govee LED Lights", required: true) 118 | input("refreshTimeSec", "refreshTimeSec", title: "Polling/Refresh Time", description: "Number of seconds between refreshing (minimum 300)", required: true) 119 | } 120 | } 121 | 122 | // parse events into attributes 123 | def parse(description) { 124 | log.trace "Executing 'parse($description)'..." 125 | 126 | def results = [] 127 | def map = description 128 | if (description instanceof String) { 129 | log.debug "Hue Bulb stringToMap - ${map}" 130 | map = stringToMap(description) 131 | } 132 | if (map?.name && map?.value) { 133 | results << createEvent(name: "${map?.name}", value: "${map?.value}") 134 | } 135 | results 136 | } 137 | 138 | // handle commands 139 | def on() { 140 | log.trace "Executing 'on()'..." 141 | 142 | callURL('devicecontrol-power', "on") 143 | 144 | sendEvent(name: "switch", value: "on") 145 | } 146 | 147 | def off() { 148 | log.trace "Executing 'off()'..." 149 | 150 | callURL('devicecontrol-power', "off") 151 | 152 | sendEvent(name: "switch", value: "off") 153 | } 154 | 155 | def nextLevel() { 156 | log.trace "Executing 'nextLevel()'..." 157 | 158 | def level = device.latestValue("level") as Integer ?: 0 159 | if (level <= 100) { 160 | level = Math.min(25 * (Math.round(level / 25) + 1), 100) as Integer 161 | } 162 | else { 163 | level = 25 164 | } 165 | setLevel(level) 166 | } 167 | 168 | def setLevel(percent, rate = null) { 169 | log.trace "Executing 'setLevel($percent, this)'..." 170 | 171 | sendEvent(name: "level", value: percent) 172 | def power = Math.round(percent / 1.175) * 0.1 173 | 174 | callURL('devicecontrol-brightness', percent) 175 | 176 | // sendEvent(name: "power", value: power) 177 | } 178 | 179 | def setSaturation(percent) { 180 | log.trace "Executing 'setSaturation($percent)'..." 181 | 182 | sendEvent(name: "saturation", value: percent) 183 | } 184 | 185 | def setHue(percent) { 186 | log.trace "Executing 'setHue($percent)'..." 187 | 188 | sendEvent(name: "hue", value: percent) 189 | } 190 | 191 | def setColor(value) { 192 | log.trace "Executing 'setColor($value)'..." 193 | 194 | if (value.hue) { sendEvent(name: "hue", value: value.hue)} 195 | if (value.saturation) { sendEvent(name: "saturation", value: value.saturation)} 196 | if (value.hex) { sendEvent(name: "color", value: value.hex)} 197 | if (value.level) { sendEvent(name: "level", value: value.level)} 198 | if (value.switch) { sendEvent(name: "switch", value: value.switch)} 199 | 200 | def rgb 201 | // state.staged << value.subMap("hue", "saturation") // stage ST hue and saturation attributes 202 | def hex = colorUtil.hsvToHex(Math.round(value.hue) as int, Math.round(value.saturation) as int) // convert to hex 203 | log.trace "HEX=${hex}" 204 | // state.staged << [color: hex] // stage ST RGB color attribute 205 | rgb = colorUtil.hexToRgb(hex) // separate RGB elements for zwave setter 206 | callURL('devicecontrol-rgb', rgb) 207 | } 208 | 209 | def reset() { 210 | log.trace "Executing 'reset()'..." 211 | 212 | setAdjustedColor([level:100, hex:"#90C638", saturation:56, hue:23]) 213 | } 214 | 215 | def setAdjustedColor(value) { 216 | log.trace "Executing 'setAdjustedColor($value)'..." 217 | 218 | if (value) { 219 | log.trace "setAdjustedColor: ${value}" 220 | def adjusted = value + [:] 221 | adjusted.hue = adjustOutgoingHue(value.hue) 222 | // Needed because color picker always sends 100 223 | adjusted.level = null 224 | setColor(adjusted) 225 | } 226 | } 227 | 228 | def installed() { 229 | log.trace "Executing 'installed()'.." 230 | refresh() 231 | } 232 | 233 | def updated() { 234 | log.trace "Executing 'updated()'.." 235 | refresh() 236 | 237 | // unschedule() 238 | // runEvery1Minutes(refresh) 239 | // runIn(2, refresh) 240 | } 241 | 242 | def poll() { 243 | log.trace "Executing 'poll()'..." 244 | 245 | refresh() 246 | } 247 | 248 | def refresh() { 249 | log.trace "Executing 'refresh()'..." 250 | 251 | def ret = callURL('devicestate', '') 252 | 253 | // Handling the power state 254 | def power = ret.data["properties"][1]["powerState"] 255 | // log.debug "POWER=${power}" 256 | sendEvent(name: "switch", value: power) 257 | 258 | // Handling the brightness level 259 | def brightness = ret.data["properties"][2]["brightness"] 260 | // log.debug "BRIGHTNESS=${brightness}" 261 | sendEvent(name: "level", value: brightness) 262 | 263 | // Handling the color 264 | def rgb = [ret.data["properties"][3]["color"]["r"], ret.data["properties"][3]["color"]["g"], ret.data["properties"][3]["color"]["b"]] 265 | // log.debug "RGB=${rgb}" 266 | def hex = colorUtil.rgbToHex(rgb[0], rgb[1], rgb[2]) 267 | // log.debug "HEX=${hex}" 268 | sendEvent(name: "color", value: hex) 269 | 270 | // unschedule() 271 | // Set it to run every 5 minutes 272 | // runEvery5Minutes(refresh) 273 | // Set it to run once a minute (continuous polling) 274 | // runEvery1Minute(refresh) 275 | 276 | unschedule() 277 | // Set it to run once a minute (continuous polling) 278 | if(get_DEBUG() == "on") { log.debug "[refresh()] ---- Polling/Refresh every ${settings.refreshTimeSec}" } 279 | runIn(settings.refreshTimeSec as int, refresh) 280 | } 281 | 282 | def adjustOutgoingHue(percent) { 283 | log.trace "Executing 'adjustOutgoingHue($percent)'..." 284 | 285 | def adjusted = percent 286 | if (percent > 31) { 287 | if (percent < 63.0) { 288 | adjusted = percent + (7 * (percent -30 ) / 32) 289 | } 290 | else if (percent < 73.0) { 291 | adjusted = 69 + (5 * (percent - 62) / 10) 292 | } 293 | else { 294 | adjusted = percent + (2 * (100 - percent) / 28) 295 | } 296 | } 297 | log.info "percent: $percent, adjusted: $adjusted" 298 | adjusted 299 | } 300 | 301 | 302 | 303 | 304 | 305 | 306 | 307 | 308 | 309 | 310 | 311 | 312 | // TODO: implement event handlers 313 | def callURL(apiAction, details) { 314 | log.trace "Executing 'callURL($apiAction, $details)'..." 315 | 316 | // log.trace "[SETTINGS] APIKEY=${settings.apikey}, ID=${settings.deviceID}, MODEL=${settings.modelNum}" 317 | 318 | def params 319 | if(apiAction == 'devices') { 320 | params = [ 321 | method: 'GET', 322 | uri : "https://developer-api.govee.com", 323 | path : '/v1/devices', 324 | headers: ["Govee-API-Key": settings.apikey, "Content-Type": "application/json"], 325 | ] 326 | } else if(apiAction == 'devicestate') { 327 | params = [ 328 | method: 'GET', 329 | uri : "https://developer-api.govee.com", 330 | path : '/v1/devices/state', 331 | headers: ["Govee-API-Key": settings.apikey, "Content-Type": "application/json"], 332 | query: [device: settings.deviceID, model: settings.modelNum], 333 | ] 334 | } else if(apiAction == 'devicecontrol-power') { 335 | params = [ 336 | method: 'PUT', 337 | uri : "https://developer-api.govee.com", 338 | path : '/v1/devices/control', 339 | headers: ["Govee-API-Key": settings.apikey, "Content-Type": "application/json"], 340 | contentType: "application/json", 341 | body: [device: settings.deviceID, model: settings.modelNum, cmd: ["name": "turn", "value": details]], 342 | ] 343 | } else if(apiAction == 'devicecontrol-brightness') { 344 | params = [ 345 | method: 'PUT', 346 | uri : "https://developer-api.govee.com", 347 | path : '/v1/devices/control', 348 | headers: ["Govee-API-Key": settings.apikey, "Content-Type": "application/json"], 349 | contentType: "application/json", 350 | body: [device: settings.deviceID, model: settings.modelNum, cmd: ["name": "brightness", "value": details]], 351 | ] 352 | } else if(apiAction == 'devicecontrol-rgb') { 353 | params = [ 354 | method: 'PUT', 355 | uri : "https://developer-api.govee.com", 356 | path : '/v1/devices/control', 357 | headers: ["Govee-API-Key": settings.apikey, "Content-Type": "application/json"], 358 | contentType: "application/json", 359 | body: [device: settings.deviceID, model: settings.modelNum, cmd: ["name": "color", "value": ["r": details[0], "g": details[1], "b": details[2]]]], 360 | ] 361 | } 362 | 363 | /* 364 | log.debug params 365 | log.debug "APIACTION=${apiAction}" 366 | log.debug "METHOD=${params.method}" 367 | log.debug "URI=${params.uri}${params.path}" 368 | log.debug "HEADERS=${params.headers}" 369 | log.debug "QUERY=${params.query}" 370 | log.debug "BODY=${params.body}" 371 | //*/ 372 | 373 | try { 374 | if(params.method == 'GET') { 375 | httpGet(params) { resp -> 376 | //log.debug "RESP=" 377 | //log.debug "HEADERS="+resp.headers 378 | //log.debug "DATA="+resp.data 379 | 380 | log.debug "response.data="+resp.data 381 | 382 | return resp.data 383 | } 384 | } else if(params.method == 'PUT') { 385 | httpPutJson(params) { resp -> 386 | //log debug "RESP=" 387 | //log.debug "HEADERS="+resp.headers 388 | //log.debug "DATA="+resp.data 389 | 390 | log.debug "response.data="+resp.data 391 | 392 | return resp.data 393 | } 394 | } 395 | } catch (groovyx.net.http.HttpResponseException e) { 396 | log.error "callURL() >>>>>>>>>>>>>>>> ERROR >>>>>>>>>>>>>>>>" 397 | log.error "Error: e.statusCode ${e.statusCode}" 398 | log.error "${e}" 399 | log.error "callURL() <<<<<<<<<<<<<<<< ERROR <<<<<<<<<<<<<<<<" 400 | 401 | return 'unknown' 402 | } 403 | } 404 | --------------------------------------------------------------------------------