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

pychromecast - python node-castv2 - java script

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

receiver-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.

