The first I had to figure out a way I can communicate with Chromecasts. The official API to communicate only supports Android, iOS and Chrome browser. For my purpose either of those options are usable, I needed to communication from a microcontroller.
Third party options:
- pychromecast - python
- node-castv2 - java script
- gcast - rust
None of these options were appropriate for my use case but I have found a lot's of useful information in the documentations.
Protocol-buffers:
Chromecasts use a communication protocol called Protocol-buffers or protobuf, developed by Google.
To use protocol-buffers you need to 'define' your protocol in a .proto file which you can compile out to a library. The supported languages are:
- C++
- C#
- Dart
- Go
- Java
- Python
I started development on a PC and I choose Python because it was the easiest and quickest to develop in for me. At first I tried to construct my own protocol-buffer messages but I couldn't get it to work.Then I tried the .proto file and the compiled library from the pychromecast library, but i still didn't got any response.
Then I tried to capture the messages sent from the pychromecast library with wireshark, but the socket is encrypted.
Then I inserted a few print statements in to the library before sending the messages.
And i got messages like this:
b'\x00\x00\x00Y\x08\x00\x12\x08sender-0\x1a\nreceiver-0"(urn:x-cast:com.google.cast.tp.connection(\x002\x13{"type": "CONNECT"}'
With the protocol-buffer libray I could parse these strings and into more readable JSON format.
When i tried to send these back, I got an answer from the Chromecast - Finally!
I continued with this method and found the message responsible for changing the volume, I could even change the value and it still worked.
Done. Right?
Not so fast!
For some reason it only worked when I converted the messages to strings with the precompiled protocol-buffer library.
Due to size and complexity I can't use the protobuf library on a microcontroller, I need a simpler solution.
My first thought was creating messages to set the volume from 0 to 100 and from that create a lookup table. As I was creating that table I noticed a pattern, besides the value of the volume i wanted to change there is a request number. Every message from the initial connection is numbered, starting from 1 and increments by 1. I needed to change that as well. Although almost everything else stayed the same between the messages there was still one important difference. Every part of the message had a number before it indicating its size. Since I wanted to send volume and request values from single digits to triple digits (0 to 100) I needed 5 different sized message. From those 5 created messages I can pick according to the current volume level and request number. And it worked. :)
Now I got it working without any third party library, I was getting closer.
Discussions
Become a Hackaday.io Member
Create an account to leave a comment. Already have an account? Log In.