ruby_astm 1.4.3 → 1.4.4

Sign up to get free protection for your applications and to get access to all the features.
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