Ability to use wget - maybe via luup.inet.wget ??

Hi,

I’m trying to run some code found here (Code for Energenie LAN Powerstrip - Domoticz) which uses ‘wget’. - see below.

Is it possible to run these with Vera e.g. In a script / via a scene ?

To login

wget --post-data 'pw=smartlab' 'http://nn.nn.nn.nn/login.html' -O foo.html --delete-after

To switch Socket3 ON:

wget --post-data 'cte1=&cte2=&cte3=1&cte4=' 'http://nn.nn.nn.nn' -O foo.html --delete-after

To switch Socket3 OFF:

wget --post-data 'cte1=&cte2=&cte3=0&cte4=' 'http://nn.nn.nn.nn' -O foo.html --delete-after

To logout:

wget 'http://nn.nn.nn.nn/login.html' -O foo.html ?-delete-after

I’ve continued to search the forum and can find an example of wget only being used, via os.execute

os.execute("wget -q -O /usr/lib/lua/json.lua http://code.mios.com/trac/mios_genericutils/export/20/json.lua")

Is that the only way ? I’m curious now, what is the difference between wget and luup.inet.wget ?

Looks like your example wget is doing an http POST request. I’ve put some sample code below that I use for doing this in lua. Of course you can continue to use the os.execute if you wish. What I’m not sure about is how to add the login/logout that you need in the sample code. You’ll need to do some research there or maybe someone else will have a suggestion. Also, this is for sending JSON - you may need a change there too.

[code]local http = require(“socket.http”)
local ltn12 = require(“ltn12”)
local path = “http://192.168.1.203/tstat
local payload = [[ {“t_mode”:1,“t_heat”:61} ]]

local response_body = { }
local res, code, response_headers, status = http.request
{
url = path,
method = “POST”,
headers =
{
[“Content-Type”] = “application/json”,
[“Content-Length”] = payload:len()
},
source = ltn12.source.string(payload),
sink = ltn12.sink.table(response_body)
}[/code]

Thanks

I’m not sure how much flexibility the power strip I’m looking to control has, it seems reasonable basic - so I’m continuing to research, both online (wget Command in Linux) and the Vera wiki which stats the following

Module: luup.inet

function: wget
parameters: URL (String), Timeout (Number), Username (String), Password (String)
returns: operationStatusCode (Number), content (String), httpStatusCode (Number)
This reads the URL and returns 3 variables: the first is a numeric error code which is 0 if successful. The second variable is a string containing the contents of the page. The third variable is the HTTP status code. If Timeout is specified, the function will timeout after that many seconds. The default value for Timeout is 5 seconds. If Username and Password are specified, they will be used for HTTP Basic Authentication.

As for wget or luup.inet.wget; I’ve seen a few examples used.

os.execute("wget -q -O /usr/lib/lua/json.lua http://code.mios.com/trac/mios_genericutils/export/20/json.lua")
luup.inet.wget("http://192.168.0.28:8080/json.htm?type=command&dparam=udevice&idx=267&nvalue=0&svalue="..kw..";"..kwh, 5)
luup.inet.wget "http://%s:3480/data_request?id=action&serviceId=%s&action=%s&SceneNum=%d"' 

I’m no expert on this, but this page: http://wiki.micasaverde.com/index.php/Luup_Scenes_Events#Access_the_web indicates that the luup.inet.wget only does the GET request. If you need the POST method as implied by the “–post-data” in your original message (see HTTP Options (GNU Wget 1.21.1-dirty Manual)), then maybe you have to use http.request()?

Thanks,

I’m out of my depth here :slight_smile:

I now have examples of command line entries that work for my Energenie PMS-LAN, the quest now is to see how I can get Vera to run them. As it seem both curl or wget can do the job.

The first thing you need to do is login (the default password is 1, so I have left it as that for those examples) - and this times out after I think 3-5 mins

Using curl,

curl -s -d "pw=1" http://192.168.1.90/login.html

or wget

wget -q -O - --post-data="pw=1" http://192.168.1.90/login.html 

And the to turn the sockets on or off you set the value of your target to either 1 or 0 e.g.

Turn on socket 4 (via curl)

curl -s -d "cte4=1" http://192.168.1.90/

Turn off socket 4 (via curl)

curl -s -d "cte4=0" http://192.168.1.90/

Turn on socket 4 (via wget)

wget -q -O - --post-data="cte4=1" 'http://192.168.1.90/'

Turn off socket 4 (via wget)

wget -q -O - --post-data="cte4=0" 'http://192.168.1.90/'

My suggestion is to turn on the verbose option in curl to see what is doing. (I’m sure you can do the same in wget but I haven’t tried it.) Look for this option for curl. Then you can see what it is doing and piece it back together in lua. I’m sure someone has done something similar, but this will give you a better idea of what you need.

-v, --verbose

Makes curl verbose during the operation. Useful for debugging and seeing what’s going on “under the hood”. A line starting with ‘>’ means “header data” sent by curl, ‘<’ means “header data” received by curl that is hidden in normal cases, and a line starting with ‘*’ means additional info provided by curl.

If you only want HTTP headers in the output, -i, --include might be the option you’re looking for.

If you think this option still doesn’t give you enough details, consider using --trace or --trace-ascii instead.

I suggest accessing Vera over SSH, and trying these commands on the shell to see if you get any errors or not. If they work, you can run the commands from LUUP using

os.execute(" ... ")

@parkerc, do you have AltUI installed? I’ve been looking at something similar for other reasons and I think what you need isn’t too hard, but you’ll need to do a little experimentation. The test code window in AltUI makes this very easy. Otherwise you can use luup.log() instead of the print’s below.

Something like this: “curl -s -d “cte4=1” http://192.168.1.90/” might be this:

[code]
function testFunc()
local http = require(“socket.http”)
local ltn12 = require(“ltn12”)
local path = “http://192.168.1.90/

local reqbody = “cte4=1” – your function can change this as needed, and you can combine with others such as the pw like this:
– pw=1&cte4=1
local response_body = { }
local res, code, response_headers, status = http.request
{
url = path,
method = “POST”,
headers =
{
[“Content-Type”] = “text/html”, – this may need some adjustment, but give it a try
[“Content-Length”] = reqbody:len()
},
source = ltn12.source.string(reqbody),
sink = ltn12.sink.table(response_body) – can possibly delete this
}
print("res: " … res)
print("code: " … code)
print("status: " … status)
end

testFunc()[/code]

Hi @jwimm788

Thanks for the suggestion, I tried your suggested code via Lua Test (which support ‘Print’), and it returned the following

[b]LuaTest 1.5.2[/b]

Lua file: /nas/luatest/pms-lanscript1.lua

Results
Runtime error: Line 21: attempt to concatenate local ‘res’ (a nil value)

Locals
[testFunc]
http={ USERAGENT=“LuaSocket 2.0.2”, PORT=80, _NAME=“socket.http”, _PACKAGE=“socket.”, request=function, _M=http, open=function, TIMEOUT=60 }
ltn12={ source={ rewind=function, simplify=function, chain=function, cat=function, string=function, file=function, error=function, empty=function }, _PACKAGE=“”, pump={ step=function, all=function }, _VERSION=“LTN12 1.0.1”, sink={ simplify=function, chain=function, table=function, file=function, null=function, error=function }, _NAME=“ltn12”, filter={ chain=function, cycle=function }, _M=ltn12, BLOCKSIZE=2048 }
path=“http://192.168.1.90/
reqbody=“cte4=1”
response_body={ }
res=nil
code=“timeout”
response_headers=nil
status=nil
[main]

Print output
(none)

With line 21, being this.

print("res: " .. res)

Any thoughts / suggestions on what to change ?

In the case of the request call failing, res will be nil.

Suggest you replace your print statements with

  print("res: ", res)
  print("code: ", code)
  print("status: ", status)
end

Hi @akbooer

Thanks for the suggestion…

FYI - I added the following as the first line to ensure I was always logged in.

os.execute("curl -s -d 'pw=1' http://192.168.1.90/login.html")

After changing the code; it now returns this.

[b]LuaTest 1.5.2[/b]

Lua file: /nas/luatest/pms-lanscript1.lua

Results
No errors
Runtime: 60167.1 ms
Code returned: nil

Print output
res:
code: timeout
status:

If it helps, this is what is returned when curl is used at the command line; and I successfully switch on socket 4.

[b]root@MiOS_123456789[/b]:~# curl -s -d "cte4=1" [url=http://192.168.1.90/]http://192.168.1.90/[/url] EnerGenie LAN Power Manager

WARNING! JAVASCRIPT IS DISABLED!

Server 1

<>



EnerGenie<>
Socket 1 <>
Socket 2 <>
Socket 3 <>
Socket 4 <>
Socket Name Settings<>
Device Settings<>
LAN Settings<>
Log Out<><><>
<>

Socket 1

Socket 2

Socket 3

Socket 4



<>

Your EnerGenie account

<>


Activate  Register
<>
Status: <><>
<><><>root@MiOS_[font=Verdana]123456789[/font]:~#

Any chance you could try this command on something other than the Vera?

curl -v -d "cte4=1" http://192.168.1.90/

The -s makes it silent so there is no debug info there. (If you have nothing else, try the above on the Vera, replace -s with -d)

I’m surprised you got a nil result. That makes it sound like it didn’t get to talk to the server. I just tried the code to a local web server and I got unauthorized which is what I would expect. However, this is running on openLuup - it is possible there is a difference with the real Vera. I’ll have to try that when I get a chance. I think you are close but it isn’t quite right yet.

res: 1 code: 401 status: HTTP/1.1 401 Unauthorized

For reference, after logging in - the running of just that command on Vera returns the following.

[b]root@MiOS_12345678[/b]:~# curl -v -d "cte4=0" http://192.168.1.90/

POST / HTTP/1.1
User-Agent: curl/7.21.3 (mipsel-openwrt-linux-gnu) libcurl/7.21.3 OpenSSL/1.0.0d zlib/1.2.5
Host: 192.168.1.90
Accept: /
Content-Length: 6
Content-Type: application/x-www-form-urlencoded

< HTTP/1.1 200 OK
< Date: Mon, 23 May 2010 22:38:36 GMT
< Server: EG-Web
< Content-Length: 3275
< Connection: Keep-Alive
<

EnerGenie LAN Power Manager

WARNING! JAVASCRIPT IS DISABLED!

Socket 1

Socket 2

Socket 3

Socket 4



Your EnerGenie account



Activate  Register
Status:

root@MiOS_12345678:~#

In regards to the script, I’m unsure where to change the curl parameters to make the logging verbose?

[code]os.execute(“curl -s -d ‘pw=1’ http://192.168.1.90/login.html”)

function testFunc()
local http = require(“socket.http”)
local ltn12 = require(“ltn12”)
local path = “http://192.168.1.90/

local reqbody = “cte4=1” – your function can change this as needed, and you can combine with others such as the pw like this:
– pw=1&cte4=1
local response_body = { }
local res, code, response_headers, status = http.request
{
url = path,
method = “POST”,
headers =
{
[“Content-Type”] = “text/html”, – this may need some adjustment, but give it a try
[“Content-Length”] = reqbody:len()
},
source = ltn12.source.string(reqbody),
sink = ltn12.sink.table(response_body) – can possibly delete this
}
print("res: ", res)
print("code: ", code)
print("status: ", status)
end

testFunc()[/code]

2 suggestions:

  1. try changing the content-type header in the script from text/html to application/x-www-form-urlencoded as shown in your debug output.

  2. see if you can do the login instead of the cte as a test. Change the path to this: http://192.168.1.90/login.html, and change the reqbody to “pw=1”. See if that behaves any differently. Still a timeout?

You are seeing a timeout - the question is why? The server must not like something that is being sent, but I’m not sure what it doesn’t like… I suppose you could add the ‘Accept: /’ header as well, but I don’t see why that would case a timeout.

Hi

I tried this but it seems to have no effect

Yes, sadly even the login.html times out via this script too…

Maybe we are trying to be too complicated. Try the simple form instead:

local status, statusMsg = http.request{ url = "http://192.168.1.90", body = "cte4=1"}

I’m trying to think of why you get a timeout. One thing that popped to mind was that in the code we have ‘sink’ set to a table - but what is being returned is html. Perhaps that is causing the timeout as the request is waiting for something else? The above shouldn’t have that issue. And you could try the other code without the sink line.

If this doesn’t work, it might be time for Wireshark. I still think this is almost working and there is just a small problem. It really shouldn’t be rocket science.

Thanks for all your help @jswim788

It would be great to be able to use the LUA libraries and void using os.execute, but for some reason any combination I’ve tried does not seem to work. Which seems so strange if it works via Curl ??!??

What I have found is that I can send multiple requests via a single curl request - so it logs on, carries out the change and then logs out - so that makes a single command line entry much easier to complete.

EXTRA

It just proves how old I’m getting but I’d started a simular thread for the particular power sockets I’m trying to control here 3-4 years ago ! - To have a look go to : http://forum.micasaverde.com/index.php/topic,17008.0.html

To avoid duplication - I would recommend any other thoughts/ideas be focused back there to keep a single thread running…

Okay, we’ll move over to the other thread. I am 99.9% sure you can do this from within lua and don’t need the os.execute with curl. And you can do multiple settings with the http request such as: body = “pw=1&cte4=1”. But debugging what is going on isn’t easy.