millworker 0.1.0

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.
Binary file
@@ -0,0 +1,23 @@
1
+ # -*- ruby -*-
2
+
3
+ require 'autotest/restart'
4
+
5
+ # Autotest.add_hook :initialize do |at|
6
+ # at.extra_files << "../some/external/dependency.rb"
7
+ #
8
+ # at.libs << ":../some/external"
9
+ #
10
+ # at.add_exception 'vendor'
11
+ #
12
+ # at.add_mapping(/dependency.rb/) do |f, _|
13
+ # at.files_matching(/test_.*rb$/)
14
+ # end
15
+ #
16
+ # %w(TestA TestB).each do |klass|
17
+ # at.extra_class_map[klass] = "test/test_misc.rb"
18
+ # end
19
+ # end
20
+
21
+ # Autotest.add_hook :run_command do |at|
22
+ # system "rake build"
23
+ # end
File without changes
@@ -0,0 +1,6 @@
1
+ === 1.0.0 / 2012-08-22
2
+
3
+ * 1 major enhancement
4
+
5
+ * Birthday!
6
+
data/LICENSE ADDED
@@ -0,0 +1,23 @@
1
+ (The MIT License)
2
+
3
+ Copyright (c) 2012 Tom Kersten
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ 'Software'), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
19
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
20
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
21
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
22
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23
+
@@ -0,0 +1,12 @@
1
+ .autotest
2
+ History.txt
3
+ LICENSE
4
+ Manifest.txt
5
+ README.md
6
+ Rakefile
7
+ bin/millworker
8
+ example_tasks/log_to_csv.rb
9
+ lib/millworker.rb
10
+ lib/millworker/version.rb
11
+ spec/spec.opts
12
+ spec/spec_helper.rb
@@ -0,0 +1,83 @@
1
+ # millworker
2
+
3
+ * http://github.com/tomkersten/millworker
4
+
5
+ ## DESCRIPTION:
6
+
7
+ A Ruby gem which takes the pain of continuously reading data from a serial port
8
+ away and lets you focus on dealing with the data received.
9
+
10
+ This was written specifically for reading in data from an ID-20
11
+ RFID card reader and running custom scripts to automatically perform
12
+ various tasks when patrons scanned their badge at the
13
+ [MN Mill](http://mnmill.org) (logging attendance, etc).
14
+
15
+
16
+ Custom scripts are loaded from `ENV["HOME"]/millworker/tasks` and are executed
17
+ in alphabetical order. Each script is executed with the ID of the badge passed
18
+ in as an argument. For example, a script called `tweet_id.rb` existed in the
19
+ afformentioned directory, it would be executed as if you had opened up a
20
+ command terminal and typed `tweet_id.rb RFID_TAG_ID_HERE`.
21
+
22
+ ## SYNOPSIS:
23
+
24
+ Install the millworker gem (see below for instructions).
25
+
26
+ In order read from the correct port on your computer, we need to do a bit of
27
+ setup.
28
+
29
+ ```bash
30
+ millworker setup
31
+ #...you will be prompted for the name of the serial port
32
+ ```
33
+
34
+ Provided you keep the device connected to the same port, you should only
35
+ have to run this one time. In the event that things stop working for some
36
+ odd reason, you can re-run this as many times as necessary to overwrite
37
+ and/or verify your settings.
38
+
39
+ Next, start the worker by issuing the following command
40
+
41
+ ```bash
42
+ millworker start
43
+ ```
44
+
45
+ Each time the reader receives a card, an entry in the logfile is written, which
46
+ includes a timestamp and the data which was read over the serial port. After
47
+ logging this information, each script located in the `millworker/scripts`
48
+ directory is executed with the received data passed in as an argument.
49
+
50
+ You can stop the worker any time by issuing the following command:
51
+
52
+ ```bash
53
+ millworker stop
54
+ ```
55
+
56
+ ## REQUIREMENTS:
57
+
58
+ * Ruby 1.9.3+
59
+ * Please refer to the Gemfile for gem dependencies.
60
+
61
+ ## INSTALL:
62
+
63
+ From the command line:
64
+
65
+ ```bash
66
+ gem install millworker
67
+ ```
68
+
69
+ ## UNINSTALL:
70
+
71
+ From the command line:
72
+
73
+ ```bash
74
+ gem uninstall millworker
75
+ ```
76
+
77
+ __Note:__ You may also want to removes the entire `ENV['HOME']/millworker`
78
+ directory. This is not done automatically to prevent accidental data
79
+ loss.
80
+
81
+ ## LICENSE:
82
+
83
+ See the LICENSE file (hint: MIT)
@@ -0,0 +1,24 @@
1
+ # -*- ruby -*-
2
+
3
+ require 'rubygems'
4
+ require 'hoe'
5
+
6
+ Hoe.plugin :bundler
7
+ Hoe.plugin :git
8
+
9
+ Hoe.spec 'millworker' do
10
+ developer 'Tom Kersten', 'tom@whitespur.com'
11
+ dependency 'gli', "~> 2.0"
12
+ dependency 'dante', "~> 0.1"
13
+ dependency 'serialport', "~> 1.1"
14
+
15
+ self.readme_file = 'README.md'
16
+ self.extra_rdoc_files = FileList['README.md', 'LICENSE']
17
+ self.extra_dev_deps = [['rake'],
18
+ ['aruba'],
19
+ ['hoe-bundler'],
20
+ ['hoe-git']
21
+ ]
22
+ end
23
+
24
+ # vim: syntax=ruby
@@ -0,0 +1,121 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'gli'
4
+ require 'dante'
5
+ require 'fileutils'
6
+ require 'logger'
7
+ require 'serialport'
8
+
9
+ require 'millworker'
10
+
11
+ include GLI::App
12
+
13
+ program_desc 'Listen to a serial port and execute custom scripts with data received.'
14
+
15
+ version Millworker::VERSION
16
+
17
+ SERIAL_PORT = ENV['MILLWORKER_SERIAL_PORT']
18
+ BASE_PATH = ENV['MILLWORKER_PATH'] || File.expand_path(ENV['HOME'] + '/millworker')
19
+ CONFIG_PATH = "#{BASE_PATH}/config.yml"
20
+ TASKS_DIR = "#{BASE_PATH}/tasks"
21
+ TMP_DIR = "#{BASE_PATH}/tmp"
22
+ LOG_DIR = "#{BASE_PATH}/log"
23
+ LOG_PATH = "#{LOG_DIR}/millworker.log"
24
+ DAEMON_LOG_PATH = "#{LOG_DIR}/millworkerd.log"
25
+ PID_PATH = "#{TMP_DIR}/willworker.pid"
26
+ EXAMPLE_TASKS_DIR = File.join(File.dirname(File.dirname(__FILE__)), "example_tasks")
27
+
28
+ def execute(executable)
29
+ result = system(executable) ? "success" : "failure"
30
+ yield result
31
+ end
32
+
33
+ def config
34
+ @config ||= File.exists?(CONFIG_PATH) ? YAML.load(File.open(CONFIG_PATH)) : {}
35
+ end
36
+
37
+ def serial_port
38
+ SerialPort.new(SERIAL_PORT || config[:serial_port])
39
+ end
40
+
41
+
42
+ desc "Set up machine to use `millworker` executable"
43
+ command :setup do |c|
44
+ c.action do |g, o, a|
45
+ puts "Setting up millworker directory structure in #{BASE_PATH}"
46
+ [BASE_PATH, TMP_DIR, LOG_DIR, TASKS_DIR].each do |dir|
47
+ FileUtils.mkdir_p(dir) unless File.directory?(dir)
48
+ end
49
+ puts ""
50
+
51
+ port_name = nil
52
+ until !port_name.nil?
53
+ puts "What is the name of the serial port you'd like to read from? (eg: COM1): "
54
+ port_name= gets
55
+ port_name.strip!
56
+ end
57
+
58
+ File.open(CONFIG_PATH, "w") {|f| f.write({serial_port: port_name}.to_yaml)}
59
+
60
+ puts "Copying example tasks to #{TASKS_DIR}"
61
+ Dir["#{EXAMPLE_TASKS_DIR}/*"].map { |file|
62
+ FileUtils.cp file, TASKS_DIR
63
+ FileUtils.chmod 0755, "#{TASKS_DIR}/#{File.basename(file)}"
64
+ }
65
+
66
+ puts "Done. Now run 'millworker start' and you should be set!"
67
+ end
68
+ end
69
+
70
+ desc "Start lisening for data on an attached ID20 card reader."
71
+ command :start do |c|
72
+ c.switch :stdin, desc: 'Read input from STDIN (command line) instead of a serial port.'
73
+
74
+ c.action do |g, options, args|
75
+ Dante::Runner.new('millworker').execute(daemonize: !options[:stdin],
76
+ pid_path: PID_PATH,
77
+ log_path: DAEMON_LOG_PATH) {
78
+
79
+ FileUtils.mkdir_p(LOG_DIR) unless File.directory?(LOG_DIR)
80
+ logger = Logger.new(LOG_PATH)
81
+
82
+ input = options[:stdin] ? ARGF : serial_port
83
+
84
+ loop do
85
+ data = input.gets
86
+
87
+ unless data.nil? || data.empty?
88
+ data.strip! # Take off newline from serial read
89
+
90
+ logger.info "received: '#{data.chomp}'"
91
+
92
+ # Read task list in every time so the daemon does not need to be
93
+ # restarted after changes
94
+ tasks = Dir["#{TASKS_DIR}/*"]
95
+
96
+ if tasks.empty?
97
+ logger.warn "No tasks to execute in '#{TASKS_DIR}'. Skipping."
98
+ next
99
+ else
100
+ tasks.each do |task|
101
+ command = "#{task} #{data}"
102
+
103
+ execute(command) { |result|
104
+ logger.info("executed: '#{command}', result: #{result}")
105
+ }
106
+ end
107
+ end
108
+ end
109
+ end
110
+ }
111
+ end
112
+ end
113
+
114
+ desc "Stops a running application currently lisening for data."
115
+ command :stop do |c|
116
+ c.action do
117
+ Dante::Runner.new('millworker').execute(kill: true, pid_path: PID_PATH)
118
+ end
119
+ end
120
+
121
+ exit run(ARGV)
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+ require 'csv'
3
+
4
+ CSV_FILENAME = "millworker_log.csv"
5
+ CSV_DIR = ENV["MILLWORKER_CSV_DIR"] || File.expand_path("#{ENV['HOME']}/Desktop")
6
+ CSV_PATH = "#{CSV_DIR}/#{CSV_FILENAME}"
7
+
8
+ when_new_file = !File.exists?(CSV_PATH)
9
+
10
+ CSV_OPTIONS = {headers: %w(timestamp card_id),
11
+ write_headers: when_new_file,
12
+ force_quotes: true
13
+ }
14
+ CSV.open(CSV_PATH, "a+", CSV_OPTIONS) {|csv| csv << [Time.now, ARGV[0]]}
@@ -0,0 +1,4 @@
1
+ require 'millworker/version'
2
+
3
+ module Millworker
4
+ end
@@ -0,0 +1,3 @@
1
+ module Millworker
2
+ VERSION = '0.1.0'
3
+ end
@@ -0,0 +1,4 @@
1
+ --colour
2
+ --format
3
+ profile
4
+ --diff
@@ -0,0 +1,3 @@
1
+ require 'lib/<lib_name>'
2
+
3
+ Dir.glob('spec/support/**/*.rb').each {|f| require f}
metadata ADDED
@@ -0,0 +1,245 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: millworker
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Tom Kersten
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain:
12
+ - !binary |-
13
+ LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURNRENDQWhpZ0F3SUJB
14
+ Z0lCQURBTkJna3Foa2lHOXcwQkFRVUZBREErTVF3d0NnWURWUVFEREFOMGIy
15
+ MHgKR1RBWEJnb0praWFKay9Jc1pBRVpGZ2wzYUdsMFpYTndkWEl4RXpBUkJn
16
+ b0praWFKay9Jc1pBRVpGZ05qYjIwdwpIaGNOTVRFd05ESXlNRFF6T1RBNVdo
17
+ Y05NVEl3TkRJeE1EUXpPVEE1V2pBK01Rd3dDZ1lEVlFRRERBTjBiMjB4CkdU
18
+ QVhCZ29Ka2lhSmsvSXNaQUVaRmdsM2FHbDBaWE53ZFhJeEV6QVJCZ29Ka2lh
19
+ SmsvSXNaQUVaRmdOamIyMHcKZ2dFaU1BMEdDU3FHU0liM0RRRUJBUVVBQTRJ
20
+ QkR3QXdnZ0VLQW9JQkFRRHB4b3pEUWdWTi9vWmxqR2xJOW9wbQpDcmhOVkEv
21
+ bHNOaVhaQlVtamZRQzVYUlBZSHptbHVvbjJaejQwNTBsak9ES1grYi90a3ov
22
+ V1ZaNng3YStMb3AyCnlDTExXTGNITmdCMTBqM2ozazZiTTBsM2NmQ2RDdnpl
23
+ dkU3WmdwdzNvL2J6YXpTVDV4MHBOenVyYXNTMW91UWsKeC8ybzlFNnFxSlJ1
24
+ QjUxa2h1WktuaCtNYTUyL0kxS1FhTUo0Ylc2Tk9ncXVGQ0VJdW04TUpKQkpX
25
+ RWRHbTRJdAp2aFMvZGFSZS9BRGtZbGdXbDFZMWs3THh1SCsxVkN4N3pNRk1l
26
+ MUUwQ01KemhHZjd6dU1TMHcrZHF3Ykw1bTNOCk1MRTh2Z3h3VEVPc093R3o0
27
+ d0Q2ek1VZEJZNkZHWXdSazhMR2p2bG9rbjBwWjFqeVdIV1NnMmJVdi8xR0My
28
+ aTkKQWdNQkFBR2pPVEEzTUFrR0ExVWRFd1FDTUFBd0N3WURWUjBQQkFRREFn
29
+ U3dNQjBHQTFVZERnUVdCQlRONjFBegp5a0RZaGVSSHR6c2p3RTdmaUxoWW16
30
+ QU5CZ2txaGtpRzl3MEJBUVVGQUFPQ0FRRUFMd29Jbld1YkpYSllWSDJOClhu
31
+ Q01UNFlseE5zUW9ZZERTeEVhZ05PbVpqSzJlS3RqdTBWOUdqWkFueVlCMnEy
32
+ TExpbHZiTXlWdGcvNkFOMEkKWGhDanlZWlJSQ0FEeXZGR1Y0YUJWdjd5aktG
33
+ UXJJeVh5OEpUMWlYeEhDMU4ybzFESmxaVWx0Q1lOb3pKQmhzTwpWTmJuU3Fl
34
+ OFlZY2V6c3VRMi93OWlhdldYQ2Y5MVFQd25yZkhQWlRyRlBPdmVza0pjdG04
35
+ SGluRjQxZkt3RzVCCmlVSHk4cVZXR0JDcERGWXo2S3orSnRpZ2FJQ2NtMkQ0
36
+ L1dHTHNEVk9tZ0orZzR4b09pQ2U5WkVrZGE4SytsL0YKeVhXcUluUmxGSWxU
37
+ dXdGVHhqMjZqYXVCb3NrQlBvejViZmtaRmphVlJoeVVuUm5Ha2E2Nmx2Y0RP
38
+ R2ZrUlpXUQpOVkFESkE9PQotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tCg==
39
+ date: 2012-09-10 00:00:00.000000000 Z
40
+ dependencies:
41
+ - !ruby/object:Gem::Dependency
42
+ name: gli
43
+ requirement: !ruby/object:Gem::Requirement
44
+ none: false
45
+ requirements:
46
+ - - ~>
47
+ - !ruby/object:Gem::Version
48
+ version: '2.0'
49
+ type: :runtime
50
+ prerelease: false
51
+ version_requirements: !ruby/object:Gem::Requirement
52
+ none: false
53
+ requirements:
54
+ - - ~>
55
+ - !ruby/object:Gem::Version
56
+ version: '2.0'
57
+ - !ruby/object:Gem::Dependency
58
+ name: dante
59
+ requirement: !ruby/object:Gem::Requirement
60
+ none: false
61
+ requirements:
62
+ - - ~>
63
+ - !ruby/object:Gem::Version
64
+ version: '0.1'
65
+ type: :runtime
66
+ prerelease: false
67
+ version_requirements: !ruby/object:Gem::Requirement
68
+ none: false
69
+ requirements:
70
+ - - ~>
71
+ - !ruby/object:Gem::Version
72
+ version: '0.1'
73
+ - !ruby/object:Gem::Dependency
74
+ name: serialport
75
+ requirement: !ruby/object:Gem::Requirement
76
+ none: false
77
+ requirements:
78
+ - - ~>
79
+ - !ruby/object:Gem::Version
80
+ version: '1.1'
81
+ type: :runtime
82
+ prerelease: false
83
+ version_requirements: !ruby/object:Gem::Requirement
84
+ none: false
85
+ requirements:
86
+ - - ~>
87
+ - !ruby/object:Gem::Version
88
+ version: '1.1'
89
+ - !ruby/object:Gem::Dependency
90
+ name: rake
91
+ requirement: !ruby/object:Gem::Requirement
92
+ none: false
93
+ requirements:
94
+ - - ! '>='
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
97
+ type: :development
98
+ prerelease: false
99
+ version_requirements: !ruby/object:Gem::Requirement
100
+ none: false
101
+ requirements:
102
+ - - ! '>='
103
+ - !ruby/object:Gem::Version
104
+ version: '0'
105
+ - !ruby/object:Gem::Dependency
106
+ name: aruba
107
+ requirement: !ruby/object:Gem::Requirement
108
+ none: false
109
+ requirements:
110
+ - - ! '>='
111
+ - !ruby/object:Gem::Version
112
+ version: '0'
113
+ type: :development
114
+ prerelease: false
115
+ version_requirements: !ruby/object:Gem::Requirement
116
+ none: false
117
+ requirements:
118
+ - - ! '>='
119
+ - !ruby/object:Gem::Version
120
+ version: '0'
121
+ - !ruby/object:Gem::Dependency
122
+ name: hoe-bundler
123
+ requirement: !ruby/object:Gem::Requirement
124
+ none: false
125
+ requirements:
126
+ - - ! '>='
127
+ - !ruby/object:Gem::Version
128
+ version: '0'
129
+ type: :development
130
+ prerelease: false
131
+ version_requirements: !ruby/object:Gem::Requirement
132
+ none: false
133
+ requirements:
134
+ - - ! '>='
135
+ - !ruby/object:Gem::Version
136
+ version: '0'
137
+ - !ruby/object:Gem::Dependency
138
+ name: hoe-git
139
+ requirement: !ruby/object:Gem::Requirement
140
+ none: false
141
+ requirements:
142
+ - - ! '>='
143
+ - !ruby/object:Gem::Version
144
+ version: '0'
145
+ type: :development
146
+ prerelease: false
147
+ version_requirements: !ruby/object:Gem::Requirement
148
+ none: false
149
+ requirements:
150
+ - - ! '>='
151
+ - !ruby/object:Gem::Version
152
+ version: '0'
153
+ - !ruby/object:Gem::Dependency
154
+ name: hoe
155
+ requirement: !ruby/object:Gem::Requirement
156
+ none: false
157
+ requirements:
158
+ - - ~>
159
+ - !ruby/object:Gem::Version
160
+ version: '3.0'
161
+ type: :development
162
+ prerelease: false
163
+ version_requirements: !ruby/object:Gem::Requirement
164
+ none: false
165
+ requirements:
166
+ - - ~>
167
+ - !ruby/object:Gem::Version
168
+ version: '3.0'
169
+ description: ! 'A Ruby gem which takes the pain of continuously reading data from
170
+ a serial port
171
+
172
+ away and lets you focus on dealing with the data received.
173
+
174
+
175
+ This was written specifically for reading in data from an ID-20
176
+
177
+ RFID card reader and running custom scripts to automatically perform
178
+
179
+ various tasks when patrons scanned their badge at the
180
+
181
+ [MN Mill](http://mnmill.org) (logging attendance, etc).
182
+
183
+
184
+
185
+ Custom scripts are loaded from `ENV["HOME"]/millworker/tasks` and are executed
186
+
187
+ in alphabetical order. Each script is executed with the ID of the badge passed
188
+
189
+ in as an argument. For example, a script called `tweet_id.rb` existed in the
190
+
191
+ afformentioned directory, it would be executed as if you had opened up a
192
+
193
+ command terminal and typed `tweet_id.rb RFID_TAG_ID_HERE`.'
194
+ email:
195
+ - tom@whitespur.com
196
+ executables:
197
+ - millworker
198
+ extensions: []
199
+ extra_rdoc_files:
200
+ - History.txt
201
+ - Manifest.txt
202
+ - README.md
203
+ - LICENSE
204
+ files:
205
+ - .autotest
206
+ - History.txt
207
+ - LICENSE
208
+ - Manifest.txt
209
+ - README.md
210
+ - Rakefile
211
+ - bin/millworker
212
+ - example_tasks/log_to_csv.rb
213
+ - lib/millworker.rb
214
+ - lib/millworker/version.rb
215
+ - spec/spec.opts
216
+ - spec/spec_helper.rb
217
+ - .gemtest
218
+ homepage: http://github.com/tomkersten/millworker
219
+ licenses: []
220
+ post_install_message:
221
+ rdoc_options:
222
+ - --main
223
+ - README.md
224
+ require_paths:
225
+ - lib
226
+ required_ruby_version: !ruby/object:Gem::Requirement
227
+ none: false
228
+ requirements:
229
+ - - ! '>='
230
+ - !ruby/object:Gem::Version
231
+ version: '0'
232
+ required_rubygems_version: !ruby/object:Gem::Requirement
233
+ none: false
234
+ requirements:
235
+ - - ! '>='
236
+ - !ruby/object:Gem::Version
237
+ version: '0'
238
+ requirements: []
239
+ rubyforge_project: millworker
240
+ rubygems_version: 1.8.23
241
+ signing_key:
242
+ specification_version: 3
243
+ summary: A Ruby gem which takes the pain of continuously reading data from a serial
244
+ port away and lets you focus on dealing with the data received
245
+ test_files: []
Binary file