Skip to content

Commit

Permalink
Merge pull request #38 from superhawk610/wip
Browse files Browse the repository at this point in the history
v2.0 Milestone
  • Loading branch information
superhawk610 authored Dec 31, 2017
2 parents 9c8386a + 7d881dd commit c0922af
Show file tree
Hide file tree
Showing 29 changed files with 519 additions and 185 deletions.
7 changes: 7 additions & 0 deletions app/lib/cleanObject.js
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
}
26 changes: 19 additions & 7 deletions app/lib/connection.js
Original file line number Diff line number Diff line change
Expand Up @@ -99,16 +99,28 @@ let func = {
hasErrors: () => Object.keys(errors).length > 0,
getErrors: () => errors,
addError: (device, message) => {
if (!errors[device.deviceId])
errors[device.deviceId] = {
name: device.location,
// 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[device.deviceId].messages.indexOf(message) == -1)
errors[device.deviceId].messages.push(message)
if (errors[tag].messages.indexOf(message) == -1)
errors[tag].messages.push(message)
},
clearErrors: device => delete errors[device.deviceId]
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 = {}
errors = {},
status = []

module.exports = func
3 changes: 2 additions & 1 deletion app/lib/devices.js
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,8 @@ const findDevices = () => {
deviceId: id,
name: service.txtRecord.fn,
address: service.addresses[0],
port: service.port
port: service.port,
rotation: 'rot0'
})
}
})
Expand Down
4 changes: 4 additions & 0 deletions app/lib/sockets.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,10 @@ const func = {
init: server => {
io = require('socket.io')(server)
io.on('connection', client => {
console.log(
'connected client with host:',
stripIPv6(client.handshake.address)
)
clients.push(client)
client.on('disconnect', () => {
console.log(
Expand Down
30 changes: 30 additions & 0 deletions app/lib/squashKeyedArrays.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
module.exports = (obj, upgradeElementsToArrays) => {
let keys = Object.keys(obj),
arrays = []
keys.forEach(k => {
let key = /(.+)\[\d+\]$/.exec(k)
if (key && arrays.indexOf(key[1]) == -1) arrays.push(key[1])
})

arrays.forEach(a => {
let _arr = {},
arr = [],
highestIndex = 0
keys.forEach(k => {
let index = new RegExp(`${a}\\[(\\d+)\\]`).exec(k)
if (index) {
highestIndex = Math.max(highestIndex, index)
let item = obj[k]
if (upgradeElementsToArrays && !Array.isArray(item)) item = [item]
arr[index[1]] = item
delete obj[k]
}
})
for (let i = 0; i < highestIndex; i++) {
if (_arr.hasOwnProperty(i)) arr.push(_arr[i])
else arr.push(upgradeElementsToArrays ? [] : null)
}
obj[a] = arr
})
return obj
}
5 changes: 4 additions & 1 deletion app/lib/takeover.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
const Channel = require('../models/Channel')
const devices = require('../lib/devices')
const sockets = require('../lib/sockets')
const connection = require('../lib/connection')

var takeover = null

Expand All @@ -14,14 +15,16 @@ const func = {
if (err) console.log(err)

takeover = channel
connection.addStatus('takeover', 'Takeover is currently active!')
devices.refreshAll(() => callback())
})
},
deactivate: callback => {
takeover = null
connection.clearStatus('takeover')
sockets.list().forEach(c => c.emit('refresh'))
callback()
}
}

module.exports = func
module.exports = func
4 changes: 3 additions & 1 deletion app/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
const express = require('express')
const app = express()
const server = require('http').createServer(app)
const cors = require('cors')
const mongoose = require('mongoose')
mongoose.Promise = require('bluebird')
const bodyParser = require('body-parser')
Expand Down Expand Up @@ -37,6 +38,7 @@ channels.init()
sockets.init(server)

/* Express Setup */
app.use(cors())
app.set('view engine', 'pug')
app.set('views', path.join(__dirname, 'views'))
app.use(bodyParser.urlencoded({ extended: false }))
Expand Down Expand Up @@ -90,7 +92,7 @@ app.use('/takeover', require('./routes/takeover'))
/* Server */
server.listen(port, () => {
console.log('MultiCast is live!')
console.log(`listening at port ${port}...`)
console.log(`Listening at port ${port}...`)

if (!serveOnly) {
/* poll for active devices */
Expand Down
11 changes: 6 additions & 5 deletions app/models/Channel.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
'use strict';
const mongoose = require('mongoose')
const Schema = mongoose.Schema
'use strict'
const mongoose = require('mongoose')
const Schema = mongoose.Schema

const ChannelSchema = new Schema({
name: String,
layout: String,
URLs: [String]
URLs: [[String]],
duration: Number
})

module.exports = mongoose.model('Channel', ChannelSchema)
module.exports = mongoose.model('Channel', ChannelSchema)
8 changes: 4 additions & 4 deletions app/models/Chromecast.js
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
'use strict';
'use strict'
const mongoose = require('mongoose')
const Schema = mongoose.Schema

const ChromecastSchema = new Schema({
deviceId: String, // hexadecimal identifier provided by Chromecast
// don't confuse this with _id provided by Mongo
location: String,
channel: { type: Schema.Types.ObjectId, ref: 'Channel' },
rotation: String,
channel: { type: Schema.Types.ObjectId, ref: 'Channel' }
})

module.exports = mongoose.model('Chromecast', ChromecastSchema)
module.exports = mongoose.model('Chromecast', ChromecastSchema)
14 changes: 11 additions & 3 deletions app/routes/channels.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ const Chromecast = require('../models/Chromecast')
const Channel = require('../models/Channel')

const port = require('../lib/config').port
const squashKeyedArrays = require('../lib/squashKeyedArrays')
const cleanObject = require('../lib/cleanObject')

router.use((req, res, next) => {
if (req.body.URLs) req.body.URLs = req.body.URLs.filter(u => u.trim() != '')
Expand Down Expand Up @@ -49,7 +51,13 @@ router
})
else res.render('index', {})
})
.post((req, res) => channels.update(req.params.channel_id, req.body, id => res.send(id)))
.delete((req, res) => channels.remove(req.params.channel_id, () => res.sendStatus(200)))
.post((req, res) => {
channels.update(req.params.channel_id, squashKeyedArrays(req.body), id =>
res.send(id)
)
})
.delete((req, res) =>
channels.remove(req.params.channel_id, () => res.sendStatus(200))
)

module.exports = router
module.exports = router
140 changes: 81 additions & 59 deletions app/routes/devices.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,26 @@ const takeover = require('../lib/takeover')

const port = require('../lib/config').port

/* List of device rotations */
const rotations = [
{
value: 'rot0',
description: 'Landscape'
},
{
value: 'rot90',
description: 'Portrait'
},
{
value: 'rot180',
description: 'Landscape Reversed'
},
{
value: 'rot270',
description: 'Portrait Reversed'
}
]

router.get('/', (req, res) => {
res.render('index', { render: 'devices', devices: devices.list() })
})
Expand All @@ -22,7 +42,9 @@ router
res.render('index', {
render: 'device',
devices: devices.list().filter(d => d.unregistered),
channels: channels.list()
channels: channels.list(),
rotations: rotations,
rotation: 0
})
})
.post((req, res) => {
Expand All @@ -34,45 +56,6 @@ router
})
})

router.get('/:device_id', (req, res) => {
let d = devices.withId(req.params.device_id)
if (d && takeover.isActive()) {
res.render(`layouts/${takeover.channel().layout}`, {
deviceId: req.params.device_id,
channel: takeover.channel(),
casting: true
})
} else {
if (d) {
if (d.channel) {
/* device registered and channel set
display device page */
res.render(`layouts/${d.channel.layout}`, {
deviceId: req.params.device_id,
channel: d.channel,
casting: true
})
} else {
/* device registered but no channel set
display setup page */
res.render('setup-chromecast', {
device: d,
registered: true,
setupUrl: `${req.protocol}://${req.hostname}:${port}/`
})
}
} else {
/* device is not registered
display setup page */
res.render('setup-chromecast', {
device: d,
registered: false,
setupUrl: `${req.protocol}://${req.hostname}:${port}/`
})
}
}
})

router.get('/:device_id/connect', (req, res) => {
let d = devices.withId(req.params.device_id)
if (!devices.isOnline(req.params.device_id)) devices.reconnect(d.address)
Expand All @@ -93,31 +76,28 @@ router
res.render('index', {
render: 'device',
device: d,
channels: channels.list()
channels: channels.list(),
rotations: rotations,
rotation: d.rotation
})
} else render('index', {})
})
.post((req, res) => {
Chromecast.update(
{ deviceId: req.params.device_id },
req.body,
err => {
if (err) console.log(err)
Chromecast.update({ deviceId: req.params.device_id }, req.body, err => {
if (err) console.log(err)

let d = devices.withId(req.params.device_id)
d.location = req.body.location // update local info with location
console.log('host', d.address)
let c = sockets.withHost(d.address),
channel = null
if (req.body.channel) {
channel = channels.withId(req.body.channel)
d.channel = channel // update local info with channel
}
console.log('socket_client', c)
if (c) c.emit('change_channel', channel)
res.send(req.params.device_id)
let d = devices.withId(req.params.device_id)
d.location = req.body.location // update local info with location
d.rotation = req.body.rotation
let c = sockets.withHost(d.address),
channel = null
if (req.body.channel) {
channel = channels.withId(req.body.channel)
d.channel = channel // update local info with channel
}
)
if (c) c.emit('change_channel', channel)
res.send(req.params.device_id)
})
})
.delete((req, res) => {
Chromecast.remove({ deviceId: req.params.device_id }, () => {
Expand All @@ -126,8 +106,50 @@ router
d.unregistered = true
delete d.channel
delete d.location
delete d.rotation
res.sendStatus(200)
})
})

router.get('/:device_id/:preview*?', (req, res) => {
let d = devices.withId(req.params.device_id)
if (d && takeover.isActive()) {
res.render(`layouts/${takeover.channel().layout}`, {
deviceId: req.params.device_id,
channel: takeover.channel(),
rotation: d.rotation,
casting: !req.params.preview
})
} else {
if (d) {
if (d.channel) {
/* device registered and channel set
display device page */
res.render(`layouts/${d.channel.layout}`, {
deviceId: req.params.device_id,
channel: d.channel,
rotation: d.rotation,
casting: !req.params.preview
})
} else {
/* device registered but no channel set
display setup page */
res.render('setup-chromecast', {
device: d,
registered: true,
setupUrl: `${req.protocol}://${req.hostname}:${port}/`
})
}
} else {
/* device is not registered
display setup page */
res.render('setup-chromecast', {
device: d,
registered: false,
setupUrl: `${req.protocol}://${req.hostname}:${port}/`
})
}
}
})

module.exports = router
Loading

0 comments on commit c0922af

Please sign in to comment.