|
@@ -0,0 +1,357 @@
|
|
|
|
|
+package org.dromara.util;
|
|
|
|
|
+
|
|
|
|
|
+import cn.hutool.core.date.DateField;
|
|
|
|
|
+import cn.hutool.core.date.DatePattern;
|
|
|
|
|
+import cn.hutool.core.date.DateUtil;
|
|
|
|
|
+import cn.hutool.core.util.StrUtil;
|
|
|
|
|
+import cn.hutool.http.HttpRequest;
|
|
|
|
|
+import cn.hutool.json.JSONArray;
|
|
|
|
|
+import cn.hutool.json.JSONObject;
|
|
|
|
|
+import cn.hutool.json.JSONUtil;
|
|
|
|
|
+import com.alibaba.fastjson.JSON;
|
|
|
|
|
+import org.apache.xmlbeans.impl.xb.xsdschema.Public;
|
|
|
|
|
+import org.dromara.common.core.utils.SpringUtils;
|
|
|
|
|
+import org.dromara.common.core.utils.StringUtils;
|
|
|
|
|
+import org.dromara.common.redis.utils.CacheUtils;
|
|
|
|
|
+import org.dromara.common.redis.utils.RedisUtils;
|
|
|
|
|
+import org.dromara.system.domain.GpsData;
|
|
|
|
|
+import org.dromara.system.domain.TblCarInfo;
|
|
|
|
|
+import org.dromara.system.domain.bo.SysDictDataBo;
|
|
|
|
|
+import org.dromara.system.domain.bo.TblCarInfoBo;
|
|
|
|
|
+import org.dromara.system.domain.bo.TblCarScheduleBo;
|
|
|
|
|
+import org.dromara.system.domain.vo.SysDictDataVo;
|
|
|
|
|
+import org.dromara.system.domain.vo.TblCarInfoVo;
|
|
|
|
|
+import org.dromara.system.domain.vo.TblCarScheduleVo;
|
|
|
|
|
+import org.dromara.system.service.ISysDictDataService;
|
|
|
|
|
+import org.dromara.system.service.impl.TblCarInfoServiceImpl;
|
|
|
|
|
+import org.dromara.system.service.impl.TblCarScheduleServiceImpl;
|
|
|
|
|
+import org.slf4j.Logger;
|
|
|
|
|
+import org.slf4j.LoggerFactory;
|
|
|
|
|
+import org.springframework.scheduling.annotation.Scheduled;
|
|
|
|
|
+import org.springframework.stereotype.Component;
|
|
|
|
|
+
|
|
|
|
|
+import javax.crypto.Cipher;
|
|
|
|
|
+import java.security.Key;
|
|
|
|
|
+import java.text.DateFormat;
|
|
|
|
|
+import java.util.ArrayList;
|
|
|
|
|
+import java.util.HashMap;
|
|
|
|
|
+import java.util.List;
|
|
|
|
|
+import java.util.Map;
|
|
|
|
|
+
|
|
|
|
|
+@Component
|
|
|
|
|
+public class CabinetUtil {
|
|
|
|
|
+
|
|
|
|
|
+ private final static String appid = "bw_open_express_A8C848769E5C04E0";
|
|
|
|
|
+ private final static String appkey = "5AFC6E07CFCF4A359B775D1416A9799A";
|
|
|
|
|
+
|
|
|
|
|
+ private final static String hosts = "https://open.bestwond.com";
|
|
|
|
|
+
|
|
|
|
|
+ public final static String CABINET_INFO = "cabinet_info";
|
|
|
|
|
+ public final static String CABINET_BOXS = "cabinet_boxs";
|
|
|
|
|
+ private static final Logger log = LoggerFactory.getLogger(CabinetUtil.class);
|
|
|
|
|
+
|
|
|
|
|
+ private static String byteArr2HexStr(byte[] arrB) throws Exception {
|
|
|
|
|
+ int iLen = arrB.length;
|
|
|
|
|
+ // 每个byte用两个字符才能表示,所以字符串的长度是数组长度的两倍
|
|
|
|
|
+ StringBuffer sb = new StringBuffer(iLen * 2);
|
|
|
|
|
+ for (int i = 0; i < iLen; i++) {
|
|
|
|
|
+ int intTmp = arrB[i];
|
|
|
|
|
+ // 把负数转换为正数
|
|
|
|
|
+ while (intTmp < 0) {
|
|
|
|
|
+ intTmp = intTmp + 256;
|
|
|
|
|
+ }
|
|
|
|
|
+ // 小于0F的数需要在前面补0
|
|
|
|
|
+ if (intTmp < 16) {
|
|
|
|
|
+ sb.append("0");
|
|
|
|
|
+ }
|
|
|
|
|
+ sb.append(Integer.toString(intTmp, 16));
|
|
|
|
|
+ }
|
|
|
|
|
+ return sb.toString();
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ private static String encrypt(String strIn) throws Exception {
|
|
|
|
|
+ return byteArr2HexStr(encrypt(strIn.getBytes("UTF-8")));
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ private static byte[] encrypt(byte[] arrB) throws Exception {
|
|
|
|
|
+ Key key = getKey(appkey.getBytes("UTF-8"));
|
|
|
|
|
+ Cipher encryptCipher = Cipher.getInstance("DES");
|
|
|
|
|
+ encryptCipher.init(Cipher.ENCRYPT_MODE, key);
|
|
|
|
|
+ return encryptCipher.doFinal(arrB);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ private static Key getKey(byte[] arrBTmp) throws Exception {
|
|
|
|
|
+ // 创建一个空的8位字节数组(默认值为0)
|
|
|
|
|
+ byte[] arrB = new byte[8];
|
|
|
|
|
+ // 将原始字节数组转换为8位
|
|
|
|
|
+ for (int i = 0; i < arrBTmp.length && i < arrB.length; i++) {
|
|
|
|
|
+ arrB[i] = arrBTmp[i];
|
|
|
|
|
+ }
|
|
|
|
|
+ // 生成密钥
|
|
|
|
|
+ Key key = new javax.crypto.spec.SecretKeySpec(arrB, "DES");
|
|
|
|
|
+ return key;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+// private static String getQJM(String phone) throws Exception {
|
|
|
|
|
+// String text = SpringUtils.getBean(ISysConfigService.class).selectConfigByKey("sys.cabinet.account");
|
|
|
|
|
+//
|
|
|
|
|
+// }
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+ @Scheduled(fixedRate = 5*60*1000)
|
|
|
|
|
+ private void genScheduleList(){
|
|
|
|
|
+
|
|
|
|
|
+ TblCarScheduleBo bo =new TblCarScheduleBo();
|
|
|
|
|
+ bo.getParams().put("scheduleDate",DateUtil.format(DateUtil.date(),"yyyy-MM-dd"));
|
|
|
|
|
+ List<TblCarScheduleVo> scheduleVos = SpringUtils.getBean(TblCarScheduleServiceImpl.class).queryList(bo);
|
|
|
|
|
+ TblCarScheduleBo bo2 =new TblCarScheduleBo();
|
|
|
|
|
+ bo2.getParams().put("scheduleDate",DateUtil.format(DateUtil.date().offset(DateField.DAY_OF_MONTH,1),"yyyy-MM-dd"));
|
|
|
|
|
+ List<TblCarScheduleVo> scheduleVos2 = SpringUtils.getBean(TblCarScheduleServiceImpl.class).queryList(bo2);
|
|
|
|
|
+ Map<String,Object> map=new HashMap<>();
|
|
|
|
|
+ scheduleVos2.forEach(scheduleVo2->{
|
|
|
|
|
+ map.put(scheduleVo2.getCarNum()+DateUtil.format(scheduleVo2.getScheduleDate(),DatePattern.NORM_DATETIME_PATTERN),scheduleVo2);
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+ for (TblCarScheduleVo scheduleVo : scheduleVos) {
|
|
|
|
|
+ if(StrUtil.isNotEmpty(scheduleVo.getExt2())){
|
|
|
|
|
+ try{
|
|
|
|
|
+ if(JSONUtil.parseObj(scheduleVo.getExt2()).getBool("isauto") && map.get(scheduleVo.getCarNum()+DateUtil.format( DateUtil.date(scheduleVo.getScheduleDate()).offset(DateField.DAY_OF_MONTH,1),DatePattern.NORM_DATETIME_PATTERN))==null){
|
|
|
|
|
+ //copy
|
|
|
|
|
+ TblCarScheduleBo bo1 =new TblCarScheduleBo();
|
|
|
|
|
+ bo1.setCarNum(scheduleVo.getCarNum());
|
|
|
|
|
+ bo1.setScheduleDate(DateUtil.offset(scheduleVo.getScheduleDate(),DateField.DAY_OF_MONTH,1));
|
|
|
|
|
+ bo1.setPathInfo(scheduleVo.getPathInfo());
|
|
|
|
|
+ bo1.setCreateTime(DateUtil.date());
|
|
|
|
|
+ bo1.setExt2(scheduleVo.getExt2());
|
|
|
|
|
+ bo1.setCreateDept(103100L);
|
|
|
|
|
+ SpringUtils.getBean(TblCarScheduleServiceImpl.class).insertByBo(bo1);
|
|
|
|
|
+ }
|
|
|
|
|
+ }catch (Exception e){
|
|
|
|
|
+
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ }
|
|
|
|
|
+ @Scheduled(fixedRate = 5*60*1000)
|
|
|
|
|
+ private void getGpsList(){
|
|
|
|
|
+ List<TblCarInfoVo> carInfoVos = SpringUtils.getBean(TblCarInfoServiceImpl.class).queryList(new TblCarInfoBo());
|
|
|
|
|
+ for (TblCarInfoVo car : carInfoVos) {
|
|
|
|
|
+ if(StrUtil.isNotEmpty(car.getDeviceInfos())){
|
|
|
|
|
+ JSONUtil.parseArray(car.getDeviceInfos()).forEach(item->{
|
|
|
|
|
+ JSONObject c = (JSONObject)item;
|
|
|
|
|
+ if(c.getStr("type").equals("gps")){
|
|
|
|
|
+ GpsData gpsData = RedisUtils.getCacheObject(StringUtils.format("gps_{}", c.getStr("code")));
|
|
|
|
|
+ //1小时就离线
|
|
|
|
|
+ Map<String,Object> map=new HashMap<>();
|
|
|
|
|
+ if(gpsData.getTs()==null){
|
|
|
|
|
+ gpsData.setTs(DateUtil.date());
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ if(DateUtil.current() - gpsData.getTs().getTime()> 1000*60*60){
|
|
|
|
|
+ map.put("code",c.getStr("code"));
|
|
|
|
|
+ map.put("time", DatePattern.NORM_DATETIME_FORMAT.format(gpsData.getTs()));
|
|
|
|
|
+ map.put("station",car.getCarNum());
|
|
|
|
|
+ CacheUtils.put("offline",c.getStr("code"),map);
|
|
|
|
|
+ }else{
|
|
|
|
|
+ CacheUtils.put("offline",c.getStr("code"),map);
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ });
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+ @Scheduled(fixedRate = 5*60*1000)
|
|
|
|
|
+ private void getList(){
|
|
|
|
|
+ //获取所有gps 判断是否离线
|
|
|
|
|
+ List<List<String>> cabinetList = new ArrayList<>();
|
|
|
|
|
+ SysDictDataBo bo =new SysDictDataBo();
|
|
|
|
|
+ bo.setDictType("tbl_sites");
|
|
|
|
|
+ List<SysDictDataVo> list = SpringUtils.getBean(ISysDictDataService.class).selectDictDataList(bo);
|
|
|
|
|
+ try {
|
|
|
|
|
+ list.forEach(item->{
|
|
|
|
|
+ if(StrUtil.isNotEmpty(item.getRemark())){
|
|
|
|
|
+ JSONArray jsonArray = JSONUtil.parseArray(item.getRemark());
|
|
|
|
|
+ jsonArray.forEach(item2->{
|
|
|
|
|
+ if(((JSONObject)item2).getStr("type").equals("cabinet")){
|
|
|
|
|
+ cabinetList.add( List.of(item.getDictLabel(),((JSONObject)item2).getStr("code")));
|
|
|
|
|
+ }
|
|
|
|
|
+ });
|
|
|
|
|
+ }
|
|
|
|
|
+ });
|
|
|
|
|
+ }catch (Exception e){
|
|
|
|
|
+
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+ if(cabinetList.size()>0){
|
|
|
|
|
+ cabinetList.forEach(item->{
|
|
|
|
|
+ try {
|
|
|
|
|
+ Thread.sleep(1000);
|
|
|
|
|
+ String details= CabinetUtil.getCabinetInfo(item.get(1));
|
|
|
|
|
+ CacheUtils.put(CABINET_INFO,item.get(1),details);
|
|
|
|
|
+ log.info(StrUtil.format("获取到柜子信息:{},{}",item.get(1),details));
|
|
|
|
|
+ Thread.sleep(1000);
|
|
|
|
|
+ //获取柜子状态
|
|
|
|
|
+ String boxs= CabinetUtil.getCabinetBoxs(item.get(1));
|
|
|
|
|
+ CacheUtils.put(CABINET_BOXS,item.get(1),boxs);
|
|
|
|
|
+ log.info(StrUtil.format("获取到柜子箱子信息:{},{}",item.get(1),boxs));
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+ try{
|
|
|
|
|
+ Integer obline = JSONUtil.parseObj(details).getJSONObject("data").getInt("device_line");
|
|
|
|
|
+ Map<String,Object> map=new HashMap<>();
|
|
|
|
|
+ if(obline==0){
|
|
|
|
|
+ map.put("code",item.get(1));
|
|
|
|
|
+ map.put("time",DateUtil.now());
|
|
|
|
|
+ map.put("station",item.get(0));
|
|
|
|
|
+ //离线告警
|
|
|
|
|
+ CacheUtils.put("offline",item.get(1),map);
|
|
|
|
|
+ }else{
|
|
|
|
|
+ CacheUtils.put("offline",item.get(1),map);
|
|
|
|
|
+ }
|
|
|
|
|
+ }catch(Exception e){
|
|
|
|
|
+ log.error("快递柜信息解析错误");
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ try{
|
|
|
|
|
+ Map<String,Integer> map=new HashMap<>();
|
|
|
|
|
+ map.put("total",JSONUtil.parseObj(boxs).getJSONObject("data").getJSONObject("page").getInt("total_count"));
|
|
|
|
|
+ JSONUtil.parseObj(boxs).getJSONObject("data").getJSONArray("list").forEach(item2->{
|
|
|
|
|
+ if(((JSONObject)item2).getInt("box_use_status")==1){
|
|
|
|
|
+ map.put("used",map.get("used")==null?1:map.get("used")+1);
|
|
|
|
|
+ }else{
|
|
|
|
|
+ map.put("unuse",map.get("unuse")==null?1:map.get("unuse")+1);
|
|
|
|
|
+ }
|
|
|
|
|
+ });
|
|
|
|
|
+ if(map.get("used")==null) map.put("used",0);
|
|
|
|
|
+ if(map.get("unuse")==null) map.put("unuse",0);
|
|
|
|
|
+ CacheUtils.put(CABINET_INFO,item.get(1)+"_box",map);
|
|
|
|
|
+ }catch(Exception e){
|
|
|
|
|
+ log.error("快递柜box解析错误");
|
|
|
|
|
+ }
|
|
|
|
|
+ } catch (Exception e) {
|
|
|
|
|
+ throw new RuntimeException(e);
|
|
|
|
|
+ }
|
|
|
|
|
+ });
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+ // 获取柜子信息
|
|
|
|
|
+ public static String getCabinetInfo(String cabinetCode) throws Exception {
|
|
|
|
|
+ int times = (int) (DateUtil.date().getTime()/1000);
|
|
|
|
|
+ String str_sign = appid + "=" + times + "=" + appid;
|
|
|
|
|
+ str_sign = encrypt(str_sign);
|
|
|
|
|
+
|
|
|
|
|
+ String result3= HttpRequest.post(hosts+"/kd/api/v2/action/device_info/").body(JSON.toJSONString(Map.of("device_number",cabinetCode)))
|
|
|
|
|
+ .addHeaders(Map.of("timestamp",times+"","Content-Type","application/json","appid",appid,"sign",str_sign))
|
|
|
|
|
+ .execute().body();
|
|
|
|
|
+ return result3;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 获取柜子统计
|
|
|
|
|
+ public static String getCabinetStatistics(String cabinetCode,String startTime,String endTime) throws Exception {
|
|
|
|
|
+ int times = (int) (DateUtil.date().getTime()/1000);
|
|
|
|
|
+ String str_sign = appid + "=" + times + "=" + appid;
|
|
|
|
|
+ str_sign = encrypt(str_sign);
|
|
|
|
|
+
|
|
|
|
|
+ String result3= HttpRequest.post(hosts + "/kd/api/v2/action/deliver_statistics/").body(JSON.toJSONString(Map.of("device_number",cabinetCode,"strat_time",startTime,"end_time",endTime)))
|
|
|
|
|
+ .addHeaders(Map.of("timestamp",times+"","Content-Type","application/json","appid",appid,"sign",str_sign))
|
|
|
|
|
+ .execute().body();
|
|
|
|
|
+ return result3;
|
|
|
|
|
+
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 获取柜子盒子
|
|
|
|
|
+ public static String getCabinetBoxs(String cabinetCode) throws Exception {
|
|
|
|
|
+ int times = (int) (DateUtil.date().getTime()/1000);
|
|
|
|
|
+ String str_sign = appid + "=" + times + "=" + appid;
|
|
|
|
|
+ str_sign = encrypt(str_sign);
|
|
|
|
|
+
|
|
|
|
|
+ String result3= HttpRequest.post(hosts + "/kd/api/v2/action/box_info_list/").body(JSON.toJSONString(Map.of("device_number",cabinetCode,"page_size",1000)))
|
|
|
|
|
+ .addHeaders(Map.of("timestamp",times+"","Content-Type","application/json","appid",appid,"sign",str_sign))
|
|
|
|
|
+ .execute().body();
|
|
|
|
|
+ return result3;
|
|
|
|
|
+
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 开柜
|
|
|
|
|
+ public static String openCabinetBoxs(String cabinetCode,String lookAddr) throws Exception {
|
|
|
|
|
+ int times = (int) (DateUtil.date().getTime()/1000);
|
|
|
|
|
+ String str_sign = appid + "=" + times + "=" + appid;
|
|
|
|
|
+ str_sign = encrypt(str_sign);
|
|
|
|
|
+
|
|
|
|
|
+ String result3= HttpRequest.post(hosts + "/kd/api/v2/action/open_box/").body(JSON.toJSONString(Map.of("device_number",cabinetCode,"lock_address",lookAddr)))
|
|
|
|
|
+ .addHeaders(Map.of("timestamp",times+"","Content-Type","application/json","appid",appid,"sign",str_sign))
|
|
|
|
|
+ .execute().body();
|
|
|
|
|
+ return result3;
|
|
|
|
|
+
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 开所有柜
|
|
|
|
|
+ public static String openCabinetBoxAll(String cabinetCode) throws Exception {
|
|
|
|
|
+ int times = (int) (DateUtil.date().getTime()/1000);
|
|
|
|
|
+ String str_sign = appid + "=" + times + "=" + appid;
|
|
|
|
|
+ str_sign = encrypt(str_sign);
|
|
|
|
|
+
|
|
|
|
|
+ String result3= HttpRequest.post(hosts + "/kd/api/v2/action/open_box_all/").body(JSON.toJSONString(Map.of("device_number",cabinetCode)))
|
|
|
|
|
+ .addHeaders(Map.of("timestamp",times+"","Content-Type","application/json","appid",appid,"sign",str_sign))
|
|
|
|
|
+ .execute().body();
|
|
|
|
|
+ return result3;
|
|
|
|
|
+
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ //清理格子(不开启)
|
|
|
|
|
+ public static String clearCabinetBox(String cabinetCode,String boxUUId) throws Exception {
|
|
|
|
|
+ int times = (int) (DateUtil.date().getTime()/1000);
|
|
|
|
|
+ String str_sign = appid + "=" + times + "=" + appid;
|
|
|
|
|
+ str_sign = encrypt(str_sign);
|
|
|
|
|
+
|
|
|
|
|
+ String result3= HttpRequest.post(hosts + "/kd/api/v2/action/clear_box/").body(JSON.toJSONString(Map.of("device_number",cabinetCode,"box_uid",boxUUId)))
|
|
|
|
|
+ .addHeaders(Map.of("timestamp",times+"","Content-Type","application/json","appid",appid,"sign",str_sign))
|
|
|
|
|
+ .execute().body();
|
|
|
|
|
+ return result3;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ //清理格子(开启)
|
|
|
|
|
+ public static String clearCabinetBoxOpen(String cabinetCode,String boxUUId) throws Exception {
|
|
|
|
|
+ int times = (int) (DateUtil.date().getTime()/1000);
|
|
|
|
|
+ String str_sign = appid + "=" + times + "=" + appid;
|
|
|
|
|
+ str_sign = encrypt(str_sign);
|
|
|
|
|
+
|
|
|
|
|
+ String result3= HttpRequest.post(hosts + "/kd/api/v2/action/clear_box_open/").body(JSON.toJSONString(Map.of("device_number",cabinetCode,"box_uid",boxUUId)))
|
|
|
|
|
+ .addHeaders(Map.of("timestamp",times+"","Content-Type","application/json","appid",appid,"sign",str_sign))
|
|
|
|
|
+ .execute().body();
|
|
|
|
|
+ return result3;
|
|
|
|
|
+
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 获取取件码
|
|
|
|
|
+ public static String getQJM(String phone) throws Exception {
|
|
|
|
|
+ int times = (int) (DateUtil.date().getTime()/1000);
|
|
|
|
|
+ String str_sign = appid + "=" + times + "=" + appid;
|
|
|
|
|
+ str_sign = encrypt(str_sign);
|
|
|
|
|
+
|
|
|
|
|
+ String result3= HttpRequest.post(hosts + "/kd/api/v2/query/pick_code_by_user_mobile/").body(JSON.toJSONString(Map.of("get_user_mobile",phone)))
|
|
|
|
|
+ .addHeaders(Map.of("timestamp",times+"","Content-Type","application/json","appid",appid,"sign",str_sign))
|
|
|
|
|
+ .execute().body();
|
|
|
|
|
+ return result3;
|
|
|
|
|
+
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+}
|