quelink-mg 0.1.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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 65d82d1ee48bd09561636c3a37c45d215f83c859b5b0973d53fab2dab2000e99
4
+ data.tar.gz: 3b072ed25d29451bed4b73b23d1a97953b0839351cdbeac1de61c71d30d89f13
5
+ SHA512:
6
+ metadata.gz: a36b701c8db093fa3439ae34fa0ed73d34e8e579342d069eb626824bf32e4bd8c01f3698b5cd2f703aa9c7189e12f3badedeab517b3ea9281112ece9eec642f8
7
+ data.tar.gz: a8807739c2796ce72d53fc5c22f13238a15459b3e7d5734679d86e7429ef7c906ee33a20e9f796a0b10aed2af2be9e0c0fbf95cf0de81d50d2d3bf320b9de558
data/.rubocop.yml ADDED
@@ -0,0 +1,21 @@
1
+ require:
2
+ - rubocop-rspec
3
+ AllCops:
4
+ DisplayCopNames: true
5
+ NewCops: enable
6
+ TargetRubyVersion: 3.1
7
+ Style/Documentation:
8
+ Enabled: false
9
+ Metrics/MethodLength:
10
+ Max: 15
11
+ Metrics/BlockLength:
12
+ Max: 40
13
+ Gemspec/DevelopmentDependencies:
14
+ Enabled: false
15
+ RSpec/MultipleExpectations:
16
+ Enabled: false
17
+ RSpec/ExampleLength:
18
+ Max: 20
19
+ Layout/LineLength:
20
+ Exclude:
21
+ - spec/quelink_mg/resp/*_spec.rb
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ # frozen_string_literal: true
2
+
3
+ source 'https://rubygems.org'
4
+ gemspec
data/Gemfile.lock ADDED
@@ -0,0 +1,85 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ quelink-mg (0.1.0)
5
+ activesupport (~> 7.0)
6
+
7
+ GEM
8
+ remote: https://rubygems.org/
9
+ specs:
10
+ activesupport (7.0.7)
11
+ concurrent-ruby (~> 1.0, >= 1.0.2)
12
+ i18n (>= 1.6, < 2)
13
+ minitest (>= 5.1)
14
+ tzinfo (~> 2.0)
15
+ ast (2.4.2)
16
+ base64 (0.1.1)
17
+ coderay (1.1.3)
18
+ concurrent-ruby (1.2.2)
19
+ diff-lcs (1.5.0)
20
+ i18n (1.14.1)
21
+ concurrent-ruby (~> 1.0)
22
+ json (2.6.3)
23
+ language_server-protocol (3.17.0.3)
24
+ method_source (1.0.0)
25
+ minitest (5.19.0)
26
+ parallel (1.23.0)
27
+ parser (3.2.2.3)
28
+ ast (~> 2.4.1)
29
+ racc
30
+ pry (0.14.2)
31
+ coderay (~> 1.1)
32
+ method_source (~> 1.0)
33
+ racc (1.7.1)
34
+ rainbow (3.1.1)
35
+ regexp_parser (2.8.1)
36
+ rexml (3.2.6)
37
+ rspec (3.12.0)
38
+ rspec-core (~> 3.12.0)
39
+ rspec-expectations (~> 3.12.0)
40
+ rspec-mocks (~> 3.12.0)
41
+ rspec-core (3.12.2)
42
+ rspec-support (~> 3.12.0)
43
+ rspec-expectations (3.12.3)
44
+ diff-lcs (>= 1.2.0, < 2.0)
45
+ rspec-support (~> 3.12.0)
46
+ rspec-mocks (3.12.6)
47
+ diff-lcs (>= 1.2.0, < 2.0)
48
+ rspec-support (~> 3.12.0)
49
+ rspec-support (3.12.1)
50
+ rubocop (1.56.0)
51
+ base64 (~> 0.1.1)
52
+ json (~> 2.3)
53
+ language_server-protocol (>= 3.17.0)
54
+ parallel (~> 1.10)
55
+ parser (>= 3.2.2.3)
56
+ rainbow (>= 2.2.2, < 4.0)
57
+ regexp_parser (>= 1.8, < 3.0)
58
+ rexml (>= 3.2.5, < 4.0)
59
+ rubocop-ast (>= 1.28.1, < 2.0)
60
+ ruby-progressbar (~> 1.7)
61
+ unicode-display_width (>= 2.4.0, < 3.0)
62
+ rubocop-ast (1.29.0)
63
+ parser (>= 3.2.1.0)
64
+ rubocop-capybara (2.18.0)
65
+ rubocop (~> 1.41)
66
+ rubocop-rspec (2.21.0)
67
+ rubocop (~> 1.33)
68
+ rubocop-capybara (~> 2.17)
69
+ ruby-progressbar (1.13.0)
70
+ tzinfo (2.0.6)
71
+ concurrent-ruby (~> 1.0)
72
+ unicode-display_width (2.4.2)
73
+
74
+ PLATFORMS
75
+ x86_64-linux
76
+
77
+ DEPENDENCIES
78
+ pry (~> 0.13)
79
+ quelink-mg!
80
+ rspec (~> 3.9)
81
+ rubocop (~> 1.0)
82
+ rubocop-rspec (~> 2.2)
83
+
84
+ BUNDLED WITH
85
+ 2.4.7
data/README.md ADDED
@@ -0,0 +1,26 @@
1
+ # quelink-mg
2
+ Management of commands sent or received from QUELINK-300 device serie. Tested with MG-310 and MG-320
3
+
4
+ ## Instalation
5
+
6
+ The quelink-mg gem is available at rubygems.org. You can install with:
7
+
8
+ `gem install quelink-mg`
9
+
10
+ Alternatively, you can install the gem with bundler:
11
+
12
+ \# Gemfile
13
+
14
+ `gem 'quelink-mg'`
15
+
16
+ After doing bundle install, you should have the gem installed in your bundle.
17
+
18
+ ## Development
19
+
20
+ Building gem locally (you can change file name, ofc):
21
+ gem build *.gemspec -o pkg/quelink-mg.gem
22
+
23
+ Installing:
24
+ gem install pkg/quelink-mg.gem
25
+
26
+
@@ -0,0 +1,49 @@
1
+ # frozen_string_literal: true
2
+
3
+ module QuelinkMg
4
+ module Ack
5
+ class Base
6
+ QUELINK_DATE_FORMAT = '%Y%m%d%H%M%S'
7
+
8
+ def initialize(response:)
9
+ @response = response
10
+ end
11
+
12
+ private
13
+
14
+ def float?(value)
15
+ !Float(value, exception: false).nil?
16
+ end
17
+
18
+ def integer?(value)
19
+ !Integer(value, exception: false).nil?
20
+ end
21
+
22
+ def date?(value)
23
+ date = DateTime.strptime(value, QUELINK_DATE_FORMAT)
24
+
25
+ !date.nil? && (date - DateTime.now).abs < 3 * 365
26
+ rescue Date::Error
27
+ false
28
+ end
29
+
30
+ def transform_with_timezone(value)
31
+ QuelinkMg.configuration.time_zone.strptime(value, QUELINK_DATE_FORMAT)
32
+ end
33
+
34
+ def unify_keys(hash)
35
+ hash.transform_values do |v|
36
+ if date?(v)
37
+ transform_with_timezone(v)
38
+ elsif integer?(v)
39
+ v.to_i
40
+ elsif float?(v)
41
+ v.to_f
42
+ else
43
+ v
44
+ end
45
+ end
46
+ end
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ module QuelinkMg
4
+ module Ack
5
+ class Gtbsi < Base
6
+ GTBSI_ACK_KEYS = %w[protocol_version unique_id device_name serial_number send_time count_number].freeze
7
+
8
+ def hash
9
+ unify_keys(GTBSI_ACK_KEYS.zip(@response.split(',')).to_h)
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+
3
+ class InvalidATGTBSIException < StandardError; end
4
+
5
+ module QuelinkMg
6
+ module At
7
+ class Base
8
+ def initialize(params:)
9
+ @params = params
10
+ end
11
+
12
+ private
13
+
14
+ def verify_params(acceptable_values, error)
15
+ acceptable_values.each do |k, v|
16
+ next if v.include?(@params.fetch(k, nil))
17
+
18
+ raise_error(k, error)
19
+ end
20
+ end
21
+
22
+ def raise_error(type, error)
23
+ raise error, "Wrong #{type}: #{@params}"
24
+ end
25
+
26
+ def reserved; end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,34 @@
1
+ # frozen_string_literal: true
2
+
3
+ module QuelinkMg
4
+ module At
5
+ class Gtbsi < Base
6
+ def message
7
+ validate_values
8
+
9
+ "AT+GTBSI=#{joined_params}$"
10
+ end
11
+
12
+ private
13
+
14
+ GTBSI_VALID_PARAMS = %i[password lte_apn lte_apn_user_name ltn_apn_password gprs_apn gprs_apn_user_name
15
+ gprs_apn_password network_mode lte_mode apn_authentication_methods manual_netreg
16
+ reserved reserved reserved reserved serial_number].freeze
17
+
18
+ def joined_params
19
+ GTBSI_VALID_PARAMS.map { |method| @params.fetch(method, nil) }.join(',')
20
+ end
21
+
22
+ def validate_values
23
+ acceptable_values = {
24
+ network_mode: (0..3),
25
+ lte_mode: (0..3),
26
+ apn_authentication_methods: (0..3),
27
+ manual_netreg: (0..5)
28
+ }
29
+
30
+ verify_params(acceptable_values, InvalidATGTBSIException)
31
+ end
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ module QuelinkMg
4
+ class Configuration
5
+ attr_accessor :time_zone
6
+
7
+ DEFAULT_ZONE = ActiveSupport::TimeZone.new('Europe/Warsaw')
8
+ def initialize
9
+ @time_zone = DEFAULT_ZONE
10
+ Time.zone = @time_zone
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,49 @@
1
+ # frozen_string_literal: true
2
+
3
+ module QuelinkMg
4
+ module Resp
5
+ class Base
6
+ QUELINK_DATE_FORMAT = '%Y%m%d%H%M%S'
7
+
8
+ def initialize(response:)
9
+ @response = response
10
+ end
11
+
12
+ private
13
+
14
+ def float?(value)
15
+ !Float(value, exception: false).nil?
16
+ end
17
+
18
+ def integer?(value)
19
+ !Integer(value, exception: false).nil?
20
+ end
21
+
22
+ def date?(value)
23
+ date = DateTime.strptime(value, QUELINK_DATE_FORMAT)
24
+
25
+ !date.nil? && (date - DateTime.now).abs < 3 * 365
26
+ rescue Date::Error
27
+ false
28
+ end
29
+
30
+ def transform_with_timezone(value)
31
+ QuelinkMg.configuration.time_zone.strptime(value, QUELINK_DATE_FORMAT)
32
+ end
33
+
34
+ def unify_keys(hash)
35
+ hash.transform_values do |v|
36
+ if date?(v)
37
+ transform_with_timezone(v)
38
+ elsif integer?(v)
39
+ v.to_i
40
+ elsif float?(v)
41
+ v.to_f
42
+ else
43
+ v
44
+ end
45
+ end
46
+ end
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ module QuelinkMg
4
+ module Resp
5
+ class Gtfri < Base
6
+ GTFRI_RESP_KEYS = %w[protocol_version unique_id device_name report_id report_type number
7
+ gps_accuracy speed azimuth elevation longitude latitude gps_utc_time
8
+ mcc mnc lac cell_id odo_mileage battery_percentage send_time count_number].freeze
9
+
10
+ def hash
11
+ unify_keys(GTFRI_RESP_KEYS.zip(@response.split(',')).to_h)
12
+ end
13
+ end
14
+ end
15
+ end
data/lib/quelink_mg.rb ADDED
@@ -0,0 +1,27 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'pry'
4
+ require 'date'
5
+ require 'active_support'
6
+ require 'active_support/time_with_zone'
7
+ require 'active_support/core_ext/time/zones'
8
+
9
+ require File.expand_path('quelink-mg/at/base.rb', __dir__)
10
+ require File.expand_path('quelink-mg/at/gtbsi.rb', __dir__)
11
+ require File.expand_path('quelink-mg/resp/base.rb', __dir__)
12
+ require File.expand_path('quelink-mg/resp/gtfri.rb', __dir__)
13
+ require File.expand_path('quelink-mg/ack/base.rb', __dir__)
14
+ require File.expand_path('quelink-mg/ack/gtbsi.rb', __dir__)
15
+ require File.expand_path('quelink-mg/configuration.rb', __dir__)
16
+
17
+ module QuelinkMg
18
+ class << self
19
+ def configuration
20
+ @configuration ||= Configuration.new
21
+ end
22
+
23
+ def configure
24
+ yield(configuration)
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ Gem::Specification.new do |s|
4
+ s.name = 'quelink-mg'
5
+ s.version = '0.1.0'
6
+ s.summary = 'Quelink devices command reader and writer'
7
+ s.description = 'Quelink devices command reader and writer'
8
+ s.authors = ['Stanislaw Zawadzki']
9
+ s.email = 'st.zawadzki@gmail.com'
10
+
11
+ s.files = `git ls-files`.split($INPUT_RECORD_SEPARATOR)
12
+ s.require_paths = ['lib']
13
+ s.license = 'MIT'
14
+ s.required_ruby_version = '>= 3.1'
15
+ s.add_dependency 'activesupport', '~> 7.0'
16
+ s.add_development_dependency 'pry', '~> 0.13'
17
+ s.add_development_dependency 'rspec', '~> 3.9'
18
+ s.add_development_dependency 'rubocop', '~> 1.0'
19
+ s.add_development_dependency 'rubocop-rspec', '~> 2.2'
20
+ # s.metadata['rubygems_mfa_required'] = 'true'
21
+ end
@@ -0,0 +1,14 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ RSpec.describe QuelinkMg::Ack::Gtbsi do
6
+ it 'parses valid response' do
7
+ response = 'D40102,868239051011356,,0040,20210816045509,004F'
8
+ parsed_response = described_class.new(response:).hash
9
+ expect(parsed_response['protocol_version']).to eq 'D40102'
10
+ expect(parsed_response['unique_id']).to eq 868_239_051_011_356
11
+ expect(parsed_response['send_time']).to eq Time.zone.strptime('20210816045509',
12
+ QuelinkMg::Resp::Base::QUELINK_DATE_FORMAT)
13
+ end
14
+ end
@@ -0,0 +1,39 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ RSpec.describe QuelinkMg::At::Gtbsi do
6
+ it 'creates command when params are valid' do
7
+ params =
8
+ {
9
+ password: 'qwerty',
10
+ lte_apn: 'https://apn.org/',
11
+ network_mode: 0,
12
+ lte_mode: 0,
13
+ apn_authentication_methods: 0,
14
+ manual_netreg: 0,
15
+ serial_number: 'ABFF'
16
+ }
17
+
18
+ expect(described_class.new(params:).message).to eq 'AT+GTBSI=qwerty,https://apn.org/,,,,,,0,0,0,0,,,,,ABFF$'
19
+ end
20
+
21
+ it 'raises error on missing params' do
22
+ expect { described_class.new(params: {}).message }.to raise_error(InvalidATGTBSIException)
23
+ end
24
+
25
+ it 'raises error on improper params' do
26
+ params =
27
+ {
28
+ password: 'qwerty',
29
+ lte_apn: 'https://apn.org/',
30
+ network_mode: 10,
31
+ lte_mode: 10,
32
+ apn_authentication_methods: 0,
33
+ manual_netreg: 0,
34
+ serial_number: 'ABFF'
35
+ }
36
+
37
+ expect { described_class.new(params:).message }.to raise_error(InvalidATGTBSIException)
38
+ end
39
+ end
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ RSpec.describe QuelinkMg::Resp::Gtfri do
6
+ it 'parses valid response' do
7
+ response = 'C30204,860201061504521,,0,0,1,1,0.0,0,96.2,21.012847,52.200338,20230813061232,0260,0003,E31F,0447020D,,34,20230813061231,3E94'
8
+
9
+ parsed_response = described_class.new(response:).hash
10
+ expect(parsed_response).not_to eq({})
11
+ expect(parsed_response['send_time']).to eq Time.zone.strptime('20230813061231',
12
+ QuelinkMg::Resp::Base::QUELINK_DATE_FORMAT)
13
+ expect(parsed_response['gps_utc_time']).to eq Time.zone.strptime('20230813061232',
14
+ QuelinkMg::Resp::Base::QUELINK_DATE_FORMAT)
15
+ expect(parsed_response['longitude']).to eq 21.012847
16
+ expect(parsed_response['latitude']).to eq 52.200338
17
+ expect(parsed_response['unique_id']).to eq 860_201_061_504_521
18
+ expect(parsed_response['battery_percentage']).to eq 34
19
+ expect(parsed_response['device_name']).to eq ''
20
+ end
21
+ end
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative '../lib/quelink_mg'
4
+
5
+ QuelinkMg.configure do |config|
6
+ config.time_zone = QuelinkMg::Configuration::DEFAULT_ZONE
7
+ end
8
+
9
+ RSpec.configure do |config|
10
+ config.expect_with :rspec do |expectations|
11
+ expectations.include_chain_clauses_in_custom_matcher_descriptions = true
12
+ end
13
+
14
+ config.mock_with :rspec do |mocks|
15
+ mocks.verify_partial_doubles = true
16
+ end
17
+
18
+ config.shared_context_metadata_behavior = :apply_to_host_groups
19
+ end
metadata ADDED
@@ -0,0 +1,129 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: quelink-mg
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Stanislaw Zawadzki
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2023-08-13 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: activesupport
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '7.0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '7.0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: pry
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '0.13'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '0.13'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rspec
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '3.9'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '3.9'
55
+ - !ruby/object:Gem::Dependency
56
+ name: rubocop
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '1.0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '1.0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: rubocop-rspec
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: '2.2'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: '2.2'
83
+ description: Quelink devices command reader and writer
84
+ email: st.zawadzki@gmail.com
85
+ executables: []
86
+ extensions: []
87
+ extra_rdoc_files: []
88
+ files:
89
+ - ".rubocop.yml"
90
+ - Gemfile
91
+ - Gemfile.lock
92
+ - README.md
93
+ - lib/quelink-mg/ack/base.rb
94
+ - lib/quelink-mg/ack/gtbsi.rb
95
+ - lib/quelink-mg/at/base.rb
96
+ - lib/quelink-mg/at/gtbsi.rb
97
+ - lib/quelink-mg/configuration.rb
98
+ - lib/quelink-mg/resp/base.rb
99
+ - lib/quelink-mg/resp/gtfri.rb
100
+ - lib/quelink_mg.rb
101
+ - quelink-mg.gemspec
102
+ - spec/quelink_mg/ack/gtbsi_spec.rb
103
+ - spec/quelink_mg/at/gtbsi_spec.rb
104
+ - spec/quelink_mg/resp/gtfri_spec.rb
105
+ - spec/spec_helper.rb
106
+ homepage:
107
+ licenses:
108
+ - MIT
109
+ metadata: {}
110
+ post_install_message:
111
+ rdoc_options: []
112
+ require_paths:
113
+ - lib
114
+ required_ruby_version: !ruby/object:Gem::Requirement
115
+ requirements:
116
+ - - ">="
117
+ - !ruby/object:Gem::Version
118
+ version: '3.1'
119
+ required_rubygems_version: !ruby/object:Gem::Requirement
120
+ requirements:
121
+ - - ">="
122
+ - !ruby/object:Gem::Version
123
+ version: '0'
124
+ requirements: []
125
+ rubygems_version: 3.3.7
126
+ signing_key:
127
+ specification_version: 4
128
+ summary: Quelink devices command reader and writer
129
+ test_files: []