Switch to send post json data

Hi all,

I am looking for a way to integrate my aircon with my vera. I am pretty new at home automation, and very much so a vera/zwave novice. I’ve seen some posts around the place that use luup to send json payloads, but im not sure how to associate that payload with a switch, or where the luup code is meant to go Can anyone help??

What im wanting to do basically the same as whats being achieved on this fibaro: https://forum.fibaro.com/index.php?/topic/21650-rest-api/&_fromLogin=1

any help appreciated!

Neil.

getting further with this… i figured out that i just need to use virtual switches with lua code. trying to get LUA code to do a curl with the json request. it works natvely with curl, but not with os.execute. This is what im trying to run:

os.execute(‘curl -X POST -H “Content-Type: application/json” -d “{“DA”:{“amOn”:true}}” https://actron.ninja.is/rest/v0/device/xxxxx?user_access_token=xxxxx’)

Anyone know why it may not work?

Woo - have it all sorted. ended up using socket http to get my Actron Connect aircon to work with a vera scene/virtual switch. If anyone else happens to need it, i used the following code:

local http=require(“socket.http”)
local https = require (“ssl.https”)
local siteurl = “https://actron.ninja.is/rest/v0/device/xxxx?user_access_token=xxxx
local payload = [[ {“DA”:{“amOn”:1}} ]]
local respback = { }
local res, code, response_headers, status = http.request
{
url = siteurl,
method = “POST”,
headers =
{
[“Content-Type”] = “application/json”,
[“Content-Length”] = payload:len()
},
source = ltn12.source.string(payload),
sink = ltn12.sink.table(respback)
}

All works with vera concierge now too :slight_smile:

Glad you have it working, and kudos for reporting your progress.

I may be wrong, but I think you’ll find that even though you’re using “https” as a string in the url, this will not go over a secure socket layer unless you explicitly use the https.request() function call.

In fact, the code as it stands is not using the required ssl module at all.

Interesting - I see what you mean and removed the “local https = require (“ssl.https”)” block. It seems to still be working, so you must be correct! thanks!

For people in the future who come here looking for a way to execute ‘curl’ in their Vera with JSON… I was able to figure it out when I was trying to get Slack webhooks to work. This worked for me. Notice how the quotes need to be escaped in just the right way.

os.execute(‘curl -X POST -k -H ‘Content-type: application/json’ -d ‘{“text”:“hello world”}’ https://hooks.slack.com/services/AAAAAA/BBBBB/CCCCCC’)

Hello,

Could you tell me how to send post json in lua code?(I need an example)

I need to control kodi in a scene.

Non-trivial until you get accustomed to the moving parts. I pared this down from one of my plugins…

local https = require "ssl.https"
local http = require "socket.http"
local ltn12 = require "ltn12"
local json = require "dkjson"

-- Send HTTP(S) POST request that sends and returns JSON.
-- If you pass "body" as a table, it will be JSON-encoded and sent
local function postJSON(url, body, method)
	method = method or "POST"

	local src
	local tHeaders = {}
	
	-- Add an API key/auth header like this if needed
	tHeaders["Authorization"] = "Bearer " .. tostring("a2372fc0-98ee-11e9-bbe1-8bca5f3e2a02")

	-- Build post/put data. If body is a table, JSON-encode (stringify) it.
	if type(body) == "table" then
		body = json.encode(body)
		tHeaders["Content-Type"] = "application/json"
	end

	-- Use string source for body, add content length header.
	if body then
		tHeaders["Content-Length"] = string.len(body)
		src = ltn12.source.string(body)
	end

	-- Handler for HTTP or HTTPS?
	local requestor = url:lower():find("^https:") and https or http

	-- Make the request.
	local r = {} -- receiver for sink
	http.TIMEOUT = timeout -- N.B. http not https, regardless
	local _, httpStatus, httpHeaders = requestor.request{
		url = url,
		source = src,
		sink = ltn12.sink.table(r),
		method = method,
		headers = tHeaders,
		redirect = false
	}

	-- Since we're using the table sink, concatenate chunks to single string.
	local respBody = table.concat(r)
	r = nil	-- free that table memory faster

	-- See what happened.
	if httpStatus == 204 then
		-- Success response with no data, take shortcut, return empty table.
		return true, {}
	elseif respBody == nil or httpStatus ~= 200 then
		-- Error of some persuasion. You can provide more checks here.
		return false, httpStatus
	end

	-- Try to parse response as JSON.
	local t, _, err = json.decode(respBody)
	return t ~= nil, t or err
end

-- Example
local sendData = { op="turn_on", device="lamp_dimmer", brightness="50" }
local success,data = postJSON( "http://example.com/api/v1/query", sendData )

This function will take a URL (url) and body (body) and send it as a POST request (unless you also provide method to specify something else, e.g. PUT). If the body is a table, it will be converted to JSON (text) first. The function expects a JSON response and returns two values: success and the response data. If success is true, then data is a table (the received JSON response data). If success is false, then data contains error information.

1 Like

I want to send this request in post json

http://< MEDIA IP>:8080/jsonrpc?request={“jsonrpc”:”2.0″,”id”:”1″,”method”:”Player.Open”,”params”:{“item”:{“file”:”special://profile/playlists/music/radiojavan.m3u”}}}

this used to play a playlist in kodi but in the latest firmware of kodi it mustbe sent by post.

As I do not know about json could you possibly change it for me?

This may be a stupid question, so forgive me, but why not simply os.execute a post command?

Possibly cos post is not installed?

C

You can probably do that, but correctly escaping the characters for all the command line arguments in all the right places to get it to run may drive you mad if you don’t really understand what needs to escaped, when, where, and why.

1 Like

I have been working on it to use os.execute for three days, Vera sends the request but nothing happens in Kodi.
Is there anyway I get feedback to find the reason of failure?

I have reached to this:
os.execute(‘curl -s --data-binary ‘{“jsonrpc”:“2.0”,“id”:“1”,“method”:“Player.Open”,“params”:{“item”:{“file”:“special://profile/playlists/music/f.m3u”}}}’ -H ‘Content-type: application/json’ “http://192.168.1.5:8080/jsonrpc”’)

the curl command works but it does not work in Test Luup code section in vera

local http=require(“socket.http”)
local https = require (“ssl.https”)
local siteurl = “http://192.168.1.5:8080/jsonrpc”
local payload = [[ {“jsonrpc”:“2.0”,“id”:“1”,“method”:“Player.Open”,“params”:{“item”:{“file”:“special://profile/playlists/music/f.m3u”}}} ]]
local respback = { }
local res, code, response_headers, status = http.request
{
url = siteurl,
method = “POST”,
headers =
{
[“Content-Type”] = “application/json”,
[“Content-Length”] = payload:len()
},
source = ltn12.source.string(payload),
sink = ltn12.sink.table(respback)
}

Try running the above and see how you go??

Failed to test code, please try again:pensive:

This is what I was talking about when I said the quoting would drive you mad.

You haven’t quoted the string correctly. You are using the single quote twice: once to delimit the entire string, and again several times to quote the option arguments (to --data-binary and -H). You need to escape the interior sets of quotes on those arguments, for starters. Given that the nesting of quotes is only three levels, you could bracket-quote the entire string:

os.execute( [[curl -s --data-binary '{"jsonrpc":"2.0","id":"1","method":"Player.Open","params":{"item":{"file":"special://profile/playlists/music/f.m3u"}}}' -H 'Content-type: application/json' 'http://192.168.1.5:8080/jsonrpc']])

It did worked.

Thanks a lot for your help.

Do you know any source for beginners to learn LUA?