maxcube-client 0.4.1 → 0.5.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.
Files changed (109) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +6 -0
  3. data/.rubocop.yml +0 -3
  4. data/.yardopts +1 -0
  5. data/README.md +17 -2
  6. data/bin/maxcube-client +2 -27
  7. data/doc/MaxCube.html +502 -0
  8. data/doc/MaxCube/Messages.html +1927 -0
  9. data/doc/MaxCube/Messages/Handler.html +2912 -0
  10. data/doc/MaxCube/Messages/InvalidMessage.html +140 -0
  11. data/doc/MaxCube/Messages/InvalidMessageBody.html +264 -0
  12. data/doc/MaxCube/Messages/InvalidMessageFormat.html +247 -0
  13. data/doc/MaxCube/Messages/InvalidMessageLength.html +247 -0
  14. data/doc/MaxCube/Messages/InvalidMessageType.html +263 -0
  15. data/doc/MaxCube/Messages/Parser.html +520 -0
  16. data/doc/MaxCube/Messages/Serializer.html +701 -0
  17. data/doc/MaxCube/Messages/TCP.html +172 -0
  18. data/doc/MaxCube/Messages/TCP/Handler.html +1396 -0
  19. data/doc/MaxCube/Messages/TCP/Parser.html +462 -0
  20. data/doc/MaxCube/Messages/TCP/Parser/MessageA.html +186 -0
  21. data/doc/MaxCube/Messages/TCP/Parser/MessageC.html +1077 -0
  22. data/doc/MaxCube/Messages/TCP/Parser/MessageF.html +206 -0
  23. data/doc/MaxCube/Messages/TCP/Parser/MessageH.html +338 -0
  24. data/doc/MaxCube/Messages/TCP/Parser/MessageL.html +535 -0
  25. data/doc/MaxCube/Messages/TCP/Parser/MessageM.html +510 -0
  26. data/doc/MaxCube/Messages/TCP/Parser/MessageN.html +226 -0
  27. data/doc/MaxCube/Messages/TCP/Parser/MessageS.html +225 -0
  28. data/doc/MaxCube/Messages/TCP/Serializer.html +460 -0
  29. data/doc/MaxCube/Messages/TCP/Serializer/MessageA.html +186 -0
  30. data/doc/MaxCube/Messages/TCP/Serializer/MessageC.html +185 -0
  31. data/doc/MaxCube/Messages/TCP/Serializer/MessageF.html +206 -0
  32. data/doc/MaxCube/Messages/TCP/Serializer/MessageL.html +185 -0
  33. data/doc/MaxCube/Messages/TCP/Serializer/MessageM.html +428 -0
  34. data/doc/MaxCube/Messages/TCP/Serializer/MessageN.html +209 -0
  35. data/doc/MaxCube/Messages/TCP/Serializer/MessageQ.html +185 -0
  36. data/doc/MaxCube/Messages/TCP/Serializer/MessageS.html +1168 -0
  37. data/doc/MaxCube/Messages/TCP/Serializer/MessageT.html +240 -0
  38. data/doc/MaxCube/Messages/TCP/Serializer/MessageU.html +206 -0
  39. data/doc/MaxCube/Messages/TCP/Serializer/MessageZ.html +252 -0
  40. data/doc/MaxCube/Messages/UDP.html +164 -0
  41. data/doc/MaxCube/Messages/UDP/Handler.html +832 -0
  42. data/doc/MaxCube/Messages/UDP/Parser.html +609 -0
  43. data/doc/MaxCube/Messages/UDP/Parser/MessageH.html +218 -0
  44. data/doc/MaxCube/Messages/UDP/Parser/MessageI.html +215 -0
  45. data/doc/MaxCube/Messages/UDP/Parser/MessageN.html +226 -0
  46. data/doc/MaxCube/Messages/UDP/Serializer.html +484 -0
  47. data/doc/MaxCube/Network.html +167 -0
  48. data/doc/MaxCube/Network/TCP.html +150 -0
  49. data/doc/MaxCube/Network/TCP/Client.html +1930 -0
  50. data/doc/MaxCube/Network/TCP/Client/Commands.html +2457 -0
  51. data/doc/MaxCube/Network/TCP/SampleServer.html +910 -0
  52. data/doc/MaxCube/Network/UDP.html +150 -0
  53. data/doc/MaxCube/Network/UDP/Client.html +518 -0
  54. data/doc/MaxCube/Network/UDP/SampleSocket.html +628 -0
  55. data/doc/MaxCube/Runner.html +355 -0
  56. data/doc/_index.html +518 -0
  57. data/doc/class_list.html +51 -0
  58. data/doc/css/common.css +1 -0
  59. data/doc/css/full_list.css +58 -0
  60. data/doc/css/style.css +499 -0
  61. data/doc/file.README.html +140 -0
  62. data/doc/file_list.html +56 -0
  63. data/doc/frames.html +17 -0
  64. data/doc/index.html +140 -0
  65. data/doc/js/app.js +248 -0
  66. data/doc/js/full_list.js +216 -0
  67. data/doc/js/jquery.js +4 -0
  68. data/doc/method_list.html +1699 -0
  69. data/doc/top-level-namespace.html +110 -0
  70. data/lib/maxcube.rb +11 -0
  71. data/lib/maxcube/messages.rb +85 -8
  72. data/lib/maxcube/messages/handler.rb +138 -4
  73. data/lib/maxcube/messages/parser.rb +33 -2
  74. data/lib/maxcube/messages/serializer.rb +64 -16
  75. data/lib/maxcube/messages/tcp.rb +11 -7
  76. data/lib/maxcube/messages/tcp/handler.rb +50 -2
  77. data/lib/maxcube/messages/tcp/parser.rb +18 -17
  78. data/lib/maxcube/messages/tcp/serializer.rb +20 -21
  79. data/lib/maxcube/messages/tcp/type/a.rb +6 -6
  80. data/lib/maxcube/messages/tcp/type/c.rb +5 -3
  81. data/lib/maxcube/messages/tcp/type/f.rb +5 -3
  82. data/lib/maxcube/messages/tcp/type/h.rb +3 -2
  83. data/lib/maxcube/messages/tcp/type/l.rb +8 -7
  84. data/lib/maxcube/messages/tcp/type/m.rb +11 -7
  85. data/lib/maxcube/messages/tcp/type/n.rb +5 -3
  86. data/lib/maxcube/messages/tcp/type/q.rb +2 -2
  87. data/lib/maxcube/messages/tcp/type/s.rb +5 -2
  88. data/lib/maxcube/messages/tcp/type/t.rb +5 -4
  89. data/lib/maxcube/messages/tcp/type/u.rb +2 -1
  90. data/lib/maxcube/messages/tcp/type/z.rb +4 -2
  91. data/lib/maxcube/messages/udp.rb +7 -0
  92. data/lib/maxcube/messages/udp/handler.rb +28 -0
  93. data/lib/maxcube/messages/udp/parser.rb +23 -6
  94. data/lib/maxcube/messages/udp/serializer.rb +17 -1
  95. data/lib/maxcube/messages/udp/type/h.rb +2 -0
  96. data/lib/maxcube/messages/udp/type/i.rb +3 -0
  97. data/lib/maxcube/messages/udp/type/n.rb +3 -0
  98. data/lib/maxcube/network.rb +5 -1
  99. data/lib/maxcube/network/tcp.rb +3 -0
  100. data/lib/maxcube/network/tcp/client.rb +117 -3
  101. data/lib/maxcube/network/tcp/client/commands.rb +306 -239
  102. data/lib/maxcube/network/tcp/sample_server.rb +1 -0
  103. data/lib/maxcube/network/udp.rb +3 -0
  104. data/lib/maxcube/network/udp/client.rb +2 -0
  105. data/lib/maxcube/network/udp/sample_socket.rb +1 -0
  106. data/lib/maxcube/runner.rb +45 -0
  107. data/lib/maxcube/version.rb +2 -1
  108. data/maxcube-client.gemspec +2 -0
  109. metadata +84 -3
@@ -0,0 +1,110 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <meta charset="utf-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>
7
+ Top Level Namespace
8
+
9
+ &mdash; Documentation by YARD 0.9.12
10
+
11
+ </title>
12
+
13
+ <link rel="stylesheet" href="css/style.css" type="text/css" charset="utf-8" />
14
+
15
+ <link rel="stylesheet" href="css/common.css" type="text/css" charset="utf-8" />
16
+
17
+ <script type="text/javascript" charset="utf-8">
18
+ pathId = "";
19
+ relpath = '';
20
+ </script>
21
+
22
+
23
+ <script type="text/javascript" charset="utf-8" src="js/jquery.js"></script>
24
+
25
+ <script type="text/javascript" charset="utf-8" src="js/app.js"></script>
26
+
27
+
28
+ </head>
29
+ <body>
30
+ <div class="nav_wrap">
31
+ <iframe id="nav" src="class_list.html?1"></iframe>
32
+ <div id="resizer"></div>
33
+ </div>
34
+
35
+ <div id="main" tabindex="-1">
36
+ <div id="header">
37
+ <div id="menu">
38
+
39
+ <a href="_index.html">Index</a> &raquo;
40
+
41
+
42
+ <span class="title">Top Level Namespace</span>
43
+
44
+ </div>
45
+
46
+ <div id="search">
47
+
48
+ <a class="full_list_link" id="class_list_link"
49
+ href="class_list.html">
50
+
51
+ <svg width="24" height="24">
52
+ <rect x="0" y="4" width="24" height="4" rx="1" ry="1"></rect>
53
+ <rect x="0" y="12" width="24" height="4" rx="1" ry="1"></rect>
54
+ <rect x="0" y="20" width="24" height="4" rx="1" ry="1"></rect>
55
+ </svg>
56
+ </a>
57
+
58
+ </div>
59
+ <div class="clear"></div>
60
+ </div>
61
+
62
+ <div id="content"><h1>Top Level Namespace
63
+
64
+
65
+
66
+ </h1>
67
+ <div class="box_info">
68
+
69
+
70
+
71
+
72
+
73
+
74
+
75
+
76
+
77
+
78
+
79
+ </div>
80
+
81
+ <h2>Defined Under Namespace</h2>
82
+ <p class="children">
83
+
84
+
85
+ <strong class="modules">Modules:</strong> <span class='object_link'><a href="MaxCube.html" title="MaxCube (module)">MaxCube</a></span>
86
+
87
+
88
+
89
+
90
+ </p>
91
+
92
+
93
+
94
+
95
+
96
+
97
+
98
+
99
+
100
+ </div>
101
+
102
+ <div id="footer">
103
+ Generated on Fri Feb 16 13:44:01 2018 by
104
+ <a href="http://yardoc.org" title="Yay! A Ruby Documentation Tool" target="_parent">yard</a>
105
+ 0.9.12 (ruby-2.5.0).
106
+ </div>
107
+
108
+ </div>
109
+ </body>
110
+ </html>
data/lib/maxcube.rb CHANGED
@@ -1,4 +1,5 @@
1
1
  require 'date'
2
+ require 'time'
2
3
  require 'pathname'
3
4
  require 'ipaddr'
4
5
 
@@ -6,19 +7,29 @@ require 'pp'
6
7
 
7
8
  require 'maxcube/version'
8
9
 
10
+ # Root project module that contains only project-related utilities
9
11
  module MaxCube
12
+ # Gets path to project root directory
13
+ # @return [String] path to project root directory
10
14
  def self.root_dir
11
15
  File.dirname __dir__
12
16
  end
13
17
 
18
+ # Gets path to +bin/+ project directory with executables
19
+ # @return [String] path to +bin/+ project directory
14
20
  def self.bin_dir
15
21
  File.join(root_dir, 'bin')
16
22
  end
17
23
 
24
+ # Gets path to +lib/+ project directory with Ruby source files
25
+ # @return [String] path to +lib/+ project directory
18
26
  def self.lib_dir
19
27
  File.join(root_dir, 'lib')
20
28
  end
21
29
 
30
+ # Gets path to +data/+ project directory
31
+ # with input/output data for clients and servers
32
+ # @return [String] path to +data/+ project directory
22
33
  def self.data_dir
23
34
  File.join(root_dir, 'data')
24
35
  end
@@ -1,39 +1,58 @@
1
1
  require 'maxcube'
2
2
 
3
3
  module MaxCube
4
+ # Encapsulates methods related to Cube messages,
5
+ # i.e. parsing and serializing of TCP/UDP messages.
6
+ # It does not provide any network features
7
+ # (this is responsibility of {Network}.
4
8
  module Messages
9
+ # Device modes that determines geating scheduling.
5
10
  DEVICE_MODE = %i[auto manual vacation boost].freeze
11
+ # Device types identified in Cube protocol.
6
12
  DEVICE_TYPE = %i[cube
7
13
  radiator_thermostat radiator_thermostat_plus
8
14
  wall_thermostat
9
15
  shutter_contact eco_switch].freeze
10
16
 
17
+ # Names of days of week in order Cube protocol uses.
11
18
  DAYS_OF_WEEK = %w[Saturday Sunday Monday
12
19
  Tuesday Wednesday Thursday Friday].freeze
13
20
 
14
- PACK_FORMAT = %w[x C n N N].freeze
15
-
21
+ # Base exception class
22
+ # that denotes an error during message parsing/serializing.
16
23
  class InvalidMessage < RuntimeError; end
17
24
 
25
+ # Exception class that denotes that message is too short/long.
18
26
  class InvalidMessageLength < InvalidMessage
27
+ # @param info contains context information to occured error.
19
28
  def initialize(info = 'invalid message length')
20
29
  super
21
30
  end
22
31
  end
23
32
 
33
+ # Exception class that denotes unrecognized message type.
24
34
  class InvalidMessageType < InvalidMessage
35
+ # @param msg_type type of message that is being parsed/serialized.
36
+ # @param info contains context information to occured error.
25
37
  def initialize(msg_type, info = 'invalid message type')
26
38
  super("#{info}: #{msg_type}")
27
39
  end
28
40
  end
29
41
 
42
+ # Exception class that denotes invalid syntax format of message.
30
43
  class InvalidMessageFormat < InvalidMessage
44
+ # @param info contains context information to occured error.
31
45
  def initialize(info = 'invalid format')
32
46
  super
33
47
  end
34
48
  end
35
49
 
50
+ # Exception class that denotes that an error occured
51
+ # while parsing/serializing message body,
52
+ # which is specific to message type.
36
53
  class InvalidMessageBody < InvalidMessage
54
+ # @param msg_type type of message that is being parsed/serialized.
55
+ # @param info contains context information to occured error.
37
56
  def initialize(msg_type, info = 'invalid format')
38
57
  super("message type #{msg_type}: #{info}")
39
58
  end
@@ -41,6 +60,17 @@ module MaxCube
41
60
 
42
61
  private
43
62
 
63
+ # Applies a block to given arguments
64
+ # in order to perform conversion to certain type.
65
+ # If conversion fails, {InvalidMessageBody} is raised.
66
+ # Thus, this method can be used also for type checking purposes only.
67
+ # @param type [#to_s] name of the type to convert to.
68
+ # @param info [#to_s] context information to pass to raised error.
69
+ # @param args [Array] arguments to be converted into the same type.
70
+ # @yield a rule to provide
71
+ # certain type check and conversion of arguments.
72
+ # @return [Array] converted elements.
73
+ # @raise [InvalidMessageBody] if conversion fails.
44
74
  def conv_args(type, info, *args, &block)
45
75
  info = info.to_s.tr('_', ' ')
46
76
  args.map(&block)
@@ -50,25 +80,44 @@ module MaxCube
50
80
  "invalid #{type} format of arguments #{args} (#{info})")
51
81
  end
52
82
 
53
- # Convert string of characters (not binary data!) to hex number
54
- # For binary data use #String.unpack
83
+ # Uses {#conv_args} to convert numbers
84
+ # or string of characters (not binary data!)
85
+ # to integers in given base (radix).
86
+ # For binary data use {Parser#read}.
87
+ # @param base [Integer] integers base (radix), 0 means auto-recognition.
88
+ # @param args [Array<#Integer>] arguments to convert to integers.
89
+ # @return [Array<Integer>] converted elements.
55
90
  def to_ints(base, info, *args)
56
91
  base_str = base.zero? ? '' : "(#{base})"
57
92
  conv_args("integer#{base_str}", info, *args) { |x| Integer(x, base) }
58
93
  end
59
94
 
95
+ # Uses {#to_ints}, but operates with single argument.
96
+ # @param arg [#Integer] argument to convert to integer.
97
+ # @return [Integer] converted element.
60
98
  def to_int(base, info, arg)
61
99
  to_ints(base, info, arg).first
62
100
  end
63
101
 
102
+ # Uses {#conv_args} to convert numbers
103
+ # or string of characters (not binary data!) to floats.
104
+ # @param args [Array<#Float>] arguments to convert to floats.
105
+ # @return [Array<Float>] converted elements.
64
106
  def to_floats(info, *args)
65
107
  conv_args('float', info, *args) { |x| Float(x) }
66
108
  end
67
109
 
110
+ # Uses {#to_floats}, but operates with single argument.
111
+ # @param arg [#Float] argument to convert to float.
112
+ # @return [Float] converted element.
68
113
  def to_float(info, arg)
69
114
  to_floats(info, arg).first
70
115
  end
71
116
 
117
+ # Uses {#conv_args} to convert objects to bools.
118
+ # @param args [Array] arguments to convert to bools.
119
+ # @return [Array<Boolean>] converted elements
120
+ # to +TrueClass+ or +FalseClass+.
72
121
  def to_bools(info, *args)
73
122
  conv_args('boolean', info, *args) do |arg|
74
123
  if arg == !!arg
@@ -83,26 +132,47 @@ module MaxCube
83
132
  end
84
133
  end
85
134
 
135
+ # Uses {#to_bools}, but operates with single argument.
136
+ # @param arg argument to convert to bool.
137
+ # @return [Boolean] converted element
138
+ # to +TrueClass+ or +FalseClass+.
86
139
  def to_bool(info, arg)
87
140
  to_bools(info, arg).first
88
141
  end
89
142
 
143
+ # Uses {#conv_args} to convert objects to +Time+.
144
+ # @param args [Array] arguments to convert to +Time+.
145
+ # @return [Array<Time>] converted elements.
90
146
  def to_datetimes(info, *args)
91
147
  conv_args('datetime', info, *args) do |arg|
92
- if arg.is_a?(DateTime)
148
+ if arg.is_a?(Time)
93
149
  arg
94
- elsif arg.respond_to?('to_datetime')
95
- arg.to_datetime
150
+ elsif arg.is_a?(String)
151
+ Time.parse(arg)
152
+ elsif arg.respond_to?('to_time')
153
+ arg.to_time
154
+ elsif arg.respond_to?('to_date')
155
+ arg.to_date.to_time
96
156
  else
97
- DateTime.parse(arg)
157
+ raise ArgumentError
98
158
  end
99
159
  end
100
160
  end
101
161
 
162
+ # Uses {#to_datetime}, but operates with single argument.
163
+ # @param arg argument to convert to +Time+.
164
+ # @return [Time] converted element.
102
165
  def to_datetime(info, arg)
103
166
  to_datetimes(info, arg).first
104
167
  end
105
168
 
169
+ # Helper method that checks presence of index in array
170
+ # (if not, exception is raised).
171
+ # @param ary [#[]] input container (usually constant).
172
+ # @param id index of element in container.
173
+ # @param info [#to_s] context information to pass to raised error.
174
+ # @return element of container if found.
175
+ # @raise [InvalidMessageBody] if element not found.
106
176
  def ary_elem(ary, id, info)
107
177
  elem = ary[id]
108
178
  return elem if elem
@@ -110,6 +180,7 @@ module MaxCube
110
180
  .new(@msg_type, "unrecognized #{info} id: #{id}")
111
181
  end
112
182
 
183
+ # Reverse method to {#ary_elem}.
113
184
  def ary_elem_id(ary, elem, info)
114
185
  id = ary.index(elem)
115
186
  return id if id
@@ -117,26 +188,32 @@ module MaxCube
117
188
  .new(@msg_type, "unrecognized #{info}: #{elem}")
118
189
  end
119
190
 
191
+ # Uses {#ary_elem} with {DEVICE_TYPE}
120
192
  def device_type(device_type_id)
121
193
  ary_elem(DEVICE_TYPE, device_type_id, 'device type')
122
194
  end
123
195
 
196
+ # Uses {#ary_elem_id} with {DEVICE_TYPE}
124
197
  def device_type_id(device_type)
125
198
  ary_elem_id(DEVICE_TYPE, device_type.to_sym, 'device type')
126
199
  end
127
200
 
201
+ # Uses {#ary_elem} with {DEVICE_MODE}
128
202
  def device_mode(device_mode_id)
129
203
  ary_elem(DEVICE_MODE, device_mode_id, 'device mode')
130
204
  end
131
205
 
206
+ # Uses {#ary_elem_id} with {DEVICE_MODE}
132
207
  def device_mode_id(device_mode)
133
208
  ary_elem_id(DEVICE_MODE, device_mode.to_sym, 'device mode')
134
209
  end
135
210
 
211
+ # Uses {#ary_elem} with {DAYS_OF_WEEK}
136
212
  def day_of_week(day_id)
137
213
  ary_elem(DAYS_OF_WEEK, day_id, 'day of week')
138
214
  end
139
215
 
216
+ # Uses {#ary_elem_id} with {DAYS_OF_WEEK}
140
217
  def day_of_week_id(day)
141
218
  if day.respond_to?('to_i') && day.to_i.between?(1, 7)
142
219
  return (day.to_i + 1) % 7
@@ -5,74 +5,147 @@ require 'maxcube/messages'
5
5
 
6
6
  module MaxCube
7
7
  module Messages
8
+ # This module provides methods that handles with messages
9
+ # regardless whether it is for parse or serialize purposes.
10
+ # It mostly contains methods that validates (returns Boolean)
11
+ # or checks (raises exception on failure) some part of message.
8
12
  module Handler
9
13
  include Messages
10
14
 
15
+ # Format characters to String#unpack and Array#pack,
16
+ # for purposes to convert binary string to integer.
17
+ # Elements are sorted by integer size in bytes.
18
+ PACK_FORMAT = %w[x C n N N].freeze
19
+
20
+ # Checks whether raw data string is +String+.
21
+ # @param raw_data input raw data string.
22
+ # @return [Boolean] +true+ if argument is +String+, +false+ otherwise.
11
23
  def valid_data_type(raw_data)
12
24
  raw_data.is_a?(String)
13
25
  end
14
26
 
27
+ # Checks whether {#valid_data_type} is +true+.
28
+ # If not, exception is raised.
29
+ # @return [String] input raw data string.
30
+ # @raise [TypeError] if argument is _not_ valid.
15
31
  def check_data_type(raw_data)
16
32
  raise TypeError unless valid_data_type(raw_data)
17
33
  raw_data
18
34
  end
19
35
 
36
+ # Validates whether message type character is valid.
37
+ # Calls {#maybe_check_valid_msg_type}.
38
+ # @param msg_type [String] input message type character.
39
+ # @return [Boolean] +true+ if argument is valid message type.
20
40
  def valid_msg_type(msg_type)
21
41
  maybe_check_valid_msg_type(msg_type, false)
22
42
  end
23
43
 
44
+ # Checks whether message type character is valid.
45
+ # Calls {#maybe_check_valid_msg_type}.
46
+ # If argument is valid, it assigns the message type to internal variable.
47
+ # @param msg_type [String] input message type character.
48
+ # @return [String] message type character assigned to internal variable.
49
+ # @raise [InvalidMessageType] if validation fails.
24
50
  def check_msg_type(msg_type)
25
51
  maybe_check_valid_msg_type(msg_type, true)
26
52
  @msg_type
27
53
  end
28
54
 
55
+ # Validates whether message type character of message is valid.
56
+ # Calls {#valid_msg_type} and #msg_msg_type
57
+ # (this method depends on conrete end-class).
58
+ # @param msg [String] input message.
29
59
  def valid_msg_msg_type(msg)
30
60
  valid_msg_type(msg_msg_type(msg))
31
61
  end
32
62
 
63
+ # Checks whether message type character of message is valid.
64
+ # Calls {#check_msg_type} and #msg_msg_type
65
+ # (this method depends on conrete end-class).
66
+ # If argument is valid, it assigns the message type to internal variable.
67
+ # @param msg [String] input message.
33
68
  def check_msg_msg_type(msg)
34
69
  check_msg_type(msg_msg_type(msg))
35
70
  end
36
71
 
72
+ # Validates whether whole message is valid
73
+ # from general point of view, independently of parser/sserializer.
74
+ # Currently, it just calls {#valid_msg_msg_type}.
75
+ # @param msg [String] input message.
37
76
  def valid_msg(msg)
38
77
  valid_msg_msg_type(msg)
39
78
  end
40
79
 
80
+ # As {#valid_msg}, but raises exception if message is invalid.
81
+ # Currently, it just calls {#check_msg_msg_type}.
82
+ # @param msg [String] input message.
41
83
  def check_msg(msg)
42
84
  check_msg_msg_type(msg)
43
85
  end
44
86
 
87
+ # Validates whether message type character in hash is valid.
88
+ # Calls {#valid_msg_type}.
89
+ # @param hash [Hash] input hash.
45
90
  def valid_hash_msg_type(hash)
46
91
  valid_msg_type(hash[:type])
47
92
  end
48
93
 
94
+ # Checks whether message type character in hash is valid.
95
+ # Calls {#check_msg_type}.
96
+ # If argument is valid, it assigns the message type to internal variable.
97
+ # @param hash [Hash] input hash.
49
98
  def check_hash_msg_type(hash)
50
- msg_type = hash[:type]
51
- check_msg_type(msg_type)
52
- msg_type
99
+ check_msg_type(hash[:type])
53
100
  end
54
101
 
102
+ # Returns hash keys that are related to given message type.
103
+ # Each hash with a message type should contain these keys.
104
+ # Calls {#msg_type_which_hash_keys}.
105
+ # @param msg_type [String] message type that is being parsed/serialized.
55
106
  def msg_type_hash_keys(msg_type)
56
107
  msg_type_which_hash_keys(msg_type, false)
57
108
  end
58
109
 
110
+ # Returns optional hash keys that are related to given message type.
111
+ # Calls {#msg_type_which_hash_keys}.
112
+ # @param msg_type [String] message type that is being parsed/serialized.
59
113
  def msg_type_hash_opt_keys(msg_type)
60
114
  msg_type_which_hash_keys(msg_type, true)
61
115
  end
62
116
 
117
+ # Validates if given hash contain valid keys,
118
+ # depending on its message type
119
+ # (according to {#msg_type_which_hash_keys}).
120
+ # Calls {#maybe_check_valid_hash_keys}.
121
+ # @param hash [Hash] input hash.
63
122
  def valid_hash_keys(hash)
64
123
  maybe_check_valid_hash_keys(hash, false)
65
124
  end
66
125
 
126
+ # As {#valid_hash_keys}, but raises exception if hash is _not_ valid.
127
+ # Calls {#maybe_check_valid_hash_keys}.
128
+ # @param hash [Hash] input hash.
129
+ # @return [Hash] input hash.
67
130
  def check_hash_keys(hash)
68
131
  maybe_check_valid_hash_keys(hash, true)
69
132
  hash
70
133
  end
71
134
 
135
+ # Validates if values of given hash satisfies basic conditions
136
+ # for all hashes being used with messages.
137
+ # @param hash [Hash] input hash.
138
+ # @return [Boolean] +true+ if hash values are valid
139
+ # (from general point of view).
72
140
  def valid_hash_values(hash)
73
141
  hash.none? { |_, v| v.nil? }
74
142
  end
75
143
 
144
+ # As {#valid_hash_values}, but raises exception
145
+ # if hash values are _not_ valid.
146
+ # @param hash [Hash] input hash.
147
+ # @return [Hash] input hash.
148
+ # @raise [InvalidMessageBody] if hash values are _not_ valid.
76
149
  def check_hash_values(hash)
77
150
  return hash if valid_hash_values(hash)
78
151
  hash = hash.dup
@@ -81,12 +154,24 @@ module MaxCube
81
154
  .new(@msg_type, "invalid hash values: #{hash}")
82
155
  end
83
156
 
157
+ # Validates if given hash satisfies basic conditions
158
+ # for all hashes being used with messages.
159
+ # Calls {#valid_hash_msg_type},
160
+ # {#valid_hash_keys} and {#valid_hash_values}.
161
+ # @param hash [Hash] input hash.
162
+ # @return [Boolean] +true+ if hash is valid
163
+ # (from general point of view).
84
164
  def valid_hash(hash)
85
165
  valid_hash_msg_type(hash) &&
86
166
  valid_hash_keys(hash) &&
87
167
  valid_hash_values(hash)
88
168
  end
89
169
 
170
+ # As {#valid_hash}, but raises exception if hash is _not_ valid.
171
+ # Calls {#check_hash_msg_type},
172
+ # {#check_hash_keys} and {#check_hash_values}.
173
+ # @param hash [Hash] input hash.
174
+ # @return [Hash] input hash.
90
175
  def check_hash(hash)
91
176
  check_hash_msg_type(hash)
92
177
  check_hash_keys(hash)
@@ -96,10 +181,18 @@ module MaxCube
96
181
 
97
182
  private
98
183
 
184
+ # Gets +MSG_TYPES+ constant depending on object's end-class.
185
+ # @return [Array<String>] +MSG_TYPES+ constant
186
+ # depending on object's end-class.
99
187
  def msg_types
100
188
  self.class.const_get('MSG_TYPES')
101
189
  end
102
190
 
191
+ # Helper method that is called by {#valid_msg_type} or {#check_msg_type}.
192
+ # It provides validation or check depending on input flag.
193
+ # If argument is valid, it assigns the message type to internal variable.
194
+ # @param msg_type [String] input message type character.
195
+ # @param check [Boolean] whether to check (raise exception on failure).
103
196
  def maybe_check_valid_msg_type(msg_type, check)
104
197
  valid = msg_type&.length == 1 &&
105
198
  msg_types.include?(msg_type)
@@ -108,6 +201,16 @@ module MaxCube
108
201
  raise InvalidMessageType.new(@msg_type) unless valid
109
202
  end
110
203
 
204
+ # Checks whether given +args+
205
+ # satisfy lengths specified in input +lengths+.
206
+ # Missing positions in +lengths+ means
207
+ # that no requirement is demanded at that index.
208
+ # @param lengths [Array<Integer>] required lenghts of arguments.
209
+ # @param args [Array<#length>] arguments to be validated.
210
+ # @return [Boolean] +true+ if lengths of 'all' +args+
211
+ # fits to input +lengths+;
212
+ # +false+ otherwise, or if any +arg+ is +nil+,
213
+ # or if size of +lengths+ is higher than number of +args+.
111
214
  def valid_msg_part_lengths(lengths, *args)
112
215
  return false if args.any?(&:nil?) ||
113
216
  args.length < lengths.length
@@ -116,19 +219,42 @@ module MaxCube
116
219
  end
117
220
  end
118
221
 
222
+ # As {#valid_msg_part_lengths}, but raises exception on failure.
223
+ # @return [Array] +args+ if +lengths+ are satisfied.
224
+ # @raise [InvalidMessageBody] if +lengths+ are _not_ satisfied.
119
225
  def check_msg_part_lengths(lengths, *args)
120
- return if valid_msg_part_lengths(lengths, *args)
226
+ return args if valid_msg_part_lengths(lengths, *args)
121
227
  raise InvalidMessageBody
122
228
  .new(@msg_type,
123
229
  "invalid lengths of message parts #{args}" \
124
230
  " (lengths should be: #{lengths})")
125
231
  end
126
232
 
233
+ # Helper method that is called
234
+ # by {#msg_type_hash_keys} or {#msg_type_hash_opt_keys}.
235
+ # It accesses +KEYS+ or +OPT_KEYS+ (depending on input flag)
236
+ # from object's concrete end-class.
237
+ # @param msg_type [String] message type that is being parsed/serialized.
238
+ # @param optional [Boolean] whether to return optional or mandatory keys.
239
+ # @return [Array<Symbol>] mandatory or optional hash keys,
240
+ # depending on +optional+, related to message type.
241
+ # If constant is not found, empty array is returned.
127
242
  def msg_type_which_hash_keys(msg_type, optional = false)
128
243
  str = "Message#{msg_type.upcase}::" + (optional ? 'OPT_KEYS' : 'KEYS')
129
244
  self.class.const_defined?(str) ? self.class.const_get(str) : []
130
245
  end
131
246
 
247
+ # Helper method that is called
248
+ # by {#valid_hash_keys} or {#check_hash_keys}.
249
+ # It validates/checks whether given hash contain
250
+ # all mandatory keys ({#msg_type_hash_keys})
251
+ # and not other than optional keys ({#msg_type_hash_opt_keys}).
252
+ # @param hash [Hash] input hash.
253
+ # @param check [Boolean] whether to check (raise exception on failure).
254
+ # @return [Boolean] +true+ or +false+ for valid/invalid hash keys
255
+ # if +check+ is +false+.
256
+ # @raise [InvalidMessageBody] if +check+ is +true+
257
+ # and hash keys are invalid.
132
258
  def maybe_check_valid_hash_keys(hash, check)
133
259
  keys = msg_type_hash_keys(@msg_type).dup
134
260
  opt_keys = msg_type_hash_opt_keys(@msg_type)
@@ -142,10 +268,18 @@ module MaxCube
142
268
  "(should be: #{keys})")
143
269
  end
144
270
 
271
+ # Encodes input binary data to only printable characters
272
+ # using Base64#strict_encode64.
273
+ # @param data [String] input raw data string.
274
+ # @return [String] Base64-encoded string.
145
275
  def encode(data)
146
276
  Base64.strict_encode64(data)
147
277
  end
148
278
 
279
+ # Decodes input data with only printable characters
280
+ # to binary data using Base64#decode64.
281
+ # @param data [String] input Base64-encoded string.
282
+ # @return [String] raw data string.
149
283
  def decode(data)
150
284
  Base64.decode64(data)
151
285
  end