digital-transport 0.1.0 → 0.2.0

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: 1669102f928a133acaf1bfb0e6b5840aa6df31e7
4
- data.tar.gz: bba0e0f506afcef5278d0883d7b93f3ac3b42a06
3
+ metadata.gz: ebc25beae1ce280e5b8a3c653a92a35cf3518485
4
+ data.tar.gz: 479c4e3741cfbedb5fa95c851aa34d90d070cb77
5
5
  SHA512:
6
- metadata.gz: fe3002c1b50cb0ff33deda8c28be6f09927d6e9cc9f0396fbe25ba1de3c944d4df63dcaa9ab022c637167838b4ca52aa0fea0e056999f68b108257351a22f8a4
7
- data.tar.gz: d57e9dbc17737602bfd7816a76ce65708483b307655a404d0afafa58da5940056bb5ff5834c134c1aca78a2065bc80d4f45959500b6070892fefb4cb718aaa0e
6
+ metadata.gz: 6014ebe51f458190fc65b3523810b21e13bf9a5bbe3cf2aec18851b86abf17872ff72b2c42b1052468de9926cf8801c46136d64613384d205e54f522bd4d785a
7
+ data.tar.gz: d962fea7aa632121b9f17e33274d5f349f2f6379bc2f3d41959fdfc8bbb6f6c4c45f01caf9f3ec8b74e4acfca905d5edb426215261fe5dcc56f54e60b94bda49
@@ -1,8 +1,8 @@
1
1
  language: ruby
2
2
  rvm:
3
3
  - 2.1.2
4
- - 1.9.3
5
4
  - 2.2.1
5
+ - head
6
6
  os:
7
7
  - linux
8
8
  - osx
@@ -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(_port, _opts = {})
42
- raise NotImplementedError
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 = {})
@@ -20,7 +20,7 @@ module Digital
20
20
  not_implemented __method__
21
21
  end
22
22
 
23
- def connect(_opts = {})
23
+ def connect
24
24
  not_implemented __method__
25
25
  end
26
26
 
@@ -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] either monad representing a value of one of two possible types
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
- # @example
26
+ # @see Adapters#new_tcp_adapter
27
27
  #
28
- # include Digital::Transport::Adapters
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, map[:tcp_nodelay].to_i)
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
- map[:timeout].to_i.nonzero? || DEFAULTS[:timeout])
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).tap
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.
@@ -1,5 +1,5 @@
1
1
  module Digital
2
2
  module Transport
3
- VERSION = "0.1.0"
3
+ VERSION = "0.2.0".freeze
4
4
  end
5
5
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: digital-transport
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Roman Lishtaba