zaphod Posted December 29, 2017 Share Posted December 29, 2017 I am trying to adapt a driver to allow it to hit a web server that uses basic authentication. What I am looking to do is to have Control4 send the equivalent of: http://user:pass@192.168.1.99:7070/sage/SageCommand?context=001d6a4cf481&command=play. In the existing driver there is the NetConnect line and then the actual command is sent in a C4:SendToNetwork command that include a string with the URLPacket. So the URL Packet would look like this: GET sage/SageCommand?context=001d6a4cf481&command=play How do I adapt the C4:NetConnect call to add a user/pass? Or is this done in a different manner, such as via the URLPacket? For example in the line: C4:NetConnect(6001, Properties["Web Server Port"]) is there a way to add additional properties such as username and password. Link to comment Share on other sites More sharing options...
zaphod Posted December 29, 2017 Author Share Posted December 29, 2017 To reply to my own thread - it looks like you may be able to do this by appending a bunch more stuff in your URLPacket. For example the following should work (I have done it in a telnet script in Ubuntu, but not in a driver yet): GET /sage/SageCommand?context=001d6a4cf481&command=pause HTTP/1.1 Host: 192.168.1.99 Authorization: Basic dxNlcJPwYXNz So to do this you will also need the IP address which comes from the binding and you have to base64 encode the "user:pass" string to come up with the string to pass after Authorization: Basic. So that raises two other questions - how do I get the Host IP address? And how do you base64 encode within lua code in the driver? Is there a function that makes this easy? Is this the right way to be doing all of this or should I just be using C4:urlGet instead? Link to comment Share on other sites More sharing options...
msgreenf Posted December 29, 2017 Share Posted December 29, 2017 --[[ Create the Authorization header for http request. --]] function auth_header() local http_headers = {} if gAuthRequired then if gAuthType == "BASIC" then local http_header_field = gUsername .. ":" .. gPassword http_header_field = "Basic " .. C4:Base64Encode(http_header_field) Dbg:Trace("HTTP Authentication: " .. http_header_field) http_headers["Authorization"] = http_header_field end end return http_headers end --[[ Perform URL 'Get" request using authentication if required. Returns ticket (number) that identifies response with 'ReceivedAsync' callback function. --]] function url_get_request(url) local l_url = url if gAuthRequired and gAuthType == "DIGEST" then l_url = string.sub(url, 1, 7) .. gUsername .. ":" .. gPassword .. "@" .. string.sub(url, 8) end return C4:urlGet(l_url, auth_header()) end --[[ Perform URL 'Post" request using authentication if required. Returns ticket (number) that identifies response with 'ReceivedAsync' callback function. --]] function url_post_request(url, data) local l_url = url if gAuthRequired and gAuthType == "DIGEST" then l_url = string.sub(url, 1, 7) .. gUsername .. ":" .. gPassword .. "@" .. string.sub(url, 8) end return C4:urlPost(l_url, data, auth_header()) end --[[ Build HTTP request URL using global address and HTTP port variables and provided query string. --]] function build_http_url(query_string) return "http://" .. gAddress .. ":" .. gHttpPort .. "/" .. query_string end Link to comment Share on other sites More sharing options...
zaphod Posted December 29, 2017 Author Share Posted December 29, 2017 Thanks Mitch. Up early? You posted at like 5:30am! The driver that I am adapting for SageTV is older and just uses C4:SendToNetwork and C4:NetConnect. Were these other methods like urlGet and urlPost added later on? Does it make more sense to use them rather than building a more convoluted string as shown in my second post above and continuing to use C4:SendToNetwork? Link to comment Share on other sites More sharing options...
msgreenf Posted December 29, 2017 Share Posted December 29, 2017 Thanks Mitch. Up early? You posted at like 5:30am! The driver that I am adapting for SageTV is older and just uses C4:SendToNetwork and C4:NetConnect. Were these other methods like urlGet and urlPost added later on? Does it make more sense to use them rather than building a more convoluted string as shown in my second post above and continuing to use C4:SendToNetwork? Up usual time. Netconnect is more of an open socket not really http. If it's http the code I sent should get you pointed in the right direction Sent from my Pixel XL using Tapatalk Link to comment Share on other sites More sharing options...
zaphod Posted December 30, 2017 Author Share Posted December 30, 2017 I have the driver working for the most part now using the Get command. But I am having one other issue. When I restart the Driver by updating the version, as I am doing frequently when I am making changes, everything works fine. But if I reboot the controller or if I restart Director then I am having an issue. Right at the beginning of my Driver's Lua file there is this code: ip = C4:GetBindingAddress(6001). The variable ip is not getting populated. If I enter this statement from the Lua code window then it is fine. Or when I install or update the driver while Director has been running everythign is fine. Why wouldn't this variable get populated when Director is starting up? Is it possible that the Binding and/or the network isn't yet initialized? If so is there some way of waiting until Director has been up for a minute or two before populating the ip variable? Link to comment Share on other sites More sharing options...
msgreenf Posted December 30, 2017 Share Posted December 30, 2017 I have the driver working for the most part now using the Get command. But I am having one other issue. When I restart the Driver by updating the version, as I am doing frequently when I am making changes, everything works fine. But if I reboot the controller or if I restart Director then I am having an issue. Right at the beginning of my Driver's Lua file there is this code: ip = C4:GetBindingAddress(6001). The variable ip is not getting populated. If I enter this statement from the Lua code window then it is fine. Or when I install or update the driver while Director has been running everythign is fine. Why wouldn't this variable get populated when Director is starting up? Is it possible that the Binding and/or the network isn't yet initialized? If so is there some way of waiting until Director has been up for a minute or two before populating the ip variable?Do you have it in your init function? Sent from my Pixel XL using Tapatalk Link to comment Share on other sites More sharing options...
zaphod Posted December 30, 2017 Author Share Posted December 30, 2017 By init function do you mean the OnDriverInit or OnDriverLateInit function? I don't have either of those functions, so I guess I may need to add them. Right now the IP address is set at the top of the code where there are some constants set, like a remapping table of commands. So I am thinking that adding a function for OnDriverLateInit might do the trick. Link to comment Share on other sites More sharing options...
RyanE Posted January 1, 2018 Share Posted January 1, 2018 I wouldn't store ip in a variable at all. It's not an expensive call to just get it by calling C4:GetBindingAddress(6001) any time you need it. RyanE Link to comment Share on other sites More sharing options...
zaphod Posted January 1, 2018 Author Share Posted January 1, 2018 I am actually considering changing this from a binding to a property - the reason is that an end user could then change it himself without needing a dealer. Especially since I am now using URL Gets which aren't really a persistent connection the way that a NetConnect and SendToNetwork worked. Any main reason to choose betwen a network binding and a Property that can more easily be changed? I have seen Drivers with both - I think the Hue binding has the IP for the hub as a property. Link to comment Share on other sites More sharing options...
RyanE Posted January 1, 2018 Share Posted January 1, 2018 Binding is better if your device supports SDDP. Bindings also can show online status in 2.9.2+ (maybe it's 2.10, I forget), but the driver has to manually manage that itself. i.e. it can reflect that the device is online, even if using urlGet, and even if it's not actually online all the time (since HTTP is connectionless). I doubt it's all that useful in the driver you're doing. Otherwise, property is not a bad choice for drivers that use urlGet/urlPost/etc. RyanE Link to comment Share on other sites More sharing options...
Recommended Posts
Archived
This topic is now archived and is closed to further replies.