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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: d8d215dd5f4e11c65675f57b7b4cf605f759931f
4
- data.tar.gz: 8f9072ae324bd014b1051dc0dc7dddfdecf0e1ac
3
+ metadata.gz: cad9bc3bc78a80dccac6baba83cb3e634c13e3a9
4
+ data.tar.gz: 989fdd5fdd51f43bb291740e44368ac411db83d5
5
5
  SHA512:
6
- metadata.gz: 6bd5a86aecc7bc02622e1e6dd7d36b6e45de68f0c5322d7ed221da3a0d129033b0a34110092ac3d4ed8614a69b658ef466afe4fe237d5a0c3814fd1d3b10b695
7
- data.tar.gz: 0bc34db03e72c227dc7faf9e4df00ecd10f8d03cdd6405378938a54a555ff31c4cb893cbfa1da62ac87dd15f3cf82acc3d3b068dd80fdc5a63576a5f68942e4e
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[:raw]=raw if @debug
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
- m=nil
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
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