diff --git a/drivers/konnected-gdov2-q.groovy b/drivers/konnected-gdov2-q.groovy index d63833b..aadb530 100644 --- a/drivers/konnected-gdov2-q.groovy +++ b/drivers/konnected-gdov2-q.groovy @@ -37,9 +37,10 @@ metadata { capability 'Sensor' capability 'Refresh' capability 'Initialize' - capability 'Signal Strength' - capability 'Door Control' - capability 'Garage Door Control' + capability 'SignalStrength' + capability 'DoorControl' + capability 'GarageDoorControl' + capability 'ContactSensor' capability 'Switch' capability 'Lock' capability 'MotionSensor' @@ -51,6 +52,10 @@ metadata { attribute 'uptime', 'number' attribute 'openings', 'number' attribute 'position', 'number' + attribute 'openingDuration', 'number' + attribute 'closingDuration', 'number' + attribute 'esphomeVersion', 'string' + attribute 'securityPlusProtocol', 'string' command 'setPosition', [ [ name: 'Position*', type: 'NUMBER', description: 'Numerical position 0 (fully closed) to 100 (fully open)' ] @@ -59,6 +64,7 @@ metadata { command 'learnOff' command 'restart' command 'stop' + command 'preCloseWarning' } preferences { @@ -149,32 +155,32 @@ private void doParseDevice(Map message) { private void doParseEntity(Map message) { if (message.platform == 'cover') { - if (message.name == "Garage Door") { + if (message.objectId == "garage_door") { state.doorKey = message.key as Long } return } if (message.platform == 'binary') { - if (message.name == "Motion") { + if (message.objectId == "motion") { state.motionKey = message.key as Long getMotionDevice(message.key) } - if (message.name == "Obstruction") { + if (message.objectId == "obstruction") { state.obstructionKey = message.key as Long getObstructionDevice(message.key) } - if (message.name == "Button") { + if (message.objectId == "button") { state.buttonKey = message.key as Long getButtonDevice(message.key) } - if (message.name == "Motor") { + if (message.objectId == "motor") { state.motorKey = message.key as Long } return } if (message.platform == 'light') { - if (message.name == "Garage Light") { + if (message.objectId == "garage_light") { state.lightKey = message.key as Long getLightDevice(message.key) } @@ -182,7 +188,7 @@ private void doParseEntity(Map message) { } if (message.platform == 'switch') { - if (message.name == "Learn") { + if (message.objectId == "learn") { state.learnKey = message.key as Long getLearnDevice(message.key) } @@ -190,7 +196,7 @@ private void doParseEntity(Map message) { } if (message.platform == 'lock') { - if (message.name == "Lock") { + if (message.objectId == "lock") { state.lockKey = message.key as Long getLockDevice(message.key) } @@ -198,22 +204,49 @@ private void doParseEntity(Map message) { } if (message.platform == 'sensor') { - if (message.name == "Garage Openings") { + if (message.objectId == "garage_openings") { state.openingsKey = message.key as Long } if (message.deviceClass == 'signal_strength' && message.unitOfMeasurement == 'dBm') { state.signalStrengthKey = message.key } - if (message.name == "Uptime") { + if (message.objectId == "uptime") { state.uptimeKey = message.key as Long } return } + if (message.platform == 'number') { + if (message.objectId == 'opening_duration') { + state.openingDurationKey = message.key + } + if (message.objectId == 'closing_duration') { + state.closingDurationKey = message.key + } + return + } + + if (message.platform == 'select') { + if (message.objectId == 'security__protocol') { + state.securityPlusProtocolKey = message.key + } + return + } + + if (message.platform == 'text') { + if (message.objectId == 'esphome_version') { + state.esphomeVersionKey = message.key + } + return + } + if (message.platform == 'button') { - if (message.name == "Restart") { + if (message.objectId == "restart") { state.restartKey = message.key } + if (message.objectId == "pre-close_warning") { + state.preCloseWarningKey = message.key + } return } } @@ -226,10 +259,11 @@ private void doParseState(Map message) { return } String value + String contact switch (message.currentOperation) { case COVER_OPERATION_IDLE: value = message.position > 0 ? 'open' : 'closed' - contact = value + contact = value break case COVER_OPERATION_IS_OPENING: value = 'opening' @@ -239,6 +273,7 @@ private void doParseState(Map message) { break } sendDeviceEvent("door", value, type, "Door") + sendDeviceEvent("contact", contact, type, "Contact") int position = Math.round(message.position * 100) as int sendDeviceEvent("position", position, type, "Position") return @@ -276,7 +311,7 @@ private void doParseState(Map message) { if (state.lockKey as Long == message.key) { String value = message.state == 1 ? "locked" : "unlocked" - sendDeviceEvent("lock", value, type, "Remotes lock", getLockDevice(message.key)) + sendDeviceEvent("lock", value, type, "Lock", getLockDevice(message.key)) return } @@ -292,6 +327,33 @@ private void doParseState(Map message) { return } + if (state.esphomeVersionKey as Long == message.key) { + sendDeviceEvent("esphomeVersion", message.state, type, "ESPHome Version") + return + } + + if (state.securityPlusProtocolKey as Long == message.key) { + sendDeviceEvent("securityPlusProtocol", message.state, type, "Security+ Protocol") + return + } + + if (state.openingDurationKey as Long == message.key) { + sendDeviceEvent("openingDuration", message.state, type, "Opening duration") + return + } + + if (state.openingDurationKey as Long == message.key) { + int value = message.state as int + sendDeviceEvent("openingDuration", value, type, "Opening duration") + return + } + + if (state.closingDurationKey as Long == message.key) { + int value = message.state as int + sendDeviceEvent("closingDuration", value, type, "Closing duration") + return + } + if (state.buttonKey as Long == message.key && message.hasState) { if (message.state) { sendDeviceEvent("pushed", 1, type, "Button", getButtonDevice(message.key), null, true) @@ -405,6 +467,20 @@ public void setPosition(BigDecimal pos) { } } +public void playSound() { + if (state.playSoundKey) { + if (logTextEnable) { log.info "${device} play sound" } + espHomeButtonCommand(key: state.playSoundKey as Long) + } +} + +public void preCloseWarning() { + if (state.preCloseWarningKey) { + if (logTextEnable) { log.info "${device} pre-close warning" } + espHomeButtonCommand(key: state.preCloseWarningKey as Long) + } +} + // TODO: Toggle // public void toggle() { // if (state.doorKey) { diff --git a/drivers/konnected-gdov2-s.groovy b/drivers/konnected-gdov2-s.groovy index 26ec672..ff70889 100644 --- a/drivers/konnected-gdov2-s.groovy +++ b/drivers/konnected-gdov2-s.groovy @@ -46,6 +46,8 @@ metadata { attribute 'calibratedDistance', 'number' command 'calibrate' + command 'preCloseWarning' + command 'restart' } preferences { @@ -142,13 +144,30 @@ public void calibrate() { espHomeCallService('calibrate_open_garage') } +public void preCloseWarning() { + if (state.preCloseWarning) { + if (logTextEnable) { log.info "${device} pre-close warning" } + espHomeButtonCommand(key: state.preCloseWarning as Long) + } +} + +public void restart() { + if (state.restart) { + log.info "${device} restart" + espHomeButtonCommand(key: state.restart as Long) + } +} + + // the parse method is invoked by the API library when messages are received public void parse(Map message) { if (logEnable) { log.debug "ESPHome received: ${message}" } switch (message.type) { case 'device': - // Device information + if (!device.label && message.macAddress) { + device.label = "GDO White " + message.macAddress.replaceAll(':','').toLowerCase().substring(6) + } break case 'entity': @@ -182,6 +201,17 @@ public void parse(Map message) { state['switch'] = message.key return } + + if (message.platform == 'button') { + if (message.objectId == "restart") { + state['restart'] = message.key + } + if (message.objectId == "pre-close_warning") { + state['preCloseWarning'] = message.key + } + return + } + break case 'state': @@ -189,9 +219,11 @@ public void parse(Map message) { // Check if the entity key matches the message entity key received to update device state if (state.cover as Long == message.key) { String value + String contact switch (message.currentOperation) { case COVER_OPERATION_IDLE: value = message.position > 0 ? 'open' : 'closed' + contact = value break case COVER_OPERATION_IS_OPENING: value = 'opening' @@ -203,6 +235,7 @@ public void parse(Map message) { if (device.currentValue('door') != value) { descriptionText = "${device} door is ${value}" sendEvent(name: 'door', value: value, type: type, descriptionText: descriptionText) + sendEvent(name: 'contact', value: contact, type: type, descriptionText: descriptionText) if (logTextEnable) { log.info descriptionText } } return @@ -219,19 +252,24 @@ public void parse(Map message) { return } - if (state.wiredSensor as Long == message.key && message.hasState) { - String value = message.state ? 'open' : 'closed' - if (device.currentValue('contact') != value) { - descriptionText = "Contact is ${value}" - sendEvent([ - name: 'contact', - value: value, type: type, - descriptionText: descriptionText - ]) - if (logTextEnable) { log.info descriptionText } - } - return - } + // REMOVED because 'contact' track the state of the Garage Door + // no longer tracking the wired contact as a separate entity + // + // TODO: optionally add as a child entity + // + // if (state.wiredSensor as Long == message.key && message.hasState) { + // String value = message.state ? 'open' : 'closed' + // if (device.currentValue('contact') != value) { + // descriptionText = "Contact is ${value}" + // sendEvent([ + // name: 'contact', + // value: value, type: type, + // descriptionText: descriptionText + // ]) + // if (logTextEnable) { log.info descriptionText } + // } + // return + // } if (state.sensorDistance as Long == message.key && message.hasState) { BigDecimal value = message.state.setScale(2, BigDecimal.ROUND_HALF_UP) diff --git a/package-gdov2q.json b/package-gdov2q.json index eb245a8..f79aa79 100644 --- a/package-gdov2q.json +++ b/package-gdov2q.json @@ -1,7 +1,7 @@ { "packageName": "Garge Door Opener blaQ (GDOv2-Q)", "author": "Konnected Inc.", - "version": "1.1", + "version": "1.2", "minimumHEVersion": "0.0", "dateReleased": "2024-05-06", "bundles": [ @@ -20,7 +20,7 @@ "namespace": "konnected", "location": "https://raw.githubusercontent.com/konnected-io/konnected-hubitat/master/drivers/konnected-gdov2-q.groovy", "required": true, - "version": "1.1" + "version": "1.2" } ] } \ No newline at end of file diff --git a/package-gdov2s.json b/package-gdov2s.json index 8df3dfd..df4da54 100644 --- a/package-gdov2s.json +++ b/package-gdov2s.json @@ -1,7 +1,7 @@ { "packageName": "Garage Door Opener GDOv2-S", "author": "Konnected Inc.", - "version": "1.0", + "version": "1.1", "minimumHEVersion": "0.0", "dateReleased": "2024-03-03", "bundles": [ @@ -20,7 +20,7 @@ "namespace": "konnected", "location": "https://raw.githubusercontent.com/konnected-io/konnected-hubitat/master/drivers/konnected-gdov2-s.groovy", "required": true, - "version": "1.0" + "version": "1.1" } ] } \ No newline at end of file