coap 0.0.16 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (54) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +2 -0
  3. data/.travis.yml +13 -2
  4. data/Gemfile +0 -1
  5. data/LICENSE +2 -2
  6. data/README.md +37 -33
  7. data/Rakefile +12 -3
  8. data/bin/coap +111 -0
  9. data/coap.gemspec +34 -29
  10. data/lib/coap.rb +3 -34
  11. data/lib/core.rb +11 -0
  12. data/lib/core/coap.rb +42 -0
  13. data/lib/core/coap/block.rb +98 -0
  14. data/lib/core/coap/client.rb +314 -0
  15. data/lib/core/coap/coap.rb +26 -0
  16. data/lib/core/coap/coding.rb +146 -0
  17. data/lib/core/coap/fsm.rb +82 -0
  18. data/lib/core/coap/message.rb +203 -0
  19. data/lib/core/coap/observer.rb +40 -0
  20. data/lib/core/coap/options.rb +44 -0
  21. data/lib/core/coap/registry.rb +32 -0
  22. data/lib/core/coap/registry/content_formats.yml +7 -0
  23. data/lib/core/coap/resolver.rb +17 -0
  24. data/lib/core/coap/transmission.rb +165 -0
  25. data/lib/core/coap/types.rb +69 -0
  26. data/lib/core/coap/utility.rb +34 -0
  27. data/lib/core/coap/version.rb +5 -0
  28. data/lib/core/core_ext/socket.rb +19 -0
  29. data/lib/core/hexdump.rb +18 -0
  30. data/lib/core/link.rb +97 -0
  31. data/lib/core/os.rb +15 -0
  32. data/spec/block_spec.rb +160 -0
  33. data/spec/client_spec.rb +86 -0
  34. data/spec/fixtures/coap.me.link +1 -0
  35. data/spec/link_spec.rb +98 -0
  36. data/spec/registry_spec.rb +39 -0
  37. data/spec/resolver_spec.rb +19 -0
  38. data/spec/spec_helper.rb +17 -0
  39. data/spec/transmission_spec.rb +70 -0
  40. data/test/helper.rb +15 -0
  41. data/test/test_client.rb +99 -228
  42. data/test/test_message.rb +99 -71
  43. metadata +140 -37
  44. data/bin/client +0 -42
  45. data/lib/coap/block.rb +0 -45
  46. data/lib/coap/client.rb +0 -364
  47. data/lib/coap/coap.rb +0 -273
  48. data/lib/coap/message.rb +0 -187
  49. data/lib/coap/mysocket.rb +0 -81
  50. data/lib/coap/observer.rb +0 -41
  51. data/lib/coap/version.rb +0 -3
  52. data/lib/misc/hexdump.rb +0 -17
  53. data/test/coap_test_helper.rb +0 -2
  54. data/test/disabled_econotag_blck.rb +0 -33
data/bin/client DELETED
@@ -1,42 +0,0 @@
1
- #!/usr/bin/env ruby
2
- # Usage: client get coap://coap.me:5683/.well-known/core
3
- # Usage: client observe coap://vs0.inf.ethz.ch:5683/obs
4
-
5
- $LOAD_PATH.unshift(File.dirname(__FILE__) + '/../lib')
6
-
7
- require 'coap'
8
-
9
- def observe_callback(data, socket)
10
- pp socket.inspect if $DEBUG
11
- pp data.inspect if $DEBUG
12
- end
13
-
14
- PAYLOAD = 'CLILorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean commodo ligula eget dolor. Aenean massa. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Donec quam felis, ultricies nec, pellentesque eu, pretium quis, sem. Nulla consequat massa quis enim. Donec pede justo, fringilla vel, aliquet nec, vulputate eget, arcu. In enim justo, rhoncus ut, imperdiet a, venenatis vitae, justo. Nullam dictum felis eu pede mollis pretium. Integer tincidunt. Cras dapibus. Vivamus elementum semper nisi. Aenean vulputate eleifend tellus. Aenean leo ligula, porttitor eu, consequat vitae, eleifend ac, enim. Aliquam lorem ante, dapibus in, viverra quis, feugiat a, tellus. Phasellus viverra nulla ut metus varius laoreet. Quisque rutrum. Aenean imperdiet. Etiam ultricies nisi vel augue. Curabitur ullamcorper ultricies nisi. Nam eget dui. Etiam rhoncus. Maecenas tempus, tellus eget condimentum rhoncus, sem quam semper libero, sit amet adipiscing sem neque sed ipsum. Nam quam nunc, blandit vel, luctus pulvinar, hendrerit id, lorem. Maecenas nec odio et ante tincidunt tempus. Donec vitae sapien ut libero venenatis faucibus. Nullam quis ante. Etiam sit amet orci eget eros faucibus tincidunt. Duis leo. Sed fringilla mauris sit amet nibh. Donec sodales sagittis magna. Sed consequat, leo eget bibendum sodales, augue velit cursus nunc,Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean commodo ligula eget dolor. Aenean massa. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Donec quam felis, ultricies nec, pellentesque eu, pretium quis, sem. Nulla consequat massa quis enim. Donec pede justo, fringilla vel, aliquet nec, vulputate eget, arcu. In enim justo, rhoncus ut, imperdiet a, venenatis vitae, justo. Nullam dictum felis eu pede mollis pretium. Integer tincidunt. Cras dapibus. Vivamus elementum semper nisi. Aenean vulputate eleifend tellus. Aenean leo ligula, porttitor eu, consequat vitae, eleifend ac, enim. Aliquam lorem ante, dapibus in, viverra quis, feugiat a, tellus. Phasellus viverra nulla ut metus varius laoreet. Quisque rutrum. Aenean imperdiet. Etiam ultricies nisi vel augue. Curabitur ullamcorper ultricies nisi. Nam eget dui. Etiam rhoncus. Maecenas tempus, tellus eget condimentum rhoncus, sem quam semper libero, sit amet adipiscing sem neque sed ipsum. Nam quam nunc, blandit vel, luctus pulvinar, hendrerit id, lorem. Maecenas nec odio et ante tincidunt tempus. Donec vitae sapien ut libero venenatis faucibus. Nullam quis ante. Etiam sit amet orci eget eros faucibus tincidunt. Duis leo. Sed fringilla mauris sit amet nibh. Donec sodales sagittis magna. Sed consequat, leo eget bibendum sodales, augue velit cursus nuncLorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean commodo ligula eget dolor. Aenean massa. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Donec quam felis, ultricies nec, pellentesque eu, pretium quis, sem. Nulla consequat massa quis enim. Donec pede justo, fringilla vel, aliquet nec, vulputate eget, arcu. In enim justo, rhoncus ut, imperdiet a, venenatis vitae, justo. Nullam dictum felis eu pede mollis pretium. Integer tincidunt. Cras dapibus. Vivamus elementum semper nisi. Aenean vulputate eleifend tellus. Aenean leo ligula, porttitor eu, consequat vitae, eleifend ac, enim. Aliquam lorem ante, dapibus in, viverra quis, feugiat a, tellus. Phasellus viverra nulla ut metus varius laoreet. Quisque rutrum. Aenean imperdiet. Etiam ultricies nisi vel augue. Curabitur ullamcorper ultricies nisi. Nam eget dui. Etiam rhoncus. Maecenas tempus, tellus eget condimentum rhoncus, sem quam semper libero, sit amet adipiscing sem neque sed ipsum. Nam quam nunc, blandit vel, luctus pulvinar, hendrerit id, lorem. Maecenas nec odio et ante tincidunt tempus. Donec vitae sapien ut libero venenatis faucibus. Nullam quis ante. Etiam sit amet orci eget eros faucibus tincidunt. Duis leo. Sed fringilla mauris sit amet nibh. Donec sodales sagittis magna. Sed consequat, leo eget bibendum sodales, augue velit cursus nunc,Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean commodo ligula eget dolor. Aenean massa. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Donec quam felis, ultricies nec, pellentesque eu, pretium quis, sem. Nulla consequat massa quis enim. Donec pede justo, fringilla vel, aliquet nec, vulputate eget, arcu. In enim justo, rhoncus ut, imperdiet a, venenatis vitae, justo. Nullam dictum felis eu pede mollis pretium. Integer tincidunt. Cras dapibus. Vivamus elementum semper nisi. Aenean vulputate eleifend tellus. Aenean leo ligula, porttitor eu, consequat vitae, eleifend ac, enim. Aliquam lorem ante, dapibus in, viverra quis, feugiat a, tellus. Phasellus viverra nulla ut metus varius laoreet. Quisque rutrum. Aenean imperdiet. Etiam ultricies nisi vel augue. Curabitur ullamcorper ultricies nisi. Nam eget dui. Etiam rhoncus. Maecenas tempus, tellus eget condimentum rhoncus, sem quam semper libero, sit amet adipiscing sem neque sed ipsum. Nam quam nunc, blandit vel, luctus pulvinar, hendrerit id, lorem. Maecenas nec odio et ante tincidunt tempus. Donec vitae sapien ut libero venenatis faucibus. Nullam quis ante. Etiam sit amet orci eget eros faucibus tincidunt. Duis leo. Sed fringilla mauris sit amet nibh. Donec sodales sagittis magna. Sed consequat, leo eget bibendum sodales, augue velit cursus nunc,Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean commodo ligula eget dolor. Aenean massa. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Donec quam felis, ultricies nec, pellentesque eu, pretium quis, sem. Nulla consequat massa quis enim. Donec pede justo, fringilla vel, aliquet nec, vulputate eget, arcu. In enim justo, rhoncus ut, imperdiet a, venenatis vitae, justo. Nullam dictum felis eu pede mollis pretium. Integer tincidunt. Cras dapibus. Vivamus elementum semper nisi. Aenean vulputate eleifend tellus. Aenean leo ligula, porttitor eu, consequat vitae, eleifend ac, enim. Aliquam lorem ante, dapibus in, viverra quis, feugiat a, tellus. Phasellus viverra nulla ut metus varius laoreet. Quisque rutrum. Aenean imperdiet. Etiam ultricies nisi vel augue. Curabitur ullamcorper ultricies nisi. Nam eget dui. Etiam rhoncus. Maecenas tempus, tellus eget condimentum rhoncus, sem quam semper libero, sit amet adipiscing sem neque sed ipsum. Nam quam nunc, blandit vel, luctus pulvinar, hendrerit id, lorem. Maecenas nec odio et ante tincidunt tempus. Donec vitae sapien ut libero venenatis faucibus. Nullam quis ante. Etiam sit amet orci eget eros faucibus tincidunt. Duis leo. Sed fringilla mauris sit amet nibh. Donec sodales sagittis magna. Sed consequat, leo eget bibendum sodales, augue velit cursus nunc,Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean commodo ligula eget dolor. Aenean massa. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Donec quam felis, ultricies nec, pellentesque eu, pretium quis, sem. Nulla consequat massa quis enim. Donec pede justo, fringilla vel, aliquet nec, vulputate eget, arcu. In enim justo, rhoncus ut, imperdiet a, venenatis vitae, justo. Nullam dictum felis eu pede mollis pretium. Integer tincidunt. Cras dapibus. Vivamus elementum semper nisi. Aenean vulputate eleifend tellus. Aenean leo ligula, porttitor eu, consequat vitae, eleifend ac, enim. Aliquam lorem ante, dapibus in, viverra quis, feugiat a, tellus. Phasellus viverra nulla ut metus varius laoreet. Quisque rutrum. Aenean imperdiet. Etiam ultricies nisi vel augue. Curabitur ullamcorper ultricies nisi. Nam eget dui. Etiam rhoncus. Maecenas tempus, tellus eget condimentum rhoncus, sem quam semper libero, sit amet adipiscing sem neque sed ipsum. Nam quam nunc, blandit vel, luctus pulvinar, hendrerit id, lorem. Maecenas nec odio et ante tincidunt tempus. Donec vitae sapien ut libero venenatis faucibus. Nullam quis ante. Etiam sit amet orci eget eros faucibus tincidunt. Duis leo. Sed fringilla mauris sit amet nibh. Donec sodales sagittis magna. Sed consequat, leo eget bibendum sodales, augue velit cursus nunc,Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean commodo ligula eget dolor. Aenean massa. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Donec quam felis, ultricies nec, pellentesque eu, pretium quis, sem. Nulla consequat massa quis enim. Donec pede justo, fringilla vel, aliquet nec, vulputate eget, arcu. In enim justo, rhoncus ut, imperdiet a, venenatis vitae, justo. Nullam dictum felis eu pede mollis pretium. Integer tincidunt. Cras dapibus. Vivamus elementum semper nisi. Aenean vulputate eleifend tellus. Aenean leo ligula, porttitor eu, consequat vitae, eleifend ac, enim. Aliquam lorem ante, dapibus in, viverra quis, feugiat a, tellus. Phasellus viverra nulla ut metus varius laoreet. Quisque rutrum. Aenean imperdiet. Etiam ultricies nisi vel augue. Curabitur ullamcorper ultricies nisi. Nam eget dui. Etiam rhoncus. Maecenas tempus, tellus eget condimentum rhoncus, sem quam semper libero, sit amet adipiscing sem neque sed ipsum. Nam quam nunc, blandit vel, luctus pulvinar, hendrerit id, lorem. Maecenas nec odio et ante tincidunt tempus. Donec vitae sapien ut libero venenatis faucibus. Nullam quis ante. Etiam sit amet orci eget eros faucibus tincidunt. Duis leo. Sed fringilla mauris sit amet nibh. Donec sodales sagittis magna. Sed consequat, leo eget bibendum sodales, augue velit cursus nunc,Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean commodo ligula eget dolor. Aenean massa. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Donec quam felis, ultricies nec, pellentesque eu, pretium quis, sem. Nulla consequat massa quis enim. Donec pede justo, fringilla vel, aliquet nec, vulputate eget, arcu. In enim justo, rhoncus ut, imperdiet a, venenatis vitae, justo. Nullam dictum felis eu pede mollis pretium. Integer tincidunt. Cras dapibus. Vivamus elementum semper nisi. Aenean vulputate eleifend tellus. Aenean leo ligula, porttitor eu, consequat vitae, eleifend ac, enim. Aliquam lorem ante, dapibus in, viverra quis, feugiat a, tellus. Phasellus viverra nulla ut metus varius laoreet. Quisque rutrum. Aenean imperdiet. Etiam ultricies nisi vel augue. Curabitur ullamcorper ultricies nisi. Nam eget dui. Etiam rhoncus. Maecenas tempus, tellus eget condimentum rhoncus, sem quam semper libero, sit amet adipiscing sem neque sed ipsum. Nam quam nunc, blandit vel, luctus pulvinar, hendrerit id, lorem. Maecenas nec odio et ante tincidunt tempus. Donec vitae sapien ut libero venenatis faucibus. Nullam quis ante. Etiam sit amet orci eget eros faucibus tincidunt. Duis leo. Sed fringilla mauris sit amet nibh. Donec sodales sagittis magna. Sed consequat, leo eget bibendum sodales, augue velit cursus nuncCLI'
15
-
16
- METHODS = %w(get post put delete observe)
17
-
18
- if ARGV.size >= 2 && METHODS.include?(ARGV[0])
19
- client = CoAP::Client.new
20
- $DEBUG = true
21
- $WIREDUMP = true
22
- require 'pp'
23
-
24
- case ARGV[0]
25
- when 'get'
26
- pp client.get_by_url(ARGV[1])
27
-
28
- when 'post'
29
- pp client.post_by_url(ARGV[1], PAYLOAD)
30
-
31
- when 'put'
32
- pp client.put_by_url(ARGV[1], PAYLOAD)
33
-
34
- when 'delete'
35
- pp client.delete_by_url(ARGV[1])
36
-
37
- when 'observe'
38
- pp client.observe_by_url(ARGV[1], {}, method(:observe_callback))
39
-
40
- end
41
- end
42
- exit
data/lib/coap/block.rb DELETED
@@ -1,45 +0,0 @@
1
- module CoAP
2
- # CoAP client library
3
- class Block
4
- def self.initialize(num, more, szx)
5
- @logger = CoAP.logger
6
-
7
- { more: more, szx: szx, num: num }
8
- end
9
-
10
- def self.encode(num, more, szx)
11
- block = szx | more << 3 | num << 4
12
-
13
- @logger.debug '### CoAP Block encode ###'
14
- @logger.debug block
15
- @logger.debug '### CoAP Block encode ###'
16
-
17
- block
18
- end
19
-
20
- def self.encode_hash(blockHash)
21
- blockHash[:more] ? more = 1 : more = 0
22
- block = blockHash[:szx] | more << 3 | blockHash[:num] << 4
23
-
24
- @logger.debug '### CoAP Block encode ###'
25
- @logger.debug block
26
- @logger.debug '### CoAP Block encode ###'
27
-
28
- block
29
- end
30
-
31
- def self.decode(blockOption)
32
- more = blockOption != nil && (blockOption & 8) === 8
33
- szx = blockOption != nil ? blockOption & 7 : 0
34
- num = blockOption != nil ? blockOption >> 4 : 0
35
-
36
- @logger.debug '### CoAP Block decode ###'
37
- @logger.debug 'm: ' + more.to_s
38
- @logger.debug 'szx: ' + szx.to_s
39
- @logger.debug 'num: ' + num.to_s
40
- @logger.debug '### CoAP Block decode ###'
41
-
42
- { more: more, szx: szx, num: num }
43
- end
44
- end
45
- end
data/lib/coap/client.rb DELETED
@@ -1,364 +0,0 @@
1
- module CoAP
2
-
3
- # CoAP client library
4
- class Client
5
-
6
- # attr_writer
7
- #
8
- # @param max_payload optional payload size, default 256
9
- # @param max_retransmit optional retransmit count, default 4
10
- # @param ack_timeout optional ack_timeout, default 2
11
- # @param hostname dest optional hostname
12
- # @param port dest optional port
13
- attr_writer :max_payload, :max_retransmit, :ack_timeout, :hostname, :port
14
-
15
- # new arguments
16
- #
17
- # @param max_payload optional payload size, default 256
18
- # @param max_retransmit optional retransmit count, default 4
19
- # @param ack_timeout optional ack_timeout, default 2
20
- # @param hostname dest optional hostname
21
- # @param port dest optional port
22
- def initialize(max_payload = 256, max_retransmit = 4, ack_timeout = 2, hostname = nil, port = nil)
23
- @max_payload = max_payload
24
- @max_retransmit = max_retransmit
25
- @ack_timeout = ack_timeout
26
-
27
- @hostname = hostname
28
- @port = port
29
-
30
- # dont change the following stuff
31
- @retry_count = 0
32
-
33
- @MySocket = MySocket.new
34
- @MySocket.socket_type = UDPSocket
35
- @MySocket.ack_timeout = @ack_timeout
36
-
37
- @logger = CoAP.logger
38
- end
39
-
40
- # Enable DTLS Socket
41
- # Needs CoDTLS Gem
42
- def use_dtls
43
- @MySocket = MySocket.new
44
- @MySocket.socket_type = CoDTLS::SecureSocket
45
- @MySocket.ack_timeout = @ack_timeout
46
-
47
- self
48
- end
49
-
50
- def chunk(string, size)
51
- chunks = []
52
- string.bytes.each_slice(size) { |i| chunks << i.pack('C*') }
53
- chunks
54
- # string.scan(/.{1,#{size}}/)
55
- end
56
-
57
- def decode_url(url)
58
- url_decoded = CoAP.scheme_and_authority_decode(url)
59
-
60
- @logger.debug 'url decoded: ' + url_decoded.inspect
61
- fail ArgumentError, 'Invalid URL' if url_decoded.nil?
62
-
63
- url_decoded
64
- end
65
-
66
- # simple coap get
67
- #
68
- # @param url coap scheme + authority url eg coap://coap.me:5683/time
69
- # @param options coap options
70
- #
71
- # @return CoAP::Message #<struct CoAP::Message ver=1, tt=:ack, mcode=[2, 5], mid=866, options={:max_age=>60, :token=>150, :etag=>[16135160785136240028], :content_format=>40, :block2=>226}, payload=\"\\\";ct=50,</5>;rt=\\\"5\\\";ct=50\">"
72
- def get_by_url(url, options = {})
73
- url_decoded = CoAP.scheme_and_authority_decode(url)
74
-
75
- @logger.debug 'url decoded: ' + url_decoded.inspect
76
- fail ArgumentError, 'Invalid URL' if url_decoded.nil?
77
-
78
- get(url_decoded[0], url_decoded[1], url_decoded[2], options)
79
- end
80
-
81
- # simple coap get
82
- #
83
- # @param hostname hostname or ip address
84
- # @param port port to connect to
85
- # @param uri eg /.well-known/core
86
- # @param options coap options
87
- #
88
- # @return CoAP::Message #<struct CoAP::Message ver=1, tt=:ack, mcode=[2, 5], mid=866, options={:max_age=>60, :token=>150, :etag=>[16135160785136240028], :content_format=>40, :block2=>226}, payload=\"\\\";ct=50,</5>;rt=\\\"5\\\";ct=50\">"
89
- def get(hostname, port, uri, options = {})
90
- @retry_count = 0
91
- client(hostname, port, uri, :get, nil, options)
92
- end
93
-
94
- # coap post
95
- #
96
- # @param url coap scheme + authority url eg coap://coap.me:5683/time
97
- # @param payload payload which should be send
98
- # @param options coap options
99
- #
100
- # @return CoAP::Message #<struct CoAP::Message ver=1, tt=:ack, mcode=[2, 5], mid=866, options={:max_age=>60, :token=>150, :etag=>[16135160785136240028], :content_format=>40, :block2=>226}, payload=\"\\\";ct=50,</5>;rt=\\\"5\\\";ct=50\">"
101
- def post_by_url(url, payload, options = {})
102
- url_decoded = CoAP.scheme_and_authority_decode(url)
103
-
104
- @logger.debug 'url decoded: ' + url_decoded.inspect
105
- fail ArgumentError, 'Invalid URL' if url_decoded.nil?
106
-
107
- post(url_decoded[0], url_decoded[1], url_decoded[2], payload, options)
108
- end
109
-
110
- # coap post
111
- #
112
- # @param hostname hostname or ip address
113
- # @param port port to connect to
114
- # @param uri eg /.well-known/core
115
- # @param payload payload which should be send
116
- # @param options coap options
117
- #
118
- # @return CoAP::Message #<struct CoAP::Message ver=1, tt=:ack, mcode=[2, 5], mid=866, options={:max_age=>60, :token=>150, :etag=>[16135160785136240028], :content_format=>40, :block2=>226}, payload=\"\\\";ct=50,</5>;rt=\\\"5\\\";ct=50\">"
119
- def post(hostname, port, uri, payload, options = {})
120
- @retry_count = 0
121
- client(hostname, port, uri, :post, payload, options)
122
- end
123
-
124
- # coap put
125
- #
126
- # @param url coap scheme + authority url eg coap://coap.me:5683/time
127
- # @param payload payload which should be send
128
- # @param options coap options
129
- #
130
- # @return CoAP::Message #<struct CoAP::Message ver=1, tt=:ack, mcode=[2, 5], mid=866, options={:max_age=>60, :token=>150, :etag=>[16135160785136240028], :content_format=>40, :block2=>226}, payload=\"\\\";ct=50,</5>;rt=\\\"5\\\";ct=50\">"
131
- def put_by_url(url, payload, options = {})
132
- url_decoded = CoAP.scheme_and_authority_decode(url)
133
-
134
- @logger.debug 'url decoded: ' + url_decoded.inspect
135
- fail ArgumentError, 'Invalid URL' if url_decoded.nil?
136
-
137
- put(url_decoded[0], url_decoded[1], url_decoded[2], payload, options)
138
- end
139
-
140
- # coap put
141
- #
142
- # @param hostname hostname or ip address
143
- # @param port port to connect to
144
- # @param uri eg /.well-known/core
145
- # @param payload payload which should be send
146
- # @param options coap options
147
- #
148
- # @return CoAP::Message #<struct CoAP::Message ver=1, tt=:ack, mcode=[2, 5], mid=866, options={:max_age=>60, :token=>150, :etag=>[16135160785136240028], :content_format=>40, :block2=>226}, payload=\"\\\";ct=50,</5>;rt=\\\"5\\\";ct=50\">"
149
- def put(hostname, port, uri, payload, options = {})
150
- @retry_count = 0
151
- client(hostname, port, uri, :put, payload, options)
152
- end
153
-
154
- # coap delete
155
- #
156
- # @param url coap scheme + authority url eg coap://coap.me:5683/time
157
- # @param options coap options
158
- #
159
- # @return CoAP::Message #<struct CoAP::Message ver=1, tt=:ack, mcode=[2, 5], mid=866, options={:max_age=>60, :token=>150, :etag=>[16135160785136240028], :content_format=>40, :block2=>226}, payload=\"\\\";ct=50,</5>;rt=\\\"5\\\";ct=50\">"
160
- def delete_by_url(hostname, port, uri, options = {})
161
- url_decoded = CoAP.scheme_and_authority_decode(url)
162
-
163
- @logger.debug 'url decoded: ' + url_decoded.inspect
164
- fail ArgumentError, 'Invalid URL' if url_decoded.nil?
165
-
166
- delete(url_decoded[0], url_decoded[1], url_decoded[2], options)
167
- end
168
-
169
- # coap delete
170
- #
171
- # @param hostname hostname or ip address
172
- # @param port port to connect to
173
- # @param uri eg /.well-known/core
174
- # @param options coap options
175
- #
176
- # @return CoAP::Message #<struct CoAP::Message ver=1, tt=:ack, mcode=[2, 5], mid=866, options={:max_age=>60, :token=>150, :etag=>[16135160785136240028], :content_format=>40, :block2=>226}, payload=\"\\\";ct=50,</5>;rt=\\\"5\\\";ct=50\">"
177
- def delete(hostname, port, uri, options = {})
178
- @retry_count = 0
179
- client(hostname, port, uri, :delete, nil, options)
180
- end
181
-
182
- # coap observe
183
- #
184
- # @param url coap scheme + authority url eg coap://coap.me:5683/time
185
- # @param options coap options
186
- # @param callback method to call with the observe data eg. observe_callback(payload, socket)
187
- #
188
- def observe_by_url(hostname, port, uri, callback, options = {})
189
- url_decoded = CoAP.scheme_and_authority_decode(url)
190
-
191
- @logger.debug 'url decoded: ' + url_decoded.inspect
192
- fail ArgumentError, 'Invalid URL' if url_decoded.nil?
193
-
194
- observe(url_decoded[0], url_decoded[1], url_decoded[2], callback, options)
195
- end
196
-
197
- # coap observe
198
- #
199
- # @param hostname hostname or ip address
200
- # @param port port to connect to
201
- # @param uri eg /.well-known/core
202
- # @param options coap options
203
- # @param callback method to call with the observe data eg. observe_callback(payload, socket)
204
- #
205
- def observe(hostname, port, uri, callback, options = {})
206
- options[:observe] = 0
207
- client(hostname, port, uri, :get, nil, options, callback)
208
- end
209
-
210
- # custom client for special use
211
- #
212
- # @param url coap scheme + authority url eg coap://coap.me:5683/time
213
- # @param method string get post put delete etc
214
- # @param payload message payload
215
- # @param options coap options
216
- #
217
- # @return CoAP::Message #<struct CoAP::Message ver=1, tt=:ack, mcode=[2, 5], mid=866, options={:max_age=>60, :token=>150, :etag=>[16135160785136240028], :content_format=>40, :block2=>226}, payload=\"\\\";ct=50,</5>;rt=\\\"5\\\";ct=50\">"
218
- def custom(url, method, payload = nil, options = {})
219
-
220
- url_decoded = decode_url url
221
- client(url_decoded[0], url_decoded[1], url_decoded[2], method.to_sym, payload, options)
222
-
223
- end
224
-
225
- private
226
-
227
- def client(hostname, port, uri, method, payload, options, observe_callback = nil)
228
-
229
- # set hostname + port only one time on multiple requests
230
- hostname.nil? ? (hostname = @hostname unless @hostname.nil?) : @hostname = hostname
231
- port.nil? ? (port = @port unless @port.nil?) : @port = port
232
-
233
- # Error handling for paramaters
234
- fail ArgumentError, 'hostname missing' if hostname.nil? || hostname.empty?
235
- fail ArgumentError, 'port missing' if port.nil?
236
- fail ArgumentError, 'port must ba an integer' unless port.is_a? Integer
237
- fail ArgumentError, 'uri missing' if uri.nil? || uri.empty?
238
- fail ArgumentError, 'payload must be a string' unless payload.is_a? String unless payload.nil?
239
- fail ArgumentError, 'payload shouldnt be empty ' if payload.empty? unless payload.nil?
240
-
241
- # generate random message id
242
- mid = Random.rand(999)
243
- token = Random.rand(256)
244
- szx = Math.log2(@max_payload).floor - 4
245
-
246
- # initialize block 2 with payload size
247
- block2 = Block.initialize(0, false, szx)
248
-
249
- # initialize block1 if set
250
- block1 = options[:block1].nil? ? Block.initialize(0, false, szx) : Block.decode(options[:block1])
251
-
252
- # initialize chunks if payload size > max_payload
253
- chunks = chunk(payload, 2**((Math.log2(@max_payload).floor - 4) + 4)) unless payload.nil?
254
-
255
- # create coap message struct
256
- message = Message.new(:con, method, mid, nil, {})
257
- # , block2: Block.encode_hash(block2)
258
- message.options = { uri_path: CoAP.path_decode(uri), token: token }
259
- message.options[:block2] = Block.encode_hash(block2) if @max_payload != 256 # temp fix to disable early negotation
260
- message.payload = payload unless payload.nil?
261
-
262
- ### initialize stuff end
263
-
264
- # if chunks.size 1 > we need to use block1
265
- if !payload.nil? and chunks.size > 1
266
- # increase block number
267
- block1[:num] += 1 unless options[:block1].nil?
268
- # more ?
269
- block1[:more] = chunks.size > block1[:num] + 1
270
- chunks.size > block1[:num] + 1 ? message.options.delete(:block2) : block1[:more] = false
271
- # set final payload
272
- message.payload = chunks[block1[:num]]
273
- # set message option
274
- message.options[:block1] = Block.encode_hash(block1)
275
- end
276
-
277
- # preserve user options
278
- message.options[:block2] = options[:block2] unless options[:block2] == nil
279
- message.options[:observe] = options[:observe] unless options[:observe] == nil
280
- message.options.merge(options)
281
-
282
- # debug functions
283
- @logger.debug '### CoAP Send Data ###'
284
- #@logger.debug message.to_s.hexdump
285
- @logger.debug message.inspect
286
- @logger.debug '### CoAP Send Data ###'
287
-
288
- # connect via udp/dtls
289
- @MySocket.connect hostname, port
290
- @MySocket.send message.to_wire, 0
291
-
292
- # send message + retry
293
- begin
294
- recv_data = @MySocket.receive
295
- rescue Timeout::Error
296
- @retry_count += 1
297
- raise 'Retry Timeout ' + @retry_count.to_s if @retry_count > @max_retransmit
298
- return client(hostname, port, uri, method, payload, options, observe_callback)
299
- end
300
-
301
- # parse recv data
302
- recv_parsed = CoAP.parse(recv_data[0].force_encoding('BINARY'))
303
-
304
- # debug functions
305
- @logger.debug '### CoAP Received Data ###'
306
- #@logger.debug recv_parsed.to_s.hexdump
307
- @logger.debug recv_parsed.inspect
308
- @logger.debug '### CoAP Received Data ###'
309
-
310
- # payload is not fully transmitted
311
- if block1[:more]
312
- fail 'Max Recursion' if @retry_count > 10
313
- return client(hostname, port, uri, method, payload, message.options)
314
- end
315
-
316
- # separate ?
317
- if recv_parsed.tt == :ack && recv_parsed.payload.empty? && recv_parsed.mid == mid && recv_parsed.mcode[0] == 0 && recv_parsed.mcode[1] == 0
318
- @logger.debug '### SEPARATE REQUEST ###'
319
-
320
- # wait for answer ...
321
- recv_data = @MySocket.receive(600, @retry_count)
322
- recv_parsed = CoAP.parse(recv_data[0].force_encoding('BINARY'))
323
-
324
- # debug functions
325
- @logger.debug '### CoAP SEPARAT Data ###'
326
- #@logger.debug recv_parsed.to_s.hexdump
327
- @logger.debug recv_parsed.inspect
328
- @logger.debug '### CoAP SEPARAT Data ###'
329
-
330
- if recv_parsed.tt == :con
331
- message = Message.new(:ack, 0, recv_parsed.mid, nil, {})
332
- message.options = { token: recv_parsed.options[:token] }
333
- @MySocket.send message.to_wire, 0
334
- end
335
-
336
- @logger.debug '### SEPARATE REQUEST END ###'
337
- end
338
-
339
- # test for more block2 payload
340
- block2 = Block.decode(recv_parsed.options[:block2])
341
-
342
- if block2[:more]
343
- block2[:num] += 1
344
-
345
- options.delete(:block1) # end block1
346
- options[:block2] = Block.encode_hash(block2)
347
- fail 'Max Recursion' if @retry_count > 50
348
- local_recv_parsed = client(hostname, port, uri, method, nil, options)
349
- recv_parsed.payload << local_recv_parsed.payload unless local_recv_parsed.nil?
350
- end
351
-
352
- # do we need to observe?
353
- if recv_parsed.options[:observe]
354
- @Observer = CoAP::Observer.new
355
- @Observer.observe(recv_parsed, recv_data, observe_callback, @MySocket)
356
- end
357
-
358
- # this is bad
359
- fail ArgumentError, 'wrong token returned' if recv_parsed.options[:token] != token # create own error class
360
-
361
- recv_parsed
362
- end
363
- end
364
- end