walkon 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: e98fa4a3f793072e126e54bb7885cc9ad4a11509
4
+ data.tar.gz: a613f716836c62e95d919db026bd3101395ffe62
5
+ SHA512:
6
+ metadata.gz: 94c888a21f894d3ec03066389834954bd53dc9da3bcff4b280e7d192b78a707a5a0066bbeb8d08adce83bd7305c4dfdb0b327c2a0c7fab3c121886767c1c00c5
7
+ data.tar.gz: 5b840b4c8e37048f83b8589ce8fc8d746737d182df1f05a6f866276bfba8a85dfdf446b8485359d35eece2b803eea504bda23009ad3ad4bd2e610ff76caa9bf5
@@ -0,0 +1,37 @@
1
+ # Walkon
2
+
3
+ Walkon plays your entrance music. It's a daemon process that
4
+ periodically checks `hcitool scan` for new Bluetooth devices, then uses
5
+ their ESSIDs to find tracks to play as they leave or exit the network.
6
+
7
+ ## Installation
8
+
9
+ Walkon is best used on a **Raspberry Pi** with **Ubuntu**.
10
+
11
+ Install it yourself:
12
+
13
+ $ gem install walkon
14
+
15
+ Then, run:
16
+
17
+ $ walkon setup
18
+
19
+ ## Usage
20
+
21
+ Place an MP3 in `/music` that corresponds with your device's ESSID.
22
+ So, if your device's name is "iPhone5", you would upload a track like
23
+ so:
24
+
25
+ $ scp your-track.mp3 walkon:/music/iPhone5.mp3
26
+
27
+ To find out more about how it works, read the [Documentation][docs].
28
+
29
+ ## Contributing
30
+
31
+ 1. Fork it
32
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
33
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
34
+ 4. Push to the branch (`git push origin my-new-feature`)
35
+ 5. Create new Pull Request
36
+
37
+ [docs]: http://rdoc.info/github/tubbo/walkon
@@ -0,0 +1,17 @@
1
+ require "bundler/gem_tasks"
2
+ require 'bundler/setup'
3
+ require 'rspec/core/rake_task'
4
+
5
+ RSpec::Core::RakeTask.new :test
6
+
7
+ desc "Provision a local development VM"
8
+ task :vm do
9
+ if `which vagrant` == ""
10
+ puts "Error: You must install Vagrant to use this feature."
11
+ exit 1
12
+ end
13
+
14
+ sh 'vagrant up'
15
+ end
16
+
17
+ task :default => %w(test build)
@@ -0,0 +1,11 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'bundler/setup'
4
+ require 'walkon'
5
+
6
+ unless Walkon.found_hcitool?
7
+ puts "Error: You need BlueZ to use this software. Exiting.."
8
+ exit 1
9
+ end
10
+
11
+ Walkon.start
@@ -0,0 +1,18 @@
1
+ require "walkon/version"
2
+ require "walkon/daemon"
3
+
4
+ module Walkon
5
+ def self.start
6
+ Walkon::Daemon.start
7
+ end
8
+
9
+ def self.found_hcitool?
10
+ !!`hcitool -h`
11
+ rescue Errno::ENOENT
12
+ false
13
+ end
14
+
15
+ def self.env
16
+ ENV['WALKON_ENV'] || 'development'
17
+ end
18
+ end
@@ -0,0 +1,46 @@
1
+ require 'walkon/device'
2
+ require 'walkon/hci_tool'
3
+
4
+ # The process which listens for new Devices to come on the network, then
5
+ # immediately plays their entrance music and adds them to the collection
6
+ # so they won't be triggered again.
7
+ #
8
+ # A cron job restarts the daemon every night at 3:00am so the devices
9
+ # collection is reset and people are triggered again once they walk in
10
+ # the building.
11
+
12
+ module Walkon
13
+ class Daemon
14
+ attr_accessor :devices
15
+
16
+ def initialize
17
+ @devices = []
18
+ end
19
+
20
+ def self.start
21
+ new.run
22
+ end
23
+
24
+ def run
25
+ loop { check_for_devices }
26
+ end
27
+
28
+ def check_for_devices
29
+ scanned_devices.each do |mac_address|
30
+ unless self.devices.include? mac_address
31
+ device = Device.new mac_address
32
+ play_entrance_music_for device
33
+ self.devices << Device.new(mac_address)
34
+ end
35
+ end
36
+ end
37
+
38
+ def scanned_devices
39
+ HciTool.scan
40
+ end
41
+
42
+ def play_entrance_music_for device
43
+ device.entrance_music.play if device.has_entrance_music?
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,18 @@
1
+ require 'walkon/entrance_music'
2
+
3
+ # Represents a single Bluetooth device in the building.
4
+
5
+ module Walkon
6
+ class Device
7
+ attr_reader :mac_address, :entrance_music
8
+
9
+ def initialize with_mac_address
10
+ @mac_address = with_mac_address
11
+ @entrance_music = EntranceMusic.new self
12
+ end
13
+
14
+ def has_entrance_music?
15
+ entrance_music.exists?
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,34 @@
1
+ require 'walkon/device'
2
+
3
+ # Finds and plays the entrance music for a given device.
4
+
5
+ module Walkon
6
+ class EntranceMusic
7
+ attr_reader :device, :filename
8
+
9
+ def initialize from_device
10
+ @device = from_device
11
+ @filename = "#{prefix}/#{@device.mac_address}.mp3"
12
+ end
13
+
14
+ def exists?
15
+ File.exists? filename
16
+ end
17
+
18
+ alias present? exists?
19
+
20
+ def play
21
+ return false unless exists?
22
+ `xmms #{filename}`
23
+ end
24
+
25
+ private
26
+ def prefix
27
+ if Walkon.env == 'test'
28
+ File.expand_path "../../../spec/fixtures/music", __FILE__
29
+ else
30
+ "/music"
31
+ end
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,31 @@
1
+ # A collection of device names gathered from HciTool.
2
+
3
+ module Walkon
4
+ class HciTool
5
+ attr_accessor :results
6
+
7
+ def initialize
8
+ @results = []
9
+ end
10
+
11
+ def self.scan
12
+ new.scan
13
+ end
14
+
15
+ def scan
16
+ @results = scan_results.reduce([]) do |collection, line|
17
+ line.scan FOR_MAC_ADDRESS do |mac_address|
18
+ collection << mac_address.first
19
+ end
20
+
21
+ collection
22
+ end
23
+ end
24
+
25
+ private
26
+ FOR_MAC_ADDRESS = /(..:..:..:..:..:..)/
27
+ def scan_results
28
+ `hcitool scan`.split "\n"
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,3 @@
1
+ module Walkon
2
+ VERSION = "0.0.1"
3
+ end
@@ -0,0 +1,7 @@
1
+ require 'bundler/setup'
2
+ require 'rspec'
3
+ require 'pry'
4
+
5
+ ENV['WALKON_ENV'] ||= "test"
6
+
7
+ require 'walkon'
@@ -0,0 +1,27 @@
1
+ require 'spec_helper'
2
+ require 'walkon/daemon'
3
+
4
+ module Walkon
5
+ describe Daemon do
6
+ context "when a new device is detected" do
7
+ let(:mac_address) { "00:A1:5D:AB:B2:E9" }
8
+
9
+ before do
10
+ subject.stub(:scanned_devices) { [mac_address] }
11
+ subject.stub(:play_entrance_music_for) { |device| true }
12
+ subject.check_for_devices
13
+ end
14
+
15
+ it "adds the sample mac address to devices" do
16
+ expect(subject.devices.map(&:mac_address)).to include(mac_address)
17
+ end
18
+
19
+ it "plays device's entrance music" do
20
+ expect(subject.devices).to_not be_empty
21
+ device = subject.devices.select { |dev| dev.mac_address == mac_address }.first
22
+ expect(device).to_not be_nil
23
+ expect(device).to have_entrance_music
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,16 @@
1
+ require 'spec_helper'
2
+ require 'walkon/device'
3
+
4
+ module Walkon
5
+ describe Device do
6
+ subject { Device.new '00:A1:5D:AB:B2:E9' }
7
+
8
+ it "requires a mac address for identification" do
9
+ expect(subject.mac_address).to_not be_nil
10
+ end
11
+
12
+ it "uses mac address to find entrance music in configured dir" do
13
+ expect(subject).to have_entrance_music
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,26 @@
1
+ require 'spec_helper'
2
+ require 'walkon/entrance_music'
3
+
4
+ module Walkon
5
+ describe EntranceMusic do
6
+ let(:mac_address) { "00:A1:5D:AB:B2:E9" }
7
+ let(:device) do
8
+ dev = double :device
9
+ dev.stub(:mac_address) { mac_address }
10
+ dev
11
+ end
12
+ subject { EntranceMusic.new device }
13
+
14
+ before do
15
+ subject.stub(:play) { "" }
16
+ end
17
+
18
+ it "finds an mp3 file to play" do
19
+ expect(subject).to be_present
20
+ end
21
+
22
+ it "plays the mp3 file if found" do
23
+ expect(subject.play).to be_true
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,26 @@
1
+ require 'spec_helper'
2
+
3
+ module Walkon
4
+ describe HciTool do
5
+ let(:mac_address) { "00:A1:5D:AB:B2:E9" }
6
+ let(:sample_output) do
7
+ %(
8
+ Scanning....
9
+ #{mac_address} Nokia 6600
10
+ ).split("\n")
11
+ end
12
+
13
+ before do
14
+ subject.stub(:scan_results) { sample_output }
15
+ end
16
+
17
+ it "starts with no results" do
18
+ expect(subject.results).to be_empty
19
+ end
20
+
21
+ it "finds mac addresses with a scan" do
22
+ expect(subject.scan).to_not be_empty
23
+ expect(subject.results.first).to eq(mac_address)
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,7 @@
1
+ require 'spec_helper'
2
+
3
+ describe Walkon do
4
+ it "runs a daemon for playing entrance music" do
5
+ expect(Walkon).to respond_to :start
6
+ end
7
+ end
metadata ADDED
@@ -0,0 +1,124 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: walkon
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Tom Scott
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2013-10-29 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ~>
18
+ - !ruby/object:Gem::Version
19
+ version: '1.3'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ~>
25
+ - !ruby/object:Gem::Version
26
+ version: '1.3'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - '>='
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - '>='
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: pry
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - '>='
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - '>='
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: rspec
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - '>='
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - '>='
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ description: Play your entrance music
70
+ email:
71
+ - tubbo@psychedeli.ca
72
+ executables:
73
+ - walkon
74
+ extensions: []
75
+ extra_rdoc_files: []
76
+ files:
77
+ - bin/walkon
78
+ - lib/walkon/daemon.rb
79
+ - lib/walkon/device.rb
80
+ - lib/walkon/entrance_music.rb
81
+ - lib/walkon/hci_tool.rb
82
+ - lib/walkon/version.rb
83
+ - lib/walkon.rb
84
+ - spec/fixtures/music/00:A1:5D:AB:B2:E9.mp3
85
+ - spec/spec_helper.rb
86
+ - spec/walkon/daemon_spec.rb
87
+ - spec/walkon/device_spec.rb
88
+ - spec/walkon/entrance_music_spec.rb
89
+ - spec/walkon/hci_tool_spec.rb
90
+ - spec/walkon_spec.rb
91
+ - README.md
92
+ - Rakefile
93
+ homepage: http://github.com/tubbo/walkon
94
+ licenses:
95
+ - MIT
96
+ metadata: {}
97
+ post_install_message:
98
+ rdoc_options: []
99
+ require_paths:
100
+ - lib
101
+ required_ruby_version: !ruby/object:Gem::Requirement
102
+ requirements:
103
+ - - '>='
104
+ - !ruby/object:Gem::Version
105
+ version: '0'
106
+ required_rubygems_version: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - '>='
109
+ - !ruby/object:Gem::Version
110
+ version: '0'
111
+ requirements: []
112
+ rubyforge_project:
113
+ rubygems_version: 2.0.3
114
+ signing_key:
115
+ specification_version: 4
116
+ summary: Play your entrance music
117
+ test_files:
118
+ - spec/fixtures/music/00:A1:5D:AB:B2:E9.mp3
119
+ - spec/spec_helper.rb
120
+ - spec/walkon/daemon_spec.rb
121
+ - spec/walkon/device_spec.rb
122
+ - spec/walkon/entrance_music_spec.rb
123
+ - spec/walkon/hci_tool_spec.rb
124
+ - spec/walkon_spec.rb