micro_aeth-ae51-ruby 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.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: d6c48744a043423d468f6efbe381db6ed005d668
4
+ data.tar.gz: 992247eaeb80568221f19142cc0a0b3f8448417d
5
+ SHA512:
6
+ metadata.gz: a49064b2b7c4ef853ce5eb51ce359ae3f1ebc9895205045e577f47986c72d2bb019d5e042d7f30ad91da2b2d7957d4ed0e162ede8af6a06b274b386837562dfa
7
+ data.tar.gz: e90dc640e49fa5f117ffa001c100db896a39bcfc2e31a642fd73c5bc13ec3d75733703c5cf59a31f2788750f443540eff9f7e1cdccc54d9e034fbaf43c6b1bee
@@ -0,0 +1,317 @@
1
+ require 'serialport'
2
+ require 'timeout'
3
+
4
+ module MicroAethAE51
5
+ class ::String
6
+ ###
7
+ # @return the first charater in the string as an integer
8
+ def byte
9
+ self.bytes[0]
10
+ end
11
+
12
+ ###
13
+ # XOR two strings
14
+ # @str assumed to be a one byte string or integer
15
+ def ^ str
16
+ if str.class == String
17
+ str = str.byte
18
+ elsif str.class == Fixnum
19
+ nil
20
+ else
21
+ raise "invalid arg: #{str.class} \n Must be String or Fixnum"
22
+ end
23
+ self.bytes.each do |i|
24
+ str = str ^ i
25
+ end
26
+ str.chr.force_encoding( "ASCII-8BIT")
27
+ end
28
+ end
29
+
30
+ class Instruction
31
+ ###
32
+ # Message constants
33
+ STX = "\x02" # Start of each message
34
+ ETX = "\x03" # End of each message
35
+ M = "AE5X:" # What each message starts with
36
+ EraseFlash = "E" # Reply:ACK, after flash is erased anotherACK issent.(erasing should take 30 – 45 seconds)
37
+ StopWrite = "S" # stopswriting to flash
38
+ StartWrite = "W" # Startswriting to flash
39
+ Kill = "K" # Kill Shuts down microAeth
40
+ end
41
+
42
+ ###
43
+ # Creates and parses messages to and from the MicroAeth.
44
+ # See MicroAeth::Com for specifications on the
45
+ # transmiting of messages.
46
+ class Message
47
+ attr :original_char_string,
48
+ :ref,
49
+ :sen1,
50
+ :sen2,
51
+ :flow,
52
+ :pcb_temp,
53
+ :time,
54
+ :status,
55
+ :battery
56
+
57
+ ###
58
+ # @param data [String] conents between the `STX` "\x02"
59
+ # and the `ETX` "0x03"
60
+ def initialize data
61
+ raise "invalid data" unless data_valid? data
62
+ @original_char_string = data
63
+ parse_data( data[7..-1])
64
+ end
65
+
66
+ private
67
+ def data_valid? d
68
+ crc = d[-1]
69
+ data = d[1..-2]
70
+ len = d[0]
71
+ (data ^ len).byte == crc.byte
72
+ end
73
+ def parse_data d
74
+ b = d.bytes
75
+ @ref = d[0..2].unpack("v")[0]
76
+ @sen1 = d[3..5].unpack("v")[0]
77
+ @sen2 = d[6..8].unpack("v")[0]
78
+ @flow = d[9..10].unpack("v")[0]
79
+ @pcb_temp = b[11]
80
+ @time = Time.new ('20' + b[12].to_s).to_i,
81
+ b[13],
82
+ b[14],
83
+ b[15],
84
+ b[16],
85
+ b[17]
86
+ @status = b[18]
87
+ @battery = d[19..20].unpack("v")[0]
88
+ end
89
+ end
90
+
91
+
92
+ ##
93
+ # Initializes a link between the the system and the device.
94
+ # used to transmit and recieive MicroAeth::Message
95
+ #
96
+ class Com
97
+ attr_accessor :com, :messages
98
+ attr_reader :com_thread
99
+
100
+ def initialize
101
+ port = '/dev/serial/by-id/usb-AethLabs_microAeth_Model_AE51_AE51-S4-649-1303-if00-port0'
102
+ baud = 500_000
103
+ bytesize = 8
104
+ stopbits = 1
105
+ parity = SerialPort::MARK
106
+ @com = SerialPort.new port, baud, bytesize, stopbits, parity
107
+ @messages = []
108
+ end
109
+
110
+ ###
111
+ # @m The message to be written
112
+ def write instruction
113
+ data = MicroAeth::Instruction::M + instruction
114
+ len = data.length.chr
115
+ crc = data ^ len
116
+ @com.write (MicroAeth::Instruction::STX + len + data + crc + MicroAeth::Instruction::ETX).force_encoding("ASCII-8BIT")
117
+ end
118
+
119
+ def erase_flash
120
+ begin
121
+ clear_buffer
122
+ write MicroAeth::Instruction::EraseFlash
123
+ Timeout::timeout(60) { wait_for_acknowledge }
124
+ sleep 45
125
+ Timeout::timeout(60) { wait_for_acknowledge }
126
+ write MicroAeth::Instruction::StartWrite
127
+ Timeout::timeout(60) { wait_for_acknowledge }
128
+ rescue Timeout::Error
129
+ retry
130
+ end
131
+ end
132
+ def clear_buffer
133
+ begin
134
+ while true
135
+ Timeout::timeout(0.5) { read_message }
136
+ end
137
+ rescue Timeout::Error
138
+ nil
139
+ end
140
+ end
141
+
142
+ def wait_for_acknowledge
143
+ while read_message != "\u0006AE5X:A\u0014".force_encoding("ASCII-8BIT")
144
+ nil
145
+ end
146
+ end
147
+
148
+ def start
149
+ puts "The MicroAeth is starting!.."
150
+ begin
151
+ clear_buffer
152
+ rescue [EOFError, Timeout::Error]
153
+ raise "Problem stating the MicroAeth"
154
+ end
155
+ end
156
+
157
+ ##
158
+ # @return A ruby thread which continually reads
159
+ # from the MicroAeth::Com#com instance
160
+ def read
161
+ @com_thread = Thread.new do
162
+ begin
163
+ while true
164
+ @messages << ( Message.new read_message )
165
+ end
166
+ # Intermitently, it the serialport library raises end of file...
167
+ rescue EOFError
168
+ sleep 1
169
+ retry
170
+ end
171
+ end
172
+ end
173
+
174
+ ###
175
+ # @file a ruby file object
176
+ def start_write_to_file file_name
177
+ @stop_writing_to_file = false
178
+ @thread = Thread.new do
179
+ clear_buffer
180
+ m_prev = nil
181
+ while @stop_writing_to_file != true
182
+ begin
183
+ m = Message.new read_message
184
+ rescue RuntimeError
185
+ retry
186
+ end
187
+ erase_flash if m.status == 64
188
+ atn = Math.log( m.ref.to_f / m.sen1.to_f) * 100
189
+ file = File.new file_name, 'a'
190
+ print message = [Time.now, m.ref, m.sen1, atn, m.flow, m.pcb_temp, m.status, m.battery, sigma_ap( m, m_prev)].join(',') + "\n"
191
+ file << message
192
+ file.close
193
+ m_prev = m
194
+ end
195
+ end
196
+ end
197
+ def stop_write_to_file
198
+ @stop_writing_to_file = true
199
+ @thread.join 30
200
+ end
201
+
202
+ def sigma_ap m, m_prev
203
+ if m_prev.nil?
204
+ "NaN"
205
+ else
206
+ Math::PI * (0.3 ** 2) / 4.0 / m.flow.to_f * 60.0 *
207
+ Math.log( m_prev.sen1.to_f / m.sen1.to_f * m.ref.to_f / m_prev.ref.to_f) * (10.0 ** 8)
208
+ end
209
+ end
210
+ def read_message
211
+ m, c = '',''
212
+ while c != "\x02"; c = @com.readchar; end
213
+ c = @com.readchar
214
+ m << c
215
+ len = c.byte
216
+ 0.upto len do |i|
217
+ c = @com.readchar
218
+ m << c
219
+ end
220
+ while c != "\x03"
221
+ c = @com.readchar
222
+ m << c
223
+ end
224
+ m[0..-2]
225
+ end
226
+ end
227
+ end
228
+
229
+ =begin
230
+ You'll need to assemble a properly formed message, or it won't respond.
231
+ ## Properly forming a messages as suggested by Karl Walter
232
+
233
+ Communication protocol is based on folowing syntax:
234
+ `STX LEN DATA CRC ETX` where:
235
+
236
+ * `STX` is one byte 0x02 (HEX values)
237
+ * `LEN` is one byte lenght of `DATA`
238
+ * `CRC` is XOR function between `LEN` byte and `DATA` bytes
239
+ * I'm assuming this is the last byte of data
240
+ * `ETX` is one byte 0x03
241
+
242
+ Every string of `DATA` that microAethCOM PC
243
+ software sends starts with `AE5X:` followed by one letter.
244
+
245
+ So you need to write some code to take the data you
246
+ want to send it, add the `STX` (`0x02`), calculate the
247
+ `LEN` and add it, Calculate the `CRC`, add that, then finally
248
+ add the `ETX` (`0x03`).
249
+
250
+ The `CRC` is always the hardest to get to work.
251
+ `CRC` is `XOR` function between `LEN` byte and `DATA` bytes.
252
+ http://en.wikipedia.org/wiki/Bitwise_operation#XOR
253
+ You'll probably have to make a best guess as how to `XOR` the `DATA` and `LEN`,
254
+ then try it on the messages that the MicroAeth sends, and see if you get the
255
+ `CRC` that it produced.
256
+
257
+ The `LEN` in the messages from it seemed like they where one longer than the
258
+ number of data bytes, so you'll have to experiment with that.
259
+
260
+ Also the `LEN` is only 1 byte, and the `DATA` can be any number, so I think you
261
+ are suppose to `XOR` the `LEN` with the first `DATA` byte, then take that and
262
+ XOR with the second, and so on, sort of like Xmodem. I'm not sure which is the
263
+ first `DATA` byte, though.
264
+
265
+ This may help: http://crcmod.sourceforge.net/crcmod.html
266
+
267
+ Also just google for `XOR CRC`, finds some good stuff like
268
+ [this](http://stackoverflow.com/questions/344961/how-do-you-compute-the-xor-remainder-used-in-crc)
269
+
270
+ You should also make sure that when you send /x02 that it sends 00000010 not
271
+
272
+ 01011100 01111000 00110000 00110010.
273
+
274
+ # from http://aethlabs.com/sites/all/content/microaeth/microAeth%20Model%20AE51%20Operating%20Manual.pdf
275
+ - Data(index)
276
+ - Data(index+1)
277
+ - Data(index+2)
278
+ - ‘Sen1
279
+ - Data(index+3)
280
+ - Data(index+4)
281
+ - Data(index+5)
282
+ - ‘Sen2
283
+ - Data(index+6)
284
+ - Data(index+7)
285
+ - Data(index+8)
286
+ - ‘Flow
287
+ - Data(index+9)
288
+ - Data(index+10)
289
+ - ‘PCBTemp
290
+ - Data(index+11)
291
+ - ‘Date
292
+ - Data(index+12)
293
+ - Data(index+13)
294
+ - Data(index+14)
295
+ - ‘Time
296
+ - Data(index+15)
297
+ - Data(index+16)
298
+ - Data(index+17)
299
+ - ‘Status
300
+ - Data(index+18)
301
+ - ‘Battery
302
+ - Data(index+19)
303
+ - Data(index+20)
304
+ - ‘Reserved forGPS etc...
305
+ - Data(index+21)
306
+ - Data(index+22)
307
+ - Data(index+23)
308
+ - Data(index+24)
309
+ - Data(index+25)
310
+ - Data(index+26)
311
+ - Data(index+27)
312
+ - Data(index+28)
313
+ - Data(index+29)
314
+ - Data(index+30)
315
+
316
+ Acknowledge: "\u0006AE5X:A\u0014"
317
+ =end
@@ -0,0 +1,8 @@
1
+ module MicroAethAE51
2
+ major = 0
3
+ minor = 0
4
+ tiny = 1
5
+ #pre = ""
6
+
7
+ VERSION = [major, minor, tiny].compact.join('.')
8
+ end
metadata ADDED
@@ -0,0 +1,92 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: micro_aeth-ae51-ruby
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Kurt R. Rudolph
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2013-10-10 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: serialport
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - '>='
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - '>='
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rspec
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ~>
32
+ - !ruby/object:Gem::Version
33
+ version: '2.8'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ~>
39
+ - !ruby/object:Gem::Version
40
+ version: '2.8'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rdoc
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ~>
46
+ - !ruby/object:Gem::Version
47
+ version: '3.2'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ~>
53
+ - !ruby/object:Gem::Version
54
+ version: '3.2'
55
+ description: This Gem provides and easy to use API for sending and receiving data
56
+ and commands for the microAeth model AE51. This library is not complete but encompasses
57
+ the most common commands for interfacing with the device.
58
+ email:
59
+ - kurt@rudycomputing.io
60
+ executables: []
61
+ extensions: []
62
+ extra_rdoc_files: []
63
+ files:
64
+ - lib/micro_aeth-ae51/version.rb
65
+ - lib/micro_aeth-ae51.rb
66
+ homepage: https://github.com/RudyComputing/microAeth-AE51-Ruby
67
+ licenses:
68
+ - MIT
69
+ metadata: {}
70
+ post_install_message:
71
+ rdoc_options: []
72
+ require_paths:
73
+ - lib
74
+ required_ruby_version: !ruby/object:Gem::Requirement
75
+ requirements:
76
+ - - '>='
77
+ - !ruby/object:Gem::Version
78
+ version: 2.0.0
79
+ required_rubygems_version: !ruby/object:Gem::Requirement
80
+ requirements:
81
+ - - '>='
82
+ - !ruby/object:Gem::Version
83
+ version: '0'
84
+ requirements:
85
+ - a microAeth model AE51
86
+ rubyforge_project:
87
+ rubygems_version: 2.0.3
88
+ signing_key:
89
+ specification_version: 4
90
+ summary: Ruby API for AethLabs microAeth&reg; model AE51
91
+ test_files: []
92
+ has_rdoc: