mqtt_pipe 0.0.3 → 0.0.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: f579008e0f69a4f8dd375038f2b611d39e82ec07
4
- data.tar.gz: 4b54e9845ad534d37b6f954028f5c6d9e3bcd83b
3
+ metadata.gz: 9eb995dda9d228f1276dd94091d8e4e243eeae66
4
+ data.tar.gz: 54dbf42a2f536c7865cd3c529489ea34fccf7f1a
5
5
  SHA512:
6
- metadata.gz: 1ded3c38efb21c73ecb8ac1cb2455cb1dc206e7e6273101fd26672e1c914143748e37862f39e311a79aed4a2fe3b7a2879f48586029d9ac2c96b271f8bd31e68
7
- data.tar.gz: 249ded44ccac0db4e6f66372f242b99ea9d4c205fc245fe62c4b0233328ceebcfa9536450542dbf72a8af750754fdbf6a38bb648431b792ca24c4c18cf9df50b
6
+ metadata.gz: 8f23a64abaf8a1db9a9288b8a93367b8b5552e46c0b30645eb0bb4fdb5d9aa5a27f4f10dde32ce2ff5a2a7ee4483a69387e6b0293ff38a0548e82048283752e6
7
+ data.tar.gz: 31e0b5d28c07cc7d3b44b701dec0160559b88a7ea7a80ef6cc79127838ab5fcf26b609494f62f026e4e16b4beeed0d5c4031f2b09d266b2e818d795500181b6e
data/README.md CHANGED
@@ -41,7 +41,7 @@ MQTTPipe.create do
41
41
  end
42
42
  ```
43
43
 
44
- Everything does not need to be contained in a block:
44
+ Or without the block:
45
45
 
46
46
  ```ruby
47
47
  pipe = MQTTPipe.create
@@ -57,6 +57,7 @@ pipe.open 'test.mosquitto.org', port: 1883 do
57
57
  end
58
58
  ```
59
59
 
60
+
60
61
  ## Protocol
61
62
 
62
63
  Taking inspiration from the excellent [MessagePack](http://msgpack.org) project each data type is represented by a byte value, or in same cases a range of values. The currently supported data types along with their byte values are:
@@ -88,15 +89,17 @@ Note that the integers are split over several codes to accommodate for the vario
88
89
 
89
90
  Array and string are also special cases in that their sizes are not known. They require a length value to be passed along with them, but instead of always including an extra byte for that purpose, length smaller than 32 can be encoded directly in the type byte value. An example is shown below:
90
91
 
91
- #### Strings with length 1..31:
92
+ Strings with length 1..31:
92
93
 
93
94
  'test' -> [0xA0 + 4, 0x74, 0x65, 0x73, 0x74]
94
95
 
95
- #### Strings with length 32..288
96
+ Strings with length 32..288
96
97
 
97
98
  'testing how really long strings are encoded'
98
99
  -> [0xA0, 43 - 32, 0x74, 0x65, 0x73, ...]
99
100
 
101
+ **Note that both strings and arrays with length 0 are converted to and sent as `nil`.**
102
+
100
103
  Some data types that may be supported in the future are:
101
104
 
102
105
  - IP Addresses
@@ -5,5 +5,5 @@ pipe = MQTTPipe.create do
5
5
  p message, id
6
6
  end
7
7
 
8
- open 'test.mosquitto.org', port: 1883
8
+ open 'localhost', port: 1883
9
9
  end
@@ -6,7 +6,7 @@ pipe.on 'hello/world/5' do
6
6
  puts 'received 5'
7
7
  end
8
8
 
9
- pipe.open 'test.mosquitto.org', port: 1883 do
9
+ pipe.open 'localhost', port: 1883 do
10
10
  counter = 0
11
11
  loop do
12
12
  send 'hello/world/' + counter.to_s, Time.now
@@ -6,7 +6,7 @@ module MQTTPipe
6
6
  # given string as well as calling the action.
7
7
 
8
8
  class Listener
9
- attr_reader :topic, :pattern
9
+ attr_reader :topic, :pattern, :action
10
10
 
11
11
  ##
12
12
  # The listener requires a topic string and a callable
@@ -20,7 +20,7 @@ module MQTTPipe
20
20
  @topic = topic
21
21
  @action = action
22
22
 
23
- pattern = topic.gsub('*', '([^/]+)').gsub('/#', '/?(.*)')
23
+ pattern = topic.gsub('*', '([^/]+)').gsub('/#', '/?(.*)').gsub('#', '(.*)')
24
24
  @pattern = %r{^#{pattern}$}
25
25
  end
26
26
 
@@ -64,7 +64,7 @@ module MQTTPipe
64
64
  # the original values.
65
65
 
66
66
  def unpack raw, limit: nil
67
- raw = StringIO.new raw unless raw.respond_to? :read
67
+ raw = ::StringIO.new raw unless raw.respond_to? :read
68
68
  result = []
69
69
 
70
70
  # Either loop infinately or the number of times
@@ -6,7 +6,7 @@ module MQTTPipe
6
6
  class Pipe
7
7
 
8
8
  ##
9
- # Raised when the connection unexpectedly lost.
9
+ # Raised when the connection is broken
10
10
 
11
11
  class ConnectionError < StandardError; end
12
12
 
@@ -14,7 +14,9 @@ module MQTTPipe
14
14
  # Create a new pipe and optionally yield to a block
15
15
 
16
16
  def initialize &block
17
- @listeners = []
17
+ @listeners = []
18
+ @error_handler = nil
19
+
18
20
  instance_eval &block unless block.nil?
19
21
  end
20
22
 
@@ -35,6 +37,10 @@ module MQTTPipe
35
37
  on '#', &action
36
38
  end
37
39
 
40
+ def on_error &action
41
+ @error_handler = action
42
+ end
43
+
38
44
  alias_method :on_everything, :on_anything
39
45
 
40
46
  def topics
@@ -45,54 +51,57 @@ module MQTTPipe
45
51
  # Open the pipe
46
52
 
47
53
  def open host, port: 1883, &block
48
- MQTT::Client.connect host: host, port: port do |client|
54
+ listener_thread = nil
55
+ client = MQTT::Client.connect host: host, port: port
56
+ context = Context.new client
49
57
 
50
- # Subscribe
51
- listener_thread = nil
52
-
53
- unless @listeners.empty?
54
- listener_thread = Thread.new do
55
- client.get do |topic, data|
56
- begin
57
- unpacked_data = Packer.unpack data
58
-
59
- @listeners.each do |listener|
60
- if m = listener.match(topic)
61
- listener.call unpacked_data, *m
62
- end
58
+ unless @listeners.empty?
59
+ listener_thread = Thread.new(Thread.current) do |parent|
60
+ client.get do |topic, data|
61
+ begin
62
+ unpacked_data = Packer.unpack data
63
+
64
+ @listeners.each do |listener|
65
+ if m = listener.match(topic)
66
+ #listener.call unpacked_data, *m
67
+ context.instance_exec unpacked_data, *m, &listener.action
63
68
  end
64
-
65
- rescue Packer::FormatError
66
- # TODO: Handle more gracefully
67
- puts 'Could not parse data!'
68
- next
69
69
  end
70
+
71
+ rescue Packer::FormatError
72
+ @error_handler.call topic, data unless @error_handler.nil?
73
+ next
74
+
75
+ # Raise the exception in the parent thread
76
+ rescue Exception => e
77
+ parent.raise e
70
78
  end
71
79
  end
72
-
73
- client.subscribe *topics
74
80
  end
75
-
76
- unless block.nil?
77
- context = Context.new client
78
-
79
- begin
80
- context.instance_eval &block
81
- rescue ConnectionError
82
-
83
- puts 'Need to reconnect'
84
- rescue Interrupt
85
- ensure
86
- listener_thread.exit unless topics.empty?
87
- end
88
81
 
89
- else
90
- begin
91
- listener_thread.join unless topics.empty?
92
- rescue Interrupt
93
- end
82
+ client.subscribe *topics
83
+ end
84
+
85
+ # Call user block
86
+ unless block.nil?
87
+ begin
88
+ context.instance_eval &block
89
+ rescue ConnectionError
90
+ puts 'TODO: Handle reconnect'
91
+ rescue Interrupt
92
+ exit
94
93
  end
95
94
  end
95
+
96
+ # Join with listener thread
97
+ begin
98
+ listener_thread.join unless listener_thread.nil?
99
+ rescue Interrupt
100
+ end
101
+
102
+ ensure
103
+ client.disconnect
104
+ listener_thread.exit unless listener_thread.nil?
96
105
  end
97
106
 
98
107
  private
@@ -13,5 +13,14 @@ module MQTTPipe
13
13
  [PACKER_CODE, r, g, b].pack 'C4'
14
14
  end
15
15
  end
16
+
17
+ class << Color
18
+ def from_packed _, raw
19
+ color = 3.times.map do
20
+ Packer.read_packed_bytes(1, from: raw, as: 'C')
21
+ end
22
+ new *color
23
+ end
24
+ end
16
25
  end
17
26
  end
@@ -1,3 +1,3 @@
1
1
  module MQTTPipe
2
- VERSION = "0.0.3"
2
+ VERSION = "0.0.4"
3
3
  end
@@ -3,6 +3,7 @@ require 'mqtt_pipe'
3
3
  describe MQTTPipe::Listener do
4
4
  let(:klass) { MQTTPipe::Listener }
5
5
  let(:topic) { 'test/*/topic/#' }
6
+ let(:topic_pattern) { %r{^test/([^/]+)/topic/?(.*)$} }
6
7
  let(:matching_topic_1) { 'test/some/topic' }
7
8
  let(:matching_topic_2) { 'test/some/topic/with/more/5' }
8
9
  let(:non_matching_topic) { 'test/topic/with/8' }
@@ -31,6 +32,7 @@ describe MQTTPipe::Listener do
31
32
  pattern = @listener.pattern
32
33
 
33
34
  expect(pattern).to be_a(Regexp)
35
+ expect(pattern).to eq topic_pattern
34
36
  expect(pattern === topic).to be true
35
37
  end
36
38
 
@@ -82,6 +84,5 @@ describe MQTTPipe::Listener do
82
84
  expect(@listener.run 42).to eq 84
83
85
  end
84
86
  end
85
-
86
87
  end
87
88
  end
@@ -35,6 +35,9 @@ describe MQTTPipe::Pipe do
35
35
  end
36
36
  end
37
37
 
38
+ describe '#on_error' do
39
+ end
40
+
38
41
  describe '#topics' do
39
42
  it 'stores the topics that have beed subscribed to' do
40
43
  expect(@pipe.topics.empty?).to be true
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: mqtt_pipe
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.3
4
+ version: 0.0.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Sebastian Lindberg
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-08-27 00:00:00.000000000 Z
11
+ date: 2015-09-29 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: mqtt