quelink-mg 0.7.1 → 0.7.2
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/lib/quelink-mg/gl30meu/at/gtcfg.rb +1 -1
- data/lib/quelink-mg/gl30meu/buff/gtfri.rb +3 -5
- data/lib/quelink-mg/gl30meu/resp/gtbtc.rb +16 -0
- data/lib/quelink-mg/gl30meu/resp/gtfri.rb +3 -5
- data/lib/quelink-mg/gl30meu/resp/gtpna.rb +15 -0
- data/lib/quelink-mg/gl30meu/resp/gtstc.rb +16 -0
- data/lib/quelink-mg/resp/gtbtc.rb +15 -0
- data/lib/quelink-mg/resp/gtstc.rb +15 -0
- data/lib/quelink_mg.rb +5 -0
- data/quelink-mg.gemspec +2 -2
- data/spec/quelink_mg/gl30meu/at/gtcfg_spec.rb +11 -1
- data/spec/quelink_mg/gl30meu/buff/gtfri_spec.rb +3 -1
- data/spec/quelink_mg/gl30meu/resp/gtbtc_spec.rb +28 -0
- data/spec/quelink_mg/gl30meu/resp/gtfri_spec.rb +36 -36
- data/spec/quelink_mg/gl30meu/resp/gtpna_spec.rb +26 -0
- data/spec/quelink_mg/gl30meu/resp/gtstc_spec.rb +29 -0
- data/spec/quelink_mg/resp/gtbtc_spec.rb +27 -0
- data/spec/quelink_mg/resp/gtstc_spec.rb +28 -0
- metadata +12 -3
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 74544aedfcfc99eb889c52d771c202ed78330a78b0f37477fa7a64afc17527cd
|
|
4
|
+
data.tar.gz: 7c07309032ba1c2ad1491546960e34a14c73ca798bf2a0e4f3dd1dd7f81bec39
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: ddce591a75f31a174e804d8091d16bddcd79288194caaff32d805df75252d760749aa6e88a6673291e5777518cec4d7860db47aadab8af2ce750d006d1413e7d
|
|
7
|
+
data.tar.gz: f5b9a7542a8b2cc872a00df2c9388b5d348a9d3f4c9bb631598e6488f1d73d84907fae0ab5eecab66702ac43cc9a6ed0f817287c077a1c248968659c2a7406b4
|
|
@@ -26,7 +26,7 @@ module QuelinkMg
|
|
|
26
26
|
acceptable_values = {
|
|
27
27
|
gnss_timeout: (5..300),
|
|
28
28
|
mode_selection: (0..5),
|
|
29
|
-
continuous_send_interval: (
|
|
29
|
+
continuous_send_interval: (1..86_400),
|
|
30
30
|
start_mode: (0..3),
|
|
31
31
|
wakeup_interval: (60..86_400),
|
|
32
32
|
gnss_enable: (0..1),
|
|
@@ -6,13 +6,11 @@ module QuelinkMg
|
|
|
6
6
|
class Gtfri < ::QuelinkMg::Buff::Base
|
|
7
7
|
GTFRI_RESP_KEYS = %w[protocol_version unique_id device_name report_id report_type number
|
|
8
8
|
gps_accuracy speed azimuth elevation longitude latitude gps_utc_time
|
|
9
|
-
mcc mnc lac cell_id csq_rssi csq_ber battery_voltage
|
|
10
|
-
movement_status reserved
|
|
9
|
+
mcc mnc lac cell_id csq_rssi csq_ber battery_voltage battery_percentage
|
|
10
|
+
current_mode_status movement_status reserved send_time count_number].freeze
|
|
11
11
|
|
|
12
12
|
def hash
|
|
13
|
-
|
|
14
|
-
result['battery_percentage'] = result['current_mode_status']
|
|
15
|
-
result
|
|
13
|
+
unify_keys(GTFRI_RESP_KEYS.zip(@response.split(',')).to_h)
|
|
16
14
|
end
|
|
17
15
|
end
|
|
18
16
|
end
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module QuelinkMg
|
|
4
|
+
module Gl30meu
|
|
5
|
+
module Resp
|
|
6
|
+
class Gtbtc < ::QuelinkMg::Resp::Base
|
|
7
|
+
GTBTC_RESP_KEYS = %w[protocol_version unique_id device_name battery_voltage battery_percentage
|
|
8
|
+
mcc mnc lac cell_id csq_rssi csq_ber send_time count_number].freeze
|
|
9
|
+
|
|
10
|
+
def hash
|
|
11
|
+
unify_keys(GTBTC_RESP_KEYS.zip(@response.split(',')).to_h)
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
end
|
|
@@ -6,13 +6,11 @@ module QuelinkMg
|
|
|
6
6
|
class Gtfri < ::QuelinkMg::Resp::Base
|
|
7
7
|
GTFRI_RESP_KEYS = %w[protocol_version unique_id device_name report_id report_type number
|
|
8
8
|
gps_accuracy speed azimuth elevation longitude latitude gps_utc_time
|
|
9
|
-
mcc mnc lac cell_id csq_rssi csq_ber battery_voltage
|
|
10
|
-
movement_status reserved
|
|
9
|
+
mcc mnc lac cell_id csq_rssi csq_ber battery_voltage battery_percentage
|
|
10
|
+
current_mode_status movement_status reserved send_time count_number].freeze
|
|
11
11
|
|
|
12
12
|
def hash
|
|
13
|
-
|
|
14
|
-
result['battery_percentage'] = result['current_mode_status']
|
|
15
|
-
result
|
|
13
|
+
unify_keys(GTFRI_RESP_KEYS.zip(@response.split(',')).to_h)
|
|
16
14
|
end
|
|
17
15
|
end
|
|
18
16
|
end
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module QuelinkMg
|
|
4
|
+
module Gl30meu
|
|
5
|
+
module Resp
|
|
6
|
+
class Gtpna < ::QuelinkMg::Resp::Base
|
|
7
|
+
GTPNA_RESP_KEYS = %w[protocol_version unique_id device_name power_on_type send_time count_number].freeze
|
|
8
|
+
|
|
9
|
+
def hash
|
|
10
|
+
unify_keys(GTPNA_RESP_KEYS.zip(@response.split(',')).to_h)
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
end
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module QuelinkMg
|
|
4
|
+
module Gl30meu
|
|
5
|
+
module Resp
|
|
6
|
+
class Gtstc < ::QuelinkMg::Resp::Base
|
|
7
|
+
GTSTC_RESP_KEYS = %w[protocol_version unique_id device_name event_state battery_voltage battery_percentage
|
|
8
|
+
mcc mnc lac cell_id csq_rssi csq_ber send_time count_number].freeze
|
|
9
|
+
|
|
10
|
+
def hash
|
|
11
|
+
unify_keys(GTSTC_RESP_KEYS.zip(@response.split(',')).to_h)
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
end
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module QuelinkMg
|
|
4
|
+
module Resp
|
|
5
|
+
class Gtbtc < Base
|
|
6
|
+
GTBTC_RESP_KEYS = %w[protocol_version unique_id device_name gps_accuracy speed azimuth altitude
|
|
7
|
+
last_longitude last_latitude gps_utc_time mcc mnc lac cell_id odo_mileage
|
|
8
|
+
send_time count_number].freeze
|
|
9
|
+
|
|
10
|
+
def hash
|
|
11
|
+
unify_keys(GTBTC_RESP_KEYS.zip(@response.split(',')).to_h)
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
end
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module QuelinkMg
|
|
4
|
+
module Resp
|
|
5
|
+
class Gtstc < Base
|
|
6
|
+
GTSTC_RESP_KEYS = %w[protocol_version unique_id device_name reserved gps_accuracy speed azimuth
|
|
7
|
+
altitude last_longitude last_latitude gps_utc_time mcc mnc lac cell_id
|
|
8
|
+
odo_mileage send_time count_number].freeze
|
|
9
|
+
|
|
10
|
+
def hash
|
|
11
|
+
unify_keys(GTSTC_RESP_KEYS.zip(@response.split(',')).to_h)
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
end
|
data/lib/quelink_mg.rb
CHANGED
|
@@ -26,6 +26,8 @@ require File.expand_path('quelink-mg/resp/gtstt.rb', __dir__)
|
|
|
26
26
|
require File.expand_path('quelink-mg/resp/gtupc.rb', __dir__)
|
|
27
27
|
require File.expand_path('quelink-mg/resp/gtver.rb', __dir__)
|
|
28
28
|
require File.expand_path('quelink-mg/resp/gtupd.rb', __dir__)
|
|
29
|
+
require File.expand_path('quelink-mg/resp/gtbtc.rb', __dir__)
|
|
30
|
+
require File.expand_path('quelink-mg/resp/gtstc.rb', __dir__)
|
|
29
31
|
|
|
30
32
|
require File.expand_path('quelink-mg/ack/base.rb', __dir__)
|
|
31
33
|
require File.expand_path('quelink-mg/ack/gtbsi.rb', __dir__)
|
|
@@ -53,6 +55,9 @@ require File.expand_path('quelink-mg/gl30meu/resp/gtati.rb', __dir__)
|
|
|
53
55
|
require File.expand_path('quelink-mg/gl30meu/resp/gtinf.rb', __dir__)
|
|
54
56
|
require File.expand_path('quelink-mg/gl30meu/resp/gtupc.rb', __dir__)
|
|
55
57
|
require File.expand_path('quelink-mg/gl30meu/resp/gtupd.rb', __dir__)
|
|
58
|
+
require File.expand_path('quelink-mg/gl30meu/resp/gtbtc.rb', __dir__)
|
|
59
|
+
require File.expand_path('quelink-mg/gl30meu/resp/gtstc.rb', __dir__)
|
|
60
|
+
require File.expand_path('quelink-mg/gl30meu/resp/gtpna.rb', __dir__)
|
|
56
61
|
|
|
57
62
|
require File.expand_path('quelink-mg/gl30meu/ack/gtrto.rb', __dir__)
|
|
58
63
|
require File.expand_path('quelink-mg/gl30meu/ack/gtcfg.rb', __dir__)
|
data/quelink-mg.gemspec
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
Gem::Specification.new do |s|
|
|
4
4
|
s.name = 'quelink-mg'
|
|
5
|
-
s.version = '0.7.
|
|
5
|
+
s.version = '0.7.2'
|
|
6
6
|
s.summary = 'Quelink devices command reader and writer'
|
|
7
7
|
s.description = 'Quelink devices command reader and writer'
|
|
8
8
|
s.authors = ['Stanislaw Zawadzki']
|
|
@@ -17,5 +17,5 @@ Gem::Specification.new do |s|
|
|
|
17
17
|
s.add_development_dependency 'rspec', '~> 3.9'
|
|
18
18
|
s.add_development_dependency 'rubocop', '~> 1.0'
|
|
19
19
|
s.add_development_dependency 'rubocop-rspec', '~> 2.2'
|
|
20
|
-
s.metadata['rubygems_mfa_required'] = '
|
|
20
|
+
#s.metadata['rubygems_mfa_required'] = 'true'
|
|
21
21
|
end
|
|
@@ -64,13 +64,23 @@ RSpec.describe QuelinkMg::Gl30meu::At::Gtcfg do
|
|
|
64
64
|
expect { described_class.new(params:).message }.to raise_error(InvalidATGTCFGException)
|
|
65
65
|
end
|
|
66
66
|
|
|
67
|
-
it '
|
|
67
|
+
it 'allows low continuous_send_interval values' do
|
|
68
68
|
params = {
|
|
69
69
|
password: 'gl30',
|
|
70
70
|
continuous_send_interval: 5,
|
|
71
71
|
serial_number: 'FFFF'
|
|
72
72
|
}
|
|
73
73
|
|
|
74
|
+
expect(described_class.new(params:).message).to eq 'AT+GTCFG=gl30,,,,,,,5,,,,,,,,,,,,,,,,,,,,FFFF$'
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
it 'raises error on continuous_send_interval of 0' do
|
|
78
|
+
params = {
|
|
79
|
+
password: 'gl30',
|
|
80
|
+
continuous_send_interval: 0,
|
|
81
|
+
serial_number: 'FFFF'
|
|
82
|
+
}
|
|
83
|
+
|
|
74
84
|
expect { described_class.new(params:).message }.to raise_error(InvalidATGTCFGException)
|
|
75
85
|
end
|
|
76
86
|
end
|
|
@@ -11,7 +11,9 @@ RSpec.describe QuelinkMg::Gl30meu::Buff::Gtfri do
|
|
|
11
11
|
expect(parsed_response['longitude']).to eq 121.348554
|
|
12
12
|
expect(parsed_response['latitude']).to eq 31.163204
|
|
13
13
|
expect(parsed_response['battery_voltage']).to eq 3552
|
|
14
|
+
expect(parsed_response['battery_percentage']).to eq 2
|
|
14
15
|
expect(parsed_response['csq_rssi']).to eq 21
|
|
15
|
-
expect(parsed_response['
|
|
16
|
+
expect(parsed_response['current_mode_status']).to eq 1
|
|
17
|
+
expect(parsed_response['movement_status']).to eq 0
|
|
16
18
|
end
|
|
17
19
|
end
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'spec_helper'
|
|
4
|
+
|
|
5
|
+
RSpec.describe QuelinkMg::Gl30meu::Resp::Gtbtc do
|
|
6
|
+
it 'parses real GL30MEU GTBTC response (backup-battery starts charging)' do
|
|
7
|
+
# Captured from Linode TCP server on 2026-04-22 14:24:39 UTC during live plug-in test
|
|
8
|
+
response = '970101,867963069921253,,4159,100,0260,0003,E2A4,01C0B30F,22,0,20260422142439,38E6'
|
|
9
|
+
|
|
10
|
+
parsed_response = described_class.new(response:).hash
|
|
11
|
+
expect(parsed_response).not_to eq({})
|
|
12
|
+
expect(parsed_response['protocol_version']).to eq 970_101
|
|
13
|
+
expect(parsed_response['unique_id']).to eq 867_963_069_921_253
|
|
14
|
+
expect(parsed_response['device_name']).to eq ''
|
|
15
|
+
expect(parsed_response['battery_voltage']).to eq 4159
|
|
16
|
+
expect(parsed_response['battery_percentage']).to eq 100
|
|
17
|
+
expect(parsed_response['csq_rssi']).to eq 22
|
|
18
|
+
expect(parsed_response['csq_ber']).to eq 0
|
|
19
|
+
expect(parsed_response['send_time']).to eq Time.use_zone('UTC') { Time.zone.parse('20260422142439') }.in_time_zone
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
it 'has 13 keys' do
|
|
23
|
+
response = '970101,867963069921253,,4159,100,0260,0003,E2A4,01C0B30F,22,0,20260422142439,38E6'
|
|
24
|
+
|
|
25
|
+
parsed_response = described_class.new(response:).hash
|
|
26
|
+
expect(parsed_response.keys.length).to eq 13
|
|
27
|
+
end
|
|
28
|
+
end
|
|
@@ -1,36 +1,36 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
require 'spec_helper'
|
|
4
|
-
|
|
5
|
-
RSpec.describe QuelinkMg::Gl30meu::Resp::Gtfri do
|
|
6
|
-
it 'parses valid GL30MEU GTFRI response' do
|
|
7
|
-
response = '970101,861106059716756,GL30MEU,0,0,1,1,0.0,70,17.8,121.348554,31.163204,20231011084221,0460,0000,5B63,0867349C,21,0,3552,2,1,0,,20231011084241,1A0C'
|
|
8
|
-
|
|
9
|
-
parsed_response = described_class.new(response:).hash
|
|
10
|
-
expect(parsed_response).not_to eq({})
|
|
11
|
-
expect(parsed_response['protocol_version']).to eq 970_101
|
|
12
|
-
expect(parsed_response['unique_id']).to eq 861_106_059_716_756
|
|
13
|
-
expect(parsed_response['device_name']).to eq 'GL30MEU'
|
|
14
|
-
expect(parsed_response['longitude']).to eq 121.348554
|
|
15
|
-
expect(parsed_response['latitude']).to eq 31.163204
|
|
16
|
-
expect(parsed_response['speed']).to eq 0.0
|
|
17
|
-
expect(parsed_response['azimuth']).to eq 70
|
|
18
|
-
expect(parsed_response['elevation']).to eq 17.8
|
|
19
|
-
expect(parsed_response['gps_utc_time']).to eq Time.use_zone('UTC') {
|
|
20
|
-
Time.zone.parse('20231011084221')
|
|
21
|
-
}.in_time_zone
|
|
22
|
-
expect(parsed_response['send_time']).to eq Time.use_zone('UTC') { Time.zone.parse('20231011084241') }.in_time_zone
|
|
23
|
-
expect(parsed_response['csq_rssi']).to eq 21
|
|
24
|
-
expect(parsed_response['csq_ber']).to eq 0
|
|
25
|
-
expect(parsed_response['battery_voltage']).to eq 3552
|
|
26
|
-
expect(parsed_response['current_mode_status']).to eq
|
|
27
|
-
expect(parsed_response['movement_status']).to eq
|
|
28
|
-
end
|
|
29
|
-
|
|
30
|
-
it 'has 25 keys' do
|
|
31
|
-
response = '970101,861106059716756,GL30MEU,0,0,1,1,0.0,70,17.8,121.348554,31.163204,20231011084221,0460,0000,5B63,0867349C,21,0,3552,2,1,0,,20231011084241,1A0C'
|
|
32
|
-
|
|
33
|
-
parsed_response = described_class.new(response:).hash
|
|
34
|
-
expect(parsed_response.keys.length).to eq 26
|
|
35
|
-
end
|
|
36
|
-
end
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'spec_helper'
|
|
4
|
+
|
|
5
|
+
RSpec.describe QuelinkMg::Gl30meu::Resp::Gtfri do
|
|
6
|
+
it 'parses valid GL30MEU GTFRI response' do
|
|
7
|
+
response = '970101,861106059716756,GL30MEU,0,0,1,1,0.0,70,17.8,121.348554,31.163204,20231011084221,0460,0000,5B63,0867349C,21,0,3552,2,1,0,,20231011084241,1A0C'
|
|
8
|
+
|
|
9
|
+
parsed_response = described_class.new(response:).hash
|
|
10
|
+
expect(parsed_response).not_to eq({})
|
|
11
|
+
expect(parsed_response['protocol_version']).to eq 970_101
|
|
12
|
+
expect(parsed_response['unique_id']).to eq 861_106_059_716_756
|
|
13
|
+
expect(parsed_response['device_name']).to eq 'GL30MEU'
|
|
14
|
+
expect(parsed_response['longitude']).to eq 121.348554
|
|
15
|
+
expect(parsed_response['latitude']).to eq 31.163204
|
|
16
|
+
expect(parsed_response['speed']).to eq 0.0
|
|
17
|
+
expect(parsed_response['azimuth']).to eq 70
|
|
18
|
+
expect(parsed_response['elevation']).to eq 17.8
|
|
19
|
+
expect(parsed_response['gps_utc_time']).to eq Time.use_zone('UTC') {
|
|
20
|
+
Time.zone.parse('20231011084221')
|
|
21
|
+
}.in_time_zone
|
|
22
|
+
expect(parsed_response['send_time']).to eq Time.use_zone('UTC') { Time.zone.parse('20231011084241') }.in_time_zone
|
|
23
|
+
expect(parsed_response['csq_rssi']).to eq 21
|
|
24
|
+
expect(parsed_response['csq_ber']).to eq 0
|
|
25
|
+
expect(parsed_response['battery_voltage']).to eq 3552
|
|
26
|
+
expect(parsed_response['current_mode_status']).to eq 1
|
|
27
|
+
expect(parsed_response['movement_status']).to eq 0
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
it 'has 25 keys' do
|
|
31
|
+
response = '970101,861106059716756,GL30MEU,0,0,1,1,0.0,70,17.8,121.348554,31.163204,20231011084221,0460,0000,5B63,0867349C,21,0,3552,2,1,0,,20231011084241,1A0C'
|
|
32
|
+
|
|
33
|
+
parsed_response = described_class.new(response:).hash
|
|
34
|
+
expect(parsed_response.keys.length).to eq 26
|
|
35
|
+
end
|
|
36
|
+
end
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'spec_helper'
|
|
4
|
+
|
|
5
|
+
RSpec.describe QuelinkMg::Gl30meu::Resp::Gtpna do
|
|
6
|
+
it 'parses real GL30MEU GTPNA response (power on)' do
|
|
7
|
+
# Captured from Linode TCP server on 2026-04-22 14:19:49 UTC during power-on.
|
|
8
|
+
# Power On Type 4 = "Manual power on for the first time".
|
|
9
|
+
# Types 22/25/26 indicate charging transitions (USB connection / stop / full).
|
|
10
|
+
response = '970101,867963069921253,,4,20260422141710,38E0'
|
|
11
|
+
|
|
12
|
+
parsed_response = described_class.new(response:).hash
|
|
13
|
+
expect(parsed_response).not_to eq({})
|
|
14
|
+
expect(parsed_response['protocol_version']).to eq 970_101
|
|
15
|
+
expect(parsed_response['unique_id']).to eq 867_963_069_921_253
|
|
16
|
+
expect(parsed_response['power_on_type']).to eq 4
|
|
17
|
+
expect(parsed_response['send_time']).to eq Time.use_zone('UTC') { Time.zone.parse('20260422141710') }.in_time_zone
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
it 'has 6 keys' do
|
|
21
|
+
response = '970101,867963069921253,,4,20260422141710,38E0'
|
|
22
|
+
|
|
23
|
+
parsed_response = described_class.new(response:).hash
|
|
24
|
+
expect(parsed_response.keys.length).to eq 6
|
|
25
|
+
end
|
|
26
|
+
end
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'spec_helper'
|
|
4
|
+
|
|
5
|
+
RSpec.describe QuelinkMg::Gl30meu::Resp::Gtstc do
|
|
6
|
+
it 'parses real GL30MEU GTSTC response (backup-battery stops charging)' do
|
|
7
|
+
# Captured from Linode TCP server on 2026-04-22 14:25:08 UTC during live unplug test.
|
|
8
|
+
# Event state 0 = "Stop charge" (user unplugged), 1 = "Charge full".
|
|
9
|
+
response = '970101,867963069921253,,0,4159,100,0260,0003,E2A4,01C0B30F,22,0,20260422142507,38E8'
|
|
10
|
+
|
|
11
|
+
parsed_response = described_class.new(response:).hash
|
|
12
|
+
expect(parsed_response).not_to eq({})
|
|
13
|
+
expect(parsed_response['protocol_version']).to eq 970_101
|
|
14
|
+
expect(parsed_response['unique_id']).to eq 867_963_069_921_253
|
|
15
|
+
expect(parsed_response['event_state']).to eq 0
|
|
16
|
+
expect(parsed_response['battery_voltage']).to eq 4159
|
|
17
|
+
expect(parsed_response['battery_percentage']).to eq 100
|
|
18
|
+
expect(parsed_response['csq_rssi']).to eq 22
|
|
19
|
+
expect(parsed_response['csq_ber']).to eq 0
|
|
20
|
+
expect(parsed_response['send_time']).to eq Time.use_zone('UTC') { Time.zone.parse('20260422142507') }.in_time_zone
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
it 'has 14 keys' do
|
|
24
|
+
response = '970101,867963069921253,,0,4159,100,0260,0003,E2A4,01C0B30F,22,0,20260422142507,38E8'
|
|
25
|
+
|
|
26
|
+
parsed_response = described_class.new(response:).hash
|
|
27
|
+
expect(parsed_response.keys.length).to eq 14
|
|
28
|
+
end
|
|
29
|
+
end
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'spec_helper'
|
|
4
|
+
|
|
5
|
+
RSpec.describe QuelinkMg::Resp::Gtbtc do
|
|
6
|
+
it 'parses valid response' do
|
|
7
|
+
response = 'C30203,015181001707687,gl320m,1,0.0,0,210.5,114.016051,22.539205,20190911055726,0460,0001,253D,AEC3,0.1,20200811135727,012C$'
|
|
8
|
+
|
|
9
|
+
parsed = described_class.new(response:).hash
|
|
10
|
+
expect(parsed['protocol_version']).to eq 'C30203'
|
|
11
|
+
expect(parsed['unique_id']).to eq 15_181_001_707_687.0
|
|
12
|
+
expect(parsed['device_name']).to eq 'gl320m'
|
|
13
|
+
expect(parsed['gps_accuracy']).to eq 1
|
|
14
|
+
expect(parsed['speed']).to eq 0.0
|
|
15
|
+
expect(parsed['azimuth']).to eq 0
|
|
16
|
+
expect(parsed['altitude']).to eq 210.5
|
|
17
|
+
expect(parsed['last_longitude']).to eq 114.016051
|
|
18
|
+
expect(parsed['last_latitude']).to eq 22.539205
|
|
19
|
+
expect(parsed['gps_utc_time']).to eq Time.use_zone('UTC') { Time.zone.parse('20190911055726') }.in_time_zone
|
|
20
|
+
expect(parsed['mcc']).to eq 460
|
|
21
|
+
expect(parsed['mnc']).to eq 1
|
|
22
|
+
expect(parsed['lac']).to eq '253D'
|
|
23
|
+
expect(parsed['cell_id']).to eq 'AEC3'
|
|
24
|
+
expect(parsed['odo_mileage']).to eq 0.1
|
|
25
|
+
expect(parsed['send_time']).to eq Time.use_zone('UTC') { Time.zone.parse('20200811135727') }.in_time_zone
|
|
26
|
+
end
|
|
27
|
+
end
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'spec_helper'
|
|
4
|
+
|
|
5
|
+
RSpec.describe QuelinkMg::Resp::Gtstc do
|
|
6
|
+
it 'parses valid response' do
|
|
7
|
+
response = 'C30203,015181001707687,gl320m,,1,0.0,0,238.3,114.016303,22.539099,20190911055554,0460,0001,253D,AEC3,0.1,20200811135555,0123$'
|
|
8
|
+
|
|
9
|
+
parsed = described_class.new(response:).hash
|
|
10
|
+
expect(parsed['protocol_version']).to eq 'C30203'
|
|
11
|
+
expect(parsed['unique_id']).to eq 15_181_001_707_687.0
|
|
12
|
+
expect(parsed['device_name']).to eq 'gl320m'
|
|
13
|
+
expect(parsed['reserved']).to eq ''
|
|
14
|
+
expect(parsed['gps_accuracy']).to eq 1
|
|
15
|
+
expect(parsed['speed']).to eq 0.0
|
|
16
|
+
expect(parsed['azimuth']).to eq 0
|
|
17
|
+
expect(parsed['altitude']).to eq 238.3
|
|
18
|
+
expect(parsed['last_longitude']).to eq 114.016303
|
|
19
|
+
expect(parsed['last_latitude']).to eq 22.539099
|
|
20
|
+
expect(parsed['gps_utc_time']).to eq Time.use_zone('UTC') { Time.zone.parse('20190911055554') }.in_time_zone
|
|
21
|
+
expect(parsed['mcc']).to eq 460
|
|
22
|
+
expect(parsed['mnc']).to eq 1
|
|
23
|
+
expect(parsed['lac']).to eq '253D'
|
|
24
|
+
expect(parsed['cell_id']).to eq 'AEC3'
|
|
25
|
+
expect(parsed['odo_mileage']).to eq 0.1
|
|
26
|
+
expect(parsed['send_time']).to eq Time.use_zone('UTC') { Time.zone.parse('20200811135555') }.in_time_zone
|
|
27
|
+
end
|
|
28
|
+
end
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: quelink-mg
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.7.
|
|
4
|
+
version: 0.7.2
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Stanislaw Zawadzki
|
|
@@ -124,15 +124,20 @@ files:
|
|
|
124
124
|
- lib/quelink-mg/gl30meu/at/gtupd.rb
|
|
125
125
|
- lib/quelink-mg/gl30meu/buff/gtfri.rb
|
|
126
126
|
- lib/quelink-mg/gl30meu/resp/gtati.rb
|
|
127
|
+
- lib/quelink-mg/gl30meu/resp/gtbtc.rb
|
|
127
128
|
- lib/quelink-mg/gl30meu/resp/gtfri.rb
|
|
128
129
|
- lib/quelink-mg/gl30meu/resp/gtinf.rb
|
|
130
|
+
- lib/quelink-mg/gl30meu/resp/gtpna.rb
|
|
131
|
+
- lib/quelink-mg/gl30meu/resp/gtstc.rb
|
|
129
132
|
- lib/quelink-mg/gl30meu/resp/gtupc.rb
|
|
130
133
|
- lib/quelink-mg/gl30meu/resp/gtupd.rb
|
|
131
134
|
- lib/quelink-mg/resp/base.rb
|
|
135
|
+
- lib/quelink-mg/resp/gtbtc.rb
|
|
132
136
|
- lib/quelink-mg/resp/gtfri.rb
|
|
133
137
|
- lib/quelink-mg/resp/gtgsv.rb
|
|
134
138
|
- lib/quelink-mg/resp/gtinf.rb
|
|
135
139
|
- lib/quelink-mg/resp/gtsos.rb
|
|
140
|
+
- lib/quelink-mg/resp/gtstc.rb
|
|
136
141
|
- lib/quelink-mg/resp/gtstt.rb
|
|
137
142
|
- lib/quelink-mg/resp/gtupc.rb
|
|
138
143
|
- lib/quelink-mg/resp/gtupd.rb
|
|
@@ -165,12 +170,17 @@ files:
|
|
|
165
170
|
- spec/quelink_mg/gl30meu/at/gtrto_spec.rb
|
|
166
171
|
- spec/quelink_mg/gl30meu/buff/gtfri_spec.rb
|
|
167
172
|
- spec/quelink_mg/gl30meu/resp/gtati_spec.rb
|
|
173
|
+
- spec/quelink_mg/gl30meu/resp/gtbtc_spec.rb
|
|
168
174
|
- spec/quelink_mg/gl30meu/resp/gtfri_spec.rb
|
|
169
175
|
- spec/quelink_mg/gl30meu/resp/gtinf_spec.rb
|
|
176
|
+
- spec/quelink_mg/gl30meu/resp/gtpna_spec.rb
|
|
177
|
+
- spec/quelink_mg/gl30meu/resp/gtstc_spec.rb
|
|
178
|
+
- spec/quelink_mg/resp/gtbtc_spec.rb
|
|
170
179
|
- spec/quelink_mg/resp/gtfri_spec.rb
|
|
171
180
|
- spec/quelink_mg/resp/gtgsv_spec.rb
|
|
172
181
|
- spec/quelink_mg/resp/gtinf_spec.rb
|
|
173
182
|
- spec/quelink_mg/resp/gtsos_spec.rb
|
|
183
|
+
- spec/quelink_mg/resp/gtstc_spec.rb
|
|
174
184
|
- spec/quelink_mg/resp/gtstt_spec.rb
|
|
175
185
|
- spec/quelink_mg/resp/gtupc_spec.rb
|
|
176
186
|
- spec/quelink_mg/resp/gtupd_spec.rb
|
|
@@ -178,8 +188,7 @@ files:
|
|
|
178
188
|
- spec/spec_helper.rb
|
|
179
189
|
licenses:
|
|
180
190
|
- MIT
|
|
181
|
-
metadata:
|
|
182
|
-
rubygems_mfa_required: 'false'
|
|
191
|
+
metadata: {}
|
|
183
192
|
rdoc_options: []
|
|
184
193
|
require_paths:
|
|
185
194
|
- lib
|