websocket功能

master
liuqingkun 3 years ago
parent 1b1832f2f6
commit 8dcbdf8da9
  1. 76
      src/main/java/org/springblade/common/cache/business/CarInfoCache.java
  2. 196
      src/main/java/org/springblade/modules/business/controller/CommonApiController.java
  3. 8
      src/main/java/org/springblade/modules/business/entity/BusLine.java
  4. 2
      src/main/java/org/springblade/modules/business/mapper/BusLineMapper.xml
  5. 7
      src/main/java/org/springblade/modules/business/service/IStationHintService.java
  6. 39
      src/main/java/org/springblade/modules/business/service/impl/PublishService.java
  7. 40
      src/main/java/org/springblade/modules/business/service/impl/StationHintServiceImpl.java
  8. 213
      src/main/java/org/springblade/modules/job/CarInfoTask.java
  9. 6
      src/main/java/org/springblade/modules/websocket/controller/WebSocketController.java
  10. 22
      src/main/java/org/springblade/modules/websocket/handler/WebsocketHandler.java

@ -0,0 +1,76 @@
package org.springblade.common.cache.business;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import org.springblade.common.constant.BusinessConstant;
import org.springblade.common.utils.HttpClientUtils;
import org.springblade.core.cache.utils.CacheUtil;
import org.springblade.core.tool.utils.Func;
import org.springblade.core.tool.utils.SpringUtil;
import org.springblade.modules.business.entity.CarAdmin;
import org.springblade.modules.business.service.ICarAdminService;
public class CarInfoCache {
// cache name
private static final String CACHE_LIVE_CAR = "live:car:";
private static final String PUSH = "push";
private static final String DATA = "data";
// cache key
private static final String CAR_NO = "car-no";
private static final String STATUS = "status";
private static final String ALL_CAR_DATA = "all";
public static String getPushCarNo() {
return CacheUtil.get(CACHE_LIVE_CAR, PUSH, CAR_NO, () -> {
String url = "http://42.192.165.208:8000/device/currentPush";
String res = HttpClientUtils.doGet(url);
JSONObject json = JSON.parseObject(res);
JSONObject data = json.getJSONObject("data");
String pushStatus = (String) data.get("pushStatus");
String deviceId = (String) data.get("deviceId");
CarAdmin carAdmin = SpringUtil.getBean(ICarAdminService.class).
getOne(Wrappers.<CarAdmin>lambdaQuery().eq(CarAdmin::getReceiverId, deviceId));
String carNo = Func.isEmpty(carAdmin) ? "" : carAdmin.getName();
return carNo;
}, BusinessConstant.TENANT_MODE);
}
public static void setPushCarNo(String carNo) {
CacheUtil.put(CACHE_LIVE_CAR, PUSH, CAR_NO, carNo, BusinessConstant.TENANT_MODE);
}
public static String getPushStatus() {
return CacheUtil.get(CACHE_LIVE_CAR, PUSH, STATUS, () -> {
String url = "http://42.192.165.208:8000/device/currentPush";
String res = HttpClientUtils.doGet(url);
JSONObject json = JSON.parseObject(res);
JSONObject data = json.getJSONObject("data");
String pushStatus = (String) data.get("pushStatus");
String deviceId = (String) data.get("deviceId");
return pushStatus;
}, BusinessConstant.TENANT_MODE);
}
public static void setPushStatus(String status) {
CacheUtil.put(CACHE_LIVE_CAR, PUSH, STATUS, status, BusinessConstant.TENANT_MODE);
}
public static String getAllCarData() {
return CacheUtil.get(CACHE_LIVE_CAR, DATA, ALL_CAR_DATA, () -> {
return "";
}, BusinessConstant.TENANT_MODE);
}
public static void setAllCarData(String allCarData) {
CacheUtil.put(CACHE_LIVE_CAR, DATA, ALL_CAR_DATA, allCarData, BusinessConstant.TENANT_MODE);
}
}

@ -7,6 +7,7 @@ import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.beetl.core.util.ArrayMap; import org.beetl.core.util.ArrayMap;
import org.springblade.common.cache.business.BusLineCache; import org.springblade.common.cache.business.BusLineCache;
import org.springblade.common.cache.business.CarInfoCache;
import org.springblade.common.cache.business.SiteListCache; import org.springblade.common.cache.business.SiteListCache;
import org.springblade.common.constant.BusinessConstant; import org.springblade.common.constant.BusinessConstant;
import org.springblade.common.constant.CommonConstant; import org.springblade.common.constant.CommonConstant;
@ -76,61 +77,12 @@ public class CommonApiController extends BladeController {
CarAdmin carAdmin = carAdminService.getOne(Wrappers.<CarAdmin>lambdaQuery().eq(CarAdmin::getReceiverId, clientId)); CarAdmin carAdmin = carAdminService.getOne(Wrappers.<CarAdmin>lambdaQuery().eq(CarAdmin::getReceiverId, clientId));
String carNo = Func.isEmpty(carAdmin) ? "" : carAdmin.getName(); String carNo = Func.isEmpty(carAdmin) ? "" : carAdmin.getName();
redisTemplate.opsForValue().set("car-current-number", carNo); CarInfoCache.setPushCarNo(carNo);
redisTemplate.opsForValue().set("set-current-Facility-stat" + carNo, carStat); CarInfoCache.setPushStatus(carStat);
publishService.publishToWeb(carNo, carStat); publishService.publishToWeb(carNo, carStat);
return R.status(true); return R.status(true);
} }
/**
* 设置车牌号
*
* @return
*/
@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);
}
/**
* 设置车牌号
*
* @return
*/
@GetMapping("set-car-no")
public R setCarNo(String carNo) {
redisTemplate.opsForValue().set("car-current-number", carNo);
return R.status(true);
}
/**
* 获取车牌号
*
* @return
*/
@GetMapping("get-car-no")
public R getCarNo() {
String carNo = (String) redisTemplate.opsForValue().get("car-current-number");
if (Func.isBlank(carNo)) {
carNo = "鲁F08953D";
}
return R.data(carNo);
}
/** /**
* 获取车速 * 获取车速
* *
@ -228,9 +180,6 @@ public class CommonApiController extends BladeController {
siteMsgMap.put("type", "after"); siteMsgMap.put("type", "after");
snameList.add(siteMsgMap); snameList.add(siteMsgMap);
} }
// if (Func.isNotEmpty(nextSite3)) {
// snameList.add(nextSite3.getSname());
// }
// 计算当前车辆与前一站和后一站的距离 // 计算当前车辆与前一站和后一站的距离
double pass = 0; double pass = 0;
@ -323,146 +272,7 @@ public class CommonApiController extends BladeController {
} }
} }
return R.data(resultMap); return R.data(resultMap);
} }
/**
* 获取所有实时的车辆信息
*
* @return
*/
@ApiOperation(value = "获取所有实时的车辆信息", notes = "传入id和busLine")
@GetMapping("/get-all-car-info")
public R getAllCarInfo() {
return R.data(carInfoService.getAllCarInfo());
}
/**
* 获取实时车辆站点信息
*/
@GetMapping("/get-current-info")
public R getCurrentInfo(@RequestParam String carNo) {
CarInfoVO info = carInfoService.getCarInfo(carNo);
if (Func.isEmpty(info)) {
return R.fail("未获取到车辆信息, 请检查车是否已掉线");
}
List<SiteInfoVO> siteList = SiteListCache.getSiteList(info.getLinename(), info.getUpordown());
int nextSiteIdx = Integer.parseInt(info.getInorder());
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;
SiteInfoVO nextSite2 = (nextSiteIdx + 1) < siteList.size() ? siteList.get((nextSiteIdx) + 1) : null;
SiteInfoVO nextSite3 = (nextSiteIdx + 2) < siteList.size() ? siteList.get(nextSiteIdx + 2) : null;
// 上一站
SiteInfoVO preSite = nextSiteIdx - 1 > 0 ? siteList.get(nextSiteIdx - 1) : null;
// 上两站
SiteInfoVO preTwoSite = nextSiteIdx - 2 > 0 ? siteList.get(nextSiteIdx - 2) : null;
// 上三站
SiteInfoVO preThreeSite = nextSiteIdx - 3 > 0 ? siteList.get(nextSiteIdx - 3) : null;
Map<String, String> siteMsgMap;
if (Func.isNotEmpty(preThreeSite)) {
siteMsgMap = new HashMap<>();
siteMsgMap.put("siteName", preThreeSite.getSname());
siteMsgMap.put("type", "before");
snameList.add(siteMsgMap);
}
if (Func.isNotEmpty(preTwoSite)) {
siteMsgMap = new HashMap<>();
siteMsgMap.put("siteName", preTwoSite.getSname());
siteMsgMap.put("type", "before");
snameList.add(siteMsgMap);
}
if (Func.isNotEmpty(preSite)) {
siteMsgMap = new HashMap<>();
siteMsgMap.put("siteName", preSite.getSname());
siteMsgMap.put("type", "before");
snameList.add(siteMsgMap);
}
if (Func.isNotEmpty(nextSite)) {
siteMsgMap = new HashMap<>();
siteMsgMap.put("siteName", nextSite.getSname());
siteMsgMap.put("type", "after");
snameList.add(siteMsgMap);
}
if (Func.isNotEmpty(nextSite2)) {
siteMsgMap = new HashMap<>();
siteMsgMap.put("siteName", nextSite2.getSname());
siteMsgMap.put("type", "after");
snameList.add(siteMsgMap);
}
// if (Func.isNotEmpty(nextSite3)) {
// snameList.add(nextSite3.getSname());
// }
// 计算当前车辆与前一站和后一站的距离
double pass = 0;
if (Func.isNotEmpty(preSite)) {
pass = CommonUtil.calculateDistance(Double.parseDouble(preSite.getJingdu()), Double.parseDouble(preSite.getWeidu()),
Double.parseDouble(info.getJingdu()), Double.parseDouble(info.getWeidu()));
}
double unpass = 0;
if (Func.isNotEmpty(nextSite)) {
unpass = CommonUtil.calculateDistance(Double.parseDouble(nextSite.getJingdu()), Double.parseDouble(nextSite.getWeidu()),
Double.parseDouble(info.getJingdu()), Double.parseDouble(info.getWeidu()));
}
double runPercent = (pass + unpass) > 0 ? (pass / (pass + unpass)) * 100 : 0;
DecimalFormat df1 = new DecimalFormat("#");
// 先从缓存中获取上一次的运行百分比, 然后将本次的运行百分比更新到缓存中
String runPercentStr = df1.format(runPercent > 100 ? 100 : runPercent);
String prePercentStr = (String) redisTemplate.opsForValue().get("car-run-percent-info");
log.error("____________________________________________");
log.error("runPercentStr : " + runPercentStr);
log.error("prePercentStr : " + prePercentStr);
log.error("CarInfoVO: " + info.toString());
prePercentStr = Func.isBlank(prePercentStr) ? "0" : prePercentStr;
redisTemplate.opsForValue().set("car-run-percent-info", runPercentStr, 30, TimeUnit.SECONDS);
Map<String, Object> siteMap = new HashMap<>();
siteMap.put("startSite", siteList.get(0).getSname());
siteMap.put("endSite", siteList.get(siteList.size() - 1).getSname());
siteMap.put("siteList", snameList);
siteMap.put("prePercent", prePercentStr);
siteMap.put("runPercent", runPercentStr);
if (Func.isEmpty(nextSite)) {
nextSite = preSite;
}
BusLine busLine = BusLineCache.getBusLine(info.getUpordown(), nextSite.getSname(), nextSite.getWeizhi());
// 组织返回数据
Map<String, Object> resultMap = new HashMap<>();
resultMap.put("siteData", siteMap);
resultMap.put("catStat", redisTemplate.opsForValue().get("car-current-stat-info" + carNo));
if (Func.isEmpty(busLine)) {
resultMap.put("siteTips", "");
resultMap.put("articleData", "");
resultMap.put("activityData", "");
resultMap.put("scenicData", "");
resultMap.put("imgData", "");
resultMap.put("speed", "");
} else {
resultMap.put("siteTips", busLine.getTips());
resultMap.put("articleData", busLine.getActicle());
resultMap.put("activityData", busLine.getActivity());
resultMap.put("scenicData", busLine.getScenic());
resultMap.put("speed", info.getSpeed());
List<BusLine> busLineList = stationHintService.getBusLineByName(nextSite.getSname());
Long busLineId = busLineList.get(0).getId();
List<imgVo> imgList = proBusLineImgService.getImgByid(busLineId);
redisTemplate.opsForValue().set("imgList-info", imgList);
resultMap.put("imgData", imgList);
}
return R.data(resultMap);
}
} }

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

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

@ -17,11 +17,12 @@ import java.util.List;
public interface IStationHintService extends BaseService<BusLine> { public interface IStationHintService extends BaseService<BusLine> {
/** /**
*查询列表 * 查询列表
* @Author chents *
* @return * @return
* @Author chents
**/ **/
R QueryStationHint(String linename,String updown); R QueryStationHint(String linename, String updown);
R<List<StationHintVo>> QueryStationMessage(String linename, String updown); R<List<StationHintVo>> QueryStationMessage(String linename, String updown);

@ -1,14 +1,19 @@
package org.springblade.modules.business.service.impl; package org.springblade.modules.business.service.impl;
import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSON;
import lombok.RequiredArgsConstructor;
import org.springblade.common.cache.business.CarInfoCache;
import org.springblade.common.constant.BusinessConstant;
import org.springblade.core.tool.utils.Func; import org.springblade.core.tool.utils.Func;
import org.springblade.modules.websocket.service.WebsocketService; import org.springblade.modules.websocket.service.WebsocketService;
import org.springblade.modules.websocket.vo.WebSocketMessage; import org.springblade.modules.websocket.vo.WebSocketMessage;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisHash;
import org.springframework.data.redis.core.RedisTemplate; import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
/** /**
@ -18,10 +23,6 @@ import java.util.concurrent.TimeUnit;
@Service @Service
public class PublishService { 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 @Autowired
private WebsocketService websocketService; private WebsocketService websocketService;
@ -31,11 +32,11 @@ public class PublishService {
/** /**
* 推送车辆状态数据到web * 推送车辆状态数据到web
* *
* @Author chents
* @Date 2023/5/10 11:25
* @param carNo * @param carNo
* @param status * @param status
* @return * @return
* @Author chents
* @Date 2023/5/10 11:25
**/ **/
public void publishToWeb(String carNo, String status) { public void publishToWeb(String carNo, String status) {
// 1. 启动线程 // 1. 启动线程
@ -45,23 +46,25 @@ public class PublishService {
int times = 0; int times = 0;
// 重试策略: 先发三次, 全部失败后, 等待1s再发三次 // 重试策略: 先发三次, 全部失败后, 等待1s再发三次
while (times < 1) { while (times < 1) {
for (int i=0; i<2; i ++) { for (int i = 0; i < 2; i++) {
// 2. 调用websocket方法发送数据 // 2. 调用websocket方法发送数据
String currentFacility = (String) redisTemplate.opsForValue().get(CURRENT_FACILITY_STAT); Map<String, String> statusMap = new HashMap<>();
statusMap.put("pushCarNo", carNo);
statusMap.put("pushStatus", status);
Map<String, Object> dataMap = new HashMap<>();
dataMap.put("msgType", "status");
dataMap.put("data", statusMap);
WebSocketMessage message = new WebSocketMessage(); WebSocketMessage message = new WebSocketMessage();
message.setTitle(CURRENT_FACILITY_STAT); message.setTitle("web");
message.setCode(200); message.setCode(200);
HashMap<String, Object> map = new HashMap<>(); message.setContent(JSON.toJSONString(dataMap));
map.put("msgType", CURRENT_FACILITY_STAT);
map.put("data", currentFacility);
String messageJson = JSON.toJSONString(map);
message.setContent(messageJson);
websocketService.broadcast(message); websocketService.broadcast(message);
// 3. 查看websocket的返回结果 // 3. 查看websocket的返回结果
String result = (String) redisTemplate.opsForValue().get(CURRENT_FACILITY_RETURN); String result = (String) redisTemplate.opsForValue().get("websocket-status-return");
if (Func.isNotBlank(result)) { if (Func.isNotBlank(result) && BusinessConstant.BOOLEAN_STR_TRUE.equals(result)) {
//缓存数据到redis,设置5s过期时间
redisTemplate.opsForValue().set(CURRENT_FACILITY_RETURN, carNo + ":" + status, 5, TimeUnit.SECONDS);
return; return;
} }
} }

@ -31,7 +31,7 @@ import java.util.stream.Collectors;
* @author chents * @author chents
*/ */
@Service @Service
public class StationHintServiceImpl extends BaseServiceImpl<BusLineMapper,BusLine> implements IStationHintService { public class StationHintServiceImpl extends BaseServiceImpl<BusLineMapper, BusLine> implements IStationHintService {
@Resource @Resource
BusLineMapper busLineMapper; BusLineMapper busLineMapper;
@ -44,10 +44,10 @@ public class StationHintServiceImpl extends BaseServiceImpl<BusLineMapper,BusLin
@Override @Override
public R QueryStationHint(String linename,String updown) { public R QueryStationHint(String linename, String updown) {
QueryWrapper<BusLine> busLineQueryWrapper = new QueryWrapper<>(); QueryWrapper<BusLine> busLineQueryWrapper = new QueryWrapper<>();
busLineQueryWrapper.eq("linename",linename); busLineQueryWrapper.eq("linename", linename);
busLineQueryWrapper.eq("updown",updown); busLineQueryWrapper.eq("updown", updown);
busLineQueryWrapper.isNotNull("sname_key"); busLineQueryWrapper.isNotNull("sname_key");
List<BusLine> busLines = busLineMapper.selectList(busLineQueryWrapper); List<BusLine> busLines = busLineMapper.selectList(busLineQueryWrapper);
List<BusLineVo> busLineVoList = busLines.stream().map(x -> { List<BusLineVo> busLineVoList = busLines.stream().map(x -> {
@ -56,8 +56,8 @@ public class StationHintServiceImpl extends BaseServiceImpl<BusLineMapper,BusLin
busLineVo.setLinename(x.getLinename()); busLineVo.setLinename(x.getLinename());
busLineVo.setUpdown(x.getUpdown()); busLineVo.setUpdown(x.getUpdown());
busLineVo.setSnameKey(x.getSnameKey()); busLineVo.setSnameKey(x.getSnameKey());
busLineVo.setJingdu(x.getJingdu().toString()); // busLineVo.setJingdu(x.getJingdu().toString());
busLineVo.setWeidu(x.getWeidu().toString()); // busLineVo.setWeidu(x.getWeidu().toString());
return busLineVo; return busLineVo;
}).collect(Collectors.toList()); }).collect(Collectors.toList());
return R.data(busLineVoList); return R.data(busLineVoList);
@ -67,11 +67,11 @@ public class StationHintServiceImpl extends BaseServiceImpl<BusLineMapper,BusLin
@Override @Override
public R<List<StationHintVo>> QueryStationMessage(String linename, String updown) { public R<List<StationHintVo>> QueryStationMessage(String linename, String updown) {
QueryWrapper<BusLine> busLineQueryWrapper = new QueryWrapper<>(); QueryWrapper<BusLine> busLineQueryWrapper = new QueryWrapper<>();
busLineQueryWrapper.eq("linename",linename); busLineQueryWrapper.eq("linename", linename);
busLineQueryWrapper.eq("updown",updown); busLineQueryWrapper.eq("updown", updown);
busLineQueryWrapper.isNotNull("sname_key"); busLineQueryWrapper.isNotNull("sname_key");
List<BusLine> busLines = busLineMapper.selectList(busLineQueryWrapper); List<BusLine> busLines = busLineMapper.selectList(busLineQueryWrapper);
if (CollectionUtils.isEmpty(busLines)){ if (CollectionUtils.isEmpty(busLines)) {
throw new ServiceException(StringUtil.format("公交站点信息为空")); throw new ServiceException(StringUtil.format("公交站点信息为空"));
} }
List<StationHintVo> stationArr = busLines.stream().map(x -> { List<StationHintVo> stationArr = busLines.stream().map(x -> {
@ -83,11 +83,11 @@ public class StationHintServiceImpl extends BaseServiceImpl<BusLineMapper,BusLin
stationHintVo.setGreen(x.getActivity()); stationHintVo.setGreen(x.getActivity());
stationHintVo.setYellow(x.getScenic()); stationHintVo.setYellow(x.getScenic());
QueryWrapper<PocBusLineImg> queryWrapper = new QueryWrapper<>(); QueryWrapper<PocBusLineImg> queryWrapper = new QueryWrapper<>();
queryWrapper.select("img_url","img_type"); queryWrapper.select("img_url", "img_type");
queryWrapper.eq("bus_line_id",x.getId()); queryWrapper.eq("bus_line_id", x.getId());
List<PocBusLineImg> pocBusLineImgs = proBusLineImgMapper.selectList(queryWrapper); List<PocBusLineImg> pocBusLineImgs = proBusLineImgMapper.selectList(queryWrapper);
ArrayList<imgVo> imgList = new ArrayList<>(); ArrayList<imgVo> imgList = new ArrayList<>();
for(PocBusLineImg pocBusLineImg : pocBusLineImgs){ for (PocBusLineImg pocBusLineImg : pocBusLineImgs) {
imgVo img = new imgVo(); imgVo img = new imgVo();
img.setImgUrl(pocBusLineImg.getImgUrl()); img.setImgUrl(pocBusLineImg.getImgUrl());
img.setImgType(pocBusLineImg.getImgType()); img.setImgType(pocBusLineImg.getImgType());
@ -104,11 +104,11 @@ public class StationHintServiceImpl extends BaseServiceImpl<BusLineMapper,BusLin
@Override @Override
public R<List<StationHintVo>> QueryBusLineMessage(String linename, String updown) { public R<List<StationHintVo>> QueryBusLineMessage(String linename, String updown) {
QueryWrapper<BusLine> busLineQueryWrapper = new QueryWrapper<>(); QueryWrapper<BusLine> busLineQueryWrapper = new QueryWrapper<>();
busLineQueryWrapper.eq("linename",linename); busLineQueryWrapper.eq("linename", linename);
busLineQueryWrapper.eq("updown",updown); busLineQueryWrapper.eq("updown", updown);
busLineQueryWrapper.isNotNull("sname_key"); busLineQueryWrapper.isNotNull("sname_key");
List<BusLine> busLines = busLineMapper.selectList(busLineQueryWrapper); List<BusLine> busLines = busLineMapper.selectList(busLineQueryWrapper);
if (CollectionUtils.isEmpty(busLines)){ if (CollectionUtils.isEmpty(busLines)) {
throw new ServiceException(StringUtil.format("公交站点信息为空")); throw new ServiceException(StringUtil.format("公交站点信息为空"));
} }
List<StationHintVo> stationArr = busLines.stream().map(x -> { List<StationHintVo> stationArr = busLines.stream().map(x -> {
@ -119,14 +119,12 @@ public class StationHintServiceImpl extends BaseServiceImpl<BusLineMapper,BusLin
stationHintVo.setRed(x.getActicle()); stationHintVo.setRed(x.getActicle());
stationHintVo.setGreen(x.getActivity()); stationHintVo.setGreen(x.getActivity());
stationHintVo.setYellow(x.getScenic()); stationHintVo.setYellow(x.getScenic());
stationHintVo.setJingdu(x.getJingdu().toString());
stationHintVo.setWeidu(x.getWeidu().toString());
QueryWrapper<PocBusLineImg> queryWrapper = new QueryWrapper<>(); QueryWrapper<PocBusLineImg> queryWrapper = new QueryWrapper<>();
queryWrapper.select("img_url","img_type"); queryWrapper.select("img_url", "img_type");
queryWrapper.eq("bus_line_id",x.getId()); queryWrapper.eq("bus_line_id", x.getId());
List<PocBusLineImg> pocBusLineImgs = proBusLineImgMapper.selectList(queryWrapper); List<PocBusLineImg> pocBusLineImgs = proBusLineImgMapper.selectList(queryWrapper);
ArrayList<imgVo> imgList = new ArrayList<>(); ArrayList<imgVo> imgList = new ArrayList<>();
for(PocBusLineImg pocBusLineImg : pocBusLineImgs){ for (PocBusLineImg pocBusLineImg : pocBusLineImgs) {
imgVo img = new imgVo(); imgVo img = new imgVo();
img.setImgUrl(pocBusLineImg.getImgUrl()); img.setImgUrl(pocBusLineImg.getImgUrl());
img.setImgType(pocBusLineImg.getImgType()); img.setImgType(pocBusLineImg.getImgType());
@ -182,7 +180,7 @@ public class StationHintServiceImpl extends BaseServiceImpl<BusLineMapper,BusLin
private void validateStationHintExists(Long id) { private void validateStationHintExists(Long id) {
if (busLineMapper.selectById(id) == null) { if (busLineMapper.selectById(id) == null) {
throw new ServiceException(StringUtil.format("当前id为 [{}] 的站点不存在!",id)); throw new ServiceException(StringUtil.format("当前id为 [{}] 的站点不存在!", id));
} }
} }
} }

@ -1,22 +1,41 @@
package org.springblade.modules.job; package org.springblade.modules.job;
import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springblade.common.cache.business.BusLineCache;
import org.springblade.common.cache.business.CarInfoCache;
import org.springblade.common.cache.business.SiteListCache;
import org.springblade.common.constant.BusinessConstant;
import org.springblade.common.utils.CommonUtil;
import org.springblade.common.utils.HttpClientUtils;
import org.springblade.core.tool.api.R; import org.springblade.core.tool.api.R;
import org.springblade.core.tool.utils.BeanUtil;
import org.springblade.core.tool.utils.Func; 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.service.ICarInfoService;
import org.springblade.modules.business.service.IStationHintService; import org.springblade.modules.business.service.IStationHintService;
import org.springblade.modules.business.vo.CarInfoVO; import org.springblade.modules.business.vo.CarInfoVO;
import org.springblade.modules.business.vo.SiteInfoVO;
import org.springblade.modules.business.vo.imgVo;
import org.springblade.modules.websocket.service.WebsocketService; import org.springblade.modules.websocket.service.WebsocketService;
import org.springblade.modules.websocket.vo.WebSocketMessage; import org.springblade.modules.websocket.vo.WebSocketMessage;
import org.springblade.upload.service.IProBusLineImgService;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate; import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.scheduling.annotation.Scheduled; import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RequestParam;
import springfox.documentation.spring.web.json.Json;
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.concurrent.TimeUnit;
/** /**
* @Author: Chents * @Author: Chents
@ -24,95 +43,191 @@ import java.util.Map;
*/ */
@Component @Component
@Slf4j @Slf4j
@RequiredArgsConstructor
public class CarInfoTask { public class CarInfoTask {
private static final String WEB = "web"; private static final String WEB = "web";
private static final String CURRENT_CAR_INFO = "current_car_info"; private static final String CURRENT_CAR_INFO = "current_car_info";
private static final String PUSH_STATUS = "push_status"; private static final String SPEED = "speed";
@Autowired private final ICarInfoService carInfoService;
private ICarInfoService carInfoService;
@Autowired private final RedisTemplate<String, Object> redisTemplate;
private RedisTemplate<String, Object> redisTemplate;
@Autowired private final WebsocketService websocketService;
private WebsocketService websocketService;
@Autowired private final IStationHintService stationHintService;
private IStationHintService stationHintService;
//@Scheduled(cron = "0/1 * * * * ?") private final IProBusLineImgService proBusLineImgService;
public void setCarInfo(Map<String, Object> resultMap) {
redisTemplate.opsForValue().set("current_car_info", resultMap);
System.out.println("======存入实时车辆信息到redis成功=========");
}
/**
* 从车辆信息平台同步数据
*/
@Scheduled(cron = "0/1 * * * * ?")
public void syncCarInfo() {
String url = "http://223.99.174.234:9211/BusInfoServer/bus_getstateinfo_1014?userkey=yhlhhh20230323";
String res = HttpClientUtils.doGet(url);
CarInfoCache.setAllCarData(res);
}
@Scheduled(cron = "0/10 * * * * ?") /**
* 定时将车辆运行信息推送给web
*/
@Scheduled(cron = "0/5 * * * * ?")
public void parseCarInfo() { public void parseCarInfo() {
//从redis获取数据 //从redis获取数据
Map<String, Object> carInfoMap = (Map<String, Object>) redisTemplate.opsForValue().get("current_car_info"); CarInfoVO info = null;
if (carInfoMap.isEmpty()) { String allCarData = CarInfoCache.getAllCarData();
log.info("======未从redis获取当前车辆实时数据======="); JSONObject json = JSON.parseObject(allCarData);
return; String carNo = CarInfoCache.getPushCarNo();
JSONArray carInfoList = json.getJSONArray("bus");
for (Object o : carInfoList) {
JSONObject carInfo = (JSONObject) o;
if (carNo.equals(carInfo.getString("busno"))) {
info = BeanUtil.copy(carInfo, CarInfoVO.class);
}
} }
// 解析车辆信息
HashMap<String, Object> map = new HashMap<>();
map.put("msgType", CURRENT_CAR_INFO);
map.put("data", carInfoMap);
String messageJson = JSON.toJSONString(map);
WebSocketMessage message = new WebSocketMessage(); List<SiteInfoVO> siteList = SiteListCache.getSiteList(info.getLinename(), info.getUpordown());
message.setTitle(WEB); int nextSiteIdx = Integer.parseInt(info.getInorder());
message.setCode(200); if (BusinessConstant.CAR_STAT_IN.toString().equals(info.getNowstate())) {
message.setContent(messageJson); nextSiteIdx -= 1;
//log.info("解析车辆信息:{}", carInfoMap.toString());
// 推送消息给web页面
websocketService.broadcast(message);
log.info("推送车辆信息:{}", carInfoMap.toString());
} }
@Scheduled(cron = "0/1 * * * * ?") // 下一站
public void parsePushStatus() { List<Map<String, String>> snameList = new ArrayList<>();
//从redis获取数据 SiteInfoVO nextSite = nextSiteIdx < siteList.size() ? siteList.get(nextSiteIdx) : null;
String carNo = (String) redisTemplate.opsForValue().get("car-current-number"); SiteInfoVO nextSite2 = (nextSiteIdx + 1) < siteList.size() ? siteList.get((nextSiteIdx) + 1) : null;
String pushStatus = (String) redisTemplate.opsForValue().get("set-current-Facility-stat" + carNo); SiteInfoVO nextSite3 = (nextSiteIdx + 2) < siteList.size() ? siteList.get(nextSiteIdx + 2) : null;
Map<String, String> resultData = new HashMap<>();
resultData.put("carNo", carNo); // 上一站
resultData.put("pushStatus", pushStatus); SiteInfoVO preSite = nextSiteIdx - 1 > 0 ? siteList.get(nextSiteIdx - 1) : null;
// 上两站
SiteInfoVO preTwoSite = nextSiteIdx - 2 > 0 ? siteList.get(nextSiteIdx - 2) : null;
// 上三站
SiteInfoVO preThreeSite = nextSiteIdx - 3 > 0 ? siteList.get(nextSiteIdx - 3) : null;
Map<String, String> siteMsgMap;
if (Func.isNotEmpty(preThreeSite)) {
siteMsgMap = new HashMap<>();
siteMsgMap.put("siteName", preThreeSite.getSname());
siteMsgMap.put("type", "before");
snameList.add(siteMsgMap);
}
if (Func.isNotEmpty(preTwoSite)) {
siteMsgMap = new HashMap<>();
siteMsgMap.put("siteName", preTwoSite.getSname());
siteMsgMap.put("type", "before");
snameList.add(siteMsgMap);
}
if (Func.isNotEmpty(preSite)) {
siteMsgMap = new HashMap<>();
siteMsgMap.put("siteName", preSite.getSname());
siteMsgMap.put("type", "before");
snameList.add(siteMsgMap);
}
if (Func.isNotEmpty(nextSite)) {
siteMsgMap = new HashMap<>();
siteMsgMap.put("siteName", nextSite.getSname());
siteMsgMap.put("type", "after");
snameList.add(siteMsgMap);
}
if (Func.isNotEmpty(nextSite2)) {
siteMsgMap = new HashMap<>();
siteMsgMap.put("siteName", nextSite2.getSname());
siteMsgMap.put("type", "after");
snameList.add(siteMsgMap);
}
// 计算当前车辆与前一站和后一站的距离
double pass = 0;
if (Func.isNotEmpty(preSite)) {
pass = CommonUtil.calculateDistance(Double.parseDouble(preSite.getJingdu()), Double.parseDouble(preSite.getWeidu()),
Double.parseDouble(info.getJingdu()), Double.parseDouble(info.getWeidu()));
}
double unpass = 0;
if (Func.isNotEmpty(nextSite)) {
unpass = CommonUtil.calculateDistance(Double.parseDouble(nextSite.getJingdu()), Double.parseDouble(nextSite.getWeidu()),
Double.parseDouble(info.getJingdu()), Double.parseDouble(info.getWeidu()));
}
double runPercent = (pass + unpass) > 0 ? (pass / (pass + unpass)) * 100 : 0;
DecimalFormat df1 = new DecimalFormat("#");
// 先从缓存中获取上一次的运行百分比, 然后将本次的运行百分比更新到缓存中
String runPercentStr = df1.format(runPercent > 100 ? 100 : runPercent);
String prePercentStr = (String) redisTemplate.opsForValue().get("car-run-percent-info");
prePercentStr = Func.isBlank(prePercentStr) ? "0" : prePercentStr;
redisTemplate.opsForValue().set("car-run-percent-info", runPercentStr, 30, TimeUnit.SECONDS);
Map<String, Object> siteMap = new HashMap<>();
siteMap.put("startSite", siteList.get(0).getSname());
siteMap.put("endSite", siteList.get(siteList.size() - 1).getSname());
siteMap.put("siteList", snameList);
siteMap.put("prePercent", prePercentStr);
siteMap.put("runPercent", runPercentStr);
if (Func.isEmpty(nextSite)) {
nextSite = preSite;
}
BusLine busLine = BusLineCache.getBusLine(info.getUpordown(), nextSite.getSname(), nextSite.getWeizhi());
// 组织返回数据
Map<String, Object> resultMap = new HashMap<>();
resultMap.put("siteData", siteMap);
resultMap.put("catStat", redisTemplate.opsForValue().get("car-current-stat-info" + carNo));
if (Func.isEmpty(busLine)) {
resultMap.put("siteTips", "");
resultMap.put("articleData", "");
resultMap.put("activityData", "");
resultMap.put("scenicData", "");
resultMap.put("imgData", "");
resultMap.put("speed", "");
} else {
resultMap.put("siteTips", busLine.getTips());
resultMap.put("articleData", busLine.getActicle());
resultMap.put("activityData", busLine.getActivity());
resultMap.put("scenicData", busLine.getScenic());
resultMap.put("speed", info.getSpeed());
List<BusLine> busLineList = stationHintService.getBusLineByName(nextSite.getSname());
Long busLineId = busLineList.get(0).getId();
List<imgVo> imgList = proBusLineImgService.getImgByid(busLineId);
resultMap.put("imgData", imgList);
}
// 解析车辆信息 // 解析车辆信息
HashMap<String, Object> map = new HashMap<>(); HashMap<String, Object> map = new HashMap<>();
map.put("msgType", PUSH_STATUS); map.put("msgType", CURRENT_CAR_INFO);
map.put("data", resultData); map.put("data", resultMap);
String messageJson = JSON.toJSONString(map); String messageJson = JSON.toJSONString(map);
WebSocketMessage message = new WebSocketMessage(); WebSocketMessage message = new WebSocketMessage();
message.setTitle(WEB); message.setTitle(WEB);
message.setCode(200); message.setCode(200);
message.setContent(messageJson); message.setContent(messageJson);
//log.info("解析车辆信息:{}", carInfoMap.toString());
// 推送消息给web页面 // 推送消息给web页面
websocketService.broadcast(message); websocketService.broadcast(message);
log.info("推送车辆信息:{}", map.toString());
} }
@Scheduled(cron = "0/1 * * * * ?") @Scheduled(cron = "0/1 * * * * ?")
public void getCarSpeed() { public void getCarSpeed() {
String carNo = (String) redisTemplate.opsForValue().get("car-current-number"); String carNo = CarInfoCache.getPushCarNo();
CarInfoVO info = carInfoService.getCarInfo(carNo); CarInfoVO info = carInfoService.getCarInfo(carNo);
if (Func.isEmpty(info)) { if (Func.isEmpty(info)) {
throw new RuntimeException("未获取到车辆信息, 请检查车是否已掉线"); throw new RuntimeException("未获取到车辆信息, 请检查车是否已掉线");
} }
String speedJson = JSON.toJSONString(info.getSpeed());
Map<String, String> speedMap = new HashMap<>();
speedMap.put("speed", info.getSpeed());
Map<String, Object> dataMap = new HashMap<>();
dataMap.put("msgType", SPEED);
dataMap.put("data", speedMap);
WebSocketMessage message = new WebSocketMessage(); WebSocketMessage message = new WebSocketMessage();
message.setTitle(WEB); message.setTitle(WEB);
message.setCode(200); message.setCode(200);
message.setContent(speedJson); message.setContent(JSON.toJSONString(dataMap));
websocketService.broadcast(message); websocketService.broadcast(message);
log.info("车辆实时车速:{}", message.getContent()); log.info("车辆实时车速:{}", message.getContent());
} }
} }

@ -21,12 +21,6 @@ import org.springframework.web.bind.annotation.RestController;
public class WebSocketController{ public class WebSocketController{
private final WebsocketService websocketService; private final WebsocketService websocketService;
// @GetMapping("/broadcast")
// R broadcast(@RequestParam String type, @RequestParam String msg){
// websocketService.broadcast(type, msg);
// return R.status(true);
// }
@GetMapping("/ifhasclient") @GetMapping("/ifhasclient")
boolean ifHasClient(@RequestParam String type){ boolean ifHasClient(@RequestParam String type){
boolean b = websocketService.ifHasClient(type); boolean b = websocketService.ifHasClient(type);

@ -1,13 +1,20 @@
package org.springblade.modules.websocket.handler; package org.springblade.modules.websocket.handler;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import lombok.AllArgsConstructor; import lombok.AllArgsConstructor;
import org.springblade.common.constant.BusinessConstant;
import org.springblade.core.tool.utils.Func;
import org.springblade.modules.websocket.service.WebsocketService; import org.springblade.modules.websocket.service.WebsocketService;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import org.springframework.web.socket.CloseStatus; import org.springframework.web.socket.CloseStatus;
import org.springframework.web.socket.TextMessage; import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.WebSocketSession; import org.springframework.web.socket.WebSocketSession;
import org.springframework.web.socket.handler.TextWebSocketHandler; import org.springframework.web.socket.handler.TextWebSocketHandler;
import java.util.concurrent.TimeUnit;
/** /**
* WebSocketEventListener * WebSocketEventListener
* *
@ -46,6 +53,8 @@ public class WebsocketHandler extends TextWebSocketHandler {
} }
private RedisTemplate redisTemplate;
/** /**
* 接收客户端推送数据的方法 * 接收客户端推送数据的方法
* *
@ -57,7 +66,16 @@ public class WebsocketHandler extends TextWebSocketHandler {
protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception { protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception {
System.out.println("Received message from client: " + message.getPayload()); System.out.println("Received message from client: " + message.getPayload());
TextMessage msg = new TextMessage(message.getPayload()); TextMessage msg = new TextMessage(message.getPayload());
session.sendMessage(msg);
}
if (Func.isNotBlank(msg.getPayload())) {
// {"msgType":"status","data":{"status":"ok"}}
JSONObject jsonObject = JSON.parseObject(msg.getPayload());
if ("status".equals(jsonObject.get("msgType"))) {
JSONObject data = jsonObject.getJSONObject("data");
if ("ok".equals(data.get("status"))) {
redisTemplate.opsForValue().set("websocket-status-return", BusinessConstant.BOOLEAN_STR_TRUE, 5, TimeUnit.SECONDS);
}
}
}
}
} }

Loading…
Cancel
Save