增加gps定时任务

This commit is contained in:
zhangyue 2026-07-31 17:32:18 +08:00
parent bb6acf7ced
commit 17892dc637
27 changed files with 1742 additions and 61 deletions

View File

@ -80,7 +80,7 @@ public class MybatisPlusGenerator {
public static void main(String[] args) { public static void main(String[] args) {
new MybatisPlusGenerator().generator("surv_transdata_flowmeter","surv_hisdata_flowmeter");//指标 new MybatisPlusGenerator().generator("surv_gps_info","surv_gps_record","surv_vehicle_info");//指标
} }

View File

@ -1,6 +1,7 @@
package com.lanhai.constant; package com.lanhai.constant;
public interface IotConstants { public interface IotConstants {
/** ------------------------------------------------------厂家识别码-----------------------------------------------------------*/
/** /**
* 萤石云访问 * 萤石云访问
*/ */
@ -32,6 +33,24 @@ public interface IotConstants {
*/ */
String gcszxc_access = "gcszxc_access"; String gcszxc_access = "gcszxc_access";
/**
* 仁科应用
*/
String renke_access = "RenKe_access";
/**
* 曲沃山东芯谷网络密钥
*/
String qwxgwl_access = "qwxgwl_access";
/**
* 曲沃山东优晟系统密钥
*/
String qwmeter_access = "qwmeter_access";
/** ------------------------------------------------------厂家识别码-----------------------------------------------------------*/
/** ------------------------------------------------------redis缓存头-----------------------------------------------------------*/
/** /**
* 新普惠应用 * 新普惠应用
*/ */
@ -49,9 +68,48 @@ public interface IotConstants {
String APPLICATION_RenKe = "RenKe"; String APPLICATION_RenKe = "RenKe";
/** /**
* 仁科应用 * 物联网配置缓存头
*/ */
String renke_access = "RenKe_access"; String IOT_SURVCONFIG_CACHE = "surv:config:params";
/** ------------------------------------------------------redis缓存头-----------------------------------------------------------*/
/** ------------------------------------------------------数据生成-----------------------------------------------------------*/
/**
* 生成数据标记
*/
String MARK_GENDATA = "GenData";
/**
* 真实数据标记
*/
String MARK_REALDATA = "RealTime";
/**
* 规则类型 历史
*/
String RULE_HISTORY = "rule_history";
/**
* 规则类型 预设
*/
String RULE_PRE = "rule_preset";
/** ------------------------------------------------------数据生成-----------------------------------------------------------*/
/** ------------------------------------------------------物联网协议-----------------------------------------------------------*/
/**
*
* 深圳帝馨gps协议
*/
String PROTOCOL_SZDXGPS = "szdx_gps_protocol";
/** /**
* 萤石云标准 * 萤石云标准
@ -100,10 +158,6 @@ public interface IotConstants {
String qwxgwl_standard = "qwxgwl_standard"; String qwxgwl_standard = "qwxgwl_standard";
/**
* 曲沃山东芯谷网络密钥
*/
String qwxgwl_access = "qwxgwl_access";
/** /**
@ -111,10 +165,7 @@ public interface IotConstants {
*/ */
String qwmeter_standard = "qwmeter_standard"; String qwmeter_standard = "qwmeter_standard";
/**
* 曲沃山东优晟系统密钥
*/
String qwmeter_access = "qwmeter_access";
/** /**
@ -127,6 +178,15 @@ public interface IotConstants {
*/ */
String renke_standard = "RenKe_standard"; String renke_standard = "RenKe_standard";
/**
* 蓝海虚拟设备协议
*/
String lhviot_standard = "lhviot_standard";
/** ------------------------------------------------------物联网协议-----------------------------------------------------------*/
/** ------------------------------------------------------业务逻辑-----------------------------------------------------------*/
/** /**
* 害虫目录 * 害虫目录
*/ */
@ -189,42 +249,10 @@ public interface IotConstants {
*/ */
String iot_device_guard = "guard"; String iot_device_guard = "guard";
/**
* 物联网配置缓存头
*/
String IOT_SURVCONFIG_CACHE = "surv:config:params";
/**
* 生成数据标记
*/
String MARK_GENDATA = "GenData";
/**
* 真实数据标记
*/
String MARK_REALDATA = "RealTime";
/**
* 规则类型 历史
*/
String RULE_HISTORY = "rule_history";
/**
* 规则类型 预设
*/
String RULE_PRE = "rule_preset";
/**
* 蓝海虚拟设备协议
*/
String lhviot_standard = "lhviot_standard";
/** /**
* mqtt连接协议 * mqtt连接协议
*/ */
String CONFIG_TYPE_MQTT = "mqtt"; String CONFIG_TYPE_MQTT = "mqtt";
/** ------------------------------------------------------业务逻辑-----------------------------------------------------------*/
} }

View File

@ -0,0 +1,21 @@
package com.lanhai.controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.stereotype.Controller;
/**
* <p>
* gps信息 前端控制器
* </p>
*
* @author ${author}
* @since 2026-07-30
*/
@Controller
@RequestMapping("/survGpsInfo")
public class SurvGpsInfoController {
}

View File

@ -0,0 +1,21 @@
package com.lanhai.controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.stereotype.Controller;
/**
* <p>
* gsp轨迹记录 前端控制器
* </p>
*
* @author ${author}
* @since 2026-07-30
*/
@Controller
@RequestMapping("/survGpsRecord")
public class SurvGpsRecordController {
}

View File

@ -0,0 +1,21 @@
package com.lanhai.controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.stereotype.Controller;
/**
* <p>
* 车辆信息表 前端控制器
* </p>
*
* @author ${author}
* @since 2026-07-30
*/
@Controller
@RequestMapping("/survVehicleInfo")
public class SurvVehicleInfoController {
}

View File

@ -0,0 +1,205 @@
package com.lanhai.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.extension.activerecord.Model;
import java.time.LocalDateTime;
import java.util.Date;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableField;
import java.io.Serializable;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
/**
* <p>
* gps信息
* </p>
*
* @author ${author}
* @since 2026-07-30
*/
@Data
@EqualsAndHashCode(callSuper = false)
@Accessors(chain = true)
public class SurvGpsInfo extends Model<SurvGpsInfo> {
private static final long serialVersionUID=1L;
/**
* 主键
*/
@TableId(value = "ID", type = IdType.ID_WORKER_STR)
private String id;
/**
* 设备名称
*/
@TableField("GPS_NAME")
private String gpsName;
/**
* gps类型;vehicle=车辆
*/
@TableField("GPS_TYPE")
private String gpsType;
/**
* 物联网协议编号
*/
@TableField("PROTOCOL_CODE")
private String protocolCode;
/**
* 连接密钥配置ID
*/
@TableField("SURV_CONFIG_ID")
private String survConfigId;
/**
* 牌照号
*/
@TableField("GPS_PLATE_NUMBER")
private String gpsPlateNumber;
/**
* 设备id
*/
@TableField("GPS_DEVICE_ID")
private String gpsDeviceId;
/**
* 设备编号
*/
@TableField("GPS_CODE")
private String gpsCode;
/**
* 设备识别码;用于回执时的鉴别一般与GPS_DEVICE_ID相同
*/
@TableField("GPS_IDENT")
private String gpsIdent;
/**
* 是否在线;0=离线 1=在线静止 2=在线行驶
*/
@TableField("ONLINE_STATUS")
private Integer onlineStatus;
/**
* 速度
*/
@TableField("GPS_SPEED")
private String gpsSpeed;
/**
* 设防状态
*/
@TableField("DEFENCE_STATUS")
private String defenceStatus;
/**
* 定位时间
*/
@TableField("GPS_TIME")
private String gpsTime;
/**
* sim卡号
*/
@TableField("SIM_NUM")
private String simNum;
/**
* 设备型号
*/
@TableField("MAC_NAME")
private String macName;
/**
* 最后更新时间
*/
@TableField("LAST_UPD_TIME")
private LocalDateTime lastUpdTime;
/**
* 最后更新时间
*/
@TableField("LAST_SYNC_TIME")
private LocalDateTime lastSyncTime;
/**
* 设备备注
*/
@TableField("GPS_NOTES")
private String gpsNotes;
/**
* gsp状态;1=启用0=禁用
*/
@TableField("GPS_STATUS")
private Integer gpsStatus;
/**
* 排序值
*/
@TableField("SORT_NO")
private Integer sortNo;
/**
* 租户号
*/
@TableField("TENANT_ID")
private String tenantId;
/**
* 乐观锁
*/
@TableField("RE_VISION")
private Integer reVision;
/**
* 创建人
*/
@TableField("CREATE_BY")
private String createBy;
/**
* 创建时间
*/
@TableField("CREATE_TIME")
private LocalDateTime createTime;
/**
* 更新人
*/
@TableField("UPDATE_BY")
private String updateBy;
/**
* 逻辑删除
*/
@TableField("IS_DEL")
private Integer isDel;
/**
* 更新时间
*/
@TableField("UPDATE_TIME")
private LocalDateTime updateTime;
/**
* 乐观锁
*/
@TableField("REVISION")
private Integer revision;
@Override
protected Serializable pkVal() {
return this.id;
}
}

View File

@ -0,0 +1,330 @@
package com.lanhai.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.extension.activerecord.Model;
import java.time.LocalDateTime;
import java.util.Date;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableField;
import java.io.Serializable;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
/**
* <p>
* gsp轨迹记录
* </p>
*
* @author ${author}
* @since 2026-07-30
*/
@Data
@EqualsAndHashCode(callSuper = false)
@Accessors(chain = true)
public class SurvGpsRecord extends Model<SurvGpsRecord> {
private static final long serialVersionUID=1L;
/**
* 主键
*/
@TableId(value = "ID", type = IdType.ID_WORKER_STR)
private String id;
/**
* gpsid
*/
@TableField("GPS_ID")
private String gpsId;
/**
* 设备id
*/
@TableField("GPS_DEVICE_ID")
private String gpsDeviceId;
/**
* 设备号
*/
@TableField("GPS_CODE")
private String gpsCode;
/**
* 设备识别码
*/
@TableField("GPS_IDENT")
private String gpsIdent;
/**
* 数据id
*/
@TableField("DATA_ID")
private String dataId;
/**
* 数据采集时间
*/
@TableField("DATA_DATE_TIME")
private LocalDateTime dataDateTime;
/**
* 设备定位时间
*/
@TableField("`SYS_TIME`")
private String sys_time;
/**
* 设备名称
*/
@TableField("`USER_NAME`")
private String user_name;
/**
* 经度;gps定位
*/
@TableField("`JINGDU`")
private String jingdu;
/**
* 纬度;gps定位
*/
@TableField("`WEIDU`")
private String weidu;
/**
* 基站经度;基站或wifi定位 使用此处经纬度
*/
@TableField("`LJINGDU`")
private String ljingdu;
/**
* 基站纬度;基站或wifi定位 使用此处经纬度
*/
@TableField("`LWEIDU`")
private String lweidu;
/**
* 数据更新时间;服务器接收时间
*/
@TableField("`DATETIME`")
private String datetime;
/**
* 设备心跳时间;信号时间
*/
@TableField("`HEART_TIME`")
private String heart_time;
/**
* 速度
*/
@TableField("`SU`")
private String su;
/**
* 状态组;如下表status
*/
@TableField("`STATUS`")
private String status;
/**
* 方向
*/
@TableField("`HANGXIANG`")
private String hangxiang;
/**
* 设备编号;对应 GPS_CODE 设备号
*/
@TableField("`SIM_ID`")
private String sim_id;
/**
* 设备id;对应GPS_IDENT 识别码
*/
@TableField("`USER_ID`")
private String user_id;
/**
* 销售类型-无用途
*/
@TableField("`SALE_TYPE`")
private String sale_type;
/**
* 图标
*/
@TableField("`ICONTYPE`")
private String iconType;
/**
* 系统时间;当前时间
*/
@TableField("`SERVER_TIME`")
private String server_time;
/**
* 设备类型;例如A15
*/
@TableField("`PRODUCT_TYPE`")
private String product_type;
/**
* 到期时间;一般为204x年2393798400000
*/
@TableField("`EXPIRE_DATE`")
private String expire_date;
/**
* 监控组ID
*/
@TableField("`GROUP_ID`")
private String group_id;
/**
* 信息组;如下表status
*/
@TableField("`STATENUMBER`")
private String statenumber;
/**
* 例如100
*/
@TableField("`ELECTRIC`")
private String electric;
/**
* 设备描述信息;例如 ICCID:通常存放一些设备上传的运行参数
*/
@TableField("`DESCRIBE`")
private String describe;
/**
* sim卡
*/
@TableField("`SIM`")
private String sim;
/**
* 精度误差;当值为10表示gps定位无精度
*/
@TableField("`PRECISION`")
private String precision;
/**
* 是否关注
*/
@TableField("`ISFOLLOW`")
private String isFollow;
/**
* 车牌号
*/
@TableField("`PLATENUMBER`")
private String plateNumber;
/**
* 授权信息
*/
@TableField("`AUTH`")
private String auth;
/**
* 授权列表
*/
@TableField("`AUTHLIST`")
private String authList;
/**
* 部门名称
*/
@TableField("`DEPTNAME`")
private String deptname;
/**
* 是否显示位置
*/
@TableField("`ISSHOWLOCATION`")
private String IsShowLocation;
/**
* 模板扩展
*/
@TableField("`TEMPEXT`")
private String tempExt;
/**
* 卡到期
*/
@TableField("`CARDEXPIRE`")
private String cardExpire;
/**
* 地理围栏ID
*/
@TableField("`POLYGONFENCE_ID`")
private String polygonFence_id;
/**
* 扩展信息
*/
@TableField("`EXTENDEDSTATE`")
private String extendedState;
/**
* 租户号
*/
@TableField("TENANT_ID")
private String tenantId;
/**
* 乐观锁
*/
@TableField("RE_VISION")
private Integer reVision;
/**
* 创建人
*/
@TableField("CREATE_BY")
private String createBy;
/**
* 创建时间
*/
@TableField("CREATE_TIME")
private LocalDateTime createTime;
/**
* 更新人
*/
@TableField("UPDATE_BY")
private String updateBy;
/**
* 逻辑删除
*/
@TableField("IS_DEL")
private Integer isDel;
/**
* 更新时间
*/
@TableField("UPDATE_TIME")
private LocalDateTime updateTime;
/**
* 乐观锁
*/
@TableField("REVISION")
private Integer revision;
@Override
protected Serializable pkVal() {
return this.id;
}
}

View File

@ -0,0 +1,156 @@
package com.lanhai.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.extension.activerecord.Model;
import java.time.LocalDateTime;
import java.util.Date;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableField;
import java.io.Serializable;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
/**
* <p>
* 车辆信息表
* </p>
*
* @author ${author}
* @since 2026-07-30
*/
@Data
@EqualsAndHashCode(callSuper = false)
@Accessors(chain = true)
public class SurvVehicleInfo extends Model<SurvVehicleInfo> {
private static final long serialVersionUID=1L;
/**
* 主键
*/
@TableId(value = "ID", type = IdType.ID_WORKER_STR)
private String id;
/**
* 车辆备注
*/
@TableField("VE_NOTES")
private String veNotes;
/**
* 驾驶员姓名
*/
@TableField("VE_DRIVER")
private String veDriver;
/**
* 车牌号
*/
@TableField("VE_PLATE")
private String vePlate;
/**
* 车辆类型;1=货车2=卡车3=农机
*/
@TableField("VE_TYPE")
private String veType;
/**
* 品牌
*/
@TableField("VE_BRAND")
private String veBrand;
/**
* 车型
*/
@TableField("VE_MODEL")
private String veModel;
/**
* 联系电话
*/
@TableField("VE_PHONE")
private String vePhone;
/**
* 车辆说明
*/
@TableField("VE_DES")
private String veDes;
/**
* 车辆状态;1=可用0=暂停
*/
@TableField("VE_STATUS")
private Integer veStatus;
/**
* 排序值
*/
@TableField("SORT_NO")
private Integer sortNo;
/**
* GPSid
*/
@TableField("GPS_ID")
private String gpsId;
/**
* 租户号
*/
@TableField("TENANT_ID")
private String tenantId;
/**
* 乐观锁
*/
@TableField("RE_VISION")
private Integer reVision;
/**
* 创建人
*/
@TableField("CREATE_BY")
private String createBy;
/**
* 创建时间
*/
@TableField("CREATE_TIME")
private LocalDateTime createTime;
/**
* 更新人
*/
@TableField("UPDATE_BY")
private String updateBy;
/**
* 逻辑删除
*/
@TableField("IS_DEL")
private Integer isDel;
/**
* 更新时间
*/
@TableField("UPDATE_TIME")
private LocalDateTime updateTime;
/**
* 乐观锁
*/
@TableField("REVISION")
private Integer revision;
@Override
protected Serializable pkVal() {
return this.id;
}
}

View File

@ -0,0 +1,16 @@
package com.lanhai.mapper;
import com.lanhai.entity.SurvGpsInfo;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
/**
* <p>
* gps信息 Mapper 接口
* </p>
*
* @author ${author}
* @since 2026-07-30
*/
public interface SurvGpsInfoMapper extends BaseMapper<SurvGpsInfo> {
}

View File

@ -0,0 +1,16 @@
package com.lanhai.mapper;
import com.lanhai.entity.SurvGpsRecord;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
/**
* <p>
* gsp轨迹记录 Mapper 接口
* </p>
*
* @author ${author}
* @since 2026-07-30
*/
public interface SurvGpsRecordMapper extends BaseMapper<SurvGpsRecord> {
}

View File

@ -0,0 +1,16 @@
package com.lanhai.mapper;
import com.lanhai.entity.SurvVehicleInfo;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
/**
* <p>
* 车辆信息表 Mapper 接口
* </p>
*
* @author ${author}
* @since 2026-07-30
*/
public interface SurvVehicleInfoMapper extends BaseMapper<SurvVehicleInfo> {
}

View File

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.lanhai.mapper.SurvGpsInfoMapper">
</mapper>

View File

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.lanhai.mapper.SurvGpsRecordMapper">
</mapper>

View File

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.lanhai.mapper.SurvVehicleInfoMapper">
</mapper>

View File

@ -0,0 +1,14 @@
package com.lanhai.o.iot.szdx;
import cn.hutool.json.JSONArray;
import lombok.Data;
import java.util.List;
@Data
public class ResultDeviceData {
private ResultDeviceDataKeys key;
private List<List<Object>> records;
private List<String> groups;
}

View File

@ -0,0 +1,42 @@
package com.lanhai.o.iot.szdx;
import lombok.Data;
@Data
public class ResultDeviceDataKeys {
private int sys_time;
private int user_name;
private int jingdu;
private int weidu;
private int ljingdu;
private int lweidu;
private int datetime;
private int heart_time;
private int su;
private int status;
private int hangxiang;
private int sim_id;
private int user_id;
private int sale_type;
private int iconType;
private int server_time;
private int product_type;
private int expire_date;
private int group_id;
private int statenumber;
private int electric;
private int describe;
private int sim;
private int precision;
private int isFollow;
private int plateNumber;
private int auth;
private int authList;
private int deptname;
private int IsShowLocation;
private int tempExt;
private int cardExpire;
private int polygonFence_id;
private int extendedState;
}

View File

@ -0,0 +1,16 @@
package com.lanhai.service;
import com.lanhai.entity.SurvGpsInfo;
import com.baomidou.mybatisplus.extension.service.IService;
/**
* <p>
* gps信息 服务类
* </p>
*
* @author ${author}
* @since 2026-07-30
*/
public interface ISurvGpsInfoService extends IService<SurvGpsInfo> {
}

View File

@ -0,0 +1,16 @@
package com.lanhai.service;
import com.lanhai.entity.SurvGpsRecord;
import com.baomidou.mybatisplus.extension.service.IService;
/**
* <p>
* gsp轨迹记录 服务类
* </p>
*
* @author ${author}
* @since 2026-07-30
*/
public interface ISurvGpsRecordService extends IService<SurvGpsRecord> {
}

View File

@ -0,0 +1,16 @@
package com.lanhai.service;
import com.lanhai.entity.SurvVehicleInfo;
import com.baomidou.mybatisplus.extension.service.IService;
/**
* <p>
* 车辆信息表 服务类
* </p>
*
* @author ${author}
* @since 2026-07-30
*/
public interface ISurvVehicleInfoService extends IService<SurvVehicleInfo> {
}

View File

@ -0,0 +1,20 @@
package com.lanhai.service.Impl;
import com.lanhai.entity.SurvGpsInfo;
import com.lanhai.mapper.SurvGpsInfoMapper;
import com.lanhai.service.ISurvGpsInfoService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.stereotype.Service;
/**
* <p>
* gps信息 服务实现类
* </p>
*
* @author ${author}
* @since 2026-07-30
*/
@Service
public class SurvGpsInfoServiceImpl extends ServiceImpl<SurvGpsInfoMapper, SurvGpsInfo> implements ISurvGpsInfoService {
}

View File

@ -0,0 +1,20 @@
package com.lanhai.service.Impl;
import com.lanhai.entity.SurvGpsRecord;
import com.lanhai.mapper.SurvGpsRecordMapper;
import com.lanhai.service.ISurvGpsRecordService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.stereotype.Service;
/**
* <p>
* gsp轨迹记录 服务实现类
* </p>
*
* @author ${author}
* @since 2026-07-30
*/
@Service
public class SurvGpsRecordServiceImpl extends ServiceImpl<SurvGpsRecordMapper, SurvGpsRecord> implements ISurvGpsRecordService {
}

View File

@ -0,0 +1,20 @@
package com.lanhai.service.Impl;
import com.lanhai.entity.SurvVehicleInfo;
import com.lanhai.mapper.SurvVehicleInfoMapper;
import com.lanhai.service.ISurvVehicleInfoService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.stereotype.Service;
/**
* <p>
* 车辆信息表 服务实现类
* </p>
*
* @author ${author}
* @since 2026-07-30
*/
@Service
public class SurvVehicleInfoServiceImpl extends ServiceImpl<SurvVehicleInfoMapper, SurvVehicleInfo> implements ISurvVehicleInfoService {
}

View File

@ -0,0 +1,79 @@
package com.lanhai.task;
import cn.hutool.json.JSONUtil;
import com.lanhai.constant.IotConstants;
import com.lanhai.constant.PollutionConstants;
import com.lanhai.entity.*;
import com.lanhai.o.iot.task.DataExamineConfig;
import com.lanhai.o.iot.task.DataExamineDetail;
import com.lanhai.service.*;
import com.lanhai.util.SzDxUtils;
import com.xxl.job.core.context.XxlJobHelper;
import com.xxl.job.core.handler.annotation.XxlJob;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
/**
* 数据校验任务
*/
//@Component
@Slf4j
@Component
public class GpsRecordTask {
@Autowired
private ISurvGpsInfoService gpsInfoService;
@XxlJob("GpsRecordTask")
public void TaskHandler() throws Exception{
try{
XxlJobHelper.log("====================GPS记录任务开始====================");
log.warn("====================GPS记录任务开始====================");
List<SurvGpsInfo> gpsInfoList = gpsInfoService
.lambdaQuery()
.eq(SurvGpsInfo::getGpsStatus, 1)
.list();
XxlJobHelper.log("查询到待执行的GpsInfo数量为" + gpsInfoList.size());
log.warn("查询到待执行的GpsInfo数量为" + gpsInfoList.size());
List<String> updIdList = new ArrayList<>();
if(!gpsInfoList.isEmpty()){
for (SurvGpsInfo survGpsInfo : gpsInfoList) {
switch (survGpsInfo.getProtocolCode()){
case IotConstants.PROTOCOL_SZDXGPS:
boolean b = SzDxUtils.processDeviceData(survGpsInfo);
if(b){
updIdList.add(survGpsInfo.getId());
}
break;
}
}
}
XxlJobHelper.log("需要更新的GpsInfo数量为" + updIdList.size());
log.warn("需要更新的GpsInfo数量为" + updIdList.size());
if(!updIdList.isEmpty()){
List<SurvGpsInfo> updGpsInfoList = new ArrayList<>();
LocalDateTime now = LocalDateTime.now();
for (String id : updIdList) {
SurvGpsInfo updGpsInfo = new SurvGpsInfo();
updGpsInfo.setId(id);
updGpsInfo.setLastSyncTime(now);
updGpsInfoList.add(updGpsInfo);
}
gpsInfoService.updateBatchById(updGpsInfoList);
}
} catch (Exception e) {
log.error(e.getMessage());
e.printStackTrace();
} finally {
XxlJobHelper.log("===================GPS记录任务完成=====================");
log.warn("===================GPS记录任务完成=====================");
}
}
}

View File

@ -0,0 +1,266 @@
package com.lanhai.util;
import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson.JSONObject;
import com.lanhai.entity.SurvConfig;
import com.lanhai.entity.SurvDeviceDeploy;
import com.lanhai.o.vo.HttpResponseVo;
import com.lanhai.o.vo.VOIotAccess;
import com.lanhai.service.ISurvSurvConfigService;
import com.xxl.job.core.context.XxlJobHelper;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeParseException;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
/**
* IoT厂家工具类模板
* <p>
* 使用方式复制此类改类名改下面4个常量按需修改各方法
*/
@Slf4j
public class PlainIotUtils {
// ==================== 改这里 ====================
private static final String PROVIDER_CODE = "xxx";
private static final String PROVIDER_NAME = "XXX厂家";
private static final String ACCESS_CODE = "XXX_ACCESS";
private static final String DOMAIN = "https://api.xxx.com";
// ==================== 常量 ====================
private static final String TOKEN_KEY_PREFIX = "iot:token:";
private static final String TOKEN_EXPIRE_PREFIX = "iot:token:expire:";
private static final DateTimeFormatter FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
private static final RedisTemplate<String, String> redisTemplate = SpringContextUtil.getBean(StringRedisTemplate.class);
private static final ISurvSurvConfigService configService = SpringContextUtil.getBean(ISurvSurvConfigService.class);
// ============================================================
// 公开方法
// ============================================================
/**
* 获取Token对外入口含缓存逻辑
*
* @param deploy 设备部署信息
* @return Token
*/
public String getToken(SurvDeviceDeploy deploy) {
VOIotAccess access = getAccess(deploy);
if (access == null) {
log.warn("{}: 设备{}密钥未配置", PROVIDER_NAME, deploy.getId());
return null;
}
// 1. 查缓存
String token = getAppToken(PROVIDER_CODE, access.getAppId());
if (StringUtils.isNotBlank(token)) {
return token;
}
// 2. 缓存失效远程获取
log.warn("{}: 缓存失效重新获取Token", PROVIDER_NAME);
token = fetchToken(access);
if (StringUtils.isNotBlank(token)) {
return token;
}
log.error("{}: Token获取最终失败", PROVIDER_NAME);
return null;
}
/**
* 获取设备实时数据
*/
public JSONObject getDeviceData(SurvDeviceDeploy deploy) {
String token = getToken(deploy);
if (StringUtils.isBlank(token)) {
log.warn("{}: 设备{}获取Token失败", PROVIDER_NAME, deploy.getId());
return null;
}
String url = DOMAIN + "/api/device/data";
Map<String, String> headers = new HashMap<>();
headers.put("Authorization", token);
Map<String, Object> params = new HashMap<>();
params.put("deviceAddrs", deploy.getDeployCode());
params.put("rc", UUID.randomUUID().toString().replace("-", ""));
String result = HttpReqestUtils.getExchangeImgs(url, params, headers);
XxlJobHelper.log("========= {} 实时数据返回: {} =========", PROVIDER_NAME, result);
log.info("{} 实时数据返回: {}", PROVIDER_NAME, result);
if (StringUtils.isNotBlank(result)) {
return JSONUtil.toBean(result, JSONObject.class);
}
return null;
}
// ============================================================
// 缓存方法可复用
// ============================================================
/**
* 从缓存获取Token
*
* @param providerCode 厂家代号
* @param appKey 应用AppKey
* @return Token不存在或已过期返回null
*/
public static String getAppToken(String providerCode, String appKey) {
if (StringUtils.isAnyBlank(providerCode, appKey)) {
return null;
}
String tokenKey = TOKEN_KEY_PREFIX + providerCode + ":" + appKey;
String expireKey = TOKEN_EXPIRE_PREFIX + providerCode + ":" + appKey;
// 检查key是否存在
if (Boolean.FALSE.equals(redisTemplate.hasKey(tokenKey))) {
return null;
}
String token = CommonToolUtils.getString(redisTemplate.opsForValue().get(tokenKey), "");
String expireTimeStr = CommonToolUtils.getString(redisTemplate.opsForValue().get(expireKey), "");
if (StringUtils.isAnyBlank(token, expireTimeStr)) {
return null;
}
// 检查是否过期
try {
LocalDateTime expireTime = LocalDateTime.parse(expireTimeStr, FORMATTER);
if (LocalDateTime.now().isBefore(expireTime)) {
log.debug("{}: 命中缓存Token", providerCode);
return token;
}
} catch (DateTimeParseException e) {
log.warn("Token过期时间解析失败: providerCode={}, expireTimeStr={}", providerCode, expireTimeStr, e);
}
return null;
}
/**
* 缓存Token
*
* @param providerCode 厂家代号
* @param appKey 应用AppKey
* @param token Token值
* @param expireTime 过期时间格式yyyy-MM-dd HH:mm:ss
* @return 是否成功
*/
public static boolean setAppToken(String providerCode, String appKey, String token, String expireTime) {
if (StringUtils.isAnyBlank(providerCode, appKey, token, expireTime)) {
log.warn("setAppToken参数不完整");
return false;
}
String tokenKey = TOKEN_KEY_PREFIX + providerCode + ":" + appKey;
String expireKey = TOKEN_EXPIRE_PREFIX + providerCode + ":" + appKey;
redisTemplate.opsForValue().set(tokenKey, token);
redisTemplate.opsForValue().set(expireKey, expireTime);
log.info("Token缓存成功: providerCode={}, appKey={}, expireTime={}", providerCode, appKey, expireTime);
return true;
}
// ============================================================
// 私有方法
// ============================================================
/**
* 获取应用凭证
*/
private VOIotAccess getAccess(SurvDeviceDeploy deploy) {
if (deploy == null) {
log.warn("getAccess: deploy为null");
return null;
}
SurvConfig config = null;
// 优先使用设备绑定的配置
if (StringUtils.isNotBlank(deploy.getSurvConfigId())) {
config = configService.getConfigById(deploy.getSurvConfigId());
} else {
// 否则按租户+对接识别码查询
config = configService.getOneByTypeWithTenant(deploy.getTenantId(), ACCESS_CODE);
}
if (config == null) {
log.warn("未找到配置: tenantId={}, configId={}, accessCode={}",
deploy.getTenantId(), deploy.getSurvConfigId(), ACCESS_CODE);
return null;
}
VOIotAccess access = new VOIotAccess();
access.setAppId(config.getConfigKey());
access.setAppSecret(config.getConfigValue());
return access;
}
/**
* 远程获取Token并缓存
*/
private String fetchToken(VOIotAccess access) {
if (access == null || StringUtils.isAnyBlank(access.getAppId(), access.getAppSecret())) {
log.warn("fetchToken: 凭证不完整");
return null;
}
String url = DOMAIN + "/api/getToken";
Map<String, Object> params = new HashMap<>();
params.put("loginName", access.getAppId());
params.put("password", access.getAppSecret());
HttpResponseVo response = HttpReqestUtils.getExchange(url, params, new HashMap<>());
if (!response.isOk()) {
log.error("{} Token请求失败: httpCode", PROVIDER_NAME);
return null;
}
JSONObject respJson = response.getData();
if (respJson == null) {
log.error("{} Token响应为空", PROVIDER_NAME);
return null;
}
JSONObject data = respJson.getJSONObject("data");
if (data == null) {
log.error("{} Token响应data为空, response={}", PROVIDER_NAME, respJson);
return null;
}
String token = data.getString("token");
Long expireSeconds = data.getLong("expiration");
if (StringUtils.isBlank(token)) {
log.error("{} Token获取失败: {}", PROVIDER_NAME, respJson.getString("msg"));
return null;
}
if (expireSeconds == null || expireSeconds <= 0) {
log.warn("{} Token过期时间为空或无效使用默认2小时", PROVIDER_NAME);
expireSeconds = 7200L;
}
// 缓存Token
String expireTimeStr = LocalDateTime.now().plusSeconds(expireSeconds).format(FORMATTER);
setAppToken(PROVIDER_CODE, access.getAppId(), token, expireTimeStr);
return token;
}
}

View File

@ -0,0 +1,327 @@
package com.lanhai.util;
import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson.JSONObject;
import com.lanhai.entity.SurvConfig;
import com.lanhai.entity.SurvDeviceDeploy;
import com.lanhai.entity.SurvGpsInfo;
import com.lanhai.entity.SurvGpsRecord;
import com.lanhai.o.iot.szdx.ResultDeviceData;
import com.lanhai.o.iot.szdx.ResultDeviceDataKeys;
import com.lanhai.o.vo.HttpResponseVo;
import com.lanhai.o.vo.VOIotAccess;
import com.lanhai.service.ISurvGpsRecordService;
import com.lanhai.service.ISurvSurvConfigService;
import com.xxl.job.core.context.XxlJobHelper;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import java.lang.reflect.Field;
import java.nio.charset.StandardCharsets;
import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeParseException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;
/**
* IoT厂家工具类模板
* <p>
* 使用方式复制此类改类名改下面4个常量按需修改各方法
*/
@Slf4j
public class SzDxUtils {
// ==================== 改这里 ====================
private static final String PROVIDER_CODE = "DiXinSoft";
private static final String PROVIDER_NAME = "深圳帝馨";
private static final String ACCESS_CODE = "dxsoft_access";
private static final String DOMAIN = "http://api.18gps.net/GetDateServices.asmx";
// ==================== 常量 ====================
private static final String TOKEN_KEY_PREFIX = "iot:token:";
private static final String TOKEN_EXPIRE_PREFIX = "iot:token:expire:";
private static final DateTimeFormatter FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
private static final RedisTemplate<String, String> redisTemplate = SpringContextUtil.getBean(StringRedisTemplate.class);
private static final ISurvSurvConfigService configService = SpringContextUtil.getBean(ISurvSurvConfigService.class);
private static final ISurvGpsRecordService gpsRecordService = SpringContextUtil.getBean(ISurvGpsRecordService.class);
// ============================================================
// 公开方法
// ============================================================
/**
* 获取Token对外入口含缓存逻辑
*
* @param gpsInfo 设备部署信息
* @return Token
*/
public static String getToken(SurvGpsInfo gpsInfo) {
VOIotAccess access = getAccess(gpsInfo);
if (access == null) {
log.warn("{}: 设备{}密钥未配置", PROVIDER_NAME, gpsInfo.getId());
return null;
}
// 1. 查缓存
String token = getAppToken(PROVIDER_CODE, access.getAppId());
if (StringUtils.isNotBlank(token)) {
return token;
}
// 2. 缓存失效远程获取
log.warn("{}: 缓存失效重新获取Token", PROVIDER_NAME);
token = fetchToken(access);
if (StringUtils.isNotBlank(token)) {
return token;
}
log.error("{}: Token获取最终失败", PROVIDER_NAME);
return null;
}
/**
* 获取设备实时数据
*/
public static ResultDeviceData getDeviceData(SurvGpsInfo gpsInfo) {
String token = getToken(gpsInfo);
if (StringUtils.isBlank(token)) {
log.warn("{}: 设备{}获取Token失败", PROVIDER_NAME, gpsInfo.getId());
return null;
}
String url = DOMAIN + "/GetDate?mapType=GAODE&mds={mds}&method=getUserAndGpsInfoByIDsUtc&option=cn&user_id={user_id}";
Map<String, String> headers = new HashMap<>();
Map<String, Object> params = new HashMap<>();
params.put("mds", token);
params.put("user_id", gpsInfo.getGpsDeviceId());
String result = HttpReqestUtils.getExchangeImgs(url, params, headers);
//转utf-8编码
result = new String(
result.getBytes(StandardCharsets.ISO_8859_1),
StandardCharsets.UTF_8
);
XxlJobHelper.log("========= {} 实时数据返回: {} =========", PROVIDER_NAME, result);
log.info("{} 实时数据返回: {}", PROVIDER_NAME, result);
if (StringUtils.isNotBlank(result)) {
return JSONUtil.toBean(result, ResultDeviceData.class);
}
return null;
}
// ============================================================
// 缓存方法可复用
// ============================================================
/**
* 从缓存获取Token
*
* @param providerCode 厂家代号
* @param appKey 应用AppKey
* @return Token不存在或已过期返回null
*/
public static String getAppToken(String providerCode, String appKey) {
if (StringUtils.isAnyBlank(providerCode, appKey)) {
return null;
}
String tokenKey = TOKEN_KEY_PREFIX + providerCode + ":" + appKey;
String expireKey = TOKEN_EXPIRE_PREFIX + providerCode + ":" + appKey;
// 检查key是否存在
if (Boolean.FALSE.equals(redisTemplate.hasKey(tokenKey))) {
return null;
}
String token = CommonToolUtils.getString(redisTemplate.opsForValue().get(tokenKey), "");
String expireTimeStr = CommonToolUtils.getString(redisTemplate.opsForValue().get(expireKey), "");
if (StringUtils.isAnyBlank(token, expireTimeStr)) {
return null;
}
// 检查是否过期
try {
LocalDateTime expireTime = LocalDateTime.parse(expireTimeStr, FORMATTER);
if (LocalDateTime.now().isBefore(expireTime)) {
log.debug("{}: 命中缓存Token", providerCode);
return token;
}
} catch (DateTimeParseException e) {
log.warn("Token过期时间解析失败: providerCode={}, expireTimeStr={}", providerCode, expireTimeStr, e);
}
return null;
}
/**
* 缓存Token
*
* @param providerCode 厂家代号
* @param appKey 应用AppKey
* @param token Token值
* @param expireTime 过期时间格式yyyy-MM-dd HH:mm:ss
* @return 是否成功
*/
public static boolean setAppToken(String providerCode, String appKey, String token, String expireTime) {
if (StringUtils.isAnyBlank(providerCode, appKey, token, expireTime)) {
log.warn("setAppToken参数不完整");
return false;
}
String tokenKey = TOKEN_KEY_PREFIX + providerCode + ":" + appKey;
String expireKey = TOKEN_EXPIRE_PREFIX + providerCode + ":" + appKey;
redisTemplate.opsForValue().set(tokenKey, token);
redisTemplate.opsForValue().set(expireKey, expireTime);
log.info("Token缓存成功: providerCode={}, appKey={}, expireTime={}", providerCode, appKey, expireTime);
return true;
}
// ============================================================
// 私有方法
// ============================================================
/**
* 获取应用凭证
*/
private static VOIotAccess getAccess(SurvGpsInfo gpsInfo) {
if (gpsInfo == null) {
log.warn("getAccess: gpsInfo为null");
return null;
}
SurvConfig config = null;
// 优先使用设备绑定的配置
config = configService.getConfigById(gpsInfo.getSurvConfigId());
if (config == null) {
log.warn("未找到配置: tenantId={}, configId={}, accessCode={}",
gpsInfo.getTenantId(), gpsInfo.getSurvConfigId(), ACCESS_CODE);
return null;
}
VOIotAccess access = new VOIotAccess();
access.setAppId(config.getConfigKey());
access.setAppSecret(config.getConfigValue());
return access;
}
/**
* 远程获取Token并缓存
*/
private static String fetchToken(VOIotAccess access) {
if (access == null || StringUtils.isAnyBlank(access.getAppId(), access.getAppSecret())) {
log.warn("fetchToken: 凭证不完整");
return null;
}
String url = DOMAIN + "/loginSystem?LoginName={loginName}&LoginPassword={password}&LoginType=ENTERPRISE&language=cn&timeZone=+08&apply=APP";
Map<String, Object> params = new HashMap<>();
params.put("loginName", access.getAppId());
params.put("password", access.getAppSecret());
String response = HttpReqestUtils.getExchangeImgs(url, params, new HashMap<>());
if (StringUtils.isBlank(response)) {
log.error("{} Token响应为空", PROVIDER_NAME);
return null;
}
JSONObject respJson = JSONObject.parseObject(response);
String token = respJson.getString("mds");
Long expireSeconds = 20 * 60L;//20分钟有效期
if (StringUtils.isBlank(token)) {
log.error("{} Token获取失败: {}", PROVIDER_NAME, respJson.getString("msg"));
return null;
}
if (expireSeconds == null || expireSeconds <= 0) {
log.warn("{} Token过期时间为空或无效使用默认20分钟", PROVIDER_NAME);
expireSeconds = 20 * 60L;
}
// 缓存Token
String expireTimeStr = LocalDateTime.now().plusSeconds(expireSeconds).format(FORMATTER);
setAppToken(PROVIDER_CODE, access.getAppId(), token, expireTimeStr);
return token;
}
public static boolean processDeviceData(SurvGpsInfo survGpsInfo){
boolean isSuccess = false;
if(survGpsInfo != null){
ResultDeviceData resultDeviceData = getDeviceData(survGpsInfo);
if(resultDeviceData != null){
if(resultDeviceData.getRecords()!=null){
Field[] fields = ResultDeviceDataKeys.class.getDeclaredFields();
List<Object> record = resultDeviceData.getRecords().get(0);
SurvGpsRecord gpsRecord = new SurvGpsRecord();
gpsRecord.setGpsDeviceId(survGpsInfo.getGpsDeviceId());
gpsRecord.setGpsId(survGpsInfo.getId());
gpsRecord.setGpsCode(survGpsInfo.getGpsCode());
gpsRecord.setGpsIdent(survGpsInfo.getGpsIdent());
gpsRecord.setTenantId(survGpsInfo.getTenantId());
for (Field field : fields) {
field.setAccessible(true);
String fieldName = field.getName();
try{
Object keyNum = field.get(resultDeviceData.getKey());
int keyNumInt = Integer.parseInt(keyNum.toString());
Object value = record.get(keyNumInt);
log.error("{}-获取值:{}",fieldName,value);
XxlJobHelper.log("{}-获取值:{}",fieldName,value);
String strVal = String.valueOf(value);
if(fieldName.equals("sys_time")){//数据采集时间
LocalDateTime sysTime = Instant.ofEpochMilli(Long.parseLong(strVal)).atZone(ZoneId.systemDefault()).toLocalDateTime();
gpsRecord.setDataDateTime(sysTime);
gpsRecord.setDataId(gpsRecord.getGpsCode()+"_"+strVal);
}
TUtil.setFieldValue(gpsRecord, fieldName, strVal);
}catch ( Exception e) {
}
}
if(gpsRecord.getDataId()!=null){
int checks = gpsRecordService.lambdaQuery()
.eq(SurvGpsRecord::getDataId,gpsRecord.getDataId())
.count();
if(checks==0){
gpsRecordService.save(gpsRecord);
isSuccess = true;
}else{
log.error("==={}===设备:{}-{}==gps数据校验重复数据id为{}====",PROVIDER_NAME,survGpsInfo.getGpsName(),survGpsInfo.getGpsCode(),gpsRecord.getDataId());
XxlJobHelper.log("==={}===设备:{}-{}==gps数据校验重复数据id为{}====",PROVIDER_NAME,survGpsInfo.getGpsName(),survGpsInfo.getGpsCode(),gpsRecord.getDataId());
}
}else{
log.error("==={}===设备:{}-{}==gps数据构造失败数据id为空====",PROVIDER_NAME,survGpsInfo.getGpsName(),survGpsInfo.getGpsCode());
XxlJobHelper.log("==={}===设备:{}-{}==gps数据构造失败数据id为空====",PROVIDER_NAME,survGpsInfo.getGpsName(),survGpsInfo.getGpsCode());
}
}
}
}
return isSuccess;
}
}

View File

@ -38,18 +38,18 @@ spring:
pathmatch: pathmatch:
matching-strategy: ant_path_matcher #解决springboot高版本和swagger的集成问题 matching-strategy: ant_path_matcher #解决springboot高版本和swagger的集成问题
# redis: redis:
# port: 6379 port: 6379
# host: 49.233.25.219 host: 127.0.0.1
# database: 10 database: 8
# password: zfs_123! password: 123456
# jedis: jedis:
# pool: pool:
# min-idle: 0 min-idle: 0
# max-idle: 10 max-idle: 10
# max-wait: -1 max-wait: -1
# max-active: 20 max-active: 20
# timeout: 1000 timeout: 1000
mybatis-plus: mybatis-plus:
@ -66,18 +66,18 @@ logging:
xxl: xxl:
job: job:
accessToken: lhzn.20241215 accessToken: lhzn.20251111
admin: admin:
addresses: http://192.168.0.4:10003/xxl-job-admin addresses: http://192.168.2.110:10003/xxl-job-admin
executor: executor:
appname: jngjTask appname: fxTask
address: address:
ip: ip:
port: 10004 port: 10004
logpath: /logs/xxl-job/jobhandler logpath: /logs/xxl-job/jobhandler
logretentiondays: 30 logretentiondays: 30
mqtt: mqtt:
enabled: true enabled: false
# 指定默认客户端名称(可选) # 指定默认客户端名称(可选)
default-client: broker1 default-client: broker1
# 多客户端配置 # 多客户端配置

View File

@ -1,5 +1,5 @@
spring: spring:
profiles: profiles:
active: prod # active: local #