lora-rb 0.14.1 → 0.15.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 2d9ae8b46b9a42db2037a2fa8982464bb9752af1
4
- data.tar.gz: 9035bc787caaeb5d2ed80c2fca7bc4d59bcfebce
3
+ metadata.gz: e64d803226daebe33886346c591fe64547de3222
4
+ data.tar.gz: f8bbfa9765e0b8e59e1a5d31cd393bd162ca599f
5
5
  SHA512:
6
- metadata.gz: fb96d0297ecdde1cdd73c92ba9af09184cec57a558b50e7ab625abc32942c3dec8f0a5280eedbac23e12fbeb55f2ae813ea5096bf3e4c0abab0c37fe33133f4d
7
- data.tar.gz: 8eb4548eee426a26c629cb3a9a19214c2efff3daab9d20f5976200bf959ba67cc8125da44e570e19d7be7ea6c184f2604d21583289de91a235248dd1920692a8
6
+ metadata.gz: '02503788daa2ca41e53219162fbba9062060d491058cc9f72f5ba639ffd23341b4ce7573c4b0769c0a7bcdd97fbe261601280b7de7c0248ea0c8f55daabee7b1'
7
+ data.tar.gz: 38a51544561b73924783012f69118e0916950dacb3fc3ad8a7500a10e3b47d8f1cc47fb7937a01d8c68fc483168202e8b0fdc233e09158ec821e3a8999a0aefd
data/CHANGELOG.md CHANGED
@@ -1,3 +1,11 @@
1
+ v0.15.0 [☰](https://bitbucket.org/fractalgarden/loriot-rb/branches/compare/v0.14.0..v0.15.0) November 1th, 2017
2
+ ------------------------------
3
+ * Added new parameter "provider" to connection's configuration
4
+ * Added provider fractalgarden as new provider which support mqtt protocol. It offers free service, try it!
5
+ * LoraClient class is now extended by the provider's methods on the initialization. In the future, this will make it easier
6
+ to connect to multiple network servers.
7
+ * Several improvements
8
+
1
9
  v0.14.1 October 20th, 2017
2
10
  ------------------------------
3
11
  * Mqtt: method all_enqueued_downlink_id raise the custom exception EuiNotFound
data/lib/config/config.rb CHANGED
@@ -7,6 +7,8 @@ LoraRb.configure do |config|
7
7
  # config.host = 'localhost'
8
8
  # config.protocol = :http
9
9
  # config.host = 'eu72.resiot.io'
10
+ # A2a
11
+ config.provider = :a2a
10
12
  config.protocol = :mqtt
11
13
  config.host = 'ptnetsuite.a2asmartcity.io'
12
14
  config.port = 8883
@@ -23,4 +25,18 @@ LoraRb.configure do |config|
23
25
  ]
24
26
  config.ssl = true
25
27
  config.ssl_file = 'ssl_certificates/mqtt_ca.crt'
28
+ # Fractalgarden Free Network Server
29
+ # config.provider = :fractalgarden
30
+ # config.protocol = :mqtt
31
+ # config.host = '192.168.1.106'
32
+ # config.port = 1883
33
+ # config.uplink_url = 'application/{appid}/node/+/rx'
34
+ # config.downlink_url = 'application/{appid}/node/{deveui}/tx'
35
+ # config.timeout = 30.0
36
+ # # If you expect more than one response in a topic, ad a item with url=nil to not subscribe it newly
37
+ # config.downlink_response_urls = [
38
+ # { name: :queued, url: 'reply/{clientid}/id/{requestid}'},
39
+ # ]
40
+ # config.ssl = false
41
+ # # config.ssl_file = "#{Rails.root}/vendor/ssl_certificates/a2a_mqtt_ca.crt"
26
42
  end
@@ -8,12 +8,16 @@ defaults: &defaults
8
8
  #connector_id: "69643d32"
9
9
  # A2a
10
10
  #appid: "a1b2c3d4e5f60001"
11
- appid: "9956" # SSG dev
12
11
  token: "2B7E151628AED2A6ABF7158809CF4F3C"
12
+ appid: "9957"
13
13
  username: "fractalgarden"
14
14
  password: "fr4ctalg4rden"
15
+ # Fractalgarden
16
+ # appid: "1"
17
+ # username: "loraserver_gw"
18
+ # password: "loraserver_gw"
15
19
 
16
- test_eui: "be7a0000000010cf"
20
+ test_eui: "be7a00000000123c"
17
21
  #foo: add every variable you need and use it with => LoraRb::Settings.foo
18
22
  # bar: sub variable are accessible with hash => LoraRb::Settings.foo[:bar]
19
23
 
@@ -2,11 +2,12 @@ module LoraRb
2
2
  class Configuration
3
3
  # attr_writer :allow_sign_up
4
4
 
5
- attr_accessor :protocol, :host, :port, :uplink_url, :downlink_url, :downlink_response_urls, :ssl, :ssl_file, :env,
6
- :timeout, :enqueued_downlinks_url, :delete_enqueued_downlink_url
5
+ attr_accessor :provider, :protocol, :host, :port, :uplink_url, :downlink_url, :downlink_response_urls,
6
+ :ssl, :ssl_file, :env, :timeout, :enqueued_downlinks_url, :delete_enqueued_downlink_url
7
7
 
8
8
  def initialize
9
- @protocol = nil
9
+ @provider = nil #PROVIDERS.keys.first
10
+ @protocol = nil #PROVIDERS[@provider].first
10
11
  @host = nil
11
12
  @port = nil
12
13
  @uplink_url = nil
@@ -19,7 +20,6 @@ module LoraRb
19
20
  @env = 'development'
20
21
  @timeout = 10.0
21
22
  end
22
-
23
23
  end
24
24
 
25
25
  def self.configuration
data/lib/core/protocol.rb CHANGED
@@ -3,9 +3,19 @@ module LoraRb
3
3
  # It contains protocols methods
4
4
  class Protocol
5
5
 
6
- # Show tips on usage
7
- def self.supported_protocols
8
- %w(tls http rabbitmq mqtt)
6
+ PROVIDERS = { fractalgarden: [:mqtt],
7
+ a2a: [:mqtt],
8
+ loriot: [:tls],
9
+ resiot: [:http]
10
+ }
11
+
12
+ def self.provider_is_valid?(provider: LoraRb.configuration.provider)
13
+ PROVIDERS.has_key? provider
14
+ end
15
+ def self.supported?(provider: LoraRb.configuration.provider,
16
+ protocol: LoraRb.configuration.protocol)
17
+ return unless provider && protocol
18
+ PROVIDERS[provider] && PROVIDERS[provider].include?(protocol.to_sym)
9
19
  end
10
20
  end
11
21
  end
data/lib/lora-rb.rb CHANGED
@@ -26,16 +26,10 @@ require_relative 'lora-rb/base'
26
26
  unless defined?(Rails)
27
27
  require_relative 'config/config'
28
28
 
29
- connection_protocol = LoraRb.configuration.protocol
30
- raise "Define your protocol in the configuration file!" unless connection_protocol
31
- raise "Connection protocol #{connection_protocol} not recognized!" unless LoraRb::Protocol.supported_protocols.include?(connection_protocol.to_s)
32
- require_relative "lora-rb/#{connection_protocol}/call"
33
- LoraClient.include LoraRb::Call
34
-
35
29
  %w(private.yml).each do |file|
36
30
  filepath = File.join(LoraRb.root, 'lib', 'config', file)
37
31
  LoraRb::Settings.load!(filepath, env: LoraRb.configuration.env) if File.exist? filepath
38
32
  end
39
- raise "Insert your secret data to login on the lora cloud!" if LoraRb::Settings.appid.nil? || LoraRb::Settings.token.nil?
33
+ raise "Insert your secret data to login on the lora network server!" if LoraRb::Settings.appid.nil? || LoraRb::Settings.token.nil?
40
34
  end
41
35
 
@@ -10,27 +10,29 @@ module LoraRb
10
10
  def sub_initialize(options={})
11
11
  require 'mqtt'
12
12
 
13
- raise 'Specify uplink_url to continue!' unless options[:uplink_url]
14
- raise 'Specify downlink_url to continue!' unless options[:downlink_url]
13
+ raise 'Specify uplink_url to continue!' unless options[:uplink_url]
14
+ raise 'Specify downlink_url to continue!' unless options[:downlink_url]
15
15
  raise 'Specify downlink_response_urls to continue!' unless options[:downlink_response_urls]
16
- raise 'Specify host to continue!' unless options[:host]
17
- raise 'Specify port to continue!' unless options[:port]
18
- raise 'Specify username to continue!' unless options[:username]
19
- raise 'Specify password to continue!' unless options[:password]
20
- raise 'Specify ssl_file to continue!' if options[:ssl] && !options[:ssl_file]
16
+ raise 'Specify host to continue!' unless options[:host]
17
+ raise 'Specify port to continue!' unless options[:port]
18
+ raise 'Specify username to continue!' unless options[:username]
19
+ raise 'Specify password to continue!' unless options[:password]
20
+ raise 'Specify ssl_file to continue!' if options[:ssl] && !options[:ssl_file]
21
21
 
22
22
  @username = options[:username]
23
23
  @client_id = "#{@username}::ssg#{generate_request_id}"
24
24
 
25
- @client = MQTT::Client.connect(
25
+ connection_attributes = {
26
26
  host: options[:host],
27
27
  port: options[:port],
28
28
  ssl: options[:ssl],
29
- cert_file: options[:ssl_file],
30
29
  username: @username,
31
30
  password: options[:password],
32
31
  client_id: @client_id
33
- )
32
+ }
33
+ connection_attributes[:cert_file] = options[:ssl_file] if connection_attributes[:ssl]
34
+ # The class variable @@mock is set by the stubbed class. The other methods (send_cmd etc.) are entirely stubbed.
35
+ @client = MQTT::Client.connect(connection_attributes) unless defined?(@@mock) && @@mock
34
36
 
35
37
  @topic = merge_tags_to_url(options[:uplink_url],
36
38
  { username: @username,
@@ -56,9 +58,12 @@ module LoraRb
56
58
  "port": options[:port], # Port where the message should be sent
57
59
  "payload": options[:data], # Message payload
58
60
  "confirmed": options[:confirmed], # (Optional) Tells whether a confirmed downlink is requested. Default: false
59
- "window": options[:window] || "BOTH", # (Optional) Specifies which rx window should be used: RX1, RX2 or any(BOTH). Default: BOTH
60
- "priority": options[:priority] || 0, # (Optional) Message priority, used to sort messages in the queue. Default: 0
61
61
  }
62
+ # (Optional) Specifies which rx window should be used: RX1, RX2 or any(BOTH). Default: BOTH
63
+ h_request['window'] = options[:window] if options[:window]
64
+ # (Optional) Message priority, used to sort messages in the queue. Default: 0
65
+ h_request['priority'] = options[:priority] if options[:priority]
66
+
62
67
  request_id = generate_request_id
63
68
  publish_url = merge_tags_to_url(@downlink_url,
64
69
  username: @username,
data/lib/lora-rb/base.rb CHANGED
@@ -30,6 +30,14 @@ class LoraClient
30
30
 
31
31
  require 'philter'
32
32
  require 'securerandom'
33
+
34
+ raise "Specify your provider in the configuration file!" unless LoraRb.configuration.provider
35
+ raise "Specify the protocol in the configuration file!" unless LoraRb.configuration.protocol
36
+ raise "Provider #{LoraRb.configuration.provider} not defined!" unless LoraRb::Protocol.provider_is_valid?
37
+ raise "Connection protocol #{LoraRb.configuration.protocol} not supported by the provider #{LoraRb.configuration.provider}!" unless LoraRb::Protocol.supported?
38
+ require_relative "#{LoraRb.configuration.provider}/#{LoraRb.configuration.protocol}/call"
39
+ self.extend LoraRb::Call
40
+
33
41
  welcome_response = sub_initialize(options)
34
42
 
35
43
  raise("Lora-rb: Cannot connect to host #{options[:host]}:#{options[:port]}") unless welcome_response.key?('hello')
@@ -0,0 +1,187 @@
1
+ # LoraRb calling methods
2
+ module LoraRb
3
+ class EuiNotFound < StandardError; end
4
+ # It contains all the methods for selecting the items
5
+ module Call
6
+ attr_reader :client
7
+
8
+ private
9
+
10
+ def sub_initialize(options={})
11
+ require 'mqtt'
12
+
13
+ raise 'Specify uplink_url to continue!' unless options[:uplink_url]
14
+ raise 'Specify downlink_url to continue!' unless options[:downlink_url]
15
+ raise 'Specify downlink_response_urls to continue!' unless options[:downlink_response_urls]
16
+ raise 'Specify host to continue!' unless options[:host]
17
+ raise 'Specify port to continue!' unless options[:port]
18
+ raise 'Specify username to continue!' unless options[:username]
19
+ raise 'Specify password to continue!' unless options[:password]
20
+ raise 'Specify ssl_file to continue!' if options[:ssl] && !options[:ssl_file]
21
+
22
+ @username = options[:username]
23
+ @client_id = "#{@username}::ssg#{generate_request_id}"
24
+
25
+ connection_attributes = {
26
+ host: options[:host],
27
+ port: options[:port],
28
+ ssl: options[:ssl],
29
+ username: @username,
30
+ password: options[:password],
31
+ client_id: @client_id
32
+ }
33
+ connection_attributes[:cert_file] = options[:ssl_file] if connection_attributes[:ssl]
34
+ # The class variable @@mock is set by the stubbed class. The other methods (send_cmd etc.) are entirely stubbed.
35
+ @client = MQTT::Client.connect(connection_attributes) unless defined?(@@mock) && @@mock
36
+
37
+ @topic = merge_tags_to_url(options[:uplink_url],
38
+ { username: @username,
39
+ appid: @appid },
40
+ { debug: options[:debug] })
41
+
42
+ @downlink_url = options[:downlink_url]
43
+ @downlink_response_urls = options[:downlink_response_urls]
44
+ @enqueued_downlinks_url = options[:enqueued_downlinks_url]
45
+ @delete_enqueued_downlink_url = options[:delete_enqueued_downlink_url]
46
+ @timeout = options[:timeout]
47
+ @wait_response = options.has_key?(:wait_response) ? options[:wait_response] : true
48
+ {'hello' => 'Lora-Rb: Ready to start!'}
49
+ end
50
+
51
+ # Send the request to device
52
+ def sub_send_cmd(options={})
53
+ options = { wait_response: @wait_response }.merge(options)
54
+
55
+ request_id = generate_request_id
56
+ h_request = {
57
+ "fport": options[:port], # Port where the message should be sent
58
+ "data": options[:data], # Message payload
59
+ "confirmed": options[:confirmed], # (Optional) Tells whether a confirmed downlink is requested. Default: false
60
+ "devEUI": options[:eui],
61
+ "reference": request_id
62
+ }
63
+
64
+ publish_url = merge_tags_to_url(@downlink_url,
65
+ username: @username,
66
+ appid: @appid,
67
+ deveui: options[:eui],
68
+ clientid: @client_id,
69
+ requestid: request_id)
70
+
71
+ puts " publish #{h_request.to_json} to #{publish_url}" if options[:debug]
72
+ responses = []
73
+ response_topics = []
74
+ # thr_response = nil
75
+ if options[:wait_response]
76
+ @downlink_response_urls.each do |dru_hash|
77
+ name, response_url = dru_hash[:name], dru_hash[:url]
78
+ next unless response_url
79
+
80
+ # response_topic = "reply/#{@client_id}/id/#{request_id}"
81
+ response_topic = merge_tags_to_url(response_url,
82
+ username: @username,
83
+ appid: @appid,
84
+ deveui: options[:eui],
85
+ clientid: @client_id,
86
+ requestid: request_id)
87
+ puts " Subscribing response #{response_topic}" if options[:debug] == :full
88
+ response_topics << response_topic
89
+ end
90
+
91
+ raise "cannot subscribe without topic, response_topics is empty!" if response_topics.empty?
92
+ @client.subscribe(*response_topics)
93
+ end
94
+
95
+ @client.publish(publish_url, h_request.to_json, false)
96
+
97
+ if options[:wait_response]
98
+ # Waiting for all the responses
99
+ # thr_responses.each { |thr_response| thr_response.join }
100
+ # thr_response.join
101
+ @downlink_response_urls.each do |dru_hash|
102
+ response_topic, response_message = sub_read_data(topic: nil, debug: options[:debug])
103
+ response = { topic: response_topic, json: response_message }
104
+ puts " Found response #{response} " if options[:debug] == :full
105
+ responses << response
106
+ end
107
+
108
+ @client.unsubscribe(*response_topics)
109
+ end
110
+ responses
111
+ end
112
+
113
+ # Receive the payload from the network
114
+ # There is a timeout. Use this method only to retrieve data from the queue. If you have to waiting data
115
+ # please use listen.
116
+ # If topic is nil it uses subscribed topics
117
+ def sub_read_data(options={})
118
+ topic = options.has_key?(:topic) ? options[:topic] : @topic
119
+ if topic
120
+ topic = topic.dup
121
+ puts " Reading topic #{topic}..." if options[:debug]
122
+ end
123
+
124
+ message = nil
125
+ begin
126
+ Timeout.timeout(options[:timeout] || @timeout) do
127
+ topic, message = @client.get(topic)
128
+ end
129
+ rescue Timeout::Error
130
+ message = {error: 'Timeout'}.to_json
131
+ end
132
+
133
+ message = JSON.parse(message)
134
+ if message.respond_to? '[]'
135
+ eui = get_eui_from_topic(topic)
136
+ message['eui'] ||= eui if eui
137
+ port = get_port_from_topic(topic)
138
+ message['port'] ||= port if port
139
+ end
140
+ return topic, message
141
+ end
142
+
143
+ # Waiting for message in the queue
144
+ def sub_listen(options={}, &block)
145
+ topic = options.has_key?(:topic) ? options[:topic] : @topic
146
+ if topic
147
+ topic = topic.dup
148
+ puts " Waiting for messages in #{topic}. To exit press CTRL+C" if options[:debug]
149
+ end
150
+
151
+ @client.get(topic) do |topic, message|
152
+ # Block is executed for every message received
153
+ puts " original json: #{topic}: #{message}" if options[:debug] == :full
154
+ message = JSON.parse(message)
155
+ if message.respond_to? '[]'
156
+ eui = get_eui_from_topic(topic)
157
+ message['eui'] ||= eui if eui
158
+ port = get_port_from_topic(topic)
159
+ message['port'] ||= port if port
160
+ end
161
+ puts " #{message}" if options[:debug] #After reworking
162
+ block.call(topic, message) if block_given?
163
+ break if options[:test]
164
+ end
165
+ end
166
+
167
+ # Close the connection
168
+ def sub_quit
169
+ @client.disconnect
170
+ end
171
+
172
+ def get_eui_from_topic(topic)
173
+ res = topic&.match(/devices\/(\w{16})/)
174
+ res[1] if res
175
+ end
176
+
177
+ def get_port_from_topic(topic)
178
+ res = topic&.match(/uplink\/(\d+)(\/|\Z)/)
179
+ res[1] if res
180
+ end
181
+
182
+ def generate_request_id
183
+ "#{Time.now.strftime('%y%m%d%H%M%S')}#{SecureRandom.hex(1)}"
184
+ end
185
+
186
+ end
187
+ end
File without changes
File without changes
@@ -2,7 +2,6 @@
2
2
  module LoraRb
3
3
  # It contains generic methods
4
4
  module Base
5
- private
6
5
 
7
6
  # Show tips on usage
8
7
  def merge_tags_to_url(url, tags={}, options={})
@@ -17,6 +16,8 @@ module LoraRb
17
16
  end
18
17
  end
19
18
 
19
+ private
20
+
20
21
  def puts(message)
21
22
  Kernel.puts "[#{self.class.name}##{__method__}] #{Time.now} #{message}"
22
23
  end
data/lib/version.rb CHANGED
@@ -1,8 +1,8 @@
1
1
  module LoraRb
2
2
  def self.version
3
- "0.14.1"
3
+ "0.15.0"
4
4
  end
5
5
  def self.updated_at
6
- "2017-10-20"
6
+ "2017-11-01"
7
7
  end
8
8
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: lora-rb
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.14.1
4
+ version: 0.15.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Marco Mastrodonato
@@ -11,7 +11,7 @@ authors:
11
11
  autorequire:
12
12
  bindir: bin
13
13
  cert_chain: []
14
- date: 2017-10-20 00:00:00.000000000 Z
14
+ date: 2017-11-01 00:00:00.000000000 Z
15
15
  dependencies:
16
16
  - !ruby/object:Gem::Dependency
17
17
  name: json
@@ -32,6 +32,9 @@ dependencies:
32
32
  requirement: !ruby/object:Gem::Requirement
33
33
  requirements:
34
34
  - - "~>"
35
+ - !ruby/object:Gem::Version
36
+ version: '0.5'
37
+ - - ">="
35
38
  - !ruby/object:Gem::Version
36
39
  version: 0.5.0
37
40
  type: :runtime
@@ -39,6 +42,9 @@ dependencies:
39
42
  version_requirements: !ruby/object:Gem::Requirement
40
43
  requirements:
41
44
  - - "~>"
45
+ - !ruby/object:Gem::Version
46
+ version: '0.5'
47
+ - - ">="
42
48
  - !ruby/object:Gem::Version
43
49
  version: 0.5.0
44
50
  - !ruby/object:Gem::Dependency
@@ -46,6 +52,9 @@ dependencies:
46
52
  requirement: !ruby/object:Gem::Requirement
47
53
  requirements:
48
54
  - - "~>"
55
+ - !ruby/object:Gem::Version
56
+ version: '1.2'
57
+ - - ">="
49
58
  - !ruby/object:Gem::Version
50
59
  version: 1.2.0
51
60
  type: :runtime
@@ -53,6 +62,9 @@ dependencies:
53
62
  version_requirements: !ruby/object:Gem::Requirement
54
63
  requirements:
55
64
  - - "~>"
65
+ - !ruby/object:Gem::Version
66
+ version: '1.2'
67
+ - - ">="
56
68
  - !ruby/object:Gem::Version
57
69
  version: 1.2.0
58
70
  - !ruby/object:Gem::Dependency
@@ -91,12 +103,13 @@ files:
91
103
  - lib/core/protocol.rb
92
104
  - lib/generators/install_generator.rb
93
105
  - lib/lora-rb.rb
106
+ - lib/lora-rb/a2a/mqtt/call.rb
94
107
  - lib/lora-rb/base.rb
108
+ - lib/lora-rb/fractalgarden/mqtt/call.rb
109
+ - lib/lora-rb/fractalgarden/rabbitmq/call.rb
95
110
  - lib/lora-rb/help.rb
96
- - lib/lora-rb/http/call.rb
97
- - lib/lora-rb/mqtt/call.rb
98
- - lib/lora-rb/rabbitmq/call.rb
99
- - lib/lora-rb/tls/call.rb
111
+ - lib/lora-rb/loriot/tls/call.rb
112
+ - lib/lora-rb/resiot/http/call.rb
100
113
  - lib/lora-rb/utility.rb
101
114
  - lib/vendor/deep_symbolize.rb
102
115
  - lib/version.rb