ruby_astm 1.4.3 → 1.4.4

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 3208653db9de63f83667dbcf80b25cd763f87ad9
4
- data.tar.gz: aca46de69ad6d8f2b35ff24ca9f594bd36b44bda
3
+ metadata.gz: 1edecd39318ba2231234a0bd46de36f2eded3843
4
+ data.tar.gz: c0da0a6d63ec31c478b083ecbf11c5772f709ab9
5
5
  SHA512:
6
- metadata.gz: f58e642661cef73d25e56c14f11498ca1cadddf1db76891336a394dd0d7331b9e421d4e0a87fa2ab875b886ad3ee0594e6a3acd9344c32ff87ae3afd8b8dba87
7
- data.tar.gz: 5dc55b42cb2de3c44abefc895af5a49798e89093157cb112f7d634e4d5ecf9419c9f4210b93b8b0b3352a18d330380e3d55251ffb0629da83ca849dff6d52d8e
6
+ metadata.gz: 2b4ad9ac1b9db8eedcddf90db7fb09a2b8868388f8268591b7273900e66f4baeebf447dc93ec4772398fd87928b5edf2f591d20d895daa12a5db16e7ace0d678
7
+ data.tar.gz: 72c2afa43a44ae1d6c20ea21e26e8d9ea3cd357495c291a08694fdc1d0f65289b23b5c0e5ec5b296bf9731ddc667bd6fb9aac8c849a0ed90c467cbf6b6fc9f0d
data/lib/ruby_astm.rb CHANGED
@@ -17,5 +17,6 @@ require_relative "ruby_astm/HL7/hl7_header"
17
17
  require_relative "ruby_astm/HL7/hl7_patient"
18
18
  require_relative "ruby_astm/HL7/hl7_order"
19
19
  require_relative "ruby_astm/HL7/hl7_observation"
20
+ require_relative "ruby_astm/custom/siemens_abg_electrolyte_module"
20
21
  require_relative "ruby_astm/custom/siemens_abg_electrolyte_server"
21
22
 
@@ -9,27 +9,6 @@ require "rest-firebase"
9
9
  class AstmServer
10
10
 
11
11
  include LabInterface
12
-
13
-
14
- def self.log(message)
15
- puts "" + message
16
- $redis.zadd("ruby_astm_log",Time.now.to_i,message)
17
- end
18
-
19
- def self.root_path
20
- File.dirname __dir__
21
- end
22
-
23
- def self.default_mappings
24
- File.join AstmServer.root_path,"mappings.json"
25
- end
26
-
27
- $ENQ = "[5]"
28
- $start_text = "[2]"
29
- $end_text = "[3]"
30
- $record_end = "[13]"
31
- $frame_end = "[10]"
32
-
33
12
 
34
13
  ## DEFAULT SERIAL PORT : /dev/ttyS0
35
14
  ## DEFAULT USB PORT : /dev/ttyUSB0
@@ -38,7 +17,7 @@ class AstmServer
38
17
  #def initialize(server_ip=nil,server_port=nil,mpg=nil,respond_to_queries=false,serial_port='/dev/ttyS0',usb_port='/dev/ttyUSB0',serial_baud=9600,serial_parity=8,usb_baud=19200,usb_parity=8)
39
18
  def initialize(ethernet_connections,serial_connections,mpg=nil,respond_to_queries=nil)
40
19
  $redis = Redis.new
41
- AstmServer.log("Initializing AstmServer")
20
+ self.class.log("Initializing AstmServer")
42
21
  self.ethernet_connections = ethernet_connections
43
22
  self.serial_connections = serial_connections
44
23
  self.server_ip = server_ip || "127.0.0.1"
@@ -50,7 +29,7 @@ class AstmServer
50
29
  self.usb_port = usb_port
51
30
  self.usb_baud = usb_baud
52
31
  self.usb_parity = usb_parity
53
- $mappings = JSON.parse(IO.read(mpg || AstmServer.default_mappings))
32
+ $mappings = JSON.parse(IO.read(mpg || self.class.default_mappings))
54
33
  end
55
34
 
56
35
  def start_server
@@ -59,7 +38,7 @@ class AstmServer
59
38
  raise "please provide a valid ethernet configuration with ip address" unless econn[:server_ip]
60
39
  raise "please provide a valid ethernet configuration with port" unless econn[:server_port]
61
40
  EventMachine::start_server econn[:server_ip], econn[:server_port], LabInterface
62
- AstmServer.log("Running ETHERNET with configuration #{econn}")
41
+ self.class.log("Running ETHERNET with configuration #{econn}")
63
42
  end
64
43
  self.serial_connections.each do |sconn|
65
44
  raise "please provide a valid serial configuration with port address" unless sconn[:port_address]
@@ -0,0 +1,322 @@
1
+ module SiemensAbgElectrolyteModule
2
+
3
+ include LabInterface
4
+
5
+ def self.included base
6
+ base.extend ClassMethods
7
+ end
8
+
9
+
10
+ SIEMENS_ELECTROLYTE_END = [10,10,10,10]
11
+ ELECTROLYTE_START = [45, 45, 45, 32]
12
+ attr_accessor :current_text_segment
13
+
14
+ def get_po2
15
+ m = []
16
+ self.current_text_segment.scan(/pO2\s+(?<k>(\d+)(\.\d)*)(\^|v)?\s+mmHg/) do |l|
17
+ n = Regexp.last_match
18
+ m << n[:k].to_s
19
+ end
20
+ raise "more than one result #{m.to_s}" if (m.size > 1)
21
+ return m[0] if m.size == 1
22
+ return nil
23
+ end
24
+
25
+ def get_pco2
26
+ m = []
27
+ self.current_text_segment.scan(/pCO2\s+(?<k>(\d+)(\.\d)*)(\^|v)?\s+mmHg/) do |l|
28
+ n = Regexp.last_match
29
+ m << n[:k].to_s
30
+ end
31
+ raise "more than one result #{m.to_s}" if (m.size > 1)
32
+ return m[0] if m.size == 1
33
+ return nil
34
+ end
35
+
36
+ def get_ph
37
+ m = []
38
+ self.current_text_segment.scan(/pH\s+(?<k>(\d+)[\.\d]*)(\^|v)?\s+$/) do |l|
39
+ n = Regexp.last_match
40
+ m << n[:k].to_s
41
+ end
42
+ raise "more than one result #{m.to_s}" if (m.size > 1)
43
+ return m[0] if m.size == 1
44
+ return nil
45
+ end
46
+
47
+ def get_na
48
+ m = []
49
+ self.current_text_segment.scan(/Na\+\s+(?<k>(\d+)[\.\d]*)(\^|v)?\s+mmol\/L/) do |l|
50
+ n = Regexp.last_match
51
+ m << n[:k].to_s
52
+ end
53
+ raise "more than one result #{m.to_s}" if (m.size > 1)
54
+ return m[0] if m.size == 1
55
+ return nil
56
+ end
57
+
58
+ def get_k
59
+ m = []
60
+ self.current_text_segment.scan(/K\+\s+(?<k>(\d+)[\.\d]*)(\^|v)?\s+mmol\/L/) do |l|
61
+ n = Regexp.last_match
62
+ m << n[:k].to_s
63
+ end
64
+ raise "more than one result #{m.to_s}" if (m.size > 1)
65
+ return m[0] if m.size == 1
66
+ return nil
67
+ end
68
+
69
+ def get_cl
70
+ m = []
71
+ self.current_text_segment.scan(/Cl\-\s+(?<k>(\d+)[\.\d]*)(\^|v)?\s+mmol\/L/) do |l|
72
+ n = Regexp.last_match
73
+ m << n[:k].to_s
74
+ end
75
+ raise "more than one result #{m.to_s}" if (m.size > 1)
76
+ return m[0] if m.size == 1
77
+ return nil
78
+ end
79
+
80
+ def get_patient_id
81
+ m = []
82
+ self.current_text_segment.scan(/Patient\s+ID\s+(?<k>\d+)$/) do |l|
83
+ n = Regexp.last_match
84
+ m << n[:k].to_s
85
+ end
86
+ raise "more than one result #{m.to_s}" if (m.size > 1)
87
+ return m[0] if m.size == 1
88
+ return nil
89
+ end
90
+
91
+ ## we override the lab interface methods
92
+ ## and we don't pollute the lab interface itself.
93
+ ## as this is a custom analyzer.
94
+ ## @param[Array] :
95
+ ## [[bytes],[bytes]....]
96
+ def process_electrolytes(data_bytes)
97
+ #puts "came to process electrolytes_plain_text"
98
+ byte_arr = data_bytes.flatten
99
+ #puts "the end part of the arr is"
100
+ return if byte_arr[-4..-1] != SIEMENS_ELECTROLYTE_END
101
+ self.data_bytes = []
102
+ concat = ""
103
+ byte_arr.each do |byte|
104
+ x = [byte].pack('c*').force_encoding('UTF-8')
105
+ if x == "\r"
106
+ concat+="\n"
107
+ elsif x == "\n"
108
+ #puts "new line found --- "
109
+ concat+=x
110
+ #puts "last thing in concat."
111
+ #puts concat[-1].to_s
112
+ else
113
+ concat+=x
114
+ end
115
+ end
116
+
117
+ self.headers ||= [Header.new]
118
+ concat.split("--------------------------------").each do |record|
119
+
120
+ self.current_text_segment = record
121
+ if patient_id = get_patient_id
122
+ self.headers[-1].patients ||= []
123
+ p = Patient.new
124
+ p.patient_id = patient_id
125
+ p.orders ||= []
126
+ o = Order.new
127
+ o.results ||= {}
128
+ if sodium = get_na
129
+ r = Result.new
130
+ r.name = "SNATRIUM"
131
+ r.report_name = "Serum Electrolytes"
132
+ r.value = sodium
133
+ r.units = "mmol/L"
134
+ r.timestamp = Time.now.to_i
135
+ o.results["SNATRIUM"] = r
136
+ end
137
+
138
+ if potassium = get_k
139
+ r = Result.new
140
+ r.name = "SPOTASSIUM"
141
+ r.report_name = "Serum Electrolytes"
142
+ r.value = potassium
143
+ r.units = "mmol/L"
144
+ r.timestamp = Time.now.to_i
145
+ o.results["SPOTASSIUM"] = r
146
+ end
147
+
148
+ if chloride = get_cl
149
+ r = Result.new
150
+ r.name = "SCHLORIDE"
151
+ r.report_name = "Serum Electrolytes"
152
+ r.value = chloride
153
+ r.units = "mmol/L"
154
+ r.timestamp = Time.now.to_i
155
+ o.results["SCHLORIDE"] = r
156
+ end
157
+
158
+ if ph = get_ph
159
+ r = Result.new
160
+ r.name = "pH"
161
+ r.report_name = "Serum Electrolytes"
162
+ r.value = ph
163
+ r.units = "mmol/L"
164
+ r.timestamp = Time.now.to_i
165
+ o.results["pH"] = r
166
+ end
167
+
168
+ if po2 = get_po2
169
+ r = Result.new
170
+ r.name = "po2"
171
+ r.report_name = "Serum Electrolytes"
172
+ r.value = po2
173
+ r.units = "mmHg"
174
+ r.timestamp = Time.now.to_i
175
+ o.results["po2"] = r
176
+ end
177
+
178
+ if pco2 = get_pco2
179
+ r = Result.new
180
+ r.name = "pco2"
181
+ r.report_name = "Serum Electrolytes"
182
+ r.value = pco2
183
+ r.units = "mmHg"
184
+ r.timestamp = Time.now.to_i
185
+ o.results["pco2"] = r
186
+ end
187
+
188
+ p.orders << o
189
+ self.headers[-1].patients << p
190
+ end
191
+ end
192
+
193
+ end
194
+
195
+ def process_text_file(full_file_path)
196
+ k = IO.read(full_file_path)
197
+ process_electrolytes(k.bytes)
198
+ end
199
+
200
+
201
+ def receive_data(data)
202
+
203
+
204
+ begin
205
+
206
+
207
+ self.data_buffer ||= ''
208
+
209
+ concat = ""
210
+
211
+ byte_arr = data.bytes.to_a
212
+
213
+ self.test_data_bytes ||= []
214
+
215
+ self.data_bytes ||= []
216
+
217
+ self.test_data_bytes.push(byte_arr)
218
+
219
+ self.data_bytes.push(byte_arr)
220
+
221
+
222
+ concat = pre_process_bytes(byte_arr,concat)
223
+
224
+ #puts "concat is:"
225
+
226
+ #puts concat.to_s
227
+
228
+ self.data_buffer << concat
229
+
230
+ ## if the last byte is EOT, then call process text.
231
+ ## inside that split by line and process one at a time.
232
+ ##process_text(concat)
233
+ #puts "data bytes -1: #{self.data_bytes[-1]}"
234
+ #puts "data bytes 0: #{self.data_bytes[0]}"
235
+ #if self.data_bytes[0] == ELECTROLYTE_START
236
+ self.process_electrolytes(self.data_bytes)
237
+ #end
238
+ =begin
239
+ if data.bytes.to_a[-1] == 4
240
+ puts "GOT EOT --- PROCESSING BUFFER, AND CLEARING."
241
+ process_text(self.data_buffer)
242
+ #root_path = File.dirname __dir
243
+ #puts "root path #{root_path}"
244
+ #IO.write((File.join root_path,'test','resources','roche_multi_frame_bytes.txt'),self.test_data_bytes.to_s)
245
+ #puts self.test_data_bytes.flatten.to_s
246
+ self.data_buffer = ''
247
+ unless self.headers.blank?
248
+ if self.headers[-1].queries.blank?
249
+ #puts "no queries in header so sending ack after getting EOT and processing the buffer"
250
+ send_data(ACK)
251
+ else
252
+ #puts "sending ENQ"
253
+ send_data(ENQ)
254
+ end
255
+ else
256
+ puts "sending catch all --------------- ACK --------------"
257
+ send_data(ACK)
258
+ end
259
+ elsif data.bytes.to_a[0] == 6
260
+ puts "GOT ACK --- GENERATING RESPONSE"
261
+ unless self.headers.blank?
262
+ header_responses = self.headers[-1].build_one_response({machine_name: self.headers[-1].machine_name})
263
+ ## if no queries then, we have to send ack.
264
+ if header_responses.blank?
265
+ #puts "sending ACK since there are no queries in the header"
266
+ send_data(ACK)
267
+ end
268
+ header_responses.each_with_index {|response,key|
269
+ message_checksum = checksum(response + terminator + ETX)
270
+ final_resp = STX + response + terminator + ETX + message_checksum + "\r"
271
+ final_resp_arr = final_resp.bytes.to_a
272
+ final_resp_arr << 10
273
+ if (self.headers[-1].response_sent == false)
274
+ #puts "sending the data as follows----------------------------------------------"
275
+ #puts "response sent is:"
276
+ #puts self.headers[-1].response_sent
277
+ #puts final_resp_arr.pack('c*').gsub(/\r/,'\n')
278
+ send_data(final_resp_arr.pack('c*'))
279
+ self.headers[-1].response_sent = true if (key == (header_responses.size - 1))
280
+ else
281
+ #puts "sending EOT"
282
+ send_data(EOT)
283
+ end
284
+ }
285
+ else
286
+ #puts "NO HEADERS PRESENT --- "
287
+ end
288
+ elsif data.bytes.to_a[0] == 255
289
+ puts " ----------- got 255 data -----------, not sending anything back. "
290
+ else
291
+ #unless self.data_buffer.blank?
292
+ # puts self.data_buffer.gsub(/\r/,'\n').to_s
293
+ #end
294
+ ## send the header
295
+ #puts "--------- SENT ACK -----------"
296
+ ## strip non utf 8 characters from it.
297
+ self.data_buffer.encode!('UTF-8', 'binary', invalid: :replace, undef: :replace, replace: '')
298
+ if self.data_buffer =~ /MSH\|/
299
+ #puts " -------------- HEADERS ARE BLANK WITH HL7, sending ack. ------------ "
300
+ process_text(self.data_buffer)
301
+ self.data_buffer = ''
302
+ if self.headers.size > 0
303
+ self.headers[-1].commit
304
+ send_data(self.headers[-1].generate_ack_success_response)
305
+ end
306
+ else
307
+ #puts " -------------- HEADERS ARE BLANK NOT HL7, sending ack. ------------ "
308
+ send_data(ACK)
309
+ end
310
+ end
311
+ =end
312
+ rescue => e
313
+
314
+ #self.headers = []
315
+ AstmServer.log("data was: " + self.data_buffer + "error is:" + e.backtrace.to_s)
316
+ #send_data(EOT)
317
+ end
318
+
319
+ end
320
+
321
+
322
+ end
@@ -1,315 +1,46 @@
1
- class SiemensAbgElectrolyteServer < AstmServer
2
-
3
- SIEMENS_ELECTROLYTE_END = [10,10,10,10]
4
- ELECTROLYTE_START = [45, 45, 45, 32]
5
- attr_accessor :current_text_segment
6
-
7
- def get_po2
8
- m = []
9
- self.current_text_segment.scan(/pO2\s+(?<k>(\d+)(\.\d)*)(\^|v)?\s+mmHg/) do |l|
10
- n = Regexp.last_match
11
- m << n[:k].to_s
12
- end
13
- raise "more than one result #{m.to_s}" if (m.size > 1)
14
- return m[0] if m.size == 1
15
- return nil
16
- end
17
-
18
- def get_pco2
19
- m = []
20
- self.current_text_segment.scan(/pCO2\s+(?<k>(\d+)(\.\d)*)(\^|v)?\s+mmHg/) do |l|
21
- n = Regexp.last_match
22
- m << n[:k].to_s
23
- end
24
- raise "more than one result #{m.to_s}" if (m.size > 1)
25
- return m[0] if m.size == 1
26
- return nil
27
- end
28
-
29
- def get_ph
30
- m = []
31
- self.current_text_segment.scan(/pH\s+(?<k>(\d+)[\.\d]*)(\^|v)?\s+$/) do |l|
32
- n = Regexp.last_match
33
- m << n[:k].to_s
34
- end
35
- raise "more than one result #{m.to_s}" if (m.size > 1)
36
- return m[0] if m.size == 1
37
- return nil
38
- end
39
-
40
- def get_na
41
- m = []
42
- self.current_text_segment.scan(/Na\+\s+(?<k>(\d+)[\.\d]*)(\^|v)?\s+mmol\/L/) do |l|
43
- n = Regexp.last_match
44
- m << n[:k].to_s
45
- end
46
- raise "more than one result #{m.to_s}" if (m.size > 1)
47
- return m[0] if m.size == 1
48
- return nil
49
- end
50
-
51
- def get_k
52
- m = []
53
- self.current_text_segment.scan(/K\+\s+(?<k>(\d+)[\.\d]*)(\^|v)?\s+mmol\/L/) do |l|
54
- n = Regexp.last_match
55
- m << n[:k].to_s
56
- end
57
- raise "more than one result #{m.to_s}" if (m.size > 1)
58
- return m[0] if m.size == 1
59
- return nil
60
- end
61
-
62
- def get_cl
63
- m = []
64
- self.current_text_segment.scan(/Cl\-\s+(?<k>(\d+)[\.\d]*)(\^|v)?\s+mmol\/L/) do |l|
65
- n = Regexp.last_match
66
- m << n[:k].to_s
67
- end
68
- raise "more than one result #{m.to_s}" if (m.size > 1)
69
- return m[0] if m.size == 1
70
- return nil
71
- end
72
-
73
- def get_patient_id
74
- m = []
75
- self.current_text_segment.scan(/Patient\s+ID\s+(?<k>\d+)$/) do |l|
76
- n = Regexp.last_match
77
- m << n[:k].to_s
78
- end
79
- raise "more than one result #{m.to_s}" if (m.size > 1)
80
- return m[0] if m.size == 1
81
- return nil
82
- end
83
-
84
- ## we override the lab interface methods
85
- ## and we don't pollute the lab interface itself.
86
- ## as this is a custom analyzer.
87
- ## @param[Array] :
88
- ## [[bytes],[bytes]....]
89
- def process_electrolytes(data_bytes)
90
- #puts "came to process electrolytes_plain_text"
91
- byte_arr = data_bytes.flatten
92
- #puts "the end part of the arr is"
93
- return if byte_arr[-4..-1] != SIEMENS_ELECTROLYTE_END
94
- self.data_bytes = []
95
- concat = ""
96
- byte_arr.each do |byte|
97
- x = [byte].pack('c*').force_encoding('UTF-8')
98
- if x == "\r"
99
- concat+="\n"
100
- elsif x == "\n"
101
- #puts "new line found --- "
102
- concat+=x
103
- #puts "last thing in concat."
104
- #puts concat[-1].to_s
105
- else
106
- concat+=x
107
- end
108
- end
109
-
110
- self.headers ||= [Header.new]
111
- concat.split("--------------------------------").each do |record|
112
-
113
- self.current_text_segment = record
114
- if patient_id = get_patient_id
115
- self.headers[-1].patients ||= []
116
- p = Patient.new
117
- p.patient_id = patient_id
118
- p.orders ||= []
119
- o = Order.new
120
- o.results ||= {}
121
- if sodium = get_na
122
- r = Result.new
123
- r.name = "SNATRIUM"
124
- r.report_name = "Serum Electrolytes"
125
- r.value = sodium
126
- r.units = "mmol/L"
127
- r.timestamp = Time.now.to_i
128
- o.results["SNATRIUM"] = r
129
- end
130
-
131
- if potassium = get_k
132
- r = Result.new
133
- r.name = "SPOTASSIUM"
134
- r.report_name = "Serum Electrolytes"
135
- r.value = potassium
136
- r.units = "mmol/L"
137
- r.timestamp = Time.now.to_i
138
- o.results["SPOTASSIUM"] = r
139
- end
140
-
141
- if chloride = get_cl
142
- r = Result.new
143
- r.name = "SCHLORIDE"
144
- r.report_name = "Serum Electrolytes"
145
- r.value = chloride
146
- r.units = "mmol/L"
147
- r.timestamp = Time.now.to_i
148
- o.results["SCHLORIDE"] = r
149
- end
150
-
151
- if ph = get_ph
152
- r = Result.new
153
- r.name = "pH"
154
- r.report_name = "Serum Electrolytes"
155
- r.value = ph
156
- r.units = "mmol/L"
157
- r.timestamp = Time.now.to_i
158
- o.results["pH"] = r
159
- end
160
-
161
- if po2 = get_po2
162
- r = Result.new
163
- r.name = "po2"
164
- r.report_name = "Serum Electrolytes"
165
- r.value = po2
166
- r.units = "mmHg"
167
- r.timestamp = Time.now.to_i
168
- o.results["po2"] = r
169
- end
170
-
171
- if pco2 = get_pco2
172
- r = Result.new
173
- r.name = "pco2"
174
- r.report_name = "Serum Electrolytes"
175
- r.value = pco2
176
- r.units = "mmHg"
177
- r.timestamp = Time.now.to_i
178
- o.results["pco2"] = r
179
- end
180
-
181
- p.orders << o
182
- self.headers[-1].patients << p
183
- end
184
- end
185
-
186
- end
187
-
188
- def process_text_file(full_file_path)
189
- k = IO.read(full_file_path)
190
- process_electrolytes(k.bytes)
191
- end
192
-
193
-
194
- def receive_data(data)
195
-
196
-
197
- begin
198
-
199
-
200
- self.data_buffer ||= ''
201
-
202
- concat = ""
203
-
204
- byte_arr = data.bytes.to_a
205
-
206
- self.test_data_bytes ||= []
207
-
208
- self.data_bytes ||= []
209
-
210
- self.test_data_bytes.push(byte_arr)
211
-
212
- self.data_bytes.push(byte_arr)
213
-
214
-
215
- concat = pre_process_bytes(byte_arr,concat)
216
-
217
- #puts "concat is:"
218
-
219
- #puts concat.to_s
220
-
221
- self.data_buffer << concat
222
-
223
- ## if the last byte is EOT, then call process text.
224
- ## inside that split by line and process one at a time.
225
- ##process_text(concat)
226
- #puts "data bytes -1: #{self.data_bytes[-1]}"
227
- #puts "data bytes 0: #{self.data_bytes[0]}"
228
- #if self.data_bytes[0] == ELECTROLYTE_START
229
- self.process_electrolytes(self.data_bytes)
230
- #end
231
- =begin
232
- if data.bytes.to_a[-1] == 4
233
- puts "GOT EOT --- PROCESSING BUFFER, AND CLEARING."
234
- process_text(self.data_buffer)
235
- #root_path = File.dirname __dir
236
- #puts "root path #{root_path}"
237
- #IO.write((File.join root_path,'test','resources','roche_multi_frame_bytes.txt'),self.test_data_bytes.to_s)
238
- #puts self.test_data_bytes.flatten.to_s
239
- self.data_buffer = ''
240
- unless self.headers.blank?
241
- if self.headers[-1].queries.blank?
242
- #puts "no queries in header so sending ack after getting EOT and processing the buffer"
243
- send_data(ACK)
244
- else
245
- #puts "sending ENQ"
246
- send_data(ENQ)
247
- end
248
- else
249
- puts "sending catch all --------------- ACK --------------"
250
- send_data(ACK)
251
- end
252
- elsif data.bytes.to_a[0] == 6
253
- puts "GOT ACK --- GENERATING RESPONSE"
254
- unless self.headers.blank?
255
- header_responses = self.headers[-1].build_one_response({machine_name: self.headers[-1].machine_name})
256
- ## if no queries then, we have to send ack.
257
- if header_responses.blank?
258
- #puts "sending ACK since there are no queries in the header"
259
- send_data(ACK)
260
- end
261
- header_responses.each_with_index {|response,key|
262
- message_checksum = checksum(response + terminator + ETX)
263
- final_resp = STX + response + terminator + ETX + message_checksum + "\r"
264
- final_resp_arr = final_resp.bytes.to_a
265
- final_resp_arr << 10
266
- if (self.headers[-1].response_sent == false)
267
- #puts "sending the data as follows----------------------------------------------"
268
- #puts "response sent is:"
269
- #puts self.headers[-1].response_sent
270
- #puts final_resp_arr.pack('c*').gsub(/\r/,'\n')
271
- send_data(final_resp_arr.pack('c*'))
272
- self.headers[-1].response_sent = true if (key == (header_responses.size - 1))
273
- else
274
- #puts "sending EOT"
275
- send_data(EOT)
276
- end
277
- }
278
- else
279
- #puts "NO HEADERS PRESENT --- "
280
- end
281
- elsif data.bytes.to_a[0] == 255
282
- puts " ----------- got 255 data -----------, not sending anything back. "
283
- else
284
- #unless self.data_buffer.blank?
285
- # puts self.data_buffer.gsub(/\r/,'\n').to_s
286
- #end
287
- ## send the header
288
- #puts "--------- SENT ACK -----------"
289
- ## strip non utf 8 characters from it.
290
- self.data_buffer.encode!('UTF-8', 'binary', invalid: :replace, undef: :replace, replace: '')
291
- if self.data_buffer =~ /MSH\|/
292
- #puts " -------------- HEADERS ARE BLANK WITH HL7, sending ack. ------------ "
293
- process_text(self.data_buffer)
294
- self.data_buffer = ''
295
- if self.headers.size > 0
296
- self.headers[-1].commit
297
- send_data(self.headers[-1].generate_ack_success_response)
298
- end
299
- else
300
- #puts " -------------- HEADERS ARE BLANK NOT HL7, sending ack. ------------ "
301
- send_data(ACK)
302
- end
303
- end
304
- =end
305
- rescue => e
306
-
307
- #self.headers = []
308
- AstmServer.log("data was: " + self.data_buffer + "error is:" + e.backtrace.to_s)
309
- #send_data(EOT)
310
- end
311
-
312
- end
313
-
1
+ class SiemensAbgElectrolyteServer
2
+
3
+ include SiemensAbgElectrolyteModule
4
+
5
+ ## DEFAULT SERIAL PORT : /dev/ttyS0
6
+ ## DEFAULT USB PORT : /dev/ttyUSB0
7
+ ## @param[Array] ethernet_connections : each element is expected to be a hash, with keys for :server_ip, :server_port.
8
+ ## @param[Array] serial_connections : each element is expected to be a hash with port_address, baud_rate, and parity
9
+ #def initialize(server_ip=nil,server_port=nil,mpg=nil,respond_to_queries=false,serial_port='/dev/ttyS0',usb_port='/dev/ttyUSB0',serial_baud=9600,serial_parity=8,usb_baud=19200,usb_parity=8)
10
+ def initialize(ethernet_connections,serial_connections,mpg=nil,respond_to_queries=nil)
11
+ $redis = Redis.new
12
+ self.class.log("Initializing AstmServer")
13
+ self.ethernet_connections = ethernet_connections
14
+ self.serial_connections = serial_connections
15
+ self.server_ip = server_ip || "127.0.0.1"
16
+ self.server_port = server_port || 3000
17
+ self.respond_to_queries = respond_to_queries
18
+ self.serial_port = serial_port
19
+ self.serial_baud = serial_baud
20
+ self.serial_parity = serial_parity
21
+ self.usb_port = usb_port
22
+ self.usb_baud = usb_baud
23
+ self.usb_parity = usb_parity
24
+ $mappings = JSON.parse(IO.read(mpg || self.class.default_mappings))
25
+ end
26
+
27
+ def start_server
28
+ EventMachine.run {
29
+ self.ethernet_connections.each do |econn|
30
+ raise "please provide a valid ethernet configuration with ip address" unless econn[:server_ip]
31
+ raise "please provide a valid ethernet configuration with port" unless econn[:server_port]
32
+ EventMachine::start_server econn[:server_ip], econn[:server_port], SiemensAbgElectrolyteModule
33
+ self.class.log("Running ETHERNET with configuration #{econn}")
34
+ end
35
+ self.serial_connections.each do |sconn|
36
+ raise "please provide a valid serial configuration with port address" unless sconn[:port_address]
37
+ raise "please provide a valid serial configuration with baud rate" unless sconn[:baud_rate]
38
+ raise "please provide a valid serial configuration with parity" unless sconn[:parity]
39
+ EventMachine.open_serial(sconn[:port_address], sconn[:baud_rate], sconn[:parity],SiemensAbgElectrolyteModule)
40
+ puts "RUNNING SERIAL port with configuration : #{sconn}"
41
+ end
42
+
43
+ }
44
+ end
314
45
 
315
46
  end
@@ -2,6 +2,10 @@ require "active_support/all"
2
2
 
3
3
  module LabInterface
4
4
 
5
+ def self.included base
6
+ base.extend ClassMethods
7
+ end
8
+
5
9
  ACK = "\x06"
6
10
  ENQ = "\x05"
7
11
  STX = "\x02"
@@ -13,7 +17,6 @@ module LabInterface
13
17
 
14
18
  attr_accessor :ethernet_connections
15
19
  attr_accessor :serial_connections
16
-
17
20
  attr_accessor :ethernet_server
18
21
  attr_accessor :server_ip
19
22
  attr_accessor :server_port
@@ -38,7 +41,37 @@ module LabInterface
38
41
 
39
42
  ## buffer of incoming data.
40
43
  attr_accessor :data_buffer
44
+
45
+ $ENQ = "[5]"
46
+ $start_text = "[2]"
47
+ $end_text = "[3]"
48
+ $record_end = "[13]"
49
+ $frame_end = "[10]"
50
+
41
51
 
52
+ #######################################################
53
+ ##
54
+ ##
55
+ ##
56
+ ## CLASS METHODS
57
+ ##
58
+ ##
59
+ ##
60
+ #######################################################
61
+ module ClassMethods
62
+ def log(message)
63
+ puts "" + message
64
+ $redis.zadd("ruby_astm_log",Time.now.to_i,message)
65
+ end
66
+
67
+ def root_path
68
+ File.dirname __dir__
69
+ end
70
+
71
+ def default_mappings
72
+ File.join root_path,"mappings.json"
73
+ end
74
+ end
42
75
 
43
76
  ## returns the root directory of the gem.
44
77
  def root
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ruby_astm
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.4.3
4
+ version: 1.4.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Bhargav Raut
@@ -155,6 +155,7 @@ files:
155
155
  - lib/ruby_astm/HL7/hl7_order.rb
156
156
  - lib/ruby_astm/HL7/hl7_patient.rb
157
157
  - lib/ruby_astm/astm_server.rb
158
+ - lib/ruby_astm/custom/siemens_abg_electrolyte_module.rb
158
159
  - lib/ruby_astm/custom/siemens_abg_electrolyte_server.rb
159
160
  - lib/ruby_astm/frame.rb
160
161
  - lib/ruby_astm/header.rb