DTH for Chromecast / Google Home

TL;DR: I’ve created a DTH that allows you to talk to your Chromecasts
/ Google Homes. It’s ready for testing if you’re familiar with using
the SmartThings IDE / Github integration and can deal with the
(inevitable) bugs that will show up. There’s only very basic
documentation (this post) at this point.

Components

The Chromecast integration consists of three components:

  • Chromecast Manager, the service manager smartapp
  • Chromecast DTH
  • an intermediary app that runs in the cloud, receiving commands from
    the DTH and passing them on to your Chromecast / Google home.

The cloud intermediary

While the rest of the code here is relatively standard, using a cloud
intermediary adds complexity. In particular, it comes with two issues:

  • You need create an app running in the cloud.
  • That cloud app needs to be able to talk to your Chromecast(s), so
    you have to forward outside connections to your Chromecast(s) by using
    port forwarding.

Running the cloud app

That app is a node.js webservice that you can find at
https://github.com/germasch/smartthings-cast. I’ve been using
heroku.com to run it at the free tier, but it should run on pretty
much any cloud provider that provides node.js integration.

You can also just use my instance of the app for now, it’s at
https://pure-atoll-25146.herokuapp.com/ . This comes with the
following constraints:

  • It’s using the free tier, so there’s a limit in the number of
    requests it can handle, if I run out, this will stop working. Also,
    the free tier suspends apps that have seen no activity in the last 30
    mins, which causes an additional couple of seconds of delay when
    accessing your Chromecast device.

  • I can (and do) look at the debug logs, which means I can see your
    activity. No passwords or anything are sent to / through the app, but
    I can see the IPs / ports of your Chromecasts, and what you’re
    playing. In theory, I could tell your Chromecast to stream some
    horrible music at max volume at 3am…

The two issues above can be resolved by you running your own
instance.

One further security / privacy issue can’t be easily resolved: The
cloud app needs to talk to your Chromecast(s). In order to do that,
you need to add port forwarding rules to your Router, and those rules
allow the external internet to talk to your Chromecasts. You may be
able to restrict the forwarding to the heroku’s IP pool, which would
greatly help in preventing having the Chromecasts too far out in the open.

Alternatively, in the future I’m hoping to support running the cloud
app locally on your network. That requires some kind of computer to do
so (raspberry pi or pc, or potentially an Android device), and would
avoid the cloud complexity and security concerns.

There will have to be some kind of intermediary for the foreseeable
future, because talking to the Chromecast requires establishing a
websocket, while the local HubAction does not even provide https at
this point. For proper discovery, M-DNS would be needed as well, but
that’s easier to work around.

Service Manager / DTH

Installing the service manager / dth should be fairly straight forward
if you’re familiar with the github integration – the repo is at
https://github.com/germasch/SmartThingsKG , and you need
devicetypes/germasch/chromecast.src/chromecast.groovy and
smartapps/germasch/chromecast-manager.src/chromecast-manager.groovy.

Install/publish the DTH, then the smartapp. When you add the smartapp,
it’ll scan your local network for Chromecasts. That uses SSDP, which
is actually the old protocol to discover Chromecasts, but it still
works, though it doesn’t find Chromecast groups (a to-do item).

You can then pick which devices to represent a : s SmartThings devices,
and continue to configuration. First of all, you have to enter the URL
to reach your cloud app, and then for each Chromecast device you have
to provide information on how to access it from your cloud app. In
general, that means to create a port forward to :8009 from : on your
Router. You then enter the and
in the configuration for the respective Chromecast.

Hit done, and that should be it.

What works / doesn’t work

The Chromecast DTH implements “Music Player” and "Speech Synthesis"
capabilities, at least mostly. There’s currently no send/resume, and
it seems that other devices like Sonos implement additional commands
that apps may rely on. Let’s consider that a to-do.

The “speak” command works, but it’ll interrupt whatever is currently
playing on the Chromecast, and it can’t resume. In general, proper
resume will be difficult to implement, since Chromecast doesn’t really
support it.

You can control play/pause, stop, volume, mute, nextTrack / previous
Track, and some information about the currently playing Track may be
displayed.

The DTH does not poll or refresh automatically. That’s a to-do item
which can be much improved, but it’ll require work. (It’d be easier to
just poll every 5 seconds, but I don’t like that out of principle, and
it’d also make it much more likely to hit the free cloud app limits).

General

The cloud app uses https://github.com/thibauts/node-castv2-client to
actually talk to the Chromecast, so credit for implementing the
protocol goes there for the most part.

There are a bunch of features to be implemented, bugs to fix, etc. I’d
be more than happy to find a couple of people who want to help to make
this project production-ready and easier to use, including people who
test, make improvement suggestions, write documentation, etc.

14 Likes

Cool start. Just needs a bow and a “that was easy button”. :slight_smile:

1 Like

Well, I guess I’ll focus on making it work locally first. That’ll require a local node.js capable server (raspberry pi, PC/Mac, maybe Android), but other than that should be fairly straightforward to use.

1 Like

Local would be awesome. Thanks for working on this project.

1 Like

Got everything up and running, using the node service on a local Pi. I’m trying to use CoRE to post a notification to two of these at the same time, but it seems like it plays the message on the first Home device, waits for it to end, then plays the same message on the second Home device. Is there any way to have them both speak at the same time? It doesn’t need to be exactly synced like a cast group, but if I’m sending a notification like “Garage door is opening” to all three, I’d rather have them speak in parallel than sequentially, by the time the message starts playing on the third device the purpose of the warning is moot as whoever came home is already inside the house.

I’d even be willing to run parallel node.js servers on different ports. I tried changing the smartapp code to allow multiple instances but when I created the second instance it seemed like it wouldn’t save and I couldn’t act on the device it created.

One other note - I don’t see an option to remove the app once it’s installed. Am I missing something?

1 Like

Sorry for the late reply, life and stuff…

It should be possible to play messages on different cast devices at the same time. My guess right now would be that maybe the text-to-speech engine that smartthings uses is causing the issue. I’ll look at it, but it may be a little while, I’m also working on better local support – including for cast groups, which I guess might solve that problem, too.

On the missing “remove app”, that’s an oversight (bug).

1 Like

I’m no coder but I’d love to install the node.js bit on and old Android phone for local use.

Excuse me if I’m stupid but seems I could use this post as a guide:
https://medium.freecodecamp.com/building-a-node-js-application-on-android-part-1-termux-vim-and-node-js-dfa90c28958f#.xdht3flj4

Install termux from the play store. Use command line to install vim and node. js then use vim to create the file from the GitHub link and presto changing done.

I’ll fiddle on the weekend when I have time. But does that sound crazy to try?

so i tried to get it to run on android but no dice.

I have an old android 4.4. phone floating around
installed gnuroot debian (termux not compatible with this version of android)
in debian i did:
apt update && apt upgrade
apt install coreutils
apt install vim (to do some testing as suggested in above link- and the resultant test.js app worked)
apt install nodejs
apt install npm (used to make package.json for above test and all worked)

So fiddling around i got nodejs to work on android.

then i downloaded the app.js and package.json from github and tried those but get:
“syntax error: unexpected strict mode reserved word” errors.

I tried making a new package,json with npm init and same result.

I googled a bit since i have no idea what im doing- lol- and tried to run nodejs with --use_strict argument (before and after app,js since i dont even know the proper syntax myself) and still no joy.

not sure where to go from here. Probably need to wait for someone a bit smarter than me…

using the shared herokuapp cloud server works great- thanks for sharing.

but i would love to get something local instead.

I got node installed on my synology diskstation but it also gives the same strict mode syntax error when i go to run it.

DiskStation> node app.js
/volume1/public/st-node/app.js:54
let body = req.body;
^^^
SyntaxError: Unexpected strict mode reserved word
at exports.runInThisContext (vm.js:73:16)
at Module._compile (module.js:443:25)
at Object.Module._extensions…js (module.js:478:10)
at Module.load (module.js:355:32)
at Function.Module._load (module.js:310:12)
at Function.Module.runMain (module.js:501:10)
at startup (node.js:129:16)
at node.js:814:3

… i guess back to the shared server…

That’s weird, it’s working fine on my Pi.

Sorry, I haven’t had time lately to work much on this. From the sound of it, it seems like a problem caused by an older version of node.js / javascript that doesn’t support “let”. If it’s just complaining about that, you could try to replace all of the "let"s with "var"s.

sorry I’m nothing but bad news.
did search and replace for all let’s to var’s and that comes up with different error:

DiskStation> node app.js
/volume1/public/st-node/app.js:232
.then(() => self._getMediaStatus())
^
SyntaxError: Unexpected token )
at exports.runInThisContext (vm.js:73:16)
at Module._compile (module.js:443:25)
at Object.Module._extensions…js (module.js:478:10)
at Module.load (module.js:355:32)
at Function.Module._load (module.js:310:12)
at Function.Module.runMain (module.js:501:10)
at startup (node.js:129:16)
at node.js:814:3

I think this is the version command?

DiskStation> node -v
v0.12.6

is that possible?

got node updated to 4.4.2 and it app.js seems to be all good. (now off to learn how to install vastv2-client)

1 Like

Anyone get this working on local lan? If so how did you do it?

Sorry, should specify on PC

I got it working on a synology linux server. Same basic steps would apply.

From memory (and trial and error so might be off a bit and disclaimer first time I ever touched. Node so maybe not best methods – and typing on my phone so…)

Install node (on the PC)
Then create a project directory
Copy the github node files to the directory.
Then from command line in that directory you type node app.js
It will error what other stuff you need to install (something about module missing I think)
Then you type npm install to download and install that bit.
Type Node app.js again- repeating missing installs as needed
Eventually it will have all it needs and say sometime bout server listening on port 8080
Probably need to open port 8080 on your PC firewall
Probably need to set your PC to have static IP ( in network settings itself or use your router to reserve the address)
Probably want to set up a Windows batch file to run node app.js from the correct directory at each boot so it is still working after reboots (Not sure anymore how to do that with modern windows- just havent needed to)

Now install the dth and smartapp in smarthings IDE.
Run the smartapp on your phone and select run local. I think it will ask for IP address, use the one you did above

If all is well there will be a new device in the app on your phone. It even has test buttons. If I recall the test button will make the Google home chirp. And the test TTY button will say a test phrase.

Life is good!

Now set up core all you want to speak phrases based on whatever.

1 Like

OK got node app.js to work. Says listening on port 8080 and dth and app installed in smartthings. Nothing happens from there. OpenING ports on router seems to be the issue i guess. Didn’t think I needed to open ports on an internal network but maybe I’m wrong.

Shouldn’t need to open ports on your router but likely need to open ports on Windows firewall of the machine running node.

from another machine - use a browser to navigate to :8080 and see what happens.

On synology linux if the port is closed I get an error along the lines of rejected. If I open the port in the local machines firewall I get a web page that opens and says “can not get”.

If you can get the “cannot get” message then the server is working and the proper port is open in windows. (If windows your antivirus might also blocked the port)

1 Like

OK made sure firewall and anti virus weren’t an issue. Running node debug app.js brings up "break in \app.js:31
Which is 'use strict’
Thanks for all the help. Much appreciated.

OK got the app working. Now it’s the core piston that doesn’t work. :blush:

1 Like