lis 0.2.2 → 0.2.3

Sign up to get free protection for your applications and to get access to all the features.
data/features/lis.feature CHANGED
@@ -7,7 +7,7 @@ Feature:
7
7
  Given LIS Interface listening for messages
8
8
  And the following requests are pending for DPC:
9
9
  | id | patient_id | last_name | first_name | test_names |
10
- | 123ABC | 98 | Sierra | Rudolph | TSH, FT3, FT4, FOO, BAR, BAZ |
10
+ | 123ABC | 98 | Müller | Rudolph | TSH, FT3, FT4, FOO, BAR, BAZ |
11
11
  When receiving data
12
12
  """
13
13
  1H|\^&||PASSWORD|DPC||Randolph^New^Jersey^07869||(201)927-2828|N81|Your System||P|1|19940407120613 51
@@ -17,7 +17,7 @@ Feature:
17
17
  Then LIS should have sent test orders to client:
18
18
  """
19
19
  1H|\^&|||LIS||||8N1|DPC||P|1|
20
- 2P|1||||Sierra^Rudolph||||||||
20
+ 2P|1||||Müller^Rudolph||||||||
21
21
  3O|1|123ABC||^^^TSH
22
22
  4O|1|123ABC||^^^FT3
23
23
  5O|1|123ABC||^^^FT4
@@ -1,3 +1,5 @@
1
+ # encoding: UTF-8
2
+
1
3
  require 'mocha'
2
4
  require 'yaml'
3
5
 
@@ -8,7 +10,7 @@ Given /^LIS Interface listening for messages$/ do
8
10
  @server = LIS::InterfaceServer.create(@io, "http://localhost/lis/")
9
11
 
10
12
  stub_request(:post, /http:\/\/localhost\/lis\/result\/.*/).
11
- with(:body => /.*/, :headers => {'Accept'=>'*/*', 'Content-Type'=>'application/x-www-form-urlencoded', 'User-Agent'=>'Ruby'}).
13
+ with(:body => /.*/, :headers => {'Accept'=>'*/*', 'Content-Type'=>'application/x-www-form-urlencoded'}).
12
14
  to_return(:status => 200, :body => "", :headers => {})
13
15
 
14
16
  @t = Thread.new do
@@ -49,17 +51,14 @@ end
49
51
  #
50
52
  Given /^the following requests are pending for (\w+):$/ do |device_name, table|
51
53
  table.hashes.each do |patient|
52
- p patient
53
-
54
54
  body = { "patient" => { "last_name" => patient["last_name"],
55
55
  "first_name" => patient["first_name"],
56
56
  "id" => patient["patient_id"]},
57
57
  "id" => patient["id"],
58
58
  "types" => patient["test_names"].strip.split(/\s+/) }
59
- p body
60
59
 
61
60
  stub_request(:get, "http://localhost/lis/find_requests/#{device_name}-#{patient["id"]}").
62
- with(:headers => {'Accept'=>'*/*', 'User-Agent'=>'Ruby'}).
61
+ with(:headers => {'Accept'=>'*/*'}).
63
62
  to_return(:status => 200, :body => body.to_yaml, :headers => {})
64
63
 
65
64
  end
@@ -69,11 +68,14 @@ end
69
68
 
70
69
  Then /^LIS should have sent test orders to client:$/ do |text|
71
70
  @data = @client.read_all
71
+ @data.force_encoding("utf-8") if @data.respond_to?(:force_encoding)
72
72
  @packets = @data.split("\002").select { |s| s =~ /^\d[A-Z]/ }
73
- @packets.zip(text.lines) do |actual, expected|
73
+ @packets.zip(text.split(/\n/)) do |actual, expected|
74
+ @called = true
74
75
  rx = Regexp.new("^" + Regexp.escape(expected.strip))
75
76
  assert_match(rx, actual.gsub(/\r\003.*$/, "").strip)
76
77
  end
78
+ assert_equal(true, @called)
77
79
  end
78
80
 
79
81
 
@@ -1,3 +1,5 @@
1
+ # encoding: UTF-8
2
+
1
3
  require 'optparse'
2
4
 
3
5
  module LIS
@@ -1,3 +1,5 @@
1
+ # encoding: UTF-8
2
+
1
3
  module LIS::Message
2
4
 
3
5
  # = Comment Message
@@ -1,3 +1,5 @@
1
+ # encoding: UTF-8
2
+
1
3
  module LIS::Message
2
4
 
3
5
  # = Header Message
@@ -1,3 +1,5 @@
1
+ # encoding: UTF-8
2
+
1
3
  module LIS::Message
2
4
 
3
5
  # = Order Message
@@ -1,3 +1,5 @@
1
+ # encoding: UTF-8
2
+
1
3
  module LIS::Message
2
4
 
3
5
  # = Patient Message
@@ -72,7 +74,7 @@ module LIS::Message
72
74
  self.sequence_number = sequence_number
73
75
  self.practice_assigned_patient_id = patient_id
74
76
  self.patient_id = patient_id
75
- self.name = [last_name.force_encoding("UTF-8"), first_name.force_encoding("UTF-8")].join("^")
77
+ self.name = [last_name, first_name].join("^")
76
78
  end
77
79
 
78
80
  end
@@ -1,3 +1,5 @@
1
+ # encoding: UTF-8
2
+
1
3
  module LIS::Message
2
4
 
3
5
  # = Query Message
@@ -1,3 +1,5 @@
1
+ # encoding: UTF-8
2
+
1
3
  module LIS::Message
2
4
 
3
5
  # = Result Message
@@ -1,3 +1,5 @@
1
+ # encoding: UTF-8
2
+
1
3
  module LIS::Message
2
4
 
3
5
  # = Terminator Message
data/lib/lis/messages.rb CHANGED
@@ -1,3 +1,5 @@
1
+ # encoding: UTF-8
2
+
1
3
  require 'date'
2
4
 
3
5
  module LIS::Message
@@ -1,3 +1,4 @@
1
+ # encoding: UTF-8
1
2
 
2
3
  module LIS::Transfer
3
4
  class ApplicationProtocol < ::PacketIO::Base
@@ -1,3 +1,5 @@
1
+ # encoding: UTF-8
2
+
1
3
  module LIS::Transfer
2
4
 
3
5
  module ASTM
@@ -34,14 +36,14 @@ module LIS::Transfer
34
36
 
35
37
  def initialize(*args)
36
38
  super(*args)
37
- @memo = ""
39
+ @data = StringScanner.new("")
38
40
  @inside_transmission = false
39
41
  end
40
42
 
41
43
  def receive(data)
42
- scanner = StringScanner.new(@memo + data)
43
- while scanner.scan_until(RX)
44
- match = scanner.matched
44
+ @data.concat(data)
45
+ while @data.scan_until(RX)
46
+ match = @data.matched
45
47
  case match
46
48
  when ENQ then transmission_start
47
49
  when EOT then transmission_end
@@ -51,7 +53,6 @@ module LIS::Transfer
51
53
  write :ack
52
54
  end
53
55
  end
54
- @memo = scanner.rest
55
56
  nil
56
57
  end
57
58
 
data/lib/lis/version.rb CHANGED
@@ -1,4 +1,6 @@
1
+ # encoding: UTF-8
2
+
1
3
  module LIS
2
- VERSION = "0.2.2"
4
+ VERSION = "0.2.3"
3
5
  end
4
6
 
@@ -1,3 +1,5 @@
1
+ # encoding: UTF-8
2
+
1
3
  require 'net/http'
2
4
  require 'yaml'
3
5
 
data/lis.gemspec CHANGED
@@ -20,12 +20,12 @@ Gem::Specification.new do |s|
20
20
  s.require_paths = ["lib"]
21
21
  s.summary = %q{LIS interface to Siemens Immulite 2000XPi or other similar analyzers}
22
22
 
23
- s.add_dependency "packet_io", "~> 0.4.0.rc4"
23
+ s.add_dependency "packet_io", "~> 0.4.0"
24
24
 
25
- s.add_development_dependency("shoulda", ["~> 2.11.3"])
26
- s.add_development_dependency("mocha", ["~> 0.9.12"])
27
- s.add_development_dependency("yard", ["~> 0.7.1"])
28
- s.add_development_dependency("cucumber", ["~> 0.10.3"])
29
- s.add_development_dependency("webmock")
25
+ s.add_development_dependency("shoulda", "~> 2.11.3")
26
+ s.add_development_dependency("mocha", "~> 0.9.12")
27
+ s.add_development_dependency("yard", "~> 0.7.1")
28
+ s.add_development_dependency("cucumber", "~> 0.10.3")
29
+ s.add_development_dependency("webmock", "~> 1.6.4")
30
30
  end
31
31
 
metadata CHANGED
@@ -1,12 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: lis
3
3
  version: !ruby/object:Gem::Version
4
+ hash: 17
4
5
  prerelease: false
5
6
  segments:
6
7
  - 0
7
8
  - 2
8
- - 2
9
- version: 0.2.2
9
+ - 3
10
+ version: 0.2.3
10
11
  platform: ruby
11
12
  authors:
12
13
  - Levin Alexander
@@ -14,7 +15,7 @@ autorequire:
14
15
  bindir: bin
15
16
  cert_chain: []
16
17
 
17
- date: 2011-06-01 00:00:00 +02:00
18
+ date: 2011-06-11 00:00:00 +02:00
18
19
  default_executable:
19
20
  dependencies:
20
21
  - !ruby/object:Gem::Dependency
@@ -25,12 +26,12 @@ dependencies:
25
26
  requirements:
26
27
  - - ~>
27
28
  - !ruby/object:Gem::Version
29
+ hash: 15
28
30
  segments:
29
31
  - 0
30
32
  - 4
31
33
  - 0
32
- - rc4
33
- version: 0.4.0.rc4
34
+ version: 0.4.0
34
35
  type: :runtime
35
36
  version_requirements: *id001
36
37
  - !ruby/object:Gem::Dependency
@@ -41,6 +42,7 @@ dependencies:
41
42
  requirements:
42
43
  - - ~>
43
44
  - !ruby/object:Gem::Version
45
+ hash: 37
44
46
  segments:
45
47
  - 2
46
48
  - 11
@@ -56,6 +58,7 @@ dependencies:
56
58
  requirements:
57
59
  - - ~>
58
60
  - !ruby/object:Gem::Version
61
+ hash: 35
59
62
  segments:
60
63
  - 0
61
64
  - 9
@@ -71,6 +74,7 @@ dependencies:
71
74
  requirements:
72
75
  - - ~>
73
76
  - !ruby/object:Gem::Version
77
+ hash: 1
74
78
  segments:
75
79
  - 0
76
80
  - 7
@@ -86,6 +90,7 @@ dependencies:
86
90
  requirements:
87
91
  - - ~>
88
92
  - !ruby/object:Gem::Version
93
+ hash: 49
89
94
  segments:
90
95
  - 0
91
96
  - 10
@@ -99,11 +104,14 @@ dependencies:
99
104
  requirement: &id006 !ruby/object:Gem::Requirement
100
105
  none: false
101
106
  requirements:
102
- - - ">="
107
+ - - ~>
103
108
  - !ruby/object:Gem::Version
109
+ hash: 7
104
110
  segments:
105
- - 0
106
- version: "0"
111
+ - 1
112
+ - 6
113
+ - 4
114
+ version: 1.6.4
107
115
  type: :development
108
116
  version_requirements: *id006
109
117
  description: ""
@@ -127,7 +135,6 @@ files:
127
135
  - features/step_definitions/lis_steps.rb
128
136
  - features/support/env.rb
129
137
  - lib/lis.rb
130
- - lib/lis/application_protocol.rb
131
138
  - lib/lis/commands/application.rb
132
139
  - lib/lis/interface_server.rb
133
140
  - lib/lis/messages.rb
@@ -138,7 +145,6 @@ files:
138
145
  - lib/lis/messages/query.rb
139
146
  - lib/lis/messages/result.rb
140
147
  - lib/lis/messages/terminator.rb
141
- - lib/lis/packetized_protocol.rb
142
148
  - lib/lis/transfer/application_protocol.rb
143
149
  - lib/lis/transfer/astm_e1394.rb
144
150
  - lib/lis/version.rb
@@ -167,6 +173,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
167
173
  requirements:
168
174
  - - ">="
169
175
  - !ruby/object:Gem::Version
176
+ hash: 3
170
177
  segments:
171
178
  - 0
172
179
  version: "0"
@@ -175,6 +182,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
175
182
  requirements:
176
183
  - - ">="
177
184
  - !ruby/object:Gem::Version
185
+ hash: 3
178
186
  segments:
179
187
  - 0
180
188
  version: "0"
@@ -1,104 +0,0 @@
1
-
2
- module LIS::Transfer
3
- class ApplicationProtocol < Base
4
- attr_reader :device_name
5
-
6
- def on_result(&block)
7
- @on_result_callback = block
8
- end
9
-
10
- def on_request(&block)
11
- @on_request_callback = block
12
- end
13
-
14
- def received_header(message)
15
- @patient_information_requests ||= {} # delete the list of patients
16
- @device_name = message.sender_name
17
- end
18
-
19
- def result_for(patient, order, result)
20
- @on_result_callback.call(@device_name, patient, order, result)
21
- end
22
-
23
- def received_patient_information(message)
24
- @last_order = nil
25
- @last_patient = message
26
- end
27
-
28
- def received_order_record(message)
29
- @last_order = message
30
- end
31
-
32
- def received_result(message)
33
- result_for(@last_patient, @last_order, message)
34
- end
35
-
36
- def received_request_for_information(message)
37
- @patient_information_requests ||= {}
38
- requests = @on_request_callback.call(@device_name, message.starting_range_id)
39
- @patient_information_requests[message.sequence_number] = requests if requests
40
- end
41
-
42
- def send_pending_requests
43
- sending_session(@patient_information_requests) do |patient_information|
44
- patient_information.each do |sequence_nr, data|
45
- write :message, LIS::Message::Patient.new(sequence_nr,
46
- data["patient"]["number"],
47
- data["patient"]["last_name"],
48
- data["patient"]["first_name"]).to_message
49
- data["types"].each do |request|
50
- write :message, LIS::Message::Order.new(sequence_nr, data["id"], request).to_message
51
- end
52
- end
53
- end
54
- @patient_information_requests = {}
55
- end
56
-
57
- def initialize(*args)
58
- super
59
-
60
- @patient_information_requests = {}
61
- @last_patient = nil
62
- @last_order = nil
63
- @handlers = {
64
- LIS::Message::Header => :received_header,
65
- LIS::Message::Patient => :received_patient_information,
66
- LIS::Message::Order => :received_order_record,
67
- LIS::Message::Result => :received_result,
68
- LIS::Message::Query => :received_request_for_information
69
- }
70
- end
71
-
72
- def receive(type, message = nil)
73
- warn "[R] #{message}" if type == :message and $VERBOSE
74
- case type
75
- when :begin
76
- @last_patient = nil
77
- @last_order = nil
78
- when :idle
79
- send_pending_requests
80
- when :message
81
- @message = LIS::Message::Base.from_string(message)
82
- handler = @handlers[@message.class]
83
- send(handler, @message) if handler
84
- end
85
- end
86
-
87
- def write(type, message=nil)
88
- warn "[S] #{message}" if type == :message and $VERBOSE
89
- super
90
- end
91
-
92
- # @yield data
93
- def sending_session(data)
94
- # don't send anything if there are no pending requests
95
- return if data.nil? or data.empty?
96
-
97
- write :begin
98
- write :message, LIS::Message::Header.new("LIS", @device_name).to_message
99
- yield data
100
- write :message, LIS::Message::Terminator.new.to_message
101
- write :idle
102
- end
103
- end
104
- end
@@ -1,119 +0,0 @@
1
-
2
- module LIS::Transfer
3
-
4
- # splits a stream into lis packets and only lets packets through
5
- # that are inside a session delimited by ENQ .. EOT
6
- #
7
- # check the checksum and do acknowledgement of messages
8
- #
9
- # forwards the following events:
10
- #
11
- # - :message, String :: when a message is received
12
- # - :idle :: when a transmission is finished (after EOT is received)
13
- #
14
- class PacketizedProtocol < Base
15
- ACK = "\006"
16
- NAK = "\025"
17
- ENQ = "\005"
18
- EOT = "\004"
19
-
20
- # format of a message
21
- RX = /(?:
22
- \005 | # ENQ - start a transaction
23
- \004 | # EOT - ends a transaction
24
- \005 | # ACK
25
- \025 | # NAK
26
- (?:\002 (.) (.*?) \015 \003 (.+?) \015 \012) # a message with a checksum
27
- # | | `-- checksum
28
- # | `------------------ message
29
- # `---------------------- frame number
30
- )
31
- /xm
32
-
33
- def initialize(*args)
34
- super(*args)
35
- @memo = ""
36
- @inside_transmission = false
37
- end
38
-
39
- def receive(data)
40
- scanner = StringScanner.new(@memo + data)
41
- while scanner.scan_until(RX)
42
- match = scanner.matched
43
- case match
44
- when ENQ then transmission_start
45
- when EOT then transmission_end
46
- when ACK, NAK then nil
47
- else
48
- received_message(match)
49
- write :ack
50
- end
51
- end
52
- @memo = scanner.rest
53
- nil
54
- end
55
-
56
- def write(type, data = nil)
57
- str = case type
58
- when :ack then ACK
59
- when :nak then NAK
60
- when :begin then
61
- @frame_number = 0
62
- ENQ
63
- when :idle then EOT
64
- when :message then
65
- @frame_number = (@frame_number + 1) % 8
66
- self.class.wrap_message(data, @frame_number)
67
- else
68
- raise ArgumentError
69
- end
70
- super(str)
71
- end
72
-
73
-
74
- private
75
-
76
- def self.message_from_string(string)
77
- match = string.match(RX)
78
-
79
- frame_number, data, checksum = match[1 .. 3]
80
-
81
- expected_checksum = (frame_number + data).each_byte.inject(16) { |a,b| (a+b) % 0x100 }
82
- actual_checksum = checksum.to_i(16)
83
-
84
- raise "checksum mismatch" unless expected_checksum == actual_checksum
85
- return [frame_number.to_i, data]
86
- end
87
-
88
- def self.wrap_message(string, frame_number)
89
- frame_number = (frame_number % 8).to_s
90
- checksum = (frame_number + string).each_byte.inject(16) { |a,b| (a+b) % 0x100 }
91
- checksum = checksum.to_s(16).upcase.rjust(2,"0")
92
-
93
- "\002#{frame_number}#{string}\015\003#{checksum}\015\012"
94
- end
95
-
96
-
97
- def received_message(message)
98
- return false unless @inside_transmission
99
- frame_number, message = *self.class.message_from_string(message)
100
- forward(:message, message)
101
- end
102
-
103
- def transmission_start
104
- return false if @inside_transmission
105
- write :ack
106
- forward :begin
107
- @inside_transmission = true
108
- true
109
- end
110
-
111
- def transmission_end
112
- return false unless @inside_transmission
113
- forward :idle
114
- @inside_transmission = false
115
- true
116
- end
117
- end
118
-
119
- end