digital-transport 0.1.0 → 0.2.0
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 +4 -4
- data/.travis.yml +1 -1
- data/lib/digital/transport/adapters.rb +4 -4
- data/lib/digital/transport/adapters/interface.rb +1 -1
- data/lib/digital/transport/adapters/serial.rb +108 -0
- data/lib/digital/transport/adapters/tcp.rb +11 -29
- data/lib/digital/transport/version.rb +1 -1
- metadata +1 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ebc25beae1ce280e5b8a3c653a92a35cf3518485
|
4
|
+
data.tar.gz: 479c4e3741cfbedb5fa95c851aa34d90d070cb77
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 6014ebe51f458190fc65b3523810b21e13bf9a5bbe3cf2aec18851b86abf17872ff72b2c42b1052468de9926cf8801c46136d64613384d205e54f522bd4d785a
|
7
|
+
data.tar.gz: d962fea7aa632121b9f17e33274d5f349f2f6379bc2f3d41959fdfc8bbb6f6c4c45f01caf9f3ec8b74e4acfca905d5edb426215261fe5dcc56f54e60b94bda49
|
data/.travis.yml
CHANGED
@@ -34,12 +34,12 @@ module Digital
|
|
34
34
|
|
35
35
|
private_constant :Tcp, :Serial
|
36
36
|
|
37
|
-
def new_tcp_adapter(ip, port)
|
38
|
-
Tcp.new(ip.dup.freeze, port)
|
37
|
+
def new_tcp_adapter(ip, port, opts = {})
|
38
|
+
Tcp.new(ip.dup.freeze, port, opts.dup.freeze)
|
39
39
|
end
|
40
40
|
|
41
|
-
def new_serial_adapter(
|
42
|
-
|
41
|
+
def new_serial_adapter(port, opts = {})
|
42
|
+
Serial.new(port, opts.dup.freeze)
|
43
43
|
end
|
44
44
|
|
45
45
|
def new_usb_adapter(_port, _opts = {})
|
@@ -6,8 +6,116 @@ module Digital
|
|
6
6
|
class Serial
|
7
7
|
include Digital::Transport::Errors
|
8
8
|
include Digital::Transport::Adapters::Interface
|
9
|
+
include CommPort
|
9
10
|
include Functional
|
10
11
|
|
12
|
+
DEFAULTS = {
|
13
|
+
timeout: 10,
|
14
|
+
baud_rate: CommPort::BAUD_115200,
|
15
|
+
data_bits: CommPort::DATA_BITS_8,
|
16
|
+
parity: CommPort::PAR_NONE,
|
17
|
+
stop_bits: CommPort::STOP_BITS_1,
|
18
|
+
flow_control: CommPort::FLOW_OFF
|
19
|
+
}.freeze
|
20
|
+
|
21
|
+
def initialize(port, opt = {})
|
22
|
+
@port = port.freeze
|
23
|
+
@opts = DEFAULTS.merge(opt.dup).freeze
|
24
|
+
@io = nil
|
25
|
+
end
|
26
|
+
|
27
|
+
# @return [Either] monad representing a value of one of two possible types
|
28
|
+
# 1. Exception covariant
|
29
|
+
# 2. Adapter interface invariant
|
30
|
+
#
|
31
|
+
# @see Adapters#new_serial_adapter
|
32
|
+
#
|
33
|
+
def connect
|
34
|
+
io = Rs232.new(@port)
|
35
|
+
io.connecting_timeout = @opts[:timeout].to_i if p.respond_to?(:connecting_timeout)
|
36
|
+
io.open
|
37
|
+
io.baud_rate = @opts[:baud_rate].to_i
|
38
|
+
io.data_bits = @opts[:data_bits].to_i
|
39
|
+
io.parity = @opts[:parity].to_i
|
40
|
+
io.stop_bits = @opts[:stop_bits].to_i
|
41
|
+
io.flow_control = @opts[:flow_control].to_i
|
42
|
+
@io = io
|
43
|
+
Either.right(self)
|
44
|
+
rescue Exception => ex
|
45
|
+
Either.left(ex)
|
46
|
+
end
|
47
|
+
|
48
|
+
def write(bytes)
|
49
|
+
raise NotConnected unless open?
|
50
|
+
Either.right(@io.write(bytes))
|
51
|
+
rescue => ex
|
52
|
+
Either.left(ex)
|
53
|
+
end
|
54
|
+
|
55
|
+
def close
|
56
|
+
return !open? unless open?
|
57
|
+
@io && @io.close
|
58
|
+
@io = nil
|
59
|
+
!open?
|
60
|
+
end
|
61
|
+
|
62
|
+
def flush
|
63
|
+
@io && @io.flush
|
64
|
+
end
|
65
|
+
|
66
|
+
def open?
|
67
|
+
@io && !@io.closed?
|
68
|
+
end
|
69
|
+
|
70
|
+
def read(count, blocking = false)
|
71
|
+
raise NotConnected unless open?
|
72
|
+
array = []
|
73
|
+
|
74
|
+
bytes_count = (count == -1) ? @io.available? : count
|
75
|
+
|
76
|
+
if blocking
|
77
|
+
bytes = read_io_until(count, count)
|
78
|
+
array.push bytes if bytes
|
79
|
+
else
|
80
|
+
bytes_count.times do
|
81
|
+
byte = @io.read(1)
|
82
|
+
array.push byte if byte
|
83
|
+
end
|
84
|
+
end
|
85
|
+
Either.right(array.empty? ? nil : array.join)
|
86
|
+
rescue => ex
|
87
|
+
Either.left(ex)
|
88
|
+
end
|
89
|
+
|
90
|
+
private
|
91
|
+
|
92
|
+
# @api private
|
93
|
+
#
|
94
|
+
# simulate blocking function
|
95
|
+
#
|
96
|
+
# @param [Fixnum] count
|
97
|
+
# @param [Fixnum] up_to
|
98
|
+
#
|
99
|
+
# no direct ruby usage
|
100
|
+
#
|
101
|
+
def block_io_until(count, up_to)
|
102
|
+
up_to -= 1 while @io.available? < count && up_to > 0
|
103
|
+
up_to > 0
|
104
|
+
end
|
105
|
+
|
106
|
+
# @api private
|
107
|
+
#
|
108
|
+
# simulate blocking function
|
109
|
+
#
|
110
|
+
# @param [Fixnum] count
|
111
|
+
# @param [Fixnum] up_to
|
112
|
+
#
|
113
|
+
# no direct ruby usage
|
114
|
+
#
|
115
|
+
def read_io_until(count, up_to)
|
116
|
+
sleep 0.001 until block_io_until(count, up_to)
|
117
|
+
read(count)
|
118
|
+
end
|
11
119
|
end
|
12
120
|
end
|
13
121
|
end
|
@@ -10,47 +10,32 @@ module Digital
|
|
10
10
|
include Digital::Transport::Errors
|
11
11
|
include Digital::Transport::Adapters::Interface
|
12
12
|
|
13
|
-
DEFAULTS = { timeout: 10 }.freeze
|
13
|
+
DEFAULTS = { timeout: 10, tcp_no_delay: 1 }.freeze
|
14
14
|
|
15
|
-
def initialize(ip, port)
|
16
|
-
@ip = ip
|
15
|
+
def initialize(ip, port, opts = {})
|
16
|
+
@ip = ip.freeze
|
17
|
+
@opts = DEFAULTS.merge(opts.dup).freeze
|
17
18
|
@port = port
|
18
19
|
@io = nil
|
19
|
-
yield self if block_given?
|
20
20
|
end
|
21
21
|
|
22
|
-
# @return [Either]
|
22
|
+
# @return [Either] monad representing a value of one of two possible types
|
23
23
|
# 1. Exception covariant
|
24
24
|
# 2. Adapter interface invariant
|
25
25
|
#
|
26
|
-
# @
|
26
|
+
# @see Adapters#new_tcp_adapter
|
27
27
|
#
|
28
|
-
|
29
|
-
#
|
30
|
-
# on_success = -> x {
|
31
|
-
# puts "connection open? -> #{x.open?}"
|
32
|
-
# x.write("Hello, World!") =>
|
33
|
-
# x.read 2 #=>
|
34
|
-
# }
|
35
|
-
# on_failure = -> x { puts "Wasn't able to connect due to: #{x.message}" }
|
36
|
-
#
|
37
|
-
# maybe = new_tcp_adapter('10.0.0.250', 12000).connect
|
38
|
-
# maybe.either(on_failure, on_success)
|
39
|
-
#
|
40
|
-
def connect(opt = { timeout: 10, tcp_no_delay: 1 })
|
28
|
+
def connect
|
41
29
|
return open? if open?
|
42
|
-
map = opt.dup.freeze
|
43
30
|
Socket.new(AF_INET, SOCK_STREAM, 0).tap do |socket|
|
44
|
-
socket.setsockopt(IPPROTO_TCP, TCP_NODELAY,
|
31
|
+
socket.setsockopt(IPPROTO_TCP, TCP_NODELAY, (@opts[:tcp_nodelay] || DEFAULTS[:tcp_no_delay]).to_i)
|
45
32
|
return connect_nonblock(
|
46
33
|
socket,
|
47
34
|
Socket.pack_sockaddr_in(@port, @ip),
|
48
|
-
|
35
|
+
@opts[:timeout].to_i.nonzero? || DEFAULTS[:timeout])
|
49
36
|
end
|
50
37
|
end
|
51
38
|
|
52
|
-
# @raise [Errno::ECONNRESET] if connection reset by peer
|
53
|
-
#
|
54
39
|
# @return [Boolean] representing operation state
|
55
40
|
def close
|
56
41
|
return !open? unless open?
|
@@ -60,14 +45,11 @@ module Digital
|
|
60
45
|
!open?
|
61
46
|
end
|
62
47
|
|
63
|
-
# @raise [Errno::ECONNRESET] if connection reset by peer
|
64
|
-
# @return [Ethernet] it self
|
65
48
|
def flush
|
66
49
|
@io && @io.flush
|
67
50
|
end
|
68
51
|
|
69
52
|
# @param [String] string
|
70
|
-
# @return [Fixnum] representing amount of bytes written
|
71
53
|
def write(string)
|
72
54
|
raise NotConnected unless open?
|
73
55
|
written = 0
|
@@ -90,10 +72,9 @@ module Digital
|
|
90
72
|
|
91
73
|
# @param [Fixnum] count how many bytes to read
|
92
74
|
# @param [Boolean] should_block which will simulate blocking function
|
93
|
-
# @return [String, nil] the String which was received or nil otherwise
|
94
75
|
def read(count, should_block = false)
|
95
76
|
raise NotConnected unless open?
|
96
|
-
Either.right @io.read_nonblock(count)
|
77
|
+
Either.right @io.read_nonblock(count)
|
97
78
|
rescue IO::WaitReadable
|
98
79
|
if should_block
|
99
80
|
IO.select [@io]
|
@@ -111,6 +92,7 @@ module Digital
|
|
111
92
|
|
112
93
|
private
|
113
94
|
|
95
|
+
# @api private
|
114
96
|
def connect_nonblock(io_like, endpoint, timeout)
|
115
97
|
io_like.connect_nonblock(endpoint)
|
116
98
|
rescue Errno::EINPROGRESS # connection in progress, wait a bit.
|