Hi Folks!
I am slowly working on a Home Automation controller similar to OpenHAB or HomeAssistant, but built with Elixir!
One feature I am looking to replicate is the ability to control different types of Components, or Things. Here are the compatible HomeAssistant components. A pretty large list and many client/controller libraries for off the shelf home automation products do not exist for Elixir!
Sonos, the most popular wireless speakers system, a common component for home automation controllers, and something I happen to have on hand for example. Libraries/tools exist to control a Sonos system from Python and Javascript, but nothing for Elixir…
To get a better idea of how I want to build common clients to be controlled via the large umbrella home automation project I have decided to work on a Sonos Controller OTP application that can easily be integrated with other projects. It also happens to be a pretty good project to help learn and understand OTP.
After a few days of messing around I think I have a good enough idea how the Sonos UPNP/SOAP API works, but having a bit of trouble with the implementation.
This is still very much a prototype, but lays the foundation for how I envision the controller functioning.
Sonex Project Repository
The Sonos API is a bit richer than HTTP/REST API…
- UPNP for auto discovery of Sonos devices on a LAN
- UPNP subscriptions
- SOAP/XML WebService API
Auto discovery was easy, have that working fine, simple POST requests to control a Sonos Zone e.g. Play, Pause, Volume is working fine.
My concerns are surrounding the subscriptions…
In order keep track of changes made to any of the Sonos Devices by a different controller, you can subscribe to events. By sending an HTTP SUBSCRIBE request to a specified Sonos player, it will emit events back to you as HTTP POSTS with XML body.
Am using HTTPoison as an HTTP Client for sending the POST/SUBSCRIBE messages, and cowboy as the HTTP Server to handle incoming Subscription events.
I am having problems parsing the Incoming XML sent from the Sonos devices I have subscribed to recieve events from.
Not sure if it is malformed or what. Could be using SweetXML improperly…
After cleaning the HTML encoding this is what the XML looks, like:
<e:propertyset xmlns:e="urn:schemas-upnp-org:event-1-0">
<e:property>
<LastChange>
<Event xmlns="urn:schemas-upnp-org:metadata-1-0/AVT/" xmlns:r="urn:schemas-rinconnetworks-com:metadata-1-0/">
<InstanceID val="0">
<TransportState val="STOPPED"/>
<CurrentPlayMode val="NORMAL"/>
<CurrentCrossfadeMode val="0"/>
<NumberOfTracks val="0"/>
<CurrentTrack val="0"/>
<CurrentSection val="0"/>
<CurrentTrackURI val=""/>
<CurrentTrackDuration val="0:00:00"/>
<CurrentTrackMetaData val=""/>
<r:NextTrackURI val=""/>
<r:NextTrackMetaData val=""/>
<r:EnqueuedTransportURI val=""/>
<r:EnqueuedTransportURIMetaData val=""/>
<PlaybackStorageMedium val="NONE"/>
<AVTransportURI val=""/>
<AVTransportURIMetaData val=""/>
<NextAVTransportURI val=""/>
<NextAVTransportURIMetaData val=""/>
<CurrentTransportActions val="Set, Play, Stop, Pause, Seek, Next, Previous"/>
<r:CurrentValidPlayModes val=""/>
<r:MuseSessions val=""/>
<TransportStatus val="OK"/>
<r:SleepTimerGeneration val="0"/>
<r:AlarmRunning val="0"/>
<r:SnoozeRunning val="0"/>
<r:RestartPending val="0"/>
<TransportPlaySpeed val="NOT_IMPLEMENTED"/>
<CurrentMediaDuration val="NOT_IMPLEMENTED"/>
<RecordStorageMedium val="NOT_IMPLEMENTED"/>
<PossiblePlaybackStorageMedia val="NONE, NETWORK"/>
<PossibleRecordStorageMedia val="NOT_IMPLEMENTED"/>
<RecordMediumWriteStatus val="NOT_IMPLEMENTED"/>
<CurrentRecordQualityMode val="NOT_IMPLEMENTED"/>
<PossibleRecordQualityModes val="NOT_IMPLEMENTED"/>
</InstanceID>
</Event>
</LastChange>
</e:property>
</e:propertyset>
Anyone have experience with SweetXML that could provide some tips for handling XML incoming over HTTP?
Also looking for contributors who want to help with this or other projects related to the Elixir Home Automation Controller, lots of things are lacking Elixir Client libraries.
I cannot build them all myself
Thanks a lot for any tips!
Going to be on here regularly, and also Slack/IRC to engage more with the community, I love Elixir!