maxcube-client 0.4.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.
- checksums.yaml +7 -0
- data/.rubocop.yml +32 -0
- data/Gemfile +5 -0
- data/LICENSE.md +21 -0
- data/README.md +35 -0
- data/Rakefile +6 -0
- data/bin/console +8 -0
- data/bin/maxcube-client +31 -0
- data/bin/sample_server +13 -0
- data/bin/sample_socket +13 -0
- data/bin/setup +6 -0
- data/data/load/del +6 -0
- data/data/load/meta +20 -0
- data/data/load/ntp +6 -0
- data/data/load/set_temp +13 -0
- data/data/load/set_temp_mode +12 -0
- data/data/load/set_valve +11 -0
- data/data/load/url +4 -0
- data/data/load/wake +4 -0
- data/lib/maxcube/messages.rb +148 -0
- data/lib/maxcube/messages/handler.rb +154 -0
- data/lib/maxcube/messages/parser.rb +34 -0
- data/lib/maxcube/messages/serializer.rb +59 -0
- data/lib/maxcube/messages/tcp.rb +18 -0
- data/lib/maxcube/messages/tcp/handler.rb +70 -0
- data/lib/maxcube/messages/tcp/parser.rb +46 -0
- data/lib/maxcube/messages/tcp/serializer.rb +47 -0
- data/lib/maxcube/messages/tcp/type/a.rb +32 -0
- data/lib/maxcube/messages/tcp/type/c.rb +248 -0
- data/lib/maxcube/messages/tcp/type/f.rb +33 -0
- data/lib/maxcube/messages/tcp/type/h.rb +70 -0
- data/lib/maxcube/messages/tcp/type/l.rb +131 -0
- data/lib/maxcube/messages/tcp/type/m.rb +185 -0
- data/lib/maxcube/messages/tcp/type/n.rb +44 -0
- data/lib/maxcube/messages/tcp/type/q.rb +18 -0
- data/lib/maxcube/messages/tcp/type/s.rb +246 -0
- data/lib/maxcube/messages/tcp/type/t.rb +38 -0
- data/lib/maxcube/messages/tcp/type/u.rb +19 -0
- data/lib/maxcube/messages/tcp/type/z.rb +36 -0
- data/lib/maxcube/messages/udp.rb +9 -0
- data/lib/maxcube/messages/udp/handler.rb +40 -0
- data/lib/maxcube/messages/udp/parser.rb +50 -0
- data/lib/maxcube/messages/udp/serializer.rb +30 -0
- data/lib/maxcube/messages/udp/type/h.rb +24 -0
- data/lib/maxcube/messages/udp/type/i.rb +23 -0
- data/lib/maxcube/messages/udp/type/n.rb +21 -0
- data/lib/maxcube/network.rb +14 -0
- data/lib/maxcube/network/tcp.rb +11 -0
- data/lib/maxcube/network/tcp/client.rb +174 -0
- data/lib/maxcube/network/tcp/client/commands.rb +286 -0
- data/lib/maxcube/network/tcp/sample_server.rb +96 -0
- data/lib/maxcube/network/udp.rb +11 -0
- data/lib/maxcube/network/udp/client.rb +52 -0
- data/lib/maxcube/network/udp/sample_socket.rb +65 -0
- data/lib/maxcube/version.rb +4 -0
- data/maxcube-client.gemspec +29 -0
- metadata +155 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: f724f91f573430c052cc4111ded2e56f36b02349702e6f9dd9ed7e1929f7eee2
|
4
|
+
data.tar.gz: 8a474badc26be87026e855763bfa959b2b89a3165a2891d199ac67a3c26928e0
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: d6e28eec5439846c020d105697f2263e060ebf5f638fbb7397f9d2d878d41452af13cdbd3cacd4caa71252a4ce4e4a364dc44eef2cfa07d72ace5c59abbb0b83
|
7
|
+
data.tar.gz: 5381d96a92770f4510da936f93cb88b0d5313833e771db10c0bca1d4fefd9b9ba284dcf455f8c7c4e0d468963aca004e40de651475d733318a281fc34fbda27c
|
data/.rubocop.yml
ADDED
@@ -0,0 +1,32 @@
|
|
1
|
+
AllCops:
|
2
|
+
TargetRubyVersion: 2.4
|
3
|
+
|
4
|
+
Metrics/ModuleLength:
|
5
|
+
Max: 200
|
6
|
+
|
7
|
+
Metrics/ClassLength:
|
8
|
+
Max: 200
|
9
|
+
|
10
|
+
Metrics/MethodLength:
|
11
|
+
Max: 30
|
12
|
+
|
13
|
+
Metrics/AbcSize:
|
14
|
+
Enabled: false
|
15
|
+
|
16
|
+
Style/TrailingCommaInLiteral:
|
17
|
+
Enabled: false
|
18
|
+
|
19
|
+
Style/TrailingCommaInArguments:
|
20
|
+
Enabled: false
|
21
|
+
|
22
|
+
Style/FrozenStringLiteralComment:
|
23
|
+
Enabled: false
|
24
|
+
|
25
|
+
Style/DoubleNegation:
|
26
|
+
Enabled: false
|
27
|
+
|
28
|
+
Style/RaiseArgs:
|
29
|
+
EnforcedStyle: compact
|
30
|
+
|
31
|
+
Documentation:
|
32
|
+
Enabled: false
|
data/Gemfile
ADDED
data/LICENSE.md
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
MIT License
|
2
|
+
|
3
|
+
Copyright (c) 2018 Tomaqa
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
13
|
+
copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
21
|
+
SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,35 @@
|
|
1
|
+
# eQ3/ELV Max! Cube TCP client
|
2
|
+
|
3
|
+
## Installation
|
4
|
+
|
5
|
+
Add this line to your application's Gemfile:
|
6
|
+
|
7
|
+
```ruby
|
8
|
+
gem 'maxcube-client'
|
9
|
+
```
|
10
|
+
|
11
|
+
And then execute:
|
12
|
+
|
13
|
+
$ bundle
|
14
|
+
|
15
|
+
Or install it yourself as:
|
16
|
+
|
17
|
+
$ gem install maxcube-client
|
18
|
+
|
19
|
+
## Usage
|
20
|
+
|
21
|
+
TODO: Write usage instructions here
|
22
|
+
|
23
|
+
## Development
|
24
|
+
|
25
|
+
After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
|
26
|
+
|
27
|
+
To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
|
28
|
+
|
29
|
+
## Contributing
|
30
|
+
|
31
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/Tomaqa/maxcube-client.
|
32
|
+
|
33
|
+
## License
|
34
|
+
|
35
|
+
The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
|
data/Rakefile
ADDED
data/bin/console
ADDED
data/bin/maxcube-client
ADDED
@@ -0,0 +1,31 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'bundler/setup'
|
4
|
+
require 'maxcube/network/tcp/client'
|
5
|
+
require 'maxcube/network/udp/client'
|
6
|
+
|
7
|
+
HELP_KEYS = %w[h -h help -help --help ? -?].freeze
|
8
|
+
|
9
|
+
help = ARGV.size == 1 && HELP_KEYS.include?(ARGV.first)
|
10
|
+
wrong_args = ARGV.size > 2
|
11
|
+
|
12
|
+
if help || wrong_args
|
13
|
+
puts "Wrong number of arguments: #{ARGV.size} (expected: 0..2)" if wrong_args
|
14
|
+
puts "USAGE: ruby #{__FILE__} [<help>|<host>] [<port>]\n" \
|
15
|
+
" <help> - on of these: #{HELP_KEYS}\n\n" \
|
16
|
+
"If no arguments are given, UDP discovery is performed.\n" \
|
17
|
+
'Otherwise, TCP client is launched (unless help command entered).'
|
18
|
+
exit
|
19
|
+
end
|
20
|
+
|
21
|
+
if ARGV.empty?
|
22
|
+
puts "No arguments given - performing UDP discovery ...\n" \
|
23
|
+
"(For usage message, type one of these: #{HELP_KEYS})\n\n"
|
24
|
+
client = MaxCube::Network::UDP::Client.new
|
25
|
+
client.discovery
|
26
|
+
client.close
|
27
|
+
exit
|
28
|
+
end
|
29
|
+
|
30
|
+
client = MaxCube::Network::TCP::Client.new
|
31
|
+
client.connect(*ARGV)
|
data/bin/sample_server
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'bundler/setup'
|
4
|
+
require 'maxcube/network/tcp/sample_server'
|
5
|
+
|
6
|
+
unless ARGV.size <= 1
|
7
|
+
puts "Wrong number of arguments: #{ARGV.size} (expected: 0..1)"
|
8
|
+
puts "Usage: ruby #{__FILE__} [port]"
|
9
|
+
exit
|
10
|
+
end
|
11
|
+
|
12
|
+
server = MaxCube::Network::TCP::SampleServer.new(*ARGV)
|
13
|
+
server.run
|
data/bin/sample_socket
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'bundler/setup'
|
4
|
+
require 'maxcube/network/udp/sample_socket'
|
5
|
+
|
6
|
+
unless ARGV.size <= 1
|
7
|
+
puts "Wrong number of arguments: #{ARGV.size} (expected: 0..1)"
|
8
|
+
puts "Usage: ruby #{__FILE__} [port]"
|
9
|
+
exit
|
10
|
+
end
|
11
|
+
|
12
|
+
socket = MaxCube::Network::UDP::SampleSocket.new(*ARGV)
|
13
|
+
socket.run
|
data/bin/setup
ADDED
data/data/load/del
ADDED
data/data/load/meta
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
---
|
2
|
+
:type: m
|
3
|
+
:index: 0
|
4
|
+
:unknown1: Vx
|
5
|
+
:unknown2: "\x01"
|
6
|
+
:rooms_count: 1
|
7
|
+
:rooms:
|
8
|
+
- :id: 33
|
9
|
+
:name_length: 2
|
10
|
+
:name: XY
|
11
|
+
:rf_address: 3224115
|
12
|
+
:devices_count: 1
|
13
|
+
:devices:
|
14
|
+
- :type: shutter_contact
|
15
|
+
:rf_address: 5391937
|
16
|
+
:serial_number: serial_num
|
17
|
+
:name_length: 4
|
18
|
+
:name: NAME
|
19
|
+
:room_id: 33
|
20
|
+
|
data/data/load/ntp
ADDED
data/data/load/set_temp
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
---
|
2
|
+
:type: s
|
3
|
+
:unknown: "\0"
|
4
|
+
:command: :set_temperature
|
5
|
+
:rf_address: 1033088
|
6
|
+
:room_id: 0
|
7
|
+
:comfort_temperature: 21.5
|
8
|
+
:eco_temperature: 16.5
|
9
|
+
:max_setpoint_temperature: 30.5
|
10
|
+
:min_setpoint_temperature: 4.5
|
11
|
+
:temperature_offset: 0
|
12
|
+
:window_open_temperature: 12.0
|
13
|
+
:window_open_duration: 15
|
@@ -0,0 +1,12 @@
|
|
1
|
+
---
|
2
|
+
:type: s
|
3
|
+
:unknown: "\0"
|
4
|
+
:command: :set_temperature_mode
|
5
|
+
:rf_address_range: !ruby/range
|
6
|
+
begin: 4
|
7
|
+
end: 495872
|
8
|
+
excl: false
|
9
|
+
:room_id: 1
|
10
|
+
:temperature: 19.0
|
11
|
+
:mode: :vacation
|
12
|
+
:datetime_until: !ruby/object:DateTime 2011-08-29 02:00:00.000000000 Z
|
data/data/load/set_valve
ADDED
data/data/load/url
ADDED
data/data/load/wake
ADDED
@@ -0,0 +1,148 @@
|
|
1
|
+
require 'date'
|
2
|
+
require 'ipaddr'
|
3
|
+
|
4
|
+
module MaxCube
|
5
|
+
module Messages
|
6
|
+
DEVICE_MODE = %i[auto manual vacation boost].freeze
|
7
|
+
DEVICE_TYPE = %i[cube
|
8
|
+
radiator_thermostat radiator_thermostat_plus
|
9
|
+
wall_thermostat
|
10
|
+
shutter_contact eco_switch].freeze
|
11
|
+
|
12
|
+
DAYS_OF_WEEK = %w[Saturday Sunday Monday
|
13
|
+
Tuesday Wednesday Thursday Friday].freeze
|
14
|
+
|
15
|
+
PACK_FORMAT = %w[x C n N N].freeze
|
16
|
+
|
17
|
+
class InvalidMessage < RuntimeError; end
|
18
|
+
|
19
|
+
class InvalidMessageLength < InvalidMessage
|
20
|
+
def initialize(info = 'invalid message length')
|
21
|
+
super
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
class InvalidMessageType < InvalidMessage
|
26
|
+
def initialize(msg_type, info = 'invalid message type')
|
27
|
+
super("#{info}: #{msg_type}")
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
class InvalidMessageFormat < InvalidMessage
|
32
|
+
def initialize(info = 'invalid format')
|
33
|
+
super
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
class InvalidMessageBody < InvalidMessage
|
38
|
+
def initialize(msg_type, info = 'invalid format')
|
39
|
+
super("message type #{msg_type}: #{info}")
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
private
|
44
|
+
|
45
|
+
def conv_args(type, info, *args, &block)
|
46
|
+
info = info.to_s.tr('_', ' ')
|
47
|
+
args.map(&block)
|
48
|
+
rescue ArgumentError, TypeError
|
49
|
+
raise InvalidMessageBody
|
50
|
+
.new(@msg_type,
|
51
|
+
"invalid #{type} format of arguments #{args} (#{info})")
|
52
|
+
end
|
53
|
+
|
54
|
+
# Convert string of characters (not binary data!) to hex number
|
55
|
+
# For binary data use #String.unpack
|
56
|
+
def to_ints(base, info, *args)
|
57
|
+
base_str = base.zero? ? '' : "(#{base})"
|
58
|
+
conv_args("integer#{base_str}", info, *args) { |x| Integer(x, base) }
|
59
|
+
end
|
60
|
+
|
61
|
+
def to_int(base, info, arg)
|
62
|
+
to_ints(base, info, arg).first
|
63
|
+
end
|
64
|
+
|
65
|
+
def to_floats(info, *args)
|
66
|
+
conv_args('float', info, *args) { |x| Float(x) }
|
67
|
+
end
|
68
|
+
|
69
|
+
def to_float(info, arg)
|
70
|
+
to_floats(info, arg).first
|
71
|
+
end
|
72
|
+
|
73
|
+
def to_bools(info, *args)
|
74
|
+
conv_args('boolean', info, *args) do |arg|
|
75
|
+
if arg == !!arg
|
76
|
+
arg
|
77
|
+
elsif arg.nil?
|
78
|
+
false
|
79
|
+
elsif %w[true false].include?(arg)
|
80
|
+
arg == 'true'
|
81
|
+
else
|
82
|
+
!Integer(arg).zero?
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
def to_bool(info, arg)
|
88
|
+
to_bools(info, arg).first
|
89
|
+
end
|
90
|
+
|
91
|
+
def to_datetimes(info, *args)
|
92
|
+
conv_args('datetime', info, *args) do |arg|
|
93
|
+
if arg.is_a?(DateTime)
|
94
|
+
arg
|
95
|
+
elsif arg.respond_to?('to_datetime')
|
96
|
+
arg.to_datetime
|
97
|
+
else
|
98
|
+
DateTime.parse(arg)
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
def to_datetime(info, arg)
|
104
|
+
to_datetimes(info, arg).first
|
105
|
+
end
|
106
|
+
|
107
|
+
def ary_elem(ary, id, info)
|
108
|
+
elem = ary[id]
|
109
|
+
return elem if elem
|
110
|
+
raise InvalidMessageBody
|
111
|
+
.new(@msg_type, "unrecognized #{info} id: #{id}")
|
112
|
+
end
|
113
|
+
|
114
|
+
def ary_elem_id(ary, elem, info)
|
115
|
+
id = ary.index(elem)
|
116
|
+
return id if id
|
117
|
+
raise InvalidMessageBody
|
118
|
+
.new(@msg_type, "unrecognized #{info}: #{elem}")
|
119
|
+
end
|
120
|
+
|
121
|
+
def device_type(device_type_id)
|
122
|
+
ary_elem(DEVICE_TYPE, device_type_id, 'device type')
|
123
|
+
end
|
124
|
+
|
125
|
+
def device_type_id(device_type)
|
126
|
+
ary_elem_id(DEVICE_TYPE, device_type.to_sym, 'device type')
|
127
|
+
end
|
128
|
+
|
129
|
+
def device_mode(device_mode_id)
|
130
|
+
ary_elem(DEVICE_MODE, device_mode_id, 'device mode')
|
131
|
+
end
|
132
|
+
|
133
|
+
def device_mode_id(device_mode)
|
134
|
+
ary_elem_id(DEVICE_MODE, device_mode.to_sym, 'device mode')
|
135
|
+
end
|
136
|
+
|
137
|
+
def day_of_week(day_id)
|
138
|
+
ary_elem(DAYS_OF_WEEK, day_id, 'day of week')
|
139
|
+
end
|
140
|
+
|
141
|
+
def day_of_week_id(day)
|
142
|
+
if day.respond_to?('to_i') && day.to_i.between?(1, 7)
|
143
|
+
return (day.to_i + 1) % 7
|
144
|
+
end
|
145
|
+
ary_elem_id(DAYS_OF_WEEK, day.capitalize, 'day of week')
|
146
|
+
end
|
147
|
+
end
|
148
|
+
end
|
@@ -0,0 +1,154 @@
|
|
1
|
+
require 'base64'
|
2
|
+
require 'stringio'
|
3
|
+
|
4
|
+
require 'maxcube/messages'
|
5
|
+
|
6
|
+
module MaxCube
|
7
|
+
module Messages
|
8
|
+
module Handler
|
9
|
+
include Messages
|
10
|
+
|
11
|
+
def valid_data_type(raw_data)
|
12
|
+
raw_data.is_a?(String)
|
13
|
+
end
|
14
|
+
|
15
|
+
def check_data_type(raw_data)
|
16
|
+
raise TypeError unless valid_data_type(raw_data)
|
17
|
+
raw_data
|
18
|
+
end
|
19
|
+
|
20
|
+
def valid_msg_type(msg_type)
|
21
|
+
maybe_check_valid_msg_type(msg_type, false)
|
22
|
+
end
|
23
|
+
|
24
|
+
def check_msg_type(msg_type)
|
25
|
+
maybe_check_valid_msg_type(msg_type, true)
|
26
|
+
@msg_type
|
27
|
+
end
|
28
|
+
|
29
|
+
def valid_msg_msg_type(msg)
|
30
|
+
valid_msg_type(msg_msg_type(msg))
|
31
|
+
end
|
32
|
+
|
33
|
+
def check_msg_msg_type(msg)
|
34
|
+
check_msg_type(msg_msg_type(msg))
|
35
|
+
end
|
36
|
+
|
37
|
+
def valid_msg(msg)
|
38
|
+
valid_msg_msg_type(msg)
|
39
|
+
end
|
40
|
+
|
41
|
+
def check_msg(msg)
|
42
|
+
check_msg_msg_type(msg)
|
43
|
+
end
|
44
|
+
|
45
|
+
def valid_hash_msg_type(hash)
|
46
|
+
valid_msg_type(hash[:type])
|
47
|
+
end
|
48
|
+
|
49
|
+
def check_hash_msg_type(hash)
|
50
|
+
msg_type = hash[:type]
|
51
|
+
check_msg_type(msg_type)
|
52
|
+
msg_type
|
53
|
+
end
|
54
|
+
|
55
|
+
def msg_type_hash_keys(msg_type)
|
56
|
+
msg_type_which_hash_keys(msg_type, false)
|
57
|
+
end
|
58
|
+
|
59
|
+
def msg_type_hash_opt_keys(msg_type)
|
60
|
+
msg_type_which_hash_keys(msg_type, true)
|
61
|
+
end
|
62
|
+
|
63
|
+
def valid_hash_keys(hash)
|
64
|
+
maybe_check_valid_hash_keys(hash, false)
|
65
|
+
end
|
66
|
+
|
67
|
+
def check_hash_keys(hash)
|
68
|
+
maybe_check_valid_hash_keys(hash, true)
|
69
|
+
hash
|
70
|
+
end
|
71
|
+
|
72
|
+
def valid_hash_values(hash)
|
73
|
+
hash.none? { |_, v| v.nil? }
|
74
|
+
end
|
75
|
+
|
76
|
+
def check_hash_values(hash)
|
77
|
+
return hash if valid_hash_values(hash)
|
78
|
+
hash = hash.dup
|
79
|
+
hash.delete(:type)
|
80
|
+
raise InvalidMessageBody
|
81
|
+
.new(@msg_type, "invalid hash values: #{hash}")
|
82
|
+
end
|
83
|
+
|
84
|
+
def valid_hash(hash)
|
85
|
+
valid_hash_msg_type(hash) &&
|
86
|
+
valid_hash_keys(hash) &&
|
87
|
+
valid_hash_values(hash)
|
88
|
+
end
|
89
|
+
|
90
|
+
def check_hash(hash)
|
91
|
+
check_hash_msg_type(hash)
|
92
|
+
check_hash_keys(hash)
|
93
|
+
check_hash_values(hash)
|
94
|
+
hash
|
95
|
+
end
|
96
|
+
|
97
|
+
private
|
98
|
+
|
99
|
+
def msg_types
|
100
|
+
self.class.const_get('MSG_TYPES')
|
101
|
+
end
|
102
|
+
|
103
|
+
def maybe_check_valid_msg_type(msg_type, check)
|
104
|
+
valid = msg_type&.length == 1 &&
|
105
|
+
msg_types.include?(msg_type)
|
106
|
+
return valid ? msg_type : false unless check
|
107
|
+
@msg_type = msg_type
|
108
|
+
raise InvalidMessageType.new(@msg_type) unless valid
|
109
|
+
end
|
110
|
+
|
111
|
+
def valid_msg_part_lengths(lengths, *args)
|
112
|
+
return false if args.any?(&:nil?) ||
|
113
|
+
args.length < lengths.length
|
114
|
+
args.each_with_index.all? do |v, i|
|
115
|
+
!lengths[i] || v.length == lengths[i]
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
def check_msg_part_lengths(lengths, *args)
|
120
|
+
return if valid_msg_part_lengths(lengths, *args)
|
121
|
+
raise InvalidMessageBody
|
122
|
+
.new(@msg_type,
|
123
|
+
"invalid lengths of message parts #{args}" \
|
124
|
+
" (lengths should be: #{lengths})")
|
125
|
+
end
|
126
|
+
|
127
|
+
def msg_type_which_hash_keys(msg_type, optional = false)
|
128
|
+
str = "Message#{msg_type.upcase}::" + (optional ? 'OPT_KEYS' : 'KEYS')
|
129
|
+
self.class.const_defined?(str) ? self.class.const_get(str) : []
|
130
|
+
end
|
131
|
+
|
132
|
+
def maybe_check_valid_hash_keys(hash, check)
|
133
|
+
keys = msg_type_hash_keys(@msg_type).dup
|
134
|
+
opt_keys = msg_type_hash_opt_keys(@msg_type)
|
135
|
+
|
136
|
+
hash_keys = hash.keys - opt_keys - [:type]
|
137
|
+
|
138
|
+
valid = hash_keys.sort == keys.sort
|
139
|
+
return valid if !check || valid
|
140
|
+
raise InvalidMessageBody
|
141
|
+
.new(@msg_type, "invalid hash keys: #{hash_keys} " \
|
142
|
+
"(should be: #{keys})")
|
143
|
+
end
|
144
|
+
|
145
|
+
def encode(data)
|
146
|
+
Base64.strict_encode64(data)
|
147
|
+
end
|
148
|
+
|
149
|
+
def decode(data)
|
150
|
+
Base64.decode64(data)
|
151
|
+
end
|
152
|
+
end
|
153
|
+
end
|
154
|
+
end
|