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 340 \ No newline at end of file
... ...
src/main/java/com/bsth/Application.java
... ... @@ -2,6 +2,10 @@ package com.bsth;
2 2  
3 3 import com.fasterxml.jackson.databind.ObjectMapper;
4 4 import com.fasterxml.jackson.databind.SerializationFeature;
  5 +
  6 +import java.util.concurrent.Executors;
  7 +import java.util.concurrent.ScheduledExecutorService;
  8 +
5 9 import org.springframework.boot.SpringApplication;
6 10 import org.springframework.boot.autoconfigure.SpringBootApplication;
7 11 import org.springframework.boot.builder.SpringApplicationBuilder;
... ... @@ -11,6 +15,8 @@ import org.springframework.context.annotation.Primary;
11 15  
12 16 @SpringBootApplication
13 17 public class Application extends SpringBootServletInitializer {
  18 +
  19 + public static ScheduledExecutorService mainServices = Executors.newScheduledThreadPool(8);
14 20  
15 21 @Override
16 22 protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
... ...
src/main/java/com/bsth/StartCommand.java
1 1 package com.bsth;
2 2  
3 3  
4   -import com.bsth.repository.schedule.CarConfigInfoRepository;
5 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 6 import org.slf4j.Logger;
19 7 import org.slf4j.LoggerFactory;
... ... @@ -21,9 +9,6 @@ import org.springframework.beans.factory.annotation.Autowired;
21 9 import org.springframework.boot.CommandLineRunner;
22 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 23 @Autowired
39 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 29 GpsRealDataRefreshThread gpsRefreshThread;
45 30 @Autowired
46 31 GetSchedulePlanThread getSchedulePlanThread;
... ... @@ -63,11 +48,11 @@ public class StartCommand implements CommandLineRunner{
63 48 CarConfigInfoRepository carConfigInfoRepository;
64 49  
65 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 57 @Override
73 58 public void run(String... arg0){
... ... @@ -78,61 +63,61 @@ public class StartCommand implements CommandLineRunner{
78 63  
79 64 /**
80 65 * 车辆,设备,公司等常用的映射数据,每两小时刷新一次
81   - */
  66 + *//*
82 67 commonRefreshThread.start();
83 68 scheduler.scheduleWithFixedDelay(commonRefreshThread, HOUR_SECOND * 2 , HOUR_SECOND * 2, TimeUnit.SECONDS);
84 69 //等映射数据加载完......睡一会吧
85 70 Thread.sleep(4000);
86 71  
87   - /**
  72 + *//**
88 73 * GPS实时数据更新 线程
89 74 * 每8秒和网关HTTP接口同步一次
90   - */
  75 + *//*
91 76 scheduler.scheduleWithFixedDelay(gpsRefreshThread, 0, 8, TimeUnit.SECONDS);
92 77  
93   - /**
  78 + *//**
94 79 * GPS 监控设备掉线行为
95 80 * 每分钟检测一次
96   - */
  81 + *//*
97 82 scheduler.scheduleWithFixedDelay(gpsOfflineMonitorThread, 60, 60, TimeUnit.SECONDS);
98 83  
99 84  
100   - /**
  85 + *//**
101 86 * 每天 凌晨 2 点 抓取当天实际排班
102   - */
  87 + *//*
103 88 //启动时先run一次
104 89 getSchedulePlanThread.start();
105 90 scheduler.scheduleAtFixedRate(getSchedulePlanThread
106 91 , ((DateUtils.getTimesnight2() + HOUR_TIME * 2) - System.currentTimeMillis()) / 1000
107 92 , 60 * 60 * 24, TimeUnit.SECONDS);
108 93  
109   - /**
  94 + *//**
110 95 * 调度指令两分钟入库一次
111 96 * 指令会缓存在内存,直到收到所有响应再入库
112   - */
  97 + *//*
113 98 //从数据库恢复初始数据
114 99 directiveBuffer.recovery();
115 100 scheduler.scheduleWithFixedDelay(directivePersistenceThread, 20, 60 * 2, TimeUnit.SECONDS);
116 101  
117   - /**
  102 + *//**
118 103 * 每分钟将有变更的班次入库(不包括子任务)
119 104 * 单纯为了提高 线调操作 的响应速度
120   - */
  105 + *//*
121 106 scheduler.scheduleWithFixedDelay(SchedulePersistenceThread, 60 * 1, 60 * 1, TimeUnit.SECONDS);
122 107  
123   - /**
  108 + *//**
124 109 * 每15秒从数据库抓取到离站信息和班次匹配
125 110 * (网关生成的到离站数据也是延迟批量入库,所以缩短该线程执行周期并不会提高 “实际到离站” 的实时性)
126   - */
  111 + *//*
127 112 scheduler.scheduleWithFixedDelay(gpsArrivalStationThread, 35, 15, TimeUnit.SECONDS);
128 113  
129   - /**
  114 + *//**
130 115 * 首个调度指令下发(2分钟运行一次)
131 116 * 每辆车的第一个调度指令由该线程下发
132 117 * 后续班次由 “实际终点到达” 事件触发指令下发
133   - */
  118 + *//*
134 119 scheduler.scheduleWithFixedDelay(firstScheduleIssuedThread, 60 , 60 * 2, TimeUnit.SECONDS);
135   -
  120 + */
136 121  
137 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 65 public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
66 66 //线调webSocket
67 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 3 import org.slf4j.Logger;
4 4 import org.slf4j.LoggerFactory;
... ... @@ -10,9 +10,10 @@ import org.springframework.web.bind.annotation.RestController;
10 10  
11 11 import com.alibaba.fastjson.JSON;
12 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 30 Logger logger = LoggerFactory.getLogger(this.getClass());
30 31  
31 32 @Autowired
32   - DirectiveBuffer directiveBuffer;
  33 + DayOfDirectives dayOfDirectives;
  34 +
  35 + @Autowired
  36 + PilotReport pilotReport;
33 37  
34 38 @RequestMapping(value = "/upstream", method = RequestMethod.POST)
35 39 public String main(@RequestParam String json) {
... ... @@ -37,29 +41,29 @@ public class UpstreamEntrance {
37 41 try {
38 42 JSONObject jsonParam = JSONObject.parseObject(json);
39 43  
40   - // 46和47 调度指令确认
  44 + // 60协议回复
41 45 if (jsonParam.getInteger("operCode") == null && jsonParam.getInteger("status") != null) {
42 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 49 } catch (NumberFormatException e) {
46 50 logger.error("NumberFormatException ,,,,一般是老数据,msgId太大");
47 51 }
48 52 }
49   - // 80协议
  53 + // 80协议上报
50 54 else if (jsonParam.getInteger("operCode") == 0X80) {
51 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 60 } catch (Exception e) {
57 61 logger.error("", e);
58 62 }
59 63 }
60 64 // 64协议 线路切换回复
61 65 else if (jsonParam.getInteger("operCode") == 0X64) {
62   - directiveBuffer.reply64(jsonParam);
  66 + dayOfDirectives.reply64(jsonParam);
63 67 } else
64 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 12 import org.springframework.web.bind.annotation.RestController;
13 13  
14 14 import com.bsth.controller.BaseController;
  15 +import com.bsth.data.BasicData;
  16 +import com.bsth.data.schedule.DayOfSchedule;
15 17 import com.bsth.entity.realcontrol.ScheduleRealInfo;
16 18 import com.bsth.security.util.SecurityUtils;
17 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 20 import com.google.common.base.Splitter;
22 21  
23 22 @RestController
24 23 @RequestMapping("/realSchedule")
25 24 public class ScheduleRealInfoController extends BaseController<ScheduleRealInfo, Long> {
26 25  
27   - @Autowired
28   - GetSchedulePlanThread getSchedulePlanThread;
  26 + /*@Autowired
  27 + GetSchedulePlanThread getSchedulePlanThread;*/
29 28  
30 29 @Autowired
31 30 ScheduleRealInfoService scheduleRealInfoService;
  31 +
  32 + @Autowired
  33 + DayOfSchedule dayOfSchedule;
32 34  
33 35 @RequestMapping(value = "/lines")
34 36 public Map<String, Collection<ScheduleRealInfo>> findByLines(@RequestParam String lines) {
... ... @@ -47,10 +49,10 @@ public class ScheduleRealInfoController extends BaseController&lt;ScheduleRealInfo,
47 49 String userName = SecurityUtils.getCurrentUser().getUserName();
48 50 // 注销之前的绑定
49 51 for (String line : list)
50   - CommonMapped.lineUserMap.get(Integer.parseInt(line)).remove(userName);
  52 + BasicData.lineCode2SocketUserMap.get(line).remove(userName);
51 53 // 重新绑定
52 54 for (String line : list)
53   - CommonMapped.lineUserMap.put(Integer.parseInt(line), userName);
  55 + BasicData.lineCode2SocketUserMap.put(line, userName);
54 56  
55 57 return 0;
56 58 }
... ... @@ -84,7 +86,7 @@ public class ScheduleRealInfoController extends BaseController&lt;ScheduleRealInfo,
84 86 */
85 87 @RequestMapping(value = "/carDeviceMapp", method = RequestMethod.GET)
86 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 233 */
232 234 @RequestMapping(value = "/trustStatus/change", method = RequestMethod.POST)
233 235 public int changeTrustStatus(@RequestParam Integer lineCode, @RequestParam Integer status) {
234   - ScheduleBuffer.trustMap.put(lineCode, status);
  236 + //ScheduleBuffer.trustMap.put(lineCode, status);
235 237 return 200;
236 238 }
237 239  
... ... @@ -243,8 +245,8 @@ public class ScheduleRealInfoController extends BaseController&lt;ScheduleRealInfo,
243 245 * @param @param upDown
244 246 */
245 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 263  
262 264 @RequestMapping(value = "/test/getSch")
263 265 public int getSch(){
264   - getSchedulePlanThread.start();
  266 + //getSchedulePlanThread.start();
265 267 return 1;
266 268 }
267 269  
... ... @@ -285,7 +287,8 @@ public class ScheduleRealInfoController extends BaseController&lt;ScheduleRealInfo,
285 287 */
286 288 @RequestMapping(value = "/lineCode/{lineCode}")
287 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 294 @RequestMapping(value = "/queryUserInfo")
... ... @@ -362,7 +365,12 @@ public class ScheduleRealInfoController extends BaseController&lt;ScheduleRealInfo,
362 365 * @return
363 366 */
364 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 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 32 public Map<String, Object> settRoleModules(@RequestParam Integer roleId,@RequestParam String mIds){
33 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 1 package com.bsth.controller.sys;
2 2  
3 3 import javax.servlet.http.HttpServletRequest;
4   -import javax.servlet.http.HttpServletResponse;
5 4 import javax.servlet.http.HttpSession;
6 5  
7 6 import org.springframework.beans.factory.annotation.Autowired;
8 7 import org.springframework.security.authentication.BadCredentialsException;
9   -import org.springframework.security.core.Authentication;
10   -import org.springframework.security.core.context.SecurityContextHolder;
11 8 import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
12   -import org.springframework.security.web.authentication.logout.SecurityContextLogoutHandler;
13 9 import org.springframework.security.web.authentication.session.SessionAuthenticationException;
14 10 import org.springframework.web.bind.annotation.RequestMapping;
15 11 import org.springframework.web.bind.annotation.RequestParam;
16 12 import org.springframework.web.bind.annotation.RestController;
17   -import org.springframework.web.servlet.ModelAndView;
18 13  
19 14 import com.bsth.controller.BaseController;
20 15 import com.bsth.entity.sys.SysUser;
... ... @@ -51,23 +46,6 @@ public class UserController extends BaseController&lt;SysUser, Integer&gt;{
51 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 49 @RequestMapping("/currentUser")
72 50 public SysUser currentUser(){
73 51 return SecurityUtils.getCurrentUser();
... ...
src/main/java/com/bsth/data/BasicData.java
1   -
2 1 package com.bsth.data;
3 2  
  3 +import java.util.ArrayList;
4 4 import java.util.HashMap;
5 5 import java.util.Iterator;
  6 +import java.util.List;
6 7 import java.util.Map;
  8 +import java.util.concurrent.TimeUnit;
7 9  
8 10 import org.slf4j.Logger;
9 11 import org.slf4j.LoggerFactory;
10 12 import org.springframework.beans.factory.annotation.Autowired;
  13 +import org.springframework.boot.CommandLineRunner;
11 14 import org.springframework.stereotype.Component;
12 15  
  16 +import com.bsth.Application;
13 17 import com.bsth.entity.CarPark;
14 18 import com.bsth.entity.Cars;
15 19 import com.bsth.entity.Line;
16 20 import com.bsth.entity.Station;
  21 +import com.bsth.entity.StationRoute;
17 22 import com.bsth.entity.schedule.CarConfigInfo;
18 23 import com.bsth.repository.CarParkRepository;
19 24 import com.bsth.repository.CarsRepository;
20 25 import com.bsth.repository.LineRepository;
21 26 import com.bsth.repository.StationRepository;
  27 +import com.bsth.repository.StationRouteRepository;
22 28 import com.bsth.repository.schedule.CarConfigInfoRepository;
23 29 import com.google.common.collect.BiMap;
24 30 import com.google.common.collect.HashBiMap;
... ... @@ -33,7 +39,7 @@ import com.google.common.collect.TreeMultimap;
33 39 *
34 40 */
35 41 @Component
36   -public class BasicData {
  42 +public class BasicData implements CommandLineRunner{
37 43  
38 44 //设备号和车辆自编号 (K: 设备编码 ,V:车辆自编号)
39 45 public static BiMap<String, String> deviceId2NbbmMap;
... ... @@ -48,40 +54,34 @@ public class BasicData {
48 54 public static Map<String, Line> nbbm2LineMap;
49 55  
50 56 //线路和用户对照 用于webSocket定向推送消息(用户进入线调时写入数据)
51   - public static TreeMultimap<Integer, String> lineCode2SocketUserMap = TreeMultimap.create();
  57 + public static TreeMultimap<String, String> lineCode2SocketUserMap = TreeMultimap.create();
52 58  
53 59 //线路ID和code 对照
54 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 82 @Component
80   - public static class BasicDataLoader{
  83 + public static class BasicDataLoader extends Thread{
81 84  
82   - public BasicDataLoader() {
83   - }
84   -
85 85 @Autowired
86 86 CarsRepository carsRepository;
87 87  
... ... @@ -97,11 +97,50 @@ public class BasicData {
97 97 @Autowired
98 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 142 * @Title: loadDeviceInfo
103 143 * @Description: TODO(加载设备相关信息)
104   - * @throws
105 144 */
106 145 public void loadDeviceInfo(){
107 146 BiMap<String, String> deviceId2Nbbm = HashBiMap.create();
... ... @@ -120,10 +159,8 @@ public class BasicData {
120 159 }
121 160  
122 161 /**
123   - *
124 162 * @Title: loadStationInfo
125 163 * @Description: TODO(加载站点信息)
126   - * @throws
127 164 */
128 165 public void loadStationInfo(){
129 166 Map<String, String> stationCode2Name = new HashMap<>();
... ... @@ -136,20 +173,23 @@ public class BasicData {
136 173 }
137 174 //停车场
138 175 Iterator<CarPark> iterator2 = carParkRepository.findAll().iterator();
  176 +
  177 + List<String> parkCodes = new ArrayList<>();
  178 +
139 179 CarPark carPark;
140 180 while(iterator2.hasNext()){
141 181 carPark = iterator2.next();
142 182 stationCode2Name.put(carPark.getParkCode(), carPark.getParkName());
  183 +
  184 + parkCodes.add(carPark.getParkCode());
143 185 }
144   -
  186 + parkCodeList = parkCodes;
145 187 stationCode2NameMap = stationCode2Name;
146 188 }
147 189  
148 190 /**
149   - *
150 191 * @Title: loadNbbm2LineInfo
151 192 * @Description: TODO(车辆和线路对照)
152   - * @throws
153 193 */
154 194 public void loadNbbm2LineInfo(){
155 195 Iterator<CarConfigInfo> allIterator = carConfigInfoRepository.findAll().iterator();
... ... @@ -164,23 +204,24 @@ public class BasicData {
164 204 }
165 205  
166 206 /**
167   - *
168 207 * @Title: loadLineInfo
169 208 * @Description: TODO(加载线路相关信息)
170   - * @throws
171 209 */
172 210 public void loadLineInfo(){
173 211 Iterator<Line> iterator = lineRepository.findAll().iterator();
174 212  
175 213 Line line;
176 214 BiMap<Integer, Integer> biMap = HashBiMap.create();
  215 + Map<String, String> code2name = new HashMap<>();
  216 +
177 217 while(iterator.hasNext()){
178 218 line = iterator.next();
179 219 biMap.put(line.getId(), Integer.parseInt(line.getLineCode()));
  220 + code2name.put(line.getLineCode(), line.getName());
180 221 }
181 222  
182 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 17 private String deviceId;
49 18  
  19 + private String nbbm;
  20 +
50 21 /** 站点名称 */
51 22 private String stopName;
52 23  
53   - /**
54   - * 时间戳
55   - */
  24 + /** 时间戳*/
56 25 private Long ts;
57 26  
58   - /**
59   - * 线路编码
60   - */
  27 + /** 线路编码*/
61 28 private String lineCode;
62 29  
63   - /**
64   - * 上下行
65   - */
  30 + /** 上下行*/
66 31 private Integer upDown;
67 32  
68   - /**
69   - * 站点编码
70   - */
  33 + /**站点编码*/
71 34 private String stopNo;
72 35  
73   - /**
74   - * 0: 进 1:出
75   - */
  36 + /** 0: 进 1:出*/
76 37 private Integer inOut;
77 38  
78 39 private Long createDate;
79   -
80   - /**
81   - * 分区字段,当年的第几周
82   - */
  40 +
  41 + /** 是否有效 */
  42 + private boolean enable;
  43 +
  44 + /**分区字段,当年的第几周*/
83 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 84 public String getLineCode() {
86 85 return lineCode;
... ... @@ -157,4 +156,28 @@ public class ArrivalInfo {
157 156 public String getId(){
158 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 3 import java.text.SimpleDateFormat;
4 4 import java.util.Date;
... ... @@ -9,30 +9,26 @@ import org.slf4j.Logger;
9 9 import org.slf4j.LoggerFactory;
10 10  
11 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 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 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 43 * @return Directive60 返回类型
48 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 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 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 57 directive.setOperCode((short) 0x60);
62 58 // 设备号
... ... @@ -86,16 +82,16 @@ public class DirectiveDataFactory {
86 82  
87 83  
88 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 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 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 96 directive.setOperCode((short) 0x60);
101 97 // 设备号
... ... @@ -105,7 +101,7 @@ public class DirectiveDataFactory {
105 101 directive.setMsgId(msgId);
106 102 // 构造数据
107 103 data.setDeviceId(deviceId);
108   - data.setDispatchInstruct(dispatchInstruct);
  104 + data.setDispatchInstruct((short) 0x02);
109 105 data.setTimestamp(timestamp);
110 106 data.setCompanyCode(company);
111 107 data.setMsgId(msgId);
... ... @@ -132,19 +128,19 @@ public class DirectiveDataFactory {
132 128 * @param @param t 时间戳
133 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 136 data.setCityCode(cityCode);
141 137 data.setDeviceId(deviceId);
142 138 //线路编码补满6位数
143   - if(lineCode > 99999){
  139 + if(lineCode > 999999){
144 140 logger.error("线路编码不能超过6位,code:" + lineCode);
145 141 return null;
146 142 }
147   - String lineCodeStr = String.format("%06d", lineCode.toString());
  143 + String lineCodeStr = String.format("%06d", lineCode);
148 144 data.setLineId(lineCodeStr);
149 145  
150 146 change.setDeviceId(deviceId);
... ... @@ -163,24 +159,36 @@ public class DirectiveDataFactory {
163 159 * @param @param lineId 线路ID
164 160 * @throws
165 161 */
166   - public static String createDeviceRefreshData(String deviceId, Integer lineId) {
  162 + public static String createDeviceRefreshData(String deviceId, Integer lineCode) {
167 163 Long t = System.currentTimeMillis();
168   - Map<String, Object> param = new HashMap<String, Object>();
  164 + Map<String, Object> param = new HashMap<>();
169 165 param.put("deviceId", deviceId);
170 166 param.put("timestamp", t);
171 167 param.put("operCode", 0Xc0);
172 168  
173   - Map<String, Object> data = new HashMap<String, Object>();
  169 + Map<String, Object> data = new HashMap<>();
174 170 data.put("operCode2", 0xa1);
175 171 data.put("cityCode", cityCode);
176 172 data.put("deviceId", deviceId);
177 173 data.put("timestamp", t);
178 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 184 data.put("lineVersion", 0);
181 185 data.put("carparkDataVersion", 0);
182 186 param.put("data", data);
183 187  
184 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 3 import java.io.IOException;
4 4  
... ... @@ -17,15 +17,14 @@ import com.bsth.util.ConfigUtil;
17 17  
18 18 /**
19 19 *
20   - * @ClassName: HttpUtils
  20 + * @ClassName: GatewayHttpUtils
21 21 * @Description: TODO(和网关HTTP通讯工具类)
22 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 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 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 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 +}
... ...