(#26) - Let there be light!
Insufficient coffee to fuel any witticisms or snarky remarks means I'll cut to the chase. The lighting controller in my house is from a company called TCP Connected. I've discussed the challenges I've had with their product back here.
Bottom line: it works (it controls the lights well), the company has abandoned the product and I've invested enough in the product that I don't want to abandon it.
Standing on the Shoulders -- Again
Several others out there in 'net land must feel the same way, in that they've reverse engineered the protocol used and resurrected the product. Thanks to folks like this person here, we're wresting control of the lighting gateway from the manufacturer and making the thing useful again. Thank you!The Code Chase We're Cutting to (towards?)
If you promise not to make fun of my Python, I'll share the relevant snippets.RoomGetCarousel
The RoomGetCarousel command is the command sent to the Lighting Gateway that returns a lot of information in an XML payload. In this large XML stream, you'll find the name of the rooms, the names of the bulbs, and their state.[ Nota Bene: You may be able to update the Gateway with new room and bulb information, but I've been doing that using the phone application when connected locally. ]
I have a TCPGatewayManager object who's responsibility is to send the https commands to the gateway.
The Gateway supports SSDP but mine's assigned a dedicated IP address so I don't bother with that discovery protocol.
Here's the call to the Gateway using HTTPS:
Parsing the XML payload slowly to discover rooms, bulbs and other neat things:
def load_rooms_and_devices(self):
logging.debug('reloading rooms and devices from gateway')
xmldata = self.my_gateway.get_response_room_get_carousel_command()
root = ET.fromstring(xmldata)
gwrcmd = root.find('gwrcmd')
gcmd = gwrcmd.find('gcmd')
gdata = gwrcmd.find('gdata')
gip = gdata.find('gip')
returnCode = gip.find('rc').text
#
# Iterate through the rooms and devices
# Bear in mind that you must send the right XML to the
# RoomGetCarousel command
# to retreive all of these fields below.
self.rooms = []
self.lights = []
self.light_names = []
for a_room in gip.findall('room'):
r_id = a_room.find('rid').text
r_name = a_room.find('name').text
r = {r_name: r_id}
self.rooms.append(r)
## print 'Room ID: ', r_id, ' Name:[', r_name, ']'
for a_device in a_room.findall('device'):
a_did = a_device.find('did').text
a_name = a_device.find('name').text
a_state = a_device.find('state').text
if a_state == '1':
a_device_powered_on = True
else:
a_device_powered_on = False
if a_device.find('offline') is not None:
a_online = False
a_level = "Unknown"
else:
a_online = True
a_level = a_device.find('level').text
## print ' Name:[', a_name, '] DID:', a_did, '
## Powered On:', a_device_powered_on,
## ' Connected To GW:', a_online, ' Level:', a_level
a_bulb = {'name': a_name, 'did': a_did, 'level': a_level,
'on': a_device_powered_on,
'connected': a_online, 'rname': r_name,
'rid': r_id}
self.lights.append(a_bulb)
self.light_names.append({a_name: a_did})
I'm still playing with the Python structures that hold my return values. Right now I care about: rooms (their names and numeric IDs) and bulbs (their name, their Device ID [did], their state and their room).
Next post will cover how to turn the lights on, off and dim them.
No comments :
Post a Comment