mqtt-sub_handler 0.1.0.dev → 0.1.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: 826fa334ef34a9c8b441343ea1ef8b80652ad4df
4
- data.tar.gz: 07cfe57e8b9b7e0d355616f60042991104efff4f
3
+ metadata.gz: 77c5c7ff31447b119bde650cc2bab092e930fb1e
4
+ data.tar.gz: 73f5d04c7d2acb4da546ab3b9a16995e643a96ab
5
5
  SHA512:
6
- metadata.gz: 3c9f4e85523610a599c764980fbbe1258e6641f8074c2f607d99256d7e9984c19be091c92bdd3b3b71c3d51da78e5db423c23167cb41d5d4d7b7c80cc3677507
7
- data.tar.gz: fe6f9db5d8bf6b6166898f2f468935f0d555c6a31fddc7beffa56ce89b31c722964c54c41ab8f45daa5422195d54a6d9807978b5553ee5e7787cca27e66b8671
6
+ metadata.gz: ecb77d9ee3bdf6d121edf8c19808c973a3a1c9ca1736119793d7b2a6afa0abb2720b7ab4e4613a6165ac473db1ee36ca0d746af6c3add4ac3e5fa58d9ad89e55
7
+ data.tar.gz: 1cb20f6c9c7a6e40a09b36d868e65698aaa953a5cd48e5a6f55ca18cb73d965d6f5c99ffdbda0f356f0407e175f3f432204bd3e9edbee966a49ae4579f5f2c86
data/README.md CHANGED
@@ -1,8 +1,3 @@
1
-
2
- ### Where're the tests?
3
- They're not here yet! But if you know how to set them up, I'd absolutely love to have you contribute.
4
- Open an issue about that and we can figure things out!
5
-
6
1
  # A topic-based, asynchronous MQTT handler
7
2
  That's right, finally there's a *mostly* stable, connection-loss resistant MQTT handler out there that runs fully asynchronously.
8
3
  What's even nicer is that you can attach (and detach!) callbacks to *any* topic you want - including wildcards!
@@ -1,8 +1,9 @@
1
1
 
2
2
  require 'timeout'
3
3
  require 'mqtt'
4
+ require 'json'
4
5
 
5
- require 'mqtt/subscription_classes'
6
+ require_relative 'subscription_classes.rb'
6
7
 
7
8
  # @author Xasin
8
9
  module MQTT
@@ -15,11 +16,14 @@ end
15
16
 
16
17
 
17
18
  class SubHandler
19
+ # Whether or not hashes and arrays should be converted to JSON when sending
20
+ attr_accessor :jsonifyHashes
21
+
18
22
  # Split a Topic into a Topic-Array
19
23
  # @param topicName [String] The string topic which to split
20
24
  # @return [Array<String>] A list of individual topic-branches
21
25
  # @note This function is mainly used for background processing.
22
- def self.getTopicSplit(topicName)
26
+ def self.get_topic_split(topicName)
23
27
  return topicName.scan(/[^\/]+/);
24
28
  end
25
29
 
@@ -27,13 +31,13 @@ class SubHandler
27
31
  # @param receivedTopicString [String] The string (as
28
32
  # returned by MQTT.get) to compare
29
33
  # @param topicPattern [Array<String>] The Topic-Array (as
30
- # returned by .getTopicSplit) to compare against
34
+ # returned by .get_topic_split) to compare against
31
35
  # @return [nil, Array<String>] Nil if no match was found.
32
36
  # An Array of matched wildcard topic branches (can be empty) when
33
37
  # successfully matched
34
- # @note (see .getTopicSplit)
38
+ # @note (see .get_topic_split)
35
39
  def self.getTopicMatch(receivedTopicString, topicPattern)
36
- receivedTopicList = getTopicSplit receivedTopicString;
40
+ receivedTopicList = get_topic_split receivedTopicString;
37
41
 
38
42
  outputTopicList = Array.new();
39
43
 
@@ -206,6 +210,10 @@ class SubHandler
206
210
  def publish_to(topic, data, qos: 1, retain: false)
207
211
  raise ArgumentError, "Wrong symbol in topic: #{topic}" if topic =~ /[#\+]/
208
212
 
213
+ if(@jsonifyHashes and (data.is_a? Array or data.is_a? Hash))
214
+ data = data.to_json
215
+ end
216
+
209
217
  begin
210
218
  @conChangeMutex.lock
211
219
  if not @connected
@@ -335,10 +343,12 @@ class SubHandler
335
343
  # @param mqttClient [String, MQTT::Client] Either a URI to connect to, or a MQTT::Client
336
344
  # The URI can be of the form "mqtts://Password@User:URL:port".
337
345
  # The MQTT client instance can be fully configured, as specified by the MQTT Gem. It must *not* already be connected!
346
+ # @param jsonify [Boolean] Should Hashes and Arrays input into publish_to be converted to JSON?
347
+ # This can be useful to have one less .to_json call. Default is true.
338
348
  # @example Starting the handler
339
349
  # mqtt = MQTT::SubHandler.new('iot.eclipse.org');
340
350
  # mqtt = MQTT::SubHandler.new(MQTT::Client.new("Your.Client.Opts"))
341
- def initialize(mqttClient)
351
+ def initialize(mqttClient, jsonify: true)
342
352
  @callbackList = Array.new();
343
353
  if mqttClient.is_a? String
344
354
  @mqtt = MQTT::Client.new(mqttClient);
@@ -346,6 +356,8 @@ class SubHandler
346
356
  @mqtt = mqttClient;
347
357
  end
348
358
 
359
+ @jsonifyHashes = jsonify;
360
+
349
361
  @conChangeMutex = Mutex.new();
350
362
  @connected = false;
351
363
 
@@ -1,5 +1,6 @@
1
1
 
2
- require "mqtt/sub_handler"
2
+ require_relative "sub_handler.rb"
3
+ require 'securerandom'
3
4
 
4
5
  module MQTT
5
6
  module Testing
@@ -12,20 +13,13 @@ module MQTT
12
13
  attr_reader :publish_queue
13
14
  attr_accessor :retained_topics
14
15
 
16
+ attr_accessor :test_handler
17
+
15
18
  def call_interested(topic, data)
16
19
  @callbackList.each do |h|
17
20
  tMatch = SubHandler.getTopicMatch(topic, h.topic_split);
18
21
  if tMatch then
19
- begin
20
- h.offer(tMatch, data)
21
- rescue StandardError => e
22
- if(@error_handler)
23
- @error_handler.call(e);
24
- else
25
- raise
26
- end
27
- return
28
- end
22
+ h.offer(tMatch, data)
29
23
  end
30
24
  end
31
25
  end
@@ -44,6 +38,12 @@ module MQTT
44
38
  # @note The published data is not immediately processed.
45
39
  # Use process_message or process_all
46
40
  def publish_to(topic, data, qos: nil, retain: false)
41
+ if(@jsonifyHashes and (data.is_a? Array or data.is_a? Hash))
42
+ data = data.to_json
43
+ else
44
+ data = data.to_s;
45
+ end
46
+
47
47
  @publish_queue << [topic, data];
48
48
  @message_log[topic] << data;
49
49
  @retained_topics[topic] = data if retain;
@@ -64,13 +64,33 @@ module MQTT
64
64
  until @publish_queue.empty?
65
65
  process_message
66
66
  max_loops -= 1;
67
+
67
68
  if(max_loops == 0)
68
69
  if(error_on_loop)
69
- raise RuntimeError, "MQTT Loop recursion detected!"
70
+ if(@test_handler)
71
+ @test_handler.flunk("MQTT Loop recursion detected")
72
+ else
73
+ raise RuntimeError, "MQTT Loop recursion detected"
74
+ end
70
75
  end
71
76
  return
72
77
  end
73
78
  end
79
+
80
+ if(error_on_loop and @test_handler)
81
+ @test_handler.pass("No MQTT Loop recursion.");
82
+ end
83
+ end
84
+
85
+ def assert_garbage_resilient()
86
+ @callbackList.each do |c|
87
+ t = Array.new() {|a,k| a[k] = SecureRandom.random_bytes(100)}
88
+ c.offer(t, SecureRandom.random_bytes(100));
89
+ end
90
+
91
+ if(@test_handler)
92
+ @test_handler.pass("No garbage message problem detected.");
93
+ end
74
94
  end
75
95
 
76
96
  # Prepare the code for the next test by cleaning out all queues.
@@ -90,15 +110,31 @@ module MQTT
90
110
  @message_log.clear()
91
111
  end
92
112
 
93
- def initialize()
113
+ # Perform a complete reset of the testing unit, clearing out all
114
+ # queues and removing all callbacks. This should mainly be used
115
+ # inside the teardown or setup routines, before creating a new
116
+ # testing instance, to prevent uncleaned garbage.
117
+ def full_reset()
118
+ @callbackList.clear();
119
+ prepare();
120
+ end
121
+
122
+ # Initialize the test class
123
+ # @param jsonify [Boolean] Whether or not Hashes and Arrays should be
124
+ # converted to JSON before sending.
125
+ # @param test_handler [nil, MiniTest::Test] The test handler to use to report
126
+ # errors or pass sanity checks. Must support flunk and pass!
127
+ def initialize(jsonify: true, test_handler: nil)
94
128
  @callbackList = Array.new();
95
129
  @retained_topics = Hash.new();
96
130
  @publish_queue = Queue.new();
97
131
  @message_log = Hash.new() do |h, key| h = Array.new() end;
98
- end
99
132
 
100
- def on_error(&handler)
101
- @error_handler = handler;
133
+ @trackerHash = Hash.new();
134
+
135
+ @jsonifyHashes = jsonify;
136
+
137
+ @test_handler = test_handler;
102
138
  end
103
139
  end
104
140
  end
@@ -1,5 +1,5 @@
1
1
 
2
- require 'mqtt/Waitpoint.rb'
2
+ require_relative 'Waitpoint.rb'
3
3
 
4
4
  module MQTT
5
5
  module Subscriptions
@@ -11,7 +11,7 @@ module MQTT
11
11
 
12
12
  def initialize(topic, _qos)
13
13
  @topic = topic;
14
- @topic_split = SubHandler.getTopicSplit(topic);
14
+ @topic_split = SubHandler.get_topic_split(topic);
15
15
 
16
16
  @qos = 0;
17
17
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: mqtt-sub_handler
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0.dev
4
+ version: 0.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Xasin
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-05-03 00:00:00.000000000 Z
11
+ date: 2018-06-26 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: mqtt
@@ -24,6 +24,62 @@ dependencies:
24
24
  - - ">="
25
25
  - !ruby/object:Gem::Version
26
26
  version: 0.5.0
27
+ - !ruby/object:Gem::Dependency
28
+ name: json
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: minitest
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: guard
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: guard-minitest
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
27
83
  description: Asynchronous handling of callbacks that can be attached to individual
28
84
  topics, based on the mqtt gem.
29
85
  email:
@@ -51,9 +107,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
51
107
  version: '0'
52
108
  required_rubygems_version: !ruby/object:Gem::Requirement
53
109
  requirements:
54
- - - ">"
110
+ - - ">="
55
111
  - !ruby/object:Gem::Version
56
- version: 1.3.1
112
+ version: '0'
57
113
  requirements: []
58
114
  rubyforge_project:
59
115
  rubygems_version: 2.6.14.1