Commit 2ba8f995a8f33c5fb9012cb6d3cb575796b2241f

Authored by 潘钊
1 parent f1e889a7

update

src/main/java/com/bsth/ServiceStateTest.java
... ... @@ -3,8 +3,8 @@ package com.bsth;
3 3 public class ServiceStateTest {
4 4  
5 5 public static void main(String[] args) {
6   - System.out.println("运营状态:" + getService(33554432));
7   - System.out.println("上下行:" + getUpOrDown(33554432));
  6 + System.out.println("运营状态:" + getService(603979776));
  7 + System.out.println("上下行:" + getUpOrDown(603979776));
8 8 }
9 9  
10 10 /**
... ...
src/main/java/com/bsth/Test2.java 0 → 100644
  1 +package com.bsth;
  2 +
  3 +public class Test2 {
  4 +
  5 + public static void main(String[] args) {
  6 +
  7 + for(int i = 0; i < 20; i ++){
  8 + new MyThread(i + "").start();
  9 + }
  10 + }
  11 +
  12 + public static class MyThread extends Thread {
  13 +
  14 + private String name ;
  15 +
  16 + public MyThread(String name) {
  17 + this.name = name;
  18 + }
  19 +
  20 + @Override
  21 + public void run() {
  22 + method(name);
  23 + }
  24 + }
  25 +
  26 + public static void method(String name){
  27 + System.out.println("线程" + name + "开始...");
  28 + int a = 0;
  29 + for(int i = 0; i < 1000; i ++){
  30 + a ++;
  31 + }
  32 + a--;
  33 + System.out.println("线程" + name + "结束... a = " + a);
  34 + }
  35 +}
... ...
src/main/java/com/bsth/controller/directive/DirectiveController.java
... ... @@ -4,10 +4,6 @@ import java.util.List;
4 4 import java.util.Map;
5 5  
6 6 import org.springframework.beans.factory.annotation.Autowired;
7   -import org.springframework.data.domain.Page;
8   -import org.springframework.data.domain.PageRequest;
9   -import org.springframework.data.domain.Sort;
10   -import org.springframework.data.domain.Sort.Direction;
11 7 import org.springframework.web.bind.annotation.RequestMapping;
12 8 import org.springframework.web.bind.annotation.RequestMethod;
13 9 import org.springframework.web.bind.annotation.RequestParam;
... ...
src/main/java/com/bsth/controller/directive/UpstreamEntrance.java
... ... @@ -3,6 +3,7 @@ package com.bsth.controller.directive;
3 3 import org.slf4j.Logger;
4 4 import org.slf4j.LoggerFactory;
5 5 import org.springframework.beans.factory.annotation.Autowired;
  6 +import org.springframework.context.annotation.Scope;
6 7 import org.springframework.web.bind.annotation.RequestMapping;
7 8 import org.springframework.web.bind.annotation.RequestMethod;
8 9 import org.springframework.web.bind.annotation.RequestParam;
... ... @@ -25,6 +26,7 @@ import com.bsth.entity.directive.DirectiveReponse;
25 26 */
26 27 @RestController
27 28 @RequestMapping("/control")
  29 +@Scope("prototype")
28 30 public class UpstreamEntrance {
29 31  
30 32 Logger logger = LoggerFactory.getLogger(this.getClass());
... ...
src/main/java/com/bsth/data/arrival/AnalyseArrivalData.java
... ... @@ -73,7 +73,7 @@ public class AnalyseArrivalData {
73 73 else if(curr.getTs() - prve.getTs() < SCH_TIME){
74 74 if(prve.getUpDown() == curr.getUpDown()){
75 75 //信号漂移,出站无效
76   - if(prve.getStopNo().equals(prve.getStopNo())
  76 + if(curr.getStopNo().equals(prve.getStopNo())
77 77 && prve.getInOut() == 1 && curr.getInOut() == 0
78 78 && curr.getTs() - prve.getTs() < SHIFT_TIME){
79 79 prve.setEnable(false);
... ...
src/main/java/com/bsth/data/arrival/ArrivalData_GPS.java
... ... @@ -122,7 +122,7 @@ public class ArrivalData_GPS implements CommandLineRunner{
122 122 logger.info(lineCode + " 清除到离站数据 ," + count);
123 123 }
124 124  
125   - public static List<ArrivalEntity> findByNbbm(String nbbm){
  125 + public synchronized static List<ArrivalEntity> findByNbbm(String nbbm){
126 126 return startAndEndMaps.get(nbbm);
127 127 }
128 128  
... ...
src/main/java/com/bsth/data/arrival/ArrivalEntity.java
1 1 package com.bsth.data.arrival;
2 2  
3   -import java.text.SimpleDateFormat;
4 3 import java.util.Date;
5 4  
  5 +import com.bsth.data.BasicData;
  6 +import com.bsth.util.DateUtils;
  7 +
6 8 /**
7 9 *
8 10 * @ClassName: ArrivalEntity
... ... @@ -46,6 +48,14 @@ public class ArrivalEntity {
46 48  
47 49 private boolean tcc;
48 50  
  51 + //是否被纠正
  52 + private boolean correct;
  53 +
  54 + private String correctText;
  55 +
  56 + /** -1 则信号有效,但程序标记为不使用 */
  57 + private int flag = 0;
  58 +
49 59 public ArrivalEntity(){}
50 60  
51 61 public ArrivalEntity(String deviceId, long ts, String lineCode, int upDown, String stopNo, int inOut, long createDate,
... ... @@ -74,11 +84,15 @@ public class ArrivalEntity {
74 84 return this.toString().hashCode();
75 85 }*/
76 86  
77   -static SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
78 87  
79 88 @Override
80 89 public String toString() {
81   - return sdf.format(new Date(this.ts)) + "_" + this.deviceId + "_" + this.inOut + "_" + this.stopName;
  90 + try {
  91 + return "["+BasicData.deviceId2NbbmMap.get(this.deviceId)+", "+DateUtils.sdfHHmm.format(new Date(this.ts))
  92 + +","+(this.getUpDown()==0?"上行":"下行")+","+(this.inOut==0?"进":"出")+","+this.stopNo+" ("+this.stopName+")]";
  93 + } catch (Exception e) {
  94 + return "";
  95 + }
82 96 }
83 97  
84 98 public String getLineCode() {
... ... @@ -180,4 +194,32 @@ static SimpleDateFormat sdf = new SimpleDateFormat(&quot;yyyy-MM-dd HH:mm:ss&quot;);
180 194 public void setTcc(boolean tcc) {
181 195 this.tcc = tcc;
182 196 }
  197 +
  198 + public boolean isOutTcc() {
  199 + return isTcc() && inOut == 1;
  200 + }
  201 +
  202 + public boolean isCorrect() {
  203 + return correct;
  204 + }
  205 +
  206 + public void setCorrect(boolean correct) {
  207 + this.correct = correct;
  208 + }
  209 +
  210 + public String getCorrectText() {
  211 + return correctText;
  212 + }
  213 +
  214 + public void setCorrectText(String correctText) {
  215 + this.correctText = correctText;
  216 + }
  217 +
  218 + public Integer getFlag() {
  219 + return flag;
  220 + }
  221 +
  222 + public void setFlag(Integer flag) {
  223 + this.flag = flag;
  224 + }
183 225 }
... ...
src/main/java/com/bsth/data/directive/DirectiveCreator.java
... ... @@ -81,8 +81,9 @@ public class DirectiveCreator {
81 81 }
82 82  
83 83  
84   - static SimpleDateFormat sdfMMddHHmm = new SimpleDateFormat("MMddHHmm");
85 84 public static D60 createD60_02(String nbbm, String text, int upDown, int state, Date alarmTime){
  85 + SimpleDateFormat sdfMMddHHmm = new SimpleDateFormat("MMddHHmm");
  86 +
86 87 Long timestamp = System.currentTimeMillis();
87 88  
88 89 Short company = Short.parseShort(BasicData.nbbm2CompanyCodeMap.get(nbbm));
... ...
src/main/java/com/bsth/data/match/Arrival2Schedule.java
1 1 package com.bsth.data.match;
2 2  
  3 +import java.text.SimpleDateFormat;
3 4 import java.util.ArrayList;
4 5 import java.util.Collections;
5 6 import java.util.List;
6 7 import java.util.Set;
7 8  
  9 +import org.slf4j.Logger;
  10 +import org.slf4j.LoggerFactory;
8 11 import org.springframework.beans.BeansException;
9 12 import org.springframework.context.ApplicationContext;
10 13 import org.springframework.context.ApplicationContextAware;
... ... @@ -19,26 +22,25 @@ import com.bsth.entity.realcontrol.ScheduleRealInfo;
19 22 import com.bsth.service.directive.DirectiveService;
20 23 import com.bsth.websocket.handler.SendUtils;
21 24  
  25 +/**
  26 + *
  27 + * @ClassName: Arrival2Schedule
  28 + * @Description: TODO(到离站数据 和 计划班次进行匹配 注意线程安全!!!!)
  29 + * @author PanZhao
  30 + * @date 2016年8月28日 上午1:13:02
  31 + *
  32 + */
22 33 @Component
23 34 public class Arrival2Schedule implements ApplicationContextAware {
24 35  
25 36 private static DayOfSchedule dayOfSchedule;
26   -
27   -
28   - private static ScheduleComparator.FCSJ schComparator;
29   - private static ArrivalComparator arrComparator;
30   - private static MatchResultComparator mrComparator;;
31 37 private static SendUtils sendUtils;
32 38 private static DirectiveService directiveService;
33 39 private final static int ONE_MINUTE = 1000 * 60;
34 40 //定一个4小时的范围,基本能对正常班次进行容错。主要防止早上停车场GPS飘导致完成晚上的进场班次
35 41 private final static int FOUR_HOURS = 1000 * 60 * 60 * 4;
36 42  
37   - static{
38   - schComparator = new ScheduleComparator.FCSJ();
39   - arrComparator = new ArrivalComparator();
40   - mrComparator = new MatchResultComparator();
41   - }
  43 + private static Logger logger = LoggerFactory.getLogger(Arrival2Schedule.class);
42 44  
43 45 /**
44 46 *
... ... @@ -58,27 +60,39 @@ public class Arrival2Schedule implements ApplicationContextAware {
58 60 public SchMatchThread(String nbbm){
59 61 this.nbbm = nbbm;
60 62 }
  63 +
  64 + //排序器
  65 + private ScheduleComparator.FCSJ schComparator = new ScheduleComparator.FCSJ();
  66 + private ArrivalComparator arrComparator = new ArrivalComparator();
  67 + private MatchResultComparator mrComparator = new MatchResultComparator();
  68 + private SimpleDateFormat sdfyyyyMMddHHmm = new SimpleDateFormat("yyyy-MM-ddHH:mm");
  69 +
61 70 @Override
62 71 public void run() {
63   - if(nbbm.equals("YT-CD002")){
64   - System.out.println("debugger..");
65   - }
66   -
67 72 //班次列表
68 73 List<ScheduleRealInfo> schList = dayOfSchedule.findByNbbm(nbbm);
69 74 //进出起终点数据
70 75 List<ArrivalEntity> arrList = ArrivalData_GPS.findByNbbm(nbbm);
  76 +
  77 + if(schList.size() == 0 || arrList.size() == 0)
  78 + return;
  79 +
71 80 //排序
72 81 Collections.sort(schList, schComparator);
73 82 Collections.sort(arrList, arrComparator);
74 83 //过滤班次
75 84 schList = matchFilter(schList);
76 85  
  86 + //检查并修正首班出场终点信号,可能会出现走向异常
  87 + correctFirstSignal(schList, arrList);
  88 +
  89 +
77 90 //用实际来匹配计划
78 91 for(ArrivalEntity arr : arrList){
79 92 match(arr, schList);
80 93 }
81 94 }
  95 +
82 96 private void match(ArrivalEntity arr, List<ScheduleRealInfo> schList) {
83 97  
84 98 if(arr.getInOut() == 1)
... ... @@ -104,6 +118,9 @@ public class Arrival2Schedule implements ApplicationContextAware {
104 118 }
105 119  
106 120 private void matchOut(ArrivalEntity arr, List<ScheduleRealInfo> schList){
  121 + if(arr.getFlag() == -1)
  122 + return;
  123 +
107 124 List<MatchResult> mrs = new ArrayList<>();
108 125 ScheduleRealInfo sch;
109 126 MatchResult mr;
... ... @@ -139,11 +156,15 @@ public class Arrival2Schedule implements ApplicationContextAware {
139 156 Collections.sort(mrs, mrComparator);
140 157 mr = mrs.get(0);
141 158  
142   - mr.sch.setFcsjActualAll(mr.ts);
143   - //通知客户端
144   - sendUtils.sendFcsj(mr.sch);
145   - //持久化
146   - dayOfSchedule.save(mr.sch);
  159 + //漂移判定
  160 + if(driftCheck(mr, arr)){
  161 +
  162 + mr.sch.setFcsjActualAll(mr.ts);
  163 + //通知客户端
  164 + sendUtils.sendFcsj(mr.sch);
  165 + //持久化
  166 + dayOfSchedule.save(mr.sch);
  167 + }
147 168 }
148 169 }
149 170  
... ... @@ -191,6 +212,10 @@ public class Arrival2Schedule implements ApplicationContextAware {
191 212 next.setQdzArrDateSJ(mr.sch.getZdsjActual());
192 213 //下发调度指令
193 214 directiveService.send60Dispatch(next, doneSum, "到站@系统");
  215 +
  216 + //起点既停车场的进场班次
  217 + if(next.getBcType().equals("in") && next.getJhlc() == null)
  218 + next.setFcsjActualAll(mr.ts);
194 219 }
195 220 else//下发文本指令(已结束运营)
196 221 directiveService.send60Phrase(nbbm, "到达终点 " + mr.sch.getZdzName() + ",已完成当日所有排班。", "系统");
... ... @@ -200,6 +225,80 @@ public class Arrival2Schedule implements ApplicationContextAware {
200 225 dayOfSchedule.save(mr.sch);
201 226 }
202 227 }
  228 +
  229 + /**
  230 + *
  231 + * @Title: correctFirstSignal
  232 + * @Description: TODO(检查并纠正首班出场到离站)
  233 + */
  234 + private final static long TEN_MINUTES = 1000 * 60 * 10;
  235 + private void correctFirstSignal(List<ScheduleRealInfo> schList, List<ArrivalEntity> arrList) {
  236 + ScheduleRealInfo sch = schList.get(0);
  237 + ArrivalEntity arr = arrList.get(0);
  238 +
  239 + //有里程的出场班次才需要纠正
  240 + if(arr.isCorrect() || !sch.getBcType().equals("out") || sch.getJhlc() == null || sch.getBcsj() == null)
  241 + return;
  242 +
  243 + //如果首个进出站信号是出场
  244 + if(arr.isOutTcc() && arrList.size() >= 2)
  245 + arr = arrList.get(1);
  246 + else
  247 + return;
  248 +
  249 + //出场任务 “进终点” 信号才需要纠正
  250 + if(arr.getInOut() != 0)
  251 + return;
  252 +
  253 + //在计划终点之前到达,或者之后10分钟内到达
  254 + if(arr.getTs() < sch.getZdsjT()
  255 + || arr.getTs() - sch.getZdsjT() < TEN_MINUTES){
  256 +
  257 + int upDown = Integer.parseInt(sch.getXlDir());
  258 + //走向不一致,相信班次的走向。纠正进站信号
  259 + if(arr.getUpDown() != upDown
  260 + && arr.getStopName().equals(sch.getZdzName())){
  261 +
  262 +
  263 + String old = arr.toString();
  264 + arr.setUpDown(upDown);
  265 + arr.setStopNo(sch.getZdzCode());
  266 + arr.setCorrect(true);
  267 + arr.setCorrectText(old + " | " + arr.toString());
  268 +
  269 + logger.info("被纠正的信号:" + arr.getCorrectText());
  270 + }
  271 + }
  272 + }
  273 +
  274 + /**
  275 + *
  276 + * @Title: driftCheck
  277 + * @Description: TODO(漂移判定)
  278 + */
  279 + public boolean driftCheck(MatchResult mr, ArrivalEntity arr){
  280 + try{
  281 + //上行发车,和到达时间比较一下。起点一般不会立即发出
  282 + if(mr.sch.getXlDir().equals("0")
  283 + && null != mr.sch.getQdzArrDateSJ()){
  284 +
  285 + long dt = sdfyyyyMMddHHmm.parse(mr.sch.getRealExecDate() + mr.sch.getQdzArrDateSJ()).getTime();
  286 +
  287 + //停站时间少于 计划的3分之1,标记为漂移信号
  288 + if((mr.ts - dt < (mr.sch.getDfsjT() - dt) / 3)){
  289 + arr.setCorrect(true);
  290 + arr.setCorrectText("停站时间太短,标记为信号漂移");
  291 + arr.setFlag(-1);
  292 +
  293 + logger.info("漂移判定:" + arr);
  294 + return false;
  295 + }
  296 + }
  297 + }catch(Exception e){
  298 + logger.error("", e);
  299 + }
  300 + return true;
  301 + }
203 302 }
204 303  
205 304 @Override
... ...
src/main/java/com/bsth/service/directive/DirectiveServiceImpl.java
... ... @@ -71,8 +71,6 @@ public class DirectiveServiceImpl extends BaseServiceImpl&lt;D60, Integer&gt; implemen
71 71 @Autowired
72 72 DayOfSchedule dayOfSchedule;
73 73  
74   - SimpleDateFormat sdfHHmm = new SimpleDateFormat("HH点mm分");
75   -
76 74 static Long schDiff = 1000 * 60 * 60L;
77 75  
78 76 @Override
... ... @@ -111,6 +109,8 @@ public class DirectiveServiceImpl extends BaseServiceImpl&lt;D60, Integer&gt; implemen
111 109 logger.warn("烂班不允许发送调度指令....");
112 110 return -1;
113 111 }
  112 + //多线程下发指令时,SimpleDateFormat必须方法内初始化
  113 + SimpleDateFormat sdfHHmm = new SimpleDateFormat("HH点mm分");
114 114  
115 115 String text = "已完成" + finish + "个班次,下一发车时间" + sdfHHmm.format(new Date(sch.getDfsjT())) + ",由"
116 116 + sch.getQdzName() + "发往" + sch.getZdzName();
... ...
src/main/java/com/bsth/service/realcontrol/impl/ScheduleRealInfoServiceImpl.java
... ... @@ -785,7 +785,8 @@ public class ScheduleRealInfoServiceImpl extends BaseServiceImpl&lt;ScheduleRealInf
785 785 }
786 786 else{
787 787 //撤销实发
788   - revokeRealOutgo(sch.getId());
  788 + if(sch.getFcsjActual() != null)
  789 + revokeRealOutgo(sch.getId());
789 790 }
790 791  
791 792 //实达时间
... ... @@ -802,15 +803,17 @@ public class ScheduleRealInfoServiceImpl extends BaseServiceImpl&lt;ScheduleRealInf
802 803 }
803 804 }
804 805 else {
805   - //将对应的到离站数据标记为不可信
806   - List<ArrivalEntity> list = ArrivalData_GPS.findByNbbm(sch.getClZbh());
807   - for(ArrivalEntity arr : list){
808   - if(arr.getInOut() == 0
809   - && arr.getUpDown() == Integer.parseInt(sch.getXlDir())
810   - && arr.getStopNo().equals(sch.getZdzCode())
811   - && Math.abs(arr.getTs() - sch.getZdsjActualTime()) < 1000 * 60){
812   - arr.setEnable(false);
813   - break;
  806 + if(sch.getZdsjActual() != null){
  807 + //将对应的到离站数据标记为不可信
  808 + List<ArrivalEntity> list = ArrivalData_GPS.findByNbbm(sch.getClZbh());
  809 + for(ArrivalEntity arr : list){
  810 + if(arr.getInOut() == 0
  811 + && arr.getUpDown() == Integer.parseInt(sch.getXlDir())
  812 + && arr.getStopNo().equals(sch.getZdzCode())
  813 + && Math.abs(arr.getTs() - sch.getZdsjActualTime()) < 1000 * 60){
  814 + arr.setEnable(false);
  815 + break;
  816 + }
814 817 }
815 818 }
816 819  
... ...
src/main/resources/application-dev.properties
... ... @@ -8,7 +8,7 @@ spring.jpa.hibernate.naming_strategy= org.hibernate.cfg.ImprovedNamingStrategy
8 8 spring.jpa.database= MYSQL
9 9 spring.jpa.show-sql= true
10 10 spring.datasource.driver-class-name= com.mysql.jdbc.Driver
11   -spring.datasource.url= jdbc:mysql://127.0.0.1:3306/qp_control
  11 +spring.datasource.url= jdbc:mysql://127.0.0.1:3306/control
12 12 spring.datasource.username= root
13 13 spring.datasource.password= panzhao
14 14 #DATASOURCE
... ...
src/main/resources/static/pages/control/line/index.html
... ... @@ -228,8 +228,8 @@ function countDown(name){
228 228  
229 229 <script>
230 230 var updateLog = {
231   - text: '<div class="updete_log"><p>1、当出场班次没有计划里程时,系统将下发下一个营运班次指令。</p><p>2、如果首班出场“待发时间”前3分钟没有收到驾驶员出场请求,系统将自动下发调度指令。</p></div>'
232   - ,title: '2016年8月27号凌晨更新日志'
  231 + text: '<div class="updete_log"><p>1、修正因设备状态异常导致的第一个营运班次被跳过问题。</p><p>2、修复发车信息微调报出的“未知异常”问题。</p></div>'
  232 + ,title: '2016年8月28号更新日志'
233 233 }
234 234  
235 235 var lineCodes = '' //全部线路编码字符串,由data.js初始化
... ...
src/main/resources/static/pages/control/line/js/home.js
... ... @@ -87,14 +87,14 @@ var _home = (function() {
87 87  
88 88 setTimeout(function() {
89 89 // 提示文本
90   - var promptFlag = storage.getItem('promptFlag_0827');
  90 + var promptFlag = storage.getItem('promptFlag_0828');
91 91 if (!promptFlag) {
92 92 layer.alert(updateLog.text, {
93 93 title: updateLog.title,
94 94 area: ['410px', '250px'],
95 95 shift : 5
96 96 });
97   - storage.setItem('promptFlag_0827', 1);
  97 + storage.setItem('promptFlag_0828', 1);
98 98 }
99 99 }, 1500);
100 100 }
... ...