gt06_server 0.0.1
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/.codeclimate.yml +17 -0
- data/.gitignore +11 -0
- data/.reek +12 -0
- data/.rubocop.yml +28 -0
- data/.ruby-version +1 -0
- data/.travis.yml +5 -0
- data/Gemfile +22 -0
- data/Gemfile.lock +148 -0
- data/README.md +61 -0
- data/Rakefile +11 -0
- data/gt06_server.gemspec +30 -0
- data/lib/ext/CMakeLists.txt +15 -0
- data/lib/ext/crc_16.cpp +47 -0
- data/lib/gt06_server.rb +8 -0
- data/lib/gt06_server/crc.rb +47 -0
- data/lib/gt06_server/messages/alarm_packet.rb +40 -0
- data/lib/gt06_server/messages/date_time_information.rb +34 -0
- data/lib/gt06_server/messages/gps_information.rb +43 -0
- data/lib/gt06_server/messages/gps_query_address.rb +7 -0
- data/lib/gt06_server/messages/lbs_information.rb +17 -0
- data/lib/gt06_server/messages/location_data.rb +32 -0
- data/lib/gt06_server/messages/login_message.rb +22 -0
- data/lib/gt06_server/messages/status_information.rb +117 -0
- data/lib/gt06_server/packet.rb +84 -0
- data/lib/gt06_server/protocol.rb +34 -0
- data/lib/gt06_server/server.rb +82 -0
- data/lib/gt06_server/session.rb +54 -0
- data/lib/gt06_server/session_killer.rb +34 -0
- data/lib/gt06_server/version.rb +4 -0
- data/lib/libcrc16.rb +9 -0
- data/lib/libcrc_16.so +0 -0
- metadata +145 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: b78ca30efa3569ad2d506db73e1fb407cbc9655d
|
4
|
+
data.tar.gz: 4be9efbb31e2e8bf02d5ce0f609d1f3a55bf73e3
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 7a3c0643ec2b53e282c7bcac7691c8a1c9d4a2582257871a92b8b0710b6fbf2c023c5c017261f8624247f24dcc88c7a643c5ad760cd259b315dd21a0f3cf45a4
|
7
|
+
data.tar.gz: c0f4251eae69690753bedbcdef6996b8270340ef90aeab04b27f900f877c2bb78e1a5fbb95980f06105dd7e0774f3217ecd3536a35db1115c3455a1fa423be31
|
data/.codeclimate.yml
ADDED
data/.gitignore
ADDED
data/.reek
ADDED
data/.rubocop.yml
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
AllCops:
|
2
|
+
TargetRubyVersion: 2.3
|
3
|
+
|
4
|
+
Exclude:
|
5
|
+
- 'test/**/*'
|
6
|
+
|
7
|
+
Metrics/LineLength:
|
8
|
+
Max: 200
|
9
|
+
|
10
|
+
Metrics/MethodLength:
|
11
|
+
Max: 15
|
12
|
+
|
13
|
+
Metrics/ClassLength:
|
14
|
+
CountComments: false # count full line comments?
|
15
|
+
Max: 150
|
16
|
+
|
17
|
+
Metrics/ModuleLength:
|
18
|
+
CountComments: false # count full line comments?
|
19
|
+
Max: 150
|
20
|
+
|
21
|
+
Style/AsciiComments:
|
22
|
+
Description: 'Use only ascii symbols in comments.'
|
23
|
+
StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#english-comments'
|
24
|
+
Enabled: false
|
25
|
+
|
26
|
+
Style/Documentation:
|
27
|
+
Description: 'Document classes and non-namespace modules.'
|
28
|
+
Enabled: false
|
data/.ruby-version
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
2.3.1
|
data/.travis.yml
ADDED
data/Gemfile
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
source 'https://rubygems.org'
|
3
|
+
|
4
|
+
# Specify your gem's dependencies in gt06_server.gemspec
|
5
|
+
gemspec
|
6
|
+
|
7
|
+
gem 'rake'
|
8
|
+
|
9
|
+
group :test do
|
10
|
+
gem 'minitest'
|
11
|
+
gem 'codeclimate-test-reporter', require: nil
|
12
|
+
end
|
13
|
+
|
14
|
+
group :development do
|
15
|
+
gem 'pry'
|
16
|
+
gem 'pry-byebug'
|
17
|
+
gem 'rubocop', require: false
|
18
|
+
gem 'reek', require: false
|
19
|
+
gem 'capistrano'
|
20
|
+
gem 'capistrano-rbenv'
|
21
|
+
gem 'capistrano-bundler'
|
22
|
+
end
|
data/Gemfile.lock
ADDED
@@ -0,0 +1,148 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
gt06_server (0.0.1)
|
5
|
+
bindata (~> 2.3)
|
6
|
+
celluloid-io (~> 0.17.3)
|
7
|
+
concurrent-ruby (>= 1.0.2)
|
8
|
+
|
9
|
+
GEM
|
10
|
+
remote: https://rubygems.org/
|
11
|
+
specs:
|
12
|
+
airbrussh (1.0.2)
|
13
|
+
sshkit (>= 1.6.1, != 1.7.0)
|
14
|
+
ast (2.3.0)
|
15
|
+
axiom-types (0.1.1)
|
16
|
+
descendants_tracker (~> 0.0.4)
|
17
|
+
ice_nine (~> 0.11.0)
|
18
|
+
thread_safe (~> 0.3, >= 0.3.1)
|
19
|
+
bindata (2.3.1)
|
20
|
+
byebug (9.0.5)
|
21
|
+
capistrano (3.5.0)
|
22
|
+
airbrussh (>= 1.0.0)
|
23
|
+
capistrano-harrow
|
24
|
+
i18n
|
25
|
+
rake (>= 10.0.0)
|
26
|
+
sshkit (>= 1.9.0)
|
27
|
+
capistrano-bundler (1.1.4)
|
28
|
+
capistrano (~> 3.1)
|
29
|
+
sshkit (~> 1.2)
|
30
|
+
capistrano-harrow (0.5.2)
|
31
|
+
capistrano-rbenv (2.0.4)
|
32
|
+
capistrano (~> 3.1)
|
33
|
+
sshkit (~> 1.3)
|
34
|
+
celluloid (0.17.3)
|
35
|
+
celluloid-essentials
|
36
|
+
celluloid-extras
|
37
|
+
celluloid-fsm
|
38
|
+
celluloid-pool
|
39
|
+
celluloid-supervision
|
40
|
+
timers (>= 4.1.1)
|
41
|
+
celluloid-essentials (0.20.5)
|
42
|
+
timers (>= 4.1.1)
|
43
|
+
celluloid-extras (0.20.5)
|
44
|
+
timers (>= 4.1.1)
|
45
|
+
celluloid-fsm (0.20.5)
|
46
|
+
timers (>= 4.1.1)
|
47
|
+
celluloid-io (0.17.3)
|
48
|
+
celluloid (>= 0.17.2)
|
49
|
+
nio4r (>= 1.1)
|
50
|
+
timers (>= 4.1.1)
|
51
|
+
celluloid-pool (0.20.5)
|
52
|
+
timers (>= 4.1.1)
|
53
|
+
celluloid-supervision (0.20.6)
|
54
|
+
timers (>= 4.1.1)
|
55
|
+
codeclimate-engine-rb (0.3.1)
|
56
|
+
virtus (~> 1.0)
|
57
|
+
codeclimate-test-reporter (0.6.0)
|
58
|
+
simplecov (>= 0.7.1, < 1.0.0)
|
59
|
+
coderay (1.1.1)
|
60
|
+
coercible (1.0.0)
|
61
|
+
descendants_tracker (~> 0.0.1)
|
62
|
+
concurrent-ruby (1.0.2)
|
63
|
+
descendants_tracker (0.0.4)
|
64
|
+
thread_safe (~> 0.3, >= 0.3.1)
|
65
|
+
docile (1.1.5)
|
66
|
+
equalizer (0.0.11)
|
67
|
+
ffi (1.9.10-java)
|
68
|
+
hitimes (1.2.4)
|
69
|
+
i18n (0.7.0)
|
70
|
+
ice_nine (0.11.2)
|
71
|
+
json (1.8.3)
|
72
|
+
json (1.8.3-java)
|
73
|
+
method_source (0.8.2)
|
74
|
+
minitest (5.9.0)
|
75
|
+
net-scp (1.2.1)
|
76
|
+
net-ssh (>= 2.6.5)
|
77
|
+
net-ssh (3.2.0)
|
78
|
+
nio4r (1.2.1)
|
79
|
+
parser (2.3.1.2)
|
80
|
+
ast (~> 2.2)
|
81
|
+
powerpack (0.1.1)
|
82
|
+
pry (0.10.3)
|
83
|
+
coderay (~> 1.1.0)
|
84
|
+
method_source (~> 0.8.1)
|
85
|
+
slop (~> 3.4)
|
86
|
+
pry (0.10.3-java)
|
87
|
+
coderay (~> 1.1.0)
|
88
|
+
method_source (~> 0.8.1)
|
89
|
+
slop (~> 3.4)
|
90
|
+
spoon (~> 0.0)
|
91
|
+
pry-byebug (3.4.0)
|
92
|
+
byebug (~> 9.0)
|
93
|
+
pry (~> 0.10)
|
94
|
+
rainbow (2.1.0)
|
95
|
+
rake (11.2.2)
|
96
|
+
reek (4.1.0)
|
97
|
+
codeclimate-engine-rb (~> 0.3.1)
|
98
|
+
parser (~> 2.3.1, >= 2.3.1.2)
|
99
|
+
rainbow (~> 2.0)
|
100
|
+
rubocop (0.41.1)
|
101
|
+
parser (>= 2.3.1.1, < 3.0)
|
102
|
+
powerpack (~> 0.1)
|
103
|
+
rainbow (>= 1.99.1, < 3.0)
|
104
|
+
ruby-progressbar (~> 1.7)
|
105
|
+
unicode-display_width (~> 1.0, >= 1.0.1)
|
106
|
+
ruby-progressbar (1.8.1)
|
107
|
+
simplecov (0.11.2)
|
108
|
+
docile (~> 1.1.0)
|
109
|
+
json (~> 1.8)
|
110
|
+
simplecov-html (~> 0.10.0)
|
111
|
+
simplecov-html (0.10.0)
|
112
|
+
slop (3.6.0)
|
113
|
+
spoon (0.0.4)
|
114
|
+
ffi
|
115
|
+
sshkit (1.11.1)
|
116
|
+
net-scp (>= 1.1.2)
|
117
|
+
net-ssh (>= 2.8.0)
|
118
|
+
thread_safe (0.3.5)
|
119
|
+
thread_safe (0.3.5-java)
|
120
|
+
timers (4.1.1)
|
121
|
+
hitimes
|
122
|
+
unicode-display_width (1.1.0)
|
123
|
+
virtus (1.0.5)
|
124
|
+
axiom-types (~> 0.1)
|
125
|
+
coercible (~> 1.0)
|
126
|
+
descendants_tracker (~> 0.0, >= 0.0.3)
|
127
|
+
equalizer (~> 0.0, >= 0.0.9)
|
128
|
+
|
129
|
+
PLATFORMS
|
130
|
+
java
|
131
|
+
ruby
|
132
|
+
|
133
|
+
DEPENDENCIES
|
134
|
+
bundler (~> 1.11)
|
135
|
+
capistrano
|
136
|
+
capistrano-bundler
|
137
|
+
capistrano-rbenv
|
138
|
+
codeclimate-test-reporter
|
139
|
+
gt06_server!
|
140
|
+
minitest
|
141
|
+
pry
|
142
|
+
pry-byebug
|
143
|
+
rake
|
144
|
+
reek
|
145
|
+
rubocop
|
146
|
+
|
147
|
+
BUNDLED WITH
|
148
|
+
1.12.5
|
data/README.md
ADDED
@@ -0,0 +1,61 @@
|
|
1
|
+
# Server for gps tracker GT06(TK100)
|
2
|
+
|
3
|
+
[](https://codeclimate.com/github/CoolElvis/gt06_server)
|
4
|
+
[](https://codeclimate.com/github/CoolElvis/gt06_server/coverage)
|
5
|
+
[](https://codeclimate.com/github/CoolElvis/gt06_server)
|
6
|
+
[](https://travis-ci.org/CoolElvis/gt06_server)
|
7
|
+
|
8
|
+
|
9
|
+
## Installation
|
10
|
+
|
11
|
+
Add this line to your application's Gemfile:
|
12
|
+
|
13
|
+
```ruby
|
14
|
+
gem 'gt06_server'
|
15
|
+
```
|
16
|
+
|
17
|
+
And then execute:
|
18
|
+
|
19
|
+
$ bundle
|
20
|
+
|
21
|
+
## Usage
|
22
|
+
|
23
|
+
````ruby
|
24
|
+
require 'gt06_server'
|
25
|
+
|
26
|
+
log_path = File.expand_path(File.join(File.dirname(__FILE__), 'log/server.log'))
|
27
|
+
|
28
|
+
Gt06Server::Server.run '0.0.0.0', 9000, logger: Logger.new(log_path) do |message|
|
29
|
+
p message
|
30
|
+
end
|
31
|
+
|
32
|
+
sleep
|
33
|
+
|
34
|
+
````
|
35
|
+
|
36
|
+
The message is a Hash like:
|
37
|
+
|
38
|
+
````ruby
|
39
|
+
{ :packet_length => 10,
|
40
|
+
:protocol_number => 19,
|
41
|
+
:message_type => :status_information,
|
42
|
+
:information_content =>
|
43
|
+
{ :terminal_information =>
|
44
|
+
{
|
45
|
+
:electricity_bit => 0,
|
46
|
+
:gps_bit => 0,
|
47
|
+
:alarm_status => :normal,
|
48
|
+
:charge_bit => 1,
|
49
|
+
:acc_bit => 0,
|
50
|
+
:defense_bit => 1
|
51
|
+
},
|
52
|
+
:voltage_level => 0,
|
53
|
+
:gsm_signal_strength => 100,
|
54
|
+
:alarm => :normal,
|
55
|
+
:language => :english
|
56
|
+
},
|
57
|
+
:serial_number => 48
|
58
|
+
}
|
59
|
+
````
|
60
|
+
The content of 'information_content' depends on 'message_type'
|
61
|
+
See lib/gt06_server/messages for details
|
data/Rakefile
ADDED
data/gt06_server.gemspec
ADDED
@@ -0,0 +1,30 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
# frozen_string_literal: true
|
3
|
+
$LOAD_PATH.unshift File.expand_path('../lib', __FILE__)
|
4
|
+
require 'gt06_server/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = 'gt06_server'
|
8
|
+
spec.version = Gt06Server::VERSION
|
9
|
+
spec.authors = ['CoolElvis']
|
10
|
+
spec.email = ['elvisplus2@gmail.com']
|
11
|
+
|
12
|
+
spec.summary = 'TCP server for gt06(TK100) gps tracker'
|
13
|
+
spec.description = 'TCP server for gt06(TK100) gps tracker'
|
14
|
+
spec.homepage = 'https://github.com/CoolElvis/gt06_server'
|
15
|
+
spec.license = 'MIT'
|
16
|
+
|
17
|
+
raise 'RubyGems 2.0 or newer is required to protect against public gem pushes.' unless spec.respond_to?(:metadata)
|
18
|
+
|
19
|
+
spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
20
|
+
spec.bindir = 'exe'
|
21
|
+
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
22
|
+
spec.require_paths = ['lib']
|
23
|
+
|
24
|
+
spec.add_runtime_dependency 'bindata', '~>2.3'
|
25
|
+
spec.add_runtime_dependency 'celluloid-io', '~>0.17.3'
|
26
|
+
spec.add_runtime_dependency 'concurrent-ruby', '~>1.0'
|
27
|
+
|
28
|
+
spec.add_development_dependency 'bundler', '~> 1.11'
|
29
|
+
spec.add_development_dependency 'rake', '~> 10.0'
|
30
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
cmake_minimum_required(VERSION 3.5)
|
2
|
+
project(sandbox)
|
3
|
+
|
4
|
+
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
|
5
|
+
#set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Werror")
|
6
|
+
|
7
|
+
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/bin")
|
8
|
+
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/lib")
|
9
|
+
|
10
|
+
set(SOURCE_FILES crc_16.cpp)
|
11
|
+
add_executable(sandbox main.cpp)
|
12
|
+
|
13
|
+
set(SOURCE_LIB crc_16.cpp)
|
14
|
+
|
15
|
+
add_library(crc_16 SHARED ${SOURCE_LIB})
|
data/lib/ext/crc_16.cpp
ADDED
@@ -0,0 +1,47 @@
|
|
1
|
+
#include "crc_16.h"
|
2
|
+
|
3
|
+
static const unsigned short int crctab16[] = {
|
4
|
+
0X0000, 0X1189, 0X2312, 0X329B, 0X4624, 0X57AD, 0X6536, 0X74BF,
|
5
|
+
0X8C48, 0X9DC1, 0XAF5A, 0XBED3, 0XCA6C, 0XDBE5, 0XE97E, 0XF8F7,
|
6
|
+
0X1081, 0X0108, 0X3393, 0X221A, 0X56A5, 0X472C, 0X75B7, 0X643E,
|
7
|
+
0X9CC9, 0X8D40, 0XBFDB, 0XAE52, 0XDAED, 0XCB64, 0XF9FF, 0XE876,
|
8
|
+
0X2102, 0X308B, 0X0210, 0X1399, 0X6726, 0X76AF, 0X4434, 0X55BD,
|
9
|
+
0XAD4A, 0XBCC3, 0X8E58, 0X9FD1, 0XEB6E, 0XFAE7, 0XC87C, 0XD9F5,
|
10
|
+
0X3183, 0X200A, 0X1291, 0X0318, 0X77A7, 0X662E, 0X54B5, 0X453C,
|
11
|
+
0XBDCB, 0XAC42, 0X9ED9, 0X8F50, 0XFBEF, 0XEA66, 0XD8FD, 0XC974,
|
12
|
+
0X4204, 0X538D, 0X6116, 0X709F, 0X0420, 0X15A9, 0X2732, 0X36BB,
|
13
|
+
0XCE4C, 0XDFC5, 0XED5E, 0XFCD7, 0X8868, 0X99E1, 0XAB7A, 0XBAF3,
|
14
|
+
0X5285, 0X430C, 0X7197, 0X601E, 0X14A1, 0X0528, 0X37B3, 0X263A,
|
15
|
+
0XDECD, 0XCF44, 0XFDDF, 0XEC56, 0X98E9, 0X8960, 0XBBFB, 0XAA72,
|
16
|
+
0X6306, 0X728F, 0X4014, 0X519D, 0X2522, 0X34AB, 0X0630, 0X17B9,
|
17
|
+
0XEF4E, 0XFEC7, 0XCC5C, 0XDDD5, 0XA96A, 0XB8E3, 0X8A78, 0X9BF1,
|
18
|
+
0X7387, 0X620E, 0X5095, 0X411C, 0X35A3, 0X242A, 0X16B1, 0X0738,
|
19
|
+
0XFFCF, 0XEE46, 0XDCDD, 0XCD54, 0XB9EB, 0XA862, 0X9AF9, 0X8B70,
|
20
|
+
0X8408, 0X9581, 0XA71A, 0XB693, 0XC22C, 0XD3A5, 0XE13E, 0XF0B7,
|
21
|
+
0X0840, 0X19C9, 0X2B52, 0X3ADB, 0X4E64, 0X5FED, 0X6D76, 0X7CFF,
|
22
|
+
0X9489, 0X8500, 0XB79B, 0XA612, 0XD2AD, 0XC324, 0XF1BF, 0XE036,
|
23
|
+
0X18C1, 0X0948, 0X3BD3, 0X2A5A, 0X5EE5, 0X4F6C, 0X7DF7, 0X6C7E,
|
24
|
+
0XA50A, 0XB483, 0X8618, 0X9791, 0XE32E, 0XF2A7, 0XC03C, 0XD1B5,
|
25
|
+
0X2942, 0X38CB, 0X0A50, 0X1BD9, 0X6F66, 0X7EEF, 0X4C74, 0X5DFD,
|
26
|
+
0XB58B, 0XA402, 0X9699, 0X8710, 0XF3AF, 0XE226, 0XD0BD, 0XC134,
|
27
|
+
0X39C3, 0X284A, 0X1AD/1, 0X0B58, 0X7FE7, 0X6E6E, 0X5CF5, 0X4D7C,
|
28
|
+
0XC60C, 0XD785, 0XE51E, 0XF497, 0X8028, 0X91A1, 0XA33A, 0XB2B3,
|
29
|
+
0X4A44, 0X5BCD, 0X6956, 0X78DF, 0X0C60, 0X1DE9, 0X2F72, 0X3EFB,
|
30
|
+
0XD68D, 0XC704, 0XF59F, 0XE416, 0X90A9, 0X8120, 0XB3BB, 0XA232,
|
31
|
+
0X5AC5, 0X4B4C, 0X79D7, 0X685E, 0X1CE1, 0X0D68, 0X3FF3, 0X2E7A,
|
32
|
+
0XE70E, 0XF687, 0XC41C, 0XD595, 0XA12A, 0XB0A3, 0X8238, 0X93B1,
|
33
|
+
0X6B46, 0X7ACF, 0X4854, 0X59DD, 0X2D62, 0X3CEB, 0X0E70, 0X1FF9,
|
34
|
+
0XF78F, 0XE606, 0XD49D, 0XC514, 0XB1AB, 0XA022, 0X92B9, 0X8330,
|
35
|
+
0X7BC7, 0X6A4E, 0X58D5, 0X495C, 0X3DE3, 0X2C6A, 0X1EF1, 0X0F78,
|
36
|
+
};
|
37
|
+
|
38
|
+
|
39
|
+
int GetCrc16(const char *pData, int nLength) {
|
40
|
+
int fcs = 0xffff;
|
41
|
+
while (nLength > 0) {
|
42
|
+
fcs = (fcs >> 8) ^ crctab16[(fcs ^ *pData) & 0xff];
|
43
|
+
nLength--;
|
44
|
+
pData++;
|
45
|
+
}
|
46
|
+
return ~fcs;
|
47
|
+
}
|
data/lib/gt06_server.rb
ADDED
@@ -0,0 +1,8 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
require_relative 'gt06_server/version'
|
3
|
+
require_relative 'gt06_server/crc'
|
4
|
+
require_relative 'gt06_server/packet'
|
5
|
+
require_relative 'gt06_server/protocol'
|
6
|
+
require_relative 'gt06_server/session_killer'
|
7
|
+
require_relative 'gt06_server/session'
|
8
|
+
require_relative 'gt06_server/server'
|
@@ -0,0 +1,47 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
class CRC16
|
3
|
+
def self.calc(data)
|
4
|
+
lookup_table = [
|
5
|
+
0x0000, 0x1189, 0x2312, 0x329B, 0x4624, 0x57AD, 0x6536, 0x74BF,
|
6
|
+
0x8C48, 0x9DC1, 0xAF5A, 0xBED3, 0xCA6C, 0xDBE5, 0xE97E, 0xF8F7,
|
7
|
+
0x1081, 0x0108, 0x3393, 0x221A, 0x56A5, 0x472C, 0x75B7, 0x643E,
|
8
|
+
0x9CC9, 0x8D40, 0xBFDB, 0xAE52, 0xDAED, 0xCB64, 0xF9FF, 0xE876,
|
9
|
+
0x2102, 0x308B, 0x0210, 0x1399, 0x6726, 0x76AF, 0x4434, 0x55BD,
|
10
|
+
0xAD4A, 0xBCC3, 0x8E58, 0x9FD1, 0xEB6E, 0xFAE7, 0xC87C, 0xD9F5,
|
11
|
+
0x3183, 0x200A, 0x1291, 0x0318, 0x77A7, 0x662E, 0x54B5, 0x453C,
|
12
|
+
0xBDCB, 0xAC42, 0x9ED9, 0x8F50, 0xFBEF, 0xEA66, 0xD8FD, 0xC974,
|
13
|
+
0x4204, 0x538D, 0x6116, 0x709F, 0x0420, 0x15A9, 0x2732, 0x36BB,
|
14
|
+
0xCE4C, 0xDFC5, 0xED5E, 0xFCD7, 0x8868, 0x99E1, 0xAB7A, 0xBAF3,
|
15
|
+
0x5285, 0x430C, 0x7197, 0x601E, 0x14A1, 0x0528, 0x37B3, 0x263A,
|
16
|
+
0xDECD, 0xCF44, 0xFDDF, 0xEC56, 0x98E9, 0x8960, 0xBBFB, 0xAA72,
|
17
|
+
0x6306, 0x728F, 0x4014, 0x519D, 0x2522, 0x34AB, 0x0630, 0x17B9,
|
18
|
+
0xEF4E, 0xFEC7, 0xCC5C, 0xDDD5, 0xA96A, 0xB8E3, 0x8A78, 0x9BF1,
|
19
|
+
0x7387, 0x620E, 0x5095, 0x411C, 0x35A3, 0x242A, 0x16B1, 0x0738,
|
20
|
+
0xFFCF, 0xEE46, 0xDCDD, 0xCD54, 0xB9EB, 0xA862, 0x9AF9, 0x8B70,
|
21
|
+
0x8408, 0x9581, 0xA71A, 0xB693, 0xC22C, 0xD3A5, 0xE13E, 0xF0B7,
|
22
|
+
0x0840, 0x19C9, 0x2B52, 0x3ADB, 0x4E64, 0x5FED, 0x6D76, 0x7CFF,
|
23
|
+
0x9489, 0x8500, 0xB79B, 0xA612, 0xD2AD, 0xC324, 0xF1BF, 0xE036,
|
24
|
+
0x18C1, 0x0948, 0x3BD3, 0x2A5A, 0x5EE5, 0x4F6C, 0x7DF7, 0x6C7E,
|
25
|
+
0xA50A, 0xB483, 0x8618, 0x9791, 0xE32E, 0xF2A7, 0xC03C, 0xD1B5,
|
26
|
+
0x2942, 0x38CB, 0x0A50, 0x1BD9, 0x6F66, 0x7EEF, 0x4C74, 0x5DFD,
|
27
|
+
0xB58B, 0xA402, 0x9699, 0x8710, 0xF3AF, 0xE226, 0xD0BD, 0xC134,
|
28
|
+
0x39C3, 0x284A, 0x1AD1, 0x0B58, 0x7FE7, 0x6E6E, 0x5CF5, 0x4D7C,
|
29
|
+
0xC60C, 0xD785, 0xE51E, 0xF497, 0x8028, 0x91A1, 0xA33A, 0xB2B3,
|
30
|
+
0x4A44, 0x5BCD, 0x6956, 0x78DF, 0x0C60, 0x1DE9, 0x2F72, 0x3EFB,
|
31
|
+
0xD68D, 0xC704, 0xF59F, 0xE416, 0x90A9, 0x8120, 0xB3BB, 0xA232,
|
32
|
+
0x5AC5, 0x4B4C, 0x79D7, 0x685E, 0x1CE1, 0x0D68, 0x3FF3, 0x2E7A,
|
33
|
+
0xE70E, 0xF687, 0xC41C, 0xD595, 0xA12A, 0xB0A3, 0x8238, 0x93B1,
|
34
|
+
0x6B46, 0x7ACF, 0x4854, 0x59DD, 0x2D62, 0x3CEB, 0x0E70, 0x1FF9,
|
35
|
+
0xF78F, 0xE606, 0xD49D, 0xC514, 0xB1AB, 0xA022, 0x92B9, 0x8330,
|
36
|
+
0x7BC7, 0x6A4E, 0x58D5, 0x495C, 0x3DE3, 0x2C6A, 0x1EF1, 0x0F78
|
37
|
+
]
|
38
|
+
|
39
|
+
fcs = 0xffff
|
40
|
+
|
41
|
+
data.each_byte do |byte|
|
42
|
+
fcs = (fcs >> 8) ^ lookup_table[(fcs ^ byte) & 0xff]
|
43
|
+
end
|
44
|
+
|
45
|
+
~fcs & 0xffff
|
46
|
+
end
|
47
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
module Gt06Server
|
3
|
+
module Messages
|
4
|
+
class AlarmPacket < BinData::Record
|
5
|
+
# 5.3. Alarm Packet (Combined information packet of GPS, LBS and Status)
|
6
|
+
# 5.3.1. Server Sending Alarm Data Packet to Server
|
7
|
+
# Format Length (Byte)
|
8
|
+
# Start Bit 2
|
9
|
+
# Packet Length 1
|
10
|
+
# Protocol Number 1
|
11
|
+
# Date Time 6
|
12
|
+
# GPS Information
|
13
|
+
# Quantity of GPS information satellites 1
|
14
|
+
# Latitude 4
|
15
|
+
# Longitude 4
|
16
|
+
# Speed 1
|
17
|
+
# Course, Status 2
|
18
|
+
# LBS Information
|
19
|
+
# LBS Length 1
|
20
|
+
# MCC 2
|
21
|
+
# MNC 1
|
22
|
+
# LAC 2
|
23
|
+
# Cell ID 3
|
24
|
+
# status Information
|
25
|
+
# Terminal Information Content 1
|
26
|
+
# Voltage Level 1
|
27
|
+
# GSM Signal Strength 1
|
28
|
+
# Alarm/Language 2
|
29
|
+
# Serial Number 2
|
30
|
+
# Error Check 2
|
31
|
+
# Stop Bit 2
|
32
|
+
|
33
|
+
date_time_information :date_time
|
34
|
+
gps_information :gps
|
35
|
+
string :lbs_length, length: 1
|
36
|
+
lbs_information :lbs
|
37
|
+
status_information :status
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
module Gt06Server
|
3
|
+
module Messages
|
4
|
+
class DateTimeInformation < BinData::Primitive
|
5
|
+
# 5.2.1.4. Date Time
|
6
|
+
# Format Length(Byte) Example
|
7
|
+
# Year 1 0x0A
|
8
|
+
# Month 1 0x03
|
9
|
+
# Day 1 0x17
|
10
|
+
# Hour 1 0x0F
|
11
|
+
# Minute 1 0x32
|
12
|
+
# Second 1 0x17
|
13
|
+
# Example: 2010-03-23 15:30:23
|
14
|
+
# Calculated as follows: 10(Decimal)=0A(Hexadecimal)
|
15
|
+
# 3 (Decimal)=03(Hexadecimal)
|
16
|
+
# 23(Decimal)=17(Hexadecimal)
|
17
|
+
|
18
|
+
uint8 :year
|
19
|
+
uint8 :month
|
20
|
+
uint8 :day
|
21
|
+
uint8 :hour
|
22
|
+
uint8 :minute
|
23
|
+
uint8 :second
|
24
|
+
|
25
|
+
def get
|
26
|
+
Time.new year + 2000, month, day, hour, minute, second
|
27
|
+
end
|
28
|
+
|
29
|
+
# TODO
|
30
|
+
def set(value)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
module Gt06Server
|
3
|
+
module Messages
|
4
|
+
class GpsInformation < BinData::Record
|
5
|
+
# GPS Information
|
6
|
+
# Date Time 6 0x0B 0x08 0x1D 0x11 0x2E 0x10
|
7
|
+
# Quantity of GPS information satellites 1 0xCF
|
8
|
+
# Latitude 4 0x02 0x7A 0xC7 0xEB
|
9
|
+
# Longitude 4 0x0C 0x46 0x58 0x49
|
10
|
+
# Speed 1 0x00
|
11
|
+
# Course, Status 2 0x14 0x8F
|
12
|
+
|
13
|
+
class Coord < BinData::Primitive
|
14
|
+
uint32be :coord
|
15
|
+
|
16
|
+
def get
|
17
|
+
coord.to_f / 30_000 / 60
|
18
|
+
end
|
19
|
+
|
20
|
+
# TODO
|
21
|
+
def set(value)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
struct :quantity_satellites do
|
26
|
+
bit4 :length_gps
|
27
|
+
bit4 :satellites
|
28
|
+
end
|
29
|
+
coord :latitude
|
30
|
+
coord :longitude
|
31
|
+
uint8 :speed
|
32
|
+
struct :course_status do
|
33
|
+
bit1 :null_1
|
34
|
+
bit1 :null_2
|
35
|
+
bit1 :gps_positioning_type # GPS real-time/differential positioning
|
36
|
+
bit1 :is_gps_positioning # GPS having been positioning or not
|
37
|
+
bit1 :longitude_bit # East Longitude, West Longitude
|
38
|
+
bit1 :latitude_bit # South Latitude, North Latitude
|
39
|
+
bit10 :course
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
module Gt06Server
|
3
|
+
module Messages
|
4
|
+
class LbsInformation < BinData::Record
|
5
|
+
# LBS Information
|
6
|
+
# MCC 2 0x01 0xCC
|
7
|
+
# MNC 1 0x00
|
8
|
+
# LAC 2 0x28 0x7D
|
9
|
+
# Cell ID 3 0x00 0x1F 0xB8
|
10
|
+
|
11
|
+
string :mcc, read_length: 2
|
12
|
+
string :mnc, read_length: 1
|
13
|
+
string :lac, read_length: 2
|
14
|
+
string :cell_id, read_length: 3
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
module Gt06Server
|
3
|
+
module Messages
|
4
|
+
class LocationData < BinData::Record
|
5
|
+
# 5.2. Location Data Packet (combined information package of GPS and LBS)
|
6
|
+
# 5.2.1. Terminal Sending Location Data Packet to Server
|
7
|
+
# Format Length(Byte) Example
|
8
|
+
# Start Bit 2 0x78 0x78
|
9
|
+
# Packet Length 1 0x1F
|
10
|
+
# Protocol Number 1 0x12
|
11
|
+
# Date Time 6 0x0B 0x08 0x1D 0x11 0x2E 0x10
|
12
|
+
# GPS Information
|
13
|
+
# Quantity of GPS information satellites 1 0xCF
|
14
|
+
# Latitude 4 0x02 0x7A 0xC7 0xEB
|
15
|
+
# Longitude 4 0x0C 0x46 0x58 0x49
|
16
|
+
# Speed 1 0x00
|
17
|
+
# Course, Status 2 0x14 0x8F
|
18
|
+
# LBS Information
|
19
|
+
# MCC 2 0x01 0xCC
|
20
|
+
# MNC 1 0x00
|
21
|
+
# LAC 2 0x28 0x7D
|
22
|
+
# Cell ID 3 0x00 0x1F 0xB8
|
23
|
+
# Serial Number 2 0x00 0x03
|
24
|
+
# Error Check 2 0x80 0x81
|
25
|
+
# Stop Bit 2 0x0D 0x0A
|
26
|
+
|
27
|
+
date_time_information :date_time
|
28
|
+
gps_information :gps
|
29
|
+
lbs_information :lbs
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
module Gt06Server
|
3
|
+
module Messages
|
4
|
+
class LoginMessage < BinData::Record
|
5
|
+
# 5.1. Login Message Packet
|
6
|
+
# 5.1.1. Terminal Sending Data Packet to Server
|
7
|
+
# The login message packet is used to be sent to the server with the terminal ID so as to confirm the
|
8
|
+
# established connection is normal or not.
|
9
|
+
# Description Bits Example
|
10
|
+
# Login Message Packet(18 Byte)
|
11
|
+
# Start Bit 2 0x78 0x78
|
12
|
+
# Packet Length 1 0x0D
|
13
|
+
# Protocol Number1 0x01
|
14
|
+
# Terminal ID 8 0x01 0x23 0x45 0x67 0x89 0x01 0x23 0x45
|
15
|
+
# Information SerialNumber 2 0x00 0x01
|
16
|
+
# Error Check 2 0x8C 0xDD
|
17
|
+
# Stop Bit 2 0x0D 0x0
|
18
|
+
|
19
|
+
uint64be :terminal_id
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,117 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
module Gt06Server
|
3
|
+
module Messages
|
4
|
+
# 5.3. Alarm Packet (Combined information packet of GPS, LBS and Status)
|
5
|
+
# 5.3.1. Server Sending Alarm Data Packet to Server
|
6
|
+
# Format Length (Byte)
|
7
|
+
# Start Bit 2
|
8
|
+
# Packet Length 1
|
9
|
+
# Protocol Number 1
|
10
|
+
## Information content
|
11
|
+
# Terminal Information Content 1
|
12
|
+
# Voltage Level 1
|
13
|
+
# GSM Signal Strength 1
|
14
|
+
# Alarm/Language 2
|
15
|
+
# Serial Number 2
|
16
|
+
# Error Check 2
|
17
|
+
# Stop Bit 2
|
18
|
+
|
19
|
+
# 5.3.1.14. Terminal Information
|
20
|
+
# One byte is consumed, defining various status information of the mobile phone.
|
21
|
+
# Code Meaning
|
22
|
+
# Bit7
|
23
|
+
# 1: oil and electricity disconnected
|
24
|
+
# 0: gas oil and electricity connected
|
25
|
+
# Bit6
|
26
|
+
# 1: GPS tracking is on
|
27
|
+
# 0: GPS tracking is off
|
28
|
+
# Bit3~ Bit5
|
29
|
+
# 100: SOS
|
30
|
+
# 011: Low Battery Alarm
|
31
|
+
# 010: Power Cut Alarm
|
32
|
+
# 001: Shock Alarm
|
33
|
+
# 000: Normal
|
34
|
+
# Bit2
|
35
|
+
# 1: Charge On
|
36
|
+
# 0: Charge Off
|
37
|
+
# Bit1
|
38
|
+
# 1: ACC high
|
39
|
+
# 0: ACC Low
|
40
|
+
# Bit0
|
41
|
+
# 1: Defense Activated
|
42
|
+
# 0: Defense Deactivated
|
43
|
+
|
44
|
+
# 5.3.1.17. Alarm/Language
|
45
|
+
# 0x00 (former bit) 0x01 (latter bit)
|
46
|
+
# former bit: terminal alarm status (suitable for alarm packet and electronic fence project)
|
47
|
+
# latter bit: the current language used in the terminal
|
48
|
+
# former bit
|
49
|
+
# 0x00: normal
|
50
|
+
# 0x01: SOS
|
51
|
+
# 0x02: Power Cut Alarm
|
52
|
+
# 0x03: Shock Alarm
|
53
|
+
# 0x04: Fence In Alarm
|
54
|
+
# 0x05: Fence Out Alarm
|
55
|
+
# latter bit
|
56
|
+
# 0x01: Chinese
|
57
|
+
# 0x02: English
|
58
|
+
# Examples:
|
59
|
+
# No Alarm and Language is Chinese: 0x00 0x01
|
60
|
+
# No Alarm and Language is English: 0x00 0x02
|
61
|
+
|
62
|
+
# Main record class
|
63
|
+
class StatusInformation < BinData::Record
|
64
|
+
# Primitive class
|
65
|
+
class AlarmStatus < BinData::Primitive
|
66
|
+
bit3 :alarm_status_bit
|
67
|
+
|
68
|
+
def get
|
69
|
+
[:normal, :shock, :power_cut, :low_battery, :sos][alarm_status_bit]
|
70
|
+
end
|
71
|
+
|
72
|
+
def set(value)
|
73
|
+
self.alarm_status_bit = [:normal, :shock, :power_cut, :low_battery, :sos].index(value)
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
# Primitive class
|
78
|
+
class Alarm < BinData::Primitive
|
79
|
+
bit8 :alarm_bit
|
80
|
+
|
81
|
+
def get
|
82
|
+
[:normal, :sos, :power_cut, :shock, :fence_in, :fence_out][alarm_bit]
|
83
|
+
end
|
84
|
+
|
85
|
+
# TODO
|
86
|
+
def set(value)
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
# Primitive class
|
91
|
+
class Language < BinData::Primitive
|
92
|
+
bit8 :language_bit
|
93
|
+
|
94
|
+
def get
|
95
|
+
{ 0x01 => :english, 0x02 => :chinese }[language_bit]
|
96
|
+
end
|
97
|
+
|
98
|
+
# TODO
|
99
|
+
def set(value)
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
struct :terminal_information do
|
104
|
+
bit1 :electricity_bit
|
105
|
+
bit1 :gps_bit
|
106
|
+
alarm_status :alarm_status
|
107
|
+
bit1 :charge_bit
|
108
|
+
bit1 :acc_bit
|
109
|
+
bit1 :defense_bit
|
110
|
+
end
|
111
|
+
uint8 :voltage_level, length: 1
|
112
|
+
uint8 :gsm_signal_strength, length: 1
|
113
|
+
alarm :alarm
|
114
|
+
language :language
|
115
|
+
end
|
116
|
+
end
|
117
|
+
end
|
@@ -0,0 +1,84 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
require 'bindata'
|
3
|
+
|
4
|
+
require_relative 'messages/date_time_information'
|
5
|
+
require_relative 'messages/gps_information'
|
6
|
+
require_relative 'messages/lbs_information'
|
7
|
+
require_relative 'messages/location_data'
|
8
|
+
require_relative 'messages/status_information'
|
9
|
+
require_relative 'messages/login_message'
|
10
|
+
require_relative 'messages/alarm_packet'
|
11
|
+
require_relative 'messages/gps_query_address'
|
12
|
+
|
13
|
+
module Gt06Server
|
14
|
+
class TerminalPacket < BinData::Record
|
15
|
+
class << self
|
16
|
+
attr_accessor :types
|
17
|
+
end
|
18
|
+
|
19
|
+
TerminalPacket.types = {
|
20
|
+
login_message: 0x01,
|
21
|
+
location_data: 0x12,
|
22
|
+
status_information: 0x13,
|
23
|
+
string_information: 0x15,
|
24
|
+
alarm_packet: 0x16,
|
25
|
+
gps_query_address_information: 0x1A,
|
26
|
+
command_information: 0x80
|
27
|
+
}
|
28
|
+
|
29
|
+
# Data Packet Format
|
30
|
+
# The communication is transferred asynchronously in bytes.
|
31
|
+
# The total length of packets is (10+N) Bytes.
|
32
|
+
# Format Length(Byte)
|
33
|
+
# Start Bit 2
|
34
|
+
# Packet Length 1
|
35
|
+
# Protocol Number 1
|
36
|
+
# Information Content N
|
37
|
+
# Information Serial Number 2
|
38
|
+
# Error Check 2
|
39
|
+
# Stop Bit 2
|
40
|
+
|
41
|
+
bit16 :start_bit, asserted_value: 0x7878
|
42
|
+
struct :payload do
|
43
|
+
bit8 :packet_length
|
44
|
+
bit8 :protocol_number
|
45
|
+
virtual :message_type, value: -> { TerminalPacket.types.key(protocol_number) }
|
46
|
+
choice :information_content, selection: :protocol_number do
|
47
|
+
# 4.3. Protocol Number
|
48
|
+
# Type Value
|
49
|
+
# Login Message 0x01
|
50
|
+
# Location Data 0x12
|
51
|
+
# Status information 0x13
|
52
|
+
# String information 0x15
|
53
|
+
# Alarm data 0x16
|
54
|
+
# GPS, query address information by phone number 0x1A
|
55
|
+
# Command information sent by the server to the terminal 0x80
|
56
|
+
login_message(TerminalPacket.types[:login_message])
|
57
|
+
location_data(TerminalPacket.types[:location_data])
|
58
|
+
status_information(TerminalPacket.types[:status_information])
|
59
|
+
alarm_packet(TerminalPacket.types[:alarm_packet])
|
60
|
+
gps_query_address_information(TerminalPacket.types[:gps_query_address_information])
|
61
|
+
end
|
62
|
+
bit16 :serial_number
|
63
|
+
end
|
64
|
+
bit16 :error_check, assert_value: -> { calculate_crc }
|
65
|
+
bit16 :stop_bit, asserted_value: 0x0D0A
|
66
|
+
|
67
|
+
private
|
68
|
+
|
69
|
+
def calculate_crc
|
70
|
+
CRC16.calc(payload.to_binary_s)
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
class ServerAckPacket < BinData::Record
|
75
|
+
bit16 :start_bit, value: 0x7878
|
76
|
+
bit8 :packet_length, value: 5
|
77
|
+
bit8 :protocol_number
|
78
|
+
bit16 :serial_number
|
79
|
+
bit16 :error_check, value: lambda {
|
80
|
+
CRC16.calc(packet_length.to_binary_s + protocol_number.to_binary_s + serial_number.to_binary_s)
|
81
|
+
}
|
82
|
+
bit16 :stop_bit, value: 0x0D0A
|
83
|
+
end
|
84
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
module Gt06Server
|
3
|
+
module Protocol
|
4
|
+
module_function
|
5
|
+
|
6
|
+
# @param io [IO]
|
7
|
+
# @return pack [TerminalPacket]
|
8
|
+
def read_pack(io)
|
9
|
+
TerminalPacket.read(io)
|
10
|
+
end
|
11
|
+
|
12
|
+
# @param pack [TerminalPacket]
|
13
|
+
# @return [ServerAckPacket, nil]
|
14
|
+
def replay_on(pack)
|
15
|
+
if [:login_message, :status_information].include?(pack.payload.message_type.to_sym)
|
16
|
+
acknowledgment_pack_for(pack)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
# @param pack [TerminalPacket]
|
21
|
+
# @return pack [ServerAckPacket]
|
22
|
+
def acknowledgment_pack_for(pack)
|
23
|
+
ack_pack = ServerAckPacket.new
|
24
|
+
ack_pack.protocol_number = pack.payload.protocol_number
|
25
|
+
ack_pack.serial_number = pack.payload.serial_number
|
26
|
+
|
27
|
+
ack_pack
|
28
|
+
end
|
29
|
+
|
30
|
+
# TODO
|
31
|
+
def command_pack(command)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,82 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
require 'celluloid/current'
|
3
|
+
require 'celluloid/io'
|
4
|
+
require 'logger'
|
5
|
+
require 'concurrent'
|
6
|
+
|
7
|
+
module Gt06Server
|
8
|
+
class Server
|
9
|
+
include Celluloid::IO
|
10
|
+
|
11
|
+
attr_reader :host, :port, :sessions
|
12
|
+
finalizer :shutdown
|
13
|
+
|
14
|
+
class RunError < StandardError;
|
15
|
+
end
|
16
|
+
|
17
|
+
# @param [String] host
|
18
|
+
# @param [Integer] port
|
19
|
+
# @param [Logger] logger
|
20
|
+
# @yields [Hash] information_content of packet
|
21
|
+
def self.run(host, port, options: {}, &block)
|
22
|
+
actor = Celluloid::Actor['Gt06Server']
|
23
|
+
|
24
|
+
if actor&.alive?
|
25
|
+
raise RunError, 'Attempt to run more than one the Gt06Server'
|
26
|
+
end
|
27
|
+
|
28
|
+
Gt06Server::Server.supervise(
|
29
|
+
as: 'Gt06Server',
|
30
|
+
args: [host, port, block, options: {logger: Logger.new(STDOUT)}.merge(options) ]
|
31
|
+
)
|
32
|
+
end
|
33
|
+
|
34
|
+
def initialize(host, port, handler, options: {} )
|
35
|
+
|
36
|
+
@logger = options.fetch(:logger, Logger.new(STDOUT))
|
37
|
+
@host = host
|
38
|
+
@port = port
|
39
|
+
|
40
|
+
@sessions = Concurrent::Map.new
|
41
|
+
|
42
|
+
killer = SessionKiller.new(@sessions, options.fetch(:session_timeout, nil), interval: options.fetch(:killer_interval, nil))
|
43
|
+
killer.run
|
44
|
+
|
45
|
+
@info = { killer_info: killer.info }
|
46
|
+
|
47
|
+
async.run handler
|
48
|
+
end
|
49
|
+
|
50
|
+
private
|
51
|
+
|
52
|
+
def run(handler)
|
53
|
+
@server = TCPServer.new(@host, @port)
|
54
|
+
@logger.info "Gt06Server has been run on host:#{@host} port: #{@port} "
|
55
|
+
loop { async.handle_connection(@server.accept, handler) }
|
56
|
+
end
|
57
|
+
|
58
|
+
def shutdown
|
59
|
+
@server.close if @server
|
60
|
+
end
|
61
|
+
|
62
|
+
def handle_connection(socket, handler)
|
63
|
+
begin
|
64
|
+
addr = socket.peeraddr
|
65
|
+
@logger.info "Connect #{addr}"
|
66
|
+
|
67
|
+
session = Session.new(socket, logger: @logger)
|
68
|
+
@sessions[session.object_id] = session
|
69
|
+
|
70
|
+
session.run(&handler)
|
71
|
+
rescue EOFError => exception
|
72
|
+
@logger.warn "#{addr} #{exception.message}"
|
73
|
+
rescue StandardError => exception
|
74
|
+
@logger.error exception.message
|
75
|
+
@logger.error exception.backtrace
|
76
|
+
ensure
|
77
|
+
socket.close if socket
|
78
|
+
@logger.info "Disconnect #{addr}"
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
module Gt06Server
|
3
|
+
class Session
|
4
|
+
class SessionError < RuntimeError; end
|
5
|
+
|
6
|
+
attr_reader :terminal_id, :io, :info, :logger
|
7
|
+
|
8
|
+
def initialize(io, logger: Logger.new(STDOUT))
|
9
|
+
@io = io
|
10
|
+
@terminal_id = ''
|
11
|
+
@info = { received_count: 0, sent_count: 0, last_received_at: Time.now}
|
12
|
+
@logger = logger
|
13
|
+
|
14
|
+
logger.debug 'New session has been created'
|
15
|
+
end
|
16
|
+
|
17
|
+
# @yield [Hash] information_content of packet
|
18
|
+
# @raise EOF
|
19
|
+
def run(&block)
|
20
|
+
handle_head_packet(Protocol.read_pack(@io))
|
21
|
+
|
22
|
+
loop do
|
23
|
+
handle_main_pack(Protocol.read_pack(@io), &block)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
private
|
28
|
+
|
29
|
+
def handle_head_packet(pack)
|
30
|
+
if pack.payload.message_type != :login_message
|
31
|
+
raise SessionError, 'Expect login message first but received: ' + pack.to_hex
|
32
|
+
end
|
33
|
+
|
34
|
+
@terminal_id = pack.payload.information_content.terminal_id.to_hex
|
35
|
+
@info[:received_count] += 1
|
36
|
+
@io.write(Protocol.replay_on(pack).to_binary_s)
|
37
|
+
@info[:sent_count] += 1
|
38
|
+
|
39
|
+
logger.debug "terminal_id: #{@terminal_id} , info #{@info}"
|
40
|
+
end
|
41
|
+
|
42
|
+
def handle_main_pack(pack, &block)
|
43
|
+
logger.debug "terminal_id: #{@terminal_id} , info #{@info}, message: #{pack}"
|
44
|
+
@info[:received_count] += 1
|
45
|
+
|
46
|
+
block.yield(pack.payload)
|
47
|
+
|
48
|
+
if (ack_pack = Protocol.replay_on(pack))
|
49
|
+
@io.write(ack_pack.to_binary_s)
|
50
|
+
@info[:sent_count] += 1
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
require 'concurrent'
|
2
|
+
|
3
|
+
class SessionKiller
|
4
|
+
attr_reader :sessions , :info, :timeout, :interval
|
5
|
+
|
6
|
+
def initialize(sessions, timeout = 60, interval: 30)
|
7
|
+
@sessions = sessions
|
8
|
+
@timeout = timeout
|
9
|
+
@interval = interval
|
10
|
+
@info = {killed: 0, live:0, count:0}
|
11
|
+
end
|
12
|
+
|
13
|
+
def run
|
14
|
+
timer = Concurrent::TimerTask.new(execution_interval: @interval) do
|
15
|
+
time_now = Time.now
|
16
|
+
@sessions.each_pair do |key, session|
|
17
|
+
if (session.info[:last_received_at] + @timeout) < time_now
|
18
|
+
session.io.setsockopt(Socket::SOL_SOCKET, Socket::SO_LINGER, [1,0].pack('ii'))
|
19
|
+
session.io.close
|
20
|
+
puts "Session #{session} has been closed"
|
21
|
+
@info[:killed] += 1
|
22
|
+
@sessions.delete(key)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
@info[:live] = @sessions.size
|
27
|
+
@info[:count] += 1
|
28
|
+
end
|
29
|
+
|
30
|
+
|
31
|
+
timer.execute
|
32
|
+
end
|
33
|
+
|
34
|
+
end
|
data/lib/libcrc16.rb
ADDED
data/lib/libcrc_16.so
ADDED
Binary file
|
metadata
ADDED
@@ -0,0 +1,145 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: gt06_server
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- CoolElvis
|
8
|
+
autorequire:
|
9
|
+
bindir: exe
|
10
|
+
cert_chain: []
|
11
|
+
date: 2016-08-02 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: bindata
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '2.3'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '2.3'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: celluloid-io
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: 0.17.3
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: 0.17.3
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: concurrent-ruby
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '1.0'
|
48
|
+
type: :runtime
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '1.0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: bundler
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - "~>"
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '1.11'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - "~>"
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '1.11'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: rake
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - "~>"
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '10.0'
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - "~>"
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '10.0'
|
83
|
+
description: TCP server for gt06(TK100) gps tracker
|
84
|
+
email:
|
85
|
+
- elvisplus2@gmail.com
|
86
|
+
executables: []
|
87
|
+
extensions: []
|
88
|
+
extra_rdoc_files: []
|
89
|
+
files:
|
90
|
+
- ".codeclimate.yml"
|
91
|
+
- ".gitignore"
|
92
|
+
- ".reek"
|
93
|
+
- ".rubocop.yml"
|
94
|
+
- ".ruby-version"
|
95
|
+
- ".travis.yml"
|
96
|
+
- Gemfile
|
97
|
+
- Gemfile.lock
|
98
|
+
- README.md
|
99
|
+
- Rakefile
|
100
|
+
- gt06_server.gemspec
|
101
|
+
- lib/ext/CMakeLists.txt
|
102
|
+
- lib/ext/crc_16.cpp
|
103
|
+
- lib/gt06_server.rb
|
104
|
+
- lib/gt06_server/crc.rb
|
105
|
+
- lib/gt06_server/messages/alarm_packet.rb
|
106
|
+
- lib/gt06_server/messages/date_time_information.rb
|
107
|
+
- lib/gt06_server/messages/gps_information.rb
|
108
|
+
- lib/gt06_server/messages/gps_query_address.rb
|
109
|
+
- lib/gt06_server/messages/lbs_information.rb
|
110
|
+
- lib/gt06_server/messages/location_data.rb
|
111
|
+
- lib/gt06_server/messages/login_message.rb
|
112
|
+
- lib/gt06_server/messages/status_information.rb
|
113
|
+
- lib/gt06_server/packet.rb
|
114
|
+
- lib/gt06_server/protocol.rb
|
115
|
+
- lib/gt06_server/server.rb
|
116
|
+
- lib/gt06_server/session.rb
|
117
|
+
- lib/gt06_server/session_killer.rb
|
118
|
+
- lib/gt06_server/version.rb
|
119
|
+
- lib/libcrc16.rb
|
120
|
+
- lib/libcrc_16.so
|
121
|
+
homepage: https://github.com/CoolElvis/gt06_server
|
122
|
+
licenses:
|
123
|
+
- MIT
|
124
|
+
metadata: {}
|
125
|
+
post_install_message:
|
126
|
+
rdoc_options: []
|
127
|
+
require_paths:
|
128
|
+
- lib
|
129
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
130
|
+
requirements:
|
131
|
+
- - ">="
|
132
|
+
- !ruby/object:Gem::Version
|
133
|
+
version: '0'
|
134
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
135
|
+
requirements:
|
136
|
+
- - ">="
|
137
|
+
- !ruby/object:Gem::Version
|
138
|
+
version: '0'
|
139
|
+
requirements: []
|
140
|
+
rubyforge_project:
|
141
|
+
rubygems_version: 2.5.1
|
142
|
+
signing_key:
|
143
|
+
specification_version: 4
|
144
|
+
summary: TCP server for gt06(TK100) gps tracker
|
145
|
+
test_files: []
|