-
Notifications
You must be signed in to change notification settings - Fork 26
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
44 changed files
with
2,867 additions
and
929 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
language: node_js | ||
node_js: | ||
- node | ||
cache: | ||
directories: | ||
- node_modules | ||
before_install: | ||
- sudo apt-get -qq update | ||
- sudo apt-get install -y build-essential libavahi-compat-libdnssd-dev | ||
before_script: | ||
- npm install -g gulp-cli | ||
script: gulp | ||
script: npm test |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
'use strict' | ||
|
||
const Channel = require('../models/Channel') | ||
|
||
const devices = require('./devices') | ||
|
||
let channels = [] | ||
|
||
const func = { | ||
init: () => func.refresh(), | ||
refresh: () => { | ||
Channel.find() | ||
.sort('name') | ||
.exec((err, _channels) => { | ||
if (err) console.log(err) | ||
channels = _channels | ||
}) | ||
}, | ||
list: () => channels, | ||
withId: id => channels.find(c => c._id == id), | ||
create: (opts, callback) => { | ||
var c = new Channel(opts) | ||
c.save((err, channel) => { | ||
if (err) console.log(err) | ||
channels.push(c) | ||
callback(channel._id) | ||
}) | ||
}, | ||
update: (id, opts, callback) => { | ||
Channel.update({ _id: id }, opts, err => { | ||
Object.assign(func.withId(id), opts) | ||
opts._id = id | ||
devices.updateChannel(opts, () => callback(id)) | ||
}) | ||
}, | ||
remove: (id, callback) => { | ||
Channel.remove({ _id: id }, () => { | ||
channels.splice(channels.findIndex(c => c._id == id), 1) // remove from local listing | ||
devices.removeChannel(id, () => callback()) | ||
}) | ||
} | ||
} | ||
|
||
module.exports = func |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
module.exports = obj => { | ||
let keys = Object.keys(obj) | ||
keys.forEach(k => { | ||
if (!obj[k]) delete obj[k] | ||
}) | ||
return obj | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,126 @@ | ||
'use strict' | ||
|
||
const Client = require('castv2').Client | ||
const config = require('./config') | ||
|
||
let func = { | ||
establish: (d, disconnectCallback) => { | ||
let host = d.address | ||
d.connectionFailCount = 0 | ||
if (d.status == 'offline' || d.status == 'waiting') { | ||
const client = new Client() | ||
client.connect(host, () => { | ||
// reset number of failed connection attempts | ||
d.connectionFailCount = 0 | ||
|
||
// create various namespace handlers | ||
d.connection = client.createChannel( | ||
'sender-0', | ||
'receiver-0', | ||
'urn:x-cast:com.google.cast.tp.connection', | ||
'JSON' | ||
) | ||
d.heartbeat = client.createChannel( | ||
'sender-0', | ||
'receiver-0', | ||
'urn:x-cast:com.google.cast.tp.heartbeat', | ||
'JSON' | ||
) | ||
d.receiver = client.createChannel( | ||
'sender-0', | ||
'receiver-0', | ||
'urn:x-cast:com.google.cast.receiver', | ||
'JSON' | ||
) | ||
|
||
// establish virtual connection to the receiver | ||
d.connection.send({ type: 'CONNECT' }) | ||
|
||
// start heartbeating | ||
d.missedHeartbeats = 0 | ||
d.pulse = setInterval(() => { | ||
d.missedHeartbeats++ | ||
if (d.missedHeartbeats > 6) { | ||
// receiver has been offline for more than 30 seconds | ||
d.status = 'offline' // mark receiver as offline | ||
clearInterval(d.pulse) // stop checking for pulse :( | ||
func.addError( | ||
d, | ||
'Receiver missed too many heartbeats, it is likely offline.' | ||
) | ||
} else d.heartbeat.send({ type: 'PING' }) | ||
}, 5 * 1000) | ||
d.heartbeat.on('message', (data, broadcast) => { | ||
if (data.type == 'PONG') { | ||
d.missedHeartbeats = 0 | ||
d.status = 'online' | ||
func.clearErrors(d) | ||
} | ||
}) | ||
|
||
// launch hub app | ||
d.receiver.send({ type: 'LAUNCH', appId: config.appId, requestId: 1 }) | ||
|
||
// monitor receiver status updates to insure hub is open | ||
d.receiver.on('message', (data, broadcast) => { | ||
if (data.type != 'RECEIVER_STATUS') | ||
func.addError(d, `Message from receiver: ${data.type}`) | ||
if ((data.type = 'RECEIVER_STATUS')) { | ||
// data.status contains relevant information about current app, volume, etc | ||
if (data.status && data.status.applications) { | ||
var apps = data.status.applications | ||
|
||
/* Backdrop means that our hub applications has stopped running, so we need to restart it */ | ||
if (apps.find(a => a.displayName == 'Backdrop')) { | ||
func.addError(d, 'Receiver closed hub, relaunching...') | ||
d.receiver.send({ | ||
type: 'LAUNCH', | ||
appId: config.appId, | ||
requestId: 1 | ||
}) | ||
} | ||
} | ||
} | ||
}) | ||
}) | ||
client.on('error', () => { | ||
d.connectionFailCount++ | ||
if (d.connectionFailCount > 6) { | ||
// receiver hasn't responded after 60 seconds | ||
clearTimeout(d.connectionFail) | ||
func.addError( | ||
d, | ||
'Receiver is unresponsive, attempting to reconnect...' | ||
) | ||
} else d.connectionFail = setTimeout(disconnectCallback, 10 * 1000) | ||
}) | ||
} | ||
}, | ||
hasErrors: () => Object.keys(errors).length > 0, | ||
getErrors: () => errors, | ||
addError: (device, message) => { | ||
// you can pass a tag directly instead of a device | ||
let tag = typeof device === 'object' ? device.deviceId : device | ||
if (!errors[tag]) | ||
errors[tag] = { | ||
name: typeof device === 'object' ? device.location : device, | ||
messages: [] | ||
} | ||
if (errors[tag].messages.indexOf(message) == -1) | ||
errors[tag].messages.push(message) | ||
}, | ||
clearErrors: device => | ||
delete errors[typeof device === 'object' ? device.deviceId : device], | ||
hasStatus: () => status.length > 0, | ||
getStatus: () => status.map(s => s.message), | ||
addStatus: (tag, message) => | ||
status.push({ | ||
tag: tag, | ||
message: message | ||
}), | ||
clearStatus: tag => (status = status.filter(s => s.tag != tag)) | ||
}, | ||
errors = {}, | ||
status = [] | ||
|
||
module.exports = func |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,9 +1,19 @@ | ||
'use strict' | ||
|
||
const mongoose = require('mongoose') | ||
|
||
module.exports = config => { | ||
const userPassword = config.mongoUser ? `${config.mongoUser}:${config.mongoPass}@` : '' | ||
mongoose.connect( | ||
`mongodb://${userPassword}${config.mongoHost}:${config.mongoPort}/multicast?authSource=${config.mongoAuthSource}`, { | ||
useMongoClient: true | ||
}).on('error', () => console.log('Could not connect to Mongo.')) | ||
} | ||
const userPassword = config.mongoUser | ||
? `${config.mongoUser}:${config.mongoPass}@` | ||
: '' | ||
mongoose | ||
.connect( | ||
`mongodb://${userPassword}${config.mongoHost}:${ | ||
config.mongoPort | ||
}/multicast?authSource=${config.mongoAuthSource}`, | ||
{ | ||
useMongoClient: true | ||
} | ||
) | ||
.on('error', () => console.log('Could not connect to Mongo.')) | ||
} |
Oops, something went wrong.