• Stars
    star
    180
  • Rank 213,097 (Top 5 %)
  • Language
    JavaScript
  • License
    ISC License
  • Created over 10 years ago
  • Updated over 2 years ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

Experiment to implement a sender API for Chromecast in Node.js

Nodecastor

NPM version Dependency Status npm

This library is an experiment to provide a sender API for Google Chromecast devices using mDNS and some TLS protobuf protocol instead of the DIAL discovery protocol. Early Chromecasts made use of DIAL but Google switched away from it. While SSDP/DIAL support is still present and some applications are still using it (like YouTube), existing applications have to migrate to the new SDK using the new protocol.

This library doesn't support DIAL/SSDP (and hence the applications relying on it). See nodecast instead.

Install

npm install nodecastor --save

You may need this on Ubuntu:

sudo apt-get install libavahi-compat-libdnssd-dev

Usage

This is still a work in progress. The API is not stable, the quality is pretty low and there are a lot of bugs.

Library

To use the library, you first need to discover what Chromecast devices are available on the network. This is an optional step as you can also declare a Chromecast manually from its IP address.

const util = require('util');
const nodecastor = require('nodecastor');

nodecastor.scan()
  .on('online', device => {
    console.log('New device', util.inspect(device));
  })
  .on('offline', device => {
    console.log('Removed device', util.inspect(device));
  })
  .start();

On Linux, if no device is discovered, first check that your machine is able to do mDNS address resolution. The library used for this purpose delegates this to the libc. You should have something like that in /etc/nsswitch.conf:

hosts: files mdns4_minimal [NOTFOUND=return] dns mdns4

Both online and offline events will invoke the callback with a CastDevice instance. You can also create the CastDevice instance manually:

new nodecastor.CastDevice({
  friendlyName: 'My secret Chromecast',
  address: '192.168.1.27',
  port: 8009
});

Once you have a CastDevice instance, you need to wait for the connection event. Then, you can request some informations about it:

d.on('connect', () => {
  d.status((err, s) => {
    if (!err) {
      console.log('Chromecast status', util.inspect(s));
    }
  });
});

You can get updated when the status of the Chromecast changes by listening to the status event:

d.on('status', status => {
  console.log('Chromecast status updated', util.inspect(status));
});

You can also request an application. This will give you a CastApplication instance.

d.application('YouTube', (err, a) => {
  if (!err) {
    console.log('YouTube application', util.inspect(a));
  }
});

Once you have a CastApplication instance, you can request a CastSession instance for this application. For that, you can either join an existing application (which should already be running) or you can run a new instance.

a.run('urn:x-cast:com.google.cast.demo.tictactoe', (err, s) => {
  if (!err) {
    console.log('Got a session', util.inspect(s));
  }
});
a.join('urn:x-cast:com.google.cast.demo.tictactoe', (err, s) => {
  if (!err) {
    console.log('Joined a session', util.inspect(s));
  }
});

The first parameter is the namespace you expect to run or join. Any messages sent on this session will use the given namespace.

You can then send messages and receive answers (not all messages have to be answered):

s.send({ data: 'hello' }, (err, data) => {
  if (!err) {
    console.log('Got an answer!', util.inspect(data));
  }
});
s.on('message', data => {
  console.log('Got an unexpected message', util.inspect(data));
});

Don't use callbacks for messages that you don't expect answers for. They will just leak memory...

A CastSession object can emit a close event when the connection is closed. A CastDevice object can emit a disconnect event when the connection with the device is lost and a connect event when the connection has been established (but there is no need to wait for such an event). You can close connection to a device with .stop().

Any object can take as an option a logger. For example:

const c = new CastDevice({
  address: '192.168.1.27',
  logger: console
});

By default, reconnection is tried on disconnect. Both Scanner and CastDevice constructors accept a reconnect object as an options. When set to false, no reconnection will be retried:

const c = new CastDevice({
  address: '192.168.1.27',
  reconnect: false
});

Otherwise, the provided object may contain some properties to influence the reconnection:

const c = new CastDevice({
  address: '192.168.1.27',
  reconnect: {
    maxRetries: 10,
    maxDelay: 10000, // ms
    initialDelay: 100 // ms
  }
});

Command-line helper

The functionality of this library can be tested with the chromecast helper. Invoke it with chromecast -h to get help. It embeds some simple examples too.

The Tic Tac Toe application is quite incomplete. It is expected to play against a human player. Here is how to use it:

  1. Download the Chrome version from GitHub
  2. Direct a browser to it (python -mSimpleHTTPServer if you want a quick way to get a webserver to serve the files)
  3. Start casting the application from Chrome.
  4. Starts chromecast tictactoe 192.168.1.24.
  5. On Chrome, click play.

The Dashkiosk application is a test for the Dashkiosk project.

Protocol description

There is no formal description of the protocol. However, you can look at channel.js which shows how to build low-level messages. The lower-level protocol is implemented directly in Chrome and the protocol is described in cast_channel.proto.

The high-level protocol, used by the Chromecast extension, can be discovered by modifying the extension. The following code can be appended to background_script.js:

chromesendAndLog = (channel, data) => {
  console.log('[TAP CHROMECAST send]', data);
  return chrome.cast.channel.send.apply(chrome.cast.channel, arguments);
};
chrome.cast.channel.onMessage.addListener((channel, data) => {
  console.log('[TAP CHROMECAST recv]', data);
});

Any occurrence of chrome.cast.channel.send needs to be replaced by chromesendAndLog. Monkey-patching seems to be ineffective because the whole chrome.cast.channel seems to be erased everytime you connect/disconnect to a Chromecast. Then, filter the log messages with TAP CHROMECAST in Chrome developper tools (click on background.html for the Chromecast extension in chrome://extensions).

Alternatives

More Repositories

1

network-lab

Networking lab using root-less VM
Shell
528
star
2

dashkiosk

Managing dashboards on various displays (especially those running on Android)
JavaScript
354
star
3

hellogopher

Makefile to build a Go project
Makefile
301
star
4

rfc5077

Various tools for testing RFC 5077
C
241
star
5

snimpy

interactive SNMP tool with Python
Python
180
star
6

video2hls

Prepare a video to be streamed with HLS
Python
171
star
7

awesome-configuration

My ~/.config/awesome directory
Lua
127
star
8

eudyptula-boot

Boot a Linux kernel in a VM without a dedicated root filesystem.
Shell
112
star
9

pragmatic-debian-packages

Pragmatic Debian packaging
Makefile
98
star
10

serverspec-example

Advanced use example of serverspec
JavaScript
98
star
11

jchroot

a chroot with more isolation
C
96
star
12

wiremaps

layer 2 network discovery application
Python
89
star
13

zshrc

My .zshrc
Shell
84
star
14

bootstrap.c

Boilerplate for small C projects (autotools)
C
74
star
15

i3wm-configuration

Python
72
star
16

vincent.bernat.ch

My own website
HTML
71
star
17

extend-netsnmp

Various examples on how to extend NetSNMP agent
C
46
star
18

ssl-dos

Various tools related to SSL denial of service
C
46
star
19

python-script

Sample self-contained Python script
Python
36
star
20

systemtap-cookbook

Some tools using systemtap
Python
29
star
21

vbeterm

Custom terminal based on VTE
C
21
star
22

xssproxy

Forward freedesktop.org Idle Inhibition Service calls to Xss
C
20
star
23

ip_vs_mh

Backport of ip_vs_mh for Linux (consistent hashing with Google's Maglev algorithm)
C
17
star
24

lanco

task launcher which does not want to be an init program
C
16
star
25

bootstrap.c-web

Boilerplate for small C projects (autotools) exporting a REST+SSE+WS API
C
14
star
26

puppet-workstation

Puppet setup to install my own workstation
Puppet
14
star
27

udpproxy

a Netfilter powered UDP proxy
C
13
star
28

cve-2015-3456

Experiments related to CVE-2015-3456
C
12
star
29

puppet-eizo

Puppet repository for "eizo"
Shell
12
star
30

ethtool-snmpd

Export ethtool stuff through SNMP
C
12
star
31

dot.emacs

My Emacs (and Gnus) configuration files
Emacs Lisp
12
star
32

fvwm-configuration

My configuration for fvwm
Shell
11
star
33

dashkiosk-android

Android application for Dashkiosk
Java
9
star
34

ansible-custom-module-examples

See https://vincent.bernat.ch/en/blog/2020-custom-ansible-module
Python
9
star
35

haproxy-debian-repository-wizard

Web application to select the appropriate Debian repository for HAProxy
HTML
9
star
36

junos-mode

Emacs major mode for JunOS configuration file
Emacs Lisp
9
star
37

ripe-atlas-lowest-latency

RIPE Atlas tool to determine the endpoint with the lowest latency
Python
8
star
38

ip_vs_csh

Consistent source hashing scheduler for Linux IPVS
C
8
star
39

ro-ro-tcp

performance enhancing proxy for TCP over links with high latency and moderate error rates
C
8
star
40

vpnoo

an IPSEc + XAuth client for Mac OS X
C
8
star
41

asn2org

AS numbers to organization names
Python
7
star
42

nixops-take1

Playground for NixOps
Nix
7
star
43

quagga

Quagga is free software that manages various IPv4 and IPv6 routing protocols.
C
5
star
44

flappy-bird-reborn-multiplayer

A "Flappy Bird" clone with multiplayer ability.
JavaScript
4
star
45

old-turbo-pascal-programs

Old programs that I wrote when I was a kid.
Pascal
4
star
46

cdktf-take1

Musing around CDKTF
TypeScript
3
star
47

splitpkcs12

PKCS#12 certificate splitter
C
3
star
48

net-snmp

Net-SNMP (not official)
C
3
star
49

ipoo

gather information about IP and hostnames
Python
3
star
50

dosbox

DOSBox, an x86 emulator with DOS. ⚠️ Not official. Not a complete mirror. Not updated.
C++
3
star
51

last-resort-gateway

Manage a last resort gateway
Go
2
star
52

pulumi-vultr

Pulumi provider for Vultr (based on the Terraform one), not official
Python
2
star
53

pygments-junos

JunOS lexer for pygments
Python
2
star
54

pygments-ios

IOS lexer for pygments
Python
2
star
55

homemanager-configuration

home-manager configuration for use with Debian Sid
Nix
2
star
56

www.une-oasis-une-ecole.fr

Source code for http://www.une-oasis-une-ecole.fr
HTML
2
star
57

Kitero

Interface and QoS switcher for router
Python
2
star
58

pulumi-gandi-old

Pulumi provider for Gandi, based on Terraform, not official
Python
1
star
59

pygments-haproxy

HAProxy lexer for Pygments
Python
1
star
60

QCss-3

load-balancer web service
Python
1
star