rfid 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.
- data/INSTALL.rdoc +55 -0
- data/README.rdoc +60 -0
- data/bin/rfid +18 -0
- data/bin/rfid_checkout +22 -0
- data/config.ru +9 -0
- data/config/boot.rb +6 -0
- data/config/environment.rb +8 -0
- data/config/rfid.yml +6 -0
- data/config/rfid.yml.sample +6 -0
- data/config/thin.yml +14 -0
- data/config/thin.yml.sample +14 -0
- data/lib/rfid.rb +75 -0
- data/lib/rfid/application.rb +115 -0
- data/lib/rfid/application/public/favicon.ico +0 -0
- data/lib/rfid/application/public/javascripts/application.js +12 -0
- data/lib/rfid/application/public/javascripts/debug.js +59 -0
- data/lib/rfid/application/public/stylesheets/application.css +49 -0
- data/lib/rfid/application/public/stylesheets/bootstrap.css +2467 -0
- data/lib/rfid/application/views/events.erb +34 -0
- data/lib/rfid/application/views/index.erb +21 -0
- data/lib/rfid/application/views/key_sets.erb +13 -0
- data/lib/rfid/application/views/key_string.erb +11 -0
- data/lib/rfid/application/views/keys.erb +20 -0
- data/lib/rfid/application/views/layout.erb +56 -0
- data/lib/rfid/application/views/redis.erb +16 -0
- data/lib/rfid/application/views/usage.erb +47 -0
- data/lib/rfid/cli.rb +78 -0
- data/lib/rfid/config.rb +23 -0
- data/lib/rfid/core_ext.rb +3 -0
- data/lib/rfid/core_ext/json_engine.rb +2 -0
- data/lib/rfid/event.rb +101 -0
- data/lib/rfid/translator.rb +68 -0
- data/lib/rfid/version.rb +3 -0
- data/lib/rfid/websocket.rb +35 -0
- data/lib/runner.rb +18 -0
- data/lib/server.rb +19 -0
- data/lib/templates/init +109 -0
- data/spec/models/application_spec.rb +54 -0
- data/spec/models/config_spec.rb +33 -0
- data/spec/models/event_spec.rb +22 -0
- data/spec/rfid_spec.rb +58 -0
- data/spec/spec_helper.rb +25 -0
- metadata +228 -0
data/INSTALL.rdoc
ADDED
@@ -0,0 +1,55 @@
|
|
1
|
+
== RFID install instructions
|
2
|
+
|
3
|
+
== Ruby 1.9.3
|
4
|
+
|
5
|
+
http://www.andyhawthorne.co.uk/2011/11/installing-ruby-1-9-3-and-rails-on-ubuntu-11-10/
|
6
|
+
|
7
|
+
sudo apt-get install build-essential git-core curl
|
8
|
+
|
9
|
+
sudo apt-get install build-essential openssl libreadline6 libreadline6-dev curl git-core zlib1g zlib1g-dev libssl-dev libyaml-dev libxml2-dev libxslt-dev autoconf libc6-dev ncurses-dev automake libtool bison subversion
|
10
|
+
|
11
|
+
Install yaml:
|
12
|
+
|
13
|
+
#get the source
|
14
|
+
wget http://pyyaml.org/download/libyaml/yaml-0.1.4.tar.gz
|
15
|
+
|
16
|
+
#untar the file
|
17
|
+
tar xzvf yaml-0.1.4.tar.gz
|
18
|
+
|
19
|
+
#move into the directory
|
20
|
+
cd yaml-0.1.4
|
21
|
+
|
22
|
+
#compile
|
23
|
+
./configure --prefix=/usr/local
|
24
|
+
make
|
25
|
+
sudo make install
|
26
|
+
|
27
|
+
|
28
|
+
Make and install ruby:
|
29
|
+
|
30
|
+
#download the Ruby source
|
31
|
+
wget http://ftp.ruby-lang.org/pub/ruby/1.9/ruby-1.9.3-p0.tar.gz
|
32
|
+
|
33
|
+
#untar the file
|
34
|
+
tar xzvf ruby-1.9.3-p0.tar.gz
|
35
|
+
|
36
|
+
#move into the source directory
|
37
|
+
cd ruby-1.9.3-p0
|
38
|
+
|
39
|
+
#configure with options to avoid errors
|
40
|
+
./configure --prefix=/usr/local --enable-shared --disable-install-doc --with-opt-dir=/usr/local/lib
|
41
|
+
|
42
|
+
#compile
|
43
|
+
make
|
44
|
+
sudo make install
|
45
|
+
|
46
|
+
|
47
|
+
== Redis 2.4.2
|
48
|
+
|
49
|
+
TODO:
|
50
|
+
|
51
|
+
== Curl
|
52
|
+
|
53
|
+
sudo apt-get install libcurl3 libcurl3-gnutls libcurl4-openssl-dev
|
54
|
+
|
55
|
+
Copyright (c) 2011 Aimbulance, released under the MIT license
|
data/README.rdoc
ADDED
@@ -0,0 +1,60 @@
|
|
1
|
+
= RFID WebSocket
|
2
|
+
|
3
|
+
== Setup
|
4
|
+
|
5
|
+
Install gem:
|
6
|
+
|
7
|
+
gem install rfid
|
8
|
+
|
9
|
+
Create logs and pids folders
|
10
|
+
|
11
|
+
rfid setup
|
12
|
+
|
13
|
+
sudo /usr/sbin/update-rc.d -f rfid defaults
|
14
|
+
|
15
|
+
== Start
|
16
|
+
|
17
|
+
Run websocket:
|
18
|
+
|
19
|
+
rfid websocket start
|
20
|
+
|
21
|
+
Run webui (optional):
|
22
|
+
|
23
|
+
rfid app start
|
24
|
+
|
25
|
+
== Usage
|
26
|
+
|
27
|
+
Create event
|
28
|
+
|
29
|
+
rfid checkout DEVICE_ID CARD1 CARD2 ...
|
30
|
+
|
31
|
+
rfid checkout 4ea92ba9c546617ab8000001 715=9370462=000195
|
32
|
+
|
33
|
+
== Usage (development)
|
34
|
+
|
35
|
+
=== WebSocket
|
36
|
+
|
37
|
+
ruby runner.rb start
|
38
|
+
ruby runner.rb restart
|
39
|
+
ruby runner.rb stop
|
40
|
+
|
41
|
+
For testing
|
42
|
+
|
43
|
+
ruby runner.rb run
|
44
|
+
|
45
|
+
=== Sinatra
|
46
|
+
|
47
|
+
Start thin server
|
48
|
+
|
49
|
+
bundle exec thin --rackup config.ru start
|
50
|
+
|
51
|
+
bundle exec thin start -R config.ru -C config/thin.yml
|
52
|
+
|
53
|
+
== Platform
|
54
|
+
|
55
|
+
Ruby 1.9.3-p0
|
56
|
+
Redis 2.4.2
|
57
|
+
Libcurl (Ubuntu: sudo apt-get install libcurl3 libcurl3-gnutls libcurl4-openssl-dev)
|
58
|
+
Browser with websockets enabled
|
59
|
+
|
60
|
+
Copyright (c) 2011 Aimbulance, released under the MIT license
|
data/bin/rfid
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
require 'rfid'
|
3
|
+
|
4
|
+
begin
|
5
|
+
require 'rfid/cli'
|
6
|
+
Rfid::CLI.start
|
7
|
+
rescue Interrupt => e
|
8
|
+
puts "\nQuitting..."
|
9
|
+
puts e.backtrace.join("\n")
|
10
|
+
exit 1
|
11
|
+
rescue SystemExit => e
|
12
|
+
exit e.status
|
13
|
+
rescue Exception => e
|
14
|
+
puts "Unfortunately, a fatal error has occurred. " +
|
15
|
+
"Please report this error to the Rfid issue tracker at " +
|
16
|
+
"https://aimbulance.lighthouseapp.com so that we can fix it. Thanks!"
|
17
|
+
raise e
|
18
|
+
end
|
data/bin/rfid_checkout
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
require 'rfid'
|
3
|
+
|
4
|
+
begin
|
5
|
+
require 'rfid/cli'
|
6
|
+
|
7
|
+
script = Rfid::CLI.new(ARGV)
|
8
|
+
script.invoke(:checkout)
|
9
|
+
rescue Thor::Error => e
|
10
|
+
puts e.message
|
11
|
+
rescue Interrupt => e
|
12
|
+
puts "\nQuitting..."
|
13
|
+
puts e.backtrace.join("\n")
|
14
|
+
exit 1
|
15
|
+
rescue SystemExit => e
|
16
|
+
exit e.status
|
17
|
+
rescue Exception => e
|
18
|
+
puts "Unfortunately, a fatal error has occurred. " +
|
19
|
+
"Please report this error to the Rfid issue tracker at " +
|
20
|
+
"https://aimbulance.lighthouseapp.com so that we can fix it. Thanks!"
|
21
|
+
raise e
|
22
|
+
end
|
data/config.ru
ADDED
data/config/boot.rb
ADDED
@@ -0,0 +1,8 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
$:.push File.expand_path("../../lib", __FILE__)
|
3
|
+
|
4
|
+
require 'rubygems'
|
5
|
+
|
6
|
+
# If you have a Gemfile, require the gems listed there, including any gems
|
7
|
+
# you've limited to :test, :development, or :production.
|
8
|
+
Bundler.require(:default, :development) if defined?(Bundler)
|
data/config/rfid.yml
ADDED
data/config/thin.yml
ADDED
data/lib/rfid.rb
ADDED
@@ -0,0 +1,75 @@
|
|
1
|
+
require 'active_support/core_ext'
|
2
|
+
require 'redis/connection/hiredis'
|
3
|
+
require 'redis'
|
4
|
+
require 'logger'
|
5
|
+
require 'uri'
|
6
|
+
require 'rfid/core_ext'
|
7
|
+
|
8
|
+
module Rfid
|
9
|
+
autoload :Application, 'rfid/application'
|
10
|
+
autoload :Translator, 'rfid/translator'
|
11
|
+
autoload :WebSocket, 'rfid/websocket'
|
12
|
+
autoload :Config, 'rfid/config'
|
13
|
+
autoload :Event, 'rfid/event'
|
14
|
+
|
15
|
+
extend self
|
16
|
+
|
17
|
+
def config
|
18
|
+
@config ||= Config.new(config_path)
|
19
|
+
end
|
20
|
+
|
21
|
+
def config_path
|
22
|
+
@config_path ||= File.expand_path("../../config/rfid.yml", __FILE__)
|
23
|
+
end
|
24
|
+
|
25
|
+
def redis
|
26
|
+
@redis ||= Redis.new(self.redis_options)
|
27
|
+
end
|
28
|
+
|
29
|
+
def redis_options
|
30
|
+
url = URI(self.config.redis_url)
|
31
|
+
db = (url.path[1..-1] || 10).to_i
|
32
|
+
{ :host => url.host, :port => url.port, :db => db, :password => url.password }
|
33
|
+
end
|
34
|
+
|
35
|
+
def redis_id
|
36
|
+
# support 1.x versions of redis-rb
|
37
|
+
if redis.respond_to?(:server)
|
38
|
+
redis.server
|
39
|
+
elsif redis.respond_to?(:nodes) # distributed
|
40
|
+
redis.nodes.map { |n| n.id }.join(', ')
|
41
|
+
else
|
42
|
+
redis.client.id
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
def push_event(event)
|
47
|
+
log("Redis push event", event.inspect)
|
48
|
+
redis.rpush(self.config.redis_key, event.to_json)
|
49
|
+
end
|
50
|
+
|
51
|
+
# Returns an array of all known Resque keys in Redis. Redis' KEYS operation
|
52
|
+
# is O(N) for the keyspace, so be careful - this can be slow for big databases.
|
53
|
+
def keys
|
54
|
+
redis.keys("*")
|
55
|
+
end
|
56
|
+
|
57
|
+
def logger
|
58
|
+
@logger ||= create_logger(self.config.log_path)
|
59
|
+
end
|
60
|
+
|
61
|
+
def log(*args)
|
62
|
+
timestamp = "[#{Time.now.strftime('%d.%m.%Y %H:%M')}]"
|
63
|
+
logger.info([timestamp, args.compact].flatten.join(' '))
|
64
|
+
end
|
65
|
+
|
66
|
+
protected
|
67
|
+
|
68
|
+
def create_logger(filepath)
|
69
|
+
logfile = File.open(filepath, 'a')
|
70
|
+
logfile.sync = true
|
71
|
+
Logger.new(logfile)
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
require 'rfid/version'
|
@@ -0,0 +1,115 @@
|
|
1
|
+
require 'pathname'
|
2
|
+
require 'sinatra'
|
3
|
+
|
4
|
+
module Rfid
|
5
|
+
class Application < Sinatra::Base
|
6
|
+
configure do
|
7
|
+
root_path = File.join(File.dirname(__FILE__), 'application')
|
8
|
+
|
9
|
+
enable :logging
|
10
|
+
|
11
|
+
set :environment, (ENV['RACK_ENV'] || :production)
|
12
|
+
set :root_path, Pathname.new(root_path)
|
13
|
+
set :public_folder, File.join(root_path, 'public')
|
14
|
+
set :views, File.join(root_path, 'views')
|
15
|
+
set :static, true
|
16
|
+
set :run, false
|
17
|
+
end
|
18
|
+
|
19
|
+
helpers do
|
20
|
+
def json_data(data)
|
21
|
+
status 200
|
22
|
+
content_type "application/json"
|
23
|
+
{:response => data}.to_json
|
24
|
+
end
|
25
|
+
|
26
|
+
def current_page
|
27
|
+
url_path request.path_info.sub('/','')
|
28
|
+
end
|
29
|
+
|
30
|
+
def url_path(*path_parts)
|
31
|
+
[ path_prefix, path_parts ].join("/").squeeze('/')
|
32
|
+
end
|
33
|
+
alias_method :u, :url_path
|
34
|
+
|
35
|
+
def path_prefix
|
36
|
+
request.env['SCRIPT_NAME']
|
37
|
+
end
|
38
|
+
|
39
|
+
def class_if_current(path = '')
|
40
|
+
'class="active"' if current_page[0, path.size] == path
|
41
|
+
end
|
42
|
+
|
43
|
+
def tab(name)
|
44
|
+
dname = name.to_s.downcase
|
45
|
+
path = url_path(dname)
|
46
|
+
"<li #{class_if_current(path)}><a href='#{path}'>#{name}</a></li>"
|
47
|
+
end
|
48
|
+
|
49
|
+
def redis_get_size(key)
|
50
|
+
case Rfid.redis.type(key)
|
51
|
+
when 'none'
|
52
|
+
[]
|
53
|
+
when 'list'
|
54
|
+
Rfid.redis.llen(key)
|
55
|
+
when 'set'
|
56
|
+
Rfid.redis.scard(key)
|
57
|
+
when 'string'
|
58
|
+
Rfid.redis.get(key).length
|
59
|
+
when 'zset'
|
60
|
+
Rfid.redis.zcard(key)
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
def redis_get_value_as_array(key, start = 0)
|
65
|
+
case Rfid.redis.type(key)
|
66
|
+
when 'none'
|
67
|
+
[]
|
68
|
+
when 'list'
|
69
|
+
Rfid.redis.lrange(key, start, start + 200)
|
70
|
+
when 'set'
|
71
|
+
Rfid.redis.smembers(key)[start..(start + 200)]
|
72
|
+
when 'string'
|
73
|
+
[Rfid.redis.get(key)]
|
74
|
+
when 'zset'
|
75
|
+
Rfid.redis.zrange(key, start, start + 200)
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
get '/' do
|
81
|
+
erb :index
|
82
|
+
end
|
83
|
+
|
84
|
+
get '/redis' do
|
85
|
+
erb :redis, {:layout => true}, :rfid => Rfid
|
86
|
+
end
|
87
|
+
|
88
|
+
get '/keys' do
|
89
|
+
erb :keys, {:layout => true}, :rfid => Rfid
|
90
|
+
end
|
91
|
+
|
92
|
+
get '/keys/:key' do
|
93
|
+
@key = params[:key].to_s
|
94
|
+
partial = Rfid.redis.type(@key).eql?("string") ? :key_string : :key_sets
|
95
|
+
erb partial, {:layout => true}, :rfid => Rfid
|
96
|
+
end
|
97
|
+
|
98
|
+
get '/usage' do
|
99
|
+
erb :usage
|
100
|
+
end
|
101
|
+
|
102
|
+
get '/events' do
|
103
|
+
erb :events
|
104
|
+
end
|
105
|
+
|
106
|
+
post '/events.?:format?' do
|
107
|
+
Rfid.push_event(params[:event])
|
108
|
+
|
109
|
+
case params[:format]
|
110
|
+
when 'json' then json_data(params[:event])
|
111
|
+
else redirect "/events?state=success"
|
112
|
+
end
|
113
|
+
end
|
114
|
+
end
|
115
|
+
end
|
File without changes
|
@@ -0,0 +1,12 @@
|
|
1
|
+
function jsload(id, source){
|
2
|
+
var d = document;
|
3
|
+
var s = 'script';
|
4
|
+
var js, fjs = d.getElementsByTagName(s)[0];
|
5
|
+
|
6
|
+
if (d.getElementById(id)) {return;}
|
7
|
+
js = d.createElement(s);
|
8
|
+
js.id = id;
|
9
|
+
js.src = source;
|
10
|
+
|
11
|
+
fjs.parentNode.insertBefore(js, fjs);
|
12
|
+
}
|
@@ -0,0 +1,59 @@
|
|
1
|
+
function escapeHTML(value) {
|
2
|
+
return value.replace(/&/g,'&').replace(/</g,'<').replace(/>/g,'>');
|
3
|
+
}
|
4
|
+
|
5
|
+
$(document).ready(function(){
|
6
|
+
var debug_console = $('#debug_console');
|
7
|
+
var debug_console_tbody = $('tbody', debug_console);
|
8
|
+
var channel = new FancyWebSocket("ws://127.0.0.1:8080", { debug: true });
|
9
|
+
|
10
|
+
function debug(log){
|
11
|
+
var logCss = {
|
12
|
+
'socket_opened': 'notice',
|
13
|
+
'socket_closed': 'default',
|
14
|
+
'channel_occupied': 'Occupied',
|
15
|
+
'channel_vacated': 'Vacated',
|
16
|
+
'channel_subscribed': 'notice',
|
17
|
+
'channel_unsubscribed': 'default',
|
18
|
+
'api_message': 'success',
|
19
|
+
'client_message': 'success',
|
20
|
+
'presence_message': 'success',
|
21
|
+
'error': 'important',
|
22
|
+
'api_error': 'important',
|
23
|
+
'client_error': 'important',
|
24
|
+
'pipe_incoming_message': 'warning',
|
25
|
+
'wsapi_message': 'warning'
|
26
|
+
};
|
27
|
+
|
28
|
+
var row = $('<tr>');
|
29
|
+
var logType = '<span class="label ' + logCss[log.type] + '">' + log.type + '</span>';
|
30
|
+
var message = log.message;
|
31
|
+
|
32
|
+
row.append('<td class="debug_type">' + logType + '</td>')
|
33
|
+
.append('<td class="debug_socket_id">' + (log.socket_id || '') + '</td>')
|
34
|
+
.append('<td class="debug_message">' + escapeHTML(message) + '</td>')
|
35
|
+
.append('<td class="debug_time">' + log.date + '</td>');
|
36
|
+
|
37
|
+
if (log.data) {
|
38
|
+
var string_data = log.data;
|
39
|
+
|
40
|
+
try {
|
41
|
+
string_data = JSON.stringify(JSON.parse(log.data), null, ' ');
|
42
|
+
} catch(e) {}
|
43
|
+
|
44
|
+
row.find('td.debug_message').append( $('<pre>').text(string_data) );
|
45
|
+
}
|
46
|
+
|
47
|
+
debug_console_tbody.append(row);
|
48
|
+
}
|
49
|
+
|
50
|
+
channel.bind('log_message', function(log){
|
51
|
+
debug(log);
|
52
|
+
});
|
53
|
+
|
54
|
+
channel.bind('error', function(data){
|
55
|
+
var date = new Date();
|
56
|
+
var time = date.getHours() + ":" + date.getMinutes() + ":" + date.getSeconds();
|
57
|
+
debug({type: 'error', socket_id: null, message: 'Error', date: time.format("d.m.Y H:i:s"), data: JSON.stringify(data) });
|
58
|
+
});
|
59
|
+
});
|