master
chents 3 years ago
parent 199a6bb99b
commit c9994b391e
  1. 158
      src/main/java/org/springblade/modules/business/controller/CommonApiController.java
  2. 4
      src/main/java/org/springblade/modules/business/entity/BusLine.java
  3. 2
      src/main/java/org/springblade/modules/business/mapper/BusLineMapper.xml
  4. 1
      src/main/java/org/springblade/modules/business/service/ICarInfoService.java
  5. 2
      src/main/java/org/springblade/modules/business/service/IStationHintService.java
  6. 75
      src/main/java/org/springblade/modules/business/service/impl/PublishService.java
  7. 42
      src/main/java/org/springblade/modules/business/service/impl/StationHintServiceImpl.java
  8. 13
      src/main/java/org/springblade/modules/business/vo/BusLineVo.java
  9. 29
      src/main/java/org/springblade/modules/business/vo/CurrentCarInfoVo.java
  10. 2
      src/main/java/org/springblade/modules/business/vo/StationHintVo.java
  11. 2
      src/main/java/org/springblade/modules/business/vo/imgVo.java
  12. 38
      src/main/java/org/springblade/modules/job/CarInfoTask.java
  13. 2
      src/main/java/org/springblade/modules/websocket/handler/WebsocketHandler.java
  14. 14
      src/main/java/org/springblade/modules/websocket/service/WebsocketService.java
  15. 20
      src/main/java/org/springblade/modules/websocket/vo/WebSocketMessage.java
  16. 16
      src/main/resources/application-dev.yml
  17. 4
      src/main/resources/application.yml
  18. 6
      src/main/resources/log/logback-dev.xml

@ -1,41 +1,34 @@
package org.springblade.modules.business.controller;
import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
import io.swagger.annotations.*;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.beetl.core.util.ArrayMap;
import org.openxmlformats.schemas.spreadsheetml.x2006.main.STOleUpdate;
import org.springblade.common.cache.business.BusLineCache;
import org.springblade.common.cache.business.SiteListCache;
import org.springblade.common.constant.BusinessConstant;
import org.springblade.common.constant.CommonConstant;
import org.springblade.common.utils.CommonUtil;
import org.springblade.common.utils.HttpClientUtils;
import org.springblade.common.utils.SiteResourceUtil;
import org.springblade.core.boot.ctrl.BladeController;
import org.springblade.core.tenant.annotation.TenantDS;
import org.springblade.core.tool.api.R;
import org.springblade.core.tool.utils.BeanUtil;
import org.springblade.core.tool.utils.Func;
import org.springblade.modules.business.entity.BusLine;
import org.springblade.modules.business.service.ICarInfoService;
import org.springblade.modules.business.vo.BusLineUpdateVo;
import org.springblade.modules.business.vo.CarInfoVO;
import org.springblade.modules.business.vo.SiteInfoVO;
import org.springblade.upload.entity.PocBusLineImg;
import org.springblade.modules.business.service.IStationHintService;
import org.springblade.modules.business.service.impl.PublishService;
import org.springblade.modules.business.vo.*;
import org.springblade.modules.job.CarInfoTask;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.net.URL;
import java.text.DecimalFormat;
import java.util.*;
import java.util.concurrent.TimeUnit;
/**
* 控制器
* 控制器@Autowired
*
* @author Chill
*/
@ -51,6 +44,12 @@ public class CommonApiController extends BladeController {
private final RedisTemplate redisTemplate;
private final PublishService publishService;
private final CarInfoTask carInfoTask;
private final IStationHintService stationHintService;
/**
* 设置车牌号
*
@ -58,6 +57,18 @@ public class CommonApiController extends BladeController {
*/
@GetMapping("set-car-stat")
public R setCarStat(@RequestParam String carNo, @RequestParam String carStat) {
redisTemplate.opsForValue().set("set-current-Facility-stat" + carNo, carStat);
publishService.publishToWeb(carNo, carStat);
return R.status(true);
}
/**
* 设置车牌号
*
* @return
*/
@GetMapping("set-car-stat-v2")
public R setCarStatV2(@RequestParam String carNo, @RequestParam String carStat) {
redisTemplate.opsForValue().set("car-current-stat" + carNo, carStat);
return R.status(true);
}
@ -141,7 +152,6 @@ public class CommonApiController extends BladeController {
if (BusinessConstant.CAR_STAT_IN.toString().equals(info.getNowstate())) {
nextSiteIdx -= 1;
}
// 下一站
List<Map<String, String>> snameList = new ArrayList<>();
SiteInfoVO nextSite = nextSiteIdx < siteList.size() ? siteList.get(nextSiteIdx) : null;
@ -277,7 +287,6 @@ public class CommonApiController extends BladeController {
}
redisTemplate.opsForValue().set("site-img-type", imgType, 30, TimeUnit.SECONDS);
}
}
}
@ -301,9 +310,122 @@ public class CommonApiController extends BladeController {
*
* @return
*/
@ApiOperation(value = "获取当前实时的车辆信息", notes = "传入id和busLine")
@GetMapping("/get-current-car-info")
@ApiOperation(value = "获取当前实时的车辆信息", notes = "carNo")
@PostMapping("/get-current-car-info")
public R getCurrentCarInfo(@RequestParam String carNo) {
return R.data(carInfoService.getCarInfo(carNo));
CarInfoVO carInfo = carInfoService.getCarInfo(carNo);
//获取当前站点
StationHintVo currentStation = getCurrentStation(carInfo.getLinename(),carInfo.getUpordown(), carInfo.getInorder());
//当前站点
String currentSnameKey = currentStation.getName();
//获取上一站
StationHintVo upStation = getUpStation(carInfo.getLinename(), carInfo.getUpordown(), currentSnameKey);
//获取下一站
StationHintVo downStation = getDownStation(carInfo.getLinename(), carInfo.getUpordown(), currentSnameKey);
//计算当前车辆距离上一站点百分比
double pass = 0;
if (Func.isNotEmpty(upStation)) {
pass = CommonUtil.calculateDistance(Double.parseDouble(upStation.getJingdu()), Double.parseDouble(upStation.getWeidu()),
Double.parseDouble(carInfo.getJingdu()), Double.parseDouble(carInfo.getWeidu()));
}
double unpass = 0;
if (Func.isNotEmpty(downStation)) {
unpass = CommonUtil.calculateDistance(Double.parseDouble(downStation.getJingdu()), Double.parseDouble(downStation.getWeidu()),
Double.parseDouble(carInfo.getJingdu()), Double.parseDouble(carInfo.getWeidu()));
}
double runPercent = (pass + unpass) > 0 ? (pass / (pass + unpass)) * 100 : 0;
//组装返回对象
CurrentCarInfoVo currentCarInfoVo = new CurrentCarInfoVo();
currentCarInfoVo.setBusno(carInfo.getBusno());
currentCarInfoVo.setLinename(carInfo.getLinename());
currentCarInfoVo.setSpeed(carInfo.getSpeed());
currentCarInfoVo.setCurrentStation(currentSnameKey);
currentCarInfoVo.setUpStation(upStation.getName());
currentCarInfoVo.setDownStation(downStation.getName());
currentCarInfoVo.setPercentage(runPercent);
//定时任务缓存
carInfoTask.setCarInfo(currentCarInfoVo);
return R.data(currentCarInfoVo);
}
/**
* 根据上下行和已经经过了第几个站点计算当前站点
*
* @param upOrDown 上下行
* @param inOrder 已经经过了第几个站点
* @return 当前站点
*/
private StationHintVo getCurrentStation(String linename, String upOrDown, String inOrder) {
// 根据上下行获取对应的站点集合
List<StationHintVo> stationList = getStationListByUpOrDown(linename,upOrDown);
// 计算当前站点
int currentStationIndex = Integer.parseInt(inOrder) - 1;
if (currentStationIndex < 0) {
currentStationIndex = 0;
} else if (currentStationIndex >= stationList.size()) {
currentStationIndex = stationList.size() - 1;
}
return stationList.get(currentStationIndex);
}
/**
* 当前车辆上一站
* @Date 2023/5/10 17:02
* @param linename
* @param upordown
* @param currentSnameKey
* @return
**/
private StationHintVo getUpStation(String linename, String upordown, String currentSnameKey) {
List<StationHintVo> busLineVoList = getStationListByUpOrDown(linename, upordown);
for (int i = 0; i < busLineVoList.size(); i++) {
if (busLineVoList.get(i).getName().equals(currentSnameKey)) {
if (i == 0) {
return null;
} else {
return busLineVoList.get(i - 1);
}
}
}
return null;
}
/**
* 当前车辆下一站
* @Date 2023/5/10 17:02
* @param linename
* @param upordown
* @param currentSnameKey
* @return
**/
private StationHintVo getDownStation(String linename, String upordown, String currentSnameKey) {
List<StationHintVo> busLineVoList = getStationListByUpOrDown(linename, upordown);
for (int i = 0; i < busLineVoList.size(); i++) {
if (busLineVoList.get(i).getName().equals(currentSnameKey)) {
if (i == busLineVoList.size() - 1) {
return null;
} else {
return busLineVoList.get(i + 1);
}
}
}
return null;
}
/**
* 根据上下行获取对应的站点集合
*
* @param upOrDown 上下行
* @return 站点集合
*/
private List<StationHintVo> getStationListByUpOrDown(String linename,String upOrDown) {
//根据在那条线路,上下行获取对应的站点集合
R queryStationHint = stationHintService.QueryBusLineMessage(linename, upOrDown);
List<StationHintVo> busLineVoList = (List<StationHintVo>) queryStationHint.getData();
return busLineVoList;
}
}

@ -58,5 +58,9 @@ public class BusLine extends BaseEntity {
private String imgMap;
// 景区图片
private String imgScenic;
//经度
private Double jingdu;
//纬度
private Double weidu;
}

@ -16,6 +16,8 @@
<result column="scenic" property="scenic"/>
<result column="img_map" property="imgMap"/>
<result column="img_scenic" property="imgScenic"/>
<result column="jingdu" property="jingdu"/>
<result column="weidu" property="weidu"/>
</resultMap>
</mapper>

@ -20,5 +20,4 @@ public interface ICarInfoService {
CarInfoVO getCarInfo(String carNo);
List<CarInfoVO> getAllCarInfo();
}

@ -29,4 +29,6 @@ public interface IStationHintService extends BaseService<BusLine> {
void updateStationHint(BusLineUpdateVo busLineUpdateVo);
boolean delete(String ids);
R<List<StationHintVo>> QueryBusLineMessage(String linename, String updown);
}

@ -0,0 +1,75 @@
package org.springblade.modules.business.service.impl;
import org.springblade.core.tool.utils.Func;
import org.springblade.modules.websocket.service.WebsocketService;
import org.springblade.modules.websocket.vo.WebSocketMessage;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import java.util.concurrent.TimeUnit;
/**
* @Author: Chents
* @Create: 2023-05-10
*/
@Service
public class PublishService {
private static final String CURRENT_FACILITY_STAT = "set-current-Facility-stat";
private static final String CURRENT_FACILITY_RETURN = "return-current-Facility-stat";
@Autowired
private WebsocketService websocketService;
@Autowired
private RedisTemplate redisTemplate;
/**
* 推送车辆状态数据到web
*
* @Author chents
* @Date 2023/5/10 11:25
* @param carNo
* @param status
* @return
**/
public void publishToWeb(String carNo, String status) {
// 1. 启动线程
Thread thread = new Thread(new Runnable() {
@Override
public void run() {
int times = 0;
// 重试策略: 先发三次, 全部失败后, 等待1s再发三次
while (times < 1) {
for (int i=0; i<2; i ++) {
// 2. 调用websocket方法发送数据
String currentFacility = (String) redisTemplate.opsForValue().get(CURRENT_FACILITY_STAT);
WebSocketMessage message = new WebSocketMessage();
message.setTitle(CURRENT_FACILITY_STAT);
message.setCode(200);
message.setContent("设备信息:"+currentFacility);
websocketService.broadcast(message);
// 3. 查看websocket的返回结果
String result = (String) redisTemplate.opsForValue().get(CURRENT_FACILITY_RETURN);
if (Func.isNotBlank(result)) {
//缓存数据到redis,设置5s过期时间
redisTemplate.opsForValue().set(CURRENT_FACILITY_RETURN, carNo + ":" + status, 5, TimeUnit.SECONDS);
return;
}
}
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
});
thread.start();
}
}

@ -56,6 +56,8 @@ public class StationHintServiceImpl extends BaseServiceImpl<BusLineMapper,BusLin
busLineVo.setLinename(x.getLinename());
busLineVo.setUpdown(x.getUpdown());
busLineVo.setSnameKey(x.getSnameKey());
busLineVo.setJingdu(x.getJingdu().toString());
busLineVo.setWeidu(x.getWeidu().toString());
return busLineVo;
}).collect(Collectors.toList());
return R.data(busLineVoList);
@ -89,6 +91,46 @@ public class StationHintServiceImpl extends BaseServiceImpl<BusLineMapper,BusLin
imgVo img = new imgVo();
img.setImgUrl(pocBusLineImg.getImgUrl());
img.setImgType(pocBusLineImg.getImgType());
img.setBusLineId(pocBusLineImg.getBusLineId());
imgList.add(img);
}
stationHintVo.setImgList(imgList);
return stationHintVo;
}).collect(Collectors.toList());
return R.data(stationArr);
}
@Override
public R<List<StationHintVo>> QueryBusLineMessage(String linename, String updown) {
QueryWrapper<BusLine> busLineQueryWrapper = new QueryWrapper<>();
busLineQueryWrapper.eq("linename",linename);
busLineQueryWrapper.eq("updown",updown);
busLineQueryWrapper.isNotNull("sname_key");
List<BusLine> busLines = busLineMapper.selectList(busLineQueryWrapper);
if (CollectionUtils.isEmpty(busLines)){
throw new ServiceException(StringUtil.format("公交站点信息为空"));
}
List<StationHintVo> stationArr = busLines.stream().map(x -> {
StationHintVo stationHintVo = new StationHintVo();
stationHintVo.setId(x.getId());
stationHintVo.setName(x.getSnameKey());
stationHintVo.setTips(x.getTips());
stationHintVo.setRed(x.getActicle());
stationHintVo.setGreen(x.getActivity());
stationHintVo.setYellow(x.getScenic());
stationHintVo.setJingdu(x.getJingdu().toString());
stationHintVo.setWeidu(x.getWeidu().toString());
QueryWrapper<PocBusLineImg> queryWrapper = new QueryWrapper<>();
queryWrapper.select("img_url","img_type");
queryWrapper.eq("bus_line_id",x.getId());
List<PocBusLineImg> pocBusLineImgs = proBusLineImgMapper.selectList(queryWrapper);
ArrayList<imgVo> imgList = new ArrayList<>();
for(PocBusLineImg pocBusLineImg : pocBusLineImgs){
imgVo img = new imgVo();
img.setImgUrl(pocBusLineImg.getImgUrl());
img.setImgType(pocBusLineImg.getImgType());
img.setBusLineId(pocBusLineImg.getBusLineId());
imgList.add(img);
}
stationHintVo.setImgList(imgList);

@ -11,10 +11,13 @@ import java.io.Serializable;
@Data
public class BusLineVo implements Serializable {
private static final long serialVersionUID = 1L;
private static final long serialVersionUID = 1L;
private Long id;
private String linename;
private String updown;
private String snameKey;
private String jingdu;
private String weidu;
private Long id;
private String linename;
private String updown;
private String snameKey;
}

@ -0,0 +1,29 @@
package org.springblade.modules.business.vo;
import lombok.Data;
import java.io.Serializable;
/**
* @Author: Chents
* @Create: 2023-05-10
*/
@Data
public class CurrentCarInfoVo implements Serializable {
private static final long serialVersionUID = 1L;
// 车牌号
private String busno;
// 在哪条线路
private String linename;
// 速度
private String speed;
//当前站点
private String currentStation;
//上一站
private String upStation;
//下一站
private String downStation;
//当前车辆距离上一站点百分比
private double percentage;
}

@ -23,5 +23,7 @@ public class StationHintVo implements Serializable {
private String red;//情怀,励志
private String green;//活动
private String yellow;//活动
private String jingdu;
private String weidu;
private List<imgVo> imgList;
}

@ -18,4 +18,6 @@ public class imgVo implements Serializable{
private String imgUrl;
private Integer imgType;
private Long busLineId;
}

@ -4,7 +4,9 @@ import lombok.extern.slf4j.Slf4j;
import org.springblade.modules.business.service.ICarInfoService;
import org.springblade.modules.business.service.IStationHintService;
import org.springblade.modules.business.vo.CarInfoVO;
import org.springblade.modules.business.vo.CurrentCarInfoVo;
import org.springblade.modules.websocket.service.WebsocketService;
import org.springblade.modules.websocket.vo.WebSocketMessage;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.scheduling.annotation.Scheduled;
@ -33,26 +35,28 @@ public class CarInfoTask {
private IStationHintService stationHintService;
//@Scheduled(cron = "0/1 * * * * ?")
public void getAllCarInfo() {
redisTemplate.opsForValue().set("car_info", carInfoService.getAllCarInfo());
public void setCarInfo(CurrentCarInfoVo currentCarInfoVo) {
redisTemplate.opsForValue().set("current_car_info", currentCarInfoVo);
System.out.println("======存入实时车辆信息到redis成功=========");
}
//@Scheduled(cron = "0/1 * * * * ?")
public void parseCarInfo() {
//从redis获取数据
List<CarInfoVO> carInfoList = (List<CarInfoVO>) redisTemplate.opsForValue().get("car_info");
if (carInfoList == null && carInfoList.isEmpty()) {
log.info("======未从redis获取车辆实时数据=======");
return;
}
for (CarInfoVO carInfo : carInfoList) {
// 解析车辆信息
log.info("解析车辆信息:{}", carInfo.toString());
// 推送消息给web页面
websocketService.broadcast("car_info", "车辆信息:" + carInfo.toString());
log.info("推送车辆信息:{}", carInfo.toString());
}
}
//从redis获取数据
CurrentCarInfoVo carInfo = (CurrentCarInfoVo) redisTemplate.opsForValue().get("current_car_info");
if (carInfo == null) {
log.info("======未从redis获取当前车辆实时数据=======");
return;
}
// 解析车辆信息
WebSocketMessage message = new WebSocketMessage();
message.setTitle("current_car_info");
message.setCode(200);
message.setContent("车辆信息:" + carInfo.toString());
log.info("解析车辆信息:{}", carInfo.toString());
// 推送消息给web页面
websocketService.broadcast(message);
log.info("推送车辆信息:{}", carInfo.toString());
}
}

@ -55,7 +55,7 @@ public class WebsocketHandler extends TextWebSocketHandler {
*/
@Override
protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception {
System.out.println(message.getPayload());
System.out.println("Received message from client: " + message.getPayload());
TextMessage msg = new TextMessage(message.getPayload());
session.sendMessage(msg);
}

@ -1,5 +1,6 @@
package org.springblade.modules.websocket.service;
import org.springblade.modules.websocket.vo.WebSocketMessage;
import org.springframework.stereotype.Service;
import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.WebSocketSession;
@ -46,19 +47,17 @@ public class WebsocketService extends TextWebSocketHandler {
/**
* 广播
*
* @param message
* @param webSocketMessage
*/
public synchronized void broadcast(String type, String message) {
if (!sessionMap.containsKey(type)) {
public synchronized void broadcast(WebSocketMessage webSocketMessage) {
if (!sessionMap.containsKey(webSocketMessage.getTitle())) {
return;
}
for (WebSocketSession session : sessionMap.get(type)) {
TextMessage tm = new TextMessage(message);
for (WebSocketSession session : sessionMap.get(webSocketMessage.getTitle())) {
TextMessage tm = new TextMessage(webSocketMessage.getContent().toString());
try {
Set<String> strings = sessionMap.keySet();
session.sendMessage(tm);
} catch (IOException e) {
// 发送失败后,需要继续给其他人广播,因此在循环里面用 try 捕获异常
e.printStackTrace();
@ -73,4 +72,5 @@ public class WebsocketService extends TextWebSocketHandler {
boolean b = sessionMap.containsKey(type) ? sessionMap.get(type).size() > 0 : false;
return b;
}
}

@ -0,0 +1,20 @@
package org.springblade.modules.websocket.vo;
import lombok.Data;
/**
* @Author: Chents
* @Create: 2023-05-10
*/
@Data
public class WebSocketMessage {
//自定义为唯一表示
private String title;
//http状态码
private int code;
//返回对象
private Object content;
}

@ -2,16 +2,20 @@
spring:
redis:
##redis 单机环境配置
host: 127.0.0.1
# host: 127.0.0.1
host: 192.168.72.129
port: 6379
password:
database: 0
ssl: false
datasource:
# MySql
url: jdbc:mysql://127.0.0.1:3306/yt_bus_live?useSSL=false&useUnicode=true&characterEncoding=utf-8&zeroDateTimeBehavior=convertToNull&transformedBitIsBoolean=true&serverTimezone=GMT%2B8&nullCatalogMeansCurrent=true&allowPublicKeyRetrieval=true
# url: jdbc:mysql://127.0.0.1:3306/yt_bus_live?useSSL=false&useUnicode=true&characterEncoding=utf-8&zeroDateTimeBehavior=convertToNull&transformedBitIsBoolean=true&serverTimezone=GMT%2B8&nullCatalogMeansCurrent=true&allowPublicKeyRetrieval=true
# username: root
# password: 123456
url: jdbc:mysql://192.168.72.129:3306/yt_bus_live?useSSL=false&useUnicode=true&characterEncoding=utf-8&zeroDateTimeBehavior=convertToNull&transformedBitIsBoolean=true&serverTimezone=GMT%2B8&nullCatalogMeansCurrent=true&allowPublicKeyRetrieval=true
username: root
password: 123456
password: root
#blade配置
blade:
@ -20,9 +24,11 @@ blade:
##是否启用分布式锁
enabled: false
##redis服务地址
address: redis://127.0.0.1:6379
address: redis://192.168.72.129:6379
# address: redis://127.0.0.1:6379
#本地文件上传
file:
remote-mode: true
upload-domain: http://127.0.0.1.129:8999
upload-domain: http://192.168.72.129:8999
# upload-domain: http://127.0.0.1:8999
remote-path: D:\WorkSoft\minio\data

@ -130,6 +130,4 @@ blade:
secure:
#接口放行
skip-url:
- /blade-business/stationHint/*
- /blade-business/car-admin/*
- /pro-bus-line-img/*
- /blade-business/common-api/*

@ -17,7 +17,7 @@
<!-- 控制台输出 -->
<appender name="console" class="ch.qos.logback.core.ConsoleAppender">
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>INFO</level>
<level>DEBUG</level>
<onMatch>ACCEPT</onMatch>
<onMismatch>DENY</onMismatch>
</filter>
@ -45,11 +45,11 @@
<appender-ref ref="file"/>
</appender>
<root level="INFO">
<root level="DEBUG">
<appender-ref ref="console"/>
</root>
<root level="INFO">
<root level="DEBUG">
<appender-ref ref="file"/>
</root>

Loading…
Cancel
Save