[RELEASE] HubiThings Replica

It is no problem putting a debounce in the Replica Button driver. Would that work?

try this:

Summary
/**
*  Copyright 2023 Bloodtick
*
*  Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
*  in compliance with the License. You may obtain a copy of the License at:
*
*      http://www.apache.org/licenses/LICENSE-2.0
*
*  Unless required by applicable law or agreed to in writing, software distributed under the License is distributed
*  on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License
*  for the specific language governing permissions and limitations under the License.
*
*/
@SuppressWarnings('unused')
public static String version() {return "1.3.0"}

import groovy.transform.CompileStatic
import groovy.transform.Field
@Field volatile static Map<String,Long> g_mEventSendTime = [:]

metadata 
{
    definition(name: "Replica Button + Debounce", namespace: "replica", author: "bloodtick", importUrl:"https://raw.githubusercontent.com/bloodtick/Hubitat/main/hubiThingsReplica/devices/replicaButton.groovy")
    {
        capability "Actuator"
        capability "Battery"
        capability "Configuration"
        capability "DoubleTapableButton"
        capability "HoldableButton"
        capability "PushableButton"
        capability "Refresh"
        capability "ReleasableButton"
        capability "TemperatureMeasurement"

        attribute "healthStatus", "enum", ["offline", "online"]
    }
    preferences {
        input(name:"deviceDebounce", type: "number", title: "Button debounce in milliseconds:", range: "0..10000", defaultValue: 0)
        input(name:"deviceInfoDisable", type: "bool", title: "Disable Info logging:", defaultValue: false)
    }
}

def installed() {
	initialize()
}

def updated() {
	initialize()    
}

def initialize() {
    updateDataValue("triggers", groovy.json.JsonOutput.toJson(getReplicaTriggers()))
    updateDataValue("commands", groovy.json.JsonOutput.toJson(getReplicaCommands()))
}

def configure() {
    logInfo "${device.displayName} configured default rules"
    initialize()
    updateDataValue("rules", getReplicaRules())
    sendCommand("configure")
}

// Methods documented here will show up in the Replica Command Configuration. These should be mostly setter in nature. 
Map getReplicaCommands() {
    return ([ "setBatteryValue":[[name:"battery*",type:"NUMBER"]], "setDoubleTappedValue":[[name:"buttonNumber",type:"NUMBER"]], "setHeldValue":[[name:"buttonNumber",type:"NUMBER"]], "setNumberOfButtonsValue":[[name:"numberOfButtons*",type:"NUMBER"]],             
              "setPushedValue":[[name:"buttonNumber",type:"NUMBER"]], "setReleasedValue":[[name:"buttonNumber",type:"NUMBER"]], "setTemperatureValue":[[name:"temperature*",type:"NUMBER"]], "setHealthStatusValue":[[name:"healthStatus*",type:"ENUM"]]
            ])
}

def setBatteryValue(value) {
    String descriptionText = "${device.displayName} battery level is $value %"
    sendEvent(name: "battery", value: value, unit: "%", descriptionText: descriptionText)
    logInfo descriptionText
}

def setDoubleTappedValue(value=1) {
    if(debounce("setDoubleTappedValue")) return
    String descriptionText = "${device.displayName} button $value was double tapped"
    sendEvent(name: "doubleTapped", value: value, descriptionText: descriptionText, isStateChange: true)
    logInfo descriptionText
}

def setHeldValue(value=1) {
    if(debounce("setHeldValue")) return
    String descriptionText = "${device.displayName} button $value was held"
    sendEvent(name: "held", value: value, descriptionText: descriptionText, isStateChange: true)
    logInfo descriptionText
}

def setNumberOfButtonsValue(value=1) {
    sendEvent(name: "numberOfButtons", value: value, descriptionText: "${device.displayName} has $value number of buttons")
}

def setPushedValue(value=1) {
    if(debounce("setPushedValue")) return
    String descriptionText = "${device.displayName} button $value was pushed"
    sendEvent(name: "pushed", value: value, descriptionText: descriptionText, isStateChange: true)
    logInfo descriptionText
}

def setReleasedValue(value=1) {
    if(debounce("setReleasedValue")) return
    String descriptionText = "${device.displayName} button $value was released"
    sendEvent(name: "released", value: value, descriptionText: descriptionText, isStateChange: true)
    logInfo descriptionText
}

def setTemperatureValue(value) {
    String unit = "°${getTemperatureScale()}"
    String descriptionText = "${device.displayName} temperature is $value $unit"
    sendEvent(name: "temperature", value: value, unit: unit, descriptionText: descriptionText)
    logInfo descriptionText
}

def setHealthStatusValue(value) {    
    sendEvent(name: "healthStatus", value: value, descriptionText: "${device.displayName} healthStatus set to $value")
}

// Methods documented here will show up in the Replica Trigger Configuration. These should be all of the native capability commands
Map getReplicaTriggers() {
    return ([ "doubleTap":[[name:"buttonNumber",type:"NUMBER"]], "hold":[[name:"buttonNumber",type:"NUMBER"]], "push":[[name:"buttonNumber",type:"NUMBER"]], "release":[[name:"buttonNumber",type:"NUMBER"]], "refresh":[]])
}

private def sendCommand(String name, def value=null, String unit=null, data=[:]) {
    data.version=version()
    parent?.deviceTriggerHandler(device, [name:name, value:value, unit:unit, data:data, now:now()])
}

def doubleTap(value=1) {
    sendCommand("doubleTap", value)    
}

def hold(value=1) {
    sendCommand("hold", value)    
}

def push(value=1) {
    sendCommand("push", value)    
}

def release(value=1) {
    sendCommand("release", value)    
}

void refresh() {
    sendCommand("refresh")
}

String getReplicaRules() {
    return """{"version":1,"components":[{"trigger":{"type":"attribute","properties":{"value":{"title":"PositiveInteger","type":"integer","minimum":0}},"additionalProperties":false,"required":["value"],"capability":"button","attribute":"numberOfButtons","label":"attribute: numberOfButtons.*"},"command":{"name":"setNumberOfButtonsValue","label":"command: setNumberOfButtonsValue(numberOfButtons*)","type":"command","parameters":[{"name":"numberOfButtons*","type":"NUMBER"}]},"type":"smartTrigger","mute":true},{"trigger":{"title":"IntegerPercent","type":"attribute","properties":{"value":{"type":"integer","minimum":0,"maximum":100},"unit":{"type":"string","enum":["%"],"default":"%"}},"additionalProperties":false,"required":["value"],"capability":"battery","attribute":"battery","label":"attribute: battery.*"},"command":{"name":"setBatteryValue","label":"command: setBatteryValue(battery*)","type":"command","parameters":[{"name":"battery*","type":"NUMBER"}]},"type":"smartTrigger","mute":true},{"trigger":{"type":"attribute","properties":{"value":{"title":"ButtonState","type":"string"}},"additionalProperties":false,"required":["value"],"capability":"button","attribute":"button","label":"attribute: button.held","value":"held","dataType":"ENUM"},"command":{"name":"setHeldValue","label":"command: setHeldValue(buttonNumber)","type":"command","parameters":[{"name":"buttonNumber","type":"NUMBER"}]},"type":"smartTrigger","disableStatus":true},{"trigger":{"type":"attribute","properties":{"value":{"title":"ButtonState","type":"string"}},"additionalProperties":false,"required":["value"],"capability":"button","attribute":"button","label":"attribute: button.double","value":"double","dataType":"ENUM"},"command":{"name":"setDoubleTappedValue","label":"command: setDoubleTappedValue(buttonNumber)","type":"command","parameters":[{"name":"buttonNumber","type":"NUMBER"}]},"type":"smartTrigger","disableStatus":true},{"trigger":{"type":"attribute","properties":{"value":{"title":"ButtonState","type":"string"}},"additionalProperties":false,"required":["value"],"capability":"button","attribute":"button","label":"attribute: button.pushed","value":"pushed","dataType":"ENUM"},"command":{"name":"setPushedValue","label":"command: setPushedValue(buttonNumber)","type":"command","parameters":[{"name":"buttonNumber","type":"NUMBER"}]},"type":"smartTrigger","disableStatus":true},{"trigger":{"type":"attribute","properties":{"value":{"title":"TemperatureValue","type":"number","minimum":-460,"maximum":10000},"unit":{"type":"string","enum":["F","C"]}},"additionalProperties":false,"required":["value","unit"],"capability":"temperatureMeasurement","attribute":"temperature","label":"attribute: temperature.*"},"command":{"name":"setTemperatureValue","label":"command: setTemperatureValue(temperature*)","type":"command","parameters":[{"name":"temperature*","type":"NUMBER"}]},"type":"smartTrigger","mute":true}]}"""
}

private Boolean debounce(method) {
    Boolean response = false
    String methodDeviceId = "$method${device.getId()}"
    if(deviceDebounce && g_mEventSendTime[methodDeviceId] && (now() - g_mEventSendTime[methodDeviceId] < deviceDebounce)) {
        response = true
        logInfo "${device.displayName} $method debonce"
    } else g_mEventSendTime[methodDeviceId] = now()   
    return response
}

private logInfo(msg)  { if(settings?.deviceInfoDisable != true) { log.info  "${msg}" } }
private logDebug(msg) { if(settings?.deviceDebugEnable == true) { log.debug "${msg}" } }
private logTrace(msg) { if(settings?.deviceTraceEnable == true) { log.trace "${msg}" } }
private logWarn(msg)  { log.warn   "${msg}" }
private logError(msg) { log.error  "${msg}" }

I think @djgutheinz will be working on a fridge replica DH at some point & I have both Dryer and Washer DHs on my list unless he jumps on those too.

You could probably use the 'multisensor' on the fridge now if you want the contact sensors to work.

LMK on the debounce button and I will update github.

1 Like

Anything more on that error? It sounds like there is a string to map (json) error when reading this thread.

I don't have any locks to test with, not sure if @djgutheinz or @bthrock has devices they could directly troubleshoot.

IMHO, locks are something I would bring local to HE if you can. No need sending codes all over the cloud if you don't need too. They are encrypted in transit, but text logs are forever and not. Getting off my soapbox now. :wink:

Edit: now that i'm looking at the rules, it appears only way to ST, is that intentional?


Any thoughts @djgutheinz

Enabled debug logging for device and app below, this is in response to changing inputsource via remote

[app:859](http://192.168.1.182/logs?tab=past&deviceId=777#)2023-01-15 12:34:38.350 PM[warn](http://192.168.1.182/logs?tab=past&deviceId=777#)HubiThings Replica asyncHttpPostCallback setSmartDeviceCommand status:422 reason:Unprocessable Entity

[app:859](http://192.168.1.182/logs?tab=past&deviceId=777#)2023-01-15 12:34:38.346 PM[trace](http://192.168.1.182/logs?tab=past&deviceId=777#)Content-Type : application/json

[app:859](http://192.168.1.182/logs?tab=past&deviceId=777#)2023-01-15 12:34:38.343 PM[trace](http://192.168.1.182/logs?tab=past&deviceId=777#)Access-Control-Allow-Headers : DNT,Keep-Alive,User-Agent,If-Modified-Since,Cache-Control,Content-Type,Accept,Authorization,X-ST-Client,X-ST-Api-Version,X-ST-Client-AppVersion,X-ST-Client-OS,X-ST-Client-DeviceModel

[app:859](http://192.168.1.182/logs?tab=past&deviceId=777#)2023-01-15 12:34:38.339 PM[trace](http://192.168.1.182/logs?tab=past&deviceId=777#)Date : Sun, 15 Jan 2023 17:34:37 GMT

[app:859](http://192.168.1.182/logs?tab=past&deviceId=777#)2023-01-15 12:34:38.335 PM[trace](http://192.168.1.182/logs?tab=past&deviceId=777#)X-RateLimit-Limit : 120

[app:859](http://192.168.1.182/logs?tab=past&deviceId=777#)2023-01-15 12:34:38.331 PM[trace](http://192.168.1.182/logs?tab=past&deviceId=777#)X-RateLimit-Reset : 22157

[app:859](http://192.168.1.182/logs?tab=past&deviceId=777#)2023-01-15 12:34:38.327 PM[trace](http://192.168.1.182/logs?tab=past&deviceId=777#)Connection : keep-alive

[app:859](http://192.168.1.182/logs?tab=past&deviceId=777#)2023-01-15 12:34:38.324 PM[trace](http://192.168.1.182/logs?tab=past&deviceId=777#)Access-Control-Allow-Methods : GET, POST, PUT, DELETE, OPTIONS

[app:859](http://192.168.1.182/logs?tab=past&deviceId=777#)2023-01-15 12:34:38.320 PM[trace](http://192.168.1.182/logs?tab=past&deviceId=777#)Access-Control-Allow-Origin : *

[app:859](http://192.168.1.182/logs?tab=past&deviceId=777#)2023-01-15 12:34:38.316 PM[trace](http://192.168.1.182/logs?tab=past&deviceId=777#)Server : openresty

[app:859](http://192.168.1.182/logs?tab=past&deviceId=777#)2023-01-15 12:34:38.313 PM[trace](http://192.168.1.182/logs?tab=past&deviceId=777#)X-RateLimit-Remaining : 120

[app:859](http://192.168.1.182/logs?tab=past&deviceId=777#)2023-01-15 12:34:38.309 PM[trace](http://192.168.1.182/logs?tab=past&deviceId=777#)Transfer-Encoding : chunked

[app:859](http://192.168.1.182/logs?tab=past&deviceId=777#)2023-01-15 12:34:38.305 PM[debug](http://192.168.1.182/logs?tab=past&deviceId=777#)HubiThings Replica executing 'asyncHttpPostCallback()' status: 422 method: setSmartDeviceCommand

[app:859](http://192.168.1.182/logs?tab=past&deviceId=777#)2023-01-15 12:34:38.043 PM[debug](http://192.168.1.182/logs?tab=past&deviceId=777#)HubiThings Replica executing 'deviceTriggerHandler()' replicaDevice:'Loft TV' name:'deviceRefresh' value:'null' unit:'null', data:'[:]'

[app:859](http://192.168.1.182/logs?tab=past&deviceId=777#)2023-01-15 12:34:38.037 PM[debug](http://192.168.1.182/logs?tab=past&deviceId=777#)HubiThings Replica executing 'asyncHttpPostJson()'

[app:859](http://192.168.1.182/logs?tab=past&deviceId=777#)2023-01-15 12:34:38.033 PM[debug](http://192.168.1.182/logs?tab=past&deviceId=777#)HubiThings Replica executing 'setSmartDeviceCommand()'

[app:859](http://192.168.1.182/logs?tab=past&deviceId=777#)2023-01-15 12:32:50.332 PM[warn](http://192.168.1.182/logs?tab=past&deviceId=777#)HubiThings Replica asyncHttpPostCallback setSmartDeviceCommand status:422 reason:Unprocessable Entity

[app:859](http://192.168.1.182/logs?tab=past&deviceId=777#)2023-01-15 12:32:50.328 PM[trace](http://192.168.1.182/logs?tab=past&deviceId=777#)Content-Type : application/json

[app:859](http://192.168.1.182/logs?tab=past&deviceId=777#)2023-01-15 12:32:50.324 PM[trace](http://192.168.1.182/logs?tab=past&deviceId=777#)Access-Control-Allow-Headers : DNT,Keep-Alive,User-Agent,If-Modified-Since,Cache-Control,Content-Type,Accept,Authorization,X-ST-Client,X-ST-Api-Version,X-ST-Client-AppVersion,X-ST-Client-OS,X-ST-Client-DeviceModel

[app:859](http://192.168.1.182/logs?tab=past&deviceId=777#)2023-01-15 12:32:50.319 PM[trace](http://192.168.1.182/logs?tab=past&deviceId=777#)Date : Sun, 15 Jan 2023 17:32:49 GMT

[app:859](http://192.168.1.182/logs?tab=past&deviceId=777#)2023-01-15 12:32:50.316 PM[trace](http://192.168.1.182/logs?tab=past&deviceId=777#)X-RateLimit-Limit : 120

[app:859](http://192.168.1.182/logs?tab=past&deviceId=777#)2023-01-15 12:32:50.312 PM[trace](http://192.168.1.182/logs?tab=past&deviceId=777#)X-RateLimit-Reset : 10176

[app:859](http://192.168.1.182/logs?tab=past&deviceId=777#)2023-01-15 12:32:50.308 PM[trace](http://192.168.1.182/logs?tab=past&deviceId=777#)Connection : keep-alive

[app:859](http://192.168.1.182/logs?tab=past&deviceId=777#)2023-01-15 12:32:50.304 PM[trace](http://192.168.1.182/logs?tab=past&deviceId=777#)Access-Control-Allow-Methods : GET, POST, PUT, DELETE, OPTIONS

[app:859](http://192.168.1.182/logs?tab=past&deviceId=777#)2023-01-15 12:32:50.300 PM[trace](http://192.168.1.182/logs?tab=past&deviceId=777#)Access-Control-Allow-Origin : *

[app:859](http://192.168.1.182/logs?tab=past&deviceId=777#)2023-01-15 12:32:50.297 PM[trace](http://192.168.1.182/logs?tab=past&deviceId=777#)Server : openresty

[app:859](http://192.168.1.182/logs?tab=past&deviceId=777#)2023-01-15 12:32:50.293 PM[trace](http://192.168.1.182/logs?tab=past&deviceId=777#)X-RateLimit-Remaining : 120

[app:859](http://192.168.1.182/logs?tab=past&deviceId=777#)2023-01-15 12:32:50.289 PM[trace](http://192.168.1.182/logs?tab=past&deviceId=777#)Transfer-Encoding : chunked

[app:859](http://192.168.1.182/logs?tab=past&deviceId=777#)2023-01-15 12:32:50.286 PM[debug](http://192.168.1.182/logs?tab=past&deviceId=777#)HubiThings Replica executing 'asyncHttpPostCallback()' status: 422 method: setSmartDeviceCommand

[app:859](http://192.168.1.182/logs?tab=past&deviceId=777#)2023-01-15 12:32:50.055 PM[debug](http://192.168.1.182/logs?tab=past&deviceId=777#)HubiThings Replica executing 'deviceTriggerHandler()' replicaDevice:'Master TV' name:'deviceRefresh' value:'null' unit:'null', data:'[:]'

[app:859](http://192.168.1.182/logs?tab=past&deviceId=777#)2023-01-15 12:32:50.049 PM[debug](http://192.168.1.182/logs?tab=past&deviceId=777#)HubiThings Replica executing 'asyncHttpPostJson()'

[app:859](http://192.168.1.182/logs?tab=past&deviceId=777#)2023-01-15 12:32:50.045 PM[info](http://192.168.1.182/logs?tab=past&deviceId=777#)Device:[Master TV] commands:**{"commands":[{"component":"main","capability":"main","command":"refresh","arguments":"refresh"}]}**

[app:859](http://192.168.1.182/logs?tab=past&deviceId=777#)2023-01-15 12:32:50.032 PM[debug](http://192.168.1.182/logs?tab=past&deviceId=777#)HubiThings Replica executing 'setSmartDeviceCommand()'

[app:860](http://192.168.1.182/logs?tab=past&deviceId=777#)2023-01-15 12:32:31.437 PM[debug](http://192.168.1.182/logs?tab=past&deviceId=777#)RESPONSE: {"statusCode":200}

[app:859](http://192.168.1.182/logs?tab=past&deviceId=777#)2023-01-15 12:32:31.433 PM[trace](http://192.168.1.182/logs?tab=past&deviceId=777#)smartEvent: capability:'samsungvd.mediaInputSource' attribute:'inputSource' value:'[value:HDMI1, unit:null, timestamp:2023-01-15T12:32:31.384Z]'

[app:860](http://192.168.1.182/logs?tab=past&deviceId=777#)2023-01-15 12:32:31.429 PM[debug](http://192.168.1.182/logs?tab=past&deviceId=777#)RESPONSE: {"statusCode":200}

[app:859](http://192.168.1.182/logs?tab=past&deviceId=777#)2023-01-15 12:32:31.425 PM[debug](http://192.168.1.182/logs?tab=past&deviceId=777#)HubiThings Replica executing 'smartTriggerHandler()' replicaDevice:'Master TV'

[app:859](http://192.168.1.182/logs?tab=past&deviceId=777#)2023-01-15 12:32:31.420 PM[info](http://192.168.1.182/logs?tab=past&deviceId=777#)Event: {"eventId":"96970d6a-94fa-11ed-85f7-f5d333446dcd","locationId":"855dc27a-7e5d-4ce1-bed2-5f01cab1b825","ownerId":"855dc27a-7e5d-4ce1-bed2-5f01cab1b825","ownerType":"LOCATION","deviceId":"09d0f3f0-f484-4173-ac7f-00d148257ffc","componentId":"main","capability":"samsungvd.mediaInputSource","attribute":"inputSource","value":"HDMI1","valueType":"string","stateChange":true,"data":{},"subscriptionName":"09d0f3f0-f484-4173-ac7f-00d148257ffc"}

[app:859](http://192.168.1.182/logs?tab=past&deviceId=777#)2023-01-15 12:32:31.415 PM[trace](http://192.168.1.182/logs?tab=past&deviceId=777#)smartEvent: capability:'mediaInputSource' attribute:'inputSource' value:'[value:HDMI1, unit:null, timestamp:2023-01-15T12:32:31.375Z]'

[app:859](http://192.168.1.182/logs?tab=past&deviceId=777#)2023-01-15 12:32:31.411 PM[debug](http://192.168.1.182/logs?tab=past&deviceId=777#)HubiThings Replica executing 'smartEventHandler()' replicaDevice:'Master TV'

[app:859](http://192.168.1.182/logs?tab=past&deviceId=777#)2023-01-15 12:32:31.405 PM[debug](http://192.168.1.182/logs?tab=past&deviceId=777#)HubiThings Replica executing 'smartTriggerHandler()' replicaDevice:'Master TV'

[app:859](http://192.168.1.182/logs?tab=past&deviceId=777#)2023-01-15 12:32:31.401 PM[debug](http://192.168.1.182/logs?tab=past&deviceId=777#)HubiThings Replica executing 'oauthEventHandler()'

[app:859](http://192.168.1.182/logs?tab=past&deviceId=777#)2023-01-15 12:32:31.383 PM[info](http://192.168.1.182/logs?tab=past&deviceId=777#)Event: {"eventId":"96973509-94fa-11ed-8010-45968977058a","locationId":"855dc27a-7e5d-4ce1-bed2-5f01cab1b825","ownerId":"855dc27a-7e5d-4ce1-bed2-5f01cab1b825","ownerType":"LOCATION","deviceId":"09d0f3f0-f484-4173-ac7f-00d148257ffc","componentId":"main","capability":"mediaInputSource","attribute":"inputSource","value":"HDMI1","valueType":"string","stateChange":true,"data":{},"subscriptionName":"09d0f3f0-f484-4173-ac7f-00d148257ffc"}
1 Like

Finally got my description simulator working in my personal version of the app. My immediate plans are:
Samsung Dishwasher (single component device)
Ring Doorbell (got to check if there is an integration here yet)
MyQ garage door opener (same check)

I have files with description and status values for various models of the most of the devices, if you want any. The refrigerator is very complex (a lot of components - based on model) and many door sensors/switches. The washer and dryer only have 2 components each.

3 Likes

There is a community MyQ integration, by the same developer who did the ST one. It's no longer maintained because Chamberlain keeps breaking things... but the ST driver has that issue too. I've found it to be more stable than the ST version, but YMMV. (It's one of the first cloud integrations I bought over from ST to HE; I got sick of reauthorizing it in ST...)

It's in HPM (MyQ Lite v3.1.3; author: Brian Beaird).
The thread is: [No Longer Maintained] Updated MyQ Lite Application Official Thread

1 Like

The main devices I have left on my ST hub are IKEA Tradfri buttons and sensors, because IKEA does weird group messaging stuff that HE doesn't support. This integration has definitely saved a bunch of my automations now that ST finally pulled the plug.

I think I've noticed a bug, and it's not a big one because there's a work-around, but I thought I'd note it. It happens with the IKEA two-button and five-button remotes. When adding Replica buttons, three or six component devices appear: "main", "button1", and "button2" (and buttons 3 through 5 for the five-button).

I used only the "main" component at first, and attached battery monitors and a button controller. The battery shows correctly, and button push and button hold come through... but no matter which button is pressed/held they all show up as "button 1" in HE, leading to low WAF :slight_smile:. The workaround was easy: build replica buttons for the individual button components too, and attach button controllers to those. (I still need to keep the "main" component for battery.)

That was all it took to make things work... I figure this is either worth fixing or documenting (so people know where to attach their button controllers). Thank you so much for this integration, and LMK if there's anything I can do to help debug this issue.

You should get an additional field when selecting that device, each button on HE is an individual. The problem is HE and ST do not treat buttons the same. So what you did is correct.

See here:

2 Likes

Your point on moving the locks to HE is well taken and one I had not considered. I planned to eventually move them over, I was hoping for a short-term fix to replace functionality lost with the demise of my Rboys smart apps. I guess it's likely I'll be moving them sooner rather than later.

As to your question about json errors, you're correct.

2023-01-15 03:44:11.909 PM errorgroovy.lang.MissingPropertyException: No such property: name for class: java.lang.String on line 1304 (method main)

Thank you for your thoughts, and thank you for this app. It's fantastic.

Stephen

1 Like

Oh, yeah. I forgot that there was an issue that ST buttons didn't work right in early versions of HubConnect, either (and there wasn't an easy fix because it didn't expose the component-devices). Eventually, HubConnect made the ST buttons simulate HE button behavior on the HE side, and so I forgot about this difference.

1 Like

In order to use modes bidirectionally do I need to have a physical ST hub? Isai

I was able to use a ST virtual device and just configured it with the Replica SmartThingsHub DH. Give it a try.

There is a MotionSensingDoorbell driver in my repo that I threw together during the early Alpha, but it's limited to button/motion sensor capabilities only. If there's more than can be done on the driver or integration front, I'm sure it would be welcome by everyone.

The latest version of the MyQ integration on ST (EDGE) has been as solid as a rock for me, and it's very similar in concept to the HA integration which has worked for a very long time.

FWIW, the existing ReplicaGarageDoor driver was created to work with the MyQ integration and (hopefully) more.

1 Like

Terrific! I've loaded the driver and will test with the doorbell shortly, but I have no doubt it will work perfectly.

FWIW, that driver was my first effort and strictly a cut-and-paste job, and I have zero pride of authorship in that or any of my drivers. You're more than welcome to add your professional touch to any of them. With people like your writing drivers, this amateur is happily out of the driver business for good.

Assuming this tests out as expected, would you rather add this to your driver repo or have me update mine? I don't care one way or the other myself.

It is now and always will be your driver.

My experience in industry was Project/Systems engineering on complex intelligence aircraft. I manage the sw portion of the project. However, my focus was always functionality to the end user. So, although I am an novice code slinger, I am fairly good at visualizing the functions and function flows.

You should NOT get out of the driver business. If you have time, it is a great learning experience!

3 Likes

NOTICE: We are now live with HPM. If you plan to use HPM for the application and some device handlers, it is very important you first do a "Match Up" and not a new Install. Otherwise you will end up with multiple copies loaded on your hub.

7 Likes

For additional OAuth child apps, do we need to create additional OAuth tokens on the ST side, or can the same token be used in multiple child apps?

Same PAT. Just hit the 'Authorize SmartThings Devices' button again and a new child will build.

1 Like

I tried this version of the driver and while Lock User Manager now opens it does not pull the user codes from the Replica Lock.

I tried putting my Schlage on Hubitat directly but it doesn't work well unless I bring the hub within a few feet of the lock. However it's been working well on Smartthings for 6 years. Not being able to trigger automation based on specific codes has been a major bummer for me.

1 Like