Hi bherbie!
I'm the author of the ISY994i template (device #2276) which has some SOAP calls. I only play at being a programmer (more of a SysAdmin/integrator type) so take anything I write with a grain of salt...
My device driver uses GSD. I have a function to "subscribe" to an events channel, to receive a stream of status events from the ISY controller. As part of the function, it does a base64 encoding of the Username and password as part of the call (parameters 114 & 115). It looks like this...
def subscribeToISY()
# Prepare to send a subscription SOAP request to the device.
# Subscription is a one-way stream of events from the ISY to
# LMCE using the LMCE GSD conn_ method.
$port = device_.devdata_[69].to_s
auth_s=Base64.encode64(device_.devdata_[114]+":"+device_.devdata_[115])
soapBody ='<s:Envelope><s:Body><u:Subscribe xmlns:u="urn:udi-com:service:X_Insteon_Lighting_Service:1"><reportURL>REUSE_SOCKET</reportURL><duration>infinite</duration></u:Subscribe></s:Body></s:Envelope>'
s = "POST /services HTTP/1.1 \x0D\x0A"
s+= "Host: "+$host+":"+$port+" \x0D\x0A"
s+= "Content-Length: "+soapBody.length.to_s+" \x0D\x0A"
s+= "Content-Type: text/xml; charset=\"utf-8\" \x0D\x0A"
s+= "Authorization: Basic "+auth_s+" \x0D\x0A"
s+= "NT:upnp:event \x0D\x0A"
s+= "SOAPACTION:\"urn:udi-com:service:X_Insteon_Lighting_Service:1#Subscribe\" \x0D\x0A\x0D\x0A"
s+= soapBody.to_s
log("Attempting to Subscribe to ISY Events")
debuglog(s.to_s)
# Attempt to subscribe and retrieve data from the ISY
subscribe = conn_.Send(s.to_s)
log(subscribe)
end
I send commands back to the ISY asynchronously using it's REST interface, like so:
def sendISYcommand(command)
# This function sends commands to the ISY using it's REST interface.
# Does not use the subscription channel conn_ method.
# Commands are sent asynchronously, and success/fail is returned using
# this function. Device feedback is received via the subscription.
#
# $username=device_.devdata_[114].to_s
# $password=device_.devdata_[115].to_s
$port = device_.devdata_[69].to_s
res = Net::HTTP.start($host) {|http|
req = Net::HTTP::Get.new(command)
req.basic_auth device_.devdata_[114].to_s, device_.devdata_[115].to_s
response = http.request(req)
xml_data = (response.body)
debuglog($yellow + "====== / sendISYcommand response body ======" + $grey)
debuglog(xml_data)
debuglog($yellow + "====== sendISYcommand response body / ======" + $grey)
doc = REXML::Document.new(xml_data)
s = ""
s = REXML::XPath.first(doc, "RestResponse/status")
if s != nil then
if s.text != "200" then
# Didn't get the HTTP OK :-( return error code
return s.text
end
end
p = ""
p = REXML::XPath.first(doc, "properties/property")
if p != nil then
return p.text
end
return doc.to_s
}
end
Feel free to peruse the code in the template if this looks like something useful for you. The interesting stuff is in "355 Process Initialize" and "373 Private Method Listing".
The Basic flow of the device start-up is:
355 Process Initialize (all the set-up stuff, calls functions in 373 Private Method Listing).
350 Process Incoming Data (basically, loops processing data coming in from the subscription channel). Calls functions in 373 Private Method Listing.
Events from LMCE heading outbound to the ISY are serviced by 384 Process Receive for Child, which parses the LMCE commands, formulates the appropriate REST URL , and then calls my function sendISYcommand(command), where command is the URI encoded REST URL. That code looks like this:
cmdId = cmd.id_ # Command ID: ON, OFF, SET LEVEL
cmdTo = cmd.devidto_ # Device ID in LinuxMCE
devPort = device_.childdevices_[cmdTo].devdata_[12] # 12 contains a port/channel
childType = device_.childdevices_[cmdTo].devtemplid_ # Template ID to know type of device: switch or dimmer
case cmdId
when 192 #192 is ON
command = "/rest/nodes/#{URI.encode(devPort)}/cmd/DON"
when 193 #193 is OFF
command = "/rest/nodes/#{URI.encode(devPort)}/cmd/DOF"
when 184 #184 is Level of dimmer
dim_level = percenttodecihex(cmd.params_[76])
log("------dce--- Dim Level:" + dim_level.to_s)
command = "/rest/nodes/#{URI.encode(devPort)}/cmd/DON/#{dim_level}"
else
end
log(command)
response = ""
response = sendISYcommand(command)
log(response)
You can find the commands you'll be interested in via the LMCE web GUI, under Advanced -> DCE -> Commands. Look for the media commands. Hopefully this provides some food for thought...
Good luck with your device driver!
/Mike