rfid 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
+
});
|