mqtt-sn-ruby 0.0.4 → 0.0.5
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 +4 -4
- data/bin/mqtt-sn-forwarder.rb +42 -0
- data/lib/mqtt-sn-ruby.rb +164 -97
- metadata +3 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: cad9bc3bc78a80dccac6baba83cb3e634c13e3a9
|
4
|
+
data.tar.gz: 989fdd5fdd51f43bb291740e44368ac411db83d5
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: cf0299e126aa60c1614be436eac864c2d52519ae07efa38601e41f23b240bb48d99593ccf4e5835b19f5fa5e20467908e6bf91031e62c6d7605abd169f22c149
|
7
|
+
data.tar.gz: ace1150d210c367fefe9a25a71d2d62996b897039c00a48a21edaf804e0d720a9ca7d2c66ad4b0fac0d51e602707dff82dfbaa7476251ec10fba288fce1d552b
|
@@ -0,0 +1,42 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# encode: UTF-8
|
3
|
+
|
4
|
+
require "pp"
|
5
|
+
require 'socket'
|
6
|
+
require 'json'
|
7
|
+
require 'optparse'
|
8
|
+
if File.file? './lib/mqtt-sn-ruby.rb'
|
9
|
+
require './lib/mqtt-sn-ruby.rb'
|
10
|
+
puts "using local lib"
|
11
|
+
else
|
12
|
+
require 'mqtt-sn-ruby'
|
13
|
+
end
|
14
|
+
|
15
|
+
options = {}
|
16
|
+
OptionParser.new do |opts|
|
17
|
+
opts.banner = "Usage: mqtt-sn-sub.rb [options]"
|
18
|
+
|
19
|
+
opts.on("-v", "--[no-]verbose", "Run verbosely (false)") do |v|
|
20
|
+
options[:verbose] = v
|
21
|
+
end
|
22
|
+
opts.on("-d", "--[no-]debug", "Produce Debug dump on console (false)") do |v|
|
23
|
+
options[:debug] = v
|
24
|
+
end
|
25
|
+
opts.on("-h", "--host host", "MQTT-SN Host to connect (localhost)") do |v|
|
26
|
+
options[:server] = v
|
27
|
+
end
|
28
|
+
opts.on("-p", "--port port", "MQTT-SN Port to connect (1883)") do |v|
|
29
|
+
options[:port] = v.to_i
|
30
|
+
end
|
31
|
+
end.parse!
|
32
|
+
|
33
|
+
puts "MQTT-SN-FORWARDER: #{options.to_json}"
|
34
|
+
begin
|
35
|
+
MqttSN.forwarder "20.20.20.21",3333,options
|
36
|
+
rescue SystemExit, Interrupt
|
37
|
+
puts "\nExiting after Disconnect\n"
|
38
|
+
rescue => e
|
39
|
+
puts "\nError: '#{e}' -- Quit after Disconnect\n"
|
40
|
+
end
|
41
|
+
|
42
|
+
puts "MQTT-SN-FORWARDER Done."
|
data/lib/mqtt-sn-ruby.rb
CHANGED
@@ -46,11 +46,13 @@ class MqttSN
|
|
46
46
|
@@msg_id=1
|
47
47
|
|
48
48
|
def initialize(hash={})
|
49
|
+
@options=hash #save these
|
49
50
|
@server=hash[:server]||"127.0.0.1"
|
50
51
|
@port=hash[:port]||1883
|
51
52
|
@debug=hash[:debug]
|
52
53
|
@verbose=hash[:verbose]
|
53
54
|
@state=:inited
|
55
|
+
@forward=hash[:forward] #flag to indicate forward mode
|
54
56
|
@will_topic=nil
|
55
57
|
@will_msg=nil
|
56
58
|
@id="?"
|
@@ -87,6 +89,10 @@ class MqttSN
|
|
87
89
|
hexdump msg
|
88
90
|
end
|
89
91
|
|
92
|
+
def raw_send_packet msg
|
93
|
+
@s.send(msg, 0, @server, @port)
|
94
|
+
end
|
95
|
+
|
90
96
|
def send type,hash={},&block
|
91
97
|
puts "" if @verbose
|
92
98
|
if @state!=:connected and type!=:connect and type!=:will_topic and type!=:will_msg
|
@@ -214,7 +220,7 @@ class MqttSN
|
|
214
220
|
@iq.clear
|
215
221
|
end
|
216
222
|
raw=send_packet p
|
217
|
-
hash[:
|
223
|
+
hash[:debug]=raw if @debug
|
218
224
|
puts "send:#{@id} #{type},#{hash.to_json}" if @verbose
|
219
225
|
timeout=hash[:timeout]||Tretry
|
220
226
|
retries=0
|
@@ -250,6 +256,54 @@ class MqttSN
|
|
250
256
|
|
251
257
|
end
|
252
258
|
|
259
|
+
def self.forwarder listen_ip,listen_port,hash={}
|
260
|
+
@options=hash #save these
|
261
|
+
@server=hash[:server]||"127.0.0.1"
|
262
|
+
@port=hash[:port]||1883
|
263
|
+
@debug=hash[:debug]
|
264
|
+
@verbose=hash[:verbose]
|
265
|
+
|
266
|
+
socket = UDPSocket.new
|
267
|
+
socket.bind(listen_ip,listen_port)
|
268
|
+
puts "listening #{listen_ip}:#{listen_port}"
|
269
|
+
clients={}
|
270
|
+
begin
|
271
|
+
while true
|
272
|
+
begin
|
273
|
+
r,stuff=socket.recvfrom_nonblock(200)
|
274
|
+
puts "got packet:"
|
275
|
+
client_ip=stuff[2]
|
276
|
+
client_port=stuff[1]
|
277
|
+
key="#{client_ip}:#{client_port}"
|
278
|
+
if not clients[key]
|
279
|
+
clients[key]={ip:client_ip, port:client_port, socket: UDPSocket.new }
|
280
|
+
end
|
281
|
+
clients[key][:socket].send(r, 0, @server, @port)
|
282
|
+
#process_message r
|
283
|
+
|
284
|
+
rescue IO::WaitReadable
|
285
|
+
rescue => e
|
286
|
+
puts "Error: receive thread died: #{e}"
|
287
|
+
pp e.backtrace
|
288
|
+
end
|
289
|
+
clients.each do |key,c|
|
290
|
+
begin
|
291
|
+
r,stuff=c[:socket].recvfrom_nonblock(200)
|
292
|
+
puts "got packet from server to client #{key}:"
|
293
|
+
puts "sending to #{c[:ip]}:#{c[:port]}"
|
294
|
+
socket.send(r, 0, c[:ip], c[:port])
|
295
|
+
#process_message r
|
296
|
+
rescue IO::WaitReadable
|
297
|
+
rescue => e
|
298
|
+
puts "Error: receive thread died: #{e}"
|
299
|
+
pp e.backtrace
|
300
|
+
end
|
301
|
+
end
|
302
|
+
sleep 0.01
|
303
|
+
end
|
304
|
+
end
|
305
|
+
end
|
306
|
+
|
253
307
|
def will_and_testament topic,msg
|
254
308
|
if @state==:connected #if already connected, send changes, otherwise wait until connect does it.
|
255
309
|
if @will_topic!=topic
|
@@ -377,106 +431,119 @@ class MqttSN
|
|
377
431
|
end
|
378
432
|
end
|
379
433
|
|
434
|
+
def process_message r
|
435
|
+
m=nil
|
436
|
+
len=r[0].ord
|
437
|
+
case r[len-1].ord
|
438
|
+
when 0x00
|
439
|
+
status=:ok
|
440
|
+
when 0x01
|
441
|
+
status=:rejected_congestion
|
442
|
+
when 0x02
|
443
|
+
status=:rejected_invalid_topic_id
|
444
|
+
when 0x03
|
445
|
+
status=:rejected_not_supported
|
446
|
+
else
|
447
|
+
status=:unknown_error
|
448
|
+
end
|
449
|
+
type_byte=r[1].ord
|
450
|
+
done=false
|
451
|
+
case type_byte
|
452
|
+
when CONNACK_TYPE
|
453
|
+
m={type: :connect_ack,status: status}
|
454
|
+
@state=:connected
|
455
|
+
when SUBACK_TYPE
|
456
|
+
topic_id=(r[3].ord<<8)+r[4].ord
|
457
|
+
msg_id=(r[5].ord<<8)+r[6].ord
|
458
|
+
m={type: :sub_ack, topic_id: topic_id, msg_id: msg_id, status: status}
|
459
|
+
when UNSUBACK_TYPE
|
460
|
+
msg_id=(r[2].ord<<8)+r[3].ord
|
461
|
+
m={type: :unsub_ack, msg_id: msg_id, status: :ok}
|
462
|
+
when PUBLISH_TYPE
|
463
|
+
topic_id=(r[3].ord<<8)+r[4].ord
|
464
|
+
msg_id=(r[5].ord<<8)+r[6].ord
|
465
|
+
msg=r[7,len-7]
|
466
|
+
flags=r[2].ord
|
467
|
+
qos=(flags>>5)&0x03
|
468
|
+
topic=@topics.key(topic_id)
|
469
|
+
m={type: :publish, qos: qos, topic_id: topic_id, topic: topic,msg_id: msg_id, msg: msg,status: :ok}
|
470
|
+
@dataq<<m
|
471
|
+
if not @transfer
|
472
|
+
if qos==1
|
473
|
+
send :publish_ack,topic_id: topic_id, msg_id: msg_id, return_code: 0
|
474
|
+
elsif qos==2
|
475
|
+
send :pub_rec, msg_id: msg_id
|
476
|
+
end
|
477
|
+
done=true
|
478
|
+
end
|
479
|
+
when PUBREL_TYPE
|
480
|
+
msg_id=(r[2].ord<<8)+r[3].ord
|
481
|
+
m={type: :pub_rel, status: :ok}
|
482
|
+
if not @transfer
|
483
|
+
send :pub_comp, msg_id: msg_id
|
484
|
+
done=true
|
485
|
+
end
|
486
|
+
when DISCONNECT_TYPE
|
487
|
+
m={type: :disconnect,status: :ok}
|
488
|
+
@state=:disconnected if not @transfer
|
489
|
+
when REGISTER_TYPE
|
490
|
+
topic_id=(r[2].ord<<8)+r[3].ord
|
491
|
+
msg_id=(r[4].ord<<8)+r[5].ord
|
492
|
+
topic=r[6,len-6]
|
493
|
+
m={type: :register, topic_id: topic_id, msg_id: msg_id, topic: topic,status: :ok}
|
494
|
+
@topics[topic]=m[:topic_id]
|
495
|
+
if not @transfer
|
496
|
+
send :register_ack,topic_id: topic_id, msg_id: msg_id, return_code: 0
|
497
|
+
done=true
|
498
|
+
end
|
499
|
+
when REGACK_TYPE
|
500
|
+
topic_id=(r[2].ord<<8)+r[3].ord
|
501
|
+
m={type: :register_ack,topic_id: topic_id,status: status}
|
502
|
+
when PUBREC_TYPE
|
503
|
+
msg_id=(r[2].ord<<8)+r[3].ord
|
504
|
+
m={type: :pubrec,msg_id: msg_id,status: :ok}
|
505
|
+
when PUBACK_TYPE
|
506
|
+
topic_id=(r[2].ord<<8)+r[3].ord
|
507
|
+
msg_id=(r[4].ord<<8)+r[5].ord
|
508
|
+
m={type: :publish_ack,topic_id: topic_id,msg_id: msg_id, status: status}
|
509
|
+
when PUBCOMP_TYPE
|
510
|
+
msg_id=(r[2].ord<<8)+r[3].ord
|
511
|
+
m={type: :pubcomp,status: :ok, msg_id: msg_id}
|
512
|
+
|
513
|
+
when WILLTOPICREQ_TYPE
|
514
|
+
m={type: :will_topic_req, status: :ok}
|
515
|
+
when WILLMSGREQ_TYPE
|
516
|
+
m={type: :will_msg_req, status: :ok}
|
517
|
+
|
518
|
+
when WILLTOPICRESP_TYPE
|
519
|
+
m={type: :will_topic_resp, status: :ok}
|
520
|
+
when WILLMSGRESP_TYPE
|
521
|
+
m={type: :will_msg_resp, status: :ok}
|
522
|
+
|
523
|
+
when PINGRESP_TYPE
|
524
|
+
m={type: :pong, status: :ok}
|
525
|
+
else
|
526
|
+
m={type: :unknown, type_byte: type_byte }
|
527
|
+
end
|
528
|
+
if @debug and m
|
529
|
+
m[:debug]=hexdump r
|
530
|
+
end
|
531
|
+
if @transfer
|
532
|
+
m[:raw]=r
|
533
|
+
end
|
534
|
+
puts "got :#{@id} #{m.to_json}" if @verbose
|
535
|
+
if not done
|
536
|
+
puts "pushed to q"
|
537
|
+
@iq<<m if m
|
538
|
+
end
|
539
|
+
m
|
540
|
+
end
|
541
|
+
|
380
542
|
def recv_thread
|
381
543
|
while true do
|
382
544
|
begin
|
383
545
|
r,stuff=@s.recvfrom(200) #_nonblock(200)
|
384
|
-
|
385
|
-
len=r[0].ord
|
386
|
-
case r[len-1].ord
|
387
|
-
when 0x00
|
388
|
-
status=:ok
|
389
|
-
when 0x01
|
390
|
-
status=:rejected_congestion
|
391
|
-
when 0x02
|
392
|
-
status=:rejected_invalid_topic_id
|
393
|
-
when 0x03
|
394
|
-
status=:rejected_not_supported
|
395
|
-
else
|
396
|
-
status=:unknown_error
|
397
|
-
end
|
398
|
-
type_byte=r[1].ord
|
399
|
-
done=false
|
400
|
-
case type_byte
|
401
|
-
when CONNACK_TYPE
|
402
|
-
m={type: :connect_ack,status: status}
|
403
|
-
@state=:connected
|
404
|
-
when SUBACK_TYPE
|
405
|
-
topic_id=(r[3].ord<<8)+r[4].ord
|
406
|
-
msg_id=(r[5].ord<<8)+r[6].ord
|
407
|
-
m={type: :sub_ack, topic_id: topic_id, msg_id: msg_id, status: status}
|
408
|
-
when UNSUBACK_TYPE
|
409
|
-
msg_id=(r[2].ord<<8)+r[3].ord
|
410
|
-
m={type: :unsub_ack, msg_id: msg_id, status: :ok}
|
411
|
-
when PUBLISH_TYPE
|
412
|
-
topic_id=(r[3].ord<<8)+r[4].ord
|
413
|
-
msg_id=(r[5].ord<<8)+r[6].ord
|
414
|
-
msg=r[7,len-7]
|
415
|
-
flags=r[2].ord
|
416
|
-
qos=(flags>>5)&0x03
|
417
|
-
topic=@topics.key(topic_id)
|
418
|
-
m={type: :publish, qos: qos, topic_id: topic_id, topic: topic,msg_id: msg_id, msg: msg,status: :ok}
|
419
|
-
@dataq<<m
|
420
|
-
if qos==1
|
421
|
-
send :publish_ack,topic_id: topic_id, msg_id: msg_id, return_code: 0
|
422
|
-
elsif qos==2
|
423
|
-
send :pub_rec, msg_id: msg_id
|
424
|
-
end
|
425
|
-
done=true
|
426
|
-
when PUBREL_TYPE
|
427
|
-
msg_id=(r[2].ord<<8)+r[3].ord
|
428
|
-
m={type: :pub_rel, status: :ok}
|
429
|
-
send :pub_comp, msg_id: msg_id
|
430
|
-
done=true
|
431
|
-
when DISCONNECT_TYPE
|
432
|
-
m={type: :disconnect,status: :ok}
|
433
|
-
@state=:disconnected
|
434
|
-
when REGISTER_TYPE
|
435
|
-
topic_id=(r[2].ord<<8)+r[3].ord
|
436
|
-
msg_id=(r[4].ord<<8)+r[5].ord
|
437
|
-
topic=r[6,len-6]
|
438
|
-
m={type: :register, topic_id: topic_id, msg_id: msg_id, topic: topic,status: :ok}
|
439
|
-
@topics[topic]=m[:topic_id]
|
440
|
-
#pp @topics
|
441
|
-
send :register_ack,topic_id: topic_id, msg_id: msg_id, return_code: 0
|
442
|
-
done=true
|
443
|
-
when REGACK_TYPE
|
444
|
-
topic_id=(r[2].ord<<8)+r[3].ord
|
445
|
-
m={type: :register_ack,topic_id: topic_id,status: status}
|
446
|
-
#@state=:registered
|
447
|
-
when PUBREC_TYPE
|
448
|
-
msg_id=(r[2].ord<<8)+r[3].ord
|
449
|
-
m={type: :pubrec,msg_id: msg_id,status: :ok}
|
450
|
-
when PUBACK_TYPE
|
451
|
-
topic_id=(r[2].ord<<8)+r[3].ord
|
452
|
-
msg_id=(r[4].ord<<8)+r[5].ord
|
453
|
-
m={type: :publish_ack,topic_id: topic_id,msg_id: msg_id, status: status}
|
454
|
-
when PUBCOMP_TYPE
|
455
|
-
msg_id=(r[2].ord<<8)+r[3].ord
|
456
|
-
m={type: :pubcomp,status: :ok, msg_id: msg_id}
|
457
|
-
|
458
|
-
when WILLTOPICREQ_TYPE
|
459
|
-
m={type: :will_topic_req, status: :ok}
|
460
|
-
when WILLMSGREQ_TYPE
|
461
|
-
m={type: :will_msg_req, status: :ok}
|
462
|
-
|
463
|
-
when WILLTOPICRESP_TYPE
|
464
|
-
m={type: :will_topic_resp, status: :ok}
|
465
|
-
when WILLMSGRESP_TYPE
|
466
|
-
m={type: :will_msg_resp, status: :ok}
|
467
|
-
|
468
|
-
when PINGRESP_TYPE
|
469
|
-
m={type: :pong, status: :ok}
|
470
|
-
else
|
471
|
-
m={type: :unknown, type_byte: type_byte }
|
472
|
-
end
|
473
|
-
if @debug and m
|
474
|
-
m[:raw]=hexdump r
|
475
|
-
end
|
476
|
-
puts "got :#{@id} #{m.to_json}" if @verbose
|
477
|
-
if not done
|
478
|
-
@iq<<m if m
|
479
|
-
end
|
546
|
+
process_message r
|
480
547
|
rescue IO::WaitReadable
|
481
548
|
IO.select([@s])
|
482
549
|
retry
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: mqtt-sn-ruby
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.5
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Ari Siitonen
|
@@ -16,9 +16,11 @@ email: jalopuuverstas@gmail.com
|
|
16
16
|
executables:
|
17
17
|
- mqtt-sn-pub.rb
|
18
18
|
- mqtt-sn-sub.rb
|
19
|
+
- mqtt-sn-forwarder.rb
|
19
20
|
extensions: []
|
20
21
|
extra_rdoc_files: []
|
21
22
|
files:
|
23
|
+
- bin/mqtt-sn-forwarder.rb
|
22
24
|
- bin/mqtt-sn-pub.rb
|
23
25
|
- bin/mqtt-sn-sub.rb
|
24
26
|
- lib/mqtt-sn-ruby.rb
|