lora-rb 0.15.0 → 0.16.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +8 -0
- data/README.md +26 -0
- data/lib/config/config.rb +25 -25
- data/lib/config/private.yml +8 -7
- data/lib/lora-rb/a2a/mqtt/call.rb +11 -3
- data/lib/lora-rb/base.rb +10 -2
- data/lib/lora-rb/fractalgarden/mqtt/call.rb +11 -3
- data/lib/lora-rb/fractalgarden/rabbitmq/call.rb +1 -1
- data/lib/lora-rb/loriot/tls/call.rb +1 -1
- data/lib/lora-rb/utility.rb +9 -1
- data/lib/version.rb +2 -2
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 13e675828b129c8d27b670935487ff710a8109ff
|
4
|
+
data.tar.gz: 7d559b6b2240436b69f4343648f471caee250cea
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 8757592a55411332611df7ebd2b1d69bb8ddd08c59429485b98940322dadad5cb9e7daa7ec4ca08ccdd6fd0c1a1226fa24be7a484dd18cc676ce70b64610591f
|
7
|
+
data.tar.gz: c47ea7135d3ebea9216467fbde51789f2da7ceed90e66bc43a141c67c4154bcb7c84821e59d65d88b23f9c6505d6a23bec903c4c2120a649d8b4c9998242336c
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,11 @@
|
|
1
|
+
v0.16.0 [☰](https://bitbucket.org/fractalgarden/loriot-rb/branches/compare/v0.15.0..v0.16.0) November 21th, 2017
|
2
|
+
------------------------------
|
3
|
+
* Encoding / Decoding with Base64:
|
4
|
+
* Now on a new instance is possible to set encoding: true to encode the payload sent and to decode json
|
5
|
+
attribute "payload" or "data"
|
6
|
+
* lora instance object now return provider and protocol
|
7
|
+
* Tests are now devided by provider
|
8
|
+
|
1
9
|
v0.15.0 [☰](https://bitbucket.org/fractalgarden/loriot-rb/branches/compare/v0.14.0..v0.15.0) November 1th, 2017
|
2
10
|
------------------------------
|
3
11
|
* Added new parameter "provider" to connection's configuration
|
data/README.md
CHANGED
@@ -29,6 +29,7 @@ This version supports:
|
|
29
29
|
1. TLS protocol with [Loriot](http://loriot.io) (No longer supported)
|
30
30
|
2. Http push with [Resiot](http://resiot.io) (No longer supported)
|
31
31
|
3. MQTT with [A2aSmartCity](http://www.a2asmartcity.io/)
|
32
|
+
4. MQTT with Fractalgarden (Those who are developing this gem)
|
32
33
|
|
33
34
|
## Configuration
|
34
35
|
|
@@ -115,6 +116,7 @@ LoraRb.configure do |config|
|
|
115
116
|
config.port = 8883
|
116
117
|
config.uplink_url = '/sub/v1/users/{username}/apps/{appid}/devices/+/uplink/+'
|
117
118
|
config.downlink_url = '/api/v1/users/{username}/apps/{appid}/devices/{deveui}/downlink/post/reply/{clientid}/id/{requestid}'
|
119
|
+
config.timeout = 30.0
|
118
120
|
config.downlink_response_urls = {
|
119
121
|
queued: 'reply/{clientid}/id/{requestid}',
|
120
122
|
transmitted: '/sub/v1/users/{username}/apps/{appid}/devices/{deveui}/events/downlink'
|
@@ -124,6 +126,26 @@ LoraRb.configure do |config|
|
|
124
126
|
end
|
125
127
|
```
|
126
128
|
|
129
|
+
### MQTT (with Fractalgarden free lora server)
|
130
|
+
|
131
|
+
Currently, the free network server is under development.
|
132
|
+
|
133
|
+
```ruby
|
134
|
+
LoraRb.configure do |config|
|
135
|
+
config.provider = :fractalgarden
|
136
|
+
config.protocol = :mqtt
|
137
|
+
config.host = 'lora.fractalgarden.com'
|
138
|
+
config.port = 1883
|
139
|
+
config.uplink_url = 'application/{appid}/node/+/rx'
|
140
|
+
config.downlink_url = 'application/{appid}/node/{deveui}/tx'
|
141
|
+
config.timeout = 30.0
|
142
|
+
config.downlink_response_urls = [
|
143
|
+
{ name: :queued, url: 'reply/{clientid}/id/{requestid}'},
|
144
|
+
]
|
145
|
+
config.ssl = false
|
146
|
+
end
|
147
|
+
```
|
148
|
+
|
127
149
|
## Usage
|
128
150
|
|
129
151
|
From irb require the library:
|
@@ -222,6 +244,10 @@ lora.send_cmd(eui: 'Insert here your device eui',
|
|
222
244
|
wait_response: false)
|
223
245
|
```
|
224
246
|
|
247
|
+
#### Only on Mqtt (A2a)
|
248
|
+
|
249
|
+
The a2a network server let you to manage the enqueued messages.
|
250
|
+
|
225
251
|
The param delete_previous_enqueued_commands is true by default as well. It means previous enqueued messages to the node
|
226
252
|
are deleted (the queue is emptied) before sending a new one.
|
227
253
|
|
data/lib/config/config.rb
CHANGED
@@ -8,35 +8,35 @@ LoraRb.configure do |config|
|
|
8
8
|
# config.protocol = :http
|
9
9
|
# config.host = 'eu72.resiot.io'
|
10
10
|
# A2a
|
11
|
-
config.provider = :a2a
|
11
|
+
# config.provider = :a2a
|
12
|
+
# config.protocol = :mqtt
|
13
|
+
# config.host = 'ptnetsuite.a2asmartcity.io'
|
14
|
+
# config.port = 8883
|
15
|
+
# config.uplink_url = '/sub/v1/users/{username}/apps/{appid}/devices/+/uplink/+'
|
16
|
+
# config.downlink_url = '/api/v1/users/{username}/apps/{appid}/devices/{deveui}/downlink/post/reply/{clientid}/id/{requestid}'
|
17
|
+
# config.delete_enqueued_downlink_url = '/api/v1/users/{username}/apps/{appid}/devices/{deveui}/downlink/{id}/delete/reply/{clientid}/id/{requestid}'
|
18
|
+
# config.enqueued_downlinks_url = '/api/v1/users/{username}/apps/{appid}/devices/{deveui}/downlink/get/reply/{clientid}/id/{requestid}'
|
19
|
+
# config.timeout = 60.0
|
20
|
+
# # If you expect more than one response in a topic, add an item with url=nil to not subscribe it newly
|
21
|
+
# config.downlink_response_urls = [
|
22
|
+
# { name: :queued, url: 'reply/{clientid}/id/{requestid}'},
|
23
|
+
# # { name: :transmitted, url: '/sub/v1/users/{username}/apps/{appid}/devices/{deveui}/events/downlink' }
|
24
|
+
# # { name: :confirmed, url: nil },
|
25
|
+
# ]
|
26
|
+
# config.ssl = true
|
27
|
+
# config.ssl_file = 'ssl_certificates/mqtt_ca.crt'
|
28
|
+
# Fractalgarden Free Network Server
|
29
|
+
config.provider = :fractalgarden
|
12
30
|
config.protocol = :mqtt
|
13
|
-
config.host = '
|
14
|
-
config.port =
|
31
|
+
config.host = '192.168.1.106'
|
32
|
+
config.port = 1883
|
15
33
|
config.uplink_url = '/sub/v1/users/{username}/apps/{appid}/devices/+/uplink/+'
|
16
34
|
config.downlink_url = '/api/v1/users/{username}/apps/{appid}/devices/{deveui}/downlink/post/reply/{clientid}/id/{requestid}'
|
17
|
-
config.
|
18
|
-
|
19
|
-
config.timeout = 60.0
|
20
|
-
# If you expect more than one response in a topic, add an item with url=nil to not subscribe it newly
|
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
|
21
37
|
config.downlink_response_urls = [
|
22
38
|
{ name: :queued, url: 'reply/{clientid}/id/{requestid}'},
|
23
|
-
# { name: :transmitted, url: '/sub/v1/users/{username}/apps/{appid}/devices/{deveui}/events/downlink' }
|
24
|
-
# { name: :confirmed, url: nil },
|
25
39
|
]
|
26
|
-
config.ssl =
|
27
|
-
config.ssl_file =
|
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"
|
40
|
+
config.ssl = false
|
41
|
+
# config.ssl_file = "#{Rails.root}/vendor/ssl_certificates/a2a_mqtt_ca.crt"
|
42
42
|
end
|
data/lib/config/private.yml
CHANGED
@@ -9,15 +9,16 @@ defaults: &defaults
|
|
9
9
|
# A2a
|
10
10
|
#appid: "a1b2c3d4e5f60001"
|
11
11
|
token: "2B7E151628AED2A6ABF7158809CF4F3C"
|
12
|
-
appid: "9957"
|
13
|
-
username: "fractalgarden"
|
14
|
-
password: "fr4ctalg4rden"
|
12
|
+
# appid: "9957"
|
13
|
+
# username: "fractalgarden"
|
14
|
+
# password: "fr4ctalg4rden"
|
15
15
|
# Fractalgarden
|
16
|
-
|
17
|
-
|
18
|
-
|
16
|
+
appid: "1"
|
17
|
+
username: "loraserver"
|
18
|
+
password: "loraserver"
|
19
19
|
|
20
|
-
test_eui: "be7a00000000123c"
|
20
|
+
# test_eui: "be7a00000000123c"
|
21
|
+
test_eui: "be7a000000001a5f"
|
21
22
|
#foo: add every variable you need and use it with => LoraRb::Settings.foo
|
22
23
|
# bar: sub variable are accessible with hash => LoraRb::Settings.foo[:bar]
|
23
24
|
|
@@ -55,9 +55,9 @@ module LoraRb
|
|
55
55
|
sub_delete_enqueued_messages(eui: options[:eui], debug: options[:debug]) if options[:delete_previous_enqueued_commands]
|
56
56
|
|
57
57
|
h_request = {
|
58
|
-
|
59
|
-
|
60
|
-
|
58
|
+
"port": options[:port], # Port where the message should be sent
|
59
|
+
"payload": (@encoding ? lora_encode(options[:data]) : options[:data]), # Message payload
|
60
|
+
"confirmed": options[:confirmed], # (Optional) Tells whether a confirmed downlink is requested. Default: false
|
61
61
|
}
|
62
62
|
# (Optional) Specifies which rx window should be used: RX1, RX2 or any(BOTH). Default: BOTH
|
63
63
|
h_request['window'] = options[:window] if options[:window]
|
@@ -140,6 +140,10 @@ module LoraRb
|
|
140
140
|
message['eui'] ||= eui if eui
|
141
141
|
port = get_port_from_topic(topic)
|
142
142
|
message['port'] ||= port if port
|
143
|
+
if @encoding
|
144
|
+
payload_key = %w(payload data).find { |tag| message[tag] }
|
145
|
+
message[payload_key] = lora_decode(message[payload_key]) if payload_key
|
146
|
+
end
|
143
147
|
end
|
144
148
|
return topic, message
|
145
149
|
end
|
@@ -161,6 +165,10 @@ module LoraRb
|
|
161
165
|
message['eui'] ||= eui if eui
|
162
166
|
port = get_port_from_topic(topic)
|
163
167
|
message['port'] ||= port if port
|
168
|
+
if @encoding
|
169
|
+
payload_key = %w(payload data).find { |tag| message[tag] }
|
170
|
+
message[payload_key] = lora_decode(message[payload_key]) if payload_key
|
171
|
+
end
|
164
172
|
end
|
165
173
|
puts " #{message}" if options[:debug] #After reworking
|
166
174
|
block.call(topic, message) if block_given?
|
data/lib/lora-rb/base.rb
CHANGED
@@ -7,6 +7,8 @@ require_relative 'utility'
|
|
7
7
|
class LoraClient
|
8
8
|
include LoraRb::Base
|
9
9
|
|
10
|
+
attr_reader :provider, :protocol
|
11
|
+
|
10
12
|
# Establish a secure connection to your account on the cloud
|
11
13
|
def initialize(options = {})
|
12
14
|
options = {debug: false,
|
@@ -23,11 +25,17 @@ class LoraClient
|
|
23
25
|
password: LoraRb::Settings.password,
|
24
26
|
ssl: LoraRb.configuration.ssl,
|
25
27
|
ssl_file: LoraRb.configuration.ssl_file,
|
26
|
-
timeout: LoraRb.configuration.timeout
|
28
|
+
timeout: LoraRb.configuration.timeout,
|
29
|
+
encoding: false}.merge(options)
|
27
30
|
@debug = options[:debug]
|
28
31
|
@token = options[:token]
|
29
32
|
@appid = options[:appid]
|
30
33
|
|
34
|
+
@provider = LoraRb.configuration.provider
|
35
|
+
@protocol = LoraRb.configuration.protocol
|
36
|
+
@encoding = options[:encoding]
|
37
|
+
require 'base64' if @encoding
|
38
|
+
|
31
39
|
require 'philter'
|
32
40
|
require 'securerandom'
|
33
41
|
|
@@ -35,7 +43,7 @@ class LoraClient
|
|
35
43
|
raise "Specify the protocol in the configuration file!" unless LoraRb.configuration.protocol
|
36
44
|
raise "Provider #{LoraRb.configuration.provider} not defined!" unless LoraRb::Protocol.provider_is_valid?
|
37
45
|
raise "Connection protocol #{LoraRb.configuration.protocol} not supported by the provider #{LoraRb.configuration.provider}!" unless LoraRb::Protocol.supported?
|
38
|
-
require_relative "#{
|
46
|
+
require_relative "#{@provider}/#{@protocol}/call"
|
39
47
|
self.extend LoraRb::Call
|
40
48
|
|
41
49
|
welcome_response = sub_initialize(options)
|
@@ -54,9 +54,9 @@ module LoraRb
|
|
54
54
|
|
55
55
|
request_id = generate_request_id
|
56
56
|
h_request = {
|
57
|
-
"fport": options[:port],
|
58
|
-
"data": options[:data],
|
59
|
-
"confirmed": options[:confirmed],
|
57
|
+
"fport": options[:port], # Port where the message should be sent
|
58
|
+
"data": (@encoding ? lora_encode(options[:data]) : options[:data]), # Message payload
|
59
|
+
"confirmed": options[:confirmed], # (Optional) Tells whether a confirmed downlink is requested. Default: false
|
60
60
|
"devEUI": options[:eui],
|
61
61
|
"reference": request_id
|
62
62
|
}
|
@@ -136,6 +136,10 @@ module LoraRb
|
|
136
136
|
message['eui'] ||= eui if eui
|
137
137
|
port = get_port_from_topic(topic)
|
138
138
|
message['port'] ||= port if port
|
139
|
+
if @encoding
|
140
|
+
payload_key = %w(payload data).find { |tag| message[tag] }
|
141
|
+
message[payload_key] = lora_decode(message[payload_key]) if payload_key
|
142
|
+
end
|
139
143
|
end
|
140
144
|
return topic, message
|
141
145
|
end
|
@@ -157,6 +161,10 @@ module LoraRb
|
|
157
161
|
message['eui'] ||= eui if eui
|
158
162
|
port = get_port_from_topic(topic)
|
159
163
|
message['port'] ||= port if port
|
164
|
+
if @encoding
|
165
|
+
payload_key = %w(payload data).find { |tag| message[tag] }
|
166
|
+
message[payload_key] = lora_decode(message[payload_key]) if payload_key
|
167
|
+
end
|
160
168
|
end
|
161
169
|
puts " #{message}" if options[:debug] #After reworking
|
162
170
|
block.call(topic, message) if block_given?
|
@@ -18,7 +18,7 @@ module LoraRb
|
|
18
18
|
|
19
19
|
# Send the request to device
|
20
20
|
def sub_send_cmd(options={})
|
21
|
-
str_request = "{\"cmd\":\"#{options[:cmd]}\",\"EUI\":\"#{options[:eui]}\",\"port\":#{options[:port]},\"confirmed\":#{options[:confirmed]},\"data\":\"#{options[:data]}\"} "
|
21
|
+
str_request = "{\"cmd\":\"#{options[:cmd]}\",\"EUI\":\"#{options[:eui]}\",\"port\":#{options[:port]},\"confirmed\":#{options[:confirmed]},\"data\":\"#{(@encoding ? lora_encode(options[:data]) : options[:data])}\"} "
|
22
22
|
puts "#{Time.now} Cmq request: #{str_request}" if options[:debug]
|
23
23
|
response = @channel.default_exchange.publish(str_request, routing_key: @queue.name)
|
24
24
|
puts " [x] Sent '#{str_request}'" if options[:debug]
|
@@ -25,7 +25,7 @@ module LoraRb
|
|
25
25
|
str_app_token = "{\"appid\":\"#{options[:appid]}\", \"token\":\"#{options[:token]}\"}"
|
26
26
|
puts "#{Time.now} To: #{str_app_token}" if options[:debug]
|
27
27
|
@ssl_socket.puts str_app_token
|
28
|
-
str_request = "{\"cmd\":\"#{options[:cmd]}\",\"EUI\":\"#{options[:eui]}\",\"port\":#{options[:port]},\"confirmed\":#{options[:confirmed]},\"data\":\"#{options[:data]}\"} "
|
28
|
+
str_request = "{\"cmd\":\"#{options[:cmd]}\",\"EUI\":\"#{options[:eui]}\",\"port\":#{options[:port]},\"confirmed\":#{options[:confirmed]},\"data\":\"#{(@encoding ? lora_encode(options[:data]) : options[:data])}\"} "
|
29
29
|
puts "#{Time.now} Cmq request: #{str_request}" if options[:debug]
|
30
30
|
@ssl_socket.puts(str_request)
|
31
31
|
begin
|
data/lib/lora-rb/utility.rb
CHANGED
@@ -3,7 +3,7 @@ module LoraRb
|
|
3
3
|
# It contains generic methods
|
4
4
|
module Base
|
5
5
|
|
6
|
-
#
|
6
|
+
# Substitute tags with data into url
|
7
7
|
def merge_tags_to_url(url, tags={}, options={})
|
8
8
|
url = url.dup
|
9
9
|
puts "merge_tags_to_url: #{url}" if options[:debug] == :full
|
@@ -14,6 +14,14 @@ module LoraRb
|
|
14
14
|
puts "merge_tags_to_url: completed #{url}" if options[:debug] == :full
|
15
15
|
url
|
16
16
|
end
|
17
|
+
|
18
|
+
def lora_encode(payload)
|
19
|
+
Base64.encode64(payload.scan(/.{2}/).map { |b| b.to_i(16).chr }.join)
|
20
|
+
end
|
21
|
+
|
22
|
+
def lora_decode(payload)
|
23
|
+
Base64.decode64(payload).unpack("H*").first
|
24
|
+
end
|
17
25
|
end
|
18
26
|
|
19
27
|
private
|
data/lib/version.rb
CHANGED
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.
|
4
|
+
version: 0.16.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-11-
|
14
|
+
date: 2017-11-21 00:00:00.000000000 Z
|
15
15
|
dependencies:
|
16
16
|
- !ruby/object:Gem::Dependency
|
17
17
|
name: json
|