Commit 3e338bf73e9f7fadce07e320e9979aa0d8e25482

Authored by 潘钊
2 parents 09c8d694 8c67a447

Merge branch 'minhang' into qingpu

# Conflicts:
#	src/main/java/com/bsth/data/BasicData.java
#	src/main/resources/application-dev.properties
#	src/main/resources/datatools/config-prod.properties
#	src/main/resources/static/pages/permission/user/list.html
Showing 37 changed files with 3468 additions and 860 deletions

Too many changes to show.

To preserve performance only 37 of 220 files are displayed.

README.md
1 -公交调度系统BS版 0.1  
2 -======  
3 -----------  
4 -## 目录  
5 ----------  
6 - * [字典表](#字典表)  
7 - * [动态jpa查询实现](#动态jpa查询实现)  
8 - * [车载 gps 相关数据](#gps)  
9 - * [实时gps数据接口 http](#实时gps接口)  
10 - * [进出站数据表结构](#进站数据)  
11 - * [异常警报表结构](#异常警报)  
12 - * [大间隔](#大间隔)  
13 - * [超速](#超速)  
14 - * [越界](#越界)  
15 - * [越站](#越站)  
16 - * [聚集](#聚集)  
17 - * [掉线](#掉线)  
18 - * [调度消息下发接口HTTP](#调度消息下发接口)  
19 - * [调度消息上传接口HTTP](#调度消息上传接口)  
20 -  
21 -----------  
22 -  
23 -## 字典表  
24 -----------  
25 -字典操作全部由前端负责,主要有2种。  
26 -  
27 -1、转换字典代码。  
28 - 当pjax的`pjax:success`事件被触发(片段加载完成)  
29 - 扫描容器内所有有 `$(".nt-dictionary")` 元素进行字典转换  
30 -``` html  
31 ---dom标签为span div p h1 h2 h3 h4 h5 h6 等等文本元素时,如下写法,text为要转换的代码  
32 -<span class="nt-dictionary" data-group="ScheduleType">out</span>  
33 ---to  
34 -<span>出场</span>  
35 -  
36 -<!- dom标签为input时,如下 data-code为要转换的代码 -->  
37 -<input class="nt-dictionary" data-group="ScheduleType" data-code="out">  
38 ---to  
39 -<input value="出场">  
40 -  
41 -<!- dom标签为select时 如下 data-code为要选中的项 -->  
42 -<select class="nt-dictionary" data-group="ScheduleType" data-code="out"></select>  
43 ---to  
44 -<select>  
45 - <option value="normal">正常班次</option>  
46 - <option value="out" selected>出场</option>  
47 - <option value="in">进场</option>  
48 - <option value="oil">加油</option>  
49 - <option value="temp">临加</option>  
50 - <option value="region">区间</option>  
51 - <option value="venting">放空</option>  
52 - <option value="major">放大站</option>  
53 -</select>  
54 -```  
55 -*原标签的class 除nt-dictionary 外,其余均会被保留*  
56 -  
57 -2、dictionary.js提供如下方法自行使用  
58 -| 方法名 | 参数|返回|  
59 -| ---- | ---- | ---- | ---- |  
60 -| groups (获取所有字典组) | 无| | {LineTrend: 线路走向, ScheduleType: 班次类型} |  
61 -| getByGroup (获取字典组下的字典)| (group) |{0: 上行, 1: 下行}|  
62 -| transformCode (转换字典代码)| (group, code) | 上行 |  
63 -  
64 -## 动态jpa查询实现  
65 -----------  
66 -*参考调度系统枚举com.bsth.entity.search.SearchOperator*  
67 -  
68 -  
69 -## gps  
70 -----------  
71 -### 实时gps接口  
72 -  
73 -所有在线GPS: [http://192.168.168.192:8080/transport_server/rtgps](http://192.168.168.192:8080/transport_server/rtgps/)  
74 -根据设备号查询:[http://192.168.168.192:8080/transport_server/rtgps/05B01901](http://192.168.168.192:8080/transport_server/rtgps/05B01901)  
75 -  
76 -<span style="color: red">Response</span>:  
77 -```json  
78 -{  
79 - "data":[  
80 - {  
81 - "companyCode":5,  
82 - "lineId":10329,  
83 - "deviceId":"05B01901",  
84 - "carparkNo":"00000000",  
85 - "stopNo":"7C890002",  
86 - "lon":121.549866,  
87 - "lat":31.238798,  
88 - "timestamp":1397104499000,  
89 - "speed":42.0,  
90 - "direction":245.9,  
91 - "state":0,  
92 - "upDown":0  
93 - }]  
94 -}  
95 -```  
96 -  
97 -| -- | --|--|  
98 -| ---- | ---- | ---- |  
99 -| companyCode | int | 公司代码 |  
100 -| lineId | int | 线路编码 |  
101 -| deviceId | String | 设备编号 |  
102 -| carparkNo | String | 停车场编码 |  
103 -| stopNo | String | 站点编码 |  
104 -| lon | float | 经度 |  
105 -| lat | float | 纬度 |  
106 -| timestamp | long | 时间戳 |  
107 -| speed | float | 速度|  
108 -| direction | float | 方向(角度) |  
109 -| state | int | 营运状态( 0 营运 ,1 非营运, -1 无效) |  
110 -| upDown | int | 上下行(0 上行 , 1 下行 , -1 无效)|  
111 -  
112 -  
113 -### 进站数据  
114 -----------  
115 -表名:  
116 -  
117 -| .. | .. | .. |  
118 -| ---- | ---- | ---- |  
119 -| id | int | 主键 |  
120 -| deviceId | String | 设备号 |  
121 -| lineId | int | 线路编码 |  
122 -| stopNo | long | 站点编码 |  
123 -| timestamp | long | 时间戳 |  
124 -| upDown | int | 上下行(0 上行 , 1 下行 , -1 无效) |  
125 -| createDate | Date | 创建时间 |  
126 -  
127 -  
128 -### 异常警报  
129 -----------  
130 -  
131 -### 大间隔  
132 -----------  
133 -表名:  
134 -  
135 -| .. | .. | .. |  
136 -| ---- | ---- | ---- |  
137 -| id | int | 主键 |  
138 -| line | int | 线路编码 |  
139 -| station | String | 站点编码 |  
140 -| cVehicle | String | 当前车辆编码 |  
141 -| lastVehicle | String | 上一个车辆编码 |  
142 -| interval | long | 间隔时间(秒) |  
143 -| timestamp | long | 时间戳 |  
144 -| createDate | Date | 创建时间 |  
145 -  
146 -### 超速  
147 -----------  
148 -表名:  
149 -  
150 -| .. | .. | .. |  
151 -| ---- | ---- | ---- |  
152 -| id | int | 主键 |  
153 -| vehicle | String | 车辆编码 |  
154 -| line | int | 线路编码 |  
155 -| upDown | int | 上下行(0 上行 , 1 下行 , -1 无效) |  
156 -| lon | float | 经度 |  
157 -| lat | float | 纬度|  
158 -| speed | float | 速度 |  
159 -| timestamp | long | 时间戳 |  
160 -| createDate | Date | 时间 |  
161 -  
162 -### 越界  
163 -----------  
164 -表名:  
165 -  
166 -| .. | .. | .. |  
167 -| ---- | ---- | ---- |  
168 -| id | int | 主键 |  
169 -| vehicle | String | 车辆编码 |  
170 -| line | int | 线路编码 |  
171 -| upDown | int | 上下行(0 上行 , 1 下行 , -1 无效) |  
172 -| lon | float | 经度 |  
173 -| lat | float | 纬度|  
174 -| location | String | 越界位置(由线调页面进行初始转换)意思是该字段默认为空,页面第一次查看时会写入值|  
175 -| timestamp | long | 时间戳 |  
176 -| createDate | Date | 时间 |  
177 -  
178 -  
179 -### 越站  
180 -----------  
181 -表名:  
182 -  
183 -| .. | .. | .. |  
184 -| ---- | ---- | ---- |  
185 -| id | int | 主键 |  
186 -| line | int | 线路编码 |  
187 -| upDown | int | 上下行(0 上行 , 1 下行 , -1 无效) |  
188 -| station | String | 站点编码 |  
189 -| vehicle | String | 车辆编码 |  
190 -| inData | Date | 进站时间 |  
191 -| outDate | Date | 出站时间 |  
192 -  
193 -  
194 -### 聚集  
195 -----------  
196 -表名:  
197 -  
198 -| .. | .. | .. |  
199 -| ---- | ---- | ---- |  
200 -| id | int | 主键 |  
201 -| line | int | 线路编码 |  
202 -| upDown | int | 上下行(0 上行 , 1 下行 , -1 无效) |  
203 -| stations | String | 站点(多个用 , 号分隔。应该是连续站点) |  
204 -| vehicles | String | 车辆编码(多个用 , 号分隔) |  
205 -| timestamp | long | 时间戳 |  
206 -| createDate | Date | 时间 |  
207 -  
208 -  
209 -### 掉线  
210 -----------  
211 -表名:  
212 -  
213 -| .. | .. | .. |  
214 -| ---- | ---- | ---- |  
215 -| id | int | 主键 |  
216 -| line | int | 线路编码 |  
217 -| upDown | int | 上下行(0 上行 , 1 下行 , -1 无效) |  
218 -| vehicle | String | 车辆编码 |  
219 -| lon | float | 经度 |  
220 -| lat | float | 纬度|  
221 -| timestamp | long | 时间戳 |  
222 -| createDate | Date | 时间 |  
223 -  
224 -  
225 -### 调度消息下发接口  
226 -----------  
227 -[http://192.168.168.192:8080/transport_server/message](http://192.168.168.192:8080/transport_server/message/)  
228 -  
229 -<span style="color: red">Request</span>:  
230 -```json  
231 -{  
232 - "deviceId":12345,  
233 - "timestamp":44324,  
234 - "operCode":0x60,  
235 - "data":{  
236 - "companyCode":22,  
237 - "deviceId":"029L2222",  
238 - "timestamp":134326,  
239 - "instructType":00,  
240 - "dispatchInstruct":0x00,  
241 - "msgId":12345,  
242 - "alarmTime":201606012000,  
243 - "serviceState":00000000,  
244 - "txtContent":"你好"  
245 - }  
246 -}  
247 -```  
248 -| .. | .. | .. |  
249 -| ---- | ---- | ---- |  
250 -| deviceId | string | 设备编号 |  
251 -| timestamp | long | 时间戳(ms) |  
252 -| operCode | short | 一级协议 |  
253 -| data.companyCode | short | 公司代码 |  
254 -| data.deviceId | string | 设备编号 |  
255 -| data.timestamp | long | 时间戳 |  
256 -| data.instructType | short | 保留 默认0 |  
257 -| data.dispatchInstruct | short | 调度指令 调度指令。0X00表示信息短语,0X01表示取消上次指令+调度指令(闹钟有效),0x02表示为调度指令(闹钟有效); 0x03表示运营状态指令(闹钟无效);0x04表示其他指令。|  
258 -| data.msgId | long | 同上 |  
259 -| data.alarmTime | long | 闹钟 MMddhhmm|  
260 -| data.serviceState | long | 多状态字节   先由车载发起车辆故障、事故报告、扣证、纠纷、加油等审请,经调度确认后,下发调度指令与运营状态。当调度指令为0X00终端需要提示信息。当调度指令为0x01和0x02,终端需要收到后提示信息。并且必须在闹钟结束后进行终端相关状态更新。在闹钟时间前120秒开始提示。当调度指令为0x03,收到后进行终端相关状态更新,终端不需要提示信息。当调度指令为0x04,暂不需要提示信息。|  
261 -| data.txtContent | string | 下发的消息文本 |  
262 -```json  
263 -{  
264 - "deviceId":12345,  
265 - "timestamp":44324,  
266 - "operCode":0x64,  
267 - "data":{  
268 - "cityCode":22,  
269 - "deviceId":"029L2222",  
270 - "lineId":"134326"  
271 - }  
272 -}  
273 -```  
274 -| .. | .. | .. |  
275 -| ---- | ---- | ---- |  
276 -| deviceId | string | 设备编号 |  
277 -| timestamp | long | 时间戳(ms) |  
278 -| operCode | short | 一级协议 |  
279 -| data.cityCode | short | 城市区号 |  
280 -| data.deviceId | string | 设备编号 |  
281 -| data.lineId | string | 线路编号 6位 不足6位前面补0 如编号890 用000890表示 |  
282 -  
283 -```json  
284 -{  
285 - "deviceId":12345,  
286 - "timestamp":44324,  
287 - "operCode":0xC0,  
288 - "data":{  
289 - "operCode":0x86,  
290 - "requestAck":0x06  
291 - }  
292 -}  
293 -```  
294 -| .. | .. | .. |  
295 -| ---- | ---- | ---- |  
296 -| deviceId | string | 设备编号 |  
297 -| timestamp | long | 时间戳(ms) |  
298 -| operCode | short | 一级协议 |  
299 -| data.operCode | short | 二级协议 |  
300 -| data.requestAck | short | 请求应答字 0x06同意 0x15不同意|  
301 -  
302 -<span style="color: red">Response</span>:  
303 -```json  
304 -{  
305 - "errCode":0  
306 -}  
307 -```  
308 -  
309 -  
310 -### 调度消息上传接口  
311 -----------  
312 -上行POST地址:[http://192.168.168.120:9088/control/upstream](http://192.168.168.120:9088/control/upstream)  
313 -<span style="color: red">Request</span>:  
314 -```json  
315 -{  
316 - "deviceId":12345,  
317 - "timestamp":44324,  
318 - "status":0,  
319 - "operCode":0x80,  
320 - "data":{  
321 - "operCode":0x26,  
322 - "requestCode":22  
323 - }  
324 -}  
325 -```  
326 -| .. | .. | .. |  
327 -| ---- | ---- | ---- |  
328 -| deviceId | string | 设备编号 |  
329 -| timestamp | long | 时间戳(ms) |  
330 -| status | int | 0x80时无数据 0表示失败 1表示成功或设备确认 2表示驾驶员阅读 |  
331 -| operCode | short | 一级协议 消息确认将无数据 |  
332 -| data.operCode | short | 二级协议 |  
333 -| data.requestCode | short | 请求代码0xa1 恢复运营 0xa2 申请调档 0xa3 出场请求 0xa5 进场请求 0xa7 加油请求 0x50 车辆故障 0x70 路阻报告 0x60 事故报告 0x11 扣证纠纷 0x12 报警 |  
334 -<span style="color: red">Response</span>:  
335 -```json  
336 -{  
337 - "errCode":0  
338 -} 1 +公交调度系统BS版 0.1
  2 +======
  3 +----------
  4 +## 目录
  5 +---------
  6 + * [字典表](#字典表)
  7 + * [动态jpa查询实现](#动态jpa查询实现)
  8 + * [车载 gps 相关数据](#gps)
  9 + * [实时gps数据接口 http](#实时gps接口)
  10 + * [进出站数据表结构](#进站数据)
  11 + * [异常警报表结构](#异常警报)
  12 + * [大间隔](#大间隔)
  13 + * [超速](#超速)
  14 + * [越界](#越界)
  15 + * [越站](#越站)
  16 + * [聚集](#聚集)
  17 + * [掉线](#掉线)
  18 + * [调度消息下发接口HTTP](#调度消息下发接口)
  19 + * [调度消息上传接口HTTP](#调度消息上传接口)
  20 +
  21 +----------
  22 +
  23 +## 字典表
  24 +----------
  25 +字典操作全部由前端负责,主要有2种。
  26 +
  27 +1、转换字典代码。
  28 + 当pjax的`pjax:success`事件被触发(片段加载完成)
  29 + 扫描容器内所有有 `$(".nt-dictionary")` 元素进行字典转换
  30 +``` html
  31 +--dom标签为span div p h1 h2 h3 h4 h5 h6 等等文本元素时,如下写法,text为要转换的代码
  32 +<span class="nt-dictionary" data-group="ScheduleType">out</span>
  33 +--to
  34 +<span>出场</span>
  35 +
  36 +<!- dom标签为input时,如下 data-code为要转换的代码 -->
  37 +<input class="nt-dictionary" data-group="ScheduleType" data-code="out">
  38 +--to
  39 +<input value="出场">
  40 +
  41 +<!- dom标签为select时 如下 data-code为要选中的项 -->
  42 +<select class="nt-dictionary" data-group="ScheduleType" data-code="out"></select>
  43 +--to
  44 +<select>
  45 + <option value="normal">正常班次</option>
  46 + <option value="out" selected>出场</option>
  47 + <option value="in">进场</option>
  48 + <option value="oil">加油</option>
  49 + <option value="temp">临加</option>
  50 + <option value="region">区间</option>
  51 + <option value="venting">放空</option>
  52 + <option value="major">放大站</option>
  53 +</select>
  54 +```
  55 +*原标签的class 除nt-dictionary 外,其余均会被保留*
  56 +
  57 +2、dictionary.js提供如下方法自行使用
  58 +| 方法名 | 参数|返回|
  59 +| ---- | ---- | ---- | ---- |
  60 +| groups (获取所有字典组) | 无| | {LineTrend: 线路走向, ScheduleType: 班次类型} |
  61 +| getByGroup (获取字典组下的字典)| (group) |{0: 上行, 1: 下行}|
  62 +| transformCode (转换字典代码)| (group, code) | 上行 |
  63 +
  64 +## 动态jpa查询实现
  65 +----------
  66 +*参考调度系统枚举com.bsth.entity.search.SearchOperator*
  67 +
  68 +
  69 +## gps
  70 +----------
  71 +### 实时gps接口
  72 +
  73 +所有在线GPS: [http://192.168.168.192:8080/transport_server/rtgps](http://192.168.168.192:8080/transport_server/rtgps/)
  74 +根据设备号查询:[http://192.168.168.192:8080/transport_server/rtgps/05B01901](http://192.168.168.192:8080/transport_server/rtgps/05B01901)
  75 +
  76 +<span style="color: red">Response</span>:
  77 +```json
  78 +{
  79 + "data":[
  80 + {
  81 + "companyCode":5,
  82 + "lineId":10329,
  83 + "deviceId":"05B01901",
  84 + "carparkNo":"00000000",
  85 + "stopNo":"7C890002",
  86 + "lon":121.549866,
  87 + "lat":31.238798,
  88 + "timestamp":1397104499000,
  89 + "speed":42.0,
  90 + "direction":245.9,
  91 + "state":0,
  92 + "upDown":0
  93 + }]
  94 +}
  95 +```
  96 +
  97 +| -- | --|--|
  98 +| ---- | ---- | ---- |
  99 +| companyCode | int | 公司代码 |
  100 +| lineId | int | 线路编码 |
  101 +| deviceId | String | 设备编号 |
  102 +| carparkNo | String | 停车场编码 |
  103 +| stopNo | String | 站点编码 |
  104 +| lon | float | 经度 |
  105 +| lat | float | 纬度 |
  106 +| timestamp | long | 时间戳 |
  107 +| speed | float | 速度|
  108 +| direction | float | 方向(角度) |
  109 +| state | int | 营运状态( 0 营运 ,1 非营运, -1 无效) |
  110 +| upDown | int | 上下行(0 上行 , 1 下行 , -1 无效)|
  111 +
  112 +
  113 +### 进站数据
  114 +----------
  115 +表名:
  116 +
  117 +| .. | .. | .. |
  118 +| ---- | ---- | ---- |
  119 +| id | int | 主键 |
  120 +| deviceId | String | 设备号 |
  121 +| lineId | int | 线路编码 |
  122 +| stopNo | long | 站点编码 |
  123 +| timestamp | long | 时间戳 |
  124 +| upDown | int | 上下行(0 上行 , 1 下行 , -1 无效) |
  125 +| createDate | Date | 创建时间 |
  126 +
  127 +
  128 +### 异常警报
  129 +----------
  130 +
  131 +### 大间隔
  132 +----------
  133 +表名:
  134 +
  135 +| .. | .. | .. |
  136 +| ---- | ---- | ---- |
  137 +| id | int | 主键 |
  138 +| line | int | 线路编码 |
  139 +| station | String | 站点编码 |
  140 +| cVehicle | String | 当前车辆编码 |
  141 +| lastVehicle | String | 上一个车辆编码 |
  142 +| interval | long | 间隔时间(秒) |
  143 +| timestamp | long | 时间戳 |
  144 +| createDate | Date | 创建时间 |
  145 +
  146 +### 超速
  147 +----------
  148 +表名:
  149 +
  150 +| .. | .. | .. |
  151 +| ---- | ---- | ---- |
  152 +| id | int | 主键 |
  153 +| vehicle | String | 车辆编码 |
  154 +| line | int | 线路编码 |
  155 +| upDown | int | 上下行(0 上行 , 1 下行 , -1 无效) |
  156 +| lon | float | 经度 |
  157 +| lat | float | 纬度|
  158 +| speed | float | 速度 |
  159 +| timestamp | long | 时间戳 |
  160 +| createDate | Date | 时间 |
  161 +
  162 +### 越界
  163 +----------
  164 +表名:
  165 +
  166 +| .. | .. | .. |
  167 +| ---- | ---- | ---- |
  168 +| id | int | 主键 |
  169 +| vehicle | String | 车辆编码 |
  170 +| line | int | 线路编码 |
  171 +| upDown | int | 上下行(0 上行 , 1 下行 , -1 无效) |
  172 +| lon | float | 经度 |
  173 +| lat | float | 纬度|
  174 +| location | String | 越界位置(由线调页面进行初始转换)意思是该字段默认为空,页面第一次查看时会写入值|
  175 +| timestamp | long | 时间戳 |
  176 +| createDate | Date | 时间 |
  177 +
  178 +
  179 +### 越站
  180 +----------
  181 +表名:
  182 +
  183 +| .. | .. | .. |
  184 +| ---- | ---- | ---- |
  185 +| id | int | 主键 |
  186 +| line | int | 线路编码 |
  187 +| upDown | int | 上下行(0 上行 , 1 下行 , -1 无效) |
  188 +| station | String | 站点编码 |
  189 +| vehicle | String | 车辆编码 |
  190 +| inData | Date | 进站时间 |
  191 +| outDate | Date | 出站时间 |
  192 +
  193 +
  194 +### 聚集
  195 +----------
  196 +表名:
  197 +
  198 +| .. | .. | .. |
  199 +| ---- | ---- | ---- |
  200 +| id | int | 主键 |
  201 +| line | int | 线路编码 |
  202 +| upDown | int | 上下行(0 上行 , 1 下行 , -1 无效) |
  203 +| stations | String | 站点(多个用 , 号分隔。应该是连续站点) |
  204 +| vehicles | String | 车辆编码(多个用 , 号分隔) |
  205 +| timestamp | long | 时间戳 |
  206 +| createDate | Date | 时间 |
  207 +
  208 +
  209 +### 掉线
  210 +----------
  211 +表名:
  212 +
  213 +| .. | .. | .. |
  214 +| ---- | ---- | ---- |
  215 +| id | int | 主键 |
  216 +| line | int | 线路编码 |
  217 +| upDown | int | 上下行(0 上行 , 1 下行 , -1 无效) |
  218 +| vehicle | String | 车辆编码 |
  219 +| lon | float | 经度 |
  220 +| lat | float | 纬度|
  221 +| timestamp | long | 时间戳 |
  222 +| createDate | Date | 时间 |
  223 +
  224 +
  225 +### 调度消息下发接口
  226 +----------
  227 +[http://192.168.168.192:8080/transport_server/message](http://192.168.168.192:8080/transport_server/message/)
  228 +
  229 +<span style="color: red">Request</span>:
  230 +```json
  231 +{
  232 + "deviceId":12345,
  233 + "timestamp":44324,
  234 + "operCode":0x60,
  235 + "data":{
  236 + "companyCode":22,
  237 + "deviceId":"029L2222",
  238 + "timestamp":134326,
  239 + "instructType":00,
  240 + "dispatchInstruct":0x00,
  241 + "msgId":12345,
  242 + "alarmTime":201606012000,
  243 + "serviceState":00000000,
  244 + "txtContent":"你好"
  245 + }
  246 +}
  247 +```
  248 +| .. | .. | .. |
  249 +| ---- | ---- | ---- |
  250 +| deviceId | string | 设备编号 |
  251 +| timestamp | long | 时间戳(ms) |
  252 +| operCode | short | 一级协议 |
  253 +| data.companyCode | short | 公司代码 |
  254 +| data.deviceId | string | 设备编号 |
  255 +| data.timestamp | long | 时间戳 |
  256 +| data.instructType | short | 保留 默认0 |
  257 +| data.dispatchInstruct | short | 调度指令 调度指令。0X00表示信息短语,0X01表示取消上次指令+调度指令(闹钟有效),0x02表示为调度指令(闹钟有效); 0x03表示运营状态指令(闹钟无效);0x04表示其他指令。|
  258 +| data.msgId | long | 同上 |
  259 +| data.alarmTime | long | 闹钟 MMddhhmm|
  260 +| data.serviceState | long | 多状态字节   先由车载发起车辆故障、事故报告、扣证、纠纷、加油等审请,经调度确认后,下发调度指令与运营状态。当调度指令为0X00终端需要提示信息。当调度指令为0x01和0x02,终端需要收到后提示信息。并且必须在闹钟结束后进行终端相关状态更新。在闹钟时间前120秒开始提示。当调度指令为0x03,收到后进行终端相关状态更新,终端不需要提示信息。当调度指令为0x04,暂不需要提示信息。|
  261 +| data.txtContent | string | 下发的消息文本 |
  262 +```json
  263 +{
  264 + "deviceId":12345,
  265 + "timestamp":44324,
  266 + "operCode":0x64,
  267 + "data":{
  268 + "cityCode":22,
  269 + "deviceId":"029L2222",
  270 + "lineId":"134326"
  271 + }
  272 +}
  273 +```
  274 +| .. | .. | .. |
  275 +| ---- | ---- | ---- |
  276 +| deviceId | string | 设备编号 |
  277 +| timestamp | long | 时间戳(ms) |
  278 +| operCode | short | 一级协议 |
  279 +| data.cityCode | short | 城市区号 |
  280 +| data.deviceId | string | 设备编号 |
  281 +| data.lineId | string | 线路编号 6位 不足6位前面补0 如编号890 用000890表示 |
  282 +
  283 +```json
  284 +{
  285 + "deviceId":12345,
  286 + "timestamp":44324,
  287 + "operCode":0xC0,
  288 + "data":{
  289 + "operCode":0x86,
  290 + "requestAck":0x06
  291 + }
  292 +}
  293 +```
  294 +| .. | .. | .. |
  295 +| ---- | ---- | ---- |
  296 +| deviceId | string | 设备编号 |
  297 +| timestamp | long | 时间戳(ms) |
  298 +| operCode | short | 一级协议 |
  299 +| data.operCode | short | 二级协议 |
  300 +| data.requestAck | short | 请求应答字 0x06同意 0x15不同意|
  301 +
  302 +<span style="color: red">Response</span>:
  303 +```json
  304 +{
  305 + "errCode":0
  306 +}
  307 +```
  308 +
  309 +
  310 +### 调度消息上传接口
  311 +----------
  312 +上行POST地址:[http://192.168.168.120:9088/control/upstream](http://192.168.168.120:9088/control/upstream)
  313 +<span style="color: red">Request</span>:
  314 +```json
  315 +{
  316 + "deviceId":12345,
  317 + "timestamp":44324,
  318 + "status":0,
  319 + "operCode":0x80,
  320 + "data":{
  321 + "operCode":0x26,
  322 + "requestCode":22
  323 + }
  324 +}
  325 +```
  326 +| .. | .. | .. |
  327 +| ---- | ---- | ---- |
  328 +| deviceId | string | 设备编号 |
  329 +| timestamp | long | 时间戳(ms) |
  330 +| status | int | 0x80时无数据 0表示失败 1表示成功或设备确认 2表示驾驶员阅读 |
  331 +| operCode | short | 一级协议 消息确认将无数据 |
  332 +| data.operCode | short | 二级协议 |
  333 +| data.requestCode | short | 请求代码0xa1 恢复运营 0xa2 申请调档 0xa3 出场请求 0xa5 进场请求 0xa7 加油请求 0x50 车辆故障 0x70 路阻报告 0x60 事故报告 0x11 扣证纠纷 0x12 报警 |
  334 +<span style="color: red">Response</span>:
  335 +```json
  336 +{
  337 + "errCode":0
  338 +}
339 ``` 339 ```
340 \ No newline at end of file 340 \ No newline at end of file
src/main/java/com/bsth/Application.java
@@ -2,6 +2,10 @@ package com.bsth; @@ -2,6 +2,10 @@ package com.bsth;
2 2
3 import com.fasterxml.jackson.databind.ObjectMapper; 3 import com.fasterxml.jackson.databind.ObjectMapper;
4 import com.fasterxml.jackson.databind.SerializationFeature; 4 import com.fasterxml.jackson.databind.SerializationFeature;
  5 +
  6 +import java.util.concurrent.Executors;
  7 +import java.util.concurrent.ScheduledExecutorService;
  8 +
5 import org.springframework.boot.SpringApplication; 9 import org.springframework.boot.SpringApplication;
6 import org.springframework.boot.autoconfigure.SpringBootApplication; 10 import org.springframework.boot.autoconfigure.SpringBootApplication;
7 import org.springframework.boot.builder.SpringApplicationBuilder; 11 import org.springframework.boot.builder.SpringApplicationBuilder;
@@ -11,6 +15,8 @@ import org.springframework.context.annotation.Primary; @@ -11,6 +15,8 @@ import org.springframework.context.annotation.Primary;
11 15
12 @SpringBootApplication 16 @SpringBootApplication
13 public class Application extends SpringBootServletInitializer { 17 public class Application extends SpringBootServletInitializer {
  18 +
  19 + public static ScheduledExecutorService mainServices = Executors.newScheduledThreadPool(8);
14 20
15 @Override 21 @Override
16 protected SpringApplicationBuilder configure(SpringApplicationBuilder application) { 22 protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
src/main/java/com/bsth/StartCommand.java
1 package com.bsth; 1 package com.bsth;
2 2
3 3
4 -import com.bsth.repository.schedule.CarConfigInfoRepository;  
5 import com.bsth.security.SecurityMetadataSourceService; 4 import com.bsth.security.SecurityMetadataSourceService;
6 -import com.bsth.service.realcontrol.buffer.GetSchedulePlanThread;  
7 -import com.bsth.service.realcontrol.buffer.SchedulePersistenceThread;  
8 -import com.bsth.util.DateUtils;  
9 -import com.bsth.vehicle.common.CommonRefreshThread;  
10 -import com.bsth.vehicle.directive.buffer.DirectiveBuffer;  
11 -import com.bsth.vehicle.directive.service.DirectiveService;  
12 -import com.bsth.vehicle.directive.thread.DirectivePersistenceThread;  
13 -import com.bsth.vehicle.directive.thread.FirstScheduleIssuedThread;  
14 -import com.bsth.vehicle.gpsdata.ArrivalThread;  
15 -import com.bsth.vehicle.gpsdata.GpsOfflineMonitorThread;  
16 -import com.bsth.vehicle.gpsdata.GpsRealDataRefreshThread;  
17 5
18 import org.slf4j.Logger; 6 import org.slf4j.Logger;
19 import org.slf4j.LoggerFactory; 7 import org.slf4j.LoggerFactory;
@@ -21,9 +9,6 @@ import org.springframework.beans.factory.annotation.Autowired; @@ -21,9 +9,6 @@ import org.springframework.beans.factory.annotation.Autowired;
21 import org.springframework.boot.CommandLineRunner; 9 import org.springframework.boot.CommandLineRunner;
22 import org.springframework.stereotype.Component; 10 import org.springframework.stereotype.Component;
23 11
24 -import java.util.concurrent.Executors;  
25 -import java.util.concurrent.ScheduledExecutorService;  
26 -import java.util.concurrent.TimeUnit;  
27 12
28 /** 13 /**
29 * 随应用启动运行 14 * 随应用启动运行
@@ -38,9 +23,9 @@ public class StartCommand implements CommandLineRunner{ @@ -38,9 +23,9 @@ public class StartCommand implements CommandLineRunner{
38 @Autowired 23 @Autowired
39 SecurityMetadataSourceService invocationSecurityMetadataSourceService; 24 SecurityMetadataSourceService invocationSecurityMetadataSourceService;
40 25
41 - public static ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(8); 26 + //public static ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(8);
42 27
43 - @Autowired 28 + /*@Autowired
44 GpsRealDataRefreshThread gpsRefreshThread; 29 GpsRealDataRefreshThread gpsRefreshThread;
45 @Autowired 30 @Autowired
46 GetSchedulePlanThread getSchedulePlanThread; 31 GetSchedulePlanThread getSchedulePlanThread;
@@ -63,11 +48,11 @@ public class StartCommand implements CommandLineRunner{ @@ -63,11 +48,11 @@ public class StartCommand implements CommandLineRunner{
63 CarConfigInfoRepository carConfigInfoRepository; 48 CarConfigInfoRepository carConfigInfoRepository;
64 49
65 @Autowired 50 @Autowired
66 - GpsOfflineMonitorThread gpsOfflineMonitorThread; 51 + GpsOfflineMonitorThread gpsOfflineMonitorThread;*/
67 52
68 - final static Long HOUR_TIME = 1000 * 60 * 60L; 53 + /*final static Long HOUR_TIME = 1000 * 60 * 60L;
69 54
70 - final static int HOUR_SECOND = 60 * 60; 55 + final static int HOUR_SECOND = 60 * 60;*/
71 56
72 @Override 57 @Override
73 public void run(String... arg0){ 58 public void run(String... arg0){
@@ -78,61 +63,61 @@ public class StartCommand implements CommandLineRunner{ @@ -78,61 +63,61 @@ public class StartCommand implements CommandLineRunner{
78 63
79 /** 64 /**
80 * 车辆,设备,公司等常用的映射数据,每两小时刷新一次 65 * 车辆,设备,公司等常用的映射数据,每两小时刷新一次
81 - */ 66 + *//*
82 commonRefreshThread.start(); 67 commonRefreshThread.start();
83 scheduler.scheduleWithFixedDelay(commonRefreshThread, HOUR_SECOND * 2 , HOUR_SECOND * 2, TimeUnit.SECONDS); 68 scheduler.scheduleWithFixedDelay(commonRefreshThread, HOUR_SECOND * 2 , HOUR_SECOND * 2, TimeUnit.SECONDS);
84 //等映射数据加载完......睡一会吧 69 //等映射数据加载完......睡一会吧
85 Thread.sleep(4000); 70 Thread.sleep(4000);
86 71
87 - /** 72 + *//**
88 * GPS实时数据更新 线程 73 * GPS实时数据更新 线程
89 * 每8秒和网关HTTP接口同步一次 74 * 每8秒和网关HTTP接口同步一次
90 - */ 75 + *//*
91 scheduler.scheduleWithFixedDelay(gpsRefreshThread, 0, 8, TimeUnit.SECONDS); 76 scheduler.scheduleWithFixedDelay(gpsRefreshThread, 0, 8, TimeUnit.SECONDS);
92 77
93 - /** 78 + *//**
94 * GPS 监控设备掉线行为 79 * GPS 监控设备掉线行为
95 * 每分钟检测一次 80 * 每分钟检测一次
96 - */ 81 + *//*
97 scheduler.scheduleWithFixedDelay(gpsOfflineMonitorThread, 60, 60, TimeUnit.SECONDS); 82 scheduler.scheduleWithFixedDelay(gpsOfflineMonitorThread, 60, 60, TimeUnit.SECONDS);
98 83
99 84
100 - /** 85 + *//**
101 * 每天 凌晨 2 点 抓取当天实际排班 86 * 每天 凌晨 2 点 抓取当天实际排班
102 - */ 87 + *//*
103 //启动时先run一次 88 //启动时先run一次
104 getSchedulePlanThread.start(); 89 getSchedulePlanThread.start();
105 scheduler.scheduleAtFixedRate(getSchedulePlanThread 90 scheduler.scheduleAtFixedRate(getSchedulePlanThread
106 , ((DateUtils.getTimesnight2() + HOUR_TIME * 2) - System.currentTimeMillis()) / 1000 91 , ((DateUtils.getTimesnight2() + HOUR_TIME * 2) - System.currentTimeMillis()) / 1000
107 , 60 * 60 * 24, TimeUnit.SECONDS); 92 , 60 * 60 * 24, TimeUnit.SECONDS);
108 93
109 - /** 94 + *//**
110 * 调度指令两分钟入库一次 95 * 调度指令两分钟入库一次
111 * 指令会缓存在内存,直到收到所有响应再入库 96 * 指令会缓存在内存,直到收到所有响应再入库
112 - */ 97 + *//*
113 //从数据库恢复初始数据 98 //从数据库恢复初始数据
114 directiveBuffer.recovery(); 99 directiveBuffer.recovery();
115 scheduler.scheduleWithFixedDelay(directivePersistenceThread, 20, 60 * 2, TimeUnit.SECONDS); 100 scheduler.scheduleWithFixedDelay(directivePersistenceThread, 20, 60 * 2, TimeUnit.SECONDS);
116 101
117 - /** 102 + *//**
118 * 每分钟将有变更的班次入库(不包括子任务) 103 * 每分钟将有变更的班次入库(不包括子任务)
119 * 单纯为了提高 线调操作 的响应速度 104 * 单纯为了提高 线调操作 的响应速度
120 - */ 105 + *//*
121 scheduler.scheduleWithFixedDelay(SchedulePersistenceThread, 60 * 1, 60 * 1, TimeUnit.SECONDS); 106 scheduler.scheduleWithFixedDelay(SchedulePersistenceThread, 60 * 1, 60 * 1, TimeUnit.SECONDS);
122 107
123 - /** 108 + *//**
124 * 每15秒从数据库抓取到离站信息和班次匹配 109 * 每15秒从数据库抓取到离站信息和班次匹配
125 * (网关生成的到离站数据也是延迟批量入库,所以缩短该线程执行周期并不会提高 “实际到离站” 的实时性) 110 * (网关生成的到离站数据也是延迟批量入库,所以缩短该线程执行周期并不会提高 “实际到离站” 的实时性)
126 - */ 111 + *//*
127 scheduler.scheduleWithFixedDelay(gpsArrivalStationThread, 35, 15, TimeUnit.SECONDS); 112 scheduler.scheduleWithFixedDelay(gpsArrivalStationThread, 35, 15, TimeUnit.SECONDS);
128 113
129 - /** 114 + *//**
130 * 首个调度指令下发(2分钟运行一次) 115 * 首个调度指令下发(2分钟运行一次)
131 * 每辆车的第一个调度指令由该线程下发 116 * 每辆车的第一个调度指令由该线程下发
132 * 后续班次由 “实际终点到达” 事件触发指令下发 117 * 后续班次由 “实际终点到达” 事件触发指令下发
133 - */ 118 + *//*
134 scheduler.scheduleWithFixedDelay(firstScheduleIssuedThread, 60 , 60 * 2, TimeUnit.SECONDS); 119 scheduler.scheduleWithFixedDelay(firstScheduleIssuedThread, 60 , 60 * 2, TimeUnit.SECONDS);
135 - 120 + */
136 121
137 /* new Timer().schedule(new TimerTask() { 122 /* new Timer().schedule(new TimerTask() {
138 123
src/main/java/com/bsth/WebAppConfiguration.java
@@ -65,6 +65,6 @@ public class WebAppConfiguration extends WebMvcConfigurerAdapter implements WebS @@ -65,6 +65,6 @@ public class WebAppConfiguration extends WebMvcConfigurerAdapter implements WebS
65 public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) { 65 public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
66 //线调webSocket 66 //线调webSocket
67 registry.addHandler(new RealControlSocketHandler(), "/sockjs/realcontrol").addInterceptors(new WebSocketHandshakeInterceptor()) 67 registry.addHandler(new RealControlSocketHandler(), "/sockjs/realcontrol").addInterceptors(new WebSocketHandshakeInterceptor())
68 - .withSockJS(); 68 + .withSockJS();
69 } 69 }
70 } 70 }
src/main/java/com/bsth/controller/directive/DirectiveController.java
1 -//package com.bsth.controller.directive;  
2 -//  
3 -//import java.util.List;  
4 -//import java.util.Map;  
5 -//  
6 -//import org.springframework.beans.factory.annotation.Autowired;  
7 -//import org.springframework.data.domain.Page;  
8 -//import org.springframework.data.domain.PageRequest;  
9 -//import org.springframework.data.domain.Sort;  
10 -//import org.springframework.data.domain.Sort.Direction;  
11 -//import org.springframework.web.bind.annotation.RequestMapping;  
12 -//import org.springframework.web.bind.annotation.RequestMethod;  
13 -//import org.springframework.web.bind.annotation.RequestParam;  
14 -//import org.springframework.web.bind.annotation.RestController;  
15 -//  
16 -//import com.bsth.entity.directive.D80;  
17 -//import com.bsth.entity.sys.SysUser;  
18 -//import com.bsth.security.util.SecurityUtils;  
19 -//import com.bsth.service.directive.DirectiveService;  
20 -//  
21 -///**  
22 -// *  
23 -// * @ClassName: DirectiveController  
24 -// * @Description: TODO(页面下发调度指令) .0  
25 -// * @author PanZhao  
26 -// * @date 2016年6月8日 上午9:34:51  
27 -// *  
28 -// */  
29 -//@RestController  
30 -//@RequestMapping("/directive")  
31 -//public class DirectiveController {  
32 -//  
33 -// @Autowired  
34 -// DirectiveService directiveService;  
35 -//  
36 -// /**  
37 -// *  
38 -// * @Title: send60  
39 -// * @Description: TODO(60协议短语下发)  
40 -// * @throws  
41 -// */  
42 -// @RequestMapping(value = "/phrase", method = RequestMethod.POST)  
43 -// public int send60Phrase(@RequestParam String nbbm, @RequestParam String text){  
44 -// SysUser user = SecurityUtils.getCurrentUser();  
45 -// return directiveService.send60Phrase(nbbm, text, user.getUserName());  
46 -// }  
47 -//  
48 -// /**  
49 -// *  
50 -// * @Title: send60Dispatch  
51 -// * @Description: TODO(班次信息下发)  
52 -// * @param @param id  
53 -// * @throws  
54 -// */  
55 -// @RequestMapping(value = "/dispatch", method = RequestMethod.POST)  
56 -// public int send60Dispatch(@RequestParam Long id){  
57 -// SysUser user = SecurityUtils.getCurrentUser();  
58 -// return directiveService.send60Dispatch(id, user.getUserName());  
59 -// }  
60 -//  
61 -// /**  
62 -// *  
63 -// * @Title: lineChange  
64 -// * @Description: TODO(切换线路)  
65 -// * @param @param nbbm 车辆内部编码  
66 -// * @param @param lineId 新线路编码  
67 -// * @throws  
68 -// */  
69 -// @RequestMapping(value = "/lineChnage", method = RequestMethod.POST)  
70 -// public int lineChange(@RequestParam String nbbm, @RequestParam Integer lineId){  
71 -// SysUser user = SecurityUtils.getCurrentUser();  
72 -// return directiveService.lineChange(nbbm, lineId, user.getUserName());  
73 -// }  
74 -//  
75 -// /**  
76 -// *  
77 -// * @Title: upDownChange  
78 -// * @Description: TODO(上下行切换)  
79 -// * @param @param nbbm 车辆内部编码  
80 -// * @param @param upDon  
81 -// * @throws  
82 -// */  
83 -// @RequestMapping(value = "/upDownChange", method = RequestMethod.POST)  
84 -// public int upDownChange(@RequestParam String nbbm, @RequestParam Integer upDown){  
85 -// SysUser user = SecurityUtils.getCurrentUser();  
86 -// return directiveService.upDownChange(nbbm, upDown, user.getUserName());  
87 -// }  
88 -//  
89 -// /**  
90 -// *  
91 -// * @Title: findNoCofm80  
92 -// * @Description: TODO(根据线路获取未确认的80驾驶员上报数据)  
93 -// * @throws  
94 -// */  
95 -// @RequestMapping(value = "/findNoCofm80", method = RequestMethod.GET)  
96 -// public Map<String, List<D80>> findNoCofm80(@RequestParam String lineCodes){  
97 -// return directiveService.findNoCofm80(lineCodes);  
98 -// }  
99 -//  
100 -// @RequestMapping(value = "/findAll80", method = RequestMethod.GET)  
101 -// public Page<D80> findAll80(@RequestParam Map<String, Object> map,  
102 -// @RequestParam(defaultValue = "0") int page,  
103 -// @RequestParam(defaultValue = "12") int size){  
104 -//  
105 -// return directiveService.findAll80(map, new PageRequest(page, size, new Sort(Direction.DESC, "timestamp")));  
106 -// }  
107 -//  
108 -// /**  
109 -// *  
110 -// * @Title: reply80  
111 -// * @Description: TODO(回复80)  
112 -// * @param @param reply 0:同意 -1:不同意  
113 -// * @throws  
114 -// */  
115 -// @RequestMapping(value = "/reply80", method = RequestMethod.POST)  
116 -// public Map<String, Object> reply80(@RequestParam int id, @RequestParam int reply){  
117 -// return directiveService.reply80(id, reply);  
118 -// }  
119 -//  
120 -// /**  
121 -// *  
122 -// * @Title: findDirective  
123 -// * @Description: TODO(查询调度指令)  
124 -// * @param @param nbbm 车辆  
125 -// * @param @param dType 类型  
126 -// * @param @param page 页号  
127 -// * @param @param size 每页数量  
128 -// * @throws  
129 -// */  
130 -// @RequestMapping(value = "/list", method = RequestMethod.GET)  
131 -// public Map<String, Object> findDirective(String nbbm,@RequestParam int dType  
132 -// , @RequestParam(defaultValue = "0") int page,  
133 -// @RequestParam(defaultValue = "10") int size){  
134 -//  
135 -// return directiveService.findDirective(nbbm, dType, page, size);  
136 -// }  
137 -//} 1 +package com.bsth.controller.directive;
  2 +
  3 +import java.util.List;
  4 +import java.util.Map;
  5 +
  6 +import org.springframework.beans.factory.annotation.Autowired;
  7 +import org.springframework.data.domain.Page;
  8 +import org.springframework.data.domain.PageRequest;
  9 +import org.springframework.data.domain.Sort;
  10 +import org.springframework.data.domain.Sort.Direction;
  11 +import org.springframework.web.bind.annotation.RequestMapping;
  12 +import org.springframework.web.bind.annotation.RequestMethod;
  13 +import org.springframework.web.bind.annotation.RequestParam;
  14 +import org.springframework.web.bind.annotation.RestController;
  15 +
  16 +import com.bsth.entity.directive.D80;
  17 +import com.bsth.entity.sys.SysUser;
  18 +import com.bsth.security.util.SecurityUtils;
  19 +import com.bsth.service.directive.DirectiveService;
  20 +
  21 +/**
  22 + *
  23 + * @ClassName: DirectiveController
  24 + * @Description: TODO(页面下发调度指令) .0
  25 + * @author PanZhao
  26 + * @date 2016年6月8日 上午9:34:51
  27 + *
  28 + */
  29 +@RestController
  30 +@RequestMapping("/directive")
  31 +public class DirectiveController {
  32 +
  33 + @Autowired
  34 + DirectiveService directiveService;
  35 +
  36 + /**
  37 + *
  38 + * @Title: send60
  39 + * @Description: TODO(60协议短语下发)
  40 + * @throws
  41 + */
  42 + @RequestMapping(value = "/phrase", method = RequestMethod.POST)
  43 + public int send60Phrase(@RequestParam String nbbm, @RequestParam String text){
  44 + SysUser user = SecurityUtils.getCurrentUser();
  45 + return directiveService.send60Phrase(nbbm, text, user.getUserName());
  46 + }
  47 +
  48 + /**
  49 + *
  50 + * @Title: send60Dispatch
  51 + * @Description: TODO(班次信息下发)
  52 + * @param @param id
  53 + * @throws
  54 + */
  55 + @RequestMapping(value = "/dispatch", method = RequestMethod.POST)
  56 + public int send60Dispatch(@RequestParam Long id){
  57 + SysUser user = SecurityUtils.getCurrentUser();
  58 + return directiveService.send60Dispatch(id, user.getUserName());
  59 + }
  60 +
  61 + /**
  62 + *
  63 + * @Title: lineChange
  64 + * @Description: TODO(切换线路)
  65 + * @param @param nbbm 车辆内部编码
  66 + * @param @param lineId 新线路编码
  67 + * @throws
  68 + */
  69 + @RequestMapping(value = "/lineChnage", method = RequestMethod.POST)
  70 + public int lineChange(@RequestParam String nbbm, @RequestParam Integer lineId){
  71 + SysUser user = SecurityUtils.getCurrentUser();
  72 + return directiveService.lineChange(nbbm, lineId, user.getUserName());
  73 + }
  74 +
  75 + /**
  76 + *
  77 + * @Title: upDownChange
  78 + * @Description: TODO(上下行切换)
  79 + * @param @param nbbm 车辆内部编码
  80 + * @param @param upDon
  81 + * @throws
  82 + */
  83 + @RequestMapping(value = "/upDownChange", method = RequestMethod.POST)
  84 + public int upDownChange(@RequestParam String nbbm, @RequestParam Integer upDown){
  85 + SysUser user = SecurityUtils.getCurrentUser();
  86 + return directiveService.upDownChange(nbbm, upDown, user.getUserName());
  87 + }
  88 +
  89 + /**
  90 + *
  91 + * @Title: findNoCofm80
  92 + * @Description: TODO(根据线路获取未确认的80驾驶员上报数据)
  93 + * @throws
  94 + */
  95 + @RequestMapping(value = "/findNoCofm80", method = RequestMethod.GET)
  96 + public Map<String, List<D80>> findNoCofm80(@RequestParam String lineCodes){
  97 + return directiveService.findNoCofm80(lineCodes);
  98 + }
  99 +
  100 + @RequestMapping(value = "/findAll80", method = RequestMethod.GET)
  101 + public Map<String, Object> findAll80(@RequestParam Map<String, Object> map,
  102 + @RequestParam(defaultValue = "0") int page,
  103 + @RequestParam(defaultValue = "12") int size){
  104 +
  105 + return directiveService.findAll80(map, page,size);
  106 + }
  107 +
  108 + /**
  109 + *
  110 + * @Title: reply80
  111 + * @Description: TODO(回复80)
  112 + * @param @param reply 0:同意 -1:不同意
  113 + * @throws
  114 + */
  115 + @RequestMapping(value = "/reply80", method = RequestMethod.POST)
  116 + public Map<String, Object> reply80(@RequestParam int id, @RequestParam int reply){
  117 + return directiveService.reply80(id, reply);
  118 + }
  119 +
  120 + /**
  121 + *
  122 + * @Title: findDirective
  123 + * @Description: TODO(查询调度指令)
  124 + * @param @param nbbm 车辆
  125 + * @param @param dType 类型
  126 + * @param @param page 页号
  127 + * @param @param size 每页数量
  128 + * @throws
  129 + */
  130 + @RequestMapping(value = "/list", method = RequestMethod.GET)
  131 + public Map<String, Object> findDirective(String nbbm,@RequestParam int dType
  132 + , @RequestParam(defaultValue = "0") int page,
  133 + @RequestParam(defaultValue = "10") int size){
  134 +
  135 + return directiveService.findDirective(nbbm, dType, page, size);
  136 + }
  137 +}
src/main/java/com/bsth/vehicle/UpstreamEntrance.java renamed to src/main/java/com/bsth/controller/directive/UpstreamEntrance.java
1 -package com.bsth.vehicle; 1 +package com.bsth.controller.directive;
2 2
3 import org.slf4j.Logger; 3 import org.slf4j.Logger;
4 import org.slf4j.LoggerFactory; 4 import org.slf4j.LoggerFactory;
@@ -10,9 +10,10 @@ import org.springframework.web.bind.annotation.RestController; @@ -10,9 +10,10 @@ import org.springframework.web.bind.annotation.RestController;
10 10
11 import com.alibaba.fastjson.JSON; 11 import com.alibaba.fastjson.JSON;
12 import com.alibaba.fastjson.JSONObject; 12 import com.alibaba.fastjson.JSONObject;
13 -import com.bsth.vehicle.directive.buffer.DirectiveBuffer;  
14 -import com.bsth.vehicle.directive.entity.DirectiveReply;  
15 -import com.bsth.vehicle.directive.entity.Directive80; 13 +import com.bsth.data.directive.DayOfDirectives;
  14 +import com.bsth.data.pilot80.PilotReport;
  15 +import com.bsth.entity.directive.D80;
  16 +import com.bsth.entity.directive.DirectiveReponse;
16 17
17 /** 18 /**
18 * 19 *
@@ -29,7 +30,10 @@ public class UpstreamEntrance { @@ -29,7 +30,10 @@ public class UpstreamEntrance {
29 Logger logger = LoggerFactory.getLogger(this.getClass()); 30 Logger logger = LoggerFactory.getLogger(this.getClass());
30 31
31 @Autowired 32 @Autowired
32 - DirectiveBuffer directiveBuffer; 33 + DayOfDirectives dayOfDirectives;
  34 +
  35 + @Autowired
  36 + PilotReport pilotReport;
33 37
34 @RequestMapping(value = "/upstream", method = RequestMethod.POST) 38 @RequestMapping(value = "/upstream", method = RequestMethod.POST)
35 public String main(@RequestParam String json) { 39 public String main(@RequestParam String json) {
@@ -37,29 +41,29 @@ public class UpstreamEntrance { @@ -37,29 +41,29 @@ public class UpstreamEntrance {
37 try { 41 try {
38 JSONObject jsonParam = JSONObject.parseObject(json); 42 JSONObject jsonParam = JSONObject.parseObject(json);
39 43
40 - // 46和47 调度指令确认 44 + // 60协议回复
41 if (jsonParam.getInteger("operCode") == null && jsonParam.getInteger("status") != null) { 45 if (jsonParam.getInteger("operCode") == null && jsonParam.getInteger("status") != null) {
42 try { 46 try {
43 - DirectiveReply reply = JSON.toJavaObject(jsonParam, DirectiveReply.class);  
44 - directiveBuffer.reply(reply); 47 + DirectiveReponse reply = JSON.toJavaObject(jsonParam, DirectiveReponse.class);
  48 + dayOfDirectives.reply(reply);
45 } catch (NumberFormatException e) { 49 } catch (NumberFormatException e) {
46 logger.error("NumberFormatException ,,,,一般是老数据,msgId太大"); 50 logger.error("NumberFormatException ,,,,一般是老数据,msgId太大");
47 } 51 }
48 } 52 }
49 - // 80协议 53 + // 80协议上报
50 else if (jsonParam.getInteger("operCode") == 0X80) { 54 else if (jsonParam.getInteger("operCode") == 0X80) {
51 try { 55 try {
52 - Directive80 report = JSON.toJavaObject(jsonParam, Directive80.class); 56 + D80 d80 = JSON.toJavaObject(jsonParam, D80.class);
53 // 驾驶员上报 57 // 驾驶员上报
54 - if (report.getData().getOperCode2() == 0x26)  
55 - directiveBuffer.jsyReport(report); 58 + if (d80.getData().getOperCode2() == 0x26)
  59 + pilotReport.report(d80);
56 } catch (Exception e) { 60 } catch (Exception e) {
57 logger.error("", e); 61 logger.error("", e);
58 } 62 }
59 } 63 }
60 // 64协议 线路切换回复 64 // 64协议 线路切换回复
61 else if (jsonParam.getInteger("operCode") == 0X64) { 65 else if (jsonParam.getInteger("operCode") == 0X64) {
62 - directiveBuffer.reply64(jsonParam); 66 + dayOfDirectives.reply64(jsonParam);
63 } else 67 } else
64 logger.warn("未知的上行数据,p: " + json); 68 logger.warn("未知的上行数据,p: " + json);
65 69
src/main/java/com/bsth/controller/gps/GpsController.java 0 → 100644
  1 +package com.bsth.controller.gps;
  2 +
  3 +import java.util.List;
  4 +import java.util.Map;
  5 +
  6 +import org.springframework.beans.factory.annotation.Autowired;
  7 +import org.springframework.web.bind.annotation.PathVariable;
  8 +import org.springframework.web.bind.annotation.RequestMapping;
  9 +import org.springframework.web.bind.annotation.RequestParam;
  10 +import org.springframework.web.bind.annotation.RestController;
  11 +
  12 +import com.bsth.data.BasicData;
  13 +import com.bsth.data.gpsdata.GpsEntity;
  14 +import com.bsth.data.gpsdata.GpsRealData;
  15 +import com.bsth.service.gps.GpsService;
  16 +import com.google.common.base.Splitter;
  17 +
  18 +@RestController
  19 +@RequestMapping("gps")
  20 +public class GpsController {
  21 +
  22 + @Autowired
  23 + GpsRealData gpsRealData;
  24 +
  25 + @Autowired
  26 + GpsService gpsService;
  27 +
  28 + @RequestMapping(value = "/real/line/{lineCode}")
  29 + public List<GpsEntity> findByLineCode(@PathVariable("lineCode") Integer lineCode) {
  30 + return gpsRealData.get(lineCode);
  31 + }
  32 +
  33 + @RequestMapping(value = "/real/line")
  34 + public List<GpsEntity> findByLineCode(@RequestParam String lineCodes) {
  35 + return gpsRealData.get(Splitter.on(",").splitToList(lineCodes));
  36 + }
  37 +
  38 + /**
  39 + *
  40 + * @Title: history @Description: TODO(这个方法给测试页面用) @throws
  41 + */
  42 + @RequestMapping(value = "/history/{device}")
  43 + public List<Map<String, Object>> history(@PathVariable("device") String device, @RequestParam Long startTime,
  44 + @RequestParam Long endTime, @RequestParam int directions) {
  45 +
  46 + return gpsService.history(device, startTime, endTime, directions);
  47 + }
  48 +
  49 + @RequestMapping(value = "/gpsHistory/multiple")
  50 + public List<Map<String, Object>> gpsHistory(@RequestParam String[] nbbmArray, @RequestParam Long st,
  51 + @RequestParam Long et) {
  52 + return gpsService.history(nbbmArray, st, et);
  53 + }
  54 +
  55 + /*@RequestMapping(value = "/arrival/ram")
  56 + public List<ArrivalInfo> ramData(@RequestParam String nbbm) {
  57 + return ArrivalDataBuffer.allMap.get(nbbm);
  58 + }*/
  59 +
  60 + @RequestMapping(value = "/Car2DeviceId")
  61 + public Map<String, String> findCarDeviceIdMap() {
  62 + return BasicData.deviceId2NbbmMap.inverse();
  63 + }
  64 +
  65 + @RequestMapping(value = "/buffAera")
  66 + public Map<String, Object> findBuffAeraByCode(@RequestParam String code,@RequestParam String type){
  67 + return gpsService.findBuffAeraByCode(code, type);
  68 + }
  69 +}
src/main/java/com/bsth/controller/realcontrol/LineConfigController.java 0 → 100644
  1 +package com.bsth.controller.realcontrol;
  2 +
  3 +import java.util.Map;
  4 +
  5 +import org.springframework.beans.factory.annotation.Autowired;
  6 +import org.springframework.web.bind.annotation.PathVariable;
  7 +import org.springframework.web.bind.annotation.RequestMapping;
  8 +import org.springframework.web.bind.annotation.RequestMethod;
  9 +import org.springframework.web.bind.annotation.RequestParam;
  10 +import org.springframework.web.bind.annotation.RestController;
  11 +
  12 +import com.bsth.controller.BaseController;
  13 +import com.bsth.entity.realcontrol.LineConfig;
  14 +import com.bsth.service.realcontrol.LineConfigService;
  15 +
  16 +@RestController
  17 +@RequestMapping("/lineConfig")
  18 +public class LineConfigController extends BaseController<LineConfig, Integer>{
  19 +
  20 + @Autowired
  21 + LineConfigService lineConfigService;
  22 +
  23 + @RequestMapping("/check")
  24 + public Map<String, Object> check(@RequestParam Integer[] codeArray){
  25 + return lineConfigService.check(codeArray);
  26 + }
  27 +
  28 + @RequestMapping("/init/{lineCode}")
  29 + public Integer init(@PathVariable("lineCode") Integer lineCode) throws Exception{
  30 + return lineConfigService.inti(lineCode);
  31 + }
  32 +
  33 + @RequestMapping(value = "/editTime", method = RequestMethod.POST)
  34 + public Map<String, Object> editStartOptTime(@RequestParam String time,@RequestParam String lineCode){
  35 + return lineConfigService.editStartOptTime(time, lineCode);
  36 + }
  37 +}
src/main/java/com/bsth/controller/realcontrol/ScheduleRealInfoController.java
@@ -12,23 +12,25 @@ import org.springframework.web.bind.annotation.RequestParam; @@ -12,23 +12,25 @@ import org.springframework.web.bind.annotation.RequestParam;
12 import org.springframework.web.bind.annotation.RestController; 12 import org.springframework.web.bind.annotation.RestController;
13 13
14 import com.bsth.controller.BaseController; 14 import com.bsth.controller.BaseController;
  15 +import com.bsth.data.BasicData;
  16 +import com.bsth.data.schedule.DayOfSchedule;
15 import com.bsth.entity.realcontrol.ScheduleRealInfo; 17 import com.bsth.entity.realcontrol.ScheduleRealInfo;
16 import com.bsth.security.util.SecurityUtils; 18 import com.bsth.security.util.SecurityUtils;
17 import com.bsth.service.realcontrol.ScheduleRealInfoService; 19 import com.bsth.service.realcontrol.ScheduleRealInfoService;
18 -import com.bsth.service.realcontrol.buffer.GetSchedulePlanThread;  
19 -import com.bsth.service.realcontrol.buffer.ScheduleBuffer;  
20 -import com.bsth.vehicle.common.CommonMapped;  
21 import com.google.common.base.Splitter; 20 import com.google.common.base.Splitter;
22 21
23 @RestController 22 @RestController
24 @RequestMapping("/realSchedule") 23 @RequestMapping("/realSchedule")
25 public class ScheduleRealInfoController extends BaseController<ScheduleRealInfo, Long> { 24 public class ScheduleRealInfoController extends BaseController<ScheduleRealInfo, Long> {
26 25
27 - @Autowired  
28 - GetSchedulePlanThread getSchedulePlanThread; 26 + /*@Autowired
  27 + GetSchedulePlanThread getSchedulePlanThread;*/
29 28
30 @Autowired 29 @Autowired
31 ScheduleRealInfoService scheduleRealInfoService; 30 ScheduleRealInfoService scheduleRealInfoService;
  31 +
  32 + @Autowired
  33 + DayOfSchedule dayOfSchedule;
32 34
33 @RequestMapping(value = "/lines") 35 @RequestMapping(value = "/lines")
34 public Map<String, Collection<ScheduleRealInfo>> findByLines(@RequestParam String lines) { 36 public Map<String, Collection<ScheduleRealInfo>> findByLines(@RequestParam String lines) {
@@ -47,10 +49,10 @@ public class ScheduleRealInfoController extends BaseController&lt;ScheduleRealInfo, @@ -47,10 +49,10 @@ public class ScheduleRealInfoController extends BaseController&lt;ScheduleRealInfo,
47 String userName = SecurityUtils.getCurrentUser().getUserName(); 49 String userName = SecurityUtils.getCurrentUser().getUserName();
48 // 注销之前的绑定 50 // 注销之前的绑定
49 for (String line : list) 51 for (String line : list)
50 - CommonMapped.lineUserMap.get(Integer.parseInt(line)).remove(userName); 52 + BasicData.lineCode2SocketUserMap.get(line).remove(userName);
51 // 重新绑定 53 // 重新绑定
52 for (String line : list) 54 for (String line : list)
53 - CommonMapped.lineUserMap.put(Integer.parseInt(line), userName); 55 + BasicData.lineCode2SocketUserMap.put(line, userName);
54 56
55 return 0; 57 return 0;
56 } 58 }
@@ -84,7 +86,7 @@ public class ScheduleRealInfoController extends BaseController&lt;ScheduleRealInfo, @@ -84,7 +86,7 @@ public class ScheduleRealInfoController extends BaseController&lt;ScheduleRealInfo,
84 */ 86 */
85 @RequestMapping(value = "/carDeviceMapp", method = RequestMethod.GET) 87 @RequestMapping(value = "/carDeviceMapp", method = RequestMethod.GET)
86 public Map<String, String> carDeviceMapp() { 88 public Map<String, String> carDeviceMapp() {
87 - return CommonMapped.vehicDeviceBiMap.inverse(); 89 + return BasicData.deviceId2NbbmMap.inverse();
88 } 90 }
89 91
90 /** 92 /**
@@ -231,7 +233,7 @@ public class ScheduleRealInfoController extends BaseController&lt;ScheduleRealInfo, @@ -231,7 +233,7 @@ public class ScheduleRealInfoController extends BaseController&lt;ScheduleRealInfo,
231 */ 233 */
232 @RequestMapping(value = "/trustStatus/change", method = RequestMethod.POST) 234 @RequestMapping(value = "/trustStatus/change", method = RequestMethod.POST)
233 public int changeTrustStatus(@RequestParam Integer lineCode, @RequestParam Integer status) { 235 public int changeTrustStatus(@RequestParam Integer lineCode, @RequestParam Integer status) {
234 - ScheduleBuffer.trustMap.put(lineCode, status); 236 + //ScheduleBuffer.trustMap.put(lineCode, status);
235 return 200; 237 return 200;
236 } 238 }
237 239
@@ -243,8 +245,8 @@ public class ScheduleRealInfoController extends BaseController&lt;ScheduleRealInfo, @@ -243,8 +245,8 @@ public class ScheduleRealInfoController extends BaseController&lt;ScheduleRealInfo,
243 * @param @param upDown 245 * @param @param upDown
244 */ 246 */
245 @RequestMapping(value = "/findByLineAndUpDown") 247 @RequestMapping(value = "/findByLineAndUpDown")
246 - public List<ScheduleRealInfo> findByLineAndUpDown(@RequestParam Integer line,@RequestParam Integer upDown){  
247 - return ScheduleBuffer.findByLineAndUpDown(line, upDown); 248 + public List<ScheduleRealInfo> findByLineAndUpDown(@RequestParam String line,@RequestParam Integer upDown){
  249 + return dayOfSchedule.findByLineAndUpDown(line, upDown);
248 } 250 }
249 251
250 /** 252 /**
@@ -261,7 +263,7 @@ public class ScheduleRealInfoController extends BaseController&lt;ScheduleRealInfo, @@ -261,7 +263,7 @@ public class ScheduleRealInfoController extends BaseController&lt;ScheduleRealInfo,
261 263
262 @RequestMapping(value = "/test/getSch") 264 @RequestMapping(value = "/test/getSch")
263 public int getSch(){ 265 public int getSch(){
264 - getSchedulePlanThread.start(); 266 + //getSchedulePlanThread.start();
265 return 1; 267 return 1;
266 } 268 }
267 269
@@ -285,7 +287,8 @@ public class ScheduleRealInfoController extends BaseController&lt;ScheduleRealInfo, @@ -285,7 +287,8 @@ public class ScheduleRealInfoController extends BaseController&lt;ScheduleRealInfo,
285 */ 287 */
286 @RequestMapping(value = "/lineCode/{lineCode}") 288 @RequestMapping(value = "/lineCode/{lineCode}")
287 public List<ScheduleRealInfo> findByLineCode(@PathVariable("lineCode") String lineCode){ 289 public List<ScheduleRealInfo> findByLineCode(@PathVariable("lineCode") String lineCode){
288 - return ScheduleBuffer.realSchedulListMap.get(lineCode); 290 + //return ScheduleBuffer.realSchedulListMap.get(lineCode);
  291 + return dayOfSchedule.findByLineCode(lineCode);
289 } 292 }
290 293
291 @RequestMapping(value = "/queryUserInfo") 294 @RequestMapping(value = "/queryUserInfo")
@@ -362,7 +365,12 @@ public class ScheduleRealInfoController extends BaseController&lt;ScheduleRealInfo, @@ -362,7 +365,12 @@ public class ScheduleRealInfoController extends BaseController&lt;ScheduleRealInfo,
362 * @return 365 * @return
363 */ 366 */
364 @RequestMapping(value="/scheduleDaily") 367 @RequestMapping(value="/scheduleDaily")
365 - public List<Object> scheduleDaily(@RequestParam String line,@RequestParam String date){ 368 + public Map<String,Object> scheduleDaily(@RequestParam String line,@RequestParam String date){
366 return scheduleRealInfoService.scheduleDaily(line,date); 369 return scheduleRealInfoService.scheduleDaily(line,date);
367 } 370 }
  371 +
  372 + @RequestMapping(value="/realScheduleList")
  373 + public List<ScheduleRealInfo> realScheduleList(@RequestParam String line,@RequestParam String date){
  374 + return scheduleRealInfoService.realScheduleList(line,date);
  375 + }
368 } 376 }
src/main/java/com/bsth/controller/sys/RoleController.java
@@ -32,4 +32,16 @@ public class RoleController extends BaseController&lt;Role, Integer&gt;{ @@ -32,4 +32,16 @@ public class RoleController extends BaseController&lt;Role, Integer&gt;{
32 public Map<String, Object> settRoleModules(@RequestParam Integer roleId,@RequestParam String mIds){ 32 public Map<String, Object> settRoleModules(@RequestParam Integer roleId,@RequestParam String mIds){
33 return roleService.settRoleModules(roleId, mIds); 33 return roleService.settRoleModules(roleId, mIds);
34 } 34 }
  35 +
  36 + /**
  37 + *
  38 + * @Title: roleInfo
  39 + * @Description: TODO(角色信息)
  40 + * @param @param id 角色ID
  41 + * @throws
  42 + */
  43 + @RequestMapping(value = "/roleInfo")
  44 + public Map<String, Object> roleInfo(@RequestParam Integer id){
  45 + return roleService.roleInfo(id);
  46 + }
35 } 47 }
src/main/java/com/bsth/controller/sys/UserController.java
1 package com.bsth.controller.sys; 1 package com.bsth.controller.sys;
2 2
3 import javax.servlet.http.HttpServletRequest; 3 import javax.servlet.http.HttpServletRequest;
4 -import javax.servlet.http.HttpServletResponse;  
5 import javax.servlet.http.HttpSession; 4 import javax.servlet.http.HttpSession;
6 5
7 import org.springframework.beans.factory.annotation.Autowired; 6 import org.springframework.beans.factory.annotation.Autowired;
8 import org.springframework.security.authentication.BadCredentialsException; 7 import org.springframework.security.authentication.BadCredentialsException;
9 -import org.springframework.security.core.Authentication;  
10 -import org.springframework.security.core.context.SecurityContextHolder;  
11 import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; 8 import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
12 -import org.springframework.security.web.authentication.logout.SecurityContextLogoutHandler;  
13 import org.springframework.security.web.authentication.session.SessionAuthenticationException; 9 import org.springframework.security.web.authentication.session.SessionAuthenticationException;
14 import org.springframework.web.bind.annotation.RequestMapping; 10 import org.springframework.web.bind.annotation.RequestMapping;
15 import org.springframework.web.bind.annotation.RequestParam; 11 import org.springframework.web.bind.annotation.RequestParam;
16 import org.springframework.web.bind.annotation.RestController; 12 import org.springframework.web.bind.annotation.RestController;
17 -import org.springframework.web.servlet.ModelAndView;  
18 13
19 import com.bsth.controller.BaseController; 14 import com.bsth.controller.BaseController;
20 import com.bsth.entity.sys.SysUser; 15 import com.bsth.entity.sys.SysUser;
@@ -51,23 +46,6 @@ public class UserController extends BaseController&lt;SysUser, Integer&gt;{ @@ -51,23 +46,6 @@ public class UserController extends BaseController&lt;SysUser, Integer&gt;{
51 return msg; 46 return msg;
52 } 47 }
53 48
54 - /**  
55 - *  
56 - * @Title: logout  
57 - * @Description: TODO(注销吧皮卡丘)  
58 - * @param @param request  
59 - * @return ModelAndView 返回类型  
60 - * @throws  
61 - */  
62 - @RequestMapping("/logout")  
63 - public ModelAndView logout(HttpServletRequest request, HttpServletResponse response){  
64 - Authentication auth = SecurityContextHolder.getContext().getAuthentication();  
65 - if (auth != null){  
66 - new SecurityContextLogoutHandler().logout(request, response, auth);  
67 - }  
68 - return new ModelAndView("/");  
69 - }  
70 -  
71 @RequestMapping("/currentUser") 49 @RequestMapping("/currentUser")
72 public SysUser currentUser(){ 50 public SysUser currentUser(){
73 return SecurityUtils.getCurrentUser(); 51 return SecurityUtils.getCurrentUser();
src/main/java/com/bsth/data/BasicData.java
1 -  
2 package com.bsth.data; 1 package com.bsth.data;
3 2
  3 +import java.util.ArrayList;
4 import java.util.HashMap; 4 import java.util.HashMap;
5 import java.util.Iterator; 5 import java.util.Iterator;
  6 +import java.util.List;
6 import java.util.Map; 7 import java.util.Map;
  8 +import java.util.concurrent.TimeUnit;
7 9
8 import org.slf4j.Logger; 10 import org.slf4j.Logger;
9 import org.slf4j.LoggerFactory; 11 import org.slf4j.LoggerFactory;
10 import org.springframework.beans.factory.annotation.Autowired; 12 import org.springframework.beans.factory.annotation.Autowired;
  13 +import org.springframework.boot.CommandLineRunner;
11 import org.springframework.stereotype.Component; 14 import org.springframework.stereotype.Component;
12 15
  16 +import com.bsth.Application;
13 import com.bsth.entity.CarPark; 17 import com.bsth.entity.CarPark;
14 import com.bsth.entity.Cars; 18 import com.bsth.entity.Cars;
15 import com.bsth.entity.Line; 19 import com.bsth.entity.Line;
16 import com.bsth.entity.Station; 20 import com.bsth.entity.Station;
  21 +import com.bsth.entity.StationRoute;
17 import com.bsth.entity.schedule.CarConfigInfo; 22 import com.bsth.entity.schedule.CarConfigInfo;
18 import com.bsth.repository.CarParkRepository; 23 import com.bsth.repository.CarParkRepository;
19 import com.bsth.repository.CarsRepository; 24 import com.bsth.repository.CarsRepository;
20 import com.bsth.repository.LineRepository; 25 import com.bsth.repository.LineRepository;
21 import com.bsth.repository.StationRepository; 26 import com.bsth.repository.StationRepository;
  27 +import com.bsth.repository.StationRouteRepository;
22 import com.bsth.repository.schedule.CarConfigInfoRepository; 28 import com.bsth.repository.schedule.CarConfigInfoRepository;
23 import com.google.common.collect.BiMap; 29 import com.google.common.collect.BiMap;
24 import com.google.common.collect.HashBiMap; 30 import com.google.common.collect.HashBiMap;
@@ -33,7 +39,7 @@ import com.google.common.collect.TreeMultimap; @@ -33,7 +39,7 @@ import com.google.common.collect.TreeMultimap;
33 * 39 *
34 */ 40 */
35 @Component 41 @Component
36 -public class BasicData { 42 +public class BasicData implements CommandLineRunner{
37 43
38 //设备号和车辆自编号 (K: 设备编码 ,V:车辆自编号) 44 //设备号和车辆自编号 (K: 设备编码 ,V:车辆自编号)
39 public static BiMap<String, String> deviceId2NbbmMap; 45 public static BiMap<String, String> deviceId2NbbmMap;
@@ -48,40 +54,34 @@ public class BasicData { @@ -48,40 +54,34 @@ public class BasicData {
48 public static Map<String, Line> nbbm2LineMap; 54 public static Map<String, Line> nbbm2LineMap;
49 55
50 //线路和用户对照 用于webSocket定向推送消息(用户进入线调时写入数据) 56 //线路和用户对照 用于webSocket定向推送消息(用户进入线调时写入数据)
51 - public static TreeMultimap<Integer, String> lineCode2SocketUserMap = TreeMultimap.create(); 57 + public static TreeMultimap<String, String> lineCode2SocketUserMap = TreeMultimap.create();
52 58
53 //线路ID和code 对照 59 //线路ID和code 对照
54 public static BiMap<Integer, Integer> lineId2CodeMap; 60 public static BiMap<Integer, Integer> lineId2CodeMap;
55 61
56 - @Autowired  
57 - BasicDataLoader basicDataLoader; 62 + //线路编码和名称对照
  63 + public static Map<String, String> lineCode2NameMap;
58 64
59 - Logger logger = LoggerFactory.getLogger(this.getClass()); 65 + //线路编码_站点编码 == 0|1 上下行
  66 + public static Map<String, Integer> lineStationUpDownMap;
60 67
61 - /**  
62 - *  
63 - * @Title: loadAllData  
64 - * @Description: TODO(加载所有数据)  
65 - * @throws  
66 - */  
67 - public int loadAllData(){  
68 - try{  
69 - basicDataLoader.loadDeviceInfo();  
70 - basicDataLoader.loadStationInfo();  
71 - basicDataLoader.loadLineInfo();  
72 - basicDataLoader.loadNbbm2LineInfo();  
73 - }catch(Exception e){  
74 - logger.error("加载基础数据时出现异常," , e);  
75 - }  
76 - return 0; 68 + //停车场
  69 + public static List<String> parkCodeList;
  70 +
  71 + static Logger logger = LoggerFactory.getLogger(BasicData.class);
  72 +
  73 + @Autowired
  74 + BasicDataLoader dataLoader;
  75 +
  76 + @Override
  77 + public void run(String... arg0) throws Exception {
  78 + Application.mainServices.scheduleWithFixedDelay(dataLoader, 0, 2, TimeUnit.HOURS);
77 } 79 }
78 80
  81 +
79 @Component 82 @Component
80 - public static class BasicDataLoader{ 83 + public static class BasicDataLoader extends Thread{
81 84
82 - public BasicDataLoader() {  
83 - }  
84 -  
85 @Autowired 85 @Autowired
86 CarsRepository carsRepository; 86 CarsRepository carsRepository;
87 87
@@ -97,11 +97,50 @@ public class BasicData { @@ -97,11 +97,50 @@ public class BasicData {
97 @Autowired 97 @Autowired
98 LineRepository lineRepository; 98 LineRepository lineRepository;
99 99
  100 + @Autowired
  101 + StationRouteRepository stationRouteRepository;
  102 +
  103 +
  104 + @Override
  105 + public void run() {
  106 + loadAllData();
  107 + }
  108 +
  109 + /**
  110 + * @Title: loadAllData
  111 + * @Description: TODO(加载所有数据)
  112 + */
  113 + public int loadAllData(){
  114 + try{
  115 + loadDeviceInfo();
  116 + loadStationInfo();
  117 + loadLineInfo();
  118 + loadNbbm2LineInfo();
  119 +
  120 + loadStationRouteInfo();
  121 + logger.info("加载基础数据成功!," );
  122 + }catch(Exception e){
  123 + logger.error("加载基础数据时出现异常," , e);
  124 + }
  125 + return 0;
  126 + }
  127 +
  128 +
  129 + private void loadStationRouteInfo() {
  130 + Iterator<StationRoute> iterator = stationRouteRepository.findAll().iterator();
  131 + Map<String, Integer> map = new HashMap<>();
  132 + StationRoute route;
  133 +
  134 + while(iterator.hasNext()){
  135 + route = iterator.next();
  136 + map.put(route.getLineCode() + "_" + route.getStationCode(), route.getDirections());
  137 + }
  138 + lineStationUpDownMap = map;
  139 + }
  140 +
100 /** 141 /**
101 - *  
102 * @Title: loadDeviceInfo 142 * @Title: loadDeviceInfo
103 * @Description: TODO(加载设备相关信息) 143 * @Description: TODO(加载设备相关信息)
104 - * @throws  
105 */ 144 */
106 public void loadDeviceInfo(){ 145 public void loadDeviceInfo(){
107 BiMap<String, String> deviceId2Nbbm = HashBiMap.create(); 146 BiMap<String, String> deviceId2Nbbm = HashBiMap.create();
@@ -120,10 +159,8 @@ public class BasicData { @@ -120,10 +159,8 @@ public class BasicData {
120 } 159 }
121 160
122 /** 161 /**
123 - *  
124 * @Title: loadStationInfo 162 * @Title: loadStationInfo
125 * @Description: TODO(加载站点信息) 163 * @Description: TODO(加载站点信息)
126 - * @throws  
127 */ 164 */
128 public void loadStationInfo(){ 165 public void loadStationInfo(){
129 Map<String, String> stationCode2Name = new HashMap<>(); 166 Map<String, String> stationCode2Name = new HashMap<>();
@@ -136,20 +173,23 @@ public class BasicData { @@ -136,20 +173,23 @@ public class BasicData {
136 } 173 }
137 //停车场 174 //停车场
138 Iterator<CarPark> iterator2 = carParkRepository.findAll().iterator(); 175 Iterator<CarPark> iterator2 = carParkRepository.findAll().iterator();
  176 +
  177 + List<String> parkCodes = new ArrayList<>();
  178 +
139 CarPark carPark; 179 CarPark carPark;
140 while(iterator2.hasNext()){ 180 while(iterator2.hasNext()){
141 carPark = iterator2.next(); 181 carPark = iterator2.next();
142 stationCode2Name.put(carPark.getParkCode(), carPark.getParkName()); 182 stationCode2Name.put(carPark.getParkCode(), carPark.getParkName());
  183 +
  184 + parkCodes.add(carPark.getParkCode());
143 } 185 }
144 - 186 + parkCodeList = parkCodes;
145 stationCode2NameMap = stationCode2Name; 187 stationCode2NameMap = stationCode2Name;
146 } 188 }
147 189
148 /** 190 /**
149 - *  
150 * @Title: loadNbbm2LineInfo 191 * @Title: loadNbbm2LineInfo
151 * @Description: TODO(车辆和线路对照) 192 * @Description: TODO(车辆和线路对照)
152 - * @throws  
153 */ 193 */
154 public void loadNbbm2LineInfo(){ 194 public void loadNbbm2LineInfo(){
155 Iterator<CarConfigInfo> allIterator = carConfigInfoRepository.findAll().iterator(); 195 Iterator<CarConfigInfo> allIterator = carConfigInfoRepository.findAll().iterator();
@@ -164,23 +204,24 @@ public class BasicData { @@ -164,23 +204,24 @@ public class BasicData {
164 } 204 }
165 205
166 /** 206 /**
167 - *  
168 * @Title: loadLineInfo 207 * @Title: loadLineInfo
169 * @Description: TODO(加载线路相关信息) 208 * @Description: TODO(加载线路相关信息)
170 - * @throws  
171 */ 209 */
172 public void loadLineInfo(){ 210 public void loadLineInfo(){
173 Iterator<Line> iterator = lineRepository.findAll().iterator(); 211 Iterator<Line> iterator = lineRepository.findAll().iterator();
174 212
175 Line line; 213 Line line;
176 BiMap<Integer, Integer> biMap = HashBiMap.create(); 214 BiMap<Integer, Integer> biMap = HashBiMap.create();
  215 + Map<String, String> code2name = new HashMap<>();
  216 +
177 while(iterator.hasNext()){ 217 while(iterator.hasNext()){
178 line = iterator.next(); 218 line = iterator.next();
179 biMap.put(line.getId(), Integer.parseInt(line.getLineCode())); 219 biMap.put(line.getId(), Integer.parseInt(line.getLineCode()));
  220 + code2name.put(line.getLineCode(), line.getName());
180 } 221 }
181 222
182 lineId2CodeMap = biMap; 223 lineId2CodeMap = biMap;
  224 + lineCode2NameMap = code2name;
183 } 225 }
184 } 226 }
185 } 227 }
186 -  
src/main/java/com/bsth/data/DirectiveData.java deleted 100644 → 0
1 -package com.bsth.data;  
2 -  
3 -/**  
4 - *  
5 - * @ClassName: DirectiveData  
6 - * @Description: TODO(指令数据)  
7 - * @author PanZhao  
8 - * @date 2016年8月10日 下午3:50:05  
9 - *  
10 - */  
11 -public class DirectiveData {  
12 -  
13 -  
14 -}  
src/main/java/com/bsth/data/GpsRealData.java deleted 100644 → 0
1 -package com.bsth.data;  
2 -  
3 -/**  
4 - *  
5 - * @ClassName: GpsRealData  
6 - * @Description: TODO(GPS实时数据)  
7 - * @author PanZhao  
8 - * @date 2016年8月10日 下午3:41:47  
9 - *  
10 - */  
11 -public class GpsRealData {  
12 -  
13 -}  
src/main/java/com/bsth/data/LineConfigData.java 0 → 100644
  1 +package com.bsth.data;
  2 +
  3 +import java.util.Collection;
  4 +import java.util.HashMap;
  5 +import java.util.Iterator;
  6 +import java.util.Map;
  7 +import java.util.Set;
  8 +
  9 +import org.slf4j.Logger;
  10 +import org.slf4j.LoggerFactory;
  11 +import org.springframework.beans.factory.annotation.Autowired;
  12 +import org.springframework.boot.CommandLineRunner;
  13 +import org.springframework.stereotype.Component;
  14 +
  15 +import com.bsth.entity.Line;
  16 +import com.bsth.entity.realcontrol.D80ReplyTemp;
  17 +import com.bsth.entity.realcontrol.LineConfig;
  18 +import com.bsth.service.LineService;
  19 +import com.bsth.service.realcontrol.LineConfigService;
  20 +
  21 +/**
  22 + *
  23 + * @ClassName: LineConfigData
  24 + * @Description: TODO(线路配置数据管理)
  25 + * @author PanZhao
  26 + * @date 2016年8月15日 下午2:50:19
  27 + *
  28 + */
  29 +@Component
  30 +public class LineConfigData implements CommandLineRunner {
  31 +
  32 + Logger logger = LoggerFactory.getLogger(this.getClass());
  33 +
  34 + // 线路编码和配置
  35 + private Map<String, LineConfig> lineConfMap;
  36 +
  37 + @Autowired
  38 + LineConfigService lineConfigService;
  39 +
  40 + @Autowired
  41 + LineService lineService;
  42 +
  43 + @Override
  44 + public void run(String... arg0) throws Exception {
  45 + lineConfMap = new HashMap<>();
  46 +
  47 + Iterator<LineConfig> itr = lineConfigService.findAll().iterator();
  48 + while (itr.hasNext())
  49 + setBuffer(itr.next());
  50 + }
  51 +
  52 + public LineConfig get(String lineCode){
  53 + return lineConfMap.get(lineCode);
  54 + }
  55 +
  56 + public Collection<LineConfig> getAll(){
  57 + return lineConfMap.values();
  58 + }
  59 +
  60 + public void set(LineConfig conf){
  61 + lineConfigService.save(conf);
  62 + setBuffer(conf);
  63 + }
  64 +
  65 + public void setBuffer(LineConfig conf){
  66 + lineConfMap.put(conf.getLine().getLineCode(), conf);
  67 + }
  68 +
  69 + /**
  70 + *
  71 + * @Title: init
  72 + * @Description: TODO(初始化配置信息)
  73 + */
  74 + public void init(Integer lineCode) throws Exception{
  75 + LineConfig conf = new LineConfig();
  76 + //线路
  77 + Line line = lineService.findByLineCode(lineCode);
  78 + if(null == line)
  79 + throw new NullPointerException("异常的lineCode");
  80 +
  81 + conf.setLine(line);
  82 + //开始运营时间
  83 + conf.setStartOpt("02:00");
  84 + //托管状态
  85 + conf.setTrust(true);
  86 + //出场时间类型
  87 + conf.setOutConfig(1);
  88 + //进场时间类型
  89 + conf.setInConfig(1);
  90 + //短语模板
  91 + conf.setPhraseTemps("");
  92 + //调度指令模板
  93 + conf.setSchDirectiveTemp("");
  94 +
  95 + //80指令回复
  96 + D80ReplyTemp t50 = new D80ReplyTemp(conf, (short)0x50, "同意,回电详谈", "不同意,请回电")
  97 + ,t60 = new D80ReplyTemp(conf, (short)0x60, "同意,回电详谈", "不同意,请回电")
  98 + ,tA2 = new D80ReplyTemp(conf, (short)0xA2, "同意,回电详谈", "不同意,请回电")
  99 + ,t70 = new D80ReplyTemp(conf, (short)0x70, "同意,回电详谈", "不同意,请回电")
  100 + ,t11 = new D80ReplyTemp(conf, (short)0x11, "同意,回电详谈", "不同意,请回电");
  101 +
  102 + Set<D80ReplyTemp> temps = conf.getD80Temps();
  103 + temps.add(t50);
  104 + temps.add(t60);
  105 + temps.add(tA2);
  106 + temps.add(t70);
  107 + temps.add(t11);
  108 +
  109 + set(conf);
  110 + }
  111 +}
src/main/java/com/bsth/data/ScheduleData.java deleted 100644 → 0
1 -package com.bsth.data;  
2 -  
3 -/**  
4 - *  
5 - * @ClassName: ScheduleData  
6 - * @Description: TODO(排班数据)  
7 - * @author PanZhao  
8 - * @date 2016年8月10日 下午3:42:31  
9 - *  
10 - */  
11 -public class ScheduleData {  
12 -  
13 -}  
src/main/java/com/bsth/data/arrival/AnalyseArrivalData.java 0 → 100644
  1 +package com.bsth.data.arrival;
  2 +
  3 +import java.util.ArrayList;
  4 +import java.util.Collections;
  5 +import java.util.List;
  6 +import java.util.Set;
  7 +
  8 +import org.slf4j.Logger;
  9 +import org.slf4j.LoggerFactory;
  10 +import org.springframework.stereotype.Component;
  11 +
  12 +import com.bsth.data.BasicData;
  13 +
  14 +/**
  15 + *
  16 + * @ClassName: AnalyseArrivalData
  17 + * @Description: TODO(分析一下进出站场数据)
  18 + * @author PanZhao
  19 + * @date 2016年8月24日 上午11:09:37
  20 + *
  21 + */
  22 +@Component
  23 +public class AnalyseArrivalData {
  24 +
  25 + Logger logger = LoggerFactory.getLogger(AnalyseArrivalData.class);
  26 +
  27 + public void analyse(Set<String> cars){
  28 + try{
  29 + List<ArrivalEntity> list, clearList;
  30 + for(String car : cars){
  31 + list = ArrivalData_GPS.findByNbbm(car);
  32 + analyse(list);
  33 +
  34 + //清理掉无效的点
  35 + clearList = new ArrayList<>();
  36 + for(ArrivalEntity arr : list){
  37 + if(!arr.isEnable())
  38 + clearList.add(arr);
  39 + }
  40 + list.removeAll(clearList);
  41 + }
  42 + }catch(Exception e){
  43 + logger.error("", e);
  44 + }
  45 + }
  46 +
  47 + private final static int SHIFT_TIME = 1000 * 60 * 5,
  48 + SCH_TIME = 1000 * 60 * 10;
  49 +
  50 + static ArrivalComparator comp = new ArrivalComparator();
  51 +
  52 + public void analyse(List<ArrivalEntity> list){
  53 + if(list.size() <= 1)
  54 + return;
  55 +
  56 + //排序
  57 + Collections.sort(list, comp);
  58 + ArrivalEntity prve = list.get(0)
  59 + ,curr;
  60 + for(int i = 1; i < list.size(); i ++){
  61 + curr = list.get(i);
  62 + //如果第一个点无效
  63 + if(!effective(prve)){
  64 + prve.setEnable(false);
  65 + prve = curr;
  66 + continue;
  67 + }
  68 + //如果第二个点无效
  69 + else if(!effective(curr)){
  70 + curr.setEnable(false);
  71 + continue;
  72 + }
  73 + else if(curr.getTs() - prve.getTs() < SCH_TIME){
  74 + if(prve.getUpDown() == curr.getUpDown()){
  75 + //信号漂移,出站无效
  76 + if(prve.getStopNo().equals(prve.getStopNo())
  77 + && prve.getInOut() == 1 && curr.getInOut() == 0
  78 + && curr.getTs() - prve.getTs() < SHIFT_TIME){
  79 + prve.setEnable(false);
  80 + }
  81 + }
  82 + else{
  83 + //上下行的同名站,新走向的第一个出站信号开始有效
  84 + if(prve.getStopName().equals(curr.getStopName())){
  85 + if(curr.getInOut() == 0)
  86 + curr.setEnable(false);
  87 + else
  88 + prve = curr;
  89 + }
  90 + }
  91 + }
  92 + else
  93 + prve = curr;
  94 + }
  95 + }
  96 +
  97 + private boolean effective(ArrivalEntity arr){
  98 + //停车场
  99 + if(BasicData.parkCodeList.contains(arr.getStopNo())){
  100 + arr.setTcc(true);
  101 + return true;
  102 + }
  103 +
  104 + Integer upDown = BasicData.lineStationUpDownMap.get(arr.getLineCode() + "_" + arr.getStopNo());
  105 +
  106 + return arr.getUpDown() == upDown || BasicData.parkCodeList.contains(arr.getStopNo());
  107 + }
  108 +}
src/main/java/com/bsth/data/arrival/ArrivalComparator.java 0 → 100644
  1 +package com.bsth.data.arrival;
  2 +
  3 +import java.util.Comparator;
  4 +
  5 +public class ArrivalComparator implements Comparator<ArrivalEntity>{
  6 +
  7 + @Override
  8 + public int compare(ArrivalEntity a1, ArrivalEntity a2) {
  9 + return (int) (a1.getTs() - a2.getTs());
  10 + }
  11 +}
src/main/java/com/bsth/data/arrival/ArrivalData_GPS.java 0 → 100644
  1 +package com.bsth.data.arrival;
  2 +
  3 +import java.util.ArrayList;
  4 +import java.util.Collection;
  5 +import java.util.HashMap;
  6 +import java.util.List;
  7 +import java.util.Map;
  8 +import java.util.Set;
  9 +import java.util.TreeSet;
  10 +import java.util.concurrent.TimeUnit;
  11 +
  12 +import org.slf4j.Logger;
  13 +import org.slf4j.LoggerFactory;
  14 +import org.springframework.beans.factory.annotation.Autowired;
  15 +import org.springframework.boot.CommandLineRunner;
  16 +import org.springframework.stereotype.Component;
  17 +
  18 +import com.bsth.Application;
  19 +import com.bsth.data.match.Arrival2Schedule;
  20 +import com.bsth.data.schedule.DayOfSchedule;
  21 +import com.google.common.collect.ArrayListMultimap;
  22 +import com.google.common.collect.ListMultimap;
  23 +
  24 +/**
  25 + *
  26 + * @ClassName: ArrivalData_GPS
  27 + * @Description: TODO(GPS到离站数据)
  28 + * @author PanZhao
  29 + * @date 2016年8月18日 下午10:05:27
  30 + *
  31 + */
  32 +@Component
  33 +public class ArrivalData_GPS implements CommandLineRunner{
  34 +
  35 + // 起终点站进出数据 K:车辆编码
  36 + private static ListMultimap<String, ArrivalEntity> startAndEndMaps;
  37 +
  38 + private static Map<String, Integer> carIndexMap;
  39 +
  40 + static{
  41 + startAndEndMaps = ArrayListMultimap.create();
  42 +
  43 + carIndexMap = new HashMap<>();
  44 + }
  45 +
  46 + @Autowired
  47 + DataLoaderThread dataLoaderThread;
  48 +
  49 + static Logger logger = LoggerFactory.getLogger(ArrivalData_GPS.class);
  50 +
  51 + @Override
  52 + public void run(String... arg0) throws Exception {
  53 + Application.mainServices.scheduleWithFixedDelay(dataLoaderThread, 30, 15, TimeUnit.SECONDS);
  54 + }
  55 +
  56 + @Component
  57 + public static class DataLoaderThread extends Thread {
  58 +
  59 + @Autowired
  60 + DataLoader dataLoader;
  61 +
  62 + @Autowired
  63 + DayOfSchedule dayOfSchedule;
  64 +
  65 + @Autowired
  66 + AnalyseArrivalData analyseData;
  67 +
  68 + @Override
  69 + public void run() {
  70 + try{
  71 + List<ArrivalEntity> arrSets = dataLoader.load();
  72 + if(null == arrSets || arrSets.size() == 0)
  73 + return;
  74 +
  75 + //有起终点进出的车辆
  76 + Set<String> carSet = new TreeSet<>();
  77 + //按车辆起终点站过滤数据
  78 + String nbbm;
  79 + Set<String> seList;
  80 + for(ArrivalEntity arr : arrSets){
  81 + nbbm = arr.getNbbm();
  82 +
  83 + seList = dayOfSchedule.getSEStationList(nbbm);
  84 + if(seList.contains(arr.getStopNo())){
  85 + startAndEndMaps.put(nbbm, arr);
  86 + carSet.add(nbbm);
  87 + }
  88 + }
  89 + //从专业的角度分析一下数据
  90 + analyseData.analyse(carSet);
  91 + //开始匹配
  92 + Arrival2Schedule.start(carSet);
  93 + }catch(Exception e){
  94 + logger.error("", e);
  95 + }
  96 + }
  97 + }
  98 +
  99 + /**
  100 + *
  101 + * @Title: clearRAMData
  102 + * @Description: TODO(清理内存数据)
  103 + */
  104 + public void clearRAMData(String lineCode){
  105 +
  106 + List<ArrivalEntity> remList = new ArrayList<>();
  107 +
  108 + //车辆映射的进出站数据,遍历删除对应线路数据。
  109 + Collection<ArrivalEntity> seList = startAndEndMaps.values();
  110 + for(ArrivalEntity arr : seList){
  111 + if(arr.getLineCode().equals(lineCode))
  112 + remList.add(arr);
  113 + }
  114 +
  115 + //删除数据
  116 + int count = 0;
  117 + for(ArrivalEntity arr : remList){
  118 + startAndEndMaps.remove(arr.getNbbm(), arr);
  119 + count ++;
  120 + }
  121 +
  122 + logger.info(lineCode + " 清除到离站数据 ," + count);
  123 + }
  124 +
  125 + public static List<ArrivalEntity> findByNbbm(String nbbm){
  126 + return startAndEndMaps.get(nbbm);
  127 + }
  128 +
  129 + public static List<ArrivalEntity> getIncrement(String nbbm){
  130 + Integer mark = null;
  131 + if (!carIndexMap.containsKey(nbbm))
  132 + mark = 0;
  133 + else
  134 + mark = carIndexMap.get(nbbm);
  135 +
  136 + List<ArrivalEntity> all = startAndEndMaps.get(nbbm);
  137 + int size = all.size();
  138 + if(size == 0)
  139 + return new ArrayList<>(0);
  140 +
  141 + List<ArrivalEntity> rs = all.subList(mark, size);
  142 + carIndexMap.put(nbbm, size);
  143 + return rs;
  144 + }
  145 +}
src/main/java/com/bsth/vehicle/gpsdata/entity/ArrivalInfo.java renamed to src/main/java/com/bsth/data/arrival/ArrivalEntity.java
1 -package com.bsth.vehicle.gpsdata.entity; 1 +package com.bsth.data.arrival;
2 2
3 -import com.bsth.vehicle.common.CommonMapped; 3 +import java.text.SimpleDateFormat;
  4 +import java.util.Date;
4 5
5 /** 6 /**
6 * 7 *
7 - * @ClassName: ArrivalInfo  
8 - * @Description: TODO(到离站信息)  
9 - * @author PanZhao  
10 - * @date 2016年6月27日 上午9:53:19 8 + * @ClassName: ArrivalEntity
  9 + * @Description: TODO(进出站实体)
  10 + * @author PanZhao
  11 + * @date 2016年8月19日 上午9:32:20
11 * 12 *
12 */ 13 */
13 -public class ArrivalInfo { 14 +public class ArrivalEntity {
14 15
15 - public ArrivalInfo(String deviceId, Long ts, String lineCode, Integer upDown, String stopNo, Integer inOut,  
16 - Long createDate, Integer weeksYear) {  
17 - this.deviceId = deviceId;  
18 -  
19 - this.ts = ts;  
20 -  
21 - this.lineCode = lineCode;  
22 - this.upDown = upDown;  
23 - this.stopNo = stopNo;  
24 - this.inOut = inOut;  
25 - this.createDate = createDate;  
26 - this.weeksYear = weeksYear;  
27 - this.stopName = CommonMapped.stationCodeMap.get(this.stopNo);  
28 - }  
29 -  
30 - public ArrivalInfo(String deviceId, Long ts, String lineCode, Integer upDown, String stopNo, Integer inOut,  
31 - Long createDate, Integer weeksYear, String stopName) {  
32 - this.deviceId = deviceId;  
33 -  
34 - this.ts = ts;  
35 -  
36 - this.lineCode = lineCode;  
37 - this.upDown = upDown;  
38 - this.stopNo = stopNo;  
39 - this.inOut = inOut;  
40 - this.createDate = createDate;  
41 - this.weeksYear = weeksYear;  
42 - this.stopName = stopName;  
43 - }  
44 -  
45 - /**  
46 - * 设备号  
47 - */ 16 + /** 设备号*/
48 private String deviceId; 17 private String deviceId;
49 18
  19 + private String nbbm;
  20 +
50 /** 站点名称 */ 21 /** 站点名称 */
51 private String stopName; 22 private String stopName;
52 23
53 - /**  
54 - * 时间戳  
55 - */ 24 + /** 时间戳*/
56 private Long ts; 25 private Long ts;
57 26
58 - /**  
59 - * 线路编码  
60 - */ 27 + /** 线路编码*/
61 private String lineCode; 28 private String lineCode;
62 29
63 - /**  
64 - * 上下行  
65 - */ 30 + /** 上下行*/
66 private Integer upDown; 31 private Integer upDown;
67 32
68 - /**  
69 - * 站点编码  
70 - */ 33 + /**站点编码*/
71 private String stopNo; 34 private String stopNo;
72 35
73 - /**  
74 - * 0: 进 1:出  
75 - */ 36 + /** 0: 进 1:出*/
76 private Integer inOut; 37 private Integer inOut;
77 38
78 private Long createDate; 39 private Long createDate;
79 -  
80 - /**  
81 - * 分区字段,当年的第几周  
82 - */ 40 +
  41 + /** 是否有效 */
  42 + private boolean enable;
  43 +
  44 + /**分区字段,当年的第几周*/
83 private Integer weeksYear; 45 private Integer weeksYear;
  46 +
  47 + private boolean tcc;
  48 +
  49 + public ArrivalEntity(){}
  50 +
  51 + public ArrivalEntity(String deviceId, long ts, String lineCode, int upDown, String stopNo, int inOut, long createDate,
  52 + int weeksYear, String stopName) {
  53 +
  54 + this.deviceId = deviceId;
  55 + this.ts = ts;
  56 + this.lineCode = lineCode;
  57 + this.upDown = upDown;
  58 + this.stopNo = stopNo;
  59 + this.stopName = stopName;
  60 + this.inOut = inOut;
  61 + this.createDate = createDate;
  62 + }
  63 +
  64 +/* @Override
  65 + public boolean equals(Object obj) {
  66 + ArrivalEntity a2 = (ArrivalEntity)obj;
  67 +
  68 + return this.toString().equals(a2.toString())
  69 + && Math.abs(this.ts - a2.ts) < EQ_RANGE;
  70 + }
  71 +
  72 + @Override
  73 + public int hashCode() {
  74 + return this.toString().hashCode();
  75 + }*/
  76 +
  77 +static SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
  78 +
  79 + @Override
  80 + public String toString() {
  81 + return sdf.format(new Date(this.ts)) + "_" + this.deviceId + "_" + this.inOut + "_" + this.stopName;
  82 + }
84 83
85 public String getLineCode() { 84 public String getLineCode() {
86 return lineCode; 85 return lineCode;
@@ -157,4 +156,28 @@ public class ArrivalInfo { @@ -157,4 +156,28 @@ public class ArrivalInfo {
157 public String getId(){ 156 public String getId(){
158 return this.deviceId + "_" + this.ts; 157 return this.deviceId + "_" + this.ts;
159 } 158 }
  159 +
  160 + public String getNbbm() {
  161 + return nbbm;
  162 + }
  163 +
  164 + public void setNbbm(String nbbm) {
  165 + this.nbbm = nbbm;
  166 + }
  167 +
  168 + public boolean isEnable() {
  169 + return enable;
  170 + }
  171 +
  172 + public void setEnable(boolean enable) {
  173 + this.enable = enable;
  174 + }
  175 +
  176 + public boolean isTcc() {
  177 + return tcc;
  178 + }
  179 +
  180 + public void setTcc(boolean tcc) {
  181 + this.tcc = tcc;
  182 + }
160 } 183 }
src/main/java/com/bsth/data/arrival/DataLoader.java 0 → 100644
  1 +package com.bsth.data.arrival;
  2 +
  3 +import java.sql.Connection;
  4 +import java.sql.PreparedStatement;
  5 +import java.sql.ResultSet;
  6 +import java.sql.SQLException;
  7 +import java.util.ArrayList;
  8 +import java.util.Calendar;
  9 +import java.util.Collection;
  10 +import java.util.List;
  11 +
  12 +import org.slf4j.Logger;
  13 +import org.slf4j.LoggerFactory;
  14 +import org.springframework.beans.factory.annotation.Autowired;
  15 +import org.springframework.stereotype.Component;
  16 +
  17 +import com.bsth.data.BasicData;
  18 +import com.bsth.data.LineConfigData;
  19 +import com.bsth.entity.realcontrol.LineConfig;
  20 +import com.bsth.util.db.DBUtils_MS;
  21 +
  22 +/**
  23 + *
  24 + * @ClassName: DataLoader
  25 + * @Description: TODO(从数据库加载进出站数据)
  26 + * @author PanZhao
  27 + * @date 2016年8月19日 上午9:59:21
  28 + *
  29 + */
  30 +@Component
  31 +public class DataLoader {
  32 +
  33 + private static Long prveLoadTime;
  34 +
  35 + private final static long DAY_TIME = 1000 * 60 * 60 * 24;
  36 +
  37 + private Logger logger = LoggerFactory.getLogger(this.getClass());
  38 +
  39 + @Autowired
  40 + LineConfigData lineConfigData;
  41 +
  42 + /**
  43 + *
  44 + * @Title: load
  45 + * @Description: TODO(根据上次加载时间,查询之后的增量数据)
  46 + */
  47 + public List<ArrivalEntity> load(){
  48 + List<ArrivalEntity> list = null;
  49 +
  50 + if(null == prveLoadTime)
  51 + list = recovery();
  52 + else{
  53 + Calendar cal = Calendar.getInstance();
  54 + //周数,表分区字段
  55 + int weeks_year = cal.get(Calendar.WEEK_OF_YEAR);
  56 +
  57 + Connection conn = null;
  58 + PreparedStatement ps = null;
  59 + ResultSet rs = null;
  60 +
  61 + String sql = "select * from bsth_c_arrival_info where weeks_year=? AND create_timestamp > ? AND create_timestamp <=? AND ABS(create_timestamp - ts) < 3600000 order by ts";
  62 + try{
  63 + long t = System.currentTimeMillis();
  64 +
  65 + conn = DBUtils_MS.getConnection();
  66 + ps = conn.prepareStatement(sql);
  67 + ps.setInt(1, weeks_year);
  68 + ps.setLong(2, prveLoadTime);
  69 + ps.setLong(3, t);
  70 + rs = ps.executeQuery();
  71 +
  72 + list = resultSet2Set(rs);
  73 +
  74 + prveLoadTime = t;
  75 + }catch(Exception e){
  76 + logger.error("", e);
  77 + }finally {
  78 + DBUtils_MS.close(rs, ps, conn);
  79 + }
  80 + }
  81 + return list;
  82 + }
  83 +
  84 + /**
  85 + *
  86 + * @Title: recovery
  87 + * @Description: TODO(从数据库恢复数据,按照线路的开始运营时间恢复)
  88 + */
  89 + public List<ArrivalEntity> recovery(){
  90 + Collection<LineConfig> confs = lineConfigData.getAll();
  91 + long t = System.currentTimeMillis()
  92 + ,st;
  93 +
  94 + List<ArrivalEntity> all = new ArrayList<>();
  95 + for(LineConfig conf : confs){
  96 + st = conf.getCurrStartTime();
  97 + if(t < st)
  98 + st = st - DAY_TIME;
  99 +
  100 + all.addAll(loadByLineAndTime(conf.getLine().getLineCode(), st, t));
  101 + }
  102 +
  103 + prveLoadTime = t;
  104 + return all;
  105 + }
  106 +
  107 + /**
  108 + *
  109 + * @Title: loadByLineAndStartTime
  110 + * @Description: TODO(根据线路和时间戳加载数据)
  111 + */
  112 + public List<ArrivalEntity> loadByLineAndTime(String lineCode, long st, long et){
  113 + Calendar cal = Calendar.getInstance();
  114 + cal.setTimeInMillis(st);
  115 + int weeks_year = cal.get(Calendar.WEEK_OF_YEAR);
  116 +
  117 + Connection conn = null;
  118 + PreparedStatement ps = null;
  119 + ResultSet rs = null;
  120 +
  121 + List<ArrivalEntity> list = new ArrayList<>();
  122 + String sql = "select * from bsth_c_arrival_info where weeks_year=? and line_id=? AND create_timestamp > ? AND create_timestamp <=? AND ABS(create_timestamp - ts) < 3600000 order by ts";
  123 + try{
  124 + conn = DBUtils_MS.getConnection();
  125 + ps = conn.prepareStatement(sql);
  126 + ps.setInt(1, weeks_year);
  127 + ps.setString(2, lineCode);
  128 + ps.setLong(3, st);
  129 + ps.setLong(4, et);
  130 + rs = ps.executeQuery();
  131 +
  132 + list = resultSet2Set(rs);
  133 + }catch(Exception e){
  134 + logger.error("", e);
  135 + }finally {
  136 + DBUtils_MS.close(rs, ps, conn);
  137 + }
  138 + return list;
  139 + }
  140 +
  141 + public List<ArrivalEntity> resultSet2Set(ResultSet rs) throws SQLException{
  142 + List<ArrivalEntity> list = new ArrayList<>();
  143 +
  144 + ArrivalEntity arr;
  145 + while(rs.next()){
  146 + arr = new ArrivalEntity();
  147 + arr.setDeviceId(rs.getString("device_id"));
  148 + arr.setNbbm(BasicData.deviceId2NbbmMap.get(arr.getDeviceId()));
  149 + if(null == arr.getNbbm()){
  150 + logger.warn("未注册的设备号," + arr.getDeviceId());
  151 + continue;
  152 + }
  153 +
  154 + arr.setTs(rs.getLong("ts"));
  155 + arr.setLineCode(rs.getString("line_id"));
  156 + arr.setUpDown(rs.getInt("up_down"));
  157 + arr.setStopNo(rs.getString("stop_no"));
  158 + arr.setStopName(BasicData.stationCode2NameMap.get(arr.getStopNo()));
  159 + arr.setInOut(rs.getInt("in_out"));
  160 + arr.setCreateDate(rs.getLong("create_timestamp"));
  161 + arr.setWeeksYear(rs.getInt("weeks_year"));
  162 + arr.setEnable(true);
  163 +
  164 + list.add(arr);
  165 + }
  166 + return list;
  167 + }
  168 +
  169 + public static void setPrveLoadTime(long t){
  170 + prveLoadTime = t;
  171 + }
  172 +}
src/main/java/com/bsth/data/directive/DayOfDirectives.java 0 → 100644
  1 +package com.bsth.data.directive;
  2 +
  3 +import java.util.ArrayList;
  4 +import java.util.Collection;
  5 +import java.util.Comparator;
  6 +import java.util.HashMap;
  7 +import java.util.List;
  8 +import java.util.Map;
  9 +
  10 +import org.slf4j.Logger;
  11 +import org.slf4j.LoggerFactory;
  12 +import org.springframework.beans.factory.annotation.Autowired;
  13 +import org.springframework.stereotype.Component;
  14 +
  15 +import com.alibaba.fastjson.JSONObject;
  16 +import com.bsth.data.LineConfigData;
  17 +import com.bsth.entity.directive.D60;
  18 +import com.bsth.entity.directive.D64;
  19 +import com.bsth.entity.directive.Directive;
  20 +import com.bsth.entity.directive.DirectiveReponse;
  21 +import com.bsth.entity.realcontrol.ScheduleRealInfo;
  22 +import com.bsth.service.directive.DirectiveService;
  23 +import com.bsth.websocket.handler.SendUtils;
  24 +
  25 +/**
  26 + *
  27 + * @ClassName: CurrDayDirectives
  28 + * @Description: TODO(当天指令数据)
  29 + * @author PanZhao
  30 + * @date 2016年8月14日 下午5:23:59
  31 + *
  32 + */
  33 +@Component
  34 +public class DayOfDirectives {
  35 +
  36 + // 当日60指令缓存
  37 + private static Map<Integer, D60> d60Map;
  38 +
  39 + // 线路切换指令 64
  40 + public static Map<String, D64> d64Map;
  41 +
  42 + @Autowired
  43 + DirectiveService directiveService;
  44 +
  45 + @Autowired
  46 + SendUtils sendUtils;
  47 +
  48 + @Autowired
  49 + LineConfigData lineConfigData;
  50 +
  51 + static Logger logger = LoggerFactory.getLogger(DayOfDirectives.class);
  52 +
  53 +
  54 + static{
  55 + d60Map = new HashMap<>();
  56 + d64Map = new HashMap<>();
  57 + }
  58 +
  59 + public void put60(D60 d60) {
  60 + d60Map.put(d60.getMsgId(), d60);
  61 + }
  62 +
  63 + public void put64(D64 d64) {
  64 + d64Map.put(d64.getKey(), d64);
  65 + }
  66 +
  67 + /**
  68 + *
  69 + * @Title: reply @Description: TODO(指令 46,47 响应) @throws
  70 + */
  71 + public void reply(DirectiveReponse res) {
  72 + Integer msgId = res.getMsgId();
  73 + if (msgId == null) {
  74 + logger.error("reply error , msgId is null.");
  75 + return;
  76 + }
  77 +
  78 + D60 d60 = d60Map.get(msgId);
  79 +
  80 + if (null == d60) {
  81 + logger.error("找不到msgId: " + msgId + " 对应的指令数据");
  82 + return;
  83 + }
  84 +
  85 + switch (res.getStatus()) {
  86 + case 0:
  87 + d60.setReply46((short) -1);// 失败
  88 + break;
  89 + case 1:
  90 + d60.setReply46((short) 0);// 发送成功
  91 + break;
  92 + case 2:
  93 + d60.setReply47((short) 0);// 驾驶员阅读
  94 + break;
  95 + }
  96 + // 入库
  97 + saveD60(d60);
  98 +
  99 + ScheduleRealInfo sch = d60.getSch();
  100 + if (null == sch)
  101 + return;
  102 +
  103 + if (d60.isDispatch()) {
  104 + // 更新班次状态
  105 + sch.setDirectiveState(res.getStatus() * 100);
  106 + // 通知页面
  107 + sendUtils.sendDirectiveToPage(sch);
  108 + }
  109 + }
  110 +
  111 + /**
  112 + *
  113 + * @Title: reply64 @Description: TODO(64 协议响应) @throws
  114 + */
  115 + public void reply64(JSONObject json) {
  116 + String key = json.getString("deviceId") + "_" + json.getString("timestamp");
  117 +
  118 + D64 d64 = d64Map.get(key);
  119 +
  120 + if (null == d64)
  121 + logger.warn("64响应 -找不到请求源,json: " + json);
  122 + else {
  123 + JSONObject data = json.getJSONObject("data");
  124 +
  125 + if (null == data)
  126 + logger.warn("64响应 data is null ,json: " + json);
  127 + else {
  128 + d64.setRespAck(data.getShort("requestAck"));
  129 + // 响应入库
  130 + directiveService.save64(d64);
  131 + }
  132 + }
  133 + }
  134 +
  135 + private void saveD60(D60 d60) {
  136 + // 等47再入库
  137 + if (d60.getReply47() == null)
  138 + return;
  139 +
  140 + directiveService.save(d60);
  141 + }
  142 +
  143 + public void clear(String device){
  144 + int c60 = 0, c64 = 0;
  145 + //找到该设备的60数据
  146 + Collection<D60> d60s = d60Map.values();
  147 + List<D60> rem60List = new ArrayList<>();
  148 + for(D60 d60 : d60s){
  149 + if(d60.getDeviceId().equals(device))
  150 + rem60List.add(d60);
  151 + }
  152 + //清除60数据
  153 + for(D60 d60 : rem60List){
  154 + if(d60.getReply47() == null)
  155 + directiveService.save(d60);
  156 + if(null != d60Map.remove(d60.getMsgId()))
  157 + c60 ++;
  158 + }
  159 + logger.info("清除60数据 ," + c60);
  160 +
  161 + //找到该设备的64数据
  162 + Collection<D64> d64s = d64Map.values();
  163 + List<D64> rem64List = new ArrayList<>();
  164 + for(D64 d64 : d64s){
  165 + if(d64.getDeviceId().equals(device))
  166 + rem64List.add(d64);
  167 + }
  168 +
  169 + //清除64数据
  170 + for(D64 d64 : rem64List){
  171 + if(d64.getRespAck() == null)
  172 + directiveService.save64(d64);
  173 +
  174 + if(null != d64Map.remove(d64.getKey()))
  175 + c64 ++;
  176 + }
  177 +
  178 + logger.info("清除64数据 ," + c64);
  179 + }
  180 +
  181 + public Collection<D60> all60(){
  182 + return d60Map.values();
  183 + }
  184 +
  185 + public Collection<D64> all64(){
  186 + return d64Map.values();
  187 + }
  188 +
  189 + public Collection<Directive> all(){
  190 + List<Directive> all = new ArrayList<>();
  191 + all.addAll(d60Map.values());
  192 + all.addAll(d64Map.values());
  193 +
  194 + return all;
  195 + }
  196 +
  197 + public static class DComparator implements Comparator<Directive>{
  198 +
  199 + @Override
  200 + public int compare(Directive d1, Directive d2) {
  201 + return (int) (d2.getTimestamp() - d1.getTimestamp());
  202 + }
  203 + }
  204 + }
src/main/java/com/bsth/vehicle/directive/util/DirectiveDataFactory.java renamed to src/main/java/com/bsth/data/directive/DirectiveCreator.java
1 -package com.bsth.vehicle.directive.util; 1 +package com.bsth.data.directive;
2 2
3 import java.text.SimpleDateFormat; 3 import java.text.SimpleDateFormat;
4 import java.util.Date; 4 import java.util.Date;
@@ -9,30 +9,26 @@ import org.slf4j.Logger; @@ -9,30 +9,26 @@ import org.slf4j.Logger;
9 import org.slf4j.LoggerFactory; 9 import org.slf4j.LoggerFactory;
10 10
11 import com.alibaba.fastjson.JSON; 11 import com.alibaba.fastjson.JSON;
12 -import com.bsth.vehicle.common.CommonMapped;  
13 -import com.bsth.vehicle.directive.Consts;  
14 -import com.bsth.vehicle.directive.MsgIdGenerator;  
15 -import com.bsth.vehicle.directive.entity.Directive60;  
16 -import com.bsth.vehicle.directive.entity.Directive64;  
17 -import com.bsth.vehicle.directive.entity.Directive60.DirectiveData;  
18 -import com.bsth.vehicle.directive.entity.Directive64.LineChangeData; 12 +import com.bsth.data.BasicData;
  13 +import com.bsth.entity.directive.D60;
  14 +import com.bsth.entity.directive.D60.D60Data;
  15 +import com.bsth.entity.directive.D64;
  16 +import com.bsth.entity.directive.D64.D64Data;
19 17
20 /** 18 /**
21 * 19 *
22 - * @ClassName: DirectiveDataFactory  
23 - * @Description: TODO(生成调度指令数据) 20 + * @ClassName: DirectiveCreator
  21 + * @Description: TODO(指令数据生成)
24 * @author PanZhao 22 * @author PanZhao
25 - * @date 2016年8月3日 下午3:32:27 23 + * @date 2016年8月14日 下午9:57:07
26 * 24 *
27 */ 25 */
28 -public class DirectiveDataFactory { 26 +public class DirectiveCreator {
29 27
30 - private DirectiveDataFactory() {}  
31 -  
32 // 城市代码 28 // 城市代码
33 static final short cityCode = 22; 29 static final short cityCode = 22;
34 30
35 - static Logger logger = LoggerFactory.getLogger(DirectiveDataFactory.class); 31 + static Logger logger = LoggerFactory.getLogger(DirectiveCreator.class);
36 32
37 /** 33 /**
38 * 34 *
@@ -47,16 +43,16 @@ public class DirectiveDataFactory { @@ -47,16 +43,16 @@ public class DirectiveDataFactory {
47 * @return Directive60 返回类型 43 * @return Directive60 返回类型
48 * @throws 44 * @throws
49 */ 45 */
50 - public static Directive60 createDirective60(String nbbm, String text, Short dispatchInstruct, int upDown, int state) { 46 + public static D60 createD60(String nbbm, String text, Short dispatchInstruct, int upDown, int state) {
51 Long timestamp = System.currentTimeMillis(); 47 Long timestamp = System.currentTimeMillis();
52 48
53 - Short company = Short.parseShort(CommonMapped.vehicCompanyMap.get(nbbm));  
54 - String deviceId = CommonMapped.vehicDeviceBiMap.inverse().get(nbbm); 49 + Short company = Short.parseShort(BasicData.nbbm2CompanyCodeMap.get(nbbm));
  50 + String deviceId = BasicData.deviceId2NbbmMap.inverse().get(nbbm);
55 51
56 int msgId = MsgIdGenerator.getMsgId(); 52 int msgId = MsgIdGenerator.getMsgId();
57 53
58 - Directive60 directive = new Directive60();  
59 - DirectiveData data = new DirectiveData(); 54 + D60 directive = new D60();
  55 + D60Data data = new D60Data();
60 // 一级协议 56 // 一级协议
61 directive.setOperCode((short) 0x60); 57 directive.setOperCode((short) 0x60);
62 // 设备号 58 // 设备号
@@ -86,16 +82,16 @@ public class DirectiveDataFactory { @@ -86,16 +82,16 @@ public class DirectiveDataFactory {
86 82
87 83
88 static SimpleDateFormat sdfMMddHHmm = new SimpleDateFormat("MMddHHmm"); 84 static SimpleDateFormat sdfMMddHHmm = new SimpleDateFormat("MMddHHmm");
89 - public static Directive60 createDirective6002(String nbbm, String text, Short dispatchInstruct, int upDown, int state, Date alarmTime){ 85 + public static D60 createD60_02(String nbbm, String text, int upDown, int state, Date alarmTime){
90 Long timestamp = System.currentTimeMillis(); 86 Long timestamp = System.currentTimeMillis();
91 87
92 - Short company = Short.parseShort(CommonMapped.vehicCompanyMap.get(nbbm));  
93 - String deviceId = CommonMapped.vehicDeviceBiMap.inverse().get(nbbm); 88 + Short company = Short.parseShort(BasicData.nbbm2CompanyCodeMap.get(nbbm));
  89 + String deviceId = BasicData.deviceId2NbbmMap.inverse().get(nbbm);
94 90
95 int msgId = MsgIdGenerator.getMsgId(); 91 int msgId = MsgIdGenerator.getMsgId();
96 92
97 - Directive60 directive = new Directive60();  
98 - DirectiveData data = new DirectiveData(); 93 + D60 directive = new D60();
  94 + D60Data data = new D60Data();
99 // 一级协议 95 // 一级协议
100 directive.setOperCode((short) 0x60); 96 directive.setOperCode((short) 0x60);
101 // 设备号 97 // 设备号
@@ -105,7 +101,7 @@ public class DirectiveDataFactory { @@ -105,7 +101,7 @@ public class DirectiveDataFactory {
105 directive.setMsgId(msgId); 101 directive.setMsgId(msgId);
106 // 构造数据 102 // 构造数据
107 data.setDeviceId(deviceId); 103 data.setDeviceId(deviceId);
108 - data.setDispatchInstruct(dispatchInstruct); 104 + data.setDispatchInstruct((short) 0x02);
109 data.setTimestamp(timestamp); 105 data.setTimestamp(timestamp);
110 data.setCompanyCode(company); 106 data.setCompanyCode(company);
111 data.setMsgId(msgId); 107 data.setMsgId(msgId);
@@ -132,19 +128,19 @@ public class DirectiveDataFactory { @@ -132,19 +128,19 @@ public class DirectiveDataFactory {
132 * @param @param t 时间戳 128 * @param @param t 时间戳
133 * @throws 129 * @throws
134 */ 130 */
135 - public static Directive64 createDirective64(String nbbm, Integer lineCode, long t){  
136 - String deviceId = CommonMapped.vehicDeviceBiMap.inverse().get(nbbm); 131 + public static D64 createD64(String nbbm, Integer lineCode, long t){
  132 + String deviceId = BasicData.deviceId2NbbmMap.inverse().get(nbbm);
137 133
138 - Directive64 change = new Directive64();  
139 - LineChangeData data = new LineChangeData(); 134 + D64 change = new D64();
  135 + D64Data data = new D64Data();
140 data.setCityCode(cityCode); 136 data.setCityCode(cityCode);
141 data.setDeviceId(deviceId); 137 data.setDeviceId(deviceId);
142 //线路编码补满6位数 138 //线路编码补满6位数
143 - if(lineCode > 99999){ 139 + if(lineCode > 999999){
144 logger.error("线路编码不能超过6位,code:" + lineCode); 140 logger.error("线路编码不能超过6位,code:" + lineCode);
145 return null; 141 return null;
146 } 142 }
147 - String lineCodeStr = String.format("%06d", lineCode.toString()); 143 + String lineCodeStr = String.format("%06d", lineCode);
148 data.setLineId(lineCodeStr); 144 data.setLineId(lineCodeStr);
149 145
150 change.setDeviceId(deviceId); 146 change.setDeviceId(deviceId);
@@ -163,24 +159,36 @@ public class DirectiveDataFactory { @@ -163,24 +159,36 @@ public class DirectiveDataFactory {
163 * @param @param lineId 线路ID 159 * @param @param lineId 线路ID
164 * @throws 160 * @throws
165 */ 161 */
166 - public static String createDeviceRefreshData(String deviceId, Integer lineId) { 162 + public static String createDeviceRefreshData(String deviceId, Integer lineCode) {
167 Long t = System.currentTimeMillis(); 163 Long t = System.currentTimeMillis();
168 - Map<String, Object> param = new HashMap<String, Object>(); 164 + Map<String, Object> param = new HashMap<>();
169 param.put("deviceId", deviceId); 165 param.put("deviceId", deviceId);
170 param.put("timestamp", t); 166 param.put("timestamp", t);
171 param.put("operCode", 0Xc0); 167 param.put("operCode", 0Xc0);
172 168
173 - Map<String, Object> data = new HashMap<String, Object>(); 169 + Map<String, Object> data = new HashMap<>();
174 data.put("operCode2", 0xa1); 170 data.put("operCode2", 0xa1);
175 data.put("cityCode", cityCode); 171 data.put("cityCode", cityCode);
176 data.put("deviceId", deviceId); 172 data.put("deviceId", deviceId);
177 data.put("timestamp", t); 173 data.put("timestamp", t);
178 data.put("centerId", 1); 174 data.put("centerId", 1);
179 - data.put("lineId", lineId); 175 +
  176 + //线路编码补满6位数
  177 + if(lineCode > 999999){
  178 + logger.error("线路编码不能超过6位,code:" + lineCode);
  179 + return null;
  180 + }
  181 + String lineCodeStr = String.format("%06d", lineCode);
  182 +
  183 + data.put("lineId", lineCodeStr);
180 data.put("lineVersion", 0); 184 data.put("lineVersion", 0);
181 data.put("carparkDataVersion", 0); 185 data.put("carparkDataVersion", 0);
182 param.put("data", data); 186 param.put("data", data);
183 187
184 return JSON.toJSONString(param); 188 return JSON.toJSONString(param);
185 } 189 }
  190 +
  191 + public static void main(String[] args) {
  192 + System.out.println(String.format("%06d", "1025"));
  193 + }
186 } 194 }
src/main/java/com/bsth/vehicle/directive/util/HttpUtils.java renamed to src/main/java/com/bsth/data/directive/GatewayHttpUtils.java
1 -package com.bsth.vehicle.directive.util; 1 +package com.bsth.data.directive;
2 2
3 import java.io.IOException; 3 import java.io.IOException;
4 4
@@ -17,15 +17,14 @@ import com.bsth.util.ConfigUtil; @@ -17,15 +17,14 @@ import com.bsth.util.ConfigUtil;
17 17
18 /** 18 /**
19 * 19 *
20 - * @ClassName: HttpUtils 20 + * @ClassName: GatewayHttpUtils
21 * @Description: TODO(和网关HTTP通讯工具类) 21 * @Description: TODO(和网关HTTP通讯工具类)
22 * @author PanZhao 22 * @author PanZhao
23 - * @date 2016年7月8日 上午10:38:10 23 + * @date 2016年8月14日 下午9:50:46
24 * 24 *
25 */ 25 */
26 -public class HttpUtils {  
27 -  
28 - static Logger logger = LoggerFactory.getLogger(HttpUtils.class); 26 +public class GatewayHttpUtils {
  27 + static Logger logger = LoggerFactory.getLogger(GatewayHttpUtils.class);
29 28
30 static String url; 29 static String url;
31 30
src/main/java/com/bsth/data/gpsdata/GpsRealEntity.java renamed to src/main/java/com/bsth/data/gpsdata/GpsEntity.java
@@ -8,7 +8,7 @@ package com.bsth.data.gpsdata; @@ -8,7 +8,7 @@ package com.bsth.data.gpsdata;
8 * @date 2016年5月11日 下午4:32:07 8 * @date 2016年5月11日 下午4:32:07
9 * 9 *
10 */ 10 */
11 -public class GpsRealEntity { 11 +public class GpsEntity {
12 12
13 /** 公司代码 */ 13 /** 公司代码 */
14 private Integer companyCode; 14 private Integer companyCode;
src/main/java/com/bsth/data/gpsdata/GpsRealData.java 0 → 100644
  1 +package com.bsth.data.gpsdata;
  2 +
  3 +import java.io.BufferedReader;
  4 +import java.io.InputStreamReader;
  5 +import java.util.ArrayList;
  6 +import java.util.HashMap;
  7 +import java.util.List;
  8 +import java.util.Map;
  9 +import java.util.NavigableSet;
  10 +import java.util.concurrent.TimeUnit;
  11 +
  12 +import org.apache.http.HttpEntity;
  13 +import org.apache.http.client.methods.CloseableHttpResponse;
  14 +import org.apache.http.client.methods.HttpGet;
  15 +import org.apache.http.impl.client.CloseableHttpClient;
  16 +import org.apache.http.impl.client.HttpClients;
  17 +import org.slf4j.Logger;
  18 +import org.slf4j.LoggerFactory;
  19 +import org.springframework.beans.factory.annotation.Autowired;
  20 +import org.springframework.boot.CommandLineRunner;
  21 +import org.springframework.stereotype.Component;
  22 +
  23 +import com.alibaba.fastjson.JSON;
  24 +import com.alibaba.fastjson.JSONObject;
  25 +import com.bsth.Application;
  26 +import com.bsth.data.BasicData;
  27 +import com.bsth.util.ConfigUtil;
  28 +import com.google.common.collect.TreeMultimap;
  29 +
  30 +/**
  31 + *
  32 + * @ClassName: GpsRealEntityBuffer
  33 + * @Description: TODO(实时GPS数据集合)
  34 + * @author PanZhao
  35 + * @date 2016年8月12日 下午2:04:41
  36 + *
  37 + */
  38 +@Component
  39 +public class GpsRealData implements CommandLineRunner{
  40 +
  41 + static Logger logger = LoggerFactory.getLogger(GpsRealData.class);
  42 +
  43 + private static Map<String, GpsEntity> gpsMap;
  44 +
  45 + //按线路分组设备号
  46 + private static TreeMultimap<Integer, String> lineCode2Devices;
  47 +
  48 + // 网关数据接口地址
  49 + private static String url;
  50 +
  51 + @Autowired
  52 + GpsDataLoader gpsDataLoader;
  53 +
  54 + /**
  55 + * 构造函数
  56 + */
  57 + public GpsRealData(){
  58 + gpsMap = new HashMap<>();
  59 + lineCode2Devices = TreeMultimap.create();
  60 + url = ConfigUtil.get("http.gps.real.url");
  61 + }
  62 +
  63 + @Override
  64 + public void run(String... arg0) throws Exception {
  65 + logger.info("gpsDataLoader,20,8");
  66 + Application.mainServices.scheduleWithFixedDelay(gpsDataLoader, 20, 8, TimeUnit.SECONDS);
  67 + }
  68 +
  69 + public static GpsEntity add(GpsEntity gps) {
  70 + String device = gps.getDeviceId();
  71 + gpsMap.put(device, gps);
  72 + lineCode2Devices.put(gps.getLineId(), device);
  73 + return gps;
  74 + }
  75 +
  76 + /**
  77 + *
  78 + * @Title: get @Description: TODO(设备号获取GPS)
  79 + */
  80 + public GpsEntity get(String deviceId) {
  81 + return gpsMap.get(deviceId);
  82 + }
  83 +
  84 + /**
  85 + *
  86 + * @Title: get @Description: TODO(线路编码获取GPS集合) @throws
  87 + */
  88 + public List<GpsEntity> get(Integer lineCode) {
  89 + NavigableSet<String> set = lineCode2Devices.get(lineCode);
  90 +
  91 + List<GpsEntity> rs = new ArrayList<>();
  92 + for(String device : set){
  93 + rs.add(gpsMap.get(device));
  94 + }
  95 +
  96 + return rs;
  97 + }
  98 +
  99 + public List<GpsEntity> get(List<String> pArray){
  100 + List<GpsEntity> list = new ArrayList<>();
  101 +
  102 + for(String code : pArray)
  103 + list.addAll(get(Integer.parseInt(code)));
  104 + return list;
  105 + }
  106 +
  107 + public GpsEntity findByDeviceId(String deviceId) {
  108 + return gpsMap.get(deviceId);
  109 + }
  110 +
  111 + @Component
  112 + public static class GpsDataLoader extends Thread{
  113 +
  114 + Logger logger = LoggerFactory.getLogger(GpsDataLoader.class);
  115 +
  116 + @Override
  117 + public void run() {
  118 + try{
  119 + load();
  120 + }catch(Exception e){
  121 + logger.error("", e);
  122 + }
  123 + }
  124 +
  125 + public void load() throws Exception {
  126 + List<GpsEntity> list = new ArrayList<>();
  127 + CloseableHttpClient httpClient = null;
  128 + CloseableHttpResponse response = null;
  129 + try {
  130 + httpClient = HttpClients.createDefault();
  131 + HttpGet get = new HttpGet(url);
  132 +
  133 + response = httpClient.execute(get);
  134 +
  135 + HttpEntity entity = response.getEntity();
  136 + if (null != entity) {
  137 + // 返回数据量比较大,建议以流的形式读取
  138 + BufferedReader br = new BufferedReader(new InputStreamReader(entity.getContent()));
  139 + StringBuffer stringBuffer = new StringBuffer();
  140 + String str = "";
  141 + while ((str = br.readLine()) != null)
  142 + stringBuffer.append(str);
  143 +
  144 + JSONObject jsonObj = JSON.parseObject(stringBuffer.toString());
  145 +
  146 + if (jsonObj != null)
  147 + list = JSON.parseArray(jsonObj.getString("data"), GpsEntity.class);
  148 +
  149 + //附加车辆内部编码
  150 + for(GpsEntity gps : list){
  151 + gps.setNbbm(BasicData.deviceId2NbbmMap.get(gps.getDeviceId()));
  152 + gps.setStationName(BasicData.stationCode2NameMap.get(gps.getStopNo()));
  153 + add(gps);
  154 + }
  155 + } else
  156 + logger.error("result is null");
  157 + } finally {
  158 + if (null != httpClient)
  159 + httpClient.close();
  160 + if(null != response)
  161 + response.close();
  162 + }
  163 + }
  164 + }
  165 +}
src/main/java/com/bsth/data/gpsdata/GpsRealDataList.java deleted 100644 → 0
1 -//package com.bsth.data.gpsdata;  
2 -//  
3 -//import java.io.BufferedReader;  
4 -//import java.io.InputStreamReader;  
5 -//import java.util.ArrayList;  
6 -//import java.util.HashMap;  
7 -//import java.util.List;  
8 -//import java.util.Map;  
9 -//import java.util.NavigableSet;  
10 -//  
11 -//import org.apache.http.HttpEntity;  
12 -//import org.apache.http.client.methods.CloseableHttpResponse;  
13 -//import org.apache.http.client.methods.HttpGet;  
14 -//import org.apache.http.impl.client.CloseableHttpClient;  
15 -//import org.apache.http.impl.client.HttpClients;  
16 -//import org.slf4j.Logger;  
17 -//import org.slf4j.LoggerFactory;  
18 -//  
19 -//import com.alibaba.fastjson.JSON;  
20 -//import com.alibaba.fastjson.JSONObject;  
21 -//import com.bsth.data.BasicData;  
22 -//import com.bsth.util.ConfigUtil;  
23 -//import com.bsth.vehicle.gpsdata.entity.GpsRealData;  
24 -//import com.google.common.collect.TreeMultimap;  
25 -//  
26 -///**  
27 -// *  
28 -// * @ClassName: GpsRealDataBuffer  
29 -// * @Description: TODO(实时GPS数据集合)  
30 -// * @author PanZhao  
31 -// * @date 2016年8月12日 下午2:04:41  
32 -// *  
33 -// */  
34 -//public class GpsRealDataList {  
35 -//  
36 -// private static Map<String, GpsRealData> gpsMap;  
37 -//  
38 -// private static TreeMultimap<Integer, String> lineCode2Devices;  
39 -//  
40 -// // 网关数据接口地址  
41 -// private static String url;  
42 -//  
43 -// static{  
44 -// gpsMap = new HashMap<>();  
45 -// lineCode2Devices = TreeMultimap.create();  
46 -// url = ConfigUtil.get("http.gps.real.url");  
47 -// }  
48 -//  
49 -// static Logger logger = LoggerFactory.getLogger(GpsRealDataList.class);  
50 -//  
51 -// public static GpsRealData add(GpsRealData gps) {  
52 -// String device = gps.getDeviceId();  
53 -// gpsMap.put(device, gps);  
54 -// lineCode2Devices.put(gps.getLineId(), device);  
55 -// return gps;  
56 -// }  
57 -//  
58 -// /**  
59 -// *  
60 -// * @Title: get @Description: TODO(设备号获取GPS) @param @param deviceId @throws  
61 -// */  
62 -// public static GpsRealData get(String deviceId) {  
63 -// return gpsMap.get(deviceId);  
64 -// }  
65 -//  
66 -// /**  
67 -// *  
68 -// * @Title: get @Description: TODO(线路编码获取GPS集合) @throws  
69 -// */  
70 -// public static List<GpsRealData> get(Integer lineCode) {  
71 -// NavigableSet<String> set = lineCode2Devices.get(lineCode);  
72 -//  
73 -// List<GpsRealData> rs = new ArrayList<>();  
74 -// for(String device : set){  
75 -// rs.add(gpsMap.get(device));  
76 -// }  
77 -//  
78 -// return rs;  
79 -// }  
80 -//  
81 -// public static void LoadGpsRealData() throws Exception {  
82 -// List<GpsRealData> list = new ArrayList<>();  
83 -// CloseableHttpClient httpClient = null;  
84 -//  
85 -// try {  
86 -// httpClient = HttpClients.createDefault();  
87 -// HttpGet get = new HttpGet(url);  
88 -//  
89 -// CloseableHttpResponse response = httpClient.execute(get);  
90 -//  
91 -// try {  
92 -// HttpEntity entity = response.getEntity();  
93 -// if (null != entity) {  
94 -// // 返回数据量比较大,建议以流的形式读取  
95 -// BufferedReader br = new BufferedReader(new InputStreamReader(entity.getContent()));  
96 -// StringBuffer stringBuffer = new StringBuffer();  
97 -// String str = "";  
98 -// while ((str = br.readLine()) != null)  
99 -// stringBuffer.append(str);  
100 -//  
101 -// JSONObject jsonObj = JSON.parseObject(stringBuffer.toString());  
102 -//  
103 -// if (jsonObj != null)  
104 -// list = JSON.parseArray(jsonObj.getString("data"), GpsRealData.class);  
105 -//  
106 -// for(GpsRealData gps : list){  
107 -// gps.setNbbm(BasicData.deviceId2NbbmMap.get(gps));  
108 -// add(gps);  
109 -// }  
110 -// } else  
111 -// logger.error("result is null");  
112 -// } finally {  
113 -// response.close();  
114 -// }  
115 -//  
116 -// } finally {  
117 -// if (null != httpClient)  
118 -// httpClient.close();  
119 -// }  
120 -// }  
121 -//}  
src/main/java/com/bsth/data/match/Arrival2Schedule.java 0 → 100644
  1 +package com.bsth.data.match;
  2 +
  3 +import java.util.ArrayList;
  4 +import java.util.Collections;
  5 +import java.util.List;
  6 +import java.util.Set;
  7 +
  8 +import org.springframework.beans.BeansException;
  9 +import org.springframework.context.ApplicationContext;
  10 +import org.springframework.context.ApplicationContextAware;
  11 +import org.springframework.stereotype.Component;
  12 +
  13 +import com.bsth.data.arrival.ArrivalComparator;
  14 +import com.bsth.data.arrival.ArrivalData_GPS;
  15 +import com.bsth.data.arrival.ArrivalEntity;
  16 +import com.bsth.data.schedule.DayOfSchedule;
  17 +import com.bsth.data.schedule.ScheduleComparator;
  18 +import com.bsth.entity.realcontrol.ScheduleRealInfo;
  19 +import com.bsth.service.directive.DirectiveService;
  20 +import com.bsth.websocket.handler.SendUtils;
  21 +
  22 +@Component
  23 +public class Arrival2Schedule implements ApplicationContextAware {
  24 +
  25 + private static DayOfSchedule dayOfSchedule;
  26 +
  27 +
  28 + private static ScheduleComparator.FCSJ schComparator;
  29 + private static ArrivalComparator arrComparator;
  30 + private static MatchResultComparator mrComparator;;
  31 + private static SendUtils sendUtils;
  32 + private static DirectiveService directiveService;
  33 + private final static int ONE_MINUTE = 1000 * 60;
  34 + //定一个4小时的范围,基本能对正常班次进行容错。主要防止早上停车场GPS飘导致完成晚上的进场班次
  35 + private final static int FOUR_HOURS = 1000 * 60 * 60 * 4;
  36 +
  37 + static{
  38 + schComparator = new ScheduleComparator.FCSJ();
  39 + arrComparator = new ArrivalComparator();
  40 + mrComparator = new MatchResultComparator();
  41 + }
  42 +
  43 + /**
  44 + *
  45 + * @Title: start
  46 + * @Description: TODO(开始)
  47 + * @param @param cars 需要匹配的车辆集合
  48 + */
  49 + public static void start(Set<String> cars){
  50 +
  51 + for(String car : cars){
  52 + new SchMatchThread(car).start();
  53 + }
  54 + }
  55 +
  56 + public static class SchMatchThread extends Thread{
  57 + String nbbm;
  58 + public SchMatchThread(String nbbm){
  59 + this.nbbm = nbbm;
  60 + }
  61 + @Override
  62 + public void run() {
  63 + //班次列表
  64 + List<ScheduleRealInfo> schList = dayOfSchedule.findByNbbm(nbbm);
  65 + //进出起终点数据
  66 + List<ArrivalEntity> arrList = ArrivalData_GPS.findByNbbm(nbbm);
  67 + //排序
  68 + Collections.sort(schList, schComparator);
  69 + Collections.sort(arrList, arrComparator);
  70 +
  71 + //用实际来匹配计划
  72 + for(ArrivalEntity arr : arrList){
  73 + match(arr, schList);
  74 + }
  75 + }
  76 + private void match(ArrivalEntity arr, List<ScheduleRealInfo> schList) {
  77 + schList = matchFilter(schList);
  78 +
  79 + if(arr.getInOut() == 1)
  80 + matchOut(arr, schList);
  81 + else if(arr.getInOut() == 0)
  82 + matchIn(arr, schList);
  83 + }
  84 +
  85 + private List<ScheduleRealInfo> matchFilter(List<ScheduleRealInfo> schList) {
  86 + List<ScheduleRealInfo> list = new ArrayList<>();
  87 + for(ScheduleRealInfo sch : schList){
  88 + //烂班不匹配
  89 + if(sch.isDestroy())
  90 + continue;
  91 +
  92 + //没有里程的不匹配
  93 + if(sch.getBcsj() == null && sch.getJhlc() == null)
  94 + continue;
  95 +
  96 + list.add(sch);
  97 + }
  98 + return list;
  99 + }
  100 +
  101 + private void matchOut(ArrivalEntity arr, List<ScheduleRealInfo> schList){
  102 + List<MatchResult> mrs = new ArrayList<>();
  103 + ScheduleRealInfo sch;
  104 + MatchResult mr;
  105 + for(int i = 0; i < schList.size(); i ++){
  106 + sch = schList.get(i);
  107 + if(!arr.isTcc() && arr.getUpDown() != Integer.parseInt(sch.getXlDir()))
  108 + continue;
  109 +
  110 + if(!arr.getStopNo().equals(sch.getQdzCode()))
  111 + continue;
  112 +
  113 + //班次有实发时间
  114 + if(sch.getFcsjActualTime() != null){
  115 + //实际发车已经被引用
  116 + if(Math.abs(arr.getTs() - sch.getFcsjActualTime()) < ONE_MINUTE)
  117 + return;
  118 + else
  119 + continue;
  120 + }
  121 + //添加一个匹配结果
  122 + mr = new MatchResult();
  123 + mr.sch = sch;
  124 + mr.ts = arr.getTs();
  125 + mr.diff = arr.getTs() - sch.getFcsjT();
  126 + mr.success = dayOfSchedule.validStartTime(sch, arr.getTs());
  127 +
  128 + if(Math.abs(mr.diff) < FOUR_HOURS && mr.success)
  129 + mrs.add(mr);
  130 + }
  131 +
  132 + if(mrs.size() > 0){
  133 + //排序后的第一个 就是最合适的匹配
  134 + Collections.sort(mrs, mrComparator);
  135 + mr = mrs.get(0);
  136 +
  137 + mr.sch.setFcsjActualAll(mr.ts);
  138 + //通知客户端
  139 + sendUtils.sendFcsj(mr.sch);
  140 + //持久化
  141 + dayOfSchedule.save(mr.sch);
  142 + }
  143 + }
  144 +
  145 + private void matchIn(ArrivalEntity inArr, List<ScheduleRealInfo> schList){
  146 +
  147 + List<MatchResult> mrs = new ArrayList<>();
  148 + ScheduleRealInfo sch;
  149 + MatchResult mr;
  150 + for(int i = 0; i < schList.size(); i ++){
  151 + sch = schList.get(i);
  152 + if(!inArr.isTcc() && inArr.getUpDown() != Integer.parseInt(sch.getXlDir()))
  153 + continue;
  154 +
  155 + if(!inArr.getStopNo().equals(sch.getZdzCode()))
  156 + continue;
  157 +
  158 + //班次有实达时间
  159 + if(sch.getZdsjActualTime() != null){
  160 + //实际到达已经被引用
  161 + if(Math.abs(inArr.getTs() - sch.getZdsjActualTime()) < ONE_MINUTE)
  162 + return;
  163 + else
  164 + continue;
  165 + }
  166 +
  167 + //添加一个匹配结果
  168 + mr = new MatchResult();
  169 + mr.sch = sch;
  170 + mr.ts = inArr.getTs();
  171 + mr.diff = inArr.getTs() - sch.getZdsjT();
  172 + mr.success = dayOfSchedule.validEndTime(sch, inArr.getTs());
  173 + if(Math.abs(mr.diff) < FOUR_HOURS && mr.success)
  174 + mrs.add(mr);
  175 + }
  176 +
  177 + if(mrs.size() > 0){
  178 + //排序后的第一个 就是最合适的匹配
  179 + Collections.sort(mrs, mrComparator);
  180 + mr = mrs.get(0);
  181 + mr.sch.setZdsjActualAll(mr.ts);
  182 +
  183 + int doneSum = dayOfSchedule.doneSum(mr.sch.getClZbh());
  184 + ScheduleRealInfo next = dayOfSchedule.next(mr.sch);
  185 + if(null != next){
  186 + next.setQdzArrDateSJ(mr.sch.getZdsjActual());
  187 + //下发调度指令
  188 + directiveService.send60Dispatch(next, doneSum, "系统");
  189 + }
  190 + else//下发文本指令(已结束运营)
  191 + directiveService.send60Phrase(nbbm, "到达终点 " + mr.sch.getZdzName() + ",已完成当日所有排班。", "系统");
  192 + //通知客户端
  193 + sendUtils.sendZdsj(mr.sch, next, doneSum);
  194 + //持久化
  195 + dayOfSchedule.save(mr.sch);
  196 + }
  197 + }
  198 + }
  199 +
  200 + @Override
  201 + public void setApplicationContext(ApplicationContext arg0) throws BeansException {
  202 + sendUtils = arg0.getBean(SendUtils.class);
  203 + dayOfSchedule = arg0.getBean(DayOfSchedule.class);
  204 + directiveService = arg0.getBean(DirectiveService.class);
  205 + }
  206 +}
src/main/java/com/bsth/data/match/Arrival2Schedule_old.java 0 → 100644
  1 +package com.bsth.data.match;
  2 +//package com.bsth.data.match;
  3 +//
  4 +//import java.util.ArrayList;
  5 +//import java.util.Collections;
  6 +//import java.util.List;
  7 +//import java.util.Set;
  8 +//
  9 +//import org.slf4j.Logger;
  10 +//import org.slf4j.LoggerFactory;
  11 +//import org.springframework.beans.BeansException;
  12 +//import org.springframework.context.ApplicationContext;
  13 +//import org.springframework.context.ApplicationContextAware;
  14 +//import org.springframework.stereotype.Component;
  15 +//
  16 +//import com.bsth.data.arrival.ArrivalComparator;
  17 +//import com.bsth.data.arrival.ArrivalData_GPS;
  18 +//import com.bsth.data.arrival.ArrivalEntity;
  19 +//import com.bsth.data.schedule.DayOfSchedule;
  20 +//import com.bsth.data.schedule.ScheduleComparator;
  21 +//import com.bsth.entity.realcontrol.ScheduleRealInfo;
  22 +//import com.bsth.service.directive.DirectiveService;
  23 +//import com.bsth.websocket.handler.SendUtils;
  24 +//
  25 +///**
  26 +// *
  27 +// * @ClassName: Arrival2Schedule
  28 +// * @Description: TODO(进出数据匹配班次)
  29 +// * @author PanZhao
  30 +// * @date 2016年8月10日 下午2:26:22
  31 +// *
  32 +// */
  33 +//@Component
  34 +//public class Arrival2Schedule implements ApplicationContextAware{
  35 +//
  36 +// private static ScheduleComparator.FCSJ schComparator;
  37 +// private static ArrivalComparator arrComparator;
  38 +// private static SendUtils sendUtils;
  39 +// private static DayOfSchedule dayOfSchedule;
  40 +// private static DirectiveService directiveService;
  41 +//
  42 +// private final static long MAX_RANGE = 1000 * 60 * 60 * 1L;
  43 +//
  44 +// static{
  45 +// schComparator = new ScheduleComparator.FCSJ();
  46 +// arrComparator = new ArrivalComparator();
  47 +// }
  48 +//
  49 +// static Logger logger = LoggerFactory.getLogger(Arrival2Schedule.class);
  50 +//
  51 +// /**
  52 +// *
  53 +// * @Title: start
  54 +// * @Description: TODO(开始)
  55 +// * @param @param cars 需要匹配的车辆集合
  56 +// */
  57 +// public static void start(Set<String> cars){
  58 +//
  59 +// for(String car : cars){
  60 +// new GpsMatchThread(car).start();
  61 +// }
  62 +// }
  63 +//
  64 +// public static class GpsMatchThread extends Thread{
  65 +//
  66 +// String nbbm;
  67 +// public GpsMatchThread(String nbbm){
  68 +// this.nbbm = nbbm;
  69 +// }
  70 +//
  71 +// @Override
  72 +// public void run() {
  73 +// //班次列表
  74 +// List<ScheduleRealInfo> schList = dayOfSchedule.findByNbbm(nbbm);
  75 +// //进出起终点数据
  76 +// List<ArrivalEntity> arrList = ArrivalData_GPS.getIncrement(nbbm);
  77 +// logger.info("####匹配进出站增量数据 " + arrList.size());
  78 +// //排序
  79 +// Collections.sort(schList, schComparator);
  80 +// Collections.sort(arrList, arrComparator);
  81 +//
  82 +// int si = lastMatchPoint(schList);
  83 +// int ai = afterByTime(arrList, lastMatchTime(schList.get(si)));
  84 +//
  85 +// //按起始索引开始匹配
  86 +// match(arrList, ai, schList, si);
  87 +// }
  88 +//
  89 +// public void match(List<ArrivalEntity> arrList, int ai, List<ScheduleRealInfo> schList, int si){
  90 +//
  91 +// int sLen = schList.size();
  92 +// for(; si < sLen; si ++)
  93 +// match(arrList, ai, schList.get(si));
  94 +// }
  95 +//
  96 +// public void match(List<ArrivalEntity> arrList, int ai, ScheduleRealInfo sch){
  97 +// //烂班不参与
  98 +// if(sch.isDestroy())
  99 +// return;
  100 +//
  101 +// int aLen = arrList.size();
  102 +//
  103 +// List<MatchResult> inRsList = new ArrayList<>()
  104 +// ,outRsList = new ArrayList<>();
  105 +//
  106 +// MatchResult mrs;
  107 +// for(;ai < aLen; ai ++){
  108 +// mrs = match(arrList.get(ai), sch);
  109 +// if(!mrs.success)
  110 +// continue;
  111 +//
  112 +// if(mrs.inOut == 0)
  113 +// inRsList.add(mrs);
  114 +// else if(mrs.inOut == 1)
  115 +// outRsList.add(mrs);
  116 +// }
  117 +//
  118 +// if(outRsList.size() > 0){
  119 +// //排序后的第一个 就是最合适的匹配
  120 +// Collections.sort(outRsList, new MatchResultComparator());
  121 +// mrs = outRsList.get(0);
  122 +//
  123 +// mrs.sch.setFcsjActualAll(mrs.ts);
  124 +// //通知客户端
  125 +// sendUtils.sendFcsj(mrs.sch);
  126 +// //持久化
  127 +// dayOfSchedule.save(mrs.sch);
  128 +// }
  129 +//
  130 +// if(inRsList.size() > 0){
  131 +// //排序后的第一个 就是最合适的匹配
  132 +// Collections.sort(inRsList, new MatchResultComparator());
  133 +// mrs = inRsList.get(0);
  134 +//
  135 +// /*if(!dayOfSchedule.validEndTime(mrs.sch, mrs.ts)){
  136 +// return;
  137 +// }*/
  138 +//
  139 +// mrs.sch.setZdsjActualAll(mrs.ts);
  140 +// int doneSum = dayOfSchedule.doneSum(mrs.sch.getClZbh());
  141 +// ScheduleRealInfo next = dayOfSchedule.next(mrs.sch);
  142 +// if(null != next){
  143 +// next.setQdzArrDateSJ(mrs.sch.getZdsjActual());
  144 +// //下发调度指令
  145 +// directiveService.send60Dispatch(next, doneSum, "系统");
  146 +// }
  147 +// else{
  148 +// //下发文本指令(已结束运营)
  149 +// directiveService.send60Phrase(nbbm, "到达终点 " + mrs.sch.getZdzName() + ",已完成当日所有排班。", "系统");
  150 +// }
  151 +// //通知客户端
  152 +// sendUtils.sendZdsj(mrs.sch, next, doneSum);
  153 +// //持久化
  154 +// dayOfSchedule.save(mrs.sch);
  155 +// }
  156 +// }
  157 +//
  158 +// public MatchResult match(ArrivalEntity arr, ScheduleRealInfo sch){
  159 +// MatchResult mrs = new MatchResult();
  160 +// mrs.inOut = arr.getInOut();
  161 +// mrs.sch = sch;
  162 +// mrs.ts = arr.getTs();
  163 +//
  164 +// if(Integer.parseInt(sch.getXlDir()) != arr.getUpDown()){
  165 +// return mrs;
  166 +// }
  167 +//
  168 +// if(arr.getInOut() == 1){
  169 +// if(sch.getFcsjActual() == null
  170 +// && sch.getQdzCode().equals(arr.getStopNo())
  171 +// && dayOfSchedule.validStartTime(sch, arr.getTs())){
  172 +//
  173 +// mrs.diff = arr.getTs() - sch.getDfsjT();
  174 +// if(Math.abs(mrs.diff) < MAX_RANGE)
  175 +// mrs.success = true;
  176 +// }
  177 +// }
  178 +// else if(arr.getInOut() == 0 && sch.getZdsj() != null){
  179 +// if(sch.getZdsjActual() == null
  180 +// && sch.getZdzCode().equals(arr.getStopNo())
  181 +// && dayOfSchedule.validEndTime(sch, arr.getTs())){
  182 +//
  183 +// mrs.diff = arr.getTs() - sch.getZdsjT();
  184 +// if(Math.abs(mrs.diff) < MAX_RANGE)
  185 +// mrs.success = true;
  186 +// }
  187 +// }
  188 +//
  189 +// return mrs;
  190 +// }
  191 +//
  192 +// /**
  193 +// *
  194 +// * @Title: lastMatchPoint
  195 +// * @Description: TODO(最后一个已实发的班次索引)
  196 +// */
  197 +// public int lastMatchPoint(List<ScheduleRealInfo> schList){
  198 +// int len = schList.size()
  199 +// ,rs = 0;
  200 +//
  201 +// ScheduleRealInfo sch;
  202 +// for(int i = len - 2; i >= 0; i --){
  203 +// sch = schList.get(i);
  204 +// if(sch.getFcsjActual() != null){
  205 +// rs = i;
  206 +// if(sch.getStatus() == 2)
  207 +// rs ++;
  208 +// break;
  209 +// }
  210 +// }
  211 +// return rs;
  212 +// }
  213 +//
  214 +// public long lastMatchTime(ScheduleRealInfo sch){
  215 +// Long t = 0L;
  216 +// if(null != sch.getFcsjActualTime())
  217 +// t = sch.getFcsjActualTime();
  218 +// if(null != sch.getZdsjActualTime())
  219 +// t = sch.getZdsjActualTime();
  220 +// return t;
  221 +// }
  222 +//
  223 +// /**
  224 +// *
  225 +// * @Title: afterByTime
  226 +// * @Description: TODO(参数时间戳之后的起始索引)
  227 +// */
  228 +// public int afterByTime(List<ArrivalEntity> arrList, long t){
  229 +// int len = arrList.size()
  230 +// ,rs = len - 1;
  231 +//
  232 +// for(int i = 0; i < len; i ++){
  233 +// if(arrList.get(i).getTs() > t){
  234 +// rs = i;
  235 +// break;
  236 +// }
  237 +// }
  238 +// return rs;
  239 +// }
  240 +// }
  241 +//
  242 +// @Override
  243 +// public void setApplicationContext(ApplicationContext arg0) throws BeansException {
  244 +// sendUtils = arg0.getBean(SendUtils.class);
  245 +// dayOfSchedule = arg0.getBean(DayOfSchedule.class);
  246 +// directiveService = arg0.getBean(DirectiveService.class);
  247 +// }
  248 +//}
src/main/java/com/bsth/data/match/MatchResult.java 0 → 100644
  1 +package com.bsth.data.match;
  2 +
  3 +import com.bsth.entity.realcontrol.ScheduleRealInfo;
  4 +
  5 +/**
  6 + *
  7 + * @ClassName: MatchResult
  8 + * @Description: TODO(实际和计划匹配结果)
  9 + * @author PanZhao
  10 + * @date 2016年8月10日 下午3:55:48
  11 + *
  12 + */
  13 +public class MatchResult {
  14 +
  15 + /** 班次 */
  16 + public ScheduleRealInfo sch;
  17 +
  18 + /** 时间差 */
  19 + public long diff;
  20 +
  21 + /** 0 进 1 出 */
  22 + public int inOut;
  23 +
  24 + public long ts;
  25 +
  26 + /** 交配成功 */
  27 + public boolean success;
  28 +}
src/main/java/com/bsth/data/match/MatchResultComparator.java 0 → 100644
  1 +package com.bsth.data.match;
  2 +
  3 +import java.util.Comparator;
  4 +
  5 +public class MatchResultComparator implements Comparator<MatchResult>{
  6 +
  7 + @Override
  8 + public int compare(MatchResult o1, MatchResult o2) {
  9 + return (int) (Math.abs(o1.diff) - Math.abs(o2.diff));
  10 + }
  11 +}
src/main/java/com/bsth/data/pilot80/PilotReport.java 0 → 100644
  1 +package com.bsth.data.pilot80;
  2 +
  3 +import java.util.ArrayList;
  4 +import java.util.Collection;
  5 +import java.util.List;
  6 +
  7 +import org.slf4j.Logger;
  8 +import org.slf4j.LoggerFactory;
  9 +import org.springframework.beans.factory.annotation.Autowired;
  10 +import org.springframework.stereotype.Component;
  11 +
  12 +import com.bsth.data.BasicData;
  13 +import com.bsth.data.LineConfigData;
  14 +import com.bsth.data.gpsdata.GpsEntity;
  15 +import com.bsth.data.gpsdata.GpsRealData;
  16 +import com.bsth.data.schedule.DayOfSchedule;
  17 +import com.bsth.entity.Line;
  18 +import com.bsth.entity.directive.D80;
  19 +import com.bsth.entity.realcontrol.D80ReplyTemp;
  20 +import com.bsth.entity.realcontrol.LineConfig;
  21 +import com.bsth.entity.realcontrol.ScheduleRealInfo;
  22 +import com.bsth.repository.directive.D80Repository;
  23 +import com.bsth.service.directive.DirectiveService;
  24 +import com.bsth.websocket.handler.SendUtils;
  25 +import com.google.common.collect.ArrayListMultimap;
  26 +
  27 +/**
  28 + *
  29 + * @ClassName: PilotReport
  30 + * @Description: TODO(驾驶员上报)
  31 + * @author PanZhao
  32 + * @date 2016年8月14日 下午11:37:51
  33 + *
  34 + */
  35 +@Component
  36 +public class PilotReport {
  37 +
  38 + @Autowired
  39 + D80Repository d80Repository;
  40 +
  41 + @Autowired
  42 + DayOfSchedule dayOfSchedule;
  43 +
  44 + @Autowired
  45 + LineConfigData lineConfigData;
  46 +
  47 + @Autowired
  48 + DirectiveService directiveService;
  49 +
  50 + @Autowired
  51 + GpsRealData gpsRealData;
  52 +
  53 + @Autowired
  54 + SendUtils sendUtils;
  55 +
  56 + //private static ScheduleComparator.FCNO schComp;
  57 +
  58 + private static ArrayListMultimap<Integer, D80> d80MultiMap;
  59 +
  60 + Logger logger = LoggerFactory.getLogger(PilotReport.class);
  61 +
  62 + static{
  63 + d80MultiMap = ArrayListMultimap.create();
  64 + //schComp = new ScheduleComparator.FCNO();
  65 + }
  66 +
  67 + public void report(D80 d80){
  68 + //入库
  69 + d80Repository.save(d80);
  70 + //入缓存
  71 + d80MultiMap.put(d80.getData().getLineId(), d80);
  72 +
  73 + String nbbm = BasicData.deviceId2NbbmMap.get(d80.getDeviceId());
  74 + //处理
  75 + switch (d80.getData().getRequestCode()) {
  76 + case 0xA3:
  77 + //出场请求
  78 + ScheduleRealInfo outSch = dayOfSchedule.nextByBcType(nbbm, "out");
  79 + //如果有对应出场班次
  80 + if(outSch != null){
  81 + //下发调度指令
  82 + directiveService.send60Dispatch(outSch, dayOfSchedule.doneSum(nbbm), "系统");
  83 + d80.setRemarks("计划出场时间:" + outSch.getDfsj());
  84 + //当前GPS位置
  85 + GpsEntity gps = gpsRealData.get(d80.getDeviceId());
  86 + if(null != gps)
  87 + d80.addRemarks("<br> 位置:" + coordHtmlStr(gps));
  88 +
  89 + sendUtils.refreshSch(outSch);
  90 + }else
  91 + d80.setRemarks("没有出场计划");
  92 +
  93 + break;
  94 +
  95 + case 0xA5:
  96 + //进场请求
  97 + ScheduleRealInfo inSch = dayOfSchedule.nextByBcType(nbbm, "in");
  98 + //如果有对应出场班次
  99 + if(inSch != null){
  100 + d80.setRemarks("计划进场时间:" + inSch.getDfsj());
  101 + //当前GPS位置
  102 + GpsEntity gps = gpsRealData.get(d80.getDeviceId());
  103 + if(null != gps)
  104 + d80.addRemarks("<br> 位置:" + coordHtmlStr(gps));
  105 + }else
  106 + d80.setRemarks("没有进场计划");
  107 + break;
  108 + }
  109 +
  110 + //推送到页面
  111 + sendUtils.send80ToPage(d80);
  112 + }
  113 +
  114 + /**
  115 + *
  116 + * @Title: reply
  117 + * @Description: TODO(调度员回复)
  118 + */
  119 + public void reply(D80 d80){
  120 + String nbbm = BasicData.deviceId2NbbmMap.get(d80.getDeviceId());
  121 + Short reqCode = d80.getData().getRequestCode();
  122 + //默认短语回复
  123 + defaultReply(nbbm, reqCode, d80.getConfirmRs() == 0?true:false);
  124 +
  125 + switch (reqCode) {
  126 + case 0xA3:
  127 + //出场请求回复
  128 + applyOutReply(d80);
  129 + break;
  130 + case 0xA5:
  131 + //进场请求回复
  132 + applyInReply(d80);
  133 + break;
  134 + }
  135 + }
  136 +
  137 + /**
  138 + *
  139 + * @Title: applyOutReply
  140 + * @Description: TODO(出场请求回复)
  141 + */
  142 + public void applyOutReply(D80 d80){
  143 + //同意
  144 + if(d80.getConfirmRs() == 0){
  145 + String nbbm = BasicData.deviceId2NbbmMap.get(d80.getDeviceId());
  146 +
  147 + ScheduleRealInfo sch = dayOfSchedule.nextByBcType(nbbm, "out");
  148 + if(null == sch)
  149 + return;
  150 +
  151 + LineConfig conf = lineConfigData.get(sch.getXlBm());
  152 + if(conf.getOutConfig() == 1){
  153 + //为相关班次写入请求出场时间
  154 + sch.setFcsjActualAll(d80.getTimestamp());
  155 +
  156 + dayOfSchedule.save(sch);
  157 + //通知页面
  158 + sendUtils.refreshSch(sch);
  159 + }
  160 + }
  161 + }
  162 +
  163 + /**
  164 + *
  165 + * @Title: applyInReply
  166 + * @Description: TODO(进场请求回复)
  167 + */
  168 + public void applyInReply(D80 d80){
  169 + //同意
  170 + if(d80.getConfirmRs() == 0){
  171 + String nbbm = BasicData.deviceId2NbbmMap.get(d80.getDeviceId());
  172 +
  173 + ScheduleRealInfo sch = dayOfSchedule.nextByBcType(nbbm, "in");
  174 + if(null == sch)
  175 + return;
  176 +
  177 + LineConfig conf = lineConfigData.get(sch.getXlBm());
  178 + if(conf.getInConfig() == 1){
  179 + //为相关班次写入进场时间
  180 + sch.setZdsjActualAll(d80.getTimestamp());
  181 +
  182 + //没有里程的进场班次
  183 + if(sch.getBcsj() == null && sch.getJhlc() == null)
  184 + sch.setFcsjActualAll(d80.getTimestamp());
  185 +
  186 + dayOfSchedule.save(sch);
  187 + //通知页面
  188 + sendUtils.refreshSch(sch);
  189 + }
  190 + }
  191 + }
  192 +
  193 + public void defaultReply(String nbbm, short requestCode, boolean agree){
  194 + Line line = BasicData.nbbm2LineMap.get(nbbm);
  195 + String lineCode = null;
  196 +
  197 + if(line != null)
  198 + lineCode = line.getLineCode();
  199 + else{
  200 + try{
  201 + lineCode = gpsRealData.get(BasicData.deviceId2NbbmMap.inverse().get(nbbm)).getLineId().toString();
  202 + }catch(Exception e){
  203 + logger.error("", e);
  204 + }
  205 + }
  206 +
  207 + if(null == lineCode)
  208 + return;
  209 +
  210 + LineConfig conf = lineConfigData.get(lineCode);
  211 + D80ReplyTemp temp = conf.findByCode(requestCode);
  212 +
  213 + if(null == temp)
  214 + return;
  215 +
  216 + String text;
  217 + if(agree)
  218 + text = temp.getAgreeText();
  219 + else
  220 + text = temp.getRejectText();
  221 +
  222 + directiveService.send60Phrase(nbbm, text, "系统");
  223 + }
  224 +
  225 + /**
  226 + *
  227 + * @Title: resumeOperation
  228 + * @Description: TODO(恢复营运)
  229 + */
  230 + public void resumeOperation(D80 d80){
  231 +
  232 + }
  233 +
  234 + /**
  235 + *
  236 + * @Title: applyTiaodang
  237 + * @Description: TODO(申请调档)
  238 + */
  239 + public void applyTiaodang(D80 d80){
  240 +
  241 + }
  242 +
  243 + /**
  244 + *
  245 + * @Title: unconfirmed80
  246 + * @Description: TODO(根据lineCode 获取未处理的80数据)
  247 + */
  248 + public List<D80> unconfirmed80(Integer lineCode){
  249 + List<D80> lineAll = d80MultiMap.get(lineCode)
  250 + ,rs = new ArrayList<>();
  251 +
  252 + for(D80 d80 : lineAll)
  253 + if(!d80.isConfirm())
  254 + rs.add(d80);
  255 +
  256 + return rs;
  257 + }
  258 +
  259 + public D80 findById(int id){
  260 + Collection<D80> all = d80MultiMap.values();
  261 +
  262 + for(D80 d80 : all){
  263 + if(d80.getId() == id)
  264 + return d80;
  265 + }
  266 +
  267 + return null;
  268 + }
  269 +
  270 + public String coordHtmlStr(GpsEntity gps){
  271 +
  272 + return "<span class=\"nt-coord\" data-lon=\""+gps.getLon()+"\" data-lat=\""+gps.getLat()+"\"></span>";
  273 + }
  274 +
  275 + public Collection<D80> findAll(){
  276 + return d80MultiMap.values();
  277 + }
  278 +
  279 + public void clear(String lineCode){
  280 + logger.info("清除 80数据 before: " + d80MultiMap.size());
  281 + d80MultiMap.removeAll(lineCode);
  282 + logger.info("清除 80数据 after: " + d80MultiMap.size());
  283 + }
  284 +
  285 + public Collection<? extends D80> findByCar(String nbbm) {
  286 + List<D80> rs = new ArrayList<>();
  287 + String deviceId = BasicData.deviceId2NbbmMap.inverse().get(nbbm);
  288 + if(null == deviceId)
  289 + return rs;
  290 +
  291 + Collection<D80> all = findAll();
  292 + for(D80 d80 : all){
  293 + if(d80.getDeviceId().equals(deviceId))
  294 + rs.add(d80);
  295 + }
  296 + return rs;
  297 + }
  298 +}
src/main/java/com/bsth/data/schedule/DayOfSchedule.java 0 → 100644
  1 +package com.bsth.data.schedule;
  2 +
  3 +import java.text.ParseException;
  4 +import java.util.ArrayList;
  5 +import java.util.Collection;
  6 +import java.util.Collections;
  7 +import java.util.Date;
  8 +import java.util.HashMap;
  9 +import java.util.HashSet;
  10 +import java.util.Iterator;
  11 +import java.util.LinkedList;
  12 +import java.util.List;
  13 +import java.util.Map;
  14 +import java.util.Set;
  15 +import java.util.concurrent.TimeUnit;
  16 +
  17 +import org.slf4j.Logger;
  18 +import org.slf4j.LoggerFactory;
  19 +import org.springframework.beans.factory.annotation.Autowired;
  20 +import org.springframework.boot.CommandLineRunner;
  21 +import org.springframework.stereotype.Component;
  22 +
  23 +import com.alibaba.fastjson.JSON;
  24 +import com.alibaba.fastjson.JSONArray;
  25 +import com.bsth.Application;
  26 +import com.bsth.data.LineConfigData;
  27 +import com.bsth.entity.realcontrol.LineConfig;
  28 +import com.bsth.entity.realcontrol.ScheduleRealInfo;
  29 +import com.bsth.entity.schedule.SchedulePlanInfo;
  30 +import com.bsth.repository.realcontrol.ScheduleRealInfoRepository;
  31 +import com.bsth.service.schedule.SchedulePlanInfoService;
  32 +import com.bsth.util.BatchSaveUtils;
  33 +import com.bsth.util.DateUtils;
  34 +import com.bsth.websocket.handler.SendUtils;
  35 +import com.google.common.collect.ArrayListMultimap;
  36 +import com.google.common.collect.TreeMultimap;
  37 +
  38 +/**
  39 + *
  40 + * @ClassName: DayOfSchedule
  41 + * @Description: TODO(当日实际排班)
  42 + * @author PanZhao
  43 + * @date 2016年8月15日 上午10:16:12
  44 + *
  45 + */
  46 +@Component
  47 +public class DayOfSchedule implements CommandLineRunner {
  48 +
  49 + Logger logger = LoggerFactory.getLogger(this.getClass());
  50 +
  51 + // 按车辆分组的班次数据
  52 + private static ArrayListMultimap<String, ScheduleRealInfo> nbbmScheduleMap;
  53 +
  54 + // 班次主键映射
  55 + private static Map<Long, ScheduleRealInfo> id2SchedulMap;
  56 +
  57 + // 车辆和排班起终点站对照(包括进出的停车场,区间起终点)
  58 + private static TreeMultimap<String, String> nbbm2SEStationMap;
  59 +
  60 + // 持久化缓冲区
  61 + public static LinkedList<ScheduleRealInfo> pstBuffer;
  62 +
  63 + // 排序器
  64 + private static ScheduleComparator.FCNO schNoComparator;
  65 + //private static ScheduleComparator.FCSJ schFcsjComparator;
  66 +
  67 + @Autowired
  68 + LineConfigData lineConfigData;
  69 +
  70 + /*@Autowired
  71 + ScheduleRealInfoService scheduleRealService;*/
  72 +
  73 + @Autowired
  74 + ScheduleRealInfoRepository schRepository;
  75 +
  76 + @Autowired
  77 + SchedulePlanInfoService schPlanService;
  78 +
  79 + @Autowired
  80 + SchAttrCalculator schAttrCalculator;
  81 +
  82 + @Autowired
  83 + SendUtils sendUtils;
  84 +
  85 + /** 线路当前使用的排班的日期 */
  86 + public static Map<String, String> currSchDateMap;
  87 +
  88 + static {
  89 + nbbmScheduleMap = ArrayListMultimap.create();
  90 + id2SchedulMap = new HashMap<>();
  91 + pstBuffer = new LinkedList<>();
  92 + schNoComparator = new ScheduleComparator.FCNO();
  93 + currSchDateMap = new HashMap<>();
  94 + nbbm2SEStationMap = TreeMultimap.create();
  95 + }
  96 +
  97 + @Autowired
  98 + ScheduleRefreshThread scheduleRefreshThread;
  99 +
  100 + @Autowired
  101 + SchedulePstThread schedulePstThread;
  102 +
  103 + @Override
  104 + public void run(String... arg0) throws Exception {
  105 + //翻班线程
  106 + Application.mainServices.scheduleWithFixedDelay(scheduleRefreshThread, 20, 120, TimeUnit.SECONDS);
  107 + //入库
  108 + Application.mainServices.scheduleWithFixedDelay(schedulePstThread, 60, 60, TimeUnit.SECONDS);
  109 + }
  110 +
  111 + public Map<String, String> getCurrSchDate() {
  112 + return currSchDateMap;
  113 + }
  114 +
  115 + /**
  116 + *
  117 + * @Title: calcSchDateB
  118 + * @Description: TODO(计算线路当前应该使用的排班日期)
  119 + */
  120 + public String calcSchDate(String lineCode) {
  121 + LineConfig conf = lineConfigData.get(lineCode);
  122 + long ct = System.currentTimeMillis();
  123 + String schDate = DateUtils.sdfyyyyMMdd.format(new Date(ct));
  124 + // 小于当天起始运营时间,则取前一天的排班
  125 + if (ct < conf.getCurrStartTime())
  126 + schDate = DateUtils.subtractDay(schDate, 1);
  127 +
  128 + return schDate;
  129 + }
  130 +
  131 + /**
  132 + * @Title: reloadSch
  133 + * @Title: reloadSch
  134 + * @Description: TODO(重新载入排班)
  135 + * @param @param
  136 + * lineCode 线路编码
  137 + * @param @param
  138 + * schDate 班次日期 yyyy-MM-dd
  139 + * @param @param
  140 + * forcePlan 强制从计划调度重新抓取
  141 + */
  142 + public int reloadSch(String lineCode, String schDate, boolean forcePlan) {
  143 + try {
  144 + List<ScheduleRealInfo> list;
  145 +
  146 + if (forcePlan)
  147 + removeRealSch(lineCode, schDate);
  148 + else
  149 + clearRAMData(lineCode);
  150 +
  151 + if (existRealSch(lineCode, schDate))
  152 + list = loadRealSch(lineCode, schDate);// 从实际排班表加载
  153 + else {
  154 + list = loadPlanSch(lineCode, schDate);// 从计划排班表加载
  155 + // 写入数据库
  156 + batchSave(list);
  157 + }
  158 +
  159 + //更新线路和班次日期对照
  160 + currSchDateMap.put(lineCode, schDate);
  161 + //添加到缓存
  162 + putAll(list);
  163 +
  164 + //计算“起点站应到”时间
  165 + Set<String> cars = searchAllCars(list);
  166 + for(String nbbm : cars)
  167 + schAttrCalculator.calcQdzTimePlan(nbbmScheduleMap.get(nbbm));
  168 +
  169 + // 页面 翻班通知
  170 + sendUtils.shiftSchedule(lineCode);
  171 + } catch (Exception e) {
  172 + logger.error("", e);
  173 + return -1;
  174 + }
  175 +
  176 + return 0;
  177 + }
  178 +
  179 + /**
  180 + *
  181 + * @Title: searchAllCars
  182 + * @Description: TODO(搜索班次集合中的车辆)
  183 + */
  184 + private Set<String> searchAllCars(List<ScheduleRealInfo> list) {
  185 + Set<String> cars = new HashSet<>();
  186 + for(ScheduleRealInfo sch : list)
  187 + cars.add(sch.getClZbh());
  188 +
  189 + return cars;
  190 + }
  191 +
  192 + private void putAll(List<ScheduleRealInfo> list) {
  193 + for (ScheduleRealInfo sch : list)
  194 + put(sch);
  195 + }
  196 +
  197 + /**
  198 + * @Title: removeRealSch
  199 + * @Description: TODO(清除实际排班,包括数据库和内存数据)
  200 + * @param @param
  201 + * lineCode 线路编码
  202 + * @param @param
  203 + * schDate 班次日期 yyyy-MM-dd
  204 + */
  205 + public void removeRealSch(String lineCode, String schDate) throws Exception {
  206 + try {
  207 + // 清理数据库数据
  208 + schRepository.deleteByLineCodeAndDate(lineCode + "", schDate);
  209 +
  210 + // 清理内存数据
  211 + clearRAMData(lineCode + "");
  212 + } catch (Exception e) {
  213 + logger.error("removeRealSch error, " + lineCode + " -" + schDate, e);
  214 + throw e;
  215 + }
  216 + }
  217 +
  218 + /**
  219 + *
  220 + * @Title: clearRAMData
  221 + * @Description: TODO(清理内存数据)
  222 + */
  223 + public void clearRAMData(String lineCode) {
  224 + int count = 0;
  225 + List<ScheduleRealInfo> remList = new ArrayList<>();
  226 + Collection<ScheduleRealInfo> schs = nbbmScheduleMap.values();
  227 + for (ScheduleRealInfo sch : schs) {
  228 + if (sch.getXlBm().equals(lineCode))
  229 + remList.add(sch);
  230 + }
  231 +
  232 + for(ScheduleRealInfo sch : remList){
  233 + nbbmScheduleMap.remove(sch.getClZbh(), sch);
  234 + count ++;
  235 + }
  236 +
  237 + logger.info(lineCode + "排班清理 " + count);
  238 + }
  239 +
  240 + /**
  241 + * @Title: existRealSch
  242 + * @Description: TODO(实际排班是否已存在)
  243 + */
  244 + public boolean existRealSch(String lineCode, String schDate) {
  245 + int count = schRepository.countByLineCodeAndDate(lineCode, schDate);
  246 + return count > 0;
  247 + }
  248 +
  249 + /**
  250 + * @Title: loadRealSch
  251 + * @Description: TODO(从实际排班表加载数据)
  252 + */
  253 + public List<ScheduleRealInfo> loadRealSch(String lineCode, String schDate) {
  254 + return schRepository.findByLineCodeAndDate(lineCode, schDate);
  255 + }
  256 +
  257 + /**
  258 + * @Title: loadPlanSch
  259 + * @Description: TODO(从计划排班表加载数据)
  260 + */
  261 + public List<ScheduleRealInfo> loadPlanSch(String lineCode, String schDate) {
  262 + List<ScheduleRealInfo> realList = new ArrayList<>();
  263 +
  264 + try {
  265 + Map<String, Object> data = new HashMap<>();
  266 + data.put("scheduleDate_eq", DateUtils.sdfyyyyMMdd.parse(schDate));
  267 + data.put("xlBm_eq", lineCode);
  268 +
  269 + // 查询计划排班
  270 + List<SchedulePlanInfo> planItr = cleanSchPlanItr(schPlanService.list(data).iterator());
  271 +
  272 + // 转换为实际排班
  273 + realList = JSONArray.parseArray(JSON.toJSONString(planItr), ScheduleRealInfo.class);
  274 +
  275 + for (ScheduleRealInfo sch : realList) {
  276 + sch.setScheduleDateStr(DateUtils.sdfyyyyMMdd.format(sch.getScheduleDate()));
  277 + sch.setRealExecDate(sch.getScheduleDateStr());
  278 + // 计划终点时间
  279 + if (sch.getBcsj() != null) {
  280 + try{
  281 + sch.setZdsjT(DateUtils.sdfHHmm.parse(sch.getFcsj()).getTime() + (sch.getBcsj() * 60 * 1000));
  282 + sch.setZdsj(DateUtils.sdfHHmm.format(sch.getZdsjT()));
  283 + }catch(ParseException pe){
  284 + logger.error("loadPlanSch... 计算终点时间失败...");
  285 + }
  286 + }
  287 + }
  288 + } catch (Exception e) {
  289 + logger.error("", e);
  290 + }
  291 + return realList;
  292 + }
  293 +
  294 + /**
  295 + * @Title: batchSave
  296 + * @Description: TODO(批量入库)
  297 + */
  298 + private void batchSave(List<ScheduleRealInfo> list) {
  299 + // 查询数据库最大ID
  300 + Long id = schRepository.getMaxId();
  301 + if (null == id)
  302 + id = 0L;
  303 + id++;
  304 +
  305 + for (ScheduleRealInfo item : list) {
  306 + item.setSpId(item.getId());// 保留原始的计划ID
  307 + item.setId(id++);// 设置ID
  308 + item.setScheduleDateStr(DateUtils.sdfyyyyMMdd.format(item.getScheduleDate()));
  309 + }
  310 +
  311 + // 入库
  312 + new BatchSaveUtils<ScheduleRealInfo>().saveList(list, ScheduleRealInfo.class);
  313 + }
  314 +
  315 + private List<SchedulePlanInfo> cleanSchPlanItr(Iterator<SchedulePlanInfo> itrab) {
  316 + List<SchedulePlanInfo> list = new ArrayList<>();
  317 +
  318 + SchedulePlanInfo sp;
  319 + while (itrab.hasNext()) {
  320 + sp = itrab.next();
  321 + sp.setSchedulePlan(null);
  322 + list.add(sp);
  323 + }
  324 + return list;
  325 + }
  326 +
  327 + /**
  328 + *
  329 + * @Title: findByLineCode
  330 + * @Description: TODO(lineCode 获取班次)
  331 + */
  332 + public List<ScheduleRealInfo> findByLineCode(String lineCode) {
  333 + List<ScheduleRealInfo> rs = new ArrayList<>();
  334 +
  335 + Collection<ScheduleRealInfo> schs = nbbmScheduleMap.values();
  336 + for (ScheduleRealInfo sch : schs) {
  337 + if (sch.getXlBm().equals(lineCode))
  338 + rs.add(sch);
  339 + }
  340 + return rs;
  341 + }
  342 +
  343 + /**
  344 + *
  345 + * @Title: findCarByLineCode
  346 + * @Description: TODO(线路下运营的车辆)
  347 + */
  348 + public Set<String> findCarByLineCode(String lineCode){
  349 + Set<String> rs = new HashSet<>();
  350 +
  351 + Collection<ScheduleRealInfo> schs = nbbmScheduleMap.values();
  352 + for (ScheduleRealInfo sch : schs) {
  353 + if (sch.getXlBm().equals(lineCode))
  354 + rs.add(sch.getClZbh());
  355 + }
  356 +
  357 + return rs;
  358 + }
  359 +
  360 + public List<ScheduleRealInfo> findByNbbm(String nbbm) {
  361 + return nbbmScheduleMap.get(nbbm);
  362 + }
  363 +
  364 + /**
  365 + *
  366 + * @Title: findByLineAndUpDown
  367 + * @Description: TODO(lineCode 和走向获取班次)
  368 + */
  369 + public List<ScheduleRealInfo> findByLineAndUpDown(String lineCode, Integer upDown) {
  370 + List<ScheduleRealInfo> list = findByLineCode(lineCode), rs = new ArrayList<>();
  371 +
  372 + for (ScheduleRealInfo sch : list) {
  373 + if (sch.getXlDir().equals(upDown + ""))
  374 + rs.add(sch);
  375 + }
  376 + return rs;
  377 + }
  378 +
  379 + public ScheduleRealInfo get(long id) {
  380 + return id2SchedulMap.get(id);
  381 + }
  382 +
  383 + public Set<String> getSEStationList(String nbbm) {
  384 + return nbbm2SEStationMap.get(nbbm);
  385 + }
  386 +
  387 + /**
  388 + *
  389 + * @Title: next
  390 + * @Description: TODO(下一个班次)
  391 + */
  392 + public ScheduleRealInfo next(ScheduleRealInfo sch) {
  393 +
  394 + List<ScheduleRealInfo> list = nbbmScheduleMap.get(sch.getClZbh());
  395 +
  396 + boolean flag = false;
  397 + ScheduleRealInfo next = null;
  398 + for(ScheduleRealInfo temp : list){
  399 + if(temp.getId() == sch.getId()){
  400 + flag = true;
  401 + continue;
  402 + }
  403 + //忽略烂班
  404 + if(temp.isDestroy())
  405 + continue;
  406 +
  407 + if(flag){
  408 + next = temp;
  409 + break;
  410 + }
  411 + }
  412 + return next;
  413 + }
  414 +
  415 + /**
  416 + *
  417 + * @Title: prveRealSch
  418 + * @Description: TODO(获取上一个已实际发出的班次)
  419 + */
  420 +/* public ScheduleRealInfo prveSjfc(ScheduleRealInfo sch) {
  421 + List<ScheduleRealInfo> list = nbbmScheduleMap.get(sch.getClZbh());
  422 + // 排序
  423 + Collections.sort(list, schNoComparator);
  424 +
  425 + ScheduleRealInfo prve = null;
  426 +
  427 + int i = list.indexOf(sch);
  428 + for (; i >= 0; i--){
  429 + if (list.get(i).getFcsjActual() != null){
  430 + prve = list.get(i);
  431 + break;
  432 + }
  433 + }
  434 + return prve;
  435 + }*/
  436 +
  437 + public void put(ScheduleRealInfo sch) {
  438 + schAttrCalculator
  439 + .calcRealDate(sch)
  440 + .calcAllTimeByFcsj(sch);
  441 +
  442 + String nbbm = sch.getClZbh();
  443 + nbbmScheduleMap.put(nbbm, sch);
  444 + nbbm2SEStationMap.put(nbbm, sch.getQdzCode());
  445 + nbbm2SEStationMap.put(nbbm, sch.getZdzCode());
  446 +
  447 + //主键索引
  448 + id2SchedulMap.put(sch.getId(), sch);
  449 + }
  450 +
  451 + public void calcQdzTimePlan(String nbbm){
  452 + schAttrCalculator.calcQdzTimePlan(nbbmScheduleMap.get(nbbm));
  453 + }
  454 +
  455 + /**
  456 + *
  457 + * @Title: nextAll
  458 + * @Description: TODO(之后的所有班次)
  459 + */
  460 + public List<ScheduleRealInfo> nextAll(ScheduleRealInfo sch) {
  461 + List<ScheduleRealInfo> list = nbbmScheduleMap.get(sch.getClZbh());
  462 + // 排序
  463 + Collections.sort(list, schNoComparator);
  464 +
  465 + List<ScheduleRealInfo> rs = new ArrayList<>();
  466 + ScheduleRealInfo temp;
  467 + for (int i = 0; i < list.size() - 1; i++) {
  468 + temp = list.get(i);
  469 + if(temp.getFcsjT() > sch.getFcsjT())
  470 + rs.add(temp);
  471 +
  472 + }
  473 + return rs;
  474 + }
  475 +
  476 + /**
  477 + *
  478 + * @Title: doneSum
  479 + * @Description: TODO(已完成班次总数)
  480 + */
  481 + public int doneSum(String clZbh) {
  482 + List<ScheduleRealInfo> list = nbbmScheduleMap.get(clZbh);
  483 + int rs = 0;
  484 +
  485 + for(ScheduleRealInfo sch : list){
  486 + if(sch.getZdsjActual() != null && !sch.isDestroy())
  487 + rs ++;
  488 + }
  489 + return rs;
  490 + }
  491 +
  492 + /**
  493 + *
  494 + * @Title: validEndTime
  495 + * @Description: TODO(是否是有效的到达时间)
  496 + */
  497 + public boolean validEndTime(ScheduleRealInfo sch, Long ts) {
  498 + if(sch.getFcsjActualTime() != null && sch.getFcsjActualTime() > ts)
  499 + return false;
  500 +
  501 + return validTime(sch, ts);
  502 + }
  503 +
  504 + /**
  505 + *
  506 + * @Title: validStartTime
  507 + * @Description: TODO(是否是合适的发车时间)
  508 + */
  509 + public boolean validStartTime(ScheduleRealInfo sch, Long ts) {
  510 + if(sch.getZdsjActualTime() != null && sch.getZdsjActualTime() < ts)
  511 + return false;
  512 +
  513 + return validTime(sch, ts);
  514 + }
  515 +
  516 + public boolean validTime(ScheduleRealInfo sch, Long ts){
  517 + List<ScheduleRealInfo> list = nbbmScheduleMap.get(sch.getClZbh());
  518 + int ci = list.indexOf(sch);
  519 + ScheduleRealInfo prve, next;
  520 + if(ci > 0){
  521 + //之前班次实际时间不能大于该时间
  522 + for(int i = ci - 1; i >= 0; i --){
  523 + prve = list.get(i);
  524 + if(prve.getZdsjActualTime() != null && prve.getZdsjActualTime() > ts )
  525 + return false;
  526 +
  527 + if(prve.getFcsjActualTime() != null && prve.getFcsjActualTime() > ts)
  528 + return false;
  529 + }
  530 + }
  531 +
  532 + if(ci < list.size() - 1){
  533 + //之后班次实际时间不能小于该时间
  534 + for(int i = ci + 1; i < list.size(); i ++){
  535 + next = list.get(i);
  536 + if(next.getFcsjActualTime() != null && next.getFcsjActualTime() < ts)
  537 + return false;
  538 +
  539 + if(next.getZdsjActualTime() != null && next.getZdsjActualTime() < ts)
  540 + return false;
  541 + }
  542 + }
  543 + return true;
  544 + }
  545 +
  546 + public void save(ScheduleRealInfo sch){
  547 + //schRepository.save(sch);
  548 + pstBuffer.add(sch);
  549 + }
  550 +
  551 + /**
  552 + *
  553 + * @Title: outSch
  554 + * @Description: TODO(出场班次)
  555 + */
  556 +/* public List<ScheduleRealInfo> outSch(String nbbm){
  557 + List<ScheduleRealInfo> all = nbbmScheduleMap.get(nbbm)
  558 + ,outList = new ArrayList<>();
  559 +
  560 + for(ScheduleRealInfo sch : all){
  561 + if(sch.getBcType().equals("out"))
  562 + outList.add(sch);
  563 + }
  564 + return outList;
  565 + }
  566 +
  567 + public ScheduleRealInfo nextOut(String nbbm){
  568 + List<ScheduleRealInfo> list = outSch(nbbm);
  569 + Collections.sort(list, schNoComparator);
  570 + ScheduleRealInfo sch = null;
  571 + for(ScheduleRealInfo temp : list){
  572 + if(temp.getFcsjActual() == null)
  573 + sch = temp;
  574 + }
  575 +
  576 + return sch;
  577 + }*/
  578 +
  579 + /**
  580 + *
  581 + * @Title: nextByBcType
  582 + * @Description: TODO(获取下一个指定班次类型的班次)
  583 + */
  584 + public ScheduleRealInfo nextByBcType(String nbbm, String bcType){
  585 + List<ScheduleRealInfo> list = findByBcType(nbbm, bcType);
  586 + Collections.sort(list, schNoComparator);
  587 + ScheduleRealInfo sch = null;
  588 + for(ScheduleRealInfo temp : list){
  589 + if(temp.getFcsjActual() == null)
  590 + sch = temp;
  591 + }
  592 +
  593 + return sch;
  594 + }
  595 +
  596 + public List<ScheduleRealInfo> findByBcType(String nbbm, String bcType){
  597 + List<ScheduleRealInfo> all = nbbmScheduleMap.get(nbbm)
  598 + ,outList = new ArrayList<>();
  599 +
  600 + for(ScheduleRealInfo sch : all){
  601 + if(sch.getBcType().equals(bcType))
  602 + outList.add(sch);
  603 + }
  604 + return outList;
  605 + }
  606 +
  607 + public ScheduleRealInfo delete(Long id) {
  608 + ScheduleRealInfo sch = id2SchedulMap.get(id);
  609 + if(!sch.isSflj())
  610 + return null;
  611 +
  612 + nbbmScheduleMap.remove(sch.getClZbh(), sch);
  613 + return sch;
  614 + }
  615 +}
src/main/java/com/bsth/data/schedule/SchAttrCalculator.java 0 → 100644
  1 +package com.bsth.data.schedule;
  2 +
  3 +import java.text.ParseException;
  4 +import java.util.Collections;
  5 +import java.util.Date;
  6 +import java.util.List;
  7 +
  8 +import org.slf4j.Logger;
  9 +import org.slf4j.LoggerFactory;
  10 +import org.springframework.beans.factory.annotation.Autowired;
  11 +import org.springframework.stereotype.Component;
  12 +
  13 +import com.bsth.data.LineConfigData;
  14 +import com.bsth.entity.realcontrol.LineConfig;
  15 +import com.bsth.entity.realcontrol.ScheduleRealInfo;
  16 +import com.bsth.util.DateUtils;
  17 +
  18 +/**
  19 + *
  20 + * @ClassName: SchAttrCalculator
  21 + * @Description: TODO(班次相关属性计算器)
  22 + * @author PanZhao
  23 + * @date 2016年8月15日 下午4:40:26
  24 + *
  25 + */
  26 +@Component
  27 +public class SchAttrCalculator {
  28 +
  29 + @Autowired
  30 + LineConfigData lineConfigData;
  31 +
  32 + private final static long DAY_TIME = 1000 * 60 * 60 * 24L;
  33 +
  34 + Logger logger = LoggerFactory.getLogger(this.getClass());
  35 +
  36 + /**
  37 + * @Title: calcRealDate
  38 + * @Description: TODO(计算班次的真实执行日期)
  39 + */
  40 + public SchAttrCalculator calcRealDate(ScheduleRealInfo sch) {
  41 + LineConfig conf = lineConfigData.get(sch.getXlBm());
  42 +
  43 + try {
  44 + if (null == sch.getFcsjT())
  45 + calcFcsjTime(sch);
  46 +
  47 + /*
  48 + * 早于线路开始运营时间的,加一天
  49 + * 如该线路 2点开始运营,2016-08-23的班次,则 2016-08-23 0:25 的班次应该调整成 2016-08-24 0:25
  50 + */
  51 + long st = DateUtils.sdfyyyyMMddHHmm.parse(sch.getScheduleDateStr() + conf.getStartOpt()).getTime();
  52 + if (st > sch.getFcsjT())
  53 + sch.setFcsjAll(sch.getFcsjT() + DAY_TIME);
  54 +
  55 + sch.setRealExecDate(DateUtils.sdfyyyyMMdd.format(new Date(sch.getFcsjT())));
  56 + } catch (Exception e) {
  57 + logger.error("", e);
  58 + }
  59 + return this;
  60 + }
  61 +
  62 + /**
  63 + *
  64 + * @Title: calcAllTimeByFcsj
  65 + * @Description: TODO(根据发车时间字符串计算 (计发时间,终点时间,待发时间))
  66 + */
  67 + public SchAttrCalculator calcAllTimeByFcsj(ScheduleRealInfo sch) {
  68 + try {
  69 + // 生成时间戳
  70 + calcTimestamp(sch);
  71 +
  72 + // 计划终点时间
  73 + if (sch.getBcsj() != null) {
  74 + Date zdDate = new Date(sch.getDfsjT() + (sch.getBcsj() * 60 * 1000));
  75 + sch.setZdsjT(zdDate.getTime());
  76 + sch.setZdsj(DateUtils.sdfHHmm.format(zdDate));
  77 + }
  78 + } catch (ParseException e) {
  79 + logger.error("", e);
  80 + }
  81 + return this;
  82 + }
  83 +
  84 + /**
  85 + *
  86 + * @Title: calcQdzTimePlan
  87 + * @Description: TODO(计算班次的起点应到时间,list 必须是同一辆车的班次)
  88 + */
  89 + public void calcQdzTimePlan(List<ScheduleRealInfo> list){
  90 + Collections.sort(list, new ScheduleComparator.FCNO());
  91 +
  92 + int len = list.size();
  93 + if(len == 0)
  94 + return;
  95 +
  96 + ScheduleRealInfo prve = list.get(0), curr;
  97 + for(int i = 1; i < len; i ++){
  98 + curr = list.get(i);
  99 + if(prve.getZdzName().equals(curr.getQdzName()))
  100 + curr.setQdzArrDateJH(prve.getZdsj());
  101 +
  102 + prve = curr;
  103 + }
  104 + }
  105 +
  106 + public SchAttrCalculator calcFcsjTime(ScheduleRealInfo sch) throws ParseException {
  107 + sch.setFcsjT(DateUtils.sdfyyyyMMddHHmm.parse(sch.getRealExecDate() + sch.getFcsj()).getTime());
  108 + return this;
  109 + }
  110 +
  111 + public void calcTimestamp(ScheduleRealInfo sch) throws ParseException{
  112 + //计发时间
  113 + if(sch.getFcsjT() == null)
  114 + calcFcsjTime(sch);
  115 +
  116 + //待发时间
  117 + if(sch.getDfsj() == null)
  118 + sch.setDfsjAll(sch.getFcsjT());
  119 + if(sch.getDfsjT() == null)
  120 + sch.setDfsjAll(sch.getDfsj());
  121 +
  122 + //实发时间戳
  123 + if(sch.getFcsjActualTime() == null && sch.getFcsjActual() != null)
  124 + sch.setFcsjActualAll(sch.getFcsjActual());
  125 +
  126 + //实达时间戳
  127 + if(sch.getZdsjActualTime() == null && sch.getZdsjActual() != null)
  128 + sch.setZdsjActualAll(sch.getZdsjActual());
  129 + }
  130 +}
src/main/java/com/bsth/data/schedule/ScheduleComparator.java 0 → 100644
  1 +package com.bsth.data.schedule;
  2 +
  3 +import java.util.Comparator;
  4 +
  5 +import com.bsth.entity.realcontrol.ScheduleRealInfo;
  6 +
  7 +/**
  8 + *
  9 + * @ClassName: ScheduleComparator
  10 + * @Description: TODO(实际班次排序器)
  11 + * @author PanZhao
  12 + * @date 2016年8月15日 下午1:53:28
  13 + *
  14 + */
  15 +public class ScheduleComparator {
  16 +
  17 + public static class FCNO implements Comparator<ScheduleRealInfo>{
  18 + @Override
  19 + public int compare(ScheduleRealInfo s1, ScheduleRealInfo s2) {
  20 + return s1.getFcno() - s2.getFcno();
  21 + }
  22 + }
  23 +
  24 + public static class FCSJ implements Comparator<ScheduleRealInfo>{
  25 +
  26 + @Override
  27 + public int compare(ScheduleRealInfo s1, ScheduleRealInfo s2) {
  28 + return (int) (s1.getFcsjT() - s2.getFcsjT());
  29 + }
  30 + }
  31 +}
src/main/java/com/bsth/data/schedule/SchedulePstThread.java 0 → 100644
  1 +package com.bsth.data.schedule;
  2 +
  3 +import java.util.LinkedList;
  4 +
  5 +import org.springframework.beans.factory.annotation.Autowired;
  6 +import org.springframework.stereotype.Component;
  7 +
  8 +import com.bsth.entity.realcontrol.ScheduleRealInfo;
  9 +import com.bsth.repository.realcontrol.ScheduleRealInfoRepository;
  10 +
  11 +/**
  12 + *
  13 + * @ClassName: SchedulePstThread
  14 + * @Description: TODO(班次异步持久化)
  15 + * @author PanZhao
  16 + * @date 2016年8月24日 上午1:47:05
  17 + *
  18 + */
  19 +@Component
  20 +public class SchedulePstThread extends Thread{
  21 +
  22 + @Autowired
  23 + ScheduleRealInfoRepository scheduleRepository;
  24 +
  25 + @Override
  26 + public void run() {
  27 + LinkedList<ScheduleRealInfo> list = DayOfSchedule.pstBuffer;
  28 +
  29 + ScheduleRealInfo schedule;
  30 + for (int i = 0; i < 1000; i++) {
  31 + schedule = list.poll();
  32 + if (null == schedule)
  33 + break;
  34 +
  35 + scheduleRepository.save(schedule);
  36 + }
  37 + }
  38 +}
src/main/java/com/bsth/data/schedule/ScheduleRefreshThread.java 0 → 100644
  1 +package com.bsth.data.schedule;
  2 +
  3 +import java.util.Collection;
  4 +import java.util.Set;
  5 +
  6 +import org.slf4j.Logger;
  7 +import org.slf4j.LoggerFactory;
  8 +import org.springframework.beans.factory.annotation.Autowired;
  9 +import org.springframework.stereotype.Component;
  10 +
  11 +import com.bsth.data.BasicData;
  12 +import com.bsth.data.LineConfigData;
  13 +import com.bsth.data.arrival.ArrivalData_GPS;
  14 +import com.bsth.data.directive.DayOfDirectives;
  15 +import com.bsth.data.pilot80.PilotReport;
  16 +import com.bsth.entity.realcontrol.LineConfig;
  17 +
  18 +/**
  19 + *
  20 + * @ClassName: refreshScheduleThread
  21 + * @Description: TODO(班次刷新线程,用于在营运开始时间切换到当日排班)
  22 + * @author PanZhao
  23 + * @date 2016年8月17日 下午1:23:34
  24 + *
  25 + */
  26 +@Component
  27 +public class ScheduleRefreshThread extends Thread{
  28 +
  29 + @Autowired
  30 + DayOfSchedule dayOfSchedule;
  31 +
  32 + @Autowired
  33 + ArrivalData_GPS arrivalData;
  34 +
  35 + @Autowired
  36 + LineConfigData lineConfs;
  37 +
  38 + @Autowired
  39 + DayOfDirectives dayOfDirectives;
  40 +
  41 + @Autowired
  42 + PilotReport pilotReport;
  43 +
  44 + Logger logger = LoggerFactory.getLogger(ScheduleRefreshThread.class);
  45 +
  46 + @Override
  47 + public void run() {
  48 + try {
  49 + Collection<LineConfig> confs = lineConfs.getAll();
  50 +
  51 + String currSchDate, oldSchDate;
  52 + String lineCode;
  53 + for(LineConfig conf : confs){
  54 + lineCode = conf.getLine().getLineCode();
  55 + oldSchDate = dayOfSchedule.getCurrSchDate().get(lineCode);
  56 + currSchDate = dayOfSchedule.calcSchDate(lineCode);
  57 +
  58 + if(oldSchDate == null || !oldSchDate.equals(currSchDate)){
  59 + logger.info(lineCode + "开始翻班, " + currSchDate);
  60 + //清除进出站数据
  61 + arrivalData.clearRAMData(lineCode);
  62 + //清除指令数据
  63 + Set<String> cars = dayOfSchedule.findCarByLineCode(lineCode);
  64 + for(String car : cars)
  65 + dayOfDirectives.clear(BasicData.deviceId2NbbmMap.inverse().get(car));
  66 + //清除驾驶员上报数据
  67 + pilotReport.clear(lineCode);
  68 +
  69 + //重载排班数据
  70 + dayOfSchedule.reloadSch(lineCode, currSchDate, false);
  71 + logger.info(lineCode + "翻班完成, " + currSchDate + " -班次数量:" + dayOfSchedule.findByLineCode(lineCode).size());
  72 + }
  73 + }
  74 + } catch (Exception e) {
  75 + logger.error("", e);
  76 + }
  77 + }
  78 +}