OpenGarage 2.0 Support

Here is some rough code. Paste into the Driver Code section, save and then go to Devices and add a virtual device with the Open Garage as the device type (should be at/near the bottom of the list).

Code
/*
 * Open Garage
 *
 *  Licensed Virtual 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.
 *
 *  Change History:
 *
 *    Date        Who            What
 *    ----        ---            ----
 * 
 */

import groovy.json.JsonSlurper
static String version()	{  return '0.0.1'  }

metadata {
    definition (
		name: "Open Garage", 
		namespace: "thebearmay", 
		author: "Jean P. May, Jr.",
	        importUrl:"https://raw.githubusercontent.com/thebearmay/hubitat/main/xxxx.groovy"
	) {
        capability "Actuator"
        capability "Polling"
        
        attribute "door", "string"
        attribute "distance", "number"
        attribute "vehStatus", "string"
        attribute "rssi","number"
        
        command "close"
        command "toggleDoor"
        command "rebootDevice"
    }   
}

preferences {
    input("devIP", "string", title: "IP of the Open Garage Device", width:4)
    input("devPwd", "password", title: "Device Password", width:4)
    input("pollRate","number", title: "Polling interval in seconds (0 to disable)", width:4)
	input("debugEnable", "bool", title: "Enable debug logging?",width:4)
}

def installed() {
    log.trace "Open Garage v${version()} installed()"
    device.updateSetting("devIP",[value:"192.168.4.1",type:"string"])
    device.updateSetting("devPwd",[value:"opendoor",type:"password"]) 
    device.updateSetting("pollRate",[value:0,type:"number"]) 
}

def updated(){
    log.trace "updated()"
    if(debugEnable) 
        runIn(1800,"logsOff")
    else 
        unschedule("debugEnable")
    if(pollRate > 0)
        runIn(pollRate, "poll")
    else
        unschedule("poll")
    
}


void close() {
    if(debugEnable) log.debug "closing.."
    httpGet(
        [
            uri: "http:$devIP",
            path: "/cc?dkey=$devPwd&close=1",
            headers: [            
                   Accept: "application/json"
            ]
        ]
    ) { resp -> }
    runIn(10,"poll")
  
}

void toggleDoor() {
    if(debugEnable) log.debug "toggle door.."
    httpGet(
        [
            uri: "http://$devIP",
            path: "/cc?dkey=$devPwd&click=1",
            headers: [            
                   Accept: "application/json"
            ]
        ]
    ) { resp -> }
    runIn(10,"poll")
  
}

void rebootDevice() {
    if(debugEnable) log.debug "rebooting.."
    httpGet(
        [
            uri: "http://$devIP",
            path: "/cc?dkey=$devPwd&reboot=1",
            headers: [            
                   Accept: "application/json"
            ]
        ]
    ) { resp -> }
    runIn(30,"poll")
  
}

void setStatus(dStat){
    sendEvent(name:"door", value:dStat)
}

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

void poll(){
    httpGet(
        [
            uri: "http://$devIP",
            path: "/jc",
            headers: [            
                   Accept: "application/json"
            ]
        ]
    ) { resp ->
        try{
            if (resp.getStatus() == 200){
                if (debugEnable) 
                    log.debug resp.data
                def jSlurp = new JsonSlurper()
                Map retData = (Map)jSlurp.parseText((String)resp.data)
                processJc(retData)
            }
        }catch (ex) {
            log.error "$ex"
        }
    }
}

void processJc(dMap){
    updateAttr("distance", dMap.dist, "cm")
    if(dMap.door == 1)
        updateAttr("door","open")
    else
        updateAttr("door", "closed")
    if(dMap.vehicle == 1)
        updateAttr("vehStatus", "present")
    else 
        updateAttr("vehStatus", "not present")
    updateAttr("rssi", dMap.rssi, "dBm")
}

void logsOff(){
     device.updateSetting("debugEnable",[value:"false",type:"bool"])
}
1 Like

I received the errors below and then realized I didn't have the device powered on :confused:

After powering on the device, I received the same errors.

I fat fingered the GET call; corrected the code above so if you re-copy and paste it we should get something different.

Looks like the return format is JSON like, but isn't delimited with quotes. I'll need to make a small adjustment to the code.

New set of code at (should be able to import using the address below):

https://raw.githubusercontent.com/thebearmay/hubitat/main/openGarage.groovy

Fixed...

Hmmm. Maybe now.

It worked :partying_face:

1 Like

Reboot button doesn't work:

Is there supposed to be an Open button or just Close?

Just saw that it does have an open - API had examples for Close, Toggle and Reboot, but not Open so I removed it, give me a minute and I'll put it back.

New version...

Open button is now available. Reboot still generates error.

I'll install the device and start testing...

1 Like

Interesting the Reboot is on the same endpoint as the open/close wonder if it's just not implemented.

Reboot works from the device's UI.

Poll is returning vehicle:1 but the Device page still states 'not present':


image

Made a small change, see if it registers correctly now.

That worked :slight_smile:

but polling doesn't appear to be working. I've set it to 10 seconds with debug enabled but I'm only getting Log entries if I manually click the Poll button.

DUH!!! I forgot to resubmit...

Fixed