This project provides property lists describing devices that can be used with Roomie Remote (a home theater remote control for iOS) in tandem with cec-web (RESTful webservice to control devices via the CEC bus in HDMI)
I love most everything about Roomie. One of the only things that I don't like is that they don't have 1000 developers working 24/7 to reverse engineer arcane control protocols for all my devices, like the Sony PlayStation 4 or the Apple TV (although the recently got great support for the latter!). After purchasing a PS4, I became annoyed that I couldn't do simple things like turn it on and off remotely through Roomie.
So, I started looking around for a solution and found a post on the Roomie forums by jasmas, explaining that he had set up a bridge between Roomie and HDMI-CEC through his Raspberry Pi to control devices in his setup that didn't have native Roomie support. I realized that this was a great solution, and I already had a Pi hooked up to my TV serving as a Plex client anyway! I quickly cloned his project, cecd and with a few minutes of work was amazed that I was controlling my TV through Roomie, and it was pretty fast! However, I was hungry for more. I forked his project into my own cecd and quickly wasted a few hours learning all about CEC and building a bigger property list with more commands added. I was pretty happy, as I was controlling my TV and now my PS4 with Roomie and it worked pretty well.
After using this setup for a few months now, I had found quite a few issues with it. Namely, it's really a giant hack that pipes TCP input into socat which then sends it onto cec-client from the libcec project. I would have to restart my scripts every few days, it was sometimes prone to lag, and just wasn't a clean solution overall. So I started looking for a new solution. Initially, I tried using adammw's node-cec since Node.js is my favorite language (yay Javascript!) and spent a few weeks banging my head against the wall, trying to read C code and understand how to make things work. It proved fruitless so I quickly gave up. In addition, node doesn't seem to run so well on Raspberry Pi and requires work to set it up and get the modules installed.
I started looking around for a new solution and stumbled onto cec.go by chbmuc. This looks great! I haven't done much work with Go except a very short stint years ago when it was very young, but I'll give it a try. I kept banging my head against the wall and made some good progress on a Go implementation of a TCP server that is connected to cec.go, but I realized that it wouldn't work that well, and I could make life a lot easier. As I was looking around again for ideas, I finally found my answer to all my problems: cec-web another project by chbmuc. Finally! Someone did some of my work for me! Roomie knows how to speak HTTP, so this was a match made in heaven. Within a few minutes I was up and running with Go on my Raspberry Pi and compiled cec-web.go. It was so much faster! Everything worked! Exclamation points! I quickly wrote up a property list with all of the supported CEC commands (thankfully, he already had wrote a map of human readable commands to hex values). After a few hours troubleshooting and coming up with a perfect property list, I had it. A fully working, generic implementation of a property list covering all of the codes, including some edge cases and extra functionality (like HDMI input switching). I was happy, Roomie was happy, my PS4 was happy since it wasn't being left on accidentially all the time anymore! So here we are... (also, why did I just write this novel in a README file. I guess it's just the excitement levels)
You need a few things to get started:
plutil convert -xml1 RoomieCodes.plist
in terminal to convert them from binary to text format.go get
go build cec-web.go
./cec-web -i 0.0.0.0 -n "Roomie CEC-Web"
(you can change the OSD name to anything you want. Also, you may have faster startup times if you add -a RPI
to the end of the command, assuming you are using a Raspberry Pi)~/Dropbox/Roomie
.cec-web
starts on port 8080
.I've added two of my own code sets in this repository already, one for a Sony PlayStation 4 and one for my Toshiba 55WX800U TV. You can use them as base configurations and customize them to your needs. These instructions are written for creating a code set for PS4, but the same logic can be applied for any device type.
brand
is the manufacturer name, cat
is the name/model of the device and type
corresponds to a Roomie Type (listed below). Do not modify method
. I set brand
to Sony, cat
to PlayStation 4 and type
to 8 which is Game System. To find the correct code number, refer to the Roomie DDKAll of the commands that are in the MasterCodes file are for the User Button Pressed function in the CEC spec, but you can also add raw CEC commands that will be passed through directly. You can see that's how I build the INPUT HDMI commands out. Just copy the same format into a new command. You can also of course add any of the other endpoints that cec-web() has to offer.
As an alternative to building your own code set entirely, you can use .KEY SEND
to send a custom key code that may not be listed in MasterCodes, i.e. if there is a vendor specific code that does what you need, you can use .KEY SEND
and put the correct hex code in as the parameter. The valid hex codes are listed in the HDMI-CEC specs on page 95 (titled CEC Table 27 User Control Codes). You can also generate them from CEC-O-Matic.
In the code sets, $AUTH1$
is used to allow you to use one generic code set for any device type. It expects a device identifier to be given as the authentication info (although this is really just a hack, as we don't use it for auth)
To get a list of all of your devices and their identifiers:
cec-web
is running on your CEC-enabled device and is accessible from another computer on your network.http://192.168.1.2:8080/info
, where 192.168.1.2 is the IP address of the device running cec-web
{
"Playback": {
"OSDName": "Chromecast",
"Vendor": "",
"LogicalAddress": 4,
"ActiveSource": false,
"PowerStatus": "on",
"PhysicalAddress": "1.0.0.0"
},
"Playback2": {
"OSDName": "PlayStation 4",
"Vendor": "Sony",
"LogicalAddress": 8,
"ActiveSource": false,
"PowerStatus": "standby",
"PhysicalAddress": "3.0.0.0"
},
"TV": {
"OSDName": "TV",
"Vendor": "Toshiba",
"LogicalAddress": 0,
"ActiveSource": false,
"PowerStatus": "standby",
"PhysicalAddress": "0.0.0.0"
},
"Tuner": {
"OSDName": "cec-web",
"Vendor": "Toshiba",
"LogicalAddress": 3,
"ActiveSource": false,
"PowerStatus": "on",
"PhysicalAddress": "2.0.0.0"
}
}
and I want to control my PS4, the device identifier i'd use is Playback2
. If you don't normally look at JSON all day like I do, it may be helpful to copy the entire blob and paste it into JSONLint for better readability.
If you create your own code sets, please contribute back! Just submit a pull request and i'll get right to merging it.
This wouldn't have been possible without jasmas, chbmuc, adammw and of course the hard work of everyone at Roomie Remote.
MIT
CEC-O-Matic - A great way to generate valid CEC commands
The HDMI-CEC specification PDF
The Roomie Remote Device Development Kit (DDK)
ID | Name | Notes |
---|---|---|
0 | A/V System | |
1 | Auxiliary | |
2 | Blu-ray Player | |
Cable | (Deprecated, use 18) | |
4 | CD | |
5 | DTV Converter | |
6 | DVD | |
7 | DVD/VCR Combo | |
8 | Game System | |
9 | Home Theater System | |
10 | iPod Dock | |
11 | LaserDisc | |
12 | Lighting | |
13 | MediaPlayer | |
14 | Multizone System | |
15 | Projector | |
16 | Receiver/Pre-Amp | |
(Deprecated, use 18) | ||
18 | Set Top Box | |
19 | Soundbar | |
20 | Subwoofer | |
21 | Switcher | |
22 | Tuner | |
23 | TV | |
24 | TV/DVD Combo | |
25 | TV/DVD/VCR Combo | |
26 | TV/VCR Combo | |
27 | VCR | |
28 | Video Processor | |
29 | Climate Control | |
30 | Video Camera |