quelink-mg
Management of commands sent or received from Queclink GPS tracker devices. Supports GL320M and GL30MEU (GL30MEUR01).
Installation
The quelink-mg gem is available at rubygems.org. You can install with:
gem install quelink-mg
Alternatively, you can install the gem with bundler:
# Gemfile
gem 'quelink-mg'
After doing bundle install, you should have the gem installed in your bundle.
Configuration
QuelinkMg.configure do |config|
config.time_zone = ActiveSupport::TimeZone.new('Europe/Warsaw') # default
end
Supported devices
| Feature | GL320M | GL30MEU |
|---|---|---|
| Protocol prefix | C3 |
97 |
| Default password | gl320m |
gl30 |
| Namespace | QuelinkMg::At, QuelinkMg::Resp, etc. |
QuelinkMg::Gl30meu::At, QuelinkMg::Gl30meu::Resp, etc. |
Usage
Device type detection
Detect the device model from any raw message using the protocol version prefix:
response = 'C30204,860201061504521,,0,0,1,...'
device_type = QuelinkMg::DeviceType.detect(response.split(',').first)
# => :gl320m
response = '970101,861106059716756,GL30MEU,0,0,1,...'
device_type = QuelinkMg::DeviceType.detect(response.split(',').first)
# => :gl30meu
Building AT commands
AT commands are sent from the server to the device. Build them by passing a params hash:
# GL320M — set report intervals (GTFRI)
command = QuelinkMg::At::Gtfri.new(params: {
password: 'gl320m',
mode: 2,
check_interval: 30,
send_interval: 60,
serial_number: 'FFFF'
})
command.
# => "AT+GTFRI=gl320m,,,,,,30,60,,,,,,,,,,,,FFFF$"
# GL320M — remote control / query firmware version (GTRTO)
command = QuelinkMg::At::Gtrto.new(params: {
password: 'gl320m',
sub_command: 8,
serial_number: 'FFFF'
})
command.
# => "AT+GTRTO=gl320m,8,,,,,,FFFF$"
# GL30MEU — configure device (GTCFG)
command = QuelinkMg::Gl30meu::At::Gtcfg.new(params: {
password: 'gl30',
continuous_send_interval: 30,
gnss_enable: 1,
led_on: 1,
serial_number: 'FFFF'
})
command.
# => "AT+GTCFG=gl30,,,,,,,30,,,,,,,,1,,,,,,,,,1,FFFF$"
# GL30MEU — set APN (GTBSI)
command = QuelinkMg::Gl30meu::At::Gtbsi.new(params: {
password: 'gl30',
lte_apn: 'iot.1nce.net',
network_mode: 2,
lte_mode: 2,
serial_number: 'FFFF'
})
command.
# => "AT+GTBSI=gl30,,iot.1nce.net,,,2,2,,,FFFF$"
Invalid parameters raise specific exceptions:
QuelinkMg::At::Gtfri.new(params: {
password: 'gl320m',
mode: 99, # invalid — must be 0..5
serial_number: 'FFFF'
}).
# => raises InvalidATGTFRIException
Parsing device responses (RESP)
Parse real-time messages sent from device to server. Values are automatically type-cast (integers, floats, timezone-aware timestamps):
# GL320M — position report (GTFRI)
response = 'C30204,860201061504521,,0,0,1,1,0.0,0,96.2,21.012847,52.200338,20230813061232,0260,0003,E31F,0447020D,,34,20230813061231,3E94'
parsed = QuelinkMg::Resp::Gtfri.new(response:).hash
# => {
# "protocol_version" => "C30204",
# "unique_id" => 860201061504521,
# "longitude" => 21.012847,
# "latitude" => 52.200338,
# "speed" => 0.0,
# "battery_percentage" => 34,
# "gps_utc_time" => 2023-08-13 08:12:32 +0200,
# ...
# }
# GL30MEU — position report (GTFRI) — different fields
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'
parsed = QuelinkMg::Gl30meu::Resp::Gtfri.new(response:).hash
# => {
# "protocol_version" => 970101,
# "unique_id" => 861106059716756,
# "device_name" => "GL30MEU",
# "longitude" => 121.348554,
# "latitude" => 31.163204,
# "csq_rssi" => 21,
# "battery_voltage" => 3552,
# "movement_status" => 1,
# ...
# }
# GL30MEU — device info (GTINF)
response = '970101,867963069921253,,89882280666211671601,24,0,,1,,62,,20251220005654,,,,,,,,20260224104605,1182'
parsed = QuelinkMg::Gl30meu::Resp::Gtinf.new(response:).hash
# => {
# "unique_id" => 867963069921253,
# "iccid" => "89882280666211671601",
# "csq_rssi" => 24,
# "battery_percentage" => 62,
# ...
# }
Parsing command acknowledgments (ACK)
Parse ACK messages the device sends after receiving an AT command:
# GL320M
response = 'D40102,868239051011356,,READ,0040,20210816045509,004F'
parsed = QuelinkMg::Ack::Gtrto.new(response:).hash
# => {
# "protocol_version" => "D40102",
# "unique_id" => 868239051011356,
# "sub_command" => "READ",
# "serial_number" => "0040",
# ...
# }
# GL30MEU
response = '970101,861106059716756,GL30MEU,5,FFFF,20231011084300,0A01'
parsed = QuelinkMg::Gl30meu::Ack::Gtrto.new(response:).hash
# => {
# "unique_id" => 861106059716756,
# "device_name" => "GL30MEU",
# "sub_command" => 5,
# ...
# }
Parsing buffered messages (BUFF)
Buffered messages were stored on the device while it was offline. Same interface as RESP:
# GL320M
parsed = QuelinkMg::Buff::Gtfri.new(response:).hash
# GL30MEU
parsed = QuelinkMg::Gl30meu::Buff::Gtfri.new(response:).hash
Available classes
GL320M
| Type | Classes |
|---|---|
| AT commands | Gtbsi, Gtcfg, Gtcmd, Gtfri, Gtqss, Gtrto, Gtsri, Gtudf, Gtupd |
| Response parsers | Gtfri, Gtgsv, Gtinf, Gtsos, Gtstt, Gtupc, Gtupd, Gtver |
| ACK parsers | Gtbsi, Gtcfg, Gtcmd, Gtfri, Gtqss, Gtrto, Gtsri, Gtudf |
| Buff parsers | Gtfri |
GL30MEU
| Type | Classes |
|---|---|
| AT commands | Gtbsi, Gtcfg, Gtrto, Gtsri, Gtupd |
| Response parsers | Gtati, Gtfri, Gtinf, Gtupc, Gtupd |
| ACK parsers | Gtbsi, Gtcfg, Gtrto, Gtsri |
| Buff parsers | Gtfri |
Development
Building gem locally:
gem build *.gemspec -o pkg/quelink-mg.gem
Installing:
gem install pkg/quelink-mg.gem
Running tests:
bundle exec rspec