Commit b11fe36f066da3347ddc492f5c6f8e6331d61ef9

Authored by 潘钊
1 parent 8c1b17f9

update

Showing 24 changed files with 492 additions and 136 deletions
src/main/java/com/bsth/data/BasicData.java
... ... @@ -45,7 +45,7 @@ public class BasicData implements CommandLineRunner {
45 45 public static Map<String, String> stationCode2NameMap;
46 46  
47 47 //线路起终点对照(线路编码_上下行_起终点) 1024_0_B (1024上行起点)
48   - public static Map<String, String> lineSEPointMap;
  48 + //public static Map<String, String> lineSEPointMap;
49 49  
50 50 //车辆和线路对照
51 51 public static Map<String, Line> nbbm2LineMap;
... ...
src/main/java/com/bsth/data/gpsdata/GpsRealData.java
... ... @@ -66,7 +66,7 @@ public class GpsRealData implements CommandLineRunner {
66 66 @Override
67 67 public void run(String... arg0) throws Exception {
68 68 logger.info("gpsDataLoader,20,5");
69   - //Application.mainServices.scheduleWithFixedDelay(gpsDataLoader, 20, 5, TimeUnit.SECONDS);
  69 + //Application.mainServices.scheduleWithFixedDelay(gpsDataLoader, 20, 6, TimeUnit.SECONDS);
70 70 }
71 71  
72 72 public void put(GpsEntity gps) {
... ...
src/main/java/com/bsth/data/gpsdata/SignalStateData.java
1 1 package com.bsth.data.gpsdata;
2 2  
3 3 import com.bsth.data.gpsdata.arrival.entity.SignalState;
  4 +import com.bsth.websocket.handler.SendUtils;
4 5 import com.google.common.base.Splitter;
5 6 import com.google.common.collect.ArrayListMultimap;
  7 +import org.springframework.beans.factory.annotation.Autowired;
6 8 import org.springframework.stereotype.Component;
7 9  
8 10 import java.util.ArrayList;
... ... @@ -15,11 +17,15 @@ import java.util.List;
15 17 @Component
16 18 public class SignalStateData {
17 19  
  20 + @Autowired
  21 + SendUtils sendUtils;
  22 +
18 23 private static ArrayListMultimap<String, SignalState> listMultimap = ArrayListMultimap.create();
19 24  
20 25 public void put(SignalState state){
21 26 listMultimap.put(state.getLineCode(), state);
22 27 //推送到客户端
  28 + sendUtils.sendSignalState(state);
23 29 }
24 30  
25 31 public List<SignalState> get(String idx){
... ...
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 //线路路段走向
... ... @@ -206,4 +206,16 @@ public class GeoCacheData {
206 206 }
207 207 return cds;
208 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 + }
209 221 }
210 222 \ No newline at end of file
... ...
src/main/java/com/bsth/data/gpsdata/arrival/SignalHandle.java
... ... @@ -19,43 +19,44 @@ public abstract class SignalHandle {
19 19 return prevs != null && prevs.size() > 0 && prevs.getTail() != null;
20 20 }
21 21  
  22 + protected boolean isDriftSignal(GpsEntity gps) {
  23 + return gps.getLat() == 0 || gps.getLon() == 0;
  24 + }
  25 +
22 26 /**
23 27 * 是不是异常信号
24 28 *
25 29 * @param gps
26   - * @return
27   - */
28   - protected boolean isAbnormal(GpsEntity gps) {
29   - return gps.getLat() == 0 || gps.getLon() == 0;
30   - }
  30 + * @return protected boolean isAbnormal(GpsEntity gps) {
  31 + return gps.getLat() == 0 || gps.getLon() == 0;
  32 + }*/
31 33  
32 34 /**
33 35 * 连续异常信号个数统计
34 36 *
35 37 * @param prevs
36   - * @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 + * }
37 57 */
38   - protected int abnormalCount(CircleQueue<GpsEntity> prevs) {
39   - int count = 0;
40   -
41   - if (!isNotEmpty(prevs))
42   - return count;
43   -
44   - GpsEntity[] array = (GpsEntity[]) prevs.getQueue();
45   - GpsEntity gps;
46   - for (int i = array.length - 1; i > 0; i--) {
47   - gps = array[i];
48 58  
49   - if (isAbnormal(gps))
50   - count++;
51   - else
52   - break;
53   - }
54   -
55   - return count;
56   - }
57   -
58   - protected void transformUpdown(GpsEntity gps, ScheduleRealInfo sch){
  59 + protected void transformUpdown(GpsEntity gps, ScheduleRealInfo sch) {
59 60 int updown = Integer.parseInt(sch.getXlDir());
60 61 List<StationRoute> srs = GeoCacheData.getStationRoute(sch.getXlBm(), updown);
61 62 StationRoute station = GeoUtils.gpsInStation(gps, srs);
... ... @@ -64,4 +65,25 @@ public abstract class SignalHandle {
64 65 gps.setStopNo(station.getCode());
65 66 }
66 67 }
  68 +
  69 + /**
  70 + * 是否是从异常状态恢复的第一个信号
  71 + *
  72 + * @param gps
  73 + * @param prevs
  74 + * @return
  75 + */
  76 + protected boolean abnormalRecovery(GpsEntity gps, CircleQueue<GpsEntity> prevs) {
  77 + if (prevs == null || prevs.size() == 0)
  78 + return false;
  79 +
  80 + GpsEntity prev = prevs.getTail();
  81 + //从漂移状态恢复
  82 + if (isDriftSignal(prev)
  83 + && !isDriftSignal(gps)) {
  84 + return true;
  85 + }
  86 +
  87 + return false;
  88 + }
67 89 }
68 90 \ No newline at end of file
... ...
src/main/java/com/bsth/data/gpsdata/arrival/entity/RouteReverse.java
... ... @@ -24,6 +24,9 @@ public class RouteReverse {
24 24 //是否闭合
25 25 private boolean close;
26 26  
  27 + //信号不明确
  28 + private boolean vague;
  29 +
27 30 public int getCount() {
28 31 return count;
29 32 }
... ... @@ -79,4 +82,12 @@ public class RouteReverse {
79 82 public void setNbbm(String nbbm) {
80 83 this.nbbm = nbbm;
81 84 }
  85 +
  86 + public boolean isVague() {
  87 + return vague;
  88 + }
  89 +
  90 + public void setVague(boolean vague) {
  91 + this.vague = vague;
  92 + }
82 93 }
83 94 \ No newline at end of file
... ...
src/main/java/com/bsth/data/gpsdata/arrival/entity/SignalState.java
... ... @@ -15,7 +15,7 @@ public class SignalState {
15 15  
16 16 private Long st;
17 17  
18   - private Long checkTime;
  18 + //private Long checkTime;
19 19  
20 20 private Long schId;
21 21  
... ... @@ -37,10 +37,13 @@ public class SignalState {
37 37 * @return
38 38 */
39 39 public static SignalState reverseSignalSTate(ScheduleRealInfo sch, RouteReverse reverse) {
  40 + if(reverse.isVague())
  41 + return null;
  42 +
40 43 SignalState state = new SignalState();
41 44 state.setSchId(sch.getId());
42 45 state.setType("route_reverse");
43   - state.setCheckTime(System.currentTimeMillis());
  46 + //state.setCheckTime(System.currentTimeMillis());
44 47  
45 48 String stationName = BasicData.stationCode2NameMap.get(sch.getXlBm() + "_" + sch.getXlDir() + "_" + reverse.getTurned());
46 49 state.setText(fmtHHmm.print(reverse.getZt()) + " 从 " + stationName + " 站掉头");
... ... @@ -50,26 +53,19 @@ public class SignalState {
50 53 return state;
51 54 }
52 55  
53   - public static SignalState abnormalSignalSTate(ScheduleRealInfo sch, SignalAbnormal signalAbnormal){
  56 + public static SignalState abnormalSignalSTate(ScheduleRealInfo sch, SignalAbnormal signalAbnormal) {
54 57 SignalState state = new SignalState();
55 58 state.setSchId(sch.getId());
56 59 state.setType("abnormal_signal");
57   - state.setCheckTime(signalAbnormal.getCt());
  60 + //state.setCheckTime(signalAbnormal.getCt());
58 61 state.setLineCode(sch.getXlBm());
59 62  
60   - String text = "信号";
  63 + String text = (fmtHHmm.print(signalAbnormal.getSt()) + " ~ " + fmtHHmm.print(signalAbnormal.getEt()));
61 64 String abnormType = signalAbnormal.getAbnormalType();
62   - if(abnormType.equals("drift"))
63   - text += "漂移";
64   - else if(abnormType.equals("reconnection"))
65   - text += "掉线";
66   -
67   - text += ("至" + fmtHHmm.print(signalAbnormal.getEt()) + "恢复正常");
68   -
69   - if(signalAbnormal.getOutOrIn() == 0)
70   - text += "约在 00:00 分左右发车";
71   - else if(signalAbnormal.getOutOrIn() == 1)
72   - text += "约在 00:00 分左右到达终点";
  65 + if (abnormType.equals("drift"))
  66 + text += "(GPS无效)";
  67 + else if (abnormType.equals("reconnection"))
  68 + text += "(信号丢失)";
73 69  
74 70 state.setText(text);
75 71 state.setSignalAbnormal(signalAbnormal);
... ... @@ -84,15 +80,6 @@ public class SignalState {
84 80 this.type = type;
85 81 }
86 82  
87   - public long getCheckTime() {
88   - return checkTime;
89   - }
90   -
91   - public void setCheckTime(long checkTime) {
92   - this.checkTime = checkTime;
93   - }
94   -
95   -
96 83 public long getSchId() {
97 84 return schId;
98 85 }
... ...
src/main/java/com/bsth/data/gpsdata/arrival/handlers/InOutStationSignalHandle.java
... ... @@ -5,11 +5,13 @@ import com.bsth.data.gpsdata.GpsEntity;
5 5 import com.bsth.data.gpsdata.arrival.SignalHandle;
6 6 import com.bsth.data.gpsdata.arrival.utils.CircleQueue;
7 7 import com.bsth.data.gpsdata.arrival.utils.ScheduleSignalState;
  8 +import com.bsth.data.gpsdata.arrival.utils.SignalSchPlanMatcher;
8 9 import com.bsth.data.schedule.DayOfSchedule;
9 10 import com.bsth.entity.realcontrol.LineConfig;
10 11 import com.bsth.entity.realcontrol.ScheduleRealInfo;
11 12 import com.bsth.service.directive.DirectiveService;
12 13 import com.bsth.websocket.handler.SendUtils;
  14 +import org.apache.commons.lang3.StringUtils;
13 15 import org.slf4j.Logger;
14 16 import org.slf4j.LoggerFactory;
15 17 import org.springframework.beans.factory.annotation.Autowired;
... ... @@ -39,8 +41,22 @@ public class InOutStationSignalHandle extends SignalHandle{
39 41 @Autowired
40 42 ScheduleSignalState scheduleSignalState;
41 43  
  44 + @Autowired
  45 + SignalSchPlanMatcher signalSchPlanMatcher;
  46 +
  47 + private final static int MAX_BEFORE_TIME = 1000 * 60 * 72;
  48 +
42 49 @Override
43 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 + }
44 60  
45 61 if(isNotEmpty(prevs)){
46 62 GpsEntity prev = prevs.getTail();
... ... @@ -90,11 +106,23 @@ public class InOutStationSignalHandle extends SignalHandle{
90 106 ScheduleRealInfo sch = dayOfSchedule.executeCurr(gps.getNbbm());
91 107 String qdzCode = sch.getQdzCode();
92 108  
  109 + //首班出场最多提前1.2小时
  110 + if(dayOfSchedule.isFirstOut(sch) && sch.getDfsjT() - gps.getTimestamp() > MAX_BEFORE_TIME)
  111 + return;
93 112  
94 113 //起点发车
95 114 if(qdzCode != null && prev.getStopNo().equals(qdzCode)
96 115 && !willDepart(gps, prev, sch)){
97 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 + //实发时间
98 126 sch.setFcsjActualAll(gps.getTimestamp());
99 127 //通知客户端
100 128 sendUtils.sendFcsj(sch);
... ... @@ -106,7 +134,7 @@ public class InOutStationSignalHandle extends SignalHandle{
106 134 logger.info("班次:" + sch.getDfsj() + "发车, 时间:" + sch.getFcsjActual());
107 135 }
108 136 else if(sch.getBcType().equals("out")){
109   - ScheduleRealInfo next = dayOfSchedule.next(sch);
  137 + ScheduleRealInfo next = dayOfSchedule.nextSame(sch);
110 138 if(prev.getStopNo().equals(next.getQdzCode())){
111 139 //发下一个班次
112 140 dayOfSchedule.addExecPlan(next);
... ... @@ -115,14 +143,15 @@ public class InOutStationSignalHandle extends SignalHandle{
115 143 }
116 144 }
117 145  
  146 +
118 147 private void outStationAndOutPark(ScheduleRealInfo sch){
119 148 LineConfig config = lineConfigData.get(sch.getXlBm());
120 149 if (config != null && config.getOutConfig() == 2) {
121 150 //出站既出场
122 151 ScheduleRealInfo schPrev = dayOfSchedule.prev(sch);
123 152 if (schPrev != null && schPrev.getBcType().equals("out")) {
124   - schPrev.setFcsjActualAll(sch.getFcsjActual());
125   - schPrev.setZdsjActualAll(sch.getFcsjActual());
  153 + schPrev.setFcsjActualAll(sch.getFcsjActualTime());
  154 + schPrev.setZdsjActualAll(sch.getFcsjActualTime());
126 155  
127 156 sendUtils.refreshSch(schPrev);
128 157 }
... ... @@ -139,6 +168,10 @@ public class InOutStationSignalHandle extends SignalHandle{
139 168  
140 169 if(gps.getStopNo().equals(sch.getZdzCode())){
141 170  
  171 + //实达时间不覆盖
  172 + if(StringUtils.isNotEmpty(sch.getZdsjActual()))
  173 + return;
  174 +
142 175 sch.setZdsjActualAll(gps.getTimestamp());
143 176 //已完成班次数
144 177 int doneSum = dayOfSchedule.doneSum(sch.getClZbh());
... ... @@ -148,7 +181,7 @@ public class InOutStationSignalHandle extends SignalHandle{
148 181 //持久化
149 182 dayOfSchedule.save(sch);
150 183 //下发调度指令
151   - //directiveService.send60Dispatch(next, doneSum, "到站@系统");
  184 + directiveService.send60Dispatch(next, doneSum, "到站@系统");
152 185  
153 186 //准备执行下一个班次
154 187 if (next != null) {
... ... @@ -174,8 +207,8 @@ public class InOutStationSignalHandle extends SignalHandle{
174 207 LineConfig config = lineConfigData.get(sch.getXlBm());
175 208 if (next.getBcType().equals("in") &&
176 209 config != null && config.getOutConfig() == 2) {
177   - next.setFcsjActualAll(sch.getZdsjActual());
178   - next.setZdsjActualAll(sch.getZdsjActual());
  210 + next.setFcsjActualAll(sch.getZdsjActualTime());
  211 + next.setZdsjActualAll(sch.getZdsjActualTime());
179 212  
180 213 sendUtils.refreshSch(next);
181 214 }
... ...
src/main/java/com/bsth/data/gpsdata/arrival/handlers/OfflineSignalHandle.java
... ... @@ -22,7 +22,7 @@ public class OfflineSignalHandle extends SignalHandle{
22 22 @Override
23 23 public boolean handle(GpsEntity gps, CircleQueue<GpsEntity> prevs) {
24 24 //漂移信号不管
25   - if(gps.getLat() == 0 || gps.getLon() == 0){
  25 + if(isDriftSignal(gps)){
26 26 gps.setSignalState("drift");
27 27 return true;
28 28 }
... ...
src/main/java/com/bsth/data/gpsdata/arrival/handlers/ReverseSignalHandle.java
... ... @@ -38,7 +38,9 @@ public class ReverseSignalHandle extends SignalHandle {
38 38 if (isReverse(gps, prev)) {
39 39 RouteReverse reverse = reverseSearch(prevs, gps);
40 40  
41   - if (reverse.getCount() >= 4) {
  41 + if (reverse.getCount() >= 4
  42 + && reverse.isClose()
  43 + && !GeoCacheData.isEndStation(gps.getLineId(), gps.getUpDown(), reverse.getTurned())) {
42 44 scheduleSignalState.reverseAnalyse(reverse);
43 45 }
44 46 }
... ... @@ -57,6 +59,7 @@ public class ReverseSignalHandle extends SignalHandle {
57 59 int count = 0;
58 60 String path = "";
59 61 long zt = 0L;
  62 + boolean half = false;
60 63  
61 64 //当前站点
62 65 StationRoute curr = GeoCacheData.getRouteCode(gps), sr;
... ... @@ -73,13 +76,17 @@ public class ReverseSignalHandle extends SignalHandle {
73 76 sr = GeoCacheData.getRouteCode(prev);
74 77  
75 78 if (sr.getRouteSort() > curr.getRouteSort()) {
  79 + if(half){
  80 + routeReverse.setVague(true);
  81 + }
  82 +
76 83 path += (curr.getCode() + ",");
77 84 count++;
78 85 zt = prev.getTimestamp();
79   - }
80   - else if (sr.getRouteSort() < curr.getRouteSort()) {
81   - if(routeReverse.getTurned() == null){
  86 + } else if (sr.getRouteSort() < curr.getRouteSort()) {
  87 + if (routeReverse.getTurned() == null) {
82 88 routeReverse.setTurned(curr.getCode());
  89 + half = true;
83 90 }
84 91  
85 92 path += (curr.getCode() + ",");
... ...
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
... ... @@ -104,8 +104,12 @@ public class ScheduleSignalState {
104 104 }
105 105 }
106 106  
  107 + public void signalRetrospect(GpsEntity gps) {
  108 + signalRetrospect(gps, dayOfSchedule.executeCurr(gps.getNbbm()));
  109 + }
  110 +
107 111 /**
108   - * 有到离站无发车时信号追溯
  112 + * 信号追溯
109 113 *
110 114 * @param gps
111 115 * @param sch
... ... @@ -113,15 +117,15 @@ public class ScheduleSignalState {
113 117 public void signalRetrospect(GpsEntity gps, ScheduleRealInfo sch) {
114 118 //回放数据,是否有掉线或者漂移
115 119 CircleQueue<GpsEntity> queue = GeoCacheData.getGps(gps.getNbbm());
116   - if (queue == null || queue.size() == 0 || gps.getInstation() == 0)
  120 + if (queue == null || queue.size() == 0 /*|| gps.getInstation() == 0*/)
117 121 return;
118 122  
119 123 //起始时间点
120 124 long st = 0;
121 125 ScheduleRealInfo prev = dayOfSchedule.prev(sch);
122 126  
123   - if(prev != null){
124   - if(prev.getZdsjActual() != null)
  127 + if (prev != null) {
  128 + if (prev.getZdsjActual() != null)
125 129 st = prev.getZdsjActualTime();
126 130 else
127 131 st = (GeoCacheData.midwayStation(gps.getLineId(), gps.getUpDown(), sch.getQdzCode(), gps.getStopNo()).size() + 1) * (1000 * 60 * 5);
... ... @@ -136,34 +140,112 @@ public class ScheduleSignalState {
136 140  
137 141 String gpsState = "";
138 142 GpsEntity tempGps, nearGps = null;
139   - for (int i = len - 1; i > 0; i--) {
  143 + int i = len - 1;
  144 + for (; i >= 0; i--) {
140 145 tempGps = (GpsEntity) array[i];
141 146  
142 147 gpsState = tempGps.getSignalState();
143   - if(gpsState.equals("drift")){
  148 + if (gpsState.equals("truncation"))
  149 + break;
  150 + else if (gpsState.equals("drift")) {
144 151 nearGps = (GpsEntity) array[i + 1];
145 152 break;
146   - }
147   - else if(gpsState.equals("reconnection")){
  153 + } else if (gpsState.equals("reconnection")) {
148 154 nearGps = tempGps;
149 155 break;
150 156 }
151 157  
152   - if(tempGps.getTimestamp() < st)
  158 + if (tempGps.getTimestamp() < st)
153 159 break;
154 160 }
155 161  
156   - if(nearGps != null){
157   - SignalAbnormal signalAbnormal = new SignalAbnormal();
158   - signalAbnormal.setCt(gps.getTimestamp());
159   - signalAbnormal.setEt(nearGps.getTimestamp());
160   - signalAbnormal.setAbnormalType(gpsState);
161   - signalAbnormal.setDestCode(sch.getQdzCode());
162   - signalAbnormal.setOutOrIn(0);
  162 + if (nearGps != null && i > 0) {
  163 + createSignalAbnormal(gpsState, nearGps, i, array, sch);
  164 + }
  165 + }
163 166  
164   - //记录信号状态
165   - SignalState signalState = SignalState.abnormalSignalSTate(sch, signalAbnormal);
166   - signalStateData.put(signalState);
  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;
167 175 }
168 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 + }
169 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
... ... @@ -60,7 +60,7 @@ 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("SXC-YD009"))
  63 + /*if(nbbm.equals("YT-CD008"))
64 64 new RecoveryThread(listMap.get(nbbm), count).run();*/
65 65 }
66 66  
... ... @@ -150,8 +150,6 @@ public class GpsDataRecovery implements ApplicationContextAware {
150 150 CircleQueue<GpsEntity> prevs;
151 151  
152 152 for (GpsEntity gps : list) {
153   - /* if(gps.getTimestamp() == 1483081260000L)
154   - System.out.println("aaa");*/
155 153  
156 154 prevs = GeoCacheData.getGps(gps.getNbbm());
157 155 //掉线处理
... ... @@ -166,6 +164,8 @@ public class GpsDataRecovery implements ApplicationContextAware {
166 164 //进出站动作处理
167 165 inOutStationSignalHandle.handle(gps, prevs);
168 166 GeoCacheData.putGps(gps);
  167 +
  168 + //Thread.sleep(50);
169 169 }
170 170 } catch (Exception e) {
171 171 logger.error("", e);
... ...
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 }
... ...
src/main/java/com/bsth/websocket/handler/SendUtils.java
... ... @@ -3,7 +3,7 @@ package com.bsth.websocket.handler;
3 3 import com.alibaba.fastjson.JSONObject;
4 4 import com.bsth.data.BasicData;
5 5 import com.bsth.data.LineConfigData;
6   -import com.bsth.data.schedule.DayOfSchedule;
  6 +import com.bsth.data.gpsdata.arrival.entity.SignalState;
7 7 import com.bsth.entity.directive.D80;
8 8 import com.bsth.entity.realcontrol.ScheduleRealInfo;
9 9 import com.fasterxml.jackson.core.JsonProcessingException;
... ... @@ -98,12 +98,30 @@ public class SendUtils{
98 98 logger.error("", e);
99 99 }
100 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 + }
101 119  
102 120 /**
103 121 *
104 122 * @Title: shiftSchedule
105 123 * @Description: TODO(线路翻班通知)
106   - */
  124 +
107 125 public void shiftSchedule(String lineCode){
108 126 Map<String, Object> map = new HashMap<>();
109 127 map.put("fn", "systemNotice");
... ... @@ -119,7 +137,7 @@ public class SendUtils{
119 137 logger.error("", e);
120 138 }
121 139 }
122   -
  140 + */
123 141 /**
124 142 *
125 143 * @Title: sendDirectiveToPage
... ...
src/main/resources/static/real_control_v2/css/line_schedule.css
... ... @@ -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) {
... ... @@ -1032,14 +1033,17 @@ i.signal_state_icon{
1032 1033 position: absolute;
1033 1034 right: 5px;
1034 1035 top: 7px;
1035   - color: #e85252 !important;
1036 1036 box-shadow: 0px 0px 11px 0 rgba(0, 0, 0, 0.2), -1px 3px 8px 0 rgba(0, 0, 0, 0.19);
1037 1037 text-indent: 0;
1038 1038 border-radius: 15px;
1039 1039 cursor: pointer;
1040 1040 }
1041 1041  
  1042 +i.signal_state_icon.uk-icon-question-circle{
  1043 + color: #e85252 !important;
  1044 +}
  1045 +
1042 1046 i.signal_state_icon.uk-icon-reply{
1043   - color: #4134e3;
  1047 + color: #4134e3 !important;
1044 1048 box-shadow: none;
1045 1049 }
1046 1050 \ No newline at end of file
... ...
src/main/resources/static/real_control_v2/fragments/line_schedule/sch_table.html
... ... @@ -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/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]);
... ...
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
... ... @@ -3,41 +3,97 @@
3 3 * @type {{}}
4 4 */
5 5 var gb_signal_state = (function () {
  6 + var storage = window.localStorage;
6 7  
7 8 $(document).on('click', 'i.signal_state_icon', function (e) {
8 9 e.stopPropagation();
9 10 });
10 11  
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;
12 18  
13 19 var init = function () {
14 20 $.get('/signalState/multi', {idx: gb_data_basic.line_idx}, function (rs) {
15 21 //按班次ID分组
16 22 signal_state_data = gb_common.groupBy(rs, 'schId');
17   - console.log('信号数据', signal_state_data);
18 23  
19   - $.each(rs, function () {
20   - renderIcon(this);
21   - });
22   - //for(var schId)
  24 + for (var schId in signal_state_data) {
  25 + multi_render(signal_state_data[schId]);
  26 + }
23 27 });
24 28 };
25 29  
26   - var renderIcon = function (sState) {
27   - var sch = gb_schedule_table.findScheduleByLine(sState.lineCode)[sState.schId];
  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];
28 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';
29 49  
30 50 var dd = $('dd.fcsjActualCell', dl);
31   - $('i.signal_state_icon', dd).remove();
32   - var icon='question-circle';
  51 + var se = $('i.signal_state_icon', dd);
  52 + if (se && se.length > 0)
  53 + se.remove();
33 54  
34   - if(sState.type=='route_reverse')
35   - icon = 'reply';
  55 + dd.append('<i data-uk-tooltip title="' + t + '" class="uk-icon-' + icon + ' signal_state_icon"></i>');
  56 + };
36 57  
37   - dd.append('<i data-uk-tooltip title="'+sState.text+'" class="uk-icon-'+icon+' signal_state_icon"></i>');
  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();
38 76 };
39 77  
40 78 return {
41   - init: init
  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 + }
42 98 };
43 99 })();
44 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 //定时到离站信使清理掉
... ...