Holdable and Releasable Button

From the event log you posted, Dashboard appears to be working fine. Is this the same driver as the one that should be sending the "real" commands? If so, you have some problem there. Adding some logging to your app to debug things yourself may help (can't do much without the code).

If not, you must have some other device (and its driver) involved, but from your screenshots, no automation is set up to respond to these button events and do something with a other device. I can say this because there are no "Triggered apps" in your screenshot.

Yes, there is only one drive and one device using this driver ("Projector Screen").
Here is the current driver code (essentially the same as in my original post):

/*
*    iTach iP2CC Driver for Projector Screen Control
*    Screen uses Port 1 for UP trigger and Port 2 for DOWN Trigger
*    To stop the screen both ports must be triggered
 */


@SuppressWarnings('unused')
static String version() {return "0.0.1"}

metadata {
    definition (
        name: "iTach iP2CC", 
        namespace: "uw", 
        author: "U W",
        importUrl:"na"
    ) {
        
        capability "Telnet"
        capability "Initialize"
        capability "Switch"
        capability "PushableButton"
        
        attribute "Port1", "ENUM", ["on", "off"]
        attribute "Port2", "ENUM", ["on", "off"]
        attribute "lastMessage", "STRING"
        attribute "pushed", "NUMBER"
        attribute "numberOfButtons", "NUMBER"

        command "connectTelnet"
        command "disconnectTelnet"
        command "p1On"
        command "p1Off"
        command "p2On"
        command "p2Off"
        command "ScreenUP"
        command "ScreenDOWN"
        command "ScreenSTOP"

    }   
}

preferences {

    input(name: "ipAddr", type: "string", title:"IP Address", required: true)
    input(name: "portNum", type: "number", title: "Port Number", required: true)
}

@SuppressWarnings('unused')
def installed() {

}

def initialize(){
    connectTelnet()
    log.debug "----- INITIALIZING TELNET -----"
}

void updateAttr(String aKey, aValue, String aUnit = ""){
    sendEvent(name:aKey, value:aValue, unit:aUnit)
}

def connectTelnet(){
    try{
        telnetConnect([termChars:[10]], ipAddr, (int)portNum, null, null)
    } catch (ex) {
        updateAttr("lastMessage", ex)
    }
    updateAttr("switch", "on")
}

def disconnectTelnet() {
    telnetClose()
    updateAttr("switch", "off")
}

def sendMsg(message) {
    sendHubCommand(new hubitat.device.HubAction("""$message\r\n""", hubitat.device.Protocol.TELNET))
}

def p1On(){
    sendMsg("setstate,1:1,1")
    updateAttr("Port1", "On")
}

def p1Off(){
    sendMsg("setstate,1:1,0")
    updateAttr("Port1", "Off")
}

def p2On(){
    sendMsg("setstate,1:2,1")
    updateAttr("Port2", "On")
}
               
def p2Off(){
    sendMsg("setstate,1:2,0")
    updateAttr("Port2", "Off")
}

def ScreenUP(){
    p1On()
    runInMillis(100,p1Off)
    log.debug "----- Screen UP -----"
}

def ScreenDOWN(){
    p2On()
    runInMillis(100,p2Off)
    log.debug "----- Screen DOWN -----"
}

def ScreenSTOP(){
    p1On()
    p2On()
    runInMillis(500,p1Off)
    runInMillis(500,p2Off)
    log.debug "----- Screen STOP -----"
}

def push(button){
    if (button == 1){ScreenUP()}
    if (button == 2){ScreenDOWN()}
    if (button == 3){ScreenSTOP()}
}

def parse(message) {
    updateAttr("parsedMessage", message)
}

def telnetStatus(message){
        updateAttr("statusMessage", message)
}

There are no other apps involved in this setup. The Dashboard tile is expected to trigger the device directly.

I don't see anything glaringly obviously wrong, so I'd suggest:

Specifically, you can do things like sprinkle log.trace entries throughout so you can see what is (or isn't) running when, what the values of objects that matter are, or anything else that is helpful, then go from there.

Issue resolved! (with a caveat)

I went ahead and added

    log.trace "----- Push -----"

to the driver 's "push" definition.

The trace did appear in the logs when the tile was triggered, but none of the conditions were executed.

So I tried changing from integer to string values, as such:

    if (button == "1"){ScreenUP()}
    if (button == "2"){ScreenDOWN()}
    if (button == "3"){ScreenSTOP()}

Now the Tiles work.
BUT, the Push command from the Device does not. So the Tile only takes strings, the device Push command only integers.
Smells like a BUG to me.

Sorry, I meant driver (but otherwise the same idea).

Seems like you have a solution now? Not sure about the data types, but I'd always be prepared to handle about anything given how Groovy is. :slight_smile:

I think this is more of a workaround.
The Dashboard code needs to be updated to pass numbers as integers, not strings.

While that may be helpful, with any Hubitat command that accepts numbers, I would also be prepared to parse them out of a string, given both the dynamic nature of Groovy and the fact that sometimes these values will come in via means that do not have any inherent types at all (e.g., as part of a URL query string via Maker API), so you never really know what you're going to get.

1 Like

So there still seems to be a bigger problem with how Hubitat handles pushable buttons.
When I try to create a Basic Rule with an action "Push button," the system is not accepting any numbers.

I try to enter "1" or "2", for example, and after clicking "save" the field resets, indicating that it is not a passing validation. Why not?
This seems to be related to the same thing happening under the Dashboard.

I don't think so; this looks like a problem with the driver you're using. What is the value of the numberOfButtons attribute (as seen under "Current States") on the device detail page?

Hmm... This does not show up under Current States.

If you look at the driver code I attached, I do have:

 attribute "numberOfButtons", "NUMBER"

Do I need to specify the actual number value instead of "NUMBER"?

That looks like you are declaring a custom attribute. You don't need to do that; it comes as part of "PushableButton". What you do need to do is actually provide a value for that attribute. For this particular attribute on button devices, that is often done in configure() or something else that will be called on installation, or possibly also updated() if you don't have that method/capability in your driver.

Wherever you do it, this is done via sendEvent() like any other attribute, e.g., sendEvent(name: "numberOfButtons", value: 1) (or however many buttons you have).

Thank you!
It is now showing up under the device.

However, I went to modify a Basic Rule and once I added action "Push Button" and selected the button device, the system threw up an error:

I am not able to edit or delete that rule anymore. Logs don't seem to show anything more specific. Rebooting the hub does not help.

Interestingly, when I go to create a new Basic Rule, the "Push Button" is now working...

So is there any way to delete a Basic Rule that is throwing up an error like this?

1 Like

Yes, use the App Status page (accessible from the gear-looking icon next to the app in the Apps list or the top right of the page, which I think you‘ll still see even if there is an error).

1 Like

FWIW HD+ supports push, hold and doubleTap commands for any button - Buttons - HD+ (Hubitat Dashboard)

1 Like

Looks like that's an android only thing...unfortunately.