gt06_server 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
+
[![Code Climate](https://codeclimate.com/github/CoolElvis/gt06_server/badges/gpa.svg)](https://codeclimate.com/github/CoolElvis/gt06_server)
|
4
|
+
[![Test Coverage](https://codeclimate.com/github/CoolElvis/gt06_server/badges/coverage.svg)](https://codeclimate.com/github/CoolElvis/gt06_server/coverage)
|
5
|
+
[![Issue Count](https://codeclimate.com/github/CoolElvis/gt06_server/badges/issue_count.svg)](https://codeclimate.com/github/CoolElvis/gt06_server)
|
6
|
+
[![Build Status](https://travis-ci.org/CoolElvis/gt06_server.svg?branch=master)](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: []
|