Advice in sending HTTP commands

I have yet to delve into using web functions so I thought it best to ask a couple of questions for some direction before I get too far into this project.

I’m now sending Web (HTTP) commands to smart devices flashed with Tasmota firmware and would like to strip off returned status information in an HTML Viewer. The URL commands like this:

Var Off_URL As Text = “http://” + Address(Index).value.toText + “/cm?cmnd=Power%20Off”
WebViewer(index).LoadURL(Off_URL)

When I send a Web (HTTP) Status request I would like to strip off the returned “Power”:Off/On portion to set on/off radio buttons in my home automation system to mimic smart switch status. I’m thinking it could be treated as a string. Any suggestions on how to do this?

Returned value in HTMLViewer
{“Time”:“2020-11-25T19:51:48”,“Uptime”:“1T22:22:11”,“UptimeSec”:166931,“Heap”:25,“SleepMode”:“Dynamic”,“Sleep”:50,“LoadAvg”:19,“MqttCount”:0,“POWER”:“OFF”,“Wifi”:{“AP”:1,“SSId”:“Cliff’s Wi-Fi Network”,“BSSId”:“3E:94:ED:37:87:9D”,“Channel”:6,“RSSI”:84,“Signal”:-58,“LinkCount”:1,“Downtime”:“0T00:00:04”}}

I’m not sure my approach is sound but it’s working other than getting the return status info I need. I’m open to a better direction if I’m off in the weeds on this.

Use URLConnection instead of a HTMLViewer.

Run the result through ParseJSON into a Dictionary.

Grab the “POWER” key from that Dictionary.

2 Likes

I actually understood that, good start. But I ran into a problem. The status return format is a little different than I first thought. On/Off data returned is in the format {“POWER”:“ON”} so the key pair works but when I go for the device status the Key pair is a little different and is not be picked off. Any thoughts?

{“Status”:{“Module”:1,“DeviceName”:“Tasmota”,“FriendlyName”:[“Tasmota”],“Topic”:“tasmota_E84235”,“ButtonTopic”:“0”,“Power”:1,“PowerOnState”:3,“LedState”:1,“LedMask”:“FFFF”,“SaveData”:1,“SaveState”:1,“SwitchTopic”:“0”,“SwitchMode”:[0,0,0,0,0,0,0,0],“ButtonRetain”:0,“SwitchRetain”:0,“SensorRetain”:0,“PowerRetain”:0}}

My json code is:

var json As New JSONItem(content)
If json.HasName(“POWER”) Then
ResultArea.AddText(json.value(“POWER”))
End

First, if you can, use ParseJSON instead of JSONItem.

var json as Dictionary = ParseJSON( content )
var status as Dictionary = json.Value( "Status" )
var power as integer = status.Value( "Power" )

(Untested, for illustration only.)

I find out this is also a case sensitive issue, so I needed your routine and mine. Is there a way to eliminate the case issue or a better way to approach this?

ResultArea.Text = “”
Content = Content.DefineEncoding(Encodings.UTF8)

Var json As New JSONItem(content)// For checking individual ON/Off
If json.HasName(“POWER”) Then
ResultArea.AddText(json.value(“POWER”))
Else //For checking status string
Var json2 As Dictionary = ParseJSON( content )
Var status As Dictionary = json2.Value( “Status” )
Var power As Integer = status.Value( “Power” )
ResultArea.AddText(power.tostring)
End

//Individual ON/Off HTML returns look like this:
//{“POWER”:“OFF”}

// Status returns look like this:
//{“Status”:{“Module”:1,“DeviceName”:“Tasmota”,“FriendlyName”:[“Tasmota”],“Topic”:“tasmota_E84235”,“ButtonTopic”:“0”,“Power”:1,“PowerOnState”:3,“LedState”:1,“LedMask”:“FFFF”,“SaveData”:1,“SaveState”:1,“SwitchTopic”:“0”,“SwitchMode”:[0,0,0,0,0,0,0,0],“ButtonRetain”:0,“SwitchRetain”:0,“SensorRetain”:0,“PowerRetain”:0}}

You might benefit from this site as a brief description of JSON.

You don’t need to use both JSONItem and a Dictionary. The only advantage of the latter is that it is more familiar, and ParseJSON is faster and more modern, hence my recommendation.

JSON is always case-sensitive, so the key will be case-sensitive. It’s up to you to know what to expect in the JSON you receive and there should some documentation about it somewhere.

Assuming your second example is representative, this JSON represents an object (or Dictionary) with one key, “Status”, whose value is another object. Within that embedded object is the key “Power” with the value you are looking for.

It’s a bit easier to see like this:

{
	"Status": {
		"Module": 1,
		"DeviceName": "Tasmota",
		"FriendlyName": [
			"Tasmota"
		],
		"Topic": "tasmota_E84235",
		"ButtonTopic": "0",
		"Power": 1,
		"PowerOnState": 3,
		"LedState": 1,
		"LedMask": "FFFF",
		"SaveData": 1,
		"SaveState": 1,
		"SwitchTopic": "0",
		"SwitchMode": [
			0,
			0,
			0,
			0,
			0,
			0,
			0,
			0
		],
		"ButtonRetain": 0,
		"SwitchRetain": 0,
		"SensorRetain": 0,
		"PowerRetain": 0
	}
}

With this in mind, I’d probably code it like this. (BTW, the code tags here format the code and help us help you. Please remember to use them in the future.)

content = content.DefineEncoding( Encodings.UTF8 )

var json as Dictionary = ParseJSON( content ) // Deal with the exception if it's not really JSON

if json.HasKey( "Status" ) then
  var status as Dictionary = json.Value( "Status" )
  var power as string = status.Value( "Power" )
  ResultArea.AddText( power )
else 
  // It didn't have "Status" so it's probably an error you should deal with
end if

I was able to figure out how to use code tags before the site was last revised. What do the new tags look like? Might it be the Blockquote. I liked the old preview which I also do not see.

Three backticks ("`") before an after the code will do it. It’s also one of the icons in the toolbar when composing your message.