Integration to Delta VoiceIQ

Sure, that would work, but it's tedious for the user. It would be useful to know whether this limit is there for a good reason by Hubitat or if it could be increased.

Another way to do it would be to save the token as a data value (using a device command) and then recalling it from there when needed. That's a workaround to be clear and feels a bit hacky, but it works.

It could work like in this version (note that the saveToken command must be used to store the token, and the preferences input is removed):

import groovy.json.JsonSlurper
import groovy.transform.Field

metadata {
    definition(name: "Delta Faucet Driver with Token Prompt", namespace: "your.namespace", author: "Author Name") {
        capability "Switch"
        
        command "saveToken", ["token"]
    }
}

preferences {
    input("delta_device_id", "text", title: "Delta Device ID", description: "Enter Delta Device ID", defaultValue: "")
}

def installed() {
    log.debug "Installed"
}

def updated() {
    log.debug "Updated"
}

def on() {
    toggleWater("on")
}

def off() {
    toggleWater("off")
}

def saveToken(token)
{
    device.updateDataValue("token", token)
}

def currentToken()
{
    return device.getDataValue("token")
}

private toggleWater(String toggle) {
    def deviceId = delta_device_id
    def deltaToken = "Bearer ${currentToken()}"
    def apiUrl = "https://device.legacy.deltafaucet.com/api/device/toggleWater?deviceId=${deviceId}&toggle=${toggle}"
    def headers = [
        'Authorization': deltaToken, 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/110.0.0.0 Safari/537.36',
        'Referer': 'https://device.legacy.deltafaucet.com/'
    ]
    
    try {
        def response
        httpPost(uri: apiUrl, headers: headers)
        
        {
        resp ->
        response = resp
        }
        
        if (response.status == 200) {
            def parsedResponse = new JsonSlurper().parseText(response.data)
            if (parsedResponse.success) {
                log.debug "Toggle water ${toggle} successful"
            } else {
                log.error "Toggle water ${toggle} failed: ${parsedResponse.error}"
            }
        } else {
            log.error "Toggle water ${toggle} failed: ${response.status}"
        }
    } catch (Exception e) {
        log.error "Error toggling water: ${e.message}"
    }
}

Bummer. I cannot get it to work on mine. I'm not sure what I'm doing it wrong.

Will try @vitaliy_kh 's examples on HA later and see if I can at least get it to work there.

[Edit] Looks like I have a version 2. I’ve had it for several years, but I guess I got one of the first v2 ?
Wrong, I have version 1

Many BIG Thanks to @tomw and @Sebastien
OK, I tried this updated driver and it works but produces an error for each sent command:
image

This is not a big deal but better to be suppressed.
Otherwise I already like this driver.
And I guess, it should not be a big deal to add a dispensing capability.
The command is something like this:

https://device.legacy.deltafaucet.com/api/device/dispense?deviceId={{states.input_text.delta_device_id.state}}&milliliters={{mililiters}}

URL is slightly different and requires a desired dispense quantity parameter.

response.status must be responding as set to some value other than 200. Someone with a faucet could track that down as part of the cleanup that @Sebastien mentioned. :sunglasses:

1 Like

OK, I sent On/Off commands from the web GUI.
Here is a response (if I looked in a right place):

image

"{\"Success\":true,\"Message\":\"\"}"

That's the data payload. You actually want the HTTP status code if you can find it.

Alternatively, you could add this to the Hubitat driver code to the line immediately before the status checking code:

log.debug response.status

1 Like

Here's what I tried:

log.debug response.status
log.debug response.data
log.debug response.error
log.debug response[1]

I wonder if the JsonSlurper().parseText() might not be working? The response.status does indicate success it seems...

So:
response.status = 200
log.debug response.data = {"Success":true,"Message":""}
log.debug response.error = nothing?
log.debug response[1] = nothing?

This is an exact response I got from GUI:

"{\"Success\":true,\"Message\":\"\"}"
But each " was \"

1 Like

This seems correct in the debug log, so I'll bet there's a type mismatch that is causing the check to fail.

Try this:

if(response?.status?.toInteger() == 200)

1 Like

Made the change - the error remains:

What I have now:

    try {
        def response
        httpPost(uri: apiUrl, headers: headers)
        
        {
        resp ->
        response = resp
        }
 
        log.debug response.status
        log.debug response.data

        if(response?.status?.toInteger() == 200) {
            def parsedResponse = new JsonSlurper().parseText(response.data)
            if (parsedResponse.success) {
                log.debug "Toggle water ${toggle} successful"
            } else {
                log.error "Toggle water ${toggle} failed: ${parsedResponse.error}"
            }
        } else {
            log.error "Toggle water ${toggle} failed: ${response.status}"
        }
    } catch (Exception e) {
        log.error "Error toggling water: ${e.message}"
    }
}

Error with this code:

image

From what I gather, the following if condition is not successful:
if (parsedResponse.success)

And the parsedResponse.error is null

Updating to:

else {
                log.error "Toggle water ${toggle} failed: parsedResponse.success: ${parsedResponse.success}, Response.error: ${parsedResponse.error}"
            }

I get:

Ah, I didn't look low enough. That parseResponse.success is probably the issue. Just try this stripped down approach:

if(response?.status?.toInteger() == 200)
{
    log.debug "Toggle water ${toggle} successful"
}
else
{
   log.error "Toggle water ${toggle} failed: ${response.status}"
}
catch (Exception e)
{
        log.error "Error toggling water: ${e.message}"
}
1 Like

Yup! That worked.

Sorry - I found the issue... a } was missing before "Catch". Fixed it. :slight_smile:

1 Like

I cannot see what is on the label but my toy was ordered on January 20, 2022
I guess, the part number is EP100855 (from Amazon order).

1 Like

Could you please, post final clean code (when debugging is finished)?

1 Like

I've added the Github link in the first post. Here is the direct link to the code import:

https://raw.githubusercontent.com/SebastienViel/Hubitat_Delta_Faucet/main/Hubitat_Delta_Faucet_Driver

1 Like

Very nice job @Sebastien and @tomw
I reimported the driver and now it works very well, no more errors, everything looks nice and clean.
The response time is sub second vs about 3-4 seconds with Alexa in a middle.

Now to complete a picture it will be nice to add a "Dispense Amount" command.
The URL (command) is:

https://device.legacy.deltafaucet.com/api/device/dispense?deviceId=<Device_ID>&milliliters=AMOUNT

AMOUNT is a desired water volume to dispense in milliliters

I think, it should work (don't see why it will not).

@Sebastien could you please add this command (now you are the driver codding expert)?

3 Likes

Yea, good idea! Do you know if there are any other commands, or ways to poll the device somehow?

It works! :smiley:

Not sure what the difference was, but I was getting an authorization error. Using the latest code it now works for me too. Super happy with this. Dispense amounts with be the pièce de résistance.

1 Like