rfid 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (43) hide show
  1. data/INSTALL.rdoc +55 -0
  2. data/README.rdoc +60 -0
  3. data/bin/rfid +18 -0
  4. data/bin/rfid_checkout +22 -0
  5. data/config.ru +9 -0
  6. data/config/boot.rb +6 -0
  7. data/config/environment.rb +8 -0
  8. data/config/rfid.yml +6 -0
  9. data/config/rfid.yml.sample +6 -0
  10. data/config/thin.yml +14 -0
  11. data/config/thin.yml.sample +14 -0
  12. data/lib/rfid.rb +75 -0
  13. data/lib/rfid/application.rb +115 -0
  14. data/lib/rfid/application/public/favicon.ico +0 -0
  15. data/lib/rfid/application/public/javascripts/application.js +12 -0
  16. data/lib/rfid/application/public/javascripts/debug.js +59 -0
  17. data/lib/rfid/application/public/stylesheets/application.css +49 -0
  18. data/lib/rfid/application/public/stylesheets/bootstrap.css +2467 -0
  19. data/lib/rfid/application/views/events.erb +34 -0
  20. data/lib/rfid/application/views/index.erb +21 -0
  21. data/lib/rfid/application/views/key_sets.erb +13 -0
  22. data/lib/rfid/application/views/key_string.erb +11 -0
  23. data/lib/rfid/application/views/keys.erb +20 -0
  24. data/lib/rfid/application/views/layout.erb +56 -0
  25. data/lib/rfid/application/views/redis.erb +16 -0
  26. data/lib/rfid/application/views/usage.erb +47 -0
  27. data/lib/rfid/cli.rb +78 -0
  28. data/lib/rfid/config.rb +23 -0
  29. data/lib/rfid/core_ext.rb +3 -0
  30. data/lib/rfid/core_ext/json_engine.rb +2 -0
  31. data/lib/rfid/event.rb +101 -0
  32. data/lib/rfid/translator.rb +68 -0
  33. data/lib/rfid/version.rb +3 -0
  34. data/lib/rfid/websocket.rb +35 -0
  35. data/lib/runner.rb +18 -0
  36. data/lib/server.rb +19 -0
  37. data/lib/templates/init +109 -0
  38. data/spec/models/application_spec.rb +54 -0
  39. data/spec/models/config_spec.rb +33 -0
  40. data/spec/models/event_spec.rb +22 -0
  41. data/spec/rfid_spec.rb +58 -0
  42. data/spec/spec_helper.rb +25 -0
  43. metadata +228 -0
@@ -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
@@ -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
@@ -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
@@ -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
@@ -0,0 +1,9 @@
1
+ require ::File.expand_path('../config/environment', __FILE__)
2
+ require "rack/contrib"
3
+ require "rfid"
4
+
5
+ use Rack::CommonLogger
6
+ use Rack::ShowExceptions
7
+ use Rack::Access, '/' => [ '127.0.0.1' ]
8
+
9
+ run Rfid::Application
@@ -0,0 +1,6 @@
1
+ require 'rubygems'
2
+
3
+ # Set up gems listed in the Gemfile.
4
+ ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile', __FILE__)
5
+
6
+ require 'bundler/setup' if File.exists?(ENV['BUNDLE_GEMFILE'])
@@ -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)
@@ -0,0 +1,6 @@
1
+ redis_url: "redis://127.0.0.1:6379/10"
2
+ redis_key: "rfid_events"
3
+ log_path: "/var/log/rfid.log"
4
+ api_url: "https://rfidapi.aimbulance.com/api/v1"
5
+ device_id: "test"
6
+ device_token: "test"
@@ -0,0 +1,6 @@
1
+ redis_url: "redis://127.0.0.1:6379/10"
2
+ redis_key: "rfid_events"
3
+ log_path: "/var/log/rfid.log"
4
+ api_url: "https://rfidapi.aimbulance.com/api/v1"
5
+ device_id: "test"
6
+ device_token: "test"
@@ -0,0 +1,14 @@
1
+ ---
2
+ address: 127.0.0.1
3
+ pid: /var/run/rfid_thin.pid
4
+ port: 5000
5
+ wait: 10
6
+ timeout: 60
7
+ log: /var/log/rfid_thin.log
8
+ max_conns: 1024
9
+ require: []
10
+
11
+ environment: production
12
+ max_persistent_conns: 512
13
+ daemonize: true
14
+ servers: 1
@@ -0,0 +1,14 @@
1
+ ---
2
+ address: 127.0.0.1
3
+ pid: /var/run/rfid_thin.pid
4
+ port: 5000
5
+ wait: 10
6
+ timeout: 60
7
+ log: /var/log/rfid_thin.log
8
+ max_conns: 1024
9
+ require: []
10
+
11
+ environment: production
12
+ max_persistent_conns: 512
13
+ daemonize: true
14
+ servers: 1
@@ -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
@@ -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,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;');
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
+ });