Creating triggers from luup code

Great point !

Thanks for that. I?ve been slicing and dicing the code around so much now to try to get each function to work. So I?ve had those calls in various places etc. .

I?ll look to make them part of their respective functions again and see how that changes things

I’ve been following this thread and trying to implement variable_watch. This is code is placed in my startup lua:

luup.variable_watch(“device_power_state_change”, “urn:upnp-org:serviceId:SwitchPower1”,“Status”, 2)

function device_power_state_change(dev_id,service, variable, old_val, new_val)
– called when a device is switched on or off - from a variable_watch
if new_val == “1” then
device_switched_on_or_off(dev_id,“true”)
else
device_switched_on_or_off(dev_id,“false”)
end

http = require(“socket.http”)
ltn12 = require(“ltn12”)
path = “http://192.168.1.69:180/12j0kaq1?param_1=one&param_2=two&param_3=three
payload = [[ {“key”:“My Key”,“name”:“My Name”,“description”:“The description”,“state”:1} ]]
response_body = { }

res, code, response_headers, status = http.request
{
url = path,
method = “POST”,
headers =
{
[“Authorization”] = “Maybe you need an Authorization header?”,
[“Content-Type”] = “application/json”,
[“Content-Length”] = payload:len()
},
source = ltn12.source.string(payload),
sink = ltn12.sink.table(response_body)
}
luup.task('Response: = ’ … table.concat(response_body) … ’ code = ’ … code … ’ status = ’ … status,1,‘Sample POST request with JSON data’,-1)

end

I’m not receiving the http POST on the server. Fairly new at Lua, so hope someone can provide some guidance.

Thanks

The order in which things are defined matters in Lua. One thing which stands out immediately, is that you call [tt]luup.variable_watch[/tt] before you define the [tt]device_power_state_change[/tt] function. You need to reverse that state of affairs.

Is there anything that shows up in the log by way of an error? A failure in the startup Lua should be logged. If the variable watch call fails, then the rest of the code (including the HTTP request) won’t be executed.

Thanks @akbooer, I’ve reversed the order and all is working now. Eventually, I’ll probably move the function to a lua file. So, the function is now sending data to my remote server, which will act upon it; however it appears as though Vera is awaiting a response of some sort. If I’m in the UI and turn a light on, my server shows it gets the information and light comes on, but in the UI device I get: Waiting for node to reply after 0 retries… If I then try to turn the light off, there’s about a 15-20 sec delay before the command executes. What type of response (if any) should my server be sending back to Vera? I’m very new to the http server stuff, so forgive what might be a simple question.

Thanks

...however it appears as though Vera is awaiting a response of some sort.

There may need to be some response, perhaps depending on the status return code? Just “OK” might do. You wrote the remote server yourself?

I imagine that you are seeing an HTTP handshake timeout, although the default for that in the LuaSocket library is, IIRC, 5 seconds.

The http server is a simple javascript server written by a friend. It’s receiving the POST just find. I’ve just got to figure out the proper way to send the response back to Vera…am I correct in thinking I’ll use a POST back to Vera to send my response? I’m probably totally wrong, though.

This is a big task for me as I’m new to Javascript (not to mention http server stuff). :slight_smile: But, I’m enjoying the process and all the help I get from folks.

Thanks again for letting me bother you.
Bob

No, the response needs to be in the appropriate format of headers and possible body, sent as one or more messages using the original TCP connection established by the POST request.

You were correct a couple of posts ago…all I needed to do was add: http.TIMEOUT=10, which gave the server enough time to respond properly. Now, I just have to parse out the POST on the server side. One step at a time. Thanks man.

I"m trying to add a variable to a statement as below, which sends JSON data to a server:

local a = “Hello”

payload = [[ {“id”:" … a … ", “name”:“My Name”, “description”:“The description”, “state”:1} ]]

all I’m getting on the return is: …a… Original statement was

payload = [[ {“id”:" Device ID", “name”:“My Name”, “description”:“The description”, “state”:1} ]]

Just getting started in Lua (and have been reading Programming in LUA), but am i bit confused as to how to get this to work. Thanks.

Karma to you for doing more than many others do in trying to get a basic grasp of Lua. It’s small, but subtle, so may take a while.

You are nearly there. Your original statement:

payload = [[ {"id":" Device ID", "name":"My Name", "description":"The description", "state":1} ]]

creates a single string, which itself contains double quotation marks, by using the special double-bracket syntax.

What you need now is a way to make a single string, but containing a variable. There are many, many ways to do this. To make this as as similar to your attempt you could write

local a = "Hello"

payload = [[ {"id":"]] .. a .. [[", "name":"My Name", "description":"The description", "state":1} ]]

However, what you’re doing is to script JSON code directly. For more complicated cases you would be far better off constructing the response as an actual Lua table and then using a JSON encoder. Ask again if you need to know more.

Aaaahhh…makes perfect sense now. I didn’t know about the [[ syntax, but seeing what you did makes perfect sense. The end goal is to get the device_id and pass it (and other info on a device to my server).

This thread is full of great snippets to do exactly what I need. My next chore is to take @dunked snippet that watches all switches and incorporate that into my function. Thanks for your willingness to help.

Cheers

Since you’ll be wanting to add more parameters, I’d recommend, once again, the JSON encoder route.

Your existing example would look something like this:

local json = require "dkjson"

local a = "Hello"
local b = "My Name"
local c = "The description"
local d = 1

local payload = {
    id = a, 
    name = b,
    description = c,
    state = d,
} 

local json_payload = json.encode (payload))

which would, again, give you the string:

{"id":"Hello","state":1,"name":"My Name","description":"The description"}

But then, you see, it’s MUCH easier to change values, and to read the code.

That is awesome…and yes, much much easier to read. I will utilize it soonest. Thanks, man for all the help.

I’m trying to pass an additional param in my lua function to my server, but on the server side am getting an “undefined”. Probably a rookie mistake, but any help would be super. Here’s the lua:

function device_security_sensor_tripped(dev_id, service, variable, old_val, new_val)
if (old_val ~= new_val) then

	local lightlevel = ""

	--create JSON array       
	local json = require "dkjson"

	local a = dev_id
	local b = lightlevel
	local c = new_val
	local d = "sensor"

	local payload = {		
		device_id = a, 
		light_level = b,
		state = c,
		devType = d,
	} 

	local json_payload = json.encode (payload)

	http = require("socket.http")
	http.TIMEOUT=5
	ltn12 = require("ltn12")
	path = "http://192.168.1.69:180/12j0kaq1?iparam_1=one&param_2=two&param_3=three&param_4=four"
	payload = json_payload  
	response_body = { }

	res, code, response_headers, status = http.request
	{
	url = path,
	method = "POST",
	headers =
	{
		["Authorization"] = "Maybe you need an Authorization header?", 
		["Content-Type"] = "application/json",
		["Content-Length"] = payload:len()
	},
	source = ltn12.source.string(payload),
	sink = ltn12.sink.table(response_body)
	}
	luup.task('Response: = ' .. table.concat(response_body) .. ' code = ' .. code .. '   status = ' .. status,1,'Sample POST request with JSON data',-1)
	luup.log(" ......Testing Ended.......")
end

end

…and on the server side:

self.onRequestReceived = function (id, lightlevel, devicestatus, devType) {  
    
         alert("ID=" + id + "  LightLevel=" + lightlevel + "  Status=" + devicestatus + "  Type=" + devType);
};

I’m getting the ID, LightLevel and Status, but for the Type, I get “undefined”.

Thanks

i figured it out…it ended up being something on server side that wasn’t parsing the JSON data correctly.

Thanks.

Ah! Just in time… I was about to take a look.

Not so fast @ak!!! :slight_smile: So, the watcher is working great, except for one small detail…if I turn a light on directly at the switch, the watcher doesn’t send the request to my server. It works fine if I tell Vera to turn on the light though. Does turning on a light via the switch act differently where Vera is concerned? Here’s one of the watchers:

[code]function device_dimmer_level_change(dev_id, service, variable, old_val, new_val)
–gets dim level
local lightlevel = luup.variable_get(“urn:upnp-org:serviceId:Dimming1”, “LoadLevelStatus”, dev_id)
local status

-- set light to currect status
if lightlevel > "0" then
	status = "1"
else
	status = "0"
end

-- create JSON array
local json = require "dkjson"
local a = dev_id	
local b = lightlevel
local c = status
local d = "dimmer"

local payload = {
	device_id = a, 
	light_level = b,
	state = c,
	dev_name = d
} 	

local json_payload = json.encode (payload)

http = require("socket.http")
http.TIMEOUT=5
ltn12 = require("ltn12")
path = "http://192.168.1.69:180/request?param_1=one"
payload = json_payload  
response_body = { }

res, code, response_headers, status = http.request
{	
	url = path,
	method = "POST",
	headers =
	{
		["Authorization"] = "Maybe you need an Authorization header?", 
		["Content-Type"] = "application/json",
		["Content-Length"] = payload:len()
	},
	source = ltn12.source.string(payload),
	sink = ltn12.sink.table(response_body)
}
luup.task('Response: = ' .. table.concat(response_body) .. ' code = ' .. code .. '   status = ' .. status,1,'Sample POST request with JSON data',-1)

end

luup.variable_watch(“device_dimmer_level_change”, “urn:upnp-org:serviceId:Dimming1”,“LoadLevelStatus”, dev_id)

[/code]

Hope you can help. Thanks.

This will depend on the technology of the switch. If it reports instant status, then Vera will respond quickly, if not, then the status update will not happen until Vera polls the switch, which could be some time later.