Simple URI/Json Switch Device Handler: help needed


(Neil) #1

Hi All,

I am fairly new to SmartThings and not a programmer by profession.

I have been using a lovely simple Device Handler (URI Switch by tguerena), which works perfectly and reliably for my application.

Recently I purchased some different URI switches (www.dfrobot.com DFR289) which require Json to control them. I thought this would be easy to sort out. I have the switches online and working, using the native supplied app. I also have the Json strings needed. However, I can’t find a simple example for a URI/Json Switch Device Handler and am tying myself in knots trying to write one. My total effort is below. Can someone please point me in the right direction as I am totally confused trying to understand how to implement the SmartThings developers documentation for Json.

Thanks in advance

/*

  • Author: N Vass
  • Json Switch Device Handler
    */

preferences {

section("Internal Access"){
	input "internal_ip", "text", title: "Internal IP", required: false
	input "internal_port", "text", title: "Internal Port (if not 80)", required: false
	input "json_on", "text", title: "On Json", required: false
	input "json_off", "text", title: "Off Jason", required: false
}

}

metadata {
definition (name: “Json Switch v4”, namespace: “NVass”, author: “N Vass”) {
capability “Actuator”
capability “Switch”
}

// simulator metadata
simulator {
}

// UI tile definitions
tiles {
	standardTile("button", "device.switch", width: 2, height: 2, canChangeIcon: true) {
		state "off", label: 'Off', action: "switch.on", icon: "st.switches.switch.off", backgroundColor: "#ffffff", nextState: "on"
			state "on", label: 'On', action: "switch.off", icon: "st.switches.switch.on", backgroundColor: "#79b821", nextState: "off"
	}
	standardTile("offButton", "device.button", width: 1, height: 1, canChangeIcon: true) {
		state "default", label: 'Force Off', action: "switch.off", icon: "st.switches.switch.off", backgroundColor: "#ffffff"
	}
	standardTile("onButton", "device.switch", width: 1, height: 1, canChangeIcon: true) {
		state "default", label: 'Force On', action: "switch.on", icon: "st.switches.switch.on", backgroundColor: "#79b821"
	}
	main "button"
		details (["button","onButton","offButton"])
}

}

def parse(String description) {
log.debug(description)
}

def on() {
if (json_on){
def port
if (internal_port){
port = “${internal_port}”
} else {
port = 80
}

	def result = new physicalgraph.device.HubAction(
			method: "POST",
			body: "${json_on}",
			headers: [
			HOST: "${internal_ip}:${port}"
			]
			)
		sendHubCommand(result)
		sendEvent(name: "switch", value: "on") 
		log.debug "Executing ON" 
		log.debug result
}

}

def off() {
if (json_off){
def port
if (internal_port){
port = “${internal_port}”
} else {
port = 80
}

	def result = new physicalgraph.device.HubAction(
			method: "POST",
			body: "${json_off}",
			headers: [
			HOST: "${internal_ip}:${port}"
			]
			)

		sendHubCommand(result)
		sendEvent(name: "switch", value: "off")
		log.debug "Executing OFF" 
		log.debug result
}

}


(Neil) #2

I added my code to github so it should be more readable now.


(Eric) #3

Can you post a direct link to the devices you are working with? What values are you putting in json_on and json_off?

You should consider updating this to use the Async-api smartthings has provided.

Here is an example from my code:

def effect = "breathe"
def commands = ["color" : "brightness:${brightness1}", "from_color" : "brightness:${brightness2}", "cycles" : "${cycles}" ,"period" : "${period}"]
def params = [
    uri: "https://api.lifx.com",
		path: "/v1/lights/" + getGroups() + "/effects/" + effect,
    headers: ["Content-Type": "application/json", "Accept": "application/json", "Authorization": "Bearer ${token}"],
    body: commands
]

asynchttp_v1.post('postResponseHandler', params)

Maybe your code should look like…

def commands = ["<<Your JSON>>" Format it like mine]
def params = [
    uri: "${internal_ip}:${port}",
    headers: ["Content-Type": "application/json", "Accept": "application/json"],
    body: commands
]
asynchttp_v1.post('postResponseHandler', params)

Here is my full code.


(Neil) #4

Wow thanks.

Your example is lovely and clear. I am pretty sure I can get it working now. I will let you know once I have had a chance to try it out.

The device can be found here:

https://www.dfrobot.com/product-1218.html

Its an 8 way switch. As I am using it for irrigation the 24v Valve PSU and my water pump can only cope with one valve at a time, so I am planning to setup 8 different Device Handlers such that they always turn off the other relays. The example below would be for relay 6.

json_on

{“relay1”:“off”,“relay2”:“off”,“relay3”:“off”,“relay4”:“off”,“relay5”:“off”,“relay6”:“on”,“relay7”:“off”,“relay8”:“off”}

json_off

{“relay1”:“off”,“relay2”:“off”,“relay3”:“off”,“relay4”:“off”,“relay5”:“off”,“relay6”:“off”,“relay7”:“off”,“relay8”:“off”}


(Eric) #5

Keep in mind in order for the asych-api to work you have to include this line in your code:


(Neil) #6

Well I’ve had several more goes having studied your code, but it’s still not working.

Ltest Version:

Maybe it’s the Json string I am using. This is where I got the info from:

Sorry, I thought I would be able to crack it with your previous post. It just shows how little I know!


(Eric) #7

Can you post here the specific strings you are using in the settings for on and off?

Also, I modified your code on my fork in github. I just hard coded a few things to try something out and added a postResponseHandler method. I also commented out the sendHubCommand.

Try this code. Tell me if it works. I only made it act on the first 4 relays. If you want all 8 to test, you will be able to see how to adjust it.


(Neil) #8

Hi,

Tried your code after amending the Json string to 8 Relays (The format I am sure is correct)

However, it’s throwing the following errors when I try activating the switch and its not turning the relay on or off.

b4422baa-c171-4472-a6ac-cf3221331000 2:24:59 PM: error java.lang.IllegalArgumentException: uri is required @line 93 (off)

b4422baa-c171-4472-a6ac-cf3221331000 2:24:59 PM: debug [uri:192.168.0.34:30405, headers:[Content-Type:application/json, Accept:application/json], body:[relay1:off, relay2:off, relay3:off, relay4:off, relay5:off, relay6:off, relay7:off, relay8:off]]

b4422baa-c171-4472-a6ac-cf3221331000 2:24:59 PM: debug Executing OFF

b4422baa-c171-4472-a6ac-cf3221331000 2:20:27 PM: error java.lang.IllegalArgumentException: uri is required @line 69 (on)

b4422baa-c171-4472-a6ac-cf3221331000 2:20:27 PM: debug [uri:192.168.0.34:30405, headers:[Content-Type:application/json, Accept:application/json], body:[relay1:off, relay2:off, relay3:off, relay4:off, relay5:off, relay6:on, relay7:off, relay8:off]]

b4422baa-c171-4472-a6ac-cf3221331000 2:20:27 PM: debug Executing ON

From my limited knowledge, the syntax looks OK and I can’t see whats wrong. Sorry.

Thanks for your ongoing help.


(Neil) #9

You also asked about the specific strings:

This is the example from the instruction manual that I posted as PDF yesterday.

2.JSON Communication Format

*Set relay state (on is open, off is closed).
Example Send Correct Command:
{“relay1”:“on”,“relay2”:“off”,“relay3”:“off”,“relay4”:“on”,“relay5”:“on”,"
relay6":“on”,“relay7”:“off”,“relay8”:“off”}

I have been using Relay 6 as my test case so

On is:
[“relay1”:“off”,“relay2”:“off”,“relay3”:“off”,“relay4”:“off”,“relay5”:“off”,“relay6”:“on”,“relay7”:“off”,“relay8”:“off”]

Off is:
[“relay1”:“off”,“relay2”:“off”,“relay3”:“off”,“relay4”:“off”,“relay5”:“off”,“relay6”:“off”,“relay7”:“off”,“relay8”:“off”]

Just wondering if the curly brackets in the example are important as I assumed square brackets!


(Eric) #10

Sorry, I just realized a mistake in my code. I didn’t change the name of the variable from result to params. Try this.

If that doesn’t work, I created a DH that controls only a single relay of the device. So if you have 8 relays you will need 8 devices in ST. That might make more sense anyways. Try this one also.

Make sure you adjust the settings, something like this…


(Neil) #11

Sorry for the delay in getting back to you. I have been away for the weekend and only just got back to this.

I tried both sets of code.

The first one gave the following errors:

75a3d34e-42d4-4f95-a136-cfa366f66f48 1:06:57 PM: error POST Error: java.net.ConnectException

75a3d34e-42d4-4f95-a136-cfa366f66f48 1:06:57 PM: error POST Error: java.net.ConnectException

75a3d34e-42d4-4f95-a136-cfa366f66f48 1:06:52 PM: debug [uri:http://192.168.0.34:30405, headers:[Content-Type:application/json, Accept:application/json], body:[relay1:off, relay2:off, relay3:off, relay4:off, relay5:off, relay6:off, relay7:off, relay8:off]]

75a3d34e-42d4-4f95-a136-cfa366f66f48 1:06:52 PM: debug Executing OFF

75a3d34e-42d4-4f95-a136-cfa366f66f48 1:06:46 PM: error POST Error: java.net.ConnectException

75a3d34e-42d4-4f95-a136-cfa366f66f48 1:06:46 PM: error POST Error: java.net.ConnectException

75a3d34e-42d4-4f95-a136-cfa366f66f48 1:06:41 PM: debug [uri:http://192.168.0.34:30405, headers:[Content-Type:application/json, Accept:application/json], body:[relay1:off, relay2:off, relay3:off, relay4:off, relay5:off, relay6:on, relay7:off, relay8:off]]

75a3d34e-42d4-4f95-a136-cfa366f66f48 1:06:41 PM: debug Executing ON

And the second one these errors.

033e597e-11a6-48de-bf4e-c004c4f9ef57 1:13:13 PM: error POST Error: null

033e597e-11a6-48de-bf4e-c004c4f9ef57 1:13:13 PM: info uri_switch.v0.1.0.20180824.Valve Test 2>>> Sending Off as part of the off event.

033e597e-11a6-48de-bf4e-c004c4f9ef57 1:12:58 PM: error POST Error: null

033e597e-11a6-48de-bf4e-c004c4f9ef57 1:12:58 PM: info uri_switch.v0.1.0.20180824.Valve Test 2>>> Sending On as part of the on event.

I really appreciate your help with this. I would have given up by now if it wasn’t for your help. I am actually learning quite a lot trying to figure out how your code works.

Not sure where you are but I recon I owe you a beer or two!


(Eric) #12

Can you sent the debug level of the second one to DEBUG? I don’t see any debug logs in there for the second one.

I’ve also updated both version of the app in my github for better logging and fixed something. Try again.

Also, post a picture of your settings like I did.


(Neil) #13

Info as Requested.

Version 1

75a3d34e-42d4-4f95-a136-cfa366f66f48 5:15:36 PM: error POST Error: java.net.ConnectException

75a3d34e-42d4-4f95-a136-cfa366f66f48 5:15:36 PM: error POST Error: java.net.ConnectException

75a3d34e-42d4-4f95-a136-cfa366f66f48 5:15:30 PM: debug [uri:http://192.168.0.34:30405, headers:[Content-Type:application/json, Accept:application/json], body:[relay1:off, relay2:off, relay3:off, relay4:off, relay5:off, relay6:off, relay7:off, relay8:off]]

75a3d34e-42d4-4f95-a136-cfa366f66f48 5:15:30 PM: debug Executing OFF

75a3d34e-42d4-4f95-a136-cfa366f66f48 5:15:26 PM: error POST Error: java.net.ConnectException

75a3d34e-42d4-4f95-a136-cfa366f66f48 5:15:26 PM: error POST Error: java.net.ConnectException

75a3d34e-42d4-4f95-a136-cfa366f66f48 5:15:20 PM: debug [uri:http://192.168.0.34:30405, headers:[Content-Type:application/json, Accept:application/json], body:[relay1:off, relay2:off, relay3:off, relay4:off, relay5:off, relay6:on, relay7:off, relay8:off]]

75a3d34e-42d4-4f95-a136-cfa366f66f48 5:15:20 PM: debug Executing ON

The second Version:

033e597e-11a6-48de-bf4e-c004c4f9ef57 5:21:32 PM: error POST Error: java.net.ConnectException

033e597e-11a6-48de-bf4e-c004c4f9ef57 5:21:32 PM: error POST Error: java.net.ConnectException

033e597e-11a6-48de-bf4e-c004c4f9ef57 5:21:27 PM: info uri_switch.v0.1.0.20180824.Valve Test 2>>> Sending Off as part of the off event.

033e597e-11a6-48de-bf4e-c004c4f9ef57 5:21:27 PM: debug uri_switch.v0.1.0.20180824.Valve Test 2>>> Params = [uri:http://192.168.0.34:30405, headers:[Content-Type:application/json, Accept:application/json], body:[relay6:Off]]

033e597e-11a6-48de-bf4e-c004c4f9ef57 5:21:27 PM: debug uri_switch.v0.1.0.20180824.Valve Test 2>>> Commands = [relay6:Off]

033e597e-11a6-48de-bf4e-c004c4f9ef57 5:21:20 PM: error POST Error: java.net.ConnectException

033e597e-11a6-48de-bf4e-c004c4f9ef57 5:21:20 PM: error POST Error: java.net.ConnectException

033e597e-11a6-48de-bf4e-c004c4f9ef57 5:21:15 PM: info uri_switch.v0.1.0.20180824.Valve Test 2>>> Sending On as part of the on event.

033e597e-11a6-48de-bf4e-c004c4f9ef57 5:21:15 PM: debug uri_switch.v0.1.0.20180824.Valve Test 2>>> Params = [uri:http://192.168.0.34:30405, headers:[Content-Type:application/json, Accept:application/json], body:[relay6:On]]

033e597e-11a6-48de-bf4e-c004c4f9ef57 5:21:15 PM: debug uri_switch.v0.1.0.20180824.Valve Test 2>>> Commands = [relay6:On]


(Neil) #14

Just realised the On Json and Off Json should be all lower case in the second version. I have corrected and tried again. It makes no difference.


(Eric) #15

Ok, try this now…


(Neil) #16

When I try to save the code it throws the following error!

org.codehaus.groovy.control.MultipleCompilationErrorsException: startup failed:
script_dth_metadata_6f12b6e9_6526_4b12_a8bf_26c00fc3bff7: 121: unable to resolve class JsonBuilder
@ line 121, column 17.
def commands = new JsonBuilder()
^

1 error


(Eric) #17

Try this…


(Neil) #18

Its still throwing an error:

org.codehaus.groovy.control.MultipleCompilationErrorsException: startup failed:
script_dth_metadata_425c3cbf_11f8_4eb4_867c_c5cac666cf9c: 121: unable to resolve class JsonBuilder
@ line 121, column 17.
def commands = new JsonBuilder()
^

1 error


(Eric) #19

Ok, sorry about all those iterations. I was trying to edit and debug from my phone on a plane from India back to the US. Probably not a good idea. Anyways, a couple of small mistakes due to not being able to see the code on a larger screen. I think this should work now.


(Neil) #20

Morning Eric,

Your code looks to be working well now:

afcfd820-a8a1-46cc-ab00-a846e687840f 11:58:20 AM: info uri_switch.v0.1.0.20180901.Valve test 3>>> Sending off as part of the off event.

afcfd820-a8a1-46cc-ab00-a846e687840f 11:58:20 AM: debug uri_switch.v0.1.0.20180901.Valve test 3>>> Commands = {“relay6”:“off”}

afcfd820-a8a1-46cc-ab00-a846e687840f 11:57:25 AM: info uri_switch.v0.1.0.20180901.Valve test 3>>> Sending on as part of the on event.

afcfd820-a8a1-46cc-ab00-a846e687840f 11:57:25 AM: debug uri_switch.v0.1.0.20180901.Valve test 3>>> Commands = {“relay6”:“on”}

However, it’s not turning the relay On.

Looking at the section from the switch manual (which is pretty basic). It doesn’t say you can send a command to a single switch. It seems to indicate you have to send the full block of 8.

The Link is in the thread somewhere above, but the relevant bit I have copied here.

2.JSON Communication Format
(JSON format only supports network port analysis, USB port and RS485
interface does not support this format):
*Set relay state (on is open, off is closed).
Example Send Correct Command:
{“relay1”:“on”,“relay2”:“off”,“relay3”:“off”,“relay4”:“on”,“relay5”:“on”,"
relay6":“on”,“relay7”:“off”,“relay8”:“off”}
Return:{“resp”:“ok”}
Send Error command:
{“relay1”:“off”,“relay2”:“off”,“relay3”:“off”,“relay4”:“off”,“relay5”:“off”,
“relay6”:“off”,“relay7”:“off”,“relay9”:“off”}
Return:{“resp”:“error”}
*Get Relay Status
Example Send :{“get”:“relayStatus”}
Return :
{“relay1”:“off”,“relay2”:“off”,“relay3”:“off”,“relay4”:“off”,“relay5”:“off”,
“relay6”:“off”,“relay7”:“off”,“relay8”:“off”}

I am not sure what else to suggest.

I used to have a share of a business in Gujarat. Spent a lot of time in Baroda. Best Vegetarian food I ever had!

Thanks for all your input on this. I would never have gotten this far without your help!

Neil