Commit 0734f5ef73e25f508a9c80815a28a34c00628719

Authored by mcy123
2 parents 9310b8a5 112c42c9

mcy

Showing 38 changed files with 1974 additions and 1007 deletions
src/main/java/com/bsth/controller/realcontrol/SignalStateController.java 0 → 100644
  1 +package com.bsth.controller.realcontrol;
  2 +
  3 +import com.bsth.data.gpsdata.SignalStateData;
  4 +import com.bsth.data.gpsdata.arrival.entity.SignalState;
  5 +import org.springframework.beans.factory.annotation.Autowired;
  6 +import org.springframework.web.bind.annotation.RequestMapping;
  7 +import org.springframework.web.bind.annotation.RequestParam;
  8 +import org.springframework.web.bind.annotation.RestController;
  9 +
  10 +import java.util.List;
  11 +
  12 +/**
  13 + * Created by panzhao on 2016/12/30.
  14 + */
  15 +@RestController
  16 +@RequestMapping("signalState")
  17 +public class SignalStateController {
  18 +
  19 + @Autowired
  20 + SignalStateData signalStateData;
  21 +
  22 + @RequestMapping("/multi")
  23 + public List<SignalState> findByMultiLine(@RequestParam String idx){
  24 + return signalStateData.get(idx);
  25 + }
  26 +}
... ...
src/main/java/com/bsth/data/BasicData.java
... ... @@ -13,6 +13,7 @@ import org.slf4j.Logger;
13 13 import org.slf4j.LoggerFactory;
14 14 import org.springframework.beans.factory.annotation.Autowired;
15 15 import org.springframework.boot.CommandLineRunner;
  16 +import org.springframework.core.annotation.Order;
16 17 import org.springframework.stereotype.Component;
17 18  
18 19 import java.util.*;
... ... @@ -25,13 +26,14 @@ import java.util.concurrent.TimeUnit;
25 26 * @date 2016年8月10日 下午3:27:45
26 27 */
27 28 @Component
  29 +@Order(value = 1)
28 30 public class BasicData implements CommandLineRunner {
29   -
30   - //公司代码和公司名对照(K: 公司编码,V:公司名)
31   - public static Map<String, String> businessCodeNameMap;
32   -
33   - //分公司公司代码和分公司公司名对照(K: 公司编码+分公司编码,V:分公司公司名)
34   - public static Map<String, String> businessFgsCodeNameMap;
  31 +
  32 + //公司代码和公司名对照(K: 公司编码,V:公司名)
  33 + public static Map<String, String> businessCodeNameMap;
  34 +
  35 + //分公司公司代码和分公司公司名对照(K: 公司编码+分公司编码,V:分公司公司名)
  36 + public static Map<String, String> businessFgsCodeNameMap;
35 37  
36 38 //设备号和车辆自编号 (K: 设备编码 ,V:车辆自编号)
37 39 public static BiMap<String, String> deviceId2NbbmMap;
... ... @@ -39,27 +41,21 @@ public class BasicData implements CommandLineRunner {
39 41 //车辆自编号和公司代码对照 (K: 车辆自编号 ,V:公司代码)
40 42 public static Map<String, String> nbbm2CompanyCodeMap;
41 43  
42   - //站点编码和名称对照,包括停车场 (K: 站点编码 ,V:站点名称)
  44 + //站点编码和名称对照,包括停车场 (K: lineCode_updown_stationCode ,V:站点名称)
43 45 public static Map<String, String> stationCode2NameMap;
44 46  
45 47 //线路起终点对照(线路编码_上下行_起终点) 1024_0_B (1024上行起点)
46   - public static Map<String, String> lineSEPointMap;
  48 + //public static Map<String, String> lineSEPointMap;
47 49  
48 50 //车辆和线路对照
49 51 public static Map<String, Line> nbbm2LineMap;
50 52  
51   - //线路和用户对照 用于webSocket定向推送消息(用户进入线调时写入数据)
52   - //public static TreeMultimap<String, String> lineCode2SocketUserMap = TreeMultimap.create();
53   -
54 53 //线路ID和code 对照
55 54 public static BiMap<Integer, String> lineId2CodeMap;
56 55  
57 56 //线路编码和名称对照
58 57 public static Map<String, String> lineCode2NameMap;
59 58  
60   - //线路编码_站点编码 == 0|1 上下行
61   - //public static Map<String, Integer> lineStationUpDownMap;
62   -
63 59 //停车场
64 60 public static List<String> parkCodeList;
65 61  
... ... @@ -77,7 +73,7 @@ public class BasicData implements CommandLineRunner {
77 73 public static Map<String, String> allPerson;
78 74  
79 75 //站点名和运管处编号 对照
80   - public static Map<String,Integer> stationName2YgcNumber;
  76 + public static Map<String, Integer> stationName2YgcNumber;
81 77  
82 78  
83 79 static Logger logger = LoggerFactory.getLogger(BasicData.class);
... ... @@ -87,7 +83,7 @@ public class BasicData implements CommandLineRunner {
87 83  
88 84 @Override
89 85 public void run(String... arg0) throws Exception {
90   - Application.mainServices.scheduleWithFixedDelay(dataLoader, 2, 2, TimeUnit.HOURS);
  86 + Application.mainServices.scheduleWithFixedDelay(dataLoader, 0, 2, TimeUnit.HOURS);
91 87 }
92 88  
93 89  
... ... @@ -114,7 +110,7 @@ public class BasicData implements CommandLineRunner {
114 110  
115 111 @Autowired
116 112 PersonnelRepository personnelRepository;
117   -
  113 +
118 114 @Autowired
119 115 BusinessRepository businessRepository;
120 116  
... ... @@ -156,47 +152,24 @@ public class BasicData implements CommandLineRunner {
156 152 return 0;
157 153 }
158 154  
159   -
160   -/* private void loadStationRouteInfo() {
161   - Iterator<StationRoute> iterator = stationRouteRepository.findAllEffective().iterator();
162   -
163   - Map<String, String> sePointMap = new HashMap<>();
164   - //lineSEPointMap
165   - Map<String, Integer> map = new HashMap<>();
166   -
167   - StationRoute route;
168   - while (iterator.hasNext()) {
169   - route = iterator.next();
170   - map.put(route.getLineCode() + "_" + route.getStationCode(), route.getDirections());
171   -
172   - if (route.getStationMark() != null &&
173   - (route.getStationMark().equals("B") || route.getStationMark().equals("E"))) {
174   - sePointMap.put(route.getLineCode() + "_"
175   - + route.getDirections()
176   - + "_" + route.getStationMark(), route.getStationCode());
177   - }
178   - }
179   - lineStationUpDownMap = map;
180   - lineSEPointMap = sePointMap;
181   - }*/
182   -
183 155 /**
184 156 * loadBusinessInfo
185 157 * (公司代码公司名对照)
186 158 */
187   - public void loadBusinessInfo(){
188   - Map<String, String> businessMap=new HashMap<String,String>();
189   - Map<String, String> businessFgsMap=new HashMap<String,String>();
190   - Iterator<Business> busIter=businessRepository.findAll().iterator();
191   - Business t;
192   - while(busIter.hasNext()){
193   - t=busIter.next();
194   - businessMap.put(t.getBusinessCode(), t.getBusinessName());
195   - businessFgsMap.put(t.getBusinessCode()+"_"+t.getUpCode(), t.getBusinessName());
196   - }
197   - businessCodeNameMap=businessMap;
198   - businessFgsCodeNameMap=businessFgsMap;
  159 + public void loadBusinessInfo() {
  160 + Map<String, String> businessMap = new HashMap<String, String>();
  161 + Map<String, String> businessFgsMap = new HashMap<String, String>();
  162 + Iterator<Business> busIter = businessRepository.findAll().iterator();
  163 + Business t;
  164 + while (busIter.hasNext()) {
  165 + t = busIter.next();
  166 + businessMap.put(t.getBusinessCode(), t.getBusinessName());
  167 + businessFgsMap.put(t.getBusinessCode() + "_" + t.getUpCode(), t.getBusinessName());
  168 + }
  169 + businessCodeNameMap = businessMap;
  170 + businessFgsCodeNameMap = businessFgsMap;
199 171 }
  172 +
200 173 /**
201 174 * @Title: loadDeviceInfo
202 175 * @Description: TODO(加载设备相关信息)
... ... @@ -223,13 +196,13 @@ public class BasicData implements CommandLineRunner {
223 196 */
224 197 public void loadStationInfo() {
225 198 Map<String, String> stationCode2Name = new HashMap<>();
226   - Iterator<Station> iterator = stationRepository.findAll().iterator();
227   - //站点
228   - Station station;
  199 + Iterator<StationRoute> iterator = stationRouteRepository.findAll().iterator();
  200 + StationRoute sroute;
229 201 while (iterator.hasNext()) {
230   - station = iterator.next();
231   - stationCode2Name.put(station.getStationCod(), station.getStationName());
  202 + sroute = iterator.next();
  203 + stationCode2Name.put(sroute.getLineCode() + "_" + sroute.getDirections() + "_" + sroute.getStationCode(), sroute.getStationName());
232 204 }
  205 +
233 206 //停车场
234 207 Iterator<CarPark> iterator2 = carParkRepository.findAll().iterator();
235 208  
... ... @@ -266,7 +239,7 @@ public class BasicData implements CommandLineRunner {
266 239 * @Title: loadLineInfo
267 240 * @Description: TODO(加载线路相关信息)
268 241 */
269   - public void loadLineInfo(){
  242 + public void loadLineInfo() {
270 243 Iterator<Line> iterator = lineRepository.findAll().iterator();
271 244  
272 245 Line line;
... ... @@ -276,36 +249,36 @@ public class BasicData implements CommandLineRunner {
276 249 Map<String, String> code2SHcode = new HashMap<String, String>();
277 250 Map<String, Integer> tempStationName2YgcNumber = new HashMap<String, Integer>();
278 251  
279   - while(iterator.hasNext()){
  252 + while (iterator.hasNext()) {
280 253 line = iterator.next();
281 254 biMap.put(line.getId(), line.getLineCode());
282 255 code2name.put(line.getLineCode(), line.getName());
283   - id2SHcode.put(line.getId(),line.getShanghaiLinecode());
  256 + id2SHcode.put(line.getId(), line.getShanghaiLinecode());
284 257 code2SHcode.put(line.getLineCode(), line.getShanghaiLinecode());
285 258  
286 259 /**
287 260 * 加载运管处的站点及序号
288 261 * 上行从1开始,下行顺序续编
289 262  
290   - List<Object[]> ygcLines = stationRouteRepository.findAllLineWithYgc();
291   - if(ygcLines != null && ygcLines.size() > 0){
292   - int size = ygcLines.size();
293   - Object[] tempArray ;
294   - int num = 1;
295   - String key;
296   - String lineCode = "";
297   - for (int i = 0; i < size; i ++){
298   - tempArray = ygcLines.get(i);
299   - if(lineCode.equals("")){
300   - lineCode = tempArray[0]+"";
301   - }else if(!lineCode.equals(tempArray[0]+"")){
302   - num = 1;
303   - lineCode = tempArray[0]+"";
304   - }
305   - key = tempArray[0] + "_"+tempArray[1] + "_"+tempArray[2];
306   - tempStationName2YgcNumber.put(key,num++);
307   - }
308   - }*/
  263 + List<Object[]> ygcLines = stationRouteRepository.findAllLineWithYgc();
  264 + if(ygcLines != null && ygcLines.size() > 0){
  265 + int size = ygcLines.size();
  266 + Object[] tempArray ;
  267 + int num = 1;
  268 + String key;
  269 + String lineCode = "";
  270 + for (int i = 0; i < size; i ++){
  271 + tempArray = ygcLines.get(i);
  272 + if(lineCode.equals("")){
  273 + lineCode = tempArray[0]+"";
  274 + }else if(!lineCode.equals(tempArray[0]+"")){
  275 + num = 1;
  276 + lineCode = tempArray[0]+"";
  277 + }
  278 + key = tempArray[0] + "_"+tempArray[1] + "_"+tempArray[2];
  279 + tempStationName2YgcNumber.put(key,num++);
  280 + }
  281 + }*/
309 282 }
310 283  
311 284 lineId2CodeMap = biMap;
... ...
src/main/java/com/bsth/data/LineConfigData.java
... ... @@ -10,6 +10,7 @@ import org.slf4j.Logger;
10 10 import org.slf4j.LoggerFactory;
11 11 import org.springframework.beans.factory.annotation.Autowired;
12 12 import org.springframework.boot.CommandLineRunner;
  13 +import org.springframework.core.annotation.Order;
13 14 import org.springframework.stereotype.Component;
14 15  
15 16 import java.util.*;
... ... @@ -23,6 +24,7 @@ import java.util.*;
23 24 *
24 25 */
25 26 @Component
  27 +@Order(value = 2)
26 28 public class LineConfigData implements CommandLineRunner {
27 29  
28 30 Logger logger = LoggerFactory.getLogger(this.getClass());
... ...
src/main/java/com/bsth/data/gpsdata/GpsEntity.java
... ... @@ -86,7 +86,7 @@ public class GpsEntity {
86 86 private StationRoute station;
87 87  
88 88 /** 状态 */
89   - private String signalState;
  89 + private String signalState = "normal";
90 90  
91 91 public Integer getCompanyCode() {
92 92 return companyCode;
... ...
src/main/java/com/bsth/data/gpsdata/GpsRealData.java
... ... @@ -2,7 +2,6 @@ package com.bsth.data.gpsdata;
2 2  
3 3 import com.alibaba.fastjson.JSON;
4 4 import com.alibaba.fastjson.JSONObject;
5   -import com.bsth.Application;
6 5 import com.bsth.data.BasicData;
7 6 import com.bsth.data.forecast.ForecastRealServer;
8 7 import com.bsth.data.gpsdata.arrival.GpsRealAnalyse;
... ... @@ -26,7 +25,6 @@ import org.springframework.stereotype.Component;
26 25 import java.io.BufferedReader;
27 26 import java.io.InputStreamReader;
28 27 import java.util.*;
29   -import java.util.concurrent.TimeUnit;
30 28  
31 29 /**
32 30 * @author PanZhao
... ... @@ -67,12 +65,23 @@ public class GpsRealData implements CommandLineRunner {
67 65  
68 66 @Override
69 67 public void run(String... arg0) throws Exception {
70   - logger.info("gpsDataLoader,40,6");
71   - Application.mainServices.scheduleWithFixedDelay(gpsDataLoader, 40, 6, TimeUnit.SECONDS);
  68 + logger.info("gpsDataLoader,20,5");
  69 + //Application.mainServices.scheduleWithFixedDelay(gpsDataLoader, 20, 6, TimeUnit.SECONDS);
72 70 }
73 71  
74 72 public void put(GpsEntity gps) {
75   - gpsMap.put(gps.getDeviceId(), gps);
  73 + String device = gps.getDeviceId();
  74 + gpsMap.put(device, gps);
  75 +
  76 + if (StringUtils.isNotBlank(gps.getLineId())){
  77 + //站点名称
  78 + gps.setStationName(getStationName(gps));
  79 + lineCode2Devices.put(gps.getLineId(), device);
  80 + }
  81 + }
  82 +
  83 + public String getStationName(GpsEntity gps){
  84 + return BasicData.stationCode2NameMap.get(gps.getLineId() + "_" + gps.getUpDown() + gps.getStopNo());
76 85 }
77 86  
78 87 /**
... ... @@ -197,6 +206,8 @@ public class GpsRealData implements CommandLineRunner {
197 206 gps.setNbbm(nbbm);
198 207 //有更新的点位
199 208 updateList.add(gps);
  209 + //实时GPS数据集
  210 + gpsRealData.put(gps);
200 211 }
201 212 //分析数据
202 213 gpsRealAnalyse.analyse(updateList);
... ...
src/main/java/com/bsth/data/gpsdata/SignalStateData.java 0 → 100644
  1 +package com.bsth.data.gpsdata;
  2 +
  3 +import com.bsth.data.gpsdata.arrival.entity.SignalState;
  4 +import com.bsth.websocket.handler.SendUtils;
  5 +import com.google.common.base.Splitter;
  6 +import com.google.common.collect.ArrayListMultimap;
  7 +import org.springframework.beans.factory.annotation.Autowired;
  8 +import org.springframework.stereotype.Component;
  9 +
  10 +import java.util.ArrayList;
  11 +import java.util.List;
  12 +
  13 +/**
  14 + * 信号状态数据
  15 + * Created by panzhao on 2016/12/30.
  16 + */
  17 +@Component
  18 +public class SignalStateData {
  19 +
  20 + @Autowired
  21 + SendUtils sendUtils;
  22 +
  23 + private static ArrayListMultimap<String, SignalState> listMultimap = ArrayListMultimap.create();
  24 +
  25 + public void put(SignalState state){
  26 + listMultimap.put(state.getLineCode(), state);
  27 + //推送到客户端
  28 + sendUtils.sendSignalState(state);
  29 + }
  30 +
  31 + public List<SignalState> get(String idx){
  32 + List<SignalState> rs = new ArrayList<>();
  33 + List<String> ids = Splitter.on(",").splitToList(idx);
  34 +
  35 + for(String lineCode : ids){
  36 + rs.addAll(listMultimap.get(lineCode));
  37 + }
  38 + return rs;
  39 + }
  40 +}
... ...
src/main/java/com/bsth/data/gpsdata/arrival/GeoCacheData.java
... ... @@ -29,8 +29,8 @@ public class GeoCacheData {
29 29  
30 30 static Logger logger = LoggerFactory.getLogger(GeoCacheData.class);
31 31  
32   - //每辆车缓存最后500条gps
33   - private static final int CACHE_SIZE = 500;
  32 + //每辆车缓存最后1000条gps
  33 + private static final int CACHE_SIZE = 1000;
34 34 private static Map<String, CircleQueue<GpsEntity>> gpsCacheMap = new HashMap<>();
35 35  
36 36 //线路路段走向
... ... @@ -75,7 +75,7 @@ public class GeoCacheData {
75 75 }
76 76 }
77 77  
78   - public static StationRoute getRouteCode(GpsEntity gps){
  78 + public static StationRoute getRouteCode(GpsEntity gps) {
79 79 return routeCodeMap.get(gps.getLineId() + "_" + gps.getUpDown() + "_" + gps.getStopNo());
80 80 }
81 81  
... ... @@ -94,6 +94,21 @@ public class GeoCacheData {
94 94 return null;
95 95 }
96 96  
  97 + public static List<StationRoute> midwayStation(String lineCode, int directions, String sCode, String eCode) {
  98 + List<StationRoute> list = getStationRoute(lineCode, directions), rs = new ArrayList<>();
  99 +
  100 + boolean flag = false;
  101 + for (StationRoute sr : list) {
  102 + if (flag)
  103 + rs.add(sr);
  104 + if (sr.getCode().equals(sCode))
  105 + flag = true;
  106 + else if (sr.getCode().equals(eCode))
  107 + break;
  108 + }
  109 + return rs;
  110 + }
  111 +
97 112 public static Polygon getTccPolygon(String code) {
98 113 return tccMap.get(code);
99 114 }
... ... @@ -191,4 +206,16 @@ public class GeoCacheData {
191 206 }
192 207 return cds;
193 208 }
  209 +
  210 + /**
  211 + * 是不是终点站
  212 + * @param lineId
  213 + * @param upDown
  214 + * @param stationCode
  215 + * @return
  216 + */
  217 + public static boolean isEndStation(String lineId, Integer upDown, String stationCode) {
  218 + StationRoute station = routeCodeMap.get(lineId + "_" + upDown + "_" + stationCode);
  219 + return station != null && station.getMark().equals("E");
  220 + }
194 221 }
195 222 \ No newline at end of file
... ...
src/main/java/com/bsth/data/gpsdata/arrival/SignalHandle.java
1 1 package com.bsth.data.gpsdata.arrival;
2 2  
3 3 import com.bsth.data.gpsdata.GpsEntity;
  4 +import com.bsth.data.gpsdata.arrival.entity.StationRoute;
4 5 import com.bsth.data.gpsdata.arrival.utils.CircleQueue;
  6 +import com.bsth.data.gpsdata.arrival.utils.GeoUtils;
  7 +import com.bsth.entity.realcontrol.ScheduleRealInfo;
  8 +
  9 +import java.util.List;
5 10  
6 11 /**
7 12 * Created by panzhao on 2016/12/27.
... ... @@ -14,64 +19,71 @@ public abstract class SignalHandle {
14 19 return prevs != null && prevs.size() > 0 && prevs.getTail() != null;
15 20 }
16 21  
  22 + protected boolean isDriftSignal(GpsEntity gps) {
  23 + return gps.getLat() == 0 || gps.getLon() == 0;
  24 + }
  25 +
17 26 /**
18 27 * 是不是异常信号
19 28 *
20 29 * @param gps
21   - * @return
22   - */
23   - protected boolean isAbnormal(GpsEntity gps) {
24   - return gps.getLat() == 0 || gps.getLon() == 0;
25   - }
  30 + * @return protected boolean isAbnormal(GpsEntity gps) {
  31 + return gps.getLat() == 0 || gps.getLon() == 0;
  32 + }*/
26 33  
27 34 /**
28 35 * 连续异常信号个数统计
29 36 *
30 37 * @param prevs
31   - * @return
  38 + * @return protected int abnormalCount(CircleQueue<GpsEntity> prevs) {
  39 + * int count = 0;
  40 + * <p>
  41 + * if (!isNotEmpty(prevs))
  42 + * return count;
  43 + * <p>
  44 + * GpsEntity[] array = (GpsEntity[]) prevs.getQueue();
  45 + * GpsEntity gps;
  46 + * for (int i = array.length - 1; i > 0; i--) {
  47 + * gps = array[i];
  48 + * <p>
  49 + * if (isAbnormal(gps))
  50 + * count++;
  51 + * else
  52 + * break;
  53 + * }
  54 + * <p>
  55 + * return count;
  56 + * }
32 57 */
33   - protected int abnormalCount(CircleQueue<GpsEntity> prevs) {
34   - int count = 0;
35 58  
36   - if (!isNotEmpty(prevs))
37   - return count;
38   -
39   - GpsEntity[] array = (GpsEntity[]) prevs.getQueue();
40   - GpsEntity gps;
41   - for (int i = array.length - 1; i > 0; i--) {
42   - gps = array[i];
43   -
44   - if (isAbnormal(gps))
45   - count++;
46   - else
47   - break;
  59 + protected void transformUpdown(GpsEntity gps, ScheduleRealInfo sch) {
  60 + int updown = Integer.parseInt(sch.getXlDir());
  61 + List<StationRoute> srs = GeoCacheData.getStationRoute(sch.getXlBm(), updown);
  62 + StationRoute station = GeoUtils.gpsInStation(gps, srs);
  63 + if (station != null) {
  64 + gps.setUpDown(updown);
  65 + gps.setStopNo(station.getCode());
48 66 }
49   -
50   - return count;
51 67 }
52 68  
53 69 /**
54   - * 车辆运行轨迹(最近20分钟)
55   - * 0:上行 1:下行 -1:未知
  70 + * 是否是从异常状态恢复的第一个信号
56 71 *
57 72 * @param gps
  73 + * @param prevs
58 74 * @return
59 75 */
60   - protected int runTrack(GpsEntity gps, CircleQueue<GpsEntity> prevs) {
61   - int rs = -1, count = 0;
62   -
63   - long et = gps.getTimestamp() - (1000 * 60 * 20);
64   - Object[] array = prevs.getQueue();
65   - GpsEntity prev;
66   - for(Object obj : array){
67   - prev = (GpsEntity) obj;
68   - if(prev.getTimestamp() < et)
69   - break;
70   -
  76 + protected boolean abnormalRecovery(GpsEntity gps, CircleQueue<GpsEntity> prevs) {
  77 + if (prevs == null || prevs.size() == 0)
  78 + return false;
71 79  
  80 + GpsEntity prev = prevs.getTail();
  81 + //从漂移状态恢复
  82 + if (isDriftSignal(prev)
  83 + && !isDriftSignal(gps)) {
  84 + return true;
72 85 }
73   - //for()
74   - return 0;
75   - }
76 86  
77   -}
  87 + return false;
  88 + }
  89 +}
78 90 \ No newline at end of file
... ...
src/main/java/com/bsth/data/gpsdata/arrival/entity/RouteReverse.java
... ... @@ -5,6 +5,7 @@ package com.bsth.data.gpsdata.arrival.entity;
5 5 */
6 6 public class RouteReverse {
7 7  
  8 + private String nbbm;
8 9 //反转个数
9 10 private int count;
10 11  
... ... @@ -14,18 +15,18 @@ public class RouteReverse {
14 15 //掉头站点
15 16 private String turned;
16 17  
17   - //开始时间
18   - private long st;
19   -
20 18 //掉头时间
21 19 private long zt;
22 20  
23   - //结束时间
24   - private long et;
  21 + //检测时间
  22 + private long ct;
25 23  
26 24 //是否闭合
27 25 private boolean close;
28 26  
  27 + //信号不明确
  28 + private boolean vague;
  29 +
29 30 public int getCount() {
30 31 return count;
31 32 }
... ... @@ -50,22 +51,6 @@ public class RouteReverse {
50 51 this.turned = turned;
51 52 }
52 53  
53   - public long getSt() {
54   - return st;
55   - }
56   -
57   - public void setSt(long st) {
58   - this.st = st;
59   - }
60   -
61   - public long getEt() {
62   - return et;
63   - }
64   -
65   - public void setEt(long et) {
66   - this.et = et;
67   - }
68   -
69 54 public boolean isClose() {
70 55 return close;
71 56 }
... ... @@ -81,4 +66,28 @@ public class RouteReverse {
81 66 public void setZt(long zt) {
82 67 this.zt = zt;
83 68 }
84   -}
  69 +
  70 + public long getCt() {
  71 + return ct;
  72 + }
  73 +
  74 + public void setCt(long ct) {
  75 + this.ct = ct;
  76 + }
  77 +
  78 + public String getNbbm() {
  79 + return nbbm;
  80 + }
  81 +
  82 + public void setNbbm(String nbbm) {
  83 + this.nbbm = nbbm;
  84 + }
  85 +
  86 + public boolean isVague() {
  87 + return vague;
  88 + }
  89 +
  90 + public void setVague(boolean vague) {
  91 + this.vague = vague;
  92 + }
  93 +}
85 94 \ No newline at end of file
... ...
src/main/java/com/bsth/data/gpsdata/arrival/entity/SignalAbnormal.java 0 → 100644
  1 +package com.bsth.data.gpsdata.arrival.entity;
  2 +
  3 +/**
  4 + * 班次信号异常(漂移 或 断线)
  5 + * Created by panzhao on 2016/12/31.
  6 + */
  7 +public class SignalAbnormal {
  8 +
  9 + private Long et;
  10 +
  11 + /** drift or reconnection */
  12 + private String abnormalType;
  13 +
  14 + private Long st;
  15 +
  16 + private String nearPoint;
  17 +
  18 + private String destCode;
  19 +
  20 + private Long ct;
  21 +
  22 + //0: 发车 1:到站
  23 + private int outOrIn;
  24 +
  25 + public Long getEt() {
  26 + return et;
  27 + }
  28 +
  29 + public void setEt(Long et) {
  30 + this.et = et;
  31 + }
  32 +
  33 + public String getAbnormalType() {
  34 + return abnormalType;
  35 + }
  36 +
  37 + public void setAbnormalType(String abnormalType) {
  38 + this.abnormalType = abnormalType;
  39 + }
  40 +
  41 + public Long getSt() {
  42 + return st;
  43 + }
  44 +
  45 + public void setSt(Long st) {
  46 + this.st = st;
  47 + }
  48 +
  49 + public String getNearPoint() {
  50 + return nearPoint;
  51 + }
  52 +
  53 + public void setNearPoint(String nearPoint) {
  54 + this.nearPoint = nearPoint;
  55 + }
  56 +
  57 + public Long getCt() {
  58 + return ct;
  59 + }
  60 +
  61 + public void setCt(Long ct) {
  62 + this.ct = ct;
  63 + }
  64 +
  65 + public int getOutOrIn() {
  66 + return outOrIn;
  67 + }
  68 +
  69 + public void setOutOrIn(int outOrIn) {
  70 + this.outOrIn = outOrIn;
  71 + }
  72 +
  73 + public String getDestCode() {
  74 + return destCode;
  75 + }
  76 +
  77 + public void setDestCode(String destCode) {
  78 + this.destCode = destCode;
  79 + }
  80 +}
... ...
src/main/java/com/bsth/data/gpsdata/arrival/entity/SignalState.java 0 → 100644
  1 +package com.bsth.data.gpsdata.arrival.entity;
  2 +
  3 +import com.bsth.data.BasicData;
  4 +import com.bsth.entity.realcontrol.ScheduleRealInfo;
  5 +import org.joda.time.format.DateTimeFormat;
  6 +import org.joda.time.format.DateTimeFormatter;
  7 +
  8 +/**
  9 + * 信号状态
  10 + * Created by panzhao on 2016/12/30.
  11 + */
  12 +public class SignalState {
  13 +
  14 + private String type;
  15 +
  16 + private Long st;
  17 +
  18 + //private Long checkTime;
  19 +
  20 + private Long schId;
  21 +
  22 + private String lineCode;
  23 +
  24 + private String text;
  25 +
  26 + private RouteReverse reverse;
  27 +
  28 + private SignalAbnormal signalAbnormal;
  29 +
  30 + private static DateTimeFormatter fmtHHmm = DateTimeFormat.forPattern("HH:mm");
  31 +
  32 + /**
  33 + * 记录区间调头
  34 + *
  35 + * @param sch
  36 + * @param reverse
  37 + * @return
  38 + */
  39 + public static SignalState reverseSignalSTate(ScheduleRealInfo sch, RouteReverse reverse) {
  40 + if(reverse.isVague())
  41 + return null;
  42 +
  43 + SignalState state = new SignalState();
  44 + state.setSchId(sch.getId());
  45 + state.setType("route_reverse");
  46 + //state.setCheckTime(System.currentTimeMillis());
  47 +
  48 + String stationName = BasicData.stationCode2NameMap.get(sch.getXlBm() + "_" + sch.getXlDir() + "_" + reverse.getTurned());
  49 + state.setText(fmtHHmm.print(reverse.getZt()) + " 从 " + stationName + " 站掉头");
  50 + state.setSt(sch.getFcsjActualTime());
  51 + state.setLineCode(sch.getXlBm());
  52 + state.setReverse(reverse);
  53 + return state;
  54 + }
  55 +
  56 + public static SignalState abnormalSignalSTate(ScheduleRealInfo sch, SignalAbnormal signalAbnormal) {
  57 + SignalState state = new SignalState();
  58 + state.setSchId(sch.getId());
  59 + state.setType("abnormal_signal");
  60 + //state.setCheckTime(signalAbnormal.getCt());
  61 + state.setLineCode(sch.getXlBm());
  62 +
  63 + String text = (fmtHHmm.print(signalAbnormal.getSt()) + " ~ " + fmtHHmm.print(signalAbnormal.getEt()));
  64 + String abnormType = signalAbnormal.getAbnormalType();
  65 + if (abnormType.equals("drift"))
  66 + text += "(GPS无效)";
  67 + else if (abnormType.equals("reconnection"))
  68 + text += "(信号丢失)";
  69 +
  70 + state.setText(text);
  71 + state.setSignalAbnormal(signalAbnormal);
  72 + return state;
  73 + }
  74 +
  75 + public String getType() {
  76 + return type;
  77 + }
  78 +
  79 + public void setType(String type) {
  80 + this.type = type;
  81 + }
  82 +
  83 + public long getSchId() {
  84 + return schId;
  85 + }
  86 +
  87 + public void setSchId(long schId) {
  88 + this.schId = schId;
  89 + }
  90 +
  91 + public String getLineCode() {
  92 + return lineCode;
  93 + }
  94 +
  95 + public void setLineCode(String lineCode) {
  96 + this.lineCode = lineCode;
  97 + }
  98 +
  99 + public Long getSt() {
  100 + return st;
  101 + }
  102 +
  103 + public void setSt(Long st) {
  104 + this.st = st;
  105 + }
  106 +
  107 + public String getText() {
  108 + return text;
  109 + }
  110 +
  111 + public void setText(String text) {
  112 + this.text = text;
  113 + }
  114 +
  115 + public RouteReverse getReverse() {
  116 + return reverse;
  117 + }
  118 +
  119 + public void setReverse(RouteReverse reverse) {
  120 + this.reverse = reverse;
  121 + }
  122 +
  123 + public SignalAbnormal getSignalAbnormal() {
  124 + return signalAbnormal;
  125 + }
  126 +
  127 + public void setSignalAbnormal(SignalAbnormal signalAbnormal) {
  128 + this.signalAbnormal = signalAbnormal;
  129 + }
  130 +}
... ...
src/main/java/com/bsth/data/gpsdata/arrival/handlers/InOutStationSignalHandle.java
... ... @@ -2,23 +2,21 @@ package com.bsth.data.gpsdata.arrival.handlers;
2 2  
3 3 import com.bsth.data.LineConfigData;
4 4 import com.bsth.data.gpsdata.GpsEntity;
5   -import com.bsth.data.gpsdata.arrival.GeoCacheData;
6 5 import com.bsth.data.gpsdata.arrival.SignalHandle;
7   -import com.bsth.data.gpsdata.arrival.entity.StationRoute;
8 6 import com.bsth.data.gpsdata.arrival.utils.CircleQueue;
9   -import com.bsth.data.gpsdata.arrival.utils.GeoUtils;
  7 +import com.bsth.data.gpsdata.arrival.utils.ScheduleSignalState;
  8 +import com.bsth.data.gpsdata.arrival.utils.SignalSchPlanMatcher;
10 9 import com.bsth.data.schedule.DayOfSchedule;
11 10 import com.bsth.entity.realcontrol.LineConfig;
12 11 import com.bsth.entity.realcontrol.ScheduleRealInfo;
13 12 import com.bsth.service.directive.DirectiveService;
14 13 import com.bsth.websocket.handler.SendUtils;
  14 +import org.apache.commons.lang3.StringUtils;
15 15 import org.slf4j.Logger;
16 16 import org.slf4j.LoggerFactory;
17 17 import org.springframework.beans.factory.annotation.Autowired;
18 18 import org.springframework.stereotype.Component;
19 19  
20   -import java.util.List;
21   -
22 20 /**
23 21 * 进出站动作处理
24 22 * Created by panzhao on 2016/12/27.
... ... @@ -40,8 +38,25 @@ public class InOutStationSignalHandle extends SignalHandle{
40 38 @Autowired
41 39 DirectiveService directiveService;
42 40  
  41 + @Autowired
  42 + ScheduleSignalState scheduleSignalState;
  43 +
  44 + @Autowired
  45 + SignalSchPlanMatcher signalSchPlanMatcher;
  46 +
  47 + private final static int MAX_BEFORE_TIME = 1000 * 60 * 72;
  48 +
43 49 @Override
44 50 public boolean handle(GpsEntity gps, CircleQueue<GpsEntity> prevs) {
  51 + //忽略漂移信号
  52 + if(isDriftSignal(gps))
  53 + return false;
  54 +
  55 + //从异常状态恢复的第一个信号
  56 + if(abnormalRecovery(gps, prevs)){
  57 + //回溯一下之前的轨迹
  58 + scheduleSignalState.signalRetrospect(gps);
  59 + }
45 60  
46 61 if(isNotEmpty(prevs)){
47 62 GpsEntity prev = prevs.getTail();
... ... @@ -91,13 +106,23 @@ public class InOutStationSignalHandle extends SignalHandle{
91 106 ScheduleRealInfo sch = dayOfSchedule.executeCurr(gps.getNbbm());
92 107 String qdzCode = sch.getQdzCode();
93 108  
94   -
95   - //if(sch.getFcsjActual() != )
  109 + //首班出场最多提前1.2小时
  110 + if(dayOfSchedule.isFirstOut(sch) && sch.getDfsjT() - gps.getTimestamp() > MAX_BEFORE_TIME)
  111 + return;
96 112  
97 113 //起点发车
98 114 if(qdzCode != null && prev.getStopNo().equals(qdzCode)
99 115 && !willDepart(gps, prev, sch)){
100 116  
  117 + //发车班次匹配
  118 + signalSchPlanMatcher.outMatch(gps, sch);
  119 + sch = dayOfSchedule.executeCurr(gps.getNbbm());
  120 +
  121 + //实发时间不覆盖
  122 + if(StringUtils.isNotEmpty(sch.getFcsjActual()))
  123 + return;
  124 +
  125 + //实发时间
101 126 sch.setFcsjActualAll(gps.getTimestamp());
102 127 //通知客户端
103 128 sendUtils.sendFcsj(sch);
... ... @@ -108,16 +133,27 @@ public class InOutStationSignalHandle extends SignalHandle{
108 133 outStationAndOutPark(sch);
109 134 logger.info("班次:" + sch.getDfsj() + "发车, 时间:" + sch.getFcsjActual());
110 135 }
  136 + else if(sch.getBcType().equals("out")){
  137 + ScheduleRealInfo next = dayOfSchedule.nextSame(sch);
  138 + if(prev.getStopNo().equals(next.getQdzCode())){
  139 + //发下一个班次
  140 + dayOfSchedule.addExecPlan(next);
  141 + outStation(gps, prev);
  142 + }
  143 + }
111 144 }
112 145  
  146 +
113 147 private void outStationAndOutPark(ScheduleRealInfo sch){
114 148 LineConfig config = lineConfigData.get(sch.getXlBm());
115 149 if (config != null && config.getOutConfig() == 2) {
116 150 //出站既出场
117 151 ScheduleRealInfo schPrev = dayOfSchedule.prev(sch);
118 152 if (schPrev != null && schPrev.getBcType().equals("out")) {
119   - schPrev.setFcsjActualAll(sch.getFcsjActual());
120   - schPrev.setZdsjActualAll(sch.getFcsjActual());
  153 + schPrev.setFcsjActualAll(sch.getFcsjActualTime());
  154 + schPrev.setZdsjActualAll(sch.getFcsjActualTime());
  155 +
  156 + sendUtils.refreshSch(schPrev);
121 157 }
122 158 }
123 159 }
... ... @@ -129,9 +165,12 @@ public class InOutStationSignalHandle extends SignalHandle{
129 165 */
130 166 private void inStation(GpsEntity gps, GpsEntity prev){
131 167 ScheduleRealInfo sch = dayOfSchedule.executeCurr(gps.getNbbm());
132   - String zdzCode = sch.getZdzCode();
133 168  
134   - if(zdzCode != null && gps.getStopNo().equals(zdzCode)){
  169 + if(gps.getStopNo().equals(sch.getZdzCode())){
  170 +
  171 + //实达时间不覆盖
  172 + if(StringUtils.isNotEmpty(sch.getZdsjActual()))
  173 + return;
135 174  
136 175 sch.setZdsjActualAll(gps.getTimestamp());
137 176 //已完成班次数
... ... @@ -142,33 +181,22 @@ public class InOutStationSignalHandle extends SignalHandle{
142 181 //持久化
143 182 dayOfSchedule.save(sch);
144 183 //下发调度指令
145   - //directiveService.send60Dispatch(next, doneSum, "到站@系统");
  184 + directiveService.send60Dispatch(next, doneSum, "到站@系统");
146 185  
147 186 //准备执行下一个班次
148 187 if (next != null) {
149 188 next.setQdzArrDatesj(sch.getZdsjActual());
150 189 dayOfSchedule.addExecPlan(next);
151   -
152 190 //进站既进场
153 191 inStationAndInPark(sch, next);
154   -
155 192 //将gps转换为下一个班次走向的站内信号
156   - int updown = Integer.parseInt(next.getXlDir());
157   - List<StationRoute> srs = GeoCacheData.getStationRoute(next.getXlBm(), updown);
158   - StationRoute station = GeoUtils.gpsInStation(gps, srs);
159   - if (station != null) {
160   - gps.setUpDown(updown);
161   - gps.setStopNo(station.getCode());
162   - }
  193 + transformUpdown(gps, sch);
163 194 }
164 195 }
165   - /* //如果出场班次计划终点时间5分钟后还未完成,检查一下车辆轨迹,是否已经在执行线路上班次
166   - else if(sch.getBcType().equals("out")
167   - && sch.getZdsj() != null
168   - && gps.getTimestamp() - sch.getZdsjT() >= 1000 * 60 * 5){
169   - logger.info("出场班次计划终点时间5分钟后还未完成");
170   -
171   - }*/
  196 + else if(sch.getFcsjActual() == null){
  197 + //有进站,但班次没有实发,向前追溯一下信号
  198 + scheduleSignalState.signalRetrospect(gps, sch);
  199 + }
172 200 }
173 201  
174 202 /**
... ... @@ -179,8 +207,10 @@ public class InOutStationSignalHandle extends SignalHandle{
179 207 LineConfig config = lineConfigData.get(sch.getXlBm());
180 208 if (next.getBcType().equals("in") &&
181 209 config != null && config.getOutConfig() == 2) {
182   - next.setFcsjActualAll(sch.getZdsjActual());
183   - next.setZdsjActualAll(sch.getZdsjActual());
  210 + next.setFcsjActualAll(sch.getZdsjActualTime());
  211 + next.setZdsjActualAll(sch.getZdsjActualTime());
  212 +
  213 + sendUtils.refreshSch(next);
184 214 }
185 215 }
186 216  
... ... @@ -193,7 +223,7 @@ public class InOutStationSignalHandle extends SignalHandle{
193 223 */
194 224 private boolean willDepart(GpsEntity gps, GpsEntity prev, Object task){
195 225  
196   -/* ScheduleRealInfo sch = (ScheduleRealInfo) task;
  226 + /*ScheduleRealInfo sch = (ScheduleRealInfo) task;
197 227 ScheduleRealInfo prevTask = dayOfSchedule.prev(sch);
198 228 if(prevTask == null || prevTask.getBcType().equals("out"))
199 229 return false;
... ...
src/main/java/com/bsth/data/gpsdata/arrival/handlers/OfflineSignalHandle.java
... ... @@ -13,16 +13,17 @@ import org.springframework.stereotype.Component;
13 13 @Component
14 14 public class OfflineSignalHandle extends SignalHandle{
15 15  
16   - //断开3分钟,标记为重连信号
17   - private final static int OFFLINE_TIME = 1000 * 60 * 3;
  16 + //断开2分钟,标记为重连信号
  17 + private final static int OFFLINE_TIME = 1000 * 60 * 2;
18 18  
19 19 //断开70分钟,之前的信号不再有参考价值
20 20 private final static int CLEAR_TIME = 1000 * 60 * 70;
21 21  
22 22 @Override
23 23 public boolean handle(GpsEntity gps, CircleQueue<GpsEntity> prevs) {
24   - //异常信号不管
25   - if(isAbnormal(gps)){
  24 + //漂移信号不管
  25 + if(isDriftSignal(gps)){
  26 + gps.setSignalState("drift");
26 27 return true;
27 28 }
28 29  
... ... @@ -39,4 +40,4 @@ public class OfflineSignalHandle extends SignalHandle{
39 40 }
40 41 return true;
41 42 }
42   -}
  43 +}
43 44 \ No newline at end of file
... ...
src/main/java/com/bsth/data/gpsdata/arrival/handlers/ReverseSignalHandle.java
1 1 package com.bsth.data.gpsdata.arrival.handlers;
2 2  
3   -import com.alibaba.fastjson.JSON;
4 3 import com.bsth.data.gpsdata.GpsEntity;
5 4 import com.bsth.data.gpsdata.arrival.GeoCacheData;
6 5 import com.bsth.data.gpsdata.arrival.SignalHandle;
7 6 import com.bsth.data.gpsdata.arrival.entity.RouteReverse;
8 7 import com.bsth.data.gpsdata.arrival.entity.StationRoute;
9 8 import com.bsth.data.gpsdata.arrival.utils.CircleQueue;
  9 +import com.bsth.data.gpsdata.arrival.utils.ScheduleSignalState;
10 10 import com.bsth.data.schedule.DayOfSchedule;
11   -import com.bsth.entity.realcontrol.ScheduleRealInfo;
12 11 import org.slf4j.Logger;
13 12 import org.slf4j.LoggerFactory;
14 13 import org.springframework.beans.factory.annotation.Autowired;
... ... @@ -26,6 +25,9 @@ public class ReverseSignalHandle extends SignalHandle {
26 25 @Autowired
27 26 DayOfSchedule dayOfSchedule;
28 27  
  28 + @Autowired
  29 + ScheduleSignalState scheduleSignalState;
  30 +
29 31 @Override
30 32 public boolean handle(GpsEntity gps, CircleQueue<GpsEntity> prevs) {
31 33 if (!isNotEmpty(prevs))
... ... @@ -36,17 +38,10 @@ public class ReverseSignalHandle extends SignalHandle {
36 38 if (isReverse(gps, prev)) {
37 39 RouteReverse reverse = reverseSearch(prevs, gps);
38 40  
39   - if (reverse.getCount() >= 2) {
40   - //切换到下一个班次
41   - ScheduleRealInfo sch = dayOfSchedule.executeCurr(gps.getNbbm());
42   - if (sch.getBcType().equals("out") && sch.getZdsjT() != null && sch.getZdsjT() > gps.getTimestamp()) {
43   - return false;
44   - }
45   - dayOfSchedule.addExecPlan(dayOfSchedule.next(sch));
46   -
47   - if (reverse.isClose()) {
48   - logger.info("区间掉头,车辆:" + gps.getNbbm() + " -" + JSON.toJSONString(reverse));
49   - }
  41 + if (reverse.getCount() >= 4
  42 + && reverse.isClose()
  43 + && !GeoCacheData.isEndStation(gps.getLineId(), gps.getUpDown(), reverse.getTurned())) {
  44 + scheduleSignalState.reverseAnalyse(reverse);
50 45 }
51 46 }
52 47 return false;
... ... @@ -63,7 +58,8 @@ public class ReverseSignalHandle extends SignalHandle {
63 58 RouteReverse routeReverse = new RouteReverse();
64 59 int count = 0;
65 60 String path = "";
66   - String turned = null;
  61 + long zt = 0L;
  62 + boolean half = false;
67 63  
68 64 //当前站点
69 65 StationRoute curr = GeoCacheData.getRouteCode(gps), sr;
... ... @@ -72,22 +68,29 @@ public class ReverseSignalHandle extends SignalHandle {
72 68 for (int i = array.length - 1; i > 0; i--) {
73 69 prev = (GpsEntity) array[i];
74 70  
75   - if(!prev.getUpDown().equals(gps.getUpDown()))
  71 + if (!prev.getUpDown().equals(gps.getUpDown())
  72 + || prev.getSignalState().equals("reconnection"))
76 73 break;
77 74  
78 75 if (prev.getInstation() == 1) {
79 76 sr = GeoCacheData.getRouteCode(prev);
80 77  
81 78 if (sr.getRouteSort() > curr.getRouteSort()) {
  79 + if(half){
  80 + routeReverse.setVague(true);
  81 + }
  82 +
82 83 path += (curr.getCode() + ",");
83 84 count++;
  85 + zt = prev.getTimestamp();
84 86 } else if (sr.getRouteSort() < curr.getRouteSort()) {
85   - path += (curr.getCode() + ",");
86   - //掉头点
87   - if (turned == null)
88   - turned = prev.getStopNo();
  87 + if (routeReverse.getTurned() == null) {
  88 + routeReverse.setTurned(curr.getCode());
  89 + half = true;
  90 + }
89 91  
90   - //路径闭合
  92 + path += (curr.getCode() + ",");
  93 + //掉头前当前站
91 94 if (sr.getCode().equals(gps.getStopNo())) {
92 95 routeReverse.setClose(true);
93 96 path += sr.getCode();
... ... @@ -99,9 +102,11 @@ public class ReverseSignalHandle extends SignalHandle {
99 102 }
100 103 }
101 104  
  105 + routeReverse.setZt(zt);
102 106 routeReverse.setCount(count);
103 107 routeReverse.setDetail(path);
104   - routeReverse.setTurned(turned);
  108 + routeReverse.setCt(gps.getTimestamp());
  109 + routeReverse.setNbbm(gps.getNbbm());
105 110 return routeReverse;
106 111 }
107 112  
... ... @@ -129,4 +134,4 @@ public class ReverseSignalHandle extends SignalHandle {
129 134 }
130 135 return false;
131 136 }
132   -}
  137 +}
133 138 \ No newline at end of file
... ...
src/main/java/com/bsth/data/gpsdata/arrival/utils/CircleQueue.java
... ... @@ -105,8 +105,8 @@ public class CircleQueue&lt;T&gt; {
105 105 }
106 106 }
107 107 } else {
108   - elementDataSort = new Object[tail];
109   - for (int i = 0; i < tail; i++) {
  108 + elementDataSort = new Object[tail + 1];
  109 + for (int i = 0; i <= tail; i++) {
110 110 elementDataSort[i] = elementDataCopy[i];
111 111 }
112 112 }
... ...
src/main/java/com/bsth/data/gpsdata/arrival/utils/ScheduleSignalState.java 0 → 100644
  1 +package com.bsth.data.gpsdata.arrival.utils;
  2 +
  3 +import com.bsth.data.LineConfigData;
  4 +import com.bsth.data.gpsdata.GpsEntity;
  5 +import com.bsth.data.gpsdata.SignalStateData;
  6 +import com.bsth.data.gpsdata.arrival.GeoCacheData;
  7 +import com.bsth.data.gpsdata.arrival.entity.RouteReverse;
  8 +import com.bsth.data.gpsdata.arrival.entity.SignalAbnormal;
  9 +import com.bsth.data.gpsdata.arrival.entity.SignalState;
  10 +import com.bsth.data.schedule.DayOfSchedule;
  11 +import com.bsth.entity.realcontrol.LineConfig;
  12 +import com.bsth.entity.realcontrol.ScheduleRealInfo;
  13 +import org.slf4j.Logger;
  14 +import org.slf4j.LoggerFactory;
  15 +import org.springframework.beans.factory.annotation.Autowired;
  16 +import org.springframework.stereotype.Component;
  17 +
  18 +/**
  19 + * 班次信号状态分析
  20 + * Created by panzhao on 2016/12/29.
  21 + */
  22 +@Component
  23 +public class ScheduleSignalState {
  24 +
  25 + @Autowired
  26 + DayOfSchedule dayOfSchedule;
  27 +
  28 + Logger logger = LoggerFactory.getLogger(this.getClass());
  29 +
  30 + @Autowired
  31 + LineConfigData lineConfigData;
  32 +
  33 + @Autowired
  34 + SignalStateData signalStateData;
  35 +
  36 + /**
  37 + * 路由反向分析
  38 + */
  39 + public void reverseAnalyse(RouteReverse reverse) {
  40 + ScheduleRealInfo sch = dayOfSchedule.executeCurr(reverse.getNbbm());
  41 +
  42 + String bcType = sch.getBcType();
  43 +
  44 + switch (bcType) {
  45 + case "out":
  46 + outReverseAnalyse(sch, reverse);
  47 + break;
  48 + case "normal":
  49 + normalReverseAnalyse(sch, reverse);
  50 + break;
  51 + }
  52 + }
  53 +
  54 + /**
  55 + * 出场班次路由反向分析
  56 + *
  57 + * @param sch
  58 + */
  59 + private void outReverseAnalyse(ScheduleRealInfo sch, RouteReverse reverse) {
  60 + long t = reverse.getCt();
  61 + //出场班次终点时间前,允许反向轨迹
  62 + if (sch.getZdsjT() != null && sch.getZdsjT() > t) {
  63 + return;
  64 + }
  65 +
  66 + int rt;
  67 + //从实发 到 当前时间 < 计划运送时间 * 0.9
  68 + if (sch.getFcsjActual() != null && sch.getBcsj() != null) {
  69 + rt = (int) (t - sch.getFcsjActualTime());
  70 + if (rt < sch.getBcsj() * 0.9)
  71 + return;
  72 + }
  73 +
  74 + ScheduleRealInfo next = dayOfSchedule.next(sch);
  75 + if (next.getXlDir().equals(sch.getXlDir()))
  76 + return;
  77 +
  78 + //时间足够下一个班次待发时间运行到当前站
  79 + int runTime = reverse.getCount() * 1500 * 60;
  80 + if (next.getDfsjT() + runTime < t) {
  81 + //跳到下一个班次
  82 + dayOfSchedule.addExecPlan(next);
  83 + }
  84 + }
  85 +
  86 + /**
  87 + * 正常班次路由反向分析
  88 + *
  89 + * @param sch
  90 + * @param reverse
  91 + */
  92 + private void normalReverseAnalyse(ScheduleRealInfo sch, RouteReverse reverse) {
  93 + LineConfig conf = lineConfigData.get(sch.getXlBm());
  94 +
  95 + if (conf.isReadReverse()) {
  96 + //跳下一个班次
  97 + ScheduleRealInfo next = dayOfSchedule.next(sch);
  98 + if (next != null)
  99 + dayOfSchedule.addExecPlan(next);
  100 +
  101 + //记录信号状态
  102 + SignalState signalState = SignalState.reverseSignalSTate(sch, reverse);
  103 + signalStateData.put(signalState);
  104 + }
  105 + }
  106 +
  107 + public void signalRetrospect(GpsEntity gps) {
  108 + signalRetrospect(gps, dayOfSchedule.executeCurr(gps.getNbbm()));
  109 + }
  110 +
  111 + /**
  112 + * 信号追溯
  113 + *
  114 + * @param gps
  115 + * @param sch
  116 + */
  117 + public void signalRetrospect(GpsEntity gps, ScheduleRealInfo sch) {
  118 + //回放数据,是否有掉线或者漂移
  119 + CircleQueue<GpsEntity> queue = GeoCacheData.getGps(gps.getNbbm());
  120 + if (queue == null || queue.size() == 0 /*|| gps.getInstation() == 0*/)
  121 + return;
  122 +
  123 + //起始时间点
  124 + long st = 0;
  125 + ScheduleRealInfo prev = dayOfSchedule.prev(sch);
  126 +
  127 + if (prev != null) {
  128 + if (prev.getZdsjActual() != null)
  129 + st = prev.getZdsjActualTime();
  130 + else
  131 + st = (GeoCacheData.midwayStation(gps.getLineId(), gps.getUpDown(), sch.getQdzCode(), gps.getStopNo()).size() + 1) * (1000 * 60 * 5);
  132 + }
  133 +
  134 + Object[] tempArray = queue.getQueue();
  135 + int len = tempArray.length;
  136 +
  137 + Object[] array = new Object[len + 1];
  138 + System.arraycopy(tempArray, 0, array, 0, len);
  139 + array[len] = gps;
  140 +
  141 + String gpsState = "";
  142 + GpsEntity tempGps, nearGps = null;
  143 + int i = len - 1;
  144 + for (; i >= 0; i--) {
  145 + tempGps = (GpsEntity) array[i];
  146 +
  147 + gpsState = tempGps.getSignalState();
  148 + if (gpsState.equals("truncation"))
  149 + break;
  150 + else if (gpsState.equals("drift")) {
  151 + nearGps = (GpsEntity) array[i + 1];
  152 + break;
  153 + } else if (gpsState.equals("reconnection")) {
  154 + nearGps = tempGps;
  155 + break;
  156 + }
  157 +
  158 + if (tempGps.getTimestamp() < st)
  159 + break;
  160 + }
  161 +
  162 + if (nearGps != null && i > 0) {
  163 + createSignalAbnormal(gpsState, nearGps, i, array, sch);
  164 + }
  165 + }
  166 +
  167 + private void createSignalAbnormal(String gpsState, GpsEntity nearGps, int i, Object[] array, ScheduleRealInfo sch) {
  168 + switch (gpsState) {
  169 + case "drift":
  170 + driftSignalAbnormal(nearGps, i, array, sch);
  171 + break;
  172 + case "reconnection":
  173 + offlineSignalAbnormal(nearGps, ((GpsEntity) array[i - 1]), sch);
  174 + break;
  175 + }
  176 + }
  177 +
  178 + /**
  179 + * 掉线异常状态记录
  180 + *
  181 + * @param e
  182 + * @param s
  183 + */
  184 + private void offlineSignalAbnormal(GpsEntity e, GpsEntity s, ScheduleRealInfo sch) {
  185 + long st = s.getTimestamp(), et = e.getTimestamp();
  186 +
  187 + //掉线超过10分钟才记录
  188 + if (et - st < (1000 * 60 * 10))
  189 + return;
  190 +
  191 + SignalAbnormal signalAbnormal = new SignalAbnormal();
  192 + signalAbnormal.setSt(st);
  193 + signalAbnormal.setEt(et);
  194 + signalAbnormal.setAbnormalType("reconnection");
  195 + signalAbnormal.setDestCode(sch.getQdzCode());
  196 + signalAbnormal.setOutOrIn(0);
  197 +
  198 + //截断GPS
  199 + e.setSignalState("truncation");
  200 +
  201 + //记录信号状态
  202 + SignalState signalState = SignalState.abnormalSignalSTate(sch, signalAbnormal);
  203 + signalStateData.put(signalState);
  204 + }
  205 +
  206 + /**
  207 + * 漂移异常状态记录
  208 + *
  209 + * @param nearGps
  210 + * @param i
  211 + * @param array
  212 + */
  213 + private void driftSignalAbnormal(GpsEntity nearGps, int i, Object[] array, ScheduleRealInfo sch) {
  214 + GpsEntity gps, s = null;
  215 + //找到漂移开始时间
  216 + for (; i >= 0; i--) {
  217 + gps = (GpsEntity) array[i];
  218 +
  219 + if (!gps.getSignalState().equals("drift") || i == 0
  220 + || gps.getSignalState().equals("truncation")) {
  221 + s = gps;
  222 + break;
  223 + }
  224 + }
  225 +
  226 + long st = s.getTimestamp(), et = nearGps.getTimestamp();
  227 + if (et - st < (1000 * 60 * 3))
  228 + return;
  229 + /*if (s != null){
  230 + st = s.getTimestamp();
  231 + //漂移小于3分钟
  232 + if(et - st < (1000 * 60 * 3))
  233 + return;
  234 + }*/
  235 +
  236 +
  237 + SignalAbnormal signalAbnormal = new SignalAbnormal();
  238 + signalAbnormal.setSt(st);
  239 + signalAbnormal.setEt(et);
  240 + signalAbnormal.setAbnormalType("drift");
  241 + signalAbnormal.setDestCode(sch.getQdzCode());
  242 + signalAbnormal.setOutOrIn(0);
  243 +
  244 + //截断GPS
  245 + nearGps.setSignalState("truncation");
  246 +
  247 + //记录信号状态
  248 + SignalState signalState = SignalState.abnormalSignalSTate(sch, signalAbnormal);
  249 + signalStateData.put(signalState);
  250 + }
  251 +}
... ...
src/main/java/com/bsth/data/gpsdata/arrival/utils/SignalSchPlanMatcher.java 0 → 100644
  1 +package com.bsth.data.gpsdata.arrival.utils;
  2 +
  3 +import com.bsth.data.gpsdata.GpsEntity;
  4 +import com.bsth.data.schedule.DayOfSchedule;
  5 +import com.bsth.entity.realcontrol.ScheduleRealInfo;
  6 +import org.springframework.beans.factory.annotation.Autowired;
  7 +import org.springframework.stereotype.Component;
  8 +
  9 +/**
  10 + * 班次匹配器
  11 + * Created by panzhao on 2016/12/31.
  12 + */
  13 +@Component
  14 +public class SignalSchPlanMatcher {
  15 +
  16 + @Autowired
  17 + DayOfSchedule dayOfSchedule;
  18 +
  19 + /**
  20 + * 发车信号匹配
  21 + * @param outSigal
  22 + * @param sch
  23 + * @return
  24 + */
  25 + public void outMatch(GpsEntity outSigal, ScheduleRealInfo sch){
  26 + long t = outSigal.getTimestamp();
  27 + if(t < sch.getDfsjT())
  28 + return;
  29 +
  30 + //下一个相同走向的班次
  31 + ScheduleRealInfo next = dayOfSchedule.nextSame(sch);
  32 + if(next == null || !next.getQdzCode().equals(sch.getQdzCode()))
  33 + return;
  34 +
  35 + //晚于班次间隔百分之70,跳下一个班次
  36 + double s = (int) (next.getDfsjT() - sch.getDfsjT());
  37 + double r = (int) (t - sch.getDfsjT());
  38 + if(r / s > 0.7){
  39 + dayOfSchedule.addExecPlan(next);
  40 + outMatch(outSigal, next);
  41 + }
  42 + }
  43 +}
... ...
src/main/java/com/bsth/data/gpsdata/recovery/GpsDataRecovery.java
... ... @@ -28,7 +28,7 @@ import java.util.concurrent.Executors;
28 28 * Created by panzhao on 2016/12/24.
29 29 */
30 30 @Component
31   -public class GpsDataRecovery implements ApplicationContextAware{
  31 +public class GpsDataRecovery implements ApplicationContextAware {
32 32  
33 33 static Logger logger = LoggerFactory.getLogger(GpsDataRecovery.class);
34 34  
... ... @@ -48,7 +48,7 @@ public class GpsDataRecovery implements ApplicationContextAware{
48 48 //按车辆分组数据
49 49 ArrayListMultimap<String, GpsEntity> listMap = ArrayListMultimap.create();
50 50 for (GpsEntity gps : list) {
51   - if(gps.getNbbm() != null)
  51 + if (gps.getNbbm() != null)
52 52 listMap.put(gps.getNbbm(), gps);
53 53 }
54 54  
... ... @@ -60,6 +60,8 @@ public class GpsDataRecovery implements ApplicationContextAware{
60 60 for (String nbbm : keys) {
61 61 Collections.sort(listMap.get(nbbm), comp);
62 62 threadPool.execute(new RecoveryThread(listMap.get(nbbm), count));
  63 + /*if(nbbm.equals("YT-CD008"))
  64 + new RecoveryThread(listMap.get(nbbm), count).run();*/
63 65 }
64 66  
65 67 try {
... ... @@ -124,7 +126,7 @@ public class GpsDataRecovery implements ApplicationContextAware{
124 126 reverseSignalHandle = applicationContext.getBean(ReverseSignalHandle.class);
125 127 }
126 128  
127   - public static class GpsComp implements Comparator<GpsEntity>{
  129 + public static class GpsComp implements Comparator<GpsEntity> {
128 130  
129 131 @Override
130 132 public int compare(GpsEntity g1, GpsEntity g2) {
... ... @@ -132,26 +134,28 @@ public class GpsDataRecovery implements ApplicationContextAware{
132 134 }
133 135 }
134 136  
135   - public static class RecoveryThread implements Runnable{
  137 + public static class RecoveryThread implements Runnable {
136 138 List<GpsEntity> list;
137 139 CountDownLatch count;
138 140  
139   - RecoveryThread(List<GpsEntity> list, CountDownLatch count){
  141 + RecoveryThread(List<GpsEntity> list, CountDownLatch count) {
140 142 this.list = list;
141 143 this.count = count;
142 144 }
  145 +
143 146 @Override
144 147 public void run() {
145 148 try {
146 149 //循环gps恢复数据
147 150 CircleQueue<GpsEntity> prevs;
148 151  
149   - for(GpsEntity gps : list){
  152 + for (GpsEntity gps : list) {
  153 +
150 154 prevs = GeoCacheData.getGps(gps.getNbbm());
151 155 //掉线处理
152 156 offlineSignalHandle.handle(gps, prevs);
153 157 //状态处理
154   - if(!correctSignalHandle.handle(gps, prevs))
  158 + if (!correctSignalHandle.handle(gps, prevs))
155 159 continue;
156 160 //场,站内外判断
157 161 stationInsideHandle.handle(gps, prevs);
... ... @@ -160,11 +164,12 @@ public class GpsDataRecovery implements ApplicationContextAware{
160 164 //进出站动作处理
161 165 inOutStationSignalHandle.handle(gps, prevs);
162 166 GeoCacheData.putGps(gps);
  167 +
  168 + //Thread.sleep(50);
163 169 }
164   - }catch (Exception e){
  170 + } catch (Exception e) {
165 171 logger.error("", e);
166   - }
167   - finally {
  172 + } finally {
168 173 count.countDown();
169 174 }
170 175 }
... ...
src/main/java/com/bsth/data/schedule/DayOfSchedule.java
... ... @@ -2,8 +2,6 @@ package com.bsth.data.schedule;
2 2  
3 3 import com.alibaba.fastjson.JSON;
4 4 import com.alibaba.fastjson.JSONArray;
5   -import com.bsth.Application;
6   -import com.bsth.data.BasicData;
7 5 import com.bsth.data.LineConfigData;
8 6 import com.bsth.data.directive.FirstScheduleCheckThread;
9 7 import com.bsth.data.gpsdata.GpsRealData;
... ... @@ -29,12 +27,12 @@ import org.slf4j.Logger;
29 27 import org.slf4j.LoggerFactory;
30 28 import org.springframework.beans.factory.annotation.Autowired;
31 29 import org.springframework.boot.CommandLineRunner;
  30 +import org.springframework.core.annotation.Order;
32 31 import org.springframework.stereotype.Component;
33 32  
34 33 import java.text.ParseException;
35 34 import java.text.SimpleDateFormat;
36 35 import java.util.*;
37   -import java.util.concurrent.TimeUnit;
38 36  
39 37 /**
40 38 * @author PanZhao
... ... @@ -43,443 +41,568 @@ import java.util.concurrent.TimeUnit;
43 41 * @date 2016年8月15日 上午10:16:12
44 42 */
45 43 @Component
  44 +@Order(value = 3)
46 45 public class DayOfSchedule implements CommandLineRunner {
47 46  
48   - Logger logger = LoggerFactory.getLogger(this.getClass());
49   -
50   - // 按车辆分组的班次数据
51   - private static ArrayListMultimap<String, ScheduleRealInfo> nbbmScheduleMap;
52   -
53   - // 班次主键映射
54   - private static Map<Long, ScheduleRealInfo> id2SchedulMap;
55   -
56   - // 车辆和排班起终点站对照(包括进出的停车场,区间起终点)
57   - private static TreeMultimap<String, String> nbbm2SEStationMap;
58   -
59   - //车辆 ——> 当前执行班次
60   - private static Map<String, ScheduleRealInfo> carExecutePlanMap;
61   -
62   - // 持久化缓冲区
63   - public static LinkedList<ScheduleRealInfo> pstBuffer;
64   -
65   - // 排序器
66   - private static ScheduleComparator.FCSJ schFCSJComparator;
67   -
68   - @Autowired
69   - LineConfigData lineConfigData;
70   -
71   - @Autowired
72   - ScheduleRealInfoRepository schRepository;
73   -
74   - @Autowired
75   - SchedulePlanInfoService schPlanService;
76   -
77   - @Autowired
78   - SchAttrCalculator schAttrCalculator;
79   -
80   - @Autowired
81   - SendUtils sendUtils;
82   -
83   - @Autowired
84   - GpsRealData gpsRealData;
85   -
86   - /** 线路当前使用的排班的日期 */
87   - public static Map<String, String> currSchDateMap;
88   -
89   - static {
90   - nbbmScheduleMap = ArrayListMultimap.create();
91   - id2SchedulMap = new HashMap<>();
92   - pstBuffer = new LinkedList<>();
93   - schFCSJComparator = new ScheduleComparator.FCSJ();
94   - currSchDateMap = new HashMap<>();
95   - nbbm2SEStationMap = TreeMultimap.create();
96   - carExecutePlanMap = new HashMap<>();
97   - }
98   -
99   - @Autowired
100   - ScheduleRefreshThread scheduleRefreshThread;
101   -
102   - @Autowired
103   - SchedulePstThread schedulePstThread;
104   -
105   - @Autowired
106   - FirstScheduleCheckThread firstScheduleCheckThread;
107   -
108   - @Autowired
109   - ScheduleLateThread scheduleLateThread;
110   -
111   - private static DateTimeFormatter fmtyyyyMMdd = DateTimeFormat.forPattern("yyyy-MM-dd")
112   - ,fmtHHmm = DateTimeFormat.forPattern("HH:mm");
113   -
114   - @Override
115   - public void run(String... arg0) throws Exception {
116   - //翻班线程
117   - Application.mainServices.scheduleWithFixedDelay(scheduleRefreshThread, 15, 240, TimeUnit.SECONDS);
118   - //入库
119   - Application.mainServices.scheduleWithFixedDelay(schedulePstThread, 60, 60, TimeUnit.SECONDS);
120   - //首班出场指令补发器
121   - Application.mainServices.scheduleWithFixedDelay(firstScheduleCheckThread, 30, 240, TimeUnit.SECONDS);
122   - //班次误点扫描
123   - //Application.mainServices.scheduleWithFixedDelay(scheduleLateThread, 60, 60, TimeUnit.SECONDS);
124   - }
125   -
126   - public Map<String, String> getCurrSchDate() {
127   - return currSchDateMap;
128   - }
129   -
130   - /**
131   - *
132   - * @Title: calcSchDateB
133   - * @Description: TODO(计算线路当前应该使用的排班日期)
134   - */
135   - public String calcSchDate(String lineCode) {
136   - LineConfig conf = lineConfigData.get(lineCode);
137   - long ct = System.currentTimeMillis();
138   -
139   - String schDate = fmtyyyyMMdd.print(ct);
140   - // 小于当天起始运营时间,则取前一天的排班
141   - if (ct < conf.getCurrStartTime())
142   - schDate = DateUtils.subtractDay(schDate, 1);
143   -
144   - return schDate;
145   - }
146   -
147   - /**
148   - * @Title: reloadSch
149   - * @Title: reloadSch
150   - * @Description: TODO(重新载入排班)
151   - * @param @param
152   - * lineCode 线路编码
153   - * @param @param
154   - * schDate 班次日期 yyyy-MM-dd
155   - * @param @param
156   - * forcePlan 强制从计划调度重新抓取
157   - */
158   - public int reloadSch(String lineCode, String schDate, boolean forcePlan) {
159   - try {
160   - List<ScheduleRealInfo> list;
161   -
162   - if (forcePlan)
163   - removeRealSch(lineCode, schDate);
164   - else
165   - clearRAMData(lineCode);
166   -
167   - if (existRealSch(lineCode, schDate))
168   - list = loadRealSch(lineCode, schDate);// 从实际排班表加载
169   - else {
170   - list = loadPlanSch(lineCode, schDate);// 从计划排班表加载
171   - // 写入数据库
172   - batchSave(list);
173   - }
174   -
175   - //更新线路和班次日期对照
176   - currSchDateMap.put(lineCode, schDate);
177   - //添加到缓存
178   - putAll(list);
179   -
180   - Set<String> cars = searchAllCars(list);
181   - //计算“起点站应到”时间
182   - for(String nbbm : cars)
183   - schAttrCalculator.calcQdzTimePlan(nbbmScheduleMap.get(nbbm));
184   -
185   - //是否是出站即出场
186   - LineConfig conf = lineConfigData.get(lineCode);
187   - if(conf.getOutConfig() == 2){
188   - for(String nbbm : cars)
189   - schAttrCalculator.connectOutSchedule(nbbmScheduleMap.get(nbbm));
190   - }
191   -
192   - // 页面 翻班通知
193   - sendUtils.shiftSchedule(lineCode);
194   - } catch (Exception e) {
195   - logger.error("", e);
196   - return -1;
197   - }
  47 + Logger logger = LoggerFactory.getLogger(this.getClass());
198 48  
199   - return 0;
200   - }
201   -
202   - /**
203   - *
204   - * @Title: searchAllCars
205   - * @Description: TODO(搜索班次集合中的车辆)
206   - */
207   - private Set<String> searchAllCars(List<ScheduleRealInfo> list) {
208   - Set<String> cars = new HashSet<>();
209   - for(ScheduleRealInfo sch : list)
210   - cars.add(sch.getClZbh());
211   -
212   - return cars;
213   - }
214   -
215   - private void putAll(List<ScheduleRealInfo> list) {
216   - for (ScheduleRealInfo sch : list)
217   - put(sch);
218   - }
219   -
220   - /**
221   - * @Title: removeRealSch
222   - * @Description: TODO(清除实际排班,包括数据库和内存数据)
223   - * @param @param
224   - * lineCode 线路编码
225   - * @param @param
226   - * schDate 班次日期 yyyy-MM-dd
227   - */
228   - public void removeRealSch(String lineCode, String schDate) throws Exception {
229   - try {
230   - // 清理数据库数据
231   - schRepository.deleteByLineCodeAndDate(lineCode + "", schDate);
232   -
233   - // 清理内存数据
234   - clearRAMData(lineCode + "");
235   - } catch (Exception e) {
236   - logger.error("removeRealSch error, " + lineCode + " -" + schDate, e);
237   - throw e;
238   - }
239   - }
240   -
241   - /**
242   - *
243   - * @Title: clearRAMData
244   - * @Description: TODO(清理内存数据)
245   - */
246   - public void clearRAMData(String lineCode) {
247   - int count = 0;
248   - List<ScheduleRealInfo> remList = new ArrayList<>();
249   - Collection<ScheduleRealInfo> schs = nbbmScheduleMap.values();
250   - for (ScheduleRealInfo sch : schs) {
251   - if (sch.getXlBm().equals(lineCode))
252   - remList.add(sch);
253   - }
254   -
255   - for(ScheduleRealInfo sch : remList){
256   - if(null != sch){
257   - nbbmScheduleMap.remove(sch.getClZbh(), sch);
258   - id2SchedulMap.remove(sch.getId());
259   - count ++;
260   - }
261   - }
262   -
263   - logger.info(lineCode + "排班清理 " + count);
264   - }
265   -
266   - /**
267   - * @Title: existRealSch
268   - * @Description: TODO(实际排班是否已存在)
269   - */
270   - public boolean existRealSch(String lineCode, String schDate) {
271   - int count = schRepository.countByLineCodeAndDate(lineCode, schDate);
272   - return count > 0;
273   - }
274   -
275   - /**
276   - * @Title: loadRealSch
277   - * @Description: TODO(从实际排班表加载数据)
278   - */
279   - public List<ScheduleRealInfo> loadRealSch(String lineCode, String schDate) {
280   - return schRepository.findByLineCodeAndDate(lineCode, schDate);
281   - }
282   -
283   - /**
284   - * @Title: loadPlanSch
285   - * @Description: TODO(从计划排班表加载数据)
286   - */
287   - public List<ScheduleRealInfo> loadPlanSch(String lineCode, String schDate) {
288   - logger.info("从计划排班表恢复排班,lineCode: " + lineCode + ", schDate: " + schDate);
289   - List<ScheduleRealInfo> realList = new ArrayList<>();
290   -
291   - try {
292   - Map<String, Object> data = new HashMap<>();
293   -
294   - data.put("scheduleDate_eq", fmtyyyyMMdd.parseDateTime(schDate).toDate());
295   - data.put("xlBm_eq", lineCode);
296   -
297   - // 查询计划排班
298   - List<SchedulePlanInfo> planItr = cleanSchPlanItr(schPlanService.list(data).iterator());
299   -
300   - // 转换为实际排班
301   - realList = JSONArray.parseArray(JSON.toJSONString(planItr), ScheduleRealInfo.class);
302   -
303   - for (ScheduleRealInfo sch : realList) {
304   - sch.setScheduleDateStr(fmtyyyyMMdd.print(sch.getScheduleDate().getTime()));
305   - sch.setRealExecDate(sch.getScheduleDateStr());
306   - // 计划终点时间
307   - if (sch.getBcsj() != null) {
308   - sch.setZdsj(fmtHHmm.print(fmtHHmm.parseMillis(sch.getFcsj()) + (sch.getBcsj() * 60 * 1000)));
309   - sch.setLate(false);
310   - }
311   - //计划里程为0,设置NULL
312   - if(sch.getJhlc() != null && sch.getJhlc() == 0)
313   - sch.setJhlc(null);
314   - }
315   - } catch (Exception e) {
316   - logger.error("", e);
317   - }
318   - return realList;
319   - }
320   -
321   - /**
322   - * @Title: batchSave
323   - * @Description: TODO(批量入库)
324   - */
325   - private void batchSave(List<ScheduleRealInfo> list) {
326   - // 查询数据库最大ID
327   - Long id = schRepository.getMaxId();
328   - if (null == id)
329   - id = 0L;
330   - id++;
331   -
332   - SimpleDateFormat sdfyyyyMMdd = new SimpleDateFormat("yyyy-MM-dd");
333   - for (ScheduleRealInfo item : list) {
334   - item.setSpId(item.getId());// 保留原始的计划ID
335   - item.setId(id++);// 设置ID
336   - item.setScheduleDateStr(sdfyyyyMMdd.format(item.getScheduleDate()));
337   - }
  49 + // 按车辆分组的班次数据
  50 + private static ArrayListMultimap<String, ScheduleRealInfo> nbbmScheduleMap;
338 51  
339   - // 入库
340   - new BatchSaveUtils<ScheduleRealInfo>().saveList(list, ScheduleRealInfo.class);
341   - }
  52 + // 班次主键映射
  53 + private static Map<Long, ScheduleRealInfo> id2SchedulMap;
342 54  
343   - private List<SchedulePlanInfo> cleanSchPlanItr(Iterator<SchedulePlanInfo> itrab) {
344   - List<SchedulePlanInfo> list = new ArrayList<>();
  55 + // 车辆和排班起终点站对照(包括进出的停车场,区间起终点)
  56 + private static TreeMultimap<String, String> nbbm2SEStationMap;
345 57  
346   - SchedulePlanInfo sp;
347   - while (itrab.hasNext()) {
348   - sp = itrab.next();
349   - sp.setSchedulePlan(null);
350   - list.add(sp);
351   - }
352   - return list;
353   - }
354   -
355   - /**
356   - *
357   - * @Title: findByLineCode
358   - * @Description: TODO(lineCode 获取班次)
359   - */
360   - public List<ScheduleRealInfo> findByLineCode(String lineCode) {
361   - List<ScheduleRealInfo> rs = new ArrayList<>();
  58 + //车辆 ——> 当前执行班次
  59 + private static Map<String, ScheduleRealInfo> carExecutePlanMap;
362 60  
363   - Collection<ScheduleRealInfo> schs = nbbmScheduleMap.values();
364   - for (ScheduleRealInfo sch : schs) {
365   - if (sch.getXlBm().equals(lineCode))
366   - rs.add(sch);
367   - }
368   - return rs;
369   - }
370   -
371   - /**
372   - *
373   - * @Title: findCarByLineCode
374   - * @Description: TODO(线路下运营的车辆)
375   - */
376   - public Set<String> findCarByLineCode(String lineCode){
377   - Set<String> rs = new HashSet<>();
378   -
379   - Collection<ScheduleRealInfo> schs = nbbmScheduleMap.values();
380   - for (ScheduleRealInfo sch : schs) {
381   - if (sch.getXlBm().equals(lineCode))
382   - rs.add(sch.getClZbh());
383   - }
384   -
385   - return rs;
386   - }
387   -
388   - public List<ScheduleRealInfo> findByNbbm(String nbbm) {
389   - return nbbmScheduleMap.get(nbbm);
390   - }
391   -
392   - /**
393   - *
394   - * @Title: findByLineAndUpDown
395   - * @Description: TODO(lineCode 和走向获取班次)
396   - */
397   - public List<ScheduleRealInfo> findByLineAndUpDown(String lineCode, Integer upDown) {
398   - List<ScheduleRealInfo> list = findByLineCode(lineCode), rs = new ArrayList<>();
399   -
400   - for (ScheduleRealInfo sch : list) {
401   - if (sch.getXlDir().equals(upDown + ""))
402   - rs.add(sch);
403   - }
404   - return rs;
405   - }
  61 + // 持久化缓冲区
  62 + public static LinkedList<ScheduleRealInfo> pstBuffer;
406 63  
407   - public ScheduleRealInfo get(long id) {
408   - return id2SchedulMap.get(id);
409   - }
  64 + // 排序器
  65 + private static ScheduleComparator.FCSJ schFCSJComparator;
410 66  
411   - public Set<String> getSEStationList(String nbbm) {
412   - return nbbm2SEStationMap.get(nbbm);
413   - }
  67 + @Autowired
  68 + LineConfigData lineConfigData;
414 69  
415   - /**
416   - *
417   - * @Title: next
418   - * @Description: TODO(下一个班次)
419   - */
420   - public ScheduleRealInfo next(ScheduleRealInfo sch) {
  70 + @Autowired
  71 + ScheduleRealInfoRepository schRepository;
421 72  
422   - List<ScheduleRealInfo> list = nbbmScheduleMap.get(sch.getClZbh());
423   -
424   - boolean flag = false;
425   - ScheduleRealInfo next = null;
426   - for(ScheduleRealInfo temp : list){
427   - if(temp.getId() == sch.getId()){
428   - flag = true;
429   - continue;
430   - }
431   - //忽略烂班
432   - if(temp.isDestroy())
433   - continue;
434   -
435   - if(flag){
436   - next = temp;
437   - break;
438   - }
439   - }
440   - return next;
441   - }
  73 + @Autowired
  74 + SchedulePlanInfoService schPlanService;
442 75  
443   - public void put(ScheduleRealInfo sch) {
  76 + @Autowired
  77 + SchAttrCalculator schAttrCalculator;
444 78  
445   - schAttrCalculator
446   - .calcRealDate(sch)
447   - .calcAllTimeByFcsj(sch);
  79 + @Autowired
  80 + SendUtils sendUtils;
  81 +
  82 + @Autowired
  83 + GpsRealData gpsRealData;
  84 +
  85 + /**
  86 + * 线路当前使用的排班的日期
  87 + */
  88 + public static Map<String, String> currSchDateMap;
  89 +
  90 + static {
  91 + nbbmScheduleMap = ArrayListMultimap.create();
  92 + id2SchedulMap = new HashMap<>();
  93 + pstBuffer = new LinkedList<>();
  94 + schFCSJComparator = new ScheduleComparator.FCSJ();
  95 + currSchDateMap = new HashMap<>();
  96 + nbbm2SEStationMap = TreeMultimap.create();
  97 + carExecutePlanMap = new HashMap<>();
  98 + }
  99 +
  100 + @Autowired
  101 + ScheduleRefreshThread scheduleRefreshThread;
  102 +
  103 + @Autowired
  104 + SchedulePstThread schedulePstThread;
  105 +
  106 + @Autowired
  107 + FirstScheduleCheckThread firstScheduleCheckThread;
  108 +
  109 + @Autowired
  110 + ScheduleLateThread scheduleLateThread;
  111 +
  112 + @Autowired
  113 + SubmitToTrafficManage submitToTrafficManage;
  114 +
  115 + @Autowired
  116 + LineConfigData lineConfigs;
  117 +
  118 + @Autowired
  119 + GpsDataRecovery gpsDataRecovery;
  120 +
  121 + private static DateTimeFormatter fmtyyyyMMdd = DateTimeFormat.forPattern("yyyy-MM-dd"), fmtHHmm = DateTimeFormat.forPattern("HH:mm");
  122 +
  123 + @Override
  124 + public void run(String... arg0) throws Exception {
  125 + //从数据库恢复排班
  126 + //dataRecovery();
  127 +
  128 + //翻班线程
  129 +// Application.mainServices.scheduleWithFixedDelay(scheduleRefreshThread, 15, 240, TimeUnit.SECONDS);
  130 + //入库
  131 +// Application.mainServices.scheduleWithFixedDelay(schedulePstThread, 60, 60, TimeUnit.SECONDS);
  132 + //首班出场指令补发器
  133 +// Application.mainServices.scheduleWithFixedDelay(firstScheduleCheckThread, 30, 240, TimeUnit.SECONDS);
  134 + //班次误点扫描
  135 +// Application.mainServices.scheduleWithFixedDelay(scheduleLateThread, 60, 60, TimeUnit.SECONDS);
  136 +
  137 + //每天凌晨2点20提交数据到运管处
  138 + long diff = (DateUtils.getTimestamp() + 1000 * 60 * 140) - System.currentTimeMillis();
  139 + if (diff < 0)
  140 + diff += (1000 * 60 * 60 * 24);
  141 +
  142 + logger.info(diff / 1000 / 60 + "分钟之后提交到运管处");
  143 + //Application.mainServices.scheduleWithFixedDelay(submitToTrafficManage, diff / 1000, 60 * 60 * 24, TimeUnit.SECONDS);
  144 + }
  145 +
  146 + //数据恢复
  147 + private void dataRecovery() {
  148 + GpsDataRecovery.run = true;
  149 +
  150 + Collection<LineConfig> confs = lineConfigs.getAll();
  151 + String lineCode, currSchDate;
  152 + for (LineConfig conf : confs) {
  153 + lineCode = conf.getLine().getLineCode();
  154 + currSchDate = calcSchDate(lineCode);
  155 + //加载班次数据
  156 + reloadSch(lineCode, currSchDate, false);
  157 + }
  158 +
  159 + //恢复gps数据
  160 + gpsDataRecovery.recovery();
  161 + }
  162 +
  163 + public Map<String, String> getCurrSchDate() {
  164 + return currSchDateMap;
  165 + }
  166 +
  167 + /**
  168 + * @Title: calcSchDateB
  169 + * @Description: TODO(计算线路当前应该使用的排班日期)
  170 + */
  171 + public String calcSchDate(String lineCode) {
  172 + LineConfig conf = lineConfigData.get(lineCode);
  173 + long ct = System.currentTimeMillis();
  174 +
  175 + String schDate = fmtyyyyMMdd.print(ct);
  176 + // 小于当天起始运营时间,则取前一天的排班
  177 + if (ct < conf.getCurrStartTime())
  178 + schDate = DateUtils.subtractDay(schDate, 1);
  179 +
  180 + return schDate;
  181 + }
  182 +
  183 + /**
  184 + * @param @param lineCode 线路编码
  185 + * @param @param schDate 班次日期 yyyy-MM-dd
  186 + * @param @param forcePlan 强制从计划调度重新抓取
  187 + * @Title: reloadSch
  188 + * @Title: reloadSch
  189 + * @Description: TODO(重新载入排班)
  190 + */
  191 + public int reloadSch(String lineCode, String schDate, boolean forcePlan) {
  192 + try {
  193 + List<ScheduleRealInfo> list;
  194 +
  195 + if (forcePlan)
  196 + removeRealSch(lineCode, schDate);
  197 + else
  198 + clearRAMData(lineCode);
  199 +
  200 + if (existRealSch(lineCode, schDate))
  201 + list = loadRealSch(lineCode, schDate);// 从实际排班表加载
  202 + else {
  203 + list = loadPlanSch(lineCode, schDate);// 从计划排班表加载
  204 + // 写入数据库
  205 + batchSave(list);
  206 + }
  207 +
  208 + //更新线路和班次日期对照
  209 + currSchDateMap.put(lineCode, schDate);
  210 + //添加到缓存
  211 + putAll(list);
  212 +
  213 + Set<String> cars = searchAllCars(list);
  214 + for (String nbbm : cars) {
  215 + //计算“起点站应到”时间
  216 + schAttrCalculator.calcQdzTimePlan(nbbmScheduleMap.get(nbbm));
  217 + //车辆 ——> 要执行的班次对照
  218 + reCalcExecPlan(nbbm);
  219 + }
  220 +
  221 + // 页面 翻班通知
  222 + //sendUtils.shiftSchedule(lineCode);
  223 + } catch (Exception e) {
  224 + logger.error("", e);
  225 + return -1;
  226 + }
  227 +
  228 + return 0;
  229 + }
  230 +
  231 + /**
  232 + * @Title: searchAllCars
  233 + * @Description: TODO(搜索班次集合中的车辆)
  234 + */
  235 + private Set<String> searchAllCars(List<ScheduleRealInfo> list) {
  236 + Set<String> cars = new HashSet<>();
  237 + for (ScheduleRealInfo sch : list)
  238 + cars.add(sch.getClZbh());
  239 +
  240 + return cars;
  241 + }
  242 +
  243 + private void putAll(List<ScheduleRealInfo> list) {
  244 + for (ScheduleRealInfo sch : list)
  245 + put(sch);
  246 + }
  247 +
  248 + /**
  249 + * @param @param lineCode 线路编码
  250 + * @param @param schDate 班次日期 yyyy-MM-dd
  251 + * @Title: removeRealSch
  252 + * @Description: TODO(清除实际排班,包括数据库和内存数据)
  253 + */
  254 + public void removeRealSch(String lineCode, String schDate) throws Exception {
  255 + try {
  256 + // 清理数据库数据
  257 + schRepository.deleteByLineCodeAndDate(lineCode + "", schDate);
  258 +
  259 + // 清理内存数据
  260 + clearRAMData(lineCode + "");
  261 + } catch (Exception e) {
  262 + logger.error("removeRealSch error, " + lineCode + " -" + schDate, e);
  263 + throw e;
  264 + }
  265 + }
  266 +
  267 + /**
  268 + * @Title: clearRAMData
  269 + * @Description: TODO(清理内存数据)
  270 + */
  271 + public void clearRAMData(String lineCode) {
  272 + int count = 0;
  273 + List<ScheduleRealInfo> remList = new ArrayList<>();
  274 + Collection<ScheduleRealInfo> schs = nbbmScheduleMap.values();
  275 + for (ScheduleRealInfo sch : schs) {
  276 + if (sch.getXlBm().equals(lineCode))
  277 + remList.add(sch);
  278 + }
  279 +
  280 + for (ScheduleRealInfo sch : remList) {
  281 + if (null != sch) {
  282 + nbbmScheduleMap.remove(sch.getClZbh(), sch);
  283 + id2SchedulMap.remove(sch.getId());
  284 + count++;
  285 + }
  286 + }
  287 +
  288 + logger.info(lineCode + "排班清理 " + count);
  289 + }
  290 +
  291 + /**
  292 + * @Title: existRealSch
  293 + * @Description: TODO(实际排班是否已存在)
  294 + */
  295 + public boolean existRealSch(String lineCode, String schDate) {
  296 + int count = schRepository.countByLineCodeAndDate(lineCode, schDate);
  297 + return count > 0;
  298 + }
  299 +
  300 + /**
  301 + * @Title: loadRealSch
  302 + * @Description: TODO(从实际排班表加载数据)
  303 + */
  304 + public List<ScheduleRealInfo> loadRealSch(String lineCode, String schDate) {
  305 + return schRepository.findByLineCodeAndDate(lineCode, schDate);
  306 + }
  307 +
  308 + /**
  309 + * @Title: loadPlanSch
  310 + * @Description: TODO(从计划排班表加载数据)
  311 + */
  312 + public List<ScheduleRealInfo> loadPlanSch(String lineCode, String schDate) {
  313 + logger.info("从计划排班表恢复排班,lineCode: " + lineCode + ", schDate: " + schDate);
  314 + List<ScheduleRealInfo> realList = new ArrayList<>();
  315 +
  316 + try {
  317 + Map<String, Object> data = new HashMap<>();
  318 +
  319 + data.put("scheduleDate_eq", fmtyyyyMMdd.parseDateTime(schDate).toDate());
  320 + data.put("xlBm_eq", lineCode);
  321 +
  322 + // 查询计划排班
  323 + List<SchedulePlanInfo> planItr = cleanSchPlanItr(schPlanService.list(data).iterator());
  324 +
  325 + // 转换为实际排班
  326 + realList = JSONArray.parseArray(JSON.toJSONString(planItr), ScheduleRealInfo.class);
  327 +
  328 + SimpleDateFormat sdf = new SimpleDateFormat("HH:mm");
  329 + String fcsj;
  330 + for (ScheduleRealInfo sch : realList) {
  331 + sch.setScheduleDateStr(fmtyyyyMMdd.print(sch.getScheduleDate().getTime()));
  332 + sch.setRealExecDate(sch.getScheduleDateStr());
  333 +
  334 + if (StringUtils.isEmpty(sch.getFcsj()))
  335 + sch.setFcsj("00:00");
  336 +
  337 + fcsj = sch.getFcsj().trim();
  338 + //处理一下发车时间格式没有:号的问题
  339 + if (fcsj.indexOf(":") == -1 && fcsj.length() >= 4) {
  340 + sch.setFcsj(fcsj.substring(0, 2) + ":" + fcsj.substring(2, 4));
  341 + }
  342 +
  343 + try {
  344 + sdf.parse(sch.getFcsj());
  345 + } catch (ParseException e) {
  346 + //发车时间仍然校验不过的,直接写成00:00
  347 + sch.setFcsj("00:00");
  348 + }
  349 + sch.setDfsj(sch.getFcsj());
  350 +
  351 + // 计划终点时间
  352 + if (sch.getBcsj() != null) {
  353 + sch.setZdsj(fmtHHmm.print(fmtHHmm.parseMillis(sch.getFcsj()) + (sch.getBcsj() * 60 * 1000)));
  354 + sch.setLate(false);
  355 + }
  356 + //计划里程为0,设置NULL
  357 + if (sch.getJhlc() != null && sch.getJhlc() == 0)
  358 + sch.setJhlc(null);
  359 + }
  360 + } catch (Exception e) {
  361 + logger.error("", e);
  362 + }
  363 + return realList;
  364 + }
  365 +
  366 + /**
  367 + * @Title: batchSave
  368 + * @Description: TODO(批量入库)
  369 + */
  370 + private void batchSave(List<ScheduleRealInfo> list) {
  371 + // 查询数据库最大ID
  372 + Long id = schRepository.getMaxId();
  373 + if (null == id)
  374 + id = 0L;
  375 + id++;
  376 +
  377 + SimpleDateFormat sdfyyyyMMdd = new SimpleDateFormat("yyyy-MM-dd");
  378 + for (ScheduleRealInfo item : list) {
  379 + item.setSpId(item.getId());// 保留原始的计划ID
  380 + item.setId(id++);// 设置ID
  381 + item.setScheduleDateStr(sdfyyyyMMdd.format(item.getScheduleDate()));
  382 + }
  383 +
  384 + // 入库
  385 + new BatchSaveUtils<ScheduleRealInfo>().saveList(list, ScheduleRealInfo.class);
  386 + }
  387 +
  388 + private List<SchedulePlanInfo> cleanSchPlanItr(Iterator<SchedulePlanInfo> itrab) {
  389 + List<SchedulePlanInfo> list = new ArrayList<>();
  390 +
  391 + SchedulePlanInfo sp;
  392 + while (itrab.hasNext()) {
  393 + sp = itrab.next();
  394 + sp.setSchedulePlan(null);
  395 + list.add(sp);
  396 + }
  397 + return list;
  398 + }
  399 +
  400 + /**
  401 + * @Title: findByLineCode
  402 + * @Description: TODO(lineCode 获取班次)
  403 + */
  404 + public List<ScheduleRealInfo> findByLineCode(String lineCode) {
  405 + List<ScheduleRealInfo> rs = new ArrayList<>();
  406 +
  407 + Collection<ScheduleRealInfo> schs = nbbmScheduleMap.values();
  408 + for (ScheduleRealInfo sch : schs) {
  409 + if (sch.getXlBm().equals(lineCode))
  410 + rs.add(sch);
  411 + }
  412 + return rs;
  413 + }
  414 +
  415 + /**
  416 + * @Title: findCarByLineCode
  417 + * @Description: TODO(线路下运营的车辆)
  418 + */
  419 + public Set<String> findCarByLineCode(String lineCode) {
  420 + Set<String> rs = new HashSet<>();
  421 +
  422 + Collection<ScheduleRealInfo> schs = nbbmScheduleMap.values();
  423 + for (ScheduleRealInfo sch : schs) {
  424 + if (sch.getXlBm().equals(lineCode))
  425 + rs.add(sch.getClZbh());
  426 + }
  427 +
  428 + return rs;
  429 + }
  430 +
  431 + public List<ScheduleRealInfo> findByNbbm(String nbbm) {
  432 + return nbbmScheduleMap.get(nbbm);
  433 + }
  434 +
  435 + /**
  436 + * @Title: findByLineAndUpDown
  437 + * @Description: TODO(lineCode 和走向获取班次)
  438 + */
  439 + public List<ScheduleRealInfo> findByLineAndUpDown(String lineCode, Integer upDown) {
  440 + List<ScheduleRealInfo> list = findByLineCode(lineCode), rs = new ArrayList<>();
  441 +
  442 + for (ScheduleRealInfo sch : list) {
  443 + if (sch.getXlDir().equals(upDown + ""))
  444 + rs.add(sch);
  445 + }
  446 + return rs;
  447 + }
  448 +
  449 + public ScheduleRealInfo get(long id) {
  450 + return id2SchedulMap.get(id);
  451 + }
  452 +
  453 + public Set<String> getSEStationList(String nbbm) {
  454 + return nbbm2SEStationMap.get(nbbm);
  455 + }
  456 +
  457 + /**
  458 + * @Title: next
  459 + * @Description: TODO(下一个班次)
  460 + */
  461 + public ScheduleRealInfo next(ScheduleRealInfo sch) {
  462 +
  463 + List<ScheduleRealInfo> list = nbbmScheduleMap.get(sch.getClZbh());
  464 + int outConfig = -1;
  465 + LineConfig config = lineConfigData.get(sch.getXlBm());
  466 + if (config != null)
  467 + outConfig = config.getOutConfig();
  468 +
  469 + boolean flag = false;
  470 + ScheduleRealInfo next = null;
  471 + for (ScheduleRealInfo temp : list) {
  472 + if (temp.getId() == sch.getId()) {
  473 + flag = true;
  474 + continue;
  475 + }
  476 + //忽略烂班
  477 + if (temp.isDestroy())
  478 + continue;
  479 +
  480 + //出站既出场,忽略出场班次
  481 + if (outConfig == 2 && temp.getBcType().equals("out"))
  482 + continue;
  483 +
  484 + if (flag) {
  485 + next = temp;
  486 + break;
  487 + }
  488 + }
  489 + return next;
  490 + }
  491 +
  492 + /**
  493 + * 下一个相同走向的班次
  494 + * @param sch
  495 + * @return
  496 + */
  497 + public ScheduleRealInfo nextSame(ScheduleRealInfo sch){
  498 + List<ScheduleRealInfo> list = nbbmScheduleMap.get(sch.getClZbh());
  499 + int outConfig = -1;
  500 + LineConfig config = lineConfigData.get(sch.getXlBm());
  501 + if (config != null)
  502 + outConfig = config.getOutConfig();
  503 +
  504 + boolean flag = false;
  505 + ScheduleRealInfo next = null;
  506 + for (ScheduleRealInfo temp : list) {
  507 + if (temp.getId() == sch.getId()) {
  508 + flag = true;
  509 + continue;
  510 + }
  511 + //忽略烂班
  512 + if (temp.isDestroy())
  513 + continue;
  514 +
  515 + //出站既出场,忽略出场班次
  516 + if (outConfig == 2 && temp.getBcType().equals("out"))
  517 + continue;
  518 +
  519 + if (flag && temp.getXlDir().equals(sch.getXlDir())) {
  520 + next = temp;
  521 + break;
  522 + }
  523 + }
  524 + return next;
  525 + }
  526 +
  527 + /**
  528 + * 上一个班次
  529 + *
  530 + * @param sch
  531 + * @return
  532 + */
  533 + public ScheduleRealInfo prev(ScheduleRealInfo sch) {
  534 + List<ScheduleRealInfo> list = nbbmScheduleMap.get(sch.getClZbh());
  535 +
  536 + //boolean flag = false;
  537 + ScheduleRealInfo prev = null;
  538 + int size = list.size();
  539 +
  540 + for (int i = 0; i < size; i++) {
  541 + if (list.get(i).isDestroy())
  542 + continue;
  543 +
  544 + if (list.get(i).getId().equals(sch.getId())) {
  545 + return prev;
  546 + }
  547 + prev = list.get(i);
  548 + }
  549 + return prev;
  550 + }
  551 +
  552 + /**
  553 + * 是否是首班出场
  554 + * @param sch
  555 + * @return
  556 + */
  557 + public boolean isFirstOut(ScheduleRealInfo sch){
  558 + List<ScheduleRealInfo> list = nbbmScheduleMap.get(sch.getClZbh());
  559 + if(list.get(0).equals(sch) && sch.getBcType().equals("out"))
  560 + return true;
  561 + return false;
  562 + }
  563 +
  564 + public void put(ScheduleRealInfo sch) {
  565 + schAttrCalculator
  566 + .calcRealDate(sch)
  567 + .calcAllTimeByFcsj(sch);
  568 +
  569 + String nbbm = sch.getClZbh();
  570 + nbbmScheduleMap.put(nbbm, sch);
  571 + nbbm2SEStationMap.put(nbbm, sch.getQdzCode());
  572 + nbbm2SEStationMap.put(nbbm, sch.getZdzCode());
  573 +
  574 + //主键索引
  575 + id2SchedulMap.put(sch.getId(), sch);
  576 + //跨24点的,再save一次
  577 + if (!sch.getRealExecDate().equals(sch.getScheduleDateStr()))
  578 + save(sch);
  579 + }
  580 +
  581 + public void delete(ScheduleRealInfo sch) {
  582 + //ScheduleRealInfo sch = id2SchedulMap.get(id);
  583 + if (!sch.isSflj())
  584 + return;
  585 +
  586 + nbbmScheduleMap.remove(sch.getClZbh(), sch);
  587 + id2SchedulMap.remove(sch.getId());
  588 + //return sch;
  589 + }
448 590  
449   - String nbbm = sch.getClZbh();
450   - nbbmScheduleMap.put(nbbm, sch);
451   - nbbm2SEStationMap.put(nbbm, sch.getQdzCode());
452   - nbbm2SEStationMap.put(nbbm, sch.getZdzCode());
453   -
454   - //主键索引
455   - id2SchedulMap.put(sch.getId(), sch);
456   - }
457   -
458   - public void delete(ScheduleRealInfo sch) {
459   - //ScheduleRealInfo sch = id2SchedulMap.get(id);
460   - if(!sch.isSflj())
461   - return;
462   -
463   - nbbmScheduleMap.remove(sch.getClZbh(), sch);
464   - id2SchedulMap.remove(sch.getId());
465   - //return sch;
466   - }
467   -
468 591 // public void calcQdzTimePlan(String nbbm){
469 592 // schAttrCalculator.calcQdzTimePlan(nbbmScheduleMap.get(nbbm));
470 593 // }
471   -
472   - public List<ScheduleRealInfo> updateQdzTimePlan(String nbbm){
473   - return schAttrCalculator.updateQdzTimePlan(nbbmScheduleMap.get(nbbm));
474   - }
475   -
476   - /**
477   - *
478   - * @Title: nextAll
479   - * @Description: TODO(之后的所有班次)
480   - */
  594 +
  595 + public List<ScheduleRealInfo> updateQdzTimePlan(String nbbm) {
  596 + return schAttrCalculator.updateQdzTimePlan(nbbmScheduleMap.get(nbbm));
  597 + }
  598 +
  599 + /**
  600 + *
  601 + * @Title: nextAll
  602 + * @Description: TODO(之后的所有班次)
  603 + */
481 604 /* public List<ScheduleRealInfo> nextAll(ScheduleRealInfo sch) {
482   - List<ScheduleRealInfo> list = nbbmScheduleMap.get(sch.getClZbh());
  605 + List<ScheduleRealInfo> list = nbbmScheduleMap.get(sch.getClZbh());
483 606 // 排序
484 607 Collections.sort(list, schFCSJComparator);
485 608  
... ... @@ -494,181 +617,229 @@ public class DayOfSchedule implements CommandLineRunner {
494 617 return rs;
495 618 }*/
496 619  
497   - /**
498   - *
499   - * @Title: doneSum
500   - * @Description: TODO(已完成班次总数)
501   - */
502   - public int doneSum(String clZbh) {
503   - List<ScheduleRealInfo> list = nbbmScheduleMap.get(clZbh);
504   - int rs = 0;
505   -
506   - for(ScheduleRealInfo sch : list){
507   - if(sch.getStatus() == 2 && !sch.isDestroy())
508   - rs ++;
509   - }
510   - return rs;
511   - }
512   -
513   - /**
514   - *
515   - * @Title: prveNotExecNum
516   - * @Description: TODO(班次之前未执行班次数量)
517   - */
518   - public int prveNotExecNum(ScheduleRealInfo sch){
519   - int n = 0;
520   - List<ScheduleRealInfo> list = nbbmScheduleMap.get(sch.getClZbh());
521   - for(ScheduleRealInfo s : list){
522   - if(s.getFcsjActual() == null && !s.isDestroy())
523   - n ++;
524   -
525   - if(s.getId().equals(sch.getId()))
526   - break;
527   - }
528   - return n;
529   - }
530   -
531   - /**
532   - *
533   - * @Title: validEndTime
534   - * @Description: TODO(是否是有效的到达时间)
535   - */
536   - public boolean validEndTime(ScheduleRealInfo sch, Long ts) {
537   - if(sch.getFcsjActualTime() != null && sch.getFcsjActualTime() > ts)
538   - return false;
539   -
540   - return validTime(sch, ts);
541   - }
542   -
543   - /**
544   - *
545   - * @Title: validStartTime
546   - * @Description: TODO(是否是合适的发车时间)
547   - */
548   - public boolean validStartTime(ScheduleRealInfo sch, Long ts) {
549   - if(sch.getZdsjActualTime() != null && sch.getZdsjActualTime() < ts)
550   - return false;
551   -
552   - return validTime(sch, ts);
553   - }
554   -
555   - public boolean validTime(ScheduleRealInfo sch, Long ts){
556   - List<ScheduleRealInfo> list = nbbmScheduleMap.get(sch.getClZbh());
557   - int ci = list.indexOf(sch);
558   - ScheduleRealInfo prve, next;
559   - if(ci > 0){
560   - //之前班次实际时间不能大于该时间
561   - for(int i = ci - 1; i >= 0; i --){
562   - prve = list.get(i);
563   - if(prve.getZdsjActualTime() != null && prve.getZdsjActualTime() > ts )
564   - return false;
565   -
566   - if(prve.getFcsjActualTime() != null && prve.getFcsjActualTime() > ts)
567   - return false;
568   - }
569   - }
570   -
571   - if(ci < list.size() - 1){
572   - //之后班次实际时间不能小于该时间
573   - for(int i = ci + 1; i < list.size(); i ++){
574   - next = list.get(i);
575   - if(next.getFcsjActualTime() != null && next.getFcsjActualTime() < ts)
576   - return false;
577   -
578   - if(next.getZdsjActualTime() != null && next.getZdsjActualTime() < ts)
579   - return false;
580   - }
581   - }
582   - return true;
583   - }
584   -
585   - public void save(ScheduleRealInfo sch){
586   - //schRepository.save(sch);
587   - pstBuffer.add(sch);
588   - }
589   -
590   -
591   - /**
592   - *
593   - * @Title: nextByBcType
594   - * @Description: TODO(获取下一个指定班次类型的班次)
595   - */
596   - public ScheduleRealInfo nextByBcType(String nbbm, String bcType){
597   - List<ScheduleRealInfo> list = findByBcType(nbbm, bcType);
598   -
599   - Collections.sort(list, schFCSJComparator);
600   - ScheduleRealInfo sch = null;
601   - for(ScheduleRealInfo temp : list){
602   - if(temp.getFcsjActual() == null)
603   - sch = temp;
604   - }
605   -
606   - return sch;
607   - }
608   -
609   - public List<ScheduleRealInfo> findByBcType(String nbbm, String bcType){
610   - List<ScheduleRealInfo> all = nbbmScheduleMap.get(nbbm)
611   - ,outList = new ArrayList<>();
612   -
613   - for(ScheduleRealInfo sch : all){
614   - if(sch.getBcType().equals(bcType))
615   - outList.add(sch);
616   - }
617   - return outList;
618   - }
619   -
620   - public Set<String> allCar(){
621   - return nbbmScheduleMap.keySet();
622   - }
623   -
624   - public Collection<ScheduleRealInfo> findAll(){
625   - return nbbmScheduleMap.values();
626   - }
627   -
628   - public void addExecPlan(ScheduleRealInfo sch){
629   - carExecutePlanMap.put(sch.getClZbh(), sch);
630   - }
631   -
632   - public void removeExecPlan(String clzbh){
633   - carExecutePlanMap.remove(clzbh);
634   - }
635   -
636   - public Map<String, ScheduleRealInfo> execPlamMap(){
637   - return carExecutePlanMap;
638   - }
639   -
640   - /**
641   - * @Title: changeCar
642   - * @Description: TODO(班次换车) 返回有更新的班次
643   - * @param @param sch
644   - * @param @param newClZbh 新的车辆自编号
645   - */
646   - public List<ScheduleRealInfo> changeCar(ScheduleRealInfo sch , String newClZbh){
647   - List<ScheduleRealInfo> ups = new ArrayList<>();
648   - String oldClzbh = sch.getClZbh();
649   - if(oldClzbh.equals(newClZbh))
650   - return ups;
651   -
652   -
653   - //变更相关映射信息
654   - nbbmScheduleMap.remove(sch.getClZbh(), sch);
655   -
656   - sch.setClZbh(newClZbh);
657   - nbbmScheduleMap.put(newClZbh, sch);
658   - nbbm2SEStationMap.put(newClZbh, sch.getQdzCode());
659   - nbbm2SEStationMap.put(newClZbh, sch.getZdzCode());
660   -
661   - //重新计算班次应到时间
662   - ups.addAll(updateQdzTimePlan(oldClzbh));
663   - ups.addAll(updateQdzTimePlan(newClZbh));
664   - return ups;
665   - }
666   -
667   - /**
668   - *
669   - * @Title: linkToSchPlan
670   - * @Description: TODO(车辆关联到班次)
671   - */
  620 + /**
  621 + * @Title: doneSum
  622 + * @Description: TODO(已完成班次总数)
  623 + */
  624 + public int doneSum(String clZbh) {
  625 + List<ScheduleRealInfo> list = nbbmScheduleMap.get(clZbh);
  626 + int rs = 0;
  627 +
  628 + for (ScheduleRealInfo sch : list) {
  629 + if (sch.getStatus() == 2 && !sch.isDestroy())
  630 + rs++;
  631 + }
  632 + return rs;
  633 + }
  634 +
  635 + /**
  636 + * @Title: prveNotExecNum
  637 + * @Description: TODO(班次之前未执行班次数量)
  638 + */
  639 + public int prveNotExecNum(ScheduleRealInfo sch) {
  640 + int n = 0;
  641 + List<ScheduleRealInfo> list = nbbmScheduleMap.get(sch.getClZbh());
  642 + for (ScheduleRealInfo s : list) {
  643 + if (s.getFcsjActual() == null && !s.isDestroy())
  644 + n++;
  645 +
  646 + if (s.getId().equals(sch.getId()))
  647 + break;
  648 + }
  649 + return n;
  650 + }
  651 +
  652 + /**
  653 + * @Title: validEndTime
  654 + * @Description: TODO(是否是有效的到达时间)
  655 + */
  656 + public boolean validEndTime(ScheduleRealInfo sch, Long ts) {
  657 + if (sch.getFcsjActualTime() != null && sch.getFcsjActualTime() > ts)
  658 + return false;
  659 +
  660 + return validTime(sch, ts);
  661 + }
  662 +
  663 + /**
  664 + * @Title: validStartTime
  665 + * @Description: TODO(是否是合适的发车时间)
  666 + */
  667 + public boolean validStartTime(ScheduleRealInfo sch, Long ts) {
  668 + if (sch.getZdsjActualTime() != null && sch.getZdsjActualTime() < ts)
  669 + return false;
  670 +
  671 + return validTime(sch, ts);
  672 + }
  673 +
  674 + public boolean validTime(ScheduleRealInfo sch, Long ts) {
  675 + List<ScheduleRealInfo> list = nbbmScheduleMap.get(sch.getClZbh());
  676 + int ci = list.indexOf(sch);
  677 + ScheduleRealInfo prve, next;
  678 + if (ci > 0) {
  679 + //之前班次实际时间不能大于该时间
  680 + for (int i = ci - 1; i >= 0; i--) {
  681 + prve = list.get(i);
  682 + if (prve.getZdsjActualTime() != null && prve.getZdsjActualTime() > ts)
  683 + return false;
  684 +
  685 + if (prve.getFcsjActualTime() != null && prve.getFcsjActualTime() > ts)
  686 + return false;
  687 + }
  688 + }
  689 +
  690 + if (ci < list.size() - 1) {
  691 + //之后班次实际时间不能小于该时间
  692 + for (int i = ci + 1; i < list.size(); i++) {
  693 + next = list.get(i);
  694 + if (next.getFcsjActualTime() != null && next.getFcsjActualTime() < ts)
  695 + return false;
  696 +
  697 + if (next.getZdsjActualTime() != null && next.getZdsjActualTime() < ts)
  698 + return false;
  699 + }
  700 + }
  701 + return true;
  702 + }
  703 +
  704 + public void save(ScheduleRealInfo sch) {
  705 + //schRepository.save(sch);
  706 + pstBuffer.add(sch);
  707 + }
  708 +
  709 +
  710 + /**
  711 + * @Title: nextByBcType
  712 + * @Description: TODO(获取下一个指定班次类型的班次)
  713 + */
  714 + public ScheduleRealInfo nextByBcType(String nbbm, String bcType) {
  715 + List<ScheduleRealInfo> list = findByBcType(nbbm, bcType);
  716 +
  717 + Collections.sort(list, schFCSJComparator);
  718 + ScheduleRealInfo sch = null;
  719 + for (ScheduleRealInfo temp : list) {
  720 + if (temp.getFcsjActual() == null)
  721 + sch = temp;
  722 + }
  723 +
  724 + return sch;
  725 + }
  726 +
  727 + public List<ScheduleRealInfo> findByBcType(String nbbm, String bcType) {
  728 + List<ScheduleRealInfo> all = nbbmScheduleMap.get(nbbm), outList = new ArrayList<>();
  729 +
  730 + for (ScheduleRealInfo sch : all) {
  731 + if (sch.getBcType().equals(bcType))
  732 + outList.add(sch);
  733 + }
  734 + return outList;
  735 + }
  736 +
  737 + public Set<String> allCar() {
  738 + return nbbmScheduleMap.keySet();
  739 + }
  740 +
  741 + public Collection<ScheduleRealInfo> findAll() {
  742 + return nbbmScheduleMap.values();
  743 + }
  744 +
  745 + public void addExecPlan(ScheduleRealInfo sch) {
  746 + if(sch != null)
  747 + carExecutePlanMap.put(sch.getClZbh(), sch);
  748 + }
  749 +
  750 + public void removeExecPlan(String clzbh) {
  751 + carExecutePlanMap.remove(clzbh);
  752 + }
  753 +
  754 + public Map<String, ScheduleRealInfo> execPlanMap() {
  755 + return carExecutePlanMap;
  756 + }
  757 +
  758 + /**
  759 + * 车辆当前执行的班次
  760 + *
  761 + * @param nbbm
  762 + * @return
  763 + */
  764 + public ScheduleRealInfo executeCurr(String nbbm) {
  765 + return carExecutePlanMap.get(nbbm);
  766 + }
  767 +
  768 + /**
  769 + * @param @param sch
  770 + * @param @param newClZbh 新的车辆自编号
  771 + * @Title: changeCar
  772 + * @Description: TODO(班次换车) 返回有更新的班次
  773 + */
  774 + public List<ScheduleRealInfo> changeCar(ScheduleRealInfo sch, String newClZbh) {
  775 + List<ScheduleRealInfo> ups = new ArrayList<>();
  776 + String oldClzbh = sch.getClZbh();
  777 + if (oldClzbh.equals(newClZbh))
  778 + return ups;
  779 +
  780 +
  781 + //变更相关映射信息
  782 + nbbmScheduleMap.remove(sch.getClZbh(), sch);
  783 +
  784 + sch.setClZbh(newClZbh);
  785 + nbbmScheduleMap.put(newClZbh, sch);
  786 + nbbm2SEStationMap.put(newClZbh, sch.getQdzCode());
  787 + nbbm2SEStationMap.put(newClZbh, sch.getZdzCode());
  788 +
  789 + //重新计算班次应到时间
  790 + ups.addAll(updateQdzTimePlan(oldClzbh));
  791 + ups.addAll(updateQdzTimePlan(newClZbh));
  792 +
  793 + //重新计算车辆当前执行班次
  794 + reCalcExecPlan(newClZbh);
  795 + reCalcExecPlan(sch.getClZbh());
  796 + return ups;
  797 + }
  798 +
  799 + public void reCalcExecPlan(String nbbm){
  800 + carExecutePlanMap.put(nbbm, schAttrCalculator.calcCurrentExecSch(nbbmScheduleMap.get(nbbm)));
  801 + }
  802 +
  803 + /**
  804 + * 是否在执行首班出场
  805 + * @param nbbm
  806 + * @return
  807 + */
  808 + public boolean isExecFirstOut(String nbbm, long time){
  809 + try {
  810 + List<ScheduleRealInfo> list = nbbmScheduleMap.get(nbbm);
  811 + ScheduleRealInfo second = list.get(2),
  812 + first = executeCurr(nbbm);
  813 +
  814 + if(first.getBcType().equals("out")
  815 + && first.getDfsjT() < second.getDfsjT()
  816 + && doneSum(nbbm) == 0 && second.getDfsjT() > time)
  817 + return true;
  818 + } catch (Exception e) {
  819 + logger.error("", e);
  820 + }
  821 +
  822 + return false;
  823 + }
  824 +
  825 + /**
  826 + * 获取班次的计划停站时间
  827 + * @param sch
  828 + * @return
  829 +
  830 + public int stopTimePlan(Object task) {
  831 +
  832 + ScheduleRealInfo sch = prev((ScheduleRealInfo) task);
  833 +
  834 + sch.getzdsj
  835 + return -1;
  836 + }*/
  837 +
  838 + /**
  839 + *
  840 + * @Title: linkToSchPlan
  841 + * @Description: TODO(车辆关联到班次)
  842 + */
672 843 /* public void linkToSchPlan(String nbbm) {
673 844 //当前GPS状态
674 845 GpsEntity gps = gpsRealData.get(BasicData.deviceId2NbbmMap.inverse().get(nbbm));
... ...
src/main/java/com/bsth/data/schedule/SchAttrCalculator.java
... ... @@ -62,13 +62,13 @@ public class SchAttrCalculator {
62 62 sch.setDfsjAll(fmtyyyyMMddHHmm.parseMillis(sch.getScheduleDateStr()+sch.getDfsj()));
63 63  
64 64 //實發時間
65   - if(sch.getFcsjActual() != null &&
  65 + if(StringUtils.isNotEmpty(sch.getFcsjActual()) &&
66 66 sch.getFcsjActual().compareTo(conf.getStartOpt()) < 0){
67 67 sch.setFcsjActualAll(fmtyyyyMMddHHmm.parseMillis(sch.getScheduleDateStr()+sch.getFcsjActual()) + DAY_TIME);
68 68 }
69 69  
70 70 //實際終點時間
71   - if(sch.getZdsjActual() != null &&
  71 + if(StringUtils.isNotEmpty(sch.getZdsjActual()) &&
72 72 sch.getZdsjActual().compareTo(conf.getStartOpt()) < 0){
73 73 sch.setZdsjActualAll(fmtyyyyMMddHHmm.parseMillis(sch.getScheduleDateStr()+sch.getZdsjActual()) + DAY_TIME);
74 74 }
... ... @@ -162,34 +162,6 @@ public class SchAttrCalculator {
162 162  
163 163 return updateList;
164 164 }
165   -
166   - /**
167   - *
168   - * @Title: connectOutSchedule
169   - * @Description: TODO(关联出场班次)
170   - */
171   - public void connectOutSchedule(List<ScheduleRealInfo> list){
172   - Collections.sort(list, new ScheduleComparator.FCSJ());
173   -
174   - int len = list.size();
175   - if(len == 0)
176   - return;
177   -
178   - ScheduleRealInfo prve = list.get(0), curr;
179   - for(int i = 1; i < len; i ++){
180   - curr = list.get(i);
181   -
182   - //出站即出场关联
183   - if(prve.getBcType().equals("out") && prve.getJhlc() == null)
184   - curr.setTwinsSch(prve);
185   -
186   - //进站即进场关联
187   - if(curr.getBcType().equals("in") && curr.getJhlc() == null)
188   - prve.setTwinsSch(curr);
189   -
190   - prve = curr;
191   - }
192   - }
193 165  
194 166 public SchAttrCalculator calcFcsjTime(ScheduleRealInfo sch) throws ParseException {
195 167 sch.setFcsjT(fmtyyyyMMddHHmm.parseMillis(sch.getRealExecDate() + sch.getFcsj()));
... ...
src/main/java/com/bsth/entity/realcontrol/LineConfig.java
... ... @@ -53,6 +53,9 @@ public class LineConfig {
53 53 /** 调度指令模板 */
54 54 private String schDirectiveTemp;
55 55  
  56 + /** 识别区间调头 */
  57 + private boolean readReverse;
  58 +
56 59 @OneToMany(cascade = CascadeType.ALL)
57 60 private Set<D80ReplyTemp> d80Temps = new HashSet<>();
58 61  
... ... @@ -140,4 +143,12 @@ public class LineConfig {
140 143 public void setD80Temps(Set<D80ReplyTemp> d80Temps) {
141 144 this.d80Temps = d80Temps;
142 145 }
  146 +
  147 + public boolean isReadReverse() {
  148 + return readReverse;
  149 + }
  150 +
  151 + public void setReadReverse(boolean readReverse) {
  152 + this.readReverse = readReverse;
  153 + }
143 154 }
... ...
src/main/java/com/bsth/entity/realcontrol/ScheduleRealInfo.java
... ... @@ -94,11 +94,6 @@ public class ScheduleRealInfo {
94 94 * 班次类型 TODO:正常班次、出场、进场、加油、区间班次、放空班次、放大站班次、两点间空驶
95 95 */
96 96 private String bcType;
97   -
98   - /** 出站即出场 , 关联的进出场班次 */
99   - @JsonIgnore
100   - @Transient
101   - private ScheduleRealInfo twinsSch;
102 97  
103 98 /** 创建人 */
104 99 @JsonIgnore
... ... @@ -258,21 +253,6 @@ public class ScheduleRealInfo {
258 253 this.ccno = ccno;
259 254 }
260 255  
261   - public static DateTimeFormatter getFmtHHmm() {
262   - return fmtHHmm;
263   - }
264   -
265   - public static void setFmtHHmm(DateTimeFormatter fmtHHmm) {
266   - ScheduleRealInfo.fmtHHmm = fmtHHmm;
267   - }
268   -
269   - public static DateTimeFormatter getFmtyyyyMMddHHmm() {
270   - return fmtyyyyMMddHHmm;
271   - }
272   -
273   - public static void setFmtyyyyMMddHHmm(DateTimeFormatter fmtyyyyMMddHHmm) {
274   - ScheduleRealInfo.fmtyyyyMMddHHmm = fmtyyyyMMddHHmm;
275   - }
276 256  
277 257 /** ----------------
278 258 @OneToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
... ... @@ -804,13 +784,13 @@ public class ScheduleRealInfo {
804 784 this.opDirectiveState = opDirectiveState;
805 785 }
806 786  
807   - public ScheduleRealInfo getTwinsSch() {
  787 +/* public ScheduleRealInfo getTwinsSch() {
808 788 return twinsSch;
809 789 }
810 790  
811 791 public void setTwinsSch(ScheduleRealInfo twinsSch) {
812 792 this.twinsSch = twinsSch;
813   - }
  793 + }*/
814 794  
815 795 public boolean isLate() {
816 796 return late;
... ...
src/main/java/com/bsth/repository/realcontrol/ScheduleRealInfoRepository.java
... ... @@ -32,7 +32,7 @@ public interface ScheduleRealInfoRepository extends BaseRepository&lt;ScheduleRealI
32 32  
33 33 //把sum(addMileage) 替换为0 数据表去掉了 add_mileage 字段
34 34 @Query(value="select new map(clZbh as clZbh,jGh as jGh,jName as jName,sum(jhlc) as zgl,"
35   - + " 0 as ksgl,count(jName) as bcs) from ScheduleRealInfo s where"
  35 + + "0 as ksgl,count(jName) as bcs) from ScheduleRealInfo s where"
36 36 + " s.xlBm = ?1 and DATE_FORMAT(s.scheduleDate,'%Y-%m-%d') = ?2 group by clZbh,jGh,jName")
37 37 List<Map<String, Object>> dailyInfo(String line,String date);
38 38  
... ... @@ -71,7 +71,7 @@ public interface ScheduleRealInfoRepository extends BaseRepository&lt;ScheduleRealI
71 71 @Query(value="select count(jName) from ScheduleRealInfo s where s.jName = ?1 and s.clZbh = ?2 and s.lpName = ?3 and sflj != 0")
72 72 int findLjbc(String jName,String clZbh,String lpName);
73 73  
74   - @Query(value="SELECT c.company,r.request_code,FROM_UNIXTIME(r.timestamp/1000,'%Y-%m-%d %T'),c.inside_code FROM bsth_v_report_80 r LEFT JOIN bsth_c_cars c ON c.equipment_code = r.device_id where FROM_UNIXTIME(r.timestamp/1000,'%Y-%m-%d') = ?2 and r.line_id like %?1% and c.inside_code like %?3%",nativeQuery=true)
  74 + @Query(value="SELECT c.company,r.request_code,FROM_UNIXTIME(r.timestamp/1000,'%Y-%m-%d %T') FROM bsth_v_report_80 r LEFT JOIN bsth_c_cars c ON c.equipment_code = r.device_id where FROM_UNIXTIME(r.timestamp/1000,'%Y-%m-%d') = ?2 and r.line_id = ?1 and c.inside_code = ?3",nativeQuery=true)
75 75 List<Object[]> account(String line,String date,String code);
76 76  
77 77 @Query(value="select s from ScheduleRealInfo s where s.xlBm = ?1 and s.scheduleDate >= str_to_date(?2,'%Y-%m-%d') "
... ... @@ -125,4 +125,4 @@ public interface ScheduleRealInfoRepository extends BaseRepository&lt;ScheduleRealI
125 125 @Query(value="select new map(xlBm as xlBm) from ScheduleRealInfo s where DATE_FORMAT(s.scheduleDate,'%Y-%m-%d') = ?1 GROUP BY xlBm ORDER BY xlBm")
126 126 List<Map<String,Object>> setDDRBGroup(String date);
127 127  
128   -}
129 128 \ No newline at end of file
  129 +}
... ...
src/main/java/com/bsth/websocket/handler/SendUtils.java
1 1 package com.bsth.websocket.handler;
2 2  
3   -import java.text.SimpleDateFormat;
4   -import java.util.ArrayList;
5   -import java.util.Date;
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 3 import com.alibaba.fastjson.JSONObject;
16 4 import com.bsth.data.BasicData;
17 5 import com.bsth.data.LineConfigData;
18   -import com.bsth.data.schedule.DayOfSchedule;
  6 +import com.bsth.data.gpsdata.arrival.entity.SignalState;
19 7 import com.bsth.entity.directive.D80;
20 8 import com.bsth.entity.realcontrol.ScheduleRealInfo;
21 9 import com.fasterxml.jackson.core.JsonProcessingException;
22 10 import com.fasterxml.jackson.databind.ObjectMapper;
  11 +import org.slf4j.Logger;
  12 +import org.slf4j.LoggerFactory;
  13 +import org.springframework.beans.factory.annotation.Autowired;
  14 +import org.springframework.stereotype.Component;
  15 +
  16 +import java.text.SimpleDateFormat;
  17 +import java.util.*;
23 18  
24 19 @Component
25 20 public class SendUtils{
... ... @@ -40,7 +35,7 @@ public class SendUtils{
40 35 */
41 36 public void sendFcsj(ScheduleRealInfo sch) {
42 37 //处理出站即出场的班次
43   - connectOutSchTime(sch);
  38 + //connectOutSchTime(sch);
44 39  
45 40 Map<String, Object> map = new HashMap<>();
46 41 map.put("fn", "faChe");
... ... @@ -86,7 +81,7 @@ public class SendUtils{
86 81 */
87 82 public void sendZdsj(ScheduleRealInfo sch, ScheduleRealInfo nextSch, int finish) {
88 83 //处理进站即进场的班次
89   - connectInSchTime(sch);
  84 + //connectInSchTime(sch);
90 85  
91 86 Map<String, Object> map = new HashMap<>();
92 87 map.put("fn", "zhongDian");
... ... @@ -103,12 +98,30 @@ public class SendUtils{
103 98 logger.error("", e);
104 99 }
105 100 }
  101 +
  102 + /**
  103 + * 推送班次信号状态
  104 + * @param state
  105 + */
  106 + public void sendSignalState(SignalState state){
  107 + Map<String, Object> map = new HashMap<>();
  108 + map.put("fn", "signal_state");
  109 + map.put("data", state);
  110 +
  111 + ObjectMapper mapper = new ObjectMapper();
  112 +
  113 + try {
  114 + socketHandler.sendMessageToLine(state.getLineCode(), mapper.writeValueAsString(map));
  115 + } catch (Exception e) {
  116 + logger.error("", e);
  117 + }
  118 + }
106 119  
107 120 /**
108 121 *
109 122 * @Title: shiftSchedule
110 123 * @Description: TODO(线路翻班通知)
111   - */
  124 +
112 125 public void shiftSchedule(String lineCode){
113 126 Map<String, Object> map = new HashMap<>();
114 127 map.put("fn", "systemNotice");
... ... @@ -124,7 +137,7 @@ public class SendUtils{
124 137 logger.error("", e);
125 138 }
126 139 }
127   -
  140 + */
128 141 /**
129 142 *
130 143 * @Title: sendDirectiveToPage
... ... @@ -157,39 +170,4 @@ public class SendUtils{
157 170 list.add(sch);
158 171 refreshSch(list);
159 172 }
160   -
161   -
162   - //出站即出场
163   - public void connectOutSchTime(ScheduleRealInfo sch){
164   - try{
165   - ScheduleRealInfo twins = sch.getTwinsSch();
166   - if(twins != null
167   - && lineConfigData.get(sch.getXlBm()).getOutConfig() == 2
168   - && twins.getBcType().equals("out")){
169   -
170   - twins.setFcsjActualAll(sch.getFcsjActualTime());
171   - //刷新关联的出场班次
172   - //refreshSch(twins);
173   - }
174   - }catch(Exception e){
175   - logger.error("", e);
176   - }
177   - }
178   -
179   - //进站即出场
180   - public void connectInSchTime(ScheduleRealInfo sch){
181   - try{
182   - ScheduleRealInfo twins = sch.getTwinsSch();
183   - if(twins != null
184   - && lineConfigData.get(sch.getXlBm()).getOutConfig() == 2
185   - && twins.getBcType().equals("in")){
186   -
187   - twins.setZdsjActualAll(sch.getZdsjActualTime());
188   - //刷新关联的出场班次
189   - //refreshSch(twins);
190   - }
191   - }catch(Exception e){
192   - logger.error("", e);
193   - }
194   - }
195 173 }
... ...
src/main/resources/application-dev.properties
... ... @@ -7,13 +7,13 @@ spring.jpa.hibernate.naming_strategy= org.hibernate.cfg.ImprovedNamingStrategy
7 7 #DATABASE
8 8 spring.jpa.database= MYSQL
9 9 spring.jpa.show-sql= true
10   -spring.datasource.driver-class-name= com.mysql.jdbc.Driver
11   -spring.datasource.url= jdbc:mysql://127.0.0.1/qp_control?useUnicode=true&characterEncoding=utf-8&useSSL=false
12   -spring.datasource.username= root
13   -spring.datasource.password=
14   -#spring.datasource.url= jdbc:mysql://192.168.168.117/pd_control?useUnicode=true&characterEncoding=utf-8&useSSL=false
  10 +#spring.datasource.driver-class-name= com.mysql.jdbc.Driver
  11 +#spring.datasource.url= jdbc:mysql://192.168.168.201/mh_control?useUnicode=true&characterEncoding=utf-8&useSSL=false
15 12 #spring.datasource.username= root
16   -#spring.datasource.password= root
  13 +#spring.datasource.password= 123456
  14 +spring.datasource.url= jdbc:mysql://localhost/mh_control?useUnicode=true&characterEncoding=utf-8&useSSL=false
  15 +spring.datasource.username= root
  16 +spring.datasource.password= root
17 17 #DATASOURCE
18 18 spring.datasource.max-active=100
19 19 spring.datasource.max-idle=8
... ...
src/main/resources/ms-jdbc.properties
... ... @@ -4,6 +4,6 @@
4 4 #ms.mysql.password= 123456
5 5  
6 6 ms.mysql.driver= com.mysql.jdbc.Driver
7   -ms.mysql.url= jdbc:mysql://192.168.168.171:3306/ms?useUnicode=true&characterEncoding=utf-8
  7 +ms.mysql.url= jdbc:mysql://192.168.168.117:3306/ms?useUnicode=true&characterEncoding=utf-8
8 8 ms.mysql.username= root
9   -ms.mysql.password= root2jsp
10 9 \ No newline at end of file
  10 +ms.mysql.password= root
11 11 \ No newline at end of file
... ...
src/main/resources/static/real_control_v2/css/line_schedule.css
... ... @@ -55,7 +55,7 @@
55 55 padding: 0;
56 56 }
57 57  
58   -.line_schedule .schedule-wrap i.uk-icon-question-circle{
  58 +.line_schedule .schedule-wrap .header-title i.uk-icon-question-circle{
59 59 cursor: pointer;
60 60 font-size: 14px;
61 61 color: #cccaca;
... ... @@ -528,6 +528,7 @@ div.drop-rail[data-type=&quot;car&quot;]:before {
528 528  
529 529 dl.relevance-active dd:nth-child(n+2) {
530 530 background: #f1efef !important;
  531 + color: #333;
531 532 }
532 533  
533 534 dl.relevance-active.intimity dd:nth-child(n+2) {
... ... @@ -1022,4 +1023,27 @@ dd.fcsjActualCell div.last-sch-sunken span._badge{
1022 1023 .ct_table>.ct_table_body dl.dl-last-sch:hover div.last-sch-sunken,
1023 1024 .ct_table>.ct_table_body dl.dl-last-sch.context-menu-active div.last-sch-sunken{
1024 1025 background: #f5fbff;
  1026 +}
  1027 +
  1028 +dd.fcsjActualCell{
  1029 + position: relative;
  1030 +}
  1031 +
  1032 +i.signal_state_icon{
  1033 + position: absolute;
  1034 + right: 5px;
  1035 + top: 7px;
  1036 + box-shadow: 0px 0px 11px 0 rgba(0, 0, 0, 0.2), -1px 3px 8px 0 rgba(0, 0, 0, 0.19);
  1037 + text-indent: 0;
  1038 + border-radius: 15px;
  1039 + cursor: pointer;
  1040 +}
  1041 +
  1042 +i.signal_state_icon.uk-icon-question-circle{
  1043 + color: #e85252 !important;
  1044 +}
  1045 +
  1046 +i.signal_state_icon.uk-icon-reply{
  1047 + color: #4134e3 !important;
  1048 + box-shadow: none;
1025 1049 }
1026 1050 \ No newline at end of file
... ...
src/main/resources/static/real_control_v2/fragments/line_schedule/sch_table.html
... ... @@ -83,7 +83,7 @@
83 83 <dd data-sort-val={{sch.dfsjT}} dbclick dbclick-type="dfsj" dbclick-val="{{sch.dfsj}}">
84 84 {{sch.dfsj}}
85 85 </dd>
86   - <dd class="
  86 + <dd data-uk-observe class="
87 87 {{if sch.status==-1}}
88 88 tl-qrlb
89 89 {{else if sch.status==2}}
... ... @@ -130,7 +130,7 @@
130 130 </script>
131 131  
132 132 <script id="line-schedule-sfsj-temp" type="text/html">
133   - <dd class="
  133 + <dd data-uk-observe class="
134 134 {{if status==-1}}
135 135 tl-qrlb
136 136 {{else if status==2}}
... ...
src/main/resources/static/real_control_v2/fragments/north/nav/signal_state_config.html 0 → 100644
  1 +<div class="uk-modal ct-form-modal" id="signal_state_config-modal">
  2 + <div class="uk-modal-dialog" style="width: 530px;">
  3 + <a href="" class="uk-modal-close uk-close"></a>
  4 + <div class="uk-modal-header">
  5 + <h2>信号标记设置</h2></div>
  6 +
  7 + <p style="border-bottom: 1px solid #efefef;color: grey;padding-bottom: 9px;">
  8 + <small>
  9 + <i class="uk-icon-question-circle"> </i>
  10 + 设置项将会保存在本地客户端,清理缓存和更换电脑会重置.</small>
  11 + </p>
  12 + <form class="uk-form uk-form-horizontal">
  13 + <div class="uk-grid">
  14 + <div class="uk-width-2-3 uk-container-center">
  15 + <div class="uk-form-row">
  16 + <label class="uk-form-label">是否启用</label>
  17 + <div class="uk-form-controls">
  18 + <select name="enable">
  19 + <option value="1">启用</option>
  20 + <option value="0">禁用</option>
  21 + </select>
  22 + </div>
  23 + </div>
  24 + </div>
  25 + </div>
  26 +
  27 + <div class="uk-modal-footer uk-text-right" style="margin-bottom: -20px;">
  28 + <button type="button" class="uk-button uk-modal-close">取消</button>
  29 + <button type="submit" class="uk-button uk-button-primary"><i class="uk-icon-check"></i> &nbsp;保存</button>
  30 + </div>
  31 + </form>
  32 + </div>
  33 +
  34 + <script>
  35 + (function() {
  36 + var modal = '#signal_state_config-modal';
  37 + var f = $('form', modal);
  38 +
  39 + $(modal).on('init', function(e, data) {
  40 + var val = gb_signal_state.isEnable()?1:0;
  41 + $('[name=enable]', f).val(val);
  42 + });
  43 +
  44 + f.formValidation(gb_form_validation_opts);
  45 + f.on('success.form.fv', function(e) {
  46 + e.preventDefault();
  47 + var data = $(this).serializeJSON();
  48 +
  49 + if(data.enable=='1')
  50 + gb_signal_state.enable();
  51 + else
  52 + gb_signal_state.disable();
  53 +
  54 + UIkit.modal(modal).hide();
  55 + });
  56 +
  57 + })();
  58 + </script>
  59 +</div>
0 60 \ No newline at end of file
... ...
src/main/resources/static/real_control_v2/js/data/json/north_toolbar.json
... ... @@ -93,6 +93,11 @@
93 93 "id": 3.1,
94 94 "text": "TTS",
95 95 "event": "tts_config"
  96 + },
  97 + {
  98 + "id": 3.2,
  99 + "text": "信号标记",
  100 + "event": "signal_state"
96 101 }
97 102 ]
98 103 }
... ...
src/main/resources/static/real_control_v2/js/line_schedule/layout.js
... ... @@ -22,7 +22,7 @@ var gb_line_layout = (function() {
22 22 };
23 23  
24 24 //图例icon tootip
25   - $(document).on('mouseenter', '.schedule-wrap i.uk-icon-question-circle', function() {
  25 + $(document).on('mouseenter', '.schedule-wrap .header-title i.uk-icon-question-circle', function() {
26 26 $(this).qtip({
27 27 show: {
28 28 ready: true,
... ...
src/main/resources/static/real_control_v2/js/line_schedule/sch_table.js
... ... @@ -236,6 +236,8 @@ var gb_schedule_table = (function () {
236 236 else
237 237 $(dds[8]).html('');
238 238  
  239 + //信号状态标记
  240 + gb_signal_state.marker_sch(sch);
239 241 //班次是车辆的最后一班
240 242 if(dl.hasClass('dl-last-sch'))
241 243 markerLastSch([sch]);
... ... @@ -446,6 +448,7 @@ var gb_schedule_table = (function () {
446 448 return car_yfwf_map[lineCode];
447 449 },
448 450 scroToDl: scroToDl,
449   - reset_drag_active_all: reset_drag_active_all
  451 + reset_drag_active_all: reset_drag_active_all,
  452 + getDl: getDl
450 453 };
451 454 })();
... ...
src/main/resources/static/real_control_v2/js/main.js
1 1 //主调和监控模式
2 2 var operationMode = window.localStorage.getItem('operationMode');
3   -if(operationMode == 0){
  3 +if (operationMode == 0) {
4 4 $('body>.north').addClass('monitor');
5 5 $(document).on('ajaxSend', interceptPOST);
6 6 }
... ... @@ -8,8 +8,8 @@ else
8 8 $('body>.north').addClass('main');
9 9  
10 10 //拦截POST请求
11   -function interceptPOST(e, xhr, t){
12   - if(t && (t.method == 'POST' || t.type == 'POST')){
  11 +function interceptPOST(e, xhr, t) {
  12 + if (t && (t.method == 'POST' || t.type == 'POST')) {
13 13 console.log(e, xhr, t);
14 14 xhr.abort();
15 15 notify_err('监控模式!');
... ... @@ -18,54 +18,56 @@ function interceptPOST(e, xhr, t){
18 18  
19 19 /* main js */
20 20 var gb_main_ep = new EventProxy(),
21   - res_load_ep = EventProxy.create('load_data_basic', 'load_tab', 'load_home_layout', 'load_home_line_panel', function() {
  21 + res_load_ep = EventProxy.create('load_data_basic', 'load_tab', 'load_home_layout', 'load_home_line_panel', function () {
22 22 var eq = gb_main_ep;
23 23 // basic data end
24 24 eq.once('data-basic', g_emit('tab'));
25 25 // tabs
26   - eq.once('tab', function() {
  26 + eq.once('tab', function () {
27 27 gb_tabs.init(
28 28 g_emit('home-layout')
29 29 );
30 30 });
31 31 //home layout
32   - eq.once('home-layout', function() {
  32 + eq.once('home-layout', function () {
33 33 gb_home_layout.layout(
34 34 g_emit('home-line-panel')
35 35 );
36 36 });
37 37 //home line panel
38   - eq.once('home-line-panel', function() {
  38 + eq.once('home-line-panel', function () {
39 39 gb_home_line_panel.init(g_emit('gps-time-refresh'));
40 40 });
41 41  
42 42 //start fixed time refresh gps
43   - eq.once('gps-time-refresh', function() {
  43 + eq.once('gps-time-refresh', function () {
44 44 gb_data_gps.fixedTimeRefresh();
45 45 g_emit('line-schedule-layout')();
46 46 });
47 47  
48 48 //line schedule layout
49   - eq.once('line-schedule-layout', function() {
  49 + eq.once('line-schedule-layout', function () {
50 50 gb_line_layout.layout(g_emit('render-sch-table'));
51 51 });
52 52  
53 53 //render schedule table
54   - eq.once('render-sch-table', function() {
55   - gb_schedule_table.show(function(){
56   - //搜索框
57   - gb_sch_search.init();
  54 + eq.once('render-sch-table', function () {
  55 + gb_schedule_table.show(function () {
  56 + //搜索框
  57 + gb_sch_search.init();
  58 + //加载信号状态
  59 + gb_signal_state.init();
58 60 });
59 61  
60 62 //嵌入地图页面
61   - $('li.map-panel','#main-tab-content').load('/real_control_v2/mapmonitor/real.html');
62   -
  63 + $('li.map-panel', '#main-tab-content').load('/real_control_v2/mapmonitor/real.html');
  64 + //弹出更新说明
63 65 showUpdateDescription();
64 66 });
65 67  
66 68 function g_emit(id) {
67 69 console.log('g_emit [' + id + ']');
68   - return function() {
  70 + return function () {
69 71 console.log('eq.emitLater(' + id + ')');
70 72 return eq.emitLater(id);
71 73 };
... ... @@ -73,17 +75,17 @@ var gb_main_ep = new EventProxy(),
73 75 });
74 76  
75 77 //modal hide remove dom
76   -$(document).on('hide.uk.modal', '.uk-modal', function() {
  78 +$(document).on('hide.uk.modal', '.uk-modal', function () {
77 79 $(this).remove();
78 80 });
79 81  
80 82 $(document).on('click', '.ct-bottom-drawer-close', function () {
81   - $(this).parents('.ct-bottom-drawer').removeClass('open');
  83 + $(this).parents('.ct-bottom-drawer').removeClass('open');
82 84 });
83 85  
84 86 function connectArr(arr, separator, transFun) {
85 87 var rs = '';
86   - $.each(arr, function(i, item) {
  88 + $.each(arr, function (i, item) {
87 89 if (transFun)
88 90 item = transFun(item);
89 91 rs += (separator + item);
... ... @@ -102,26 +104,26 @@ var gb_form_validation_opts = {
102 104 };
103 105  
104 106  
105   -var notify_wait = function(t) {
  107 +var notify_wait = function (t) {
106 108 UIkit.notify("<i class='uk-icon-spinner uk-icon-spin'></i> " + t, {
107 109 status: 'info'
108 110 });
109 111 };
110 112  
111   -var notify_succ = function(t) {
  113 +var notify_succ = function (t) {
112 114 UIkit.notify("<i class='uk-icon-check'></i> " + t, {
113 115 status: 'success'
114 116 });
115 117 };
116 118  
117   -var notify_err = function(t) {
  119 +var notify_err = function (t) {
118 120 UIkit.notify("<i class='uk-icon-times'></i> " + t, {
119 121 status: 'danger'
120 122 });
121 123 };
122 124  
123   -var alt_confirm = function(content, succ, okBtn) {
124   - var modalEl = UIkit.modal.confirm(content, function() {
  125 +var alt_confirm = function (content, succ, okBtn) {
  126 + var modalEl = UIkit.modal.confirm(content, function () {
125 127 succ && succ();
126 128 modalEl.hide();
127 129 }, {
... ... @@ -129,15 +131,15 @@ var alt_confirm = function(content, succ, okBtn) {
129 131 Ok: okBtn,
130 132 Cancel: '取消'
131 133 }
132   - ,center: true
  134 + , center: true
133 135 });
134 136 };
135 137  
136   -var isArray = function(obj) {
  138 +var isArray = function (obj) {
137 139 return Object.prototype.toString.call(obj) === '[object Array]';
138 140 };
139 141  
140   -var notify_err_form = function(t, form) {
  142 +var notify_err_form = function (t, form) {
141 143 $('.uk-alert-danger', form).remove();
142 144 $('.uk-modal-footer', form).before('<div class="uk-alert uk-alert-danger" data-uk-alert="">' +
143 145 '<a href="" class="uk-alert-close uk-close"></a>' +
... ... @@ -147,29 +149,29 @@ var notify_err_form = function(t, form) {
147 149 enable_submit_btn(form);
148 150 };
149 151  
150   -var enable_submit_btn = function(form) {
  152 +var enable_submit_btn = function (form) {
151 153 var subBtn = $('button[type=submit]', form);
152 154 if (subBtn) {
153 155 subBtn.removeClass('disabled').removeAttr('disabled');
154 156 }
155 157 }
156 158  
157   -var disabled_submit_btn = function(form) {
  159 +var disabled_submit_btn = function (form) {
158 160 var subBtn = $('button[type=submit]', form);
159 161 if (subBtn) {
160   - subBtn.addClass('disabled').attr('disabled','disabled');
  162 + subBtn.addClass('disabled').attr('disabled', 'disabled');
161 163 }
162 164 };
163 165  
164   -var show_modal = function(id, dom) {
  166 +var show_modal = function (id, dom) {
165 167 $(document.body).append(dom);
166 168 return UIkit.modal(id, {
167 169 bgclose: false
168 170 }).show();
169 171 };
170 172  
171   -var open_modal = function(pageUrl, data, opt) {
172   - $.get(pageUrl, function(dom) {
  173 +var open_modal = function (pageUrl, data, opt) {
  174 + $.get(pageUrl, function (dom) {
173 175 if (!$(dom).hasClass('uk-modal')) {
174 176 alert('无效的dom片段!');
175 177 return;
... ... @@ -188,20 +190,20 @@ var open_modal = function(pageUrl, data, opt) {
188 190  
189 191 function showUpdateDescription() {
190 192 //更新说明
191   - var updateDescription={
  193 + var updateDescription = {
192 194 date: '2016-12-20',
193 195 text: '<h5>1、回场子任务开放使用。</h5>'
194 196 };
195 197  
196 198 var storage = window.localStorage
197   - ,key = 'update_' + updateDescription.date;
  199 + , key = 'update_' + updateDescription.date;
198 200 var text = storage.getItem(key);
199   - if(!text){
200   - var modal = '<div class="uk-modal" id="update-description-modal">'+
201   - ' <div class="uk-modal-dialog">'+
202   - ' <a class="uk-modal-close uk-close"></a>'+
203   - ' <div class="uk-modal-header">'+
204   - ' <h2>'+updateDescription.date+' 更新说明</h2></div>'+updateDescription.text+
  201 + if (!text) {
  202 + var modal = '<div class="uk-modal" id="update-description-modal">' +
  203 + ' <div class="uk-modal-dialog">' +
  204 + ' <a class="uk-modal-close uk-close"></a>' +
  205 + ' <div class="uk-modal-header">' +
  206 + ' <h2>' + updateDescription.date + ' 更新说明</h2></div>' + updateDescription.text +
205 207 ' </div>';
206 208  
207 209 show_modal('#update-description-modal', modal);
... ...
src/main/resources/static/real_control_v2/js/north/toolbar.js
... ... @@ -71,6 +71,9 @@ var gb_northToolbar = (function() {
71 71 },
72 72 gps_play_back: function () {
73 73 gb_map_play_back.initParams();
  74 + },
  75 + signal_state: function () {
  76 + open_modal('/real_control_v2/fragments/north/nav/signal_state_config.html', {}, modal_opts);
74 77 }
75 78 }
76 79 })();
... ...
src/main/resources/static/real_control_v2/js/signal_state/signal_state.js 0 → 100644
  1 +/**
  2 + * GPS信号状态
  3 + * @type {{}}
  4 + */
  5 +var gb_signal_state = (function () {
  6 + var storage = window.localStorage;
  7 +
  8 + $(document).on('click', 'i.signal_state_icon', function (e) {
  9 + e.stopPropagation();
  10 + });
  11 +
  12 + var signal_state_data = {};
  13 + var enable = true;
  14 + //读取本地状态
  15 + var locStatus = storage.getItem("signal_state_enable");
  16 + if (locStatus && locStatus=='0')
  17 + enable = false;
  18 +
  19 + var init = function () {
  20 + $.get('/signalState/multi', {idx: gb_data_basic.line_idx}, function (rs) {
  21 + //按班次ID分组
  22 + signal_state_data = gb_common.groupBy(rs, 'schId');
  23 +
  24 + for (var schId in signal_state_data) {
  25 + multi_render(signal_state_data[schId]);
  26 + }
  27 + });
  28 + };
  29 +
  30 + var multi_render = function (list) {
  31 + if (!enable)
  32 + return;
  33 +
  34 + if (!list || list.length == 0)
  35 + return;
  36 + var line = list[0].lineCode
  37 + , schId = list[0].schId;
  38 +
  39 + var sch = gb_schedule_table.findScheduleByLine(line)[schId];
  40 + var dl = gb_schedule_table.getDl(sch);
  41 + var icon = 'question-circle';
  42 + var t = '';
  43 + $.each(list, function () {
  44 + t += (this.text + '<br>');
  45 + });
  46 +
  47 + if (list.length == 1 && list[0].type == 'route_reverse')
  48 + icon = 'reply';
  49 +
  50 + var dd = $('dd.fcsjActualCell', dl);
  51 + var se = $('i.signal_state_icon', dd);
  52 + if (se && se.length > 0)
  53 + se.remove();
  54 +
  55 + dd.append('<i data-uk-tooltip title="' + t + '" class="uk-icon-' + icon + ' signal_state_icon"></i>');
  56 + };
  57 +
  58 + var put = function (obj) {
  59 + if (!signal_state_data[obj.schId]) {
  60 + signal_state_data[obj.schId] = [];
  61 + }
  62 +
  63 + signal_state_data[obj.schId].push(obj);
  64 + multi_render(signal_state_data[obj.schId]);
  65 + };
  66 +
  67 + var marker_sch = function (sch) {
  68 + var list = signal_state_data[sch.id];
  69 + if (list) {
  70 + multi_render(list);
  71 + }
  72 + };
  73 +
  74 + var clearAll = function () {
  75 + $('.signal_state_icon').remove();
  76 + };
  77 +
  78 + return {
  79 + init: init,
  80 + put: put,
  81 + marker_sch: marker_sch,
  82 + isEnable: function () {
  83 + return enable;
  84 + },
  85 + disable: function () {
  86 + enable = false;
  87 + storage.setItem("signal_state_enable", 0);
  88 +
  89 + clearAll();
  90 + },
  91 + enable: function () {
  92 + enable = true;
  93 + storage.setItem("signal_state_enable", 1);
  94 + for (var schId in signal_state_data) {
  95 + multi_render(signal_state_data[schId]);
  96 + }
  97 + }
  98 + };
  99 +})();
0 100 \ No newline at end of file
... ...
src/main/resources/static/real_control_v2/js/websocket/sch_websocket.js
... ... @@ -26,7 +26,7 @@ var gb_sch_websocket = (function () {
26 26 var data = {
27 27 operCode: 'register_line',
28 28 idx: gb_data_basic.line_idx
29   - }
  29 + };
30 30 schSock.send(JSON.stringify(data));
31 31 console.log('regListen....', data);
32 32 }
... ... @@ -45,21 +45,21 @@ var gb_sch_websocket = (function () {
45 45 var calcUntreated = function (lineCode) {
46 46 var size = $('li.line_schedule[data-id=' + lineCode + '] .sys-mailbox .sys-mail-item').length;
47 47 $('#badge_untreated_num_' + lineCode).text(size);
48   - }
  48 + };
49 49  
50 50 var calcUntreatedAll = function () {
51 51 $('#main-tab-content li.line_schedule').each(function () {
52 52 calcUntreated($(this).data('id'));
53 53 });
54   - }
  54 + };
55 55  
56 56  
57 57 //80协议上报
58 58 var report80 = function (msg) {
59 59 msg.dateStr = moment(msg.timestamp).format('HH:mm');
60 60 msg.text = gb_common.reqCode80[msg.data.requestCode];
61   - if(!msg.text)
62   - msg.text='(未知的请求码 '+msg.data.requestCode+')';
  61 + if (!msg.text)
  62 + msg.text = '(未知的请求码 ' + msg.data.requestCode + ')';
63 63  
64 64 var $item = $(temps['sys-note-80-temp'](msg));
65 65 findMailBox(msg.data.lineId).prepend($item);
... ... @@ -68,7 +68,7 @@ var gb_sch_websocket = (function () {
68 68 gb_tts.speak(ttsMsg, msg.data.lineId);
69 69  
70 70 calcUntreated(msg.data.lineId);
71   - }
  71 + };
72 72  
73 73 var waitRemoves = [];
74 74 //车辆发出
... ... @@ -89,7 +89,7 @@ var gb_sch_websocket = (function () {
89 89 gb_schedule_table.calc_yfwf_num(msg.t.xlBm);
90 90  
91 91 calcUntreated(msg.t.xlBm);
92   - }
  92 + };
93 93  
94 94 //到达终点
95 95 var zhongDian = function (msg) {
... ... @@ -107,20 +107,20 @@ var gb_sch_websocket = (function () {
107 107 gb_tts.speak(ttsMsg, msg.t.xlBm);
108 108  
109 109 calcUntreated(msg.t.xlBm);
110   - }
  110 + };
111 111  
112 112 //服务器通知刷新班次
113 113 var refreshSch = function (msg) {
114 114 gb_schedule_table.updateSchedule(msg.ts);
115 115 /*//重新计算应发未发
116   - var idx={};
117   - $.each(msg.ts, function(i, t){
118   - if(idx[t.xlBm])
119   - return true;
120   - gb_schedule_table.calc_yfwf_num(t.xlBm);
121   - idx[t.xlBm]=1;
122   - });*/
123   - }
  116 + var idx={};
  117 + $.each(msg.ts, function(i, t){
  118 + if(idx[t.xlBm])
  119 + return true;
  120 + gb_schedule_table.calc_yfwf_num(t.xlBm);
  121 + idx[t.xlBm]=1;
  122 + });*/
  123 + };
124 124  
125 125 //80消息确认
126 126 var d80Confirm = function (msg) {
... ... @@ -129,12 +129,17 @@ var gb_sch_websocket = (function () {
129 129 calcUntreated(msg.lineId);
130 130 //重新计算应发未发
131 131 gb_schedule_table.calc_yfwf_num(msg.lineId);
132   - }
  132 + };
133 133  
134 134 //指令状态改变
135   - var directiveStatus = function(msg){
  135 + var directiveStatus = function (msg) {
136 136 gb_schedule_table.updateSchedule(msg.t);
137   - }
  137 + };
  138 +
  139 + //班次信号状态
  140 + var signalState = function (msg) {
  141 + gb_signal_state.put(msg.data);
  142 + };
138 143  
139 144 var msgHandle = {
140 145 report80: report80,
... ... @@ -142,8 +147,9 @@ var gb_sch_websocket = (function () {
142 147 zhongDian: zhongDian,
143 148 refreshSch: refreshSch,
144 149 d80Confirm: d80Confirm,
145   - directive: directiveStatus
146   - }
  150 + directive: directiveStatus,
  151 + signal_state: signalState
  152 + };
147 153  
148 154 function currentSecond() {
149 155 return Date.parse(new Date()) / 1000;
... ... @@ -167,15 +173,15 @@ var gb_sch_websocket = (function () {
167 173 $(this).parents('.sys-note-42').remove();
168 174  
169 175 var size = $(this).parents('.sys-mailbox').find('.sys-mail-item').length
170   - ,lineCode = $(this).parents('li.line_schedule').data('id');
  176 + , lineCode = $(this).parents('li.line_schedule').data('id');
171 177  
172 178 $('#badge_untreated_num_' + lineCode).text(size);
173 179 });
174 180  
175 181 //42消息点击
176 182 $(document).on('click', '.sys-mailbox .sys-note-42', function () {
177   - var lineCode=$(this).parents('li.line_schedule').data('id')
178   - ,id=$(this).data('id');
  183 + var lineCode = $(this).parents('li.line_schedule').data('id')
  184 + , id = $(this).data('id');
179 185 var sch = gb_schedule_table.findScheduleByLine(lineCode)[id];
180 186 var dl = gb_schedule_table.scroToDl(sch);
181 187 //高亮
... ... @@ -205,7 +211,7 @@ var gb_sch_websocket = (function () {
205 211 notify_succ(rs.msg);
206 212 cb && cb();
207 213 });
208   - }
  214 + };
209 215  
210 216  
211 217 //定时到离站信使清理掉
... ...
src/main/resources/static/real_control_v2/main.html
... ... @@ -142,6 +142,8 @@
142 142 <script src="/real_control_v2/assets/echarts-3/echarts.js"></script>
143 143 <!-- Geolib -->
144 144 <script src="/real_control_v2/geolib/geolib.js"></script>
  145 +
  146 + <script src="/real_control_v2/js/signal_state/signal_state.js"></script>
145 147 </body>
146 148  
147 149 </html>
... ...
src/main/resources/static/real_control_v2/mapmonitor/fragments/playback/run.html
... ... @@ -148,10 +148,14 @@
148 148 var logs = [];
149 149 for (var i = 0; i <= ei; i++) {
150 150 trailArray.push(new BMap.Point(gpsArray[i].bd_lon, gpsArray[i].bd_lat));
151   - if(i > 0 && logs[logs.length - 1].road.ROAD_CODE == gpsArray[i].road.ROAD_CODE)
152   - logs.pop();
153   -
154   - logs.push(gpsArray[i]);
  151 + try {
  152 + if(i > 0 && logs[logs.length - 1].road.ROAD_CODE == gpsArray[i].road.ROAD_CODE)
  153 + logs.pop();
  154 + }
  155 + catch (e){}
  156 +
  157 + if(gpsArray[i].road)
  158 + logs.push(gpsArray[i]);
155 159 }
156 160 trailPolyline.setPath(trailArray);
157 161  
... ... @@ -302,6 +306,9 @@
302 306 gb_ct_table.fixedHead(logWrap);
303 307  
304 308 function logWrite(gps, prve) {
  309 + if(!gps.road || !gps.road.ROAD_CODE)
  310 + return;
  311 +
305 312 var code = gps.road.ROAD_CODE;
306 313 if (!prve || code != prve.road.ROAD_CODE) {
307 314 logPanel.append('<dl data-code="' + code + '" ><dd>' + gps.timeStr + '</dd><dd>' + gps.speed + '</dd><dd>' + gps.road.ROAD_NAME + '</dd><dd>正常</dd></dl>');
... ...