diff --git a/.gitignore b/.gitignore index eb03e3e..de42cc6 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ node_modules +config/config.json *.log diff --git a/README.md b/README.md index 59b7bad..b479e0d 100755 --- a/README.md +++ b/README.md @@ -52,7 +52,25 @@ In `development` mode, it just logs to stdout. Launch the app via `script/server` to run it in the development environment. -## Docs +## MQTT + +itunes-api can report its state changes to your MQTT broker. Just edit your +config file in `config/config.json` to add your MQTT host. + +itunes-api publishes topics with the namespace of: `itunes-api`. + +### Topics + +* `itunes-api/state`, `playing`|`paused`|`stop` - This is published whenever the +state is changed. +* `itunes-api/volume`, `45` - This is published whenever the volume level is +changed. +* `itunes-api/airplay_devices/:airplay_device_id/state`, `on`|`off` - This is +published whenever the state of an airplay device has changed. +* `itunes-api/airplay_devices/:airplay_device_id/volume`, `45` - This is +published whenever the volume level of an airplay device is changed. + +## API Docs This is a quick overview of the service. Read [app.js](app.js) if you need more info. diff --git a/app.js b/app.js index d67ac64..13368ac 100755 --- a/app.js +++ b/app.js @@ -1,6 +1,7 @@ var fs = require('fs') var path = require('path') var util = require('util') +var mqtt = require('mqtt'); var express = require('express') var morgan = require('morgan') var bodyParser = require('body-parser') @@ -10,6 +11,8 @@ var osascript = require('osascript') var airplay = require('./lib/airplay') var parameterize = require('parameterize'); +var config = require('./config/config.json'); + var app = express() app.use(bodyParser.urlencoded({ extended: false })) app.use(express.static(path.join(__dirname, 'public'))); @@ -17,6 +20,9 @@ app.use(express.static(path.join(__dirname, 'public'))); var logFormat = "'[:date[iso]] - :remote-addr - :method :url :status :response-time ms - :res[content-length]b'" app.use(morgan(logFormat)) +var mqttClient = mqtt.connect(config.mqtt); +var TOPIC_NAMESPACE = "itunes-api" + function getCurrentState(){ itunes = Application('iTunes'); playerState = itunes.playerState(); @@ -129,6 +135,11 @@ function getPlaylists(callback){ }) } +function publish(topic, message, options){ + topic = TOPIC_NAMESPACE + "/" + topic + mqttClient.publish(topic, message, options); +} + app.get('/_ping', function(req, res){ res.send('OK'); }) @@ -139,12 +150,14 @@ app.get('/', function(req, res){ app.put('/play', function(req, res){ iTunes.play(function (error){ + if (!error) publish('state', 'playing', {retain: true}); sendResponse(error, res) }) }) app.put('/pause', function(req, res){ iTunes.pause(function (error){ + if (!error) publish('state', 'paused', {retain: true}); sendResponse(error, res) }) }) @@ -157,6 +170,7 @@ app.put('/playpause', function(req, res){ app.put('/stop', function(req, res){ iTunes.stop(function (error){ + if (!error) publish('state', 'stopped', {retain: true}); sendResponse(error, res) }) }) @@ -179,6 +193,7 @@ app.put('/volume', function(req, res){ console.log(error) res.sendStatus(500) }else{ + if (!error) publish('volume', req.body.level, {retain: true}); sendResponse(error, res) } }) @@ -272,6 +287,7 @@ app.put('/airplay_devices/:id/on', function (req, res) { console.log(error) res.sendStatus(500) }else{ + publish('airplay_devices/' + req.params.id + '/state', 'on', {retain: true}); res.json(data) } }) @@ -283,6 +299,7 @@ app.put('/airplay_devices/:id/off', function (req, res) { console.log(error) res.sendStatus(500) }else{ + publish('airplay_devices/' + req.params.id + '/state', 'off', {retain: true}); res.json(data) } }) @@ -294,6 +311,7 @@ app.put('/airplay_devices/:id/volume', function (req, res) { console.log(error) res.sendStatus(500) }else{ + publish('airplay_devices/' + req.params.id + '/volume', req.body.level, {retain: true}); res.json(data) } }) diff --git a/config/config.sample.json b/config/config.sample.json new file mode 100644 index 0000000..4f681a8 --- /dev/null +++ b/config/config.sample.json @@ -0,0 +1,8 @@ +{ + "mqtt": { + "host": "127.0.0.1", + "port": "1883", + "username": "", + "password": "" + } +} diff --git a/package.json b/package.json index 2461453..3fd90e8 100755 --- a/package.json +++ b/package.json @@ -20,6 +20,7 @@ "body-parser": "^1.12.4", "local-itunes": "^0.3.0", "osa": "2.2.0", - "parameterize": "^0.0.7" + "parameterize": "^0.0.7", + "mqtt": "^1.4.1" } } diff --git a/script/bootstrap b/script/bootstrap index 53e9488..e67e469 100755 --- a/script/bootstrap +++ b/script/bootstrap @@ -20,4 +20,12 @@ mkdir -p log npm install +if [ ! -f config/config.json ] +then + echo + echo "==> Creating your config. Please edit config/config.json." + echo + cp config/config.sample.json config/config.json +fi + echo "Finished setting up itunes-api! run it with script/server or install it with script/install."