From 0ff369c53d20f476d04cdaa13b88c35c363a8dd5 Mon Sep 17 00:00:00 2001 From: Annika Backstrom Date: Sun, 20 Nov 2016 01:13:19 +0000 Subject: [PATCH] Replace python player with node.js player --- .gitignore | 2 + package.json | 24 +++++++++++ player.js | 79 ++++++++++++++++++++++++++++++++++ player.py | 58 ------------------------- run-tag-reader | 3 ++ source/stylesheets/index.styl | 56 ++++++++++++++++++++++++ source/templates/default.jade | 20 +++++++++ source/templates/homepage.jade | 5 +++ static/css/index.css | 56 ++++++++++++++++++++++++ tag-reader.py | 19 ++++++++ 10 files changed, 264 insertions(+), 58 deletions(-) create mode 100644 .gitignore create mode 100644 package.json create mode 100644 player.js delete mode 100644 player.py create mode 100755 run-tag-reader create mode 100644 source/stylesheets/index.styl create mode 100644 source/templates/default.jade create mode 100644 source/templates/homepage.jade create mode 100644 static/css/index.css create mode 100644 tag-reader.py diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..491fc35 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +node_modules +lib diff --git a/package.json b/package.json new file mode 100644 index 0000000..ceccd89 --- /dev/null +++ b/package.json @@ -0,0 +1,24 @@ +{ + "name": "rfid", + "version": "1.0.0", + "description": "", + "main": "player.js", + "scripts": { + "build-css": "stylus source/stylesheets/index.styl -o static/css", + "watch-css": "stylus source/stylesheets/index.styl -o static/css -w", + "clean": "rm -rf static/css && mkdir -p static/css", + "build": "npm run clean && npm run build-css", + "watch": "npm run clean && npm run watch-css & nodemon player -e js,jade", + "start": "node player" + }, + "author": "", + "license": "ISC", + "dependencies": { + "express": "^4.14.0", + "glob": "^7.1.1", + "jade": "^1.11.0", + "morgan": "^1.7.0", + "nodemon": "^1.9.2", + "stylus": "^0.54.5" + } +} diff --git a/player.js b/player.js new file mode 100644 index 0000000..145f902 --- /dev/null +++ b/player.js @@ -0,0 +1,79 @@ +const glob = require('glob'); +const spawn = require('child_process').spawn; +const tag_reader = spawn('/home/annika/rfid/run-tag-reader'); +const player = spawn('/usr/bin/sudo', ['-n', '/usr/bin/mpg321', '-R', '-']); + +tag_reader.on('error', function(err) { + console.log(`[tag_reader:error] ${err}`); +}); + +player.on('error', function(err) { + console.log(`[player:error] ${err}`); +}); + +// player.stdin.write("GAIN 100"); + +last_tag = null; +debounce_until = 0; + +function lookup(tag, cb) { + if (tag === 'b9506555d9') { + return cb('STOP'); + } + if (tag === 'aa89665510') { + return cb('PAUSE', 2); + } + glob('media/' + tag + ' - *.mp3', function(er, files) { + if (files.length > 0) { + return cb("LOAD " + files[0], 5); + } + }); +} + +tag_reader.stdout.on('data', (data) => { + if (Date.now() / 1000 < debounce_until) { + return; + } + last_tag = String(data).trim(); + console.log("Tag: " + last_tag); + lookup(last_tag, function(action, wait_sec) { + wait_sec = wait_sec || 1; + if (action) { + debounce_until = Date.now() / 1000 + wait_sec; + console.log(`Running ${action} for ${last_tag}`); + player.stdin.write(action + "\n"); + } + }); +}); + +tag_reader.stderr.on('data', (data) => { + console.log(`[tag_reader:stderr] ${data}`); +}); + +player.stderr.on('data', (data) => { + if (String(data).substr(0, 3) === "@F ") { + return; + } + console.log(`[player:stderr] ${data}`); +}); + +var express = require('express') + , logger = require('morgan') + , app = express() + , template = require('jade').compileFile(__dirname + '/source/templates/homepage.jade') + +app.use(logger('dev')) +app.use(express.static(__dirname + '/static')) + +app.get('/', function (req, res, next) { + try { + var html = template({ title: 'Home', last_tag: last_tag }) + res.send(html) + } catch (e) { + next(e) + } +}) + +app.listen(process.env.PORT || 80, function () { + console.log('Listening on http://localhost:' + (process.env.PORT || 80)) +}) diff --git a/player.py b/player.py deleted file mode 100644 index 374b9e6..0000000 --- a/player.py +++ /dev/null @@ -1,58 +0,0 @@ -from pirc522 import RFID -from glob import glob - -import atexit -import os -import time -import signal -import subprocess -import vlc - -rdr = RFID() -util = rdr.util() - -last_seen = None -seen_at = 0 -p = None - -RETRY_TIME = 2 - -#player = subprocess.Popen(["mpg321", "-R", "-"], stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE) -player = subprocess.Popen(["mpg321", "-R", "-"], stdin=subprocess.PIPE) -player.stdin.write("GAIN 100") - -try: - while True: - (error, tag_type) = rdr.request() - if not error: - (error, uid) = rdr.anticoll() - if not error: - tag_id = ''.join(hex(x)[2:].zfill(2) for x in uid) - print("Tag: " + tag_id) - - if tag_id == 'b9506555d9': - print("Stopping playback.") - player.stdin.write("STOP\n") - continue - - if time.time() > (seen_at + RETRY_TIME): - last_seen = uid - seen_at = time.time() - - if tag_id == 'aa89665510': - print("Toggling pause.") - player.stdin.write("PAUSE\n") - continue - - file = glob("media/" + tag_id + " - *.mp3") - if file: - print("Playing file " + file[0]) - player.stdin.write("STOP\n") - player.stdin.write("LOAD " + file[0] + "\n") - - continue -except (KeyboardInterrupt, SystemExit): - os.kill(player.pid, signal.SIGTERM) - -# Calls GPIO cleanup -rdr.cleanup() diff --git a/run-tag-reader b/run-tag-reader new file mode 100755 index 0000000..aa614c8 --- /dev/null +++ b/run-tag-reader @@ -0,0 +1,3 @@ +#!/bin/bash + +sudo -n /home/annika/rfid/lib/bin/python tag-reader.py diff --git a/source/stylesheets/index.styl b/source/stylesheets/index.styl new file mode 100644 index 0000000..e1dcb69 --- /dev/null +++ b/source/stylesheets/index.styl @@ -0,0 +1,56 @@ +@import url('https://fonts.googleapis.com/css?family=Source+Code+Pro:400,200,700') + +* + margin 0 + padding 0 + box-sizing border-box + +body + font-family 'Source Code Pro', monospace + +.header + background url('https://images.unsplash.com/photo-1451337516015-6b6e9a44a8a3?crop=entropy&fit=crop&fm=jpg&h=975&ixjsv=2.1.0&ixlib=rb-0.3.5&q=80&w=1925') + background-position center + + .page-title + font-weight 200 + font-size 80px + text-align center + padding 100px + text-transform uppercase + color #fff + +.nav + background #000 + text-align center + + li + display inline-block + + a + display inline-block + padding 20px + color #fff + text-decoration none + + &:hover + background-color #3AB795 + text-decoration underline + +.main-content + margin 50px auto + max-width 600px + + p + line-height 1.6 + margin-bottom 1.7em + +.footer + margin 50px auto + max-width 600px + border-top 1px solid #444 + padding 20px 0 + + p + color #444 + font-size 12px diff --git a/source/templates/default.jade b/source/templates/default.jade new file mode 100644 index 0000000..38902c5 --- /dev/null +++ b/source/templates/default.jade @@ -0,0 +1,20 @@ +doctype html +html + head + link(rel='stylesheet', href='/css/index.css') + title World Wide Web + body + .header + h1.page-title World Wide Web + + ul.nav + li: a(href='/') Home + li: a(href='#news') News + li: a(href='#about') About + li: a(href='#contact') Contact + + .main-content + block content + + .footer + p Copyright © 2020 Futurecorpz. Futurecorpz ® is a Registered Trademark of Futures (un)Ltd. in the Mars Community and other solar systems. diff --git a/source/templates/homepage.jade b/source/templates/homepage.jade new file mode 100644 index 0000000..faada56 --- /dev/null +++ b/source/templates/homepage.jade @@ -0,0 +1,5 @@ +extend default + +block content + p. + Last tag seen: #{last_tag} diff --git a/static/css/index.css b/static/css/index.css new file mode 100644 index 0000000..2b0b36c --- /dev/null +++ b/static/css/index.css @@ -0,0 +1,56 @@ +@import url("https://fonts.googleapis.com/css?family=Source+Code+Pro:400,200,700"); +* { + margin: 0; + padding: 0; + box-sizing: border-box; +} +body { + font-family: 'Source Code Pro', monospace; +} +.header { + background: url("https://images.unsplash.com/photo-1451337516015-6b6e9a44a8a3?crop=entropy&fit=crop&fm=jpg&h=975&ixjsv=2.1.0&ixlib=rb-0.3.5&q=80&w=1925"); + background-position: center; +} +.header .page-title { + font-weight: 200; + font-size: 80px; + text-align: center; + padding: 100px; + text-transform: uppercase; + color: #fff; +} +.nav { + background: #000; + text-align: center; +} +.nav li { + display: inline-block; +} +.nav a { + display: inline-block; + padding: 20px; + color: #fff; + text-decoration: none; +} +.nav a:hover { + background-color: #3ab795; + text-decoration: underline; +} +.main-content { + margin: 50px auto; + max-width: 600px; +} +.main-content p { + line-height: 1.6; + margin-bottom: 1.7em; +} +.footer { + margin: 50px auto; + max-width: 600px; + border-top: 1px solid #444; + padding: 20px 0; +} +.footer p { + color: #444; + font-size: 12px; +} diff --git a/tag-reader.py b/tag-reader.py new file mode 100644 index 0000000..74d6dbc --- /dev/null +++ b/tag-reader.py @@ -0,0 +1,19 @@ +from pirc522 import RFID + +import RPi.GPIO as GPIO +import sys + +GPIO.setwarnings(False) + +rdr = RFID() + +while True: + (error, tag_type) = rdr.request() + if not error: + (error, uid) = rdr.anticoll() + if not error: + tag_id = ''.join(hex(x)[2:].zfill(2) for x in uid) + print(tag_id) + sys.stdout.flush() + +rdr.cleanup()