OpenGarage Forums Comments, Suggestions, Requests Request: SmartThings Integration

Viewing 25 posts - 1 through 25 (of 41 total)
  • Author
    Posts
  • #298

    jasonbade
    Participant

    I purchased the OpenGarage in hopes that I could integrate it with my SmartThings hub. I’ve played around with the SmartThings code all weekend, but with my beginner level scripting expertise, I can’t figure out how to get the SmartThings hub and OpenGarage to communicate effectively. SmartThings has a garage door controller capability, but I can’t figure it out.

    Has anyone written an integration with SmartThings for the OpenGarage that they would like to share? I saw the integration with IFTTT, but I would prefer all of the logic in my SmartThings hub.

    Attachments:
    You must be logged in to view attached files.
    #306

    Ray
    Keymaster

    The OpenGarage API is available here:
    https://openthings.freshdesk.com/solution/folders/5000283224
    everything is implemented through HTTP GET requests, which most services support.

    #443

    l0kisc0t
    Participant

    I’ve just written a device handler for the opengarage device for smarthings, which is working well for me.

    You can try it yourself here: https://github.com/littlegumSmartHome/opengarage.io-handler/tree/master

    Just create a device handle, copy this code in, and publish for your own use. Then add a device using the device handler and fill out the preferences.

    Cheers
    Ian

    #444

    l0kisc0t
    Participant

    screenshot of smartthings with the OpenGarage device added

    Attachments:
    You must be logged in to view attached files.
    #620

    kculhane
    Participant

    I used your code and it worked great! Thanks so much for posting it!

    #624

    l0kisc0t
    Participant

    No problems. Glad its working for you.

    I’ve been meaning to have a review of the code, as its not always refreshing correctly and it doesn’t do that automatically, so if you operate the garage door without using opengarage it doesn’t always report the correct status (or, at least, we’ve had one occasion where the app said the door was closed and it wasn’t).

    cheers
    Ian

    #657

    Ray
    Keymaster

    Thanks Ian for writing the sharing the code!

    #877

    ang3l12
    Participant

    So I just set up my open garage using this code, and for some reason it is always reporting that it is open, even though the API is showing “door”:0

    Could you possibly help me figure out this part of your code:

    def initialize() {
    	log.debug "initialize triggered"
        // initialize state
        state.doorStatus =  1 // 1 means open, 0 means closed
    	api("getstatus", [])

    I think it is pulling the 1 from the distance reading, here:
    {"dist":111,"door":0,"rcnt":X,"fwv":106,"name":"My OpenGarage","mac":"X","cid":X,"rssi":-58}

    instead of the “door”; is that possible that it could be the problem?

    #933

    Alonzo
    Participant

    Any fix to your problem of not reading the status correctly? I am having the same issue

    #935

    codahq
    Participant

    I had issues with this handler as well. I found a couple of problems but namely the methods in the device handler to convert the IP address to hex do not support IPs in the form of 10.*.*.* and other internal IP addresses. Here is a fork of Ian’s work that fixes this issue.

    https://github.com/codahq/opengarage.io-handler/blob/master/OpenGarage.io-handler.groovy

    #937

    Alonzo
    Participant

    Thanks codaHq!

    The code you posted worked for me. Only thing that could make it better is if the sensor could be polled every min or so. Seems that if I use my normal garage door opener smartthings is not refreshing the door status to tell me the state has changed. I have to hit the refresh button within smartthings to read the correct state. Thanks again codahq! It’s definitely closer to working perfectly for me.

    #938

    l0kisc0t
    Participant

    Apologies for the delay in replying and Thanks Codahq for tidying up and correcting my code – I’ve updated the handler to include your work.

    I’ll have a look at refreshing the door status automatically in the future….

    #947

    codahq
    Participant

    I made some more changes today. Instead of (or perhaps alongside) polling the OG for state I put logic in the device handler to refresh state before it blindly performs an open or close. If the door is found to be out of synchronization it updates the status and then decides whether or not the button should be pressed.

    I have implemented a way to poll the OG to synchronize its state as well but I don’t know if it’s best practice so I’m checking around before I push that change.

    I’m also considering implementing switch functionality so that an OG can be shared to Google Home through the SmartThings integration. It would be weird to use because you would be saying something like… “Hey, Google… turn on the garage door”. I tried creating an OOB automation with the OG’s device handler in it but for security reasons any routines with doors in them won’t share through the integration. I haven’t attempted the switch hack yet. There might be other weird restrictions that prevent it.

    https://github.com/codahq/opengarage.io-handler

    #957

    codahq
    Participant

    I added vehicle presence support today. Knock yourselves out.

    #958

    codahq
    Participant

    @Alonzo By the way, the polling I added is for every 5 minutes. I could add 1 minute but SmartThings has rate limits against device handler’s execution time and discourages frequent polling especially when doing it the way that I did it. I’ve been polling the last couple of days at 5 minutes and it feels good enough for me anyway.

    We can actually get away from polling if we want by having the OG send an update to the SmartThings hub but it would require a firmware change and I’m just too lazy to try to get the firmware compiling again. Maybe if you bug Ray or Jeff they’ll add it. It’s already very similar to the IFTTT and Blynk integrations.

    #960

    Alonzo
    Participant

    Thanks @codahq. I just saw this. I have just implemented this and will report back. Thanks again!

    #984

    lawrence_jeff
    Participant

    @codahq – Does smartthings support a webhook model? If so and you have the info handy could you point me to it

    I am having a problem with some of my polling where they pickup transient door states via the http endpoint – Opengarage itself is smart enough to filter these out and not update the actual door status but the door value in the API does temporarily update.

    Having a generic webhook type handler would avoid this constant polling and maybe help in your scenario as well

    #992

    codahq
    Participant

    @lawrence_jeff Yes, it does. It is pretty simple to register a URL for events if the URL is hosted on the SmartThings platform. Apparently it gets a little harder when you try to have a local device make calls at the SmartThings hubs directly.

    If you want to add something to the firmware that would be awesome. Here is some documentation here.

    http://docs.smartthings.com/en/latest/smartapp-web-services-developers-guide/tutorial-part1.html

    Essentially you would need to make a HTTP GET for each action to:
    https://${baseUrl}/api/smartapps/installations/${app.id}/${action}?access_token=${state.accessToken}

    The base URL will change depending on where you got hosted when you log into SmartThings first so it might be one of about 10 values. For example, mine is “graph-na02-useast1.api.smartthings.com” but my brother’s who lives only 30 miles away is different. The ${app.id} is the unique ID given to the SmartApp when it is setup in SmartThing’s API. This is different for every instance of the app. The action is whatever we decide we want to implement. I would suggest at a bare minimum we have a “open” and “close” action. ${state.accessToken} is an OAUTH token that you have to generate after installing the SmartApp.

    Please note, I am calling this part of the SmartThings integration a SmartApp instead of a Device Handler because from what I understand you can’t do this type of thing in a Device Handler. I could be wrong on that but that’s the gist after looking at a view examples. Full disclaimer, I am not an expert at SmartThings on any level. My first experience writing code for the platform is for the OpenGarage. I know this will work though… I setup a quick example to make sure I could hit the API and change the statuses on a virtual device with the following SmartApp code. This was mostly taken from another example I found on the SmartThings forum and modified to work for our purposes.

    /**
     *  OpenGarage SmartApp
     *
     *  Copyright 2018 Ben Rimmasch
     *
     */
    
    definition(
        name: "HTTP Open/Close Endpoint",
        namespace: "me.bendy.opengarage",
        author: "Ben Rimmasch",
        description: "Creates an HTTP motion endpoint for your OpenGarage",
        category: "Convenience",
        iconUrl: "https://need.an.icon.com/badly.png",
        iconX2Url: "https://need.an.icon.com/[email protected]"
    )
    
    preferences {
        page(name: "selectDevices", install: false, uninstall: true, nextPage: "viewURL") {
            section("Allow endpoint to control this thing...") {
                input "og", "capability.doorControl", title: "Which door controller is the OpenGarage?", required: true
                label title: "Assign a name", required: false
                mode title: "Set for specific mode(s)", required: false
            }
        }
        page(name: "viewURL", title: "viewURL", install: true)
    }
    
    def installed() {
        log.debug "Installed with settings: ${settings}"
    }
    
    def updated() {
        log.debug "Updated with settings: ${settings}"
        unsubscribe()
    }
    
    mappings {
        path("/open") {
            action: [
                GET: "openAction"
            ]
        }
        path("/close") {
            action: [
                GET: "closeAction"
            ]
        }
    }
    
    void openAction() {
        log.debug "Updated with settings: ${settings}"
        og?.open()
    }
    
    void closeAction() {
        log.debug "Updated with settings: ${settings}"
        og?.close()
    }
    
    def generateURL() {
        createAccessToken()
        ["https://graph.api.smartthings.com/api/smartapps/installations/${app.id}/open", "?access_token=${state.accessToken}"]
    }
    
    def viewURL() {
        dynamicPage(name: "viewURL", title: "HTTP Motion Endpoint", install:!resetOauth, nextPage: resetOauth ? "viewURL" : null) {
            section() {
                generateURL() 
                paragraph "Open: https://graph.api.smartthings.com/api/smartapps/installations/${app.id}/open?access_token=${state.accessToken}"
                paragraph "Close: https://graph.api.smartthings.com/api/smartapps/installations/${app.id}/close?access_token=${state.accessToken}"
            }
        }
    }
    #993

    codahq
    Participant

    The more I think about it the more I wonder if we shouldn’t just have the openGarage tell SmartThings when a refresh needs to happen and then the SmartThings can go ask the OpenGarage what values it has. I think this will work the best with the least amount of change on both sides.

    So, maybe:

    https://${baseUrl}/api/smartapps/installations/${app.id}/needs_update?access_token=${state.accessToken}

    Or something like that? What do you think?

    #999

    codahq
    Participant

    I did some searching around and I found a similar project that uses this approach. I think this will be okay. I have implemented a SmartApp already for this approach if you can get the firmware to call the URL.

    Here is the code for the SmartApp.

    https://github.com/codahq/opengarage.io-handler/blob/master/OpenGarage.io-smartapp.groovy

    In postman (or something similar) I was able to hit the URL that this SmartApp provided and SmartThings was responding appropriately and refreshing data from the device. @lawrence_jeff Can you make a firmware change then? Please let me know if you have any questions.

    Here is the URL the OG would need to GET:
    https://${base_api_url}/api/smartapps/installations/${app_instance_id}/do_update?access_code=${access_token}

    So, in the UI of the OG they would need to provide the base api URL, the app instance ID and the access token or alternatively just this entire URL with their info already in place.

    #1000

    lawrence_jeff
    Participant

    Yes – working on getting my dev environment back up based on 1.0.8.

    #1003

    lawrence_jeff
    Participant

    @codahq – One challenge off the bat is the HTTPS requirement of smart things, this isn’t available in the current OpenGarage codebase, as all the web calls it currently makes are http. Looks like the change to add SSL would eat a good bit of the ESP’s limited memory

    Is it an option to bridge via one of the existing supported solutions – for instance use the change notification to IFTTT to have it then call your update endpoint? Or I saw mention of a MQTT -> Smartbridge adapter that could potentially pickup the change notification from MQTT and then make the HTTPS call on the OG’s behalf

    The IFTTT option could at least operate without another device but the MQTT would need something on your network like Node-red to make the HTTPS call

    #1007

    codahq
    Participant

    @lawrence_jeff

    I guess I didn’t realize that the current integration calls weren’t HTTPS. I would prefer not to go through IFTTT but that is an option. There is probably a way for an IFTTT recipe to perform a GET to any given URL. Maybe the Maker channel does that already. I think MQTT or any proxy server is a lot of requirement to add because to me it feels like this should be more simple.

    How hard is it to do a HTTP POST with a JSON payload? I did some messing around and I was able to get the more complicated method of receiving local requests without going through the ST website. Everybody around the ST forums made it sound very complicated but it wasn’t bad. I was able to get a device handler to receive local requests. The trick was that the device network ID of the OG had to match the MAC address without the octet separator and it had to be in all caps. Then it was as easy as doing a POST in Postman to http://[internal_st_hub_ip]:39500/. The request had no authentication. It had just one header with Content-Type as “application/json” and then a body in JSON.
    The JSON it is expecting in the POST to do a refresh is { “refresh”: true }.

    I wrote this new local functionality into my device handler already. I had to change a few things in the current device handler to get this to work. For example, when an outbound request is made from the device the response is only routed to the correct device handler if the device’s device network ID is the IPinHex:PortinHex. I found out that routing also works if you use the MAC address as I described above. However, to receive inbound requests the device’s device network ID MUST be the MAC and not the IP:PORT so I adapted the code to use the IP:PORT until it could get the MAC from a “/jc” call and then fill it in so it could receive requests.

    Here is the link to the updated device handler.
    https://github.com/codahq/opengarage.io-handler/blob/master/OpenGarage.io-handler.groovy

    #1008

    lawrence_jeff
    Participant

    Doing an HTTP post with that bit of JSON is no issue, but I don’t follow this part
    The trick was that the device network ID of the OG had to match the MAC address without the octet separator

    What exactly do you mean when you say netwtork ID? Is it the user agent sent by OG in the web request, or from a network resolution standpoint your hub has to resolve the IP back to the name in form MAC Address…

    #1009

    codahq
    Participant

    @lawrence_jeff Ah, sorry for the confusion. It isn’t anything you have to handle in the request on the firmware side. If you are setting up the device in SmartThings it was something very specific that you have to do on the hub side. It was so specific in fact that I programmed around it making it easier for user by filling in values that work programmatically using the IP and port and then later putting the MAC address in there when it’s available from a response from the OG. The values had to be manipulated in a special way and wasn’t intuitive at all.

    For the firmware’s part it really is as simple as just the one header, the JSON payload and the destination address of http://[internal_st_hub_ip]:39500/ I think. The rest I’ll include as a write-up or something of how you have to configure the ST hub side. It’s actually very simple for the user now.

    By the way, the listening port on the ST hub is apparently variable so I made a printout on the ST side for the user to be able to see what it is. On the firmware side don’t append 39500 as a hardcode and let the user provide a string containing the the entire URL I think just to be safe.

    Please let me know if I haven’t cleared things up.

    • This reply was modified 6 years, 1 month ago by codahq.
Viewing 25 posts - 1 through 25 (of 41 total)
  • You must be logged in to reply to this topic.

OpenGarage Forums Comments, Suggestions, Requests Request: SmartThings Integration