bcs-interrogator 0.0.1 → 0.0.2

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,46 @@
1
+ module NRB
2
+ class BCSInterrogator
3
+ class API
4
+
5
+ autoload :Endpoint, 'bcs_interrogator/api/endpoint'
6
+ autoload :Response, 'bcs_interrogator/api/response'
7
+ autoload :Sysname, 'bcs_interrogator/api/sysname'
8
+ autoload :Ultemp, 'bcs_interrogator/api/ultemp'
9
+
10
+ API_VERSION = 'BCS 3.7.0' # Use NRB::BCSInterrogator::API.api_version instead
11
+
12
+ def self.api_version; API_VERSION; end
13
+
14
+
15
+ attr_reader :http_service, :base_url
16
+
17
+ def api_call(args,connection_opts={})
18
+ args[:response_class] ||= NRB::BCSInterrogator::API::Response
19
+ response = @http_service.new(args,connection_opts).make_request
20
+ if response.server_version &&
21
+ response.server_version != self.class.api_version
22
+ warn "Firmware version (#{response.server_version}) does not match API version (#{self.class.api_version})."
23
+ end
24
+ response
25
+ end
26
+
27
+
28
+ def initialize(args={})
29
+ @base_url = args.delete(:base_url)
30
+ raise ArgumentError.new("Please supply a :base_url") unless @base_url
31
+ @http_service = args.delete(:http_service) || NRB::HTTPService
32
+ end
33
+
34
+
35
+ def sysname; @sysname ||= Sysname.new api: self; end
36
+ def ultemp; @ultemp ||= Ultemp.new api: self; end
37
+
38
+ private
39
+
40
+ def endpoint_base
41
+ @base_url
42
+ end
43
+
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,61 @@
1
+ module NRB
2
+ class BCSInterrogator
3
+ class API
4
+ class Endpoint
5
+
6
+ include Enumerable
7
+
8
+ attr_reader :response
9
+
10
+ def self.descriptions
11
+ const_defined?(:DESCRIPTIONS) ? const_get(:DESCRIPTIONS) : nil
12
+ end
13
+
14
+
15
+ def self.endpoint
16
+ const_defined?(:ENDPOINT) ? const_get(:ENDPOINT) : nil
17
+ end
18
+
19
+
20
+ def api_call(args={})
21
+ args[:verb] ||= :get
22
+ args[:url] ||= endpoint
23
+ @response = @api.api_call args
24
+ @data = @response.body
25
+ @response
26
+ end
27
+
28
+
29
+ def each(&block)
30
+ data.each(block)
31
+ end
32
+
33
+
34
+ def endpoint
35
+ @api.base_url + self.class.endpoint
36
+ end
37
+
38
+
39
+ def initialize(args={})
40
+ @api = args.delete(:api)
41
+ raise ArgumentError.new("Please supply an API object") unless @api
42
+ end
43
+
44
+
45
+ def data
46
+ return @data if @data
47
+ api_call
48
+ @data
49
+ end
50
+
51
+
52
+ def to_a; data; end
53
+
54
+ def to_h
55
+ self.class.descriptions.each_with_index { |descr,i| data[descr] = @response.body[i] }
56
+ end
57
+
58
+ end
59
+ end
60
+ end
61
+ end
@@ -0,0 +1,38 @@
1
+ module NRB
2
+ class BCSInterrogator
3
+ class API
4
+ class Response
5
+
6
+ attr_reader :status, :body, :headers
7
+
8
+ def errored?
9
+ ! success?
10
+ end
11
+
12
+
13
+ def initialize(args)
14
+ @status = args[:status]
15
+ @body = process_body args[:body]
16
+ @headers = args[:headers]
17
+ end
18
+
19
+
20
+ def server_version
21
+ @headers.nil? ? "" : @headers["server"].sub(/\s+\(http:\/\/www\.embeddedcc\.com\)$/, '')
22
+ end
23
+
24
+
25
+ def success?
26
+ @status >= 200 && @status < 300
27
+ end
28
+
29
+ private
30
+
31
+ def process_body(body_string)
32
+ @body = body_string.split(',').map { |str| str.strip }
33
+ end
34
+
35
+ end
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,227 @@
1
+ module NRB
2
+ class BCSInterrogator
3
+ class API
4
+ class Sysname < Endpoint
5
+ # http://wiki.embeddedcc.com/index.php/Sysname.dat
6
+ # Entries in the sysname structure cannot be more than 16 characters
7
+ # Commas are not allowed
8
+
9
+ DESCRIPTIONS = [
10
+ 'Firmware Version',
11
+ 'Process 0 name',
12
+ 'Process 1 name',
13
+ 'Process 2 name',
14
+ 'Process 3 name',
15
+ 'Process 0 State 0 name',
16
+ 'Process 0 State 1 name',
17
+ 'Process 0 State 2 name',
18
+ 'Process 0 State 3 name',
19
+ 'Process 0 State 4 name',
20
+ 'Process 0 State 5 name',
21
+ 'Process 0 State 6 name',
22
+ 'Process 0 State 7 name',
23
+ 'Process 1 State 0 name',
24
+ 'Process 1 State 1 name',
25
+ 'Process 1 State 2 name',
26
+ 'Process 1 State 3 name',
27
+ 'Process 1 State 4 name',
28
+ 'Process 1 State 5 name',
29
+ 'Process 1 State 6 name',
30
+ 'Process 1 State 7 name',
31
+ 'Process 2 State 0 name',
32
+ 'Process 2 State 1 name',
33
+ 'Process 2 State 2 name',
34
+ 'Process 2 State 3 name',
35
+ 'Process 2 State 4 name',
36
+ 'Process 2 State 5 name',
37
+ 'Process 2 State 6 name',
38
+ 'Process 2 State 7 name',
39
+ 'Process 3 State 0 name',
40
+ 'Process 3 State 1 name',
41
+ 'Process 3 State 2 name',
42
+ 'Process 3 State 3 name',
43
+ 'Process 3 State 4 name',
44
+ 'Process 3 State 5 name',
45
+ 'Process 3 State 6 name',
46
+ 'Process 3 State 7 name',
47
+ 'Output 0 name',
48
+ 'Output 1 name',
49
+ 'Output 2 name',
50
+ 'Output 3 name',
51
+ 'Output 4 name',
52
+ 'Output 5 name',
53
+ 'Din 0 name',
54
+ 'Din 1 name',
55
+ 'Din 2 name',
56
+ 'Din 3 name',
57
+ 'Process 0 Win 0 name',
58
+ 'Process 0 Win 1 name',
59
+ 'Process 0 Win 2 name',
60
+ 'Process 0 Win 3 name',
61
+ 'Process 1 Win 0 name',
62
+ 'Process 1 Win 1 name',
63
+ 'Process 1 Win 2 name',
64
+ 'Process 1 Win 3 name',
65
+ 'Process 2 Win 0 name',
66
+ 'Process 2 Win 1 name',
67
+ 'Process 2 Win 2 name',
68
+ 'Process 2 Win 3 name',
69
+ 'Process 3 Win 0 name',
70
+ 'Process 3 Win 1 name',
71
+ 'Process 3 Win 2 name',
72
+ 'Process 3 Win 3 name',
73
+ 'Temp Probe 0 name',
74
+ 'Temp Probe 1 name',
75
+ 'Temp Probe 2 name',
76
+ 'Temp Probe 3 name',
77
+ 'Process 0 Timer 0 name',
78
+ 'Process 0 Timer 1 name',
79
+ 'Process 0 Timer 2 name',
80
+ 'Process 0 Timer 3 name',
81
+ 'Process 1 Timer 0 name',
82
+ 'Process 1 Timer 1 name',
83
+ 'Process 1 Timer 2 name',
84
+ 'Process 1 Timer 3 name',
85
+ 'Process 2 Timer 0 name',
86
+ 'Process 2 Timer 1 name',
87
+ 'Process 2 Timer 2 name',
88
+ 'Process 2 Timer 3 name',
89
+ 'Process 3 Timer 0 name',
90
+ 'Process 3 Timer 1 name',
91
+ 'Process 3 Timer 2 name',
92
+ 'Process 3 Timer 3 name',
93
+ 'Reserved',
94
+ 'Reserved',
95
+ 'Temp Probe 4 name',
96
+ 'Temp Probe 5 name',
97
+ 'Temp Probe 6 name',
98
+ 'Temp Probe 7 name',
99
+ 'Din 4 name',
100
+ 'Din 5 name',
101
+ 'Din 6 name',
102
+ 'Din 7 name',
103
+ 'Output 6 name',
104
+ 'Output 7 name',
105
+ 'Output 8 name',
106
+ 'Output 9 name',
107
+ 'Output 10 name',
108
+ 'Output 11 name',
109
+ 'Output 12 name',
110
+ 'Output 13 name',
111
+ 'Output 14 name',
112
+ 'Output 15 name',
113
+ 'Output 16 name',
114
+ 'Output 17 name',
115
+ 'Process 4 name',
116
+ 'Process 5 name',
117
+ 'Process 6 name',
118
+ 'Process 7 name',
119
+ 'Process 4 State 0 name',
120
+ 'Process 4 State 1 name',
121
+ 'Process 4 State 2 name',
122
+ 'Process 4 State 3 name',
123
+ 'Process 4 State 4 name',
124
+ 'Process 4 State 5 name',
125
+ 'Process 4 State 6 name',
126
+ 'Process 4 State 7 name',
127
+ 'Process 5 State 0 name',
128
+ 'Process 5 State 1 name',
129
+ 'Process 5 State 2 name',
130
+ 'Process 5 State 3 name',
131
+ 'Process 5 State 4 name',
132
+ 'Process 5 State 5 name',
133
+ 'Process 5 State 6 name',
134
+ 'Process 5 State 7 name',
135
+ 'Process 6 State 0 name',
136
+ 'Process 6 State 1 name',
137
+ 'Process 6 State 2 name',
138
+ 'Process 6 State 3 name',
139
+ 'Process 6 State 4 name',
140
+ 'Process 6 State 5 name',
141
+ 'Process 6 State 6 name',
142
+ 'Process 6 State 7 name',
143
+ 'Process 7 State 0 name',
144
+ 'Process 7 State 1 name',
145
+ 'Process 7 State 2 name',
146
+ 'Process 7 State 3 name',
147
+ 'Process 7 State 4 name',
148
+ 'Process 7 State 5 name',
149
+ 'Process 7 State 6 name',
150
+ 'Process 7 State 7 name',
151
+ 'Process 4 Win 0 name',
152
+ 'Process 4 Win 1 name',
153
+ 'Process 4 Win 2 name',
154
+ 'Process 4 Win 3 name',
155
+ 'Process 5 Win 0 name',
156
+ 'Process 5 Win 1 name',
157
+ 'Process 5 Win 2 name',
158
+ 'Process 5 Win 3 name',
159
+ 'Process 6 Win 0 name',
160
+ 'Process 6 Win 1 name',
161
+ 'Process 6 Win 2 name',
162
+ 'Process 6 Win 3 name',
163
+ 'Process 7 Win 0 name',
164
+ 'Process 7 Win 1 name',
165
+ 'Process 7 Win 2 name',
166
+ 'Process 7 Win 3 name',
167
+ '4 Timer 0 name',
168
+ '4 Timer 1 name',
169
+ '4 Timer 2 name',
170
+ '4 Timer 3 name',
171
+ '5 Timer 0 name',
172
+ '5 Timer 1 name',
173
+ '5 Timer 2 name',
174
+ '5 Timer 3 name',
175
+ '6 Timer 0 name',
176
+ '6 Timer 1 name',
177
+ '6 Timer 2 name',
178
+ '6 Timer 3 name',
179
+ '7 Timer 0 name',
180
+ '7 Timer 1 name',
181
+ '7 Timer 2 name',
182
+ '7 Timer 3 name',
183
+ 'Reserved',
184
+ 'Reserved',
185
+ 'Reserved',
186
+ 'Reserved',
187
+ 'Reserved',
188
+ 'Reserved',
189
+ 'Reserved',
190
+ 'Reserved',
191
+ 'Reserved',
192
+ 'Reserved',
193
+ 'Reserved',
194
+ 'Reserved',
195
+ 'Reserved',
196
+ 'Reserved',
197
+ 'Reserved',
198
+ 'Reserved',
199
+ 'Reserved',
200
+ 'Reserved',
201
+ 'Reserved',
202
+ 'Reserved',
203
+ 'Reserved',
204
+ 'Reserved',
205
+ 'Reserved',
206
+ 'Reserved',
207
+ 'Reserved',
208
+ 'Reserved',
209
+ 'Reserved',
210
+ 'Reserved',
211
+ 'Reserved',
212
+ 'Reserved',
213
+ 'Reserved',
214
+ 'Reserved',
215
+ 'Reserved'
216
+ ]
217
+
218
+ ENDPOINT = '/sysname.dat'
219
+
220
+ def input_names; data[43..46] + data[89..92]; end
221
+ def output_names; data[37..42] + data[93..104]; end
222
+ def temp_probe_names; data[63..66] + data[85..88]; end
223
+
224
+ end
225
+ end
226
+ end
227
+ end
@@ -0,0 +1,110 @@
1
+ module NRB
2
+ class BCSInterrogator
3
+ class API
4
+ class Ultemp < Endpoint
5
+ # http://wiki.embeddedcc.com/index.php/Ultemp.dat
6
+ # All entries in the ultemp structure have to be in the range
7
+ # 0 <= ultemp < 2^32
8
+ # Commas are not allowed
9
+
10
+ DESCRIPTIONS = [
11
+ 'Running Process (proc_en) (7:0)',
12
+ 'Discrete Outputs (17:0)',
13
+ 'Discrete Inputs (8:0)',
14
+ 'Temp0 * 10',
15
+ 'Temp1 * 10',
16
+ 'Temp2 * 10',
17
+ 'Temp3 * 10',
18
+ 'Temp4 * 10',
19
+ 'Temp5 * 10',
20
+ 'Temp6 * 10',
21
+ 'Temp7 * 10',
22
+ 'Temp0 Setpoint * 10',
23
+ 'Temp1 Setpoint * 10',
24
+ 'Temp2 Setpoint * 10',
25
+ 'Temp3 Setpoint * 10',
26
+ 'Temp4 Setpoint * 10',
27
+ 'Temp5 Setpoint * 10',
28
+ 'Temp6 Setpoint * 10',
29
+ 'Temp7 Setpoint * 10',
30
+ 'Current State - P0(31:24) P1(23:16) P2(15:8) P3(7:0)',
31
+ 'Current State - P4(31:24) P5(23:16) P6(15:8) P7(7:0)',
32
+ 'Process Timer 0 [P0:P7][T0:T3]',
33
+ 'Process Timer 0 [P0:P7][T0:T3]',
34
+ 'Process Timer 0 [P0:P7][T0:T3]',
35
+ 'Process Timer 0 [P0:P7][T0:T3]',
36
+ 'Process Timer 0 [P0:P7][T0:T3]',
37
+ 'Process Timer 0 [P0:P7][T0:T3]',
38
+ 'Process Timer 0 [P0:P7][T0:T3]',
39
+ 'Process Timer 0 [P0:P7][T0:T3]',
40
+ 'Process Timer 0 [P0:P7][T0:T3]',
41
+ 'Process Timer 0 [P0:P7][T0:T3]',
42
+ 'Process Timer 0 [P0:P7][T0:T3]',
43
+ 'Process Timer 0 [P0:P7][T0:T3]',
44
+ 'Process Timer 0 [P0:P7][T0:T3]',
45
+ 'Process Timer 0 [P0:P7][T0:T3]',
46
+ 'Process Timer 0 [P0:P7][T0:T3]',
47
+ 'Process Timer 0 [P0:P7][T0:T3]',
48
+ 'Process Timer 0 [P0:P7][T0:T3]',
49
+ 'Process Timer 0 [P0:P7][T0:T3]',
50
+ 'Process Timer 0 [P0:P7][T0:T3]',
51
+ 'Process Timer 0 [P0:P7][T0:T3]',
52
+ 'Process Timer 0 [P0:P7][T0:T3]',
53
+ 'Process Timer 0 [P0:P7][T0:T3]',
54
+ 'Process Timer 0 [P0:P7][T0:T3]',
55
+ 'Process Timer 0 [P0:P7][T0:T3]',
56
+ 'Process Timer 0 [P0:P7][T0:T3]',
57
+ 'Process Timer 0 [P0:P7][T0:T3]',
58
+ 'Process Timer 0 [P0:P7][T0:T3]',
59
+ 'Process Timer 0 [P0:P7][T0:T3]',
60
+ 'Process Timer 0 [P0:P7][T0:T3]',
61
+ 'Process Timer 0 [P0:P7][T0:T3]',
62
+ 'Process Timer 0 [P0:P7][T0:T3]',
63
+ 'Process Timer 0 [P0:P7][T0:T3]',
64
+ 'Internal Registers (15:0)',
65
+ 'Miscellaneous
66
+ Bit 8: Alarm
67
+ Bits 7:0 : Process[7:0] Pause'
68
+ ]
69
+
70
+ ENDPOINT = '/ultemp.dat'
71
+
72
+ def inputs
73
+ bitmasked_data 0..7, 2
74
+ end
75
+
76
+
77
+ def outputs
78
+ bitmasked_data 0..17, 1
79
+ end
80
+
81
+
82
+ def temps
83
+ data_by_ten(3..10)
84
+ end
85
+
86
+
87
+ def setpoints
88
+ data_by_ten(11..18)
89
+ end
90
+
91
+ private
92
+
93
+ def collect_data(range, &block)
94
+ data[range].collect &block
95
+ end
96
+
97
+
98
+ def bitmasked_data(range, data_pos)
99
+ collect_data(range) { |i| data[data_pos].to_i & (2**i) > 0 }
100
+ end
101
+
102
+
103
+ def data_by_ten(range)
104
+ collect_data(range) { |t| t.to_f / 10.0 }
105
+ end
106
+
107
+ end
108
+ end
109
+ end
110
+ end
@@ -0,0 +1,43 @@
1
+ module NRB
2
+ class BCSInterrogator
3
+ class Entity
4
+
5
+ def initialize(args={})
6
+ @bcs = args[:bcs]
7
+ raise ArgumentError("Please provide a BCS object") if @bcs.nil?
8
+ if args[:positions].is_a?(Fixnum)
9
+ @positions = { output_names: args[:positions],
10
+ outputs: args[:positions],
11
+ temp_probe_names: args[:positions],
12
+ temps: args[:positions],
13
+ setpoints: args[:positions]
14
+ }
15
+ else
16
+ @positions = args[:positions]
17
+ end
18
+ end
19
+
20
+
21
+ def input_name; data :input_names; end
22
+ def last_update; @bcs.last_update; end
23
+ def name; data :temp_probe_names; end
24
+ def output_name; data :output_names; end
25
+ def output; data :outputs; end
26
+ def setpoint; data :setpoints; end
27
+ def temp; data :temps; end
28
+ def update; @bcs.update; end
29
+
30
+ private
31
+
32
+ def data(lookup)
33
+ update if last_update.nil?
34
+ if @bcs.respond_to?(lookup)
35
+ @bcs.send(lookup)[@positions[lookup]]
36
+ else
37
+ raise ArgumentError.new "No data for #{lookup}"
38
+ end
39
+ end
40
+
41
+ end
42
+ end
43
+ end
@@ -1,6 +1,6 @@
1
1
  module NRB
2
2
  class BCSInterrogator
3
- VERSION = '0.0.1'
3
+ VERSION = '0.0.2'
4
4
  def self.version; VERSION; end
5
5
  end
6
6
  end
@@ -0,0 +1,33 @@
1
+ require 'spec_helper'
2
+
3
+ describe NRB::BCSInterrogator::API do
4
+
5
+ context 'class methods' do
6
+ it 'has a version' do
7
+ NRB::BCSInterrogator::API.should respond_to :api_version
8
+ end
9
+ end
10
+
11
+ context 'defaults' do
12
+
13
+ let(:api) { NRB::BCSInterrogator::API.new args }
14
+ let(:args) { { base_url: base_url } }
15
+ let(:base_url) { '' }
16
+ let(:http_service) { NRB::HTTPService }
17
+
18
+ it 'has a default http_service' do
19
+ api.http_service.should == http_service
20
+ end
21
+
22
+ it 'has an base_url reader' do
23
+ api.base_url.should eq base_url
24
+ end
25
+
26
+ end
27
+
28
+ it 'blows up without a base_url' do
29
+ expect { NRB::BCSInterrogator::API.new }.to raise_error(ArgumentError)
30
+ end
31
+
32
+
33
+ end
@@ -0,0 +1,4 @@
1
+ require 'spec_helper'
2
+
3
+ describe NRB::BCSInterrogator do
4
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: bcs-interrogator
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.0.2
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -117,8 +117,16 @@ files:
117
117
  - LICENSE
118
118
  - README.md
119
119
  - lib/bcs_interrogator.rb
120
+ - lib/bcs_interrogator/api.rb
121
+ - lib/bcs_interrogator/api/endpoint.rb
122
+ - lib/bcs_interrogator/api/response.rb
123
+ - lib/bcs_interrogator/api/sysname.rb
124
+ - lib/bcs_interrogator/api/ultemp.rb
125
+ - lib/bcs_interrogator/entity.rb
120
126
  - lib/bcs_interrogator/version.rb
121
127
  - spec/spec_helper.rb
128
+ - spec/cases/api_spec.rb
129
+ - spec/cases/bcs_interrogator_spec.rb
122
130
  homepage: https://github.com/NewRepublicBrewing/BCS-Interrogator
123
131
  licenses: []
124
132
  post_install_message:
@@ -145,4 +153,6 @@ specification_version: 3
145
153
  summary: A gem to intorrogate EEC Brewery Control Systems
146
154
  test_files:
147
155
  - spec/spec_helper.rb
156
+ - spec/cases/api_spec.rb
157
+ - spec/cases/bcs_interrogator_spec.rb
148
158
  has_rdoc: