Use my API as trigger?

I'm writing an API that's very similar to the one at Sunset and sunrise times API - Sunrise-Sunset.org , but is a bit different/custom for my own needs. I want to be able to write automations like "at the end of astronomical twilight, switch to the nighttime mode" or "at the start of civil twilight, turn this light on". Can someone please point me to documentation or examples on how to query my API from the Hubitat system (presumably Rule Machine) so I can use it as a trigger for rules like these?

(Note that the built-in sunrise/sunset feature won't meet my needs.)

Thanks!

How do you plan to provide access to your API? Will it be an HTTP REST-style interface or something else? What will the data format of the commands and responses be?

Are you set specifically on using RM? It might be easier in a custom driver and/or app, especially if you want to use webhooks to get events pushed to your hub.

If your system can hit an endpoint, you could use a cloud endpoint as a trigger for a RM rule (or a local endpoint if your system sending it is on the same LAN), like this:

Presumably, you'd have two of these, one for each of your values. Or you can use one and pass in a value through the url, which ends up in %value%. %value% can be put into a variable, and then tested in Conditional Actions....

Like this:

https://cloud.hubitat.com/api/xxxxxxx/apps/21073/trigger/ValueToPassIn?access_token=yyyyyyyyyyyy

1 Like

Here's an example with a local endpoint:

http://192.168.0.45/apps/api/21073/trigger/MyValuePassed_To_Rule?access_token=xxxxxx

Another way to do it is to create a virtual device of some sort, and set its value with Maker API. You would POST to Maker API to issue the device command, thus setting the device attribute state. That device could be used in automations as appropriate.

Yes, HTTP RESTful. See the link I provided as an example; I'm mimicking that closely, but returning additional info. Planning to return JSON response, but I can do whatever's best for Hubitat. I'm happy to use a custom driver or app if that's best; I know what I want to do but not how to do it!

Thanks. I'm going to have to read your examples a few more times to make sure I'm following. But I'm not following your question here, which is "your system" and which is "an endpoint"? My goal, if possible, is for Hubitat to call an API (like the one I linked), and not for an external service to call a Hubitat API.

You can have a rule do GET or a POST to an endpoint, but that's probably not going to get what you want. This is the domain of custom code.

Here's a quick example driver that shows how to query and parse the results. It will schedule to run every day at midnight or on demand with the Refresh command capability.

You'll probably want to peruse other docs and examples to see how to set values into custom attributes and then observe the events on those attributes in either built-in or custom apps.

/*

 */

metadata
{
    definition(name: "sunrise-sunset demo", namespace: "tomw", author: "tomw", importUrl: "")
    {
        capability "Refresh"
    }
}

preferences
{
    section
    {
        input "lat", "text", title: "lat", required: true
        input "lng", "text", title: "lng", required: true
        input name: "logEnable", type: "bool", title: "Enable debug logging", defaultValue: true
    }
}

def logDebug(msg) 
{
    if (logEnable)
    {
        log.debug(msg)
    }
}

def updated()
{
    refresh()
}

def refresh()
{
    unschedule()
    
    def respData = httpGetExec("lat=${lat}&lng=${lng}")
    if(respData)
    {
        logDebug("sunrise = ${respData?.results?.sunrise}")
    }
    
    // run every day at midnight
    schedule("0 0 0 * * ?", refresh)
}

def uninstalled()
{
    unschedule()
}

def getBaseURI()
{
    return "https://api.sunrise-sunset.org/json?"
}

def httpGetExec(suffix)
{
    logDebug("httpGetExec(${suffix})")

    try
    {
        def getURI = (getBaseURI() + suffix).replaceAll(' ', '%20')
        httpGet(getURI)
        { resp ->
            if (resp.data)
            {
                logDebug("resp.data = ${resp.data}")
                return resp.data
            }
        }
    }
    catch (Exception e)
    {
        logDebug("httpGetExec() failed: ${e.message}")
    }
}
2 Likes

@tomw So it seems like writing a custom driver is the way to go? Thank you! I have a lot to learn before I can finish this on my own, but I appreciate you starting me down the right path.

It all depends on how you want it to work.

If you want Hubitat to query your API, a custom driver seems like the right path. If you didn't control the API server implementation (for example, if you were using the stock sunrise-sunset API), this would possibly be the only option.

However, as @bravenel pointed out, if you have the ability to have your API server push specific updates to Hubitat, there are multiple ways that you could achieve that without custom code on Hubitat. You might prefer that path for various reasons.

1 Like