diff --git a/apps/BOND_Home_Integration.groovy b/apps/BOND_Home_Integration.groovy index 1622d3d..2a998b4 100644 --- a/apps/BOND_Home_Integration.groovy +++ b/apps/BOND_Home_Integration.groovy @@ -6,17 +6,18 @@ * Copyright 2019-2020 Dominick Meglio * * Revision History - * 2020.01.18 - Added setPosition support for motorized shades, mapping a special value of 50 to the Preset command - * 2019.12.01 - Fixed an issue where dimmers wouldn't work with fans that support direction controls, fixed an issue setting flame height * 2019.11.24 - Added support for timer based fan light dimmers and flame height adjustment for fireplaces + * 2019.12.01 - Fixed an issue where dimmers wouldn't work with fans that support direction controls, fixed an issue setting flame height * 2019.12.14 - Added support for Switch capability to the motorized shades for compatibility * 2020.01.02 - Fixed an issue where fan speed wouldn't be set properly (thanks jchurch for the troubleshooting!) + * 2020.01.18 - Added setPosition support for motorized shades, mapping a special value of 50 to the Preset command * 2020.02.01 - Fixed an issue where looking for devices was incorrect which broke Smart By BOND devices (thanks mcneillk for the fix!) * 2020.03.23 - Added the ability to fix device state when it's out of sync (thanks stephen_nutt for the suggestion) * 2020.04.13 - Added a stop command to motorized shades to stop an open/close at the current position (suggested by jchurch) * 2020.04.21 - Added better logging for connection issues to the hub * 2020.05.04 - Error logging improvements * 2020.06.28 - Added toggle command to all devices (suggested by jchurch) and support for having multiple Smart by BOND devices (discovered by jhciotti) + * 2022.05/22 - (matt1097) Improve polling time to cron string conversion logic * */ @@ -39,11 +40,37 @@ preferences { } def prefHub() { + def refreshList = [:] + refreshList[0] = "Never" + refreshList[1] = "1 Second" + refreshList[2] = "2 Second" + refreshList[3] = "3 Second" + refreshList[4] = "4 Second" + refreshList[5] = "5 Second" + refreshList[6] = "6 Second" + refreshList[10] = "10 Second" + refreshList[15] = "15 Second" + refreshList[20] = "20 Second" + refreshList[30] = "30 Second" + refreshList[60] = "1 Minute" + refreshList[300] = "5 Minute" + refreshList[600] = "10 Minute" + refreshList[900] = "15 Minute" + refreshList[1200] = "20 Minute" + refreshList[1800] = "30 Minute" + refreshList[3600] = "1 Hour" + refreshList[7200] = "2 Hour" + refreshList[10800] = "3 Hour" + refreshList[14400] = "4 Hour" + refreshList[21600] = "6 Hour" + refreshList[43200] = "12 Hour" + refreshList[86400] = "Daily" + return dynamicPage(name: "prefHub", title: "Connect to BOND", nextPage:"prefListDevices", uninstall:false, install: false) { section("Hub Information"){ input("hubIp", "text", title: "BOND Hub IP", description: "BOND Hub IP Address", required: true) input("hubToken", "text", title: "BOND Hub Token", description: "BOND Hub Token", required: true) - input("refreshInterval", "number", title: "Poll BOND Home every N seconds", required: true, defaultValue: 30) + input("refreshInterval", "enum", title: "Poll BOND Home every:", required: true, multiple: false, options: refreshList, defaultValue: "5 Minute") input("debugOutput", "bool", title: "Enable debug logging?", defaultValue: true, displayDuringSetup: false, required: false) } displayFooter() @@ -125,8 +152,34 @@ def initialize() { createChildDevices() subscribeSensorEvents() - def refreshEvery = refreshInterval ?: 30 - schedule("0/${refreshEvery} * * * * ? *", updateDevices) + def refreshEvery = (refreshInterval ?: 30) as int + if (refreshEvery > 0 ) { + def cronStr = calculateCron(refreshEvery) + schedule(cronStr, updateDevices) + } +} + +def calculateCron(refreshEvery) { + //60 seconds in a minute + //3600 seconds in a hour + //86400 in a day + + //truncated to a whole minute/hour/day + if (refreshEvery < 60) { + return "0/${refreshEvery} * * * * ? *" + } + else if (refreshEvery < 3600) { + def mins = refreshEvery.intdiv(60) + return "0 0/${mins} * * * ? *" + } + else if (refreshEvery < 86400) { + def hours = refreshEvery.intdiv(3600) + return "0 0 0/${hours} * * ? *" + } + else { + //check at 3 am every day, once a day. + return "* * 3 1/1 * ? *" + } } def getHubId() { @@ -371,8 +424,14 @@ def createChildDevices() { { fanDevice.addChildDevice("bond", "BOND Fan Timer Light", hubId + ":bond:" + fan + ":light", ["name": state.fanList[fan] + " Light", isComponent: true]) } + else if (state.fanDetails[fan].contains("StartIncreasingBrightness") && state.fanDetails[fan].contains("StartDecreasingBrightness")) + { + fanDevice.addChildDevice("bond", "BOND Fan Timer Light", hubId + ":bond:" + fan + ":light", ["name": state.fanList[fan] + " Light", isComponent: true]) + } else + { fanDevice.addChildDevice("bond", "BOND Fan Light", hubId + ":bond:" + fan + ":light", ["name": state.fanList[fan] + " Light", isComponent: true]) + } } } } @@ -799,9 +858,8 @@ def handleDim(device, duration) } } -def dimUsingTimer(device, duration, command) +def dimUsingTimer(device, bondId, duration, command) { - def bondId = getBondIdFromDevice(device) if (executeAction(bondId, command)) { runInMillis((duration*1000).toInteger(), stopDimmer, [data: [device: device, bondId: bondId]]) @@ -813,7 +871,7 @@ def stopDimmer(data) executeAction(data.bondId, "Stop") } -def handleStartDimming(device) +def handleStartDimming(device, direction = null) { def bondId = getBondIdFromDevice(device) if (device.deviceNetworkId.contains("uplight")) @@ -824,6 +882,14 @@ def handleStartDimming(device) { executeAction(bondId, "StartDownLightDimmer") } + else if (direction == 'up') + { + executeAction(bondId, "StartIncreasingBrightness") + } + else if (direction == 'down') + { + executeAction(bondId, "StartDecreasingBrightness") + } else { executeAction(bondId, "StartDimmer") diff --git a/drivers/BOND_Fan.groovy b/drivers/BOND_Fan.groovy index be10f2a..bd26ad6 100644 --- a/drivers/BOND_Fan.groovy +++ b/drivers/BOND_Fan.groovy @@ -63,8 +63,8 @@ def handleDim(device, duration) { parent.handleDim(device, duration) } -def handleStartDimming(device) { - parent.handleStartDimming(device) +def handleStartDimming(device, direction = null) { + parent.handleStartDimming(device,direction) } def handleStopDimming(device) { diff --git a/drivers/BOND_Fan_Timer_Light.groovy b/drivers/BOND_Fan_Timer_Light.groovy index 98de811..95a87df 100644 --- a/drivers/BOND_Fan_Timer_Light.groovy +++ b/drivers/BOND_Fan_Timer_Light.groovy @@ -14,11 +14,11 @@ metadata { ) { capability "Switch" capability "Light" + capability "ChangeLevel" command "dim", ["number"] command "startDimming" - command "stopDimming" command "fixPower", [[name:"Power*", type: "ENUM", description: "Power", constraints: ["off","on"] ] ] command "toggle" @@ -30,10 +30,14 @@ def dim(duration) { } def startDimming() { - parent.handleStartDimming(device) + parent.handleStartDimming(device, null) } -def stopDimming() { +def startLevelChange(direction) { + parent.handleStartDimming(device,direction) +} + +def stopLevelChange() { parent.handleStopDimming(device) } diff --git a/drivers/BOND_Fan_With_Direction.groovy b/drivers/BOND_Fan_With_Direction.groovy index 2693c2f..c1ed76e 100644 --- a/drivers/BOND_Fan_With_Direction.groovy +++ b/drivers/BOND_Fan_With_Direction.groovy @@ -70,8 +70,8 @@ def handleDim(device, duration) { parent.handleDim(device, duration) } -def handleStartDimming(device) { - parent.handleStartDimming(device) +def handleStartDimming(device, direction = null) { + parent.handleStartDimming(device, direction) } def handleStopDimming(device) { diff --git a/packageManifest.json b/packageManifest.json index 6192623..c2b26f1 100644 --- a/packageManifest.json +++ b/packageManifest.json @@ -2,11 +2,11 @@ "packageName": "BOND Home Integration", "minimumHEVersion": "2.1.9", "author": "Dominick Meglio", - "version": "1.4.0", - "dateReleased": "2021-01-25", + "version": "1.4.2", + "dateReleased": "2022-05-22", "documentationLink": "https://github.com/dcmeglio/hubitat-bond/blob/master/README.md", "communityLink": "https://community.hubitat.com/t/support-for-bond-hub/19141", - "releaseNotes": "Added support for the Preset command for shades including a setPosition command that supports 0/50/100 as values.", + "releaseNotes": "Fix cron/polling logic", "apps" : [ { "id" : "bf7d70fb-1fa9-436f-9cfc-fb8520cda22a",