1、*-global.yml配置文件中增加有关萤石云应用的配置;
2、萤石云视频监控相关数据库设计(萤石应用+视频监控站);
3、remote模块增加定时下载萤石应用AccessToken的监听器,及网络下载逻辑,数据库存储等功能实现;
| | |
| | | SchedulerTaskSupport.threadPoolPriority = threadPoolPriority; |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * 删除工作任务 |
| | | * @param jobName |
| | | * @param jobGroupName |
| | | * @throws SchedulerException |
| | | */ |
| | | public static void deleteJob(String jobName, String jobGroupName) throws SchedulerException{ |
| | | Scheduler sched = SchedulerTaskFactory.getSingleScheduler() ; |
| | | sched.deleteJob(new JobKey(jobName, jobGroupName)); |
| | | } |
| | | |
| | | /** |
| | | * 添加每X秒钟重复工作一次的工作任务, |
| | |
| | | .withIntervalInSeconds(intervalInSeconds) |
| | | .withRepeatCount(repeatCount)) |
| | | .build(); |
| | | |
| | | sched.scheduleJob(job, trigger); |
| | | sched.start(); |
| | | |
New file |
| | |
| | | package com.dy.pipIrrGlobal.daoVi; |
| | | |
| | | import com.baomidou.mybatisplus.core.mapper.BaseMapper; |
| | | import com.dy.pipIrrGlobal.pojoVi.ViYsApp; |
| | | import org.apache.ibatis.annotations.Mapper; |
| | | |
| | | import java.util.List; |
| | | |
| | | /** |
| | | * @Author: liurunyu |
| | | * @Date: 2025/6/7 10:44 |
| | | * @Description |
| | | */ |
| | | @Mapper |
| | | public interface ViYsAppMapper extends BaseMapper<ViYsApp> { |
| | | int deleteByPrimaryKey(Long id); |
| | | |
| | | int deleteAll(); |
| | | |
| | | int insert(ViYsApp record); |
| | | |
| | | int insertSelective(ViYsApp record); |
| | | |
| | | ViYsApp selectByPrimaryKey(Long id); |
| | | |
| | | List<ViYsApp> selectAll(); |
| | | |
| | | int updateByPrimaryKeySelective(ViYsApp record); |
| | | |
| | | int updateByPrimaryKey(ViYsApp record); |
| | | } |
New file |
| | |
| | | package com.dy.pipIrrGlobal.daoVi; |
| | | |
| | | import com.baomidou.mybatisplus.core.mapper.BaseMapper; |
| | | import com.dy.pipIrrGlobal.pojoVi.ViYsCamera; |
| | | import org.apache.ibatis.annotations.Mapper; |
| | | |
| | | /** |
| | | * @Author: liurunyu |
| | | * @Date: 2025/6/7 16:00 |
| | | * @Description |
| | | */ |
| | | @Mapper |
| | | public interface ViYsCameraMapper extends BaseMapper<ViYsCamera> { |
| | | int deleteByPrimaryKey(Long id); |
| | | |
| | | int insert(ViYsCamera record); |
| | | |
| | | int insertSelective(ViYsCamera record); |
| | | |
| | | ViYsCamera selectByPrimaryKey(Long id); |
| | | |
| | | int updateByPrimaryKeySelective(ViYsCamera record); |
| | | |
| | | int updateByPrimaryKey(ViYsCamera record); |
| | | } |
New file |
| | |
| | | package com.dy.pipIrrGlobal.pojoVi; |
| | | |
| | | import com.alibaba.fastjson2.annotation.JSONField; |
| | | import com.alibaba.fastjson2.writer.ObjectWriterImplToString; |
| | | import com.baomidou.mybatisplus.annotation.IdType; |
| | | import com.baomidou.mybatisplus.annotation.TableId; |
| | | import com.baomidou.mybatisplus.annotation.TableName; |
| | | import com.dy.common.po.BaseEntity; |
| | | import io.swagger.v3.oas.annotations.media.Schema; |
| | | import lombok.*; |
| | | |
| | | import java.util.Date; |
| | | |
| | | /** |
| | | * @Author: liurunyu |
| | | * @Date: 2025/6/7 10:44 |
| | | * @Description |
| | | */ |
| | | |
| | | /** |
| | | * 萤石云应用App相关 |
| | | */ |
| | | @TableName(value="vi_ys_app", autoResultMap = true) |
| | | @Data |
| | | @Builder |
| | | @ToString |
| | | @NoArgsConstructor |
| | | @AllArgsConstructor |
| | | @Schema(name = "萤石云应用App") |
| | | public class ViYsApp implements BaseEntity { |
| | | |
| | | public static final long serialVersionUID = 202506071603001L; |
| | | |
| | | /** |
| | | * 主键 |
| | | */ |
| | | @Schema(description = "主键", requiredMode = Schema.RequiredMode.REQUIRED) |
| | | @JSONField(serializeUsing= ObjectWriterImplToString.class) |
| | | @TableId(type = IdType.INPUT) |
| | | public Long id; |
| | | |
| | | /** |
| | | * 萤石云的AccessToken |
| | | */ |
| | | @Schema(description = "萤石云开放平台应用AccessToken", requiredMode = Schema.RequiredMode.NOT_REQUIRED) |
| | | public String accessToken; |
| | | |
| | | /** |
| | | * AccessToken过期时间 |
| | | */ |
| | | @Schema(description = "AccessToken过期时间(毫秒)", requiredMode = Schema.RequiredMode.NOT_REQUIRED) |
| | | public Long expireTime; |
| | | |
| | | /** |
| | | * AccessToken过期时间 |
| | | */ |
| | | @Schema(description = "AccessToken过期时间(年月日时分秒)", requiredMode = Schema.RequiredMode.NOT_REQUIRED) |
| | | public Date expireDt; |
| | | |
| | | } |
New file |
| | |
| | | package com.dy.pipIrrGlobal.pojoVi; |
| | | |
| | | import com.alibaba.fastjson2.annotation.JSONField; |
| | | import com.alibaba.fastjson2.writer.ObjectWriterImplToString; |
| | | import com.baomidou.mybatisplus.annotation.IdType; |
| | | import com.baomidou.mybatisplus.annotation.TableId; |
| | | import com.baomidou.mybatisplus.annotation.TableName; |
| | | import com.dy.common.po.BaseEntity; |
| | | import io.swagger.v3.oas.annotations.media.Schema; |
| | | import lombok.*; |
| | | |
| | | /** |
| | | * @Author: liurunyu |
| | | * @Date: 2025/6/7 16:00 |
| | | * @Description |
| | | */ |
| | | /** |
| | | * 萤石摄像机(视频站) |
| | | */ |
| | | |
| | | @TableName(value="vi_ys_camera", autoResultMap = true) |
| | | @Data |
| | | @Builder |
| | | @ToString |
| | | @NoArgsConstructor |
| | | @AllArgsConstructor |
| | | @Schema(name = "视频监控摄像机") |
| | | public class ViYsCamera implements BaseEntity { |
| | | |
| | | public static final long serialVersionUID = 202506071604001L; |
| | | |
| | | /** |
| | | * 主键 |
| | | */ |
| | | @Schema(description = "主键", requiredMode = Schema.RequiredMode.REQUIRED) |
| | | @JSONField(serializeUsing= ObjectWriterImplToString.class) |
| | | @TableId(type = IdType.INPUT) |
| | | public Long id; |
| | | |
| | | /** |
| | | * 摄像机序列号 |
| | | */ |
| | | @Schema(description = "摄像机序列号", requiredMode = Schema.RequiredMode.NOT_REQUIRED) |
| | | public String devNo; |
| | | |
| | | /** |
| | | * 视频站名称 |
| | | */ |
| | | @Schema(description = "视频站名称", requiredMode = Schema.RequiredMode.NOT_REQUIRED) |
| | | public String name; |
| | | |
| | | /** |
| | | * 经度 |
| | | */ |
| | | @Schema(description = "视频站经度", requiredMode = Schema.RequiredMode.NOT_REQUIRED) |
| | | public Double lng; |
| | | |
| | | /** |
| | | * 纬度 |
| | | */ |
| | | @Schema(description = "视频站纬度", requiredMode = Schema.RequiredMode.NOT_REQUIRED) |
| | | public Double lat; |
| | | |
| | | /** |
| | | * 备注 |
| | | */ |
| | | @Schema(description = "备注信息", requiredMode = Schema.RequiredMode.NOT_REQUIRED) |
| | | public String remark; |
| | | |
| | | } |
| | |
| | | public abstract class OrgListenerSupport { |
| | | |
| | | /** |
| | | * 实始化 |
| | | * 初始化 |
| | | */ |
| | | @SuppressWarnings("unused ") |
| | | protected void init(ResourceLoader resourceLoader) { |
| | | this.doInit(resourceLoader); |
| | | } |
| | | /** |
| | | * 实始化 |
| | | * 初始化 |
| | | */ |
| | | @SuppressWarnings("unused ") |
| | | protected void doInit(ResourceLoader resourceLoader) { |
| | |
| | | // 得到 |
| | | //////////////////////////////// |
| | | /** |
| | | * 实始化 |
| | | * 初始化 |
| | | */ |
| | | @SuppressWarnings("unused ") |
| | | protected List<Org.OrgVo> get(ResourceLoader resourceLoader) { |
| | |
| | | } |
| | | |
| | | /** |
| | | * 实始化 |
| | | * 初始化 |
| | | */ |
| | | @SuppressWarnings("unused ") |
| | | protected List<Org.OrgVo> doGet(ResourceLoader resourceLoader) { |
| | |
| | | at-all: true |
| | | mobile: 18602657034 |
| | | |
| | | #萤石云开放平台 |
| | | ys: |
| | | accessTokenExpireDay: 7 #AccessToken过期时间,单位天 |
| | | appKey: 93987fd687444c23b427181a108f5253 |
| | | secret: d73a08e4fb3c3d9d0b696630eea8bd4e |
| | | requestAccessTokenUrl: https://open.ys7.com/api/lapp/token/get |
| | | requestVideoCommonUrl: https://open.ys7.com/console/jssdk/pc.html |
| | | requestVideoCameraPreUrl: ezopen://open.ys7.com/ |
| | | requestVideoCameraTailUrl: /1.live&themeId= |
| | | |
| | | #阀控器参数 |
| | | rtu: |
| | | signalIntensity: |
New file |
| | |
| | | <?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.dy.pipIrrGlobal.daoVi.ViYsAppMapper"> |
| | | <resultMap id="BaseResultMap" type="com.dy.pipIrrGlobal.pojoVi.ViYsApp"> |
| | | <!--@mbg.generated--> |
| | | <!--@Table vi_ys_app--> |
| | | <id column="id" jdbcType="BIGINT" property="id" /> |
| | | <result column="access_token" jdbcType="VARCHAR" property="accessToken" /> |
| | | <result column="expire_time" jdbcType="BIGINT" property="expireTime" /> |
| | | <result column="expire_dt" jdbcType="TIMESTAMP" property="expireDt" /> |
| | | </resultMap> |
| | | <sql id="Base_Column_List"> |
| | | <!--@mbg.generated--> |
| | | id, access_token, expire_time, expire_dt |
| | | </sql> |
| | | <select id="selectByPrimaryKey" parameterType="java.lang.Long" resultMap="BaseResultMap"> |
| | | <!--@mbg.generated--> |
| | | select |
| | | <include refid="Base_Column_List" /> |
| | | from vi_ys_app |
| | | where id = #{id,jdbcType=BIGINT} |
| | | </select> |
| | | <select id="selectAll" resultMap="BaseResultMap"> |
| | | <!--@mbg.generated--> |
| | | select |
| | | <include refid="Base_Column_List" /> |
| | | from vi_ys_app |
| | | </select> |
| | | <delete id="deleteByPrimaryKey" parameterType="java.lang.Long"> |
| | | <!--@mbg.generated--> |
| | | delete from vi_ys_app |
| | | where id = #{id,jdbcType=BIGINT} |
| | | </delete> |
| | | <delete id="deleteAll" > |
| | | <!--@mbg.generated--> |
| | | delete from vi_ys_app |
| | | </delete> |
| | | <insert id="insert" parameterType="com.dy.pipIrrGlobal.pojoVi.ViYsApp"> |
| | | <!--@mbg.generated--> |
| | | insert into vi_ys_app (id, access_token, expire_time, |
| | | expire_dt) |
| | | values (#{id,jdbcType=BIGINT}, #{accessToken,jdbcType=VARCHAR}, #{expireTime,jdbcType=BIGINT}, |
| | | #{expireDt,jdbcType=TIMESTAMP}) |
| | | </insert> |
| | | <insert id="insertSelective" parameterType="com.dy.pipIrrGlobal.pojoVi.ViYsApp"> |
| | | <!--@mbg.generated--> |
| | | insert into vi_ys_app |
| | | <trim prefix="(" suffix=")" suffixOverrides=","> |
| | | <if test="id != null"> |
| | | id, |
| | | </if> |
| | | <if test="accessToken != null"> |
| | | access_token, |
| | | </if> |
| | | <if test="expireTime != null"> |
| | | expire_time, |
| | | </if> |
| | | <if test="expireDt != null"> |
| | | expire_dt, |
| | | </if> |
| | | </trim> |
| | | <trim prefix="values (" suffix=")" suffixOverrides=","> |
| | | <if test="id != null"> |
| | | #{id,jdbcType=BIGINT}, |
| | | </if> |
| | | <if test="accessToken != null"> |
| | | #{accessToken,jdbcType=VARCHAR}, |
| | | </if> |
| | | <if test="expireTime != null"> |
| | | #{expireTime,jdbcType=BIGINT}, |
| | | </if> |
| | | <if test="expireDt != null"> |
| | | #{expireDt,jdbcType=TIMESTAMP}, |
| | | </if> |
| | | </trim> |
| | | </insert> |
| | | <update id="updateByPrimaryKeySelective" parameterType="com.dy.pipIrrGlobal.pojoVi.ViYsApp"> |
| | | <!--@mbg.generated--> |
| | | update vi_ys_app |
| | | <set> |
| | | <if test="accessToken != null"> |
| | | access_token = #{accessToken,jdbcType=VARCHAR}, |
| | | </if> |
| | | <if test="expireTime != null"> |
| | | expire_time = #{expireTime,jdbcType=BIGINT}, |
| | | </if> |
| | | <if test="expireDt != null"> |
| | | expire_dt = #{expireDt,jdbcType=TIMESTAMP}, |
| | | </if> |
| | | </set> |
| | | where id = #{id,jdbcType=BIGINT} |
| | | </update> |
| | | <update id="updateByPrimaryKey" parameterType="com.dy.pipIrrGlobal.pojoVi.ViYsApp"> |
| | | <!--@mbg.generated--> |
| | | update vi_ys_app |
| | | set access_token = #{accessToken,jdbcType=VARCHAR}, |
| | | expire_time = #{expireTime,jdbcType=BIGINT}, |
| | | expire_dt = #{expireDt,jdbcType=TIMESTAMP} |
| | | where id = #{id,jdbcType=BIGINT} |
| | | </update> |
| | | </mapper> |
New file |
| | |
| | | <?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.dy.pipIrrGlobal.daoVi.ViYsCameraMapper"> |
| | | <resultMap id="BaseResultMap" type="com.dy.pipIrrGlobal.pojoVi.ViYsCamera"> |
| | | <!--@mbg.generated--> |
| | | <!--@Table vi_ys_camera--> |
| | | <id column="id" jdbcType="BIGINT" property="id" /> |
| | | <result column="dev_no" jdbcType="VARCHAR" property="devNo" /> |
| | | <result column="name" jdbcType="VARCHAR" property="name" /> |
| | | <result column="lng" jdbcType="DOUBLE" property="lng" /> |
| | | <result column="lat" jdbcType="DOUBLE" property="lat" /> |
| | | <result column="remark" jdbcType="VARCHAR" property="remark" /> |
| | | </resultMap> |
| | | <sql id="Base_Column_List"> |
| | | <!--@mbg.generated--> |
| | | id, dev_no, `name`, lng, lat, remark |
| | | </sql> |
| | | <select id="selectByPrimaryKey" parameterType="java.lang.Long" resultMap="BaseResultMap"> |
| | | <!--@mbg.generated--> |
| | | select |
| | | <include refid="Base_Column_List" /> |
| | | from vi_ys_camera |
| | | where id = #{id,jdbcType=BIGINT} |
| | | </select> |
| | | <delete id="deleteByPrimaryKey" parameterType="java.lang.Long"> |
| | | <!--@mbg.generated--> |
| | | delete from vi_ys_camera |
| | | where id = #{id,jdbcType=BIGINT} |
| | | </delete> |
| | | <insert id="insert" parameterType="com.dy.pipIrrGlobal.pojoVi.ViYsCamera"> |
| | | <!--@mbg.generated--> |
| | | insert into vi_ys_camera (id, dev_no, `name`, |
| | | lng, lat, remark) |
| | | values (#{id,jdbcType=BIGINT}, #{devNo,jdbcType=VARCHAR}, #{name,jdbcType=VARCHAR}, |
| | | #{lng,jdbcType=DOUBLE}, #{lat,jdbcType=DOUBLE}, #{remark,jdbcType=VARCHAR}) |
| | | </insert> |
| | | <insert id="insertSelective" parameterType="com.dy.pipIrrGlobal.pojoVi.ViYsCamera"> |
| | | <!--@mbg.generated--> |
| | | insert into vi_ys_camera |
| | | <trim prefix="(" suffix=")" suffixOverrides=","> |
| | | <if test="id != null"> |
| | | id, |
| | | </if> |
| | | <if test="devNo != null"> |
| | | dev_no, |
| | | </if> |
| | | <if test="name != null"> |
| | | `name`, |
| | | </if> |
| | | <if test="lng != null"> |
| | | lng, |
| | | </if> |
| | | <if test="lat != null"> |
| | | lat, |
| | | </if> |
| | | <if test="remark != null"> |
| | | remark, |
| | | </if> |
| | | </trim> |
| | | <trim prefix="values (" suffix=")" suffixOverrides=","> |
| | | <if test="id != null"> |
| | | #{id,jdbcType=BIGINT}, |
| | | </if> |
| | | <if test="devNo != null"> |
| | | #{devNo,jdbcType=VARCHAR}, |
| | | </if> |
| | | <if test="name != null"> |
| | | #{name,jdbcType=VARCHAR}, |
| | | </if> |
| | | <if test="lng != null"> |
| | | #{lng,jdbcType=DOUBLE}, |
| | | </if> |
| | | <if test="lat != null"> |
| | | #{lat,jdbcType=DOUBLE}, |
| | | </if> |
| | | <if test="remark != null"> |
| | | #{remark,jdbcType=VARCHAR}, |
| | | </if> |
| | | </trim> |
| | | </insert> |
| | | <update id="updateByPrimaryKeySelective" parameterType="com.dy.pipIrrGlobal.pojoVi.ViYsCamera"> |
| | | <!--@mbg.generated--> |
| | | update vi_ys_camera |
| | | <set> |
| | | <if test="devNo != null"> |
| | | dev_no = #{devNo,jdbcType=VARCHAR}, |
| | | </if> |
| | | <if test="name != null"> |
| | | `name` = #{name,jdbcType=VARCHAR}, |
| | | </if> |
| | | <if test="lng != null"> |
| | | lng = #{lng,jdbcType=DOUBLE}, |
| | | </if> |
| | | <if test="lat != null"> |
| | | lat = #{lat,jdbcType=DOUBLE}, |
| | | </if> |
| | | <if test="remark != null"> |
| | | remark = #{remark,jdbcType=VARCHAR}, |
| | | </if> |
| | | </set> |
| | | where id = #{id,jdbcType=BIGINT} |
| | | </update> |
| | | <update id="updateByPrimaryKey" parameterType="com.dy.pipIrrGlobal.pojoVi.ViYsCamera"> |
| | | <!--@mbg.generated--> |
| | | update vi_ys_camera |
| | | set dev_no = #{devNo,jdbcType=VARCHAR}, |
| | | `name` = #{name,jdbcType=VARCHAR}, |
| | | lng = #{lng,jdbcType=DOUBLE}, |
| | | lat = #{lat,jdbcType=DOUBLE}, |
| | | remark = #{remark,jdbcType=VARCHAR} |
| | | where id = #{id,jdbcType=BIGINT} |
| | | </update> |
| | | </mapper> |
| | |
| | | # 甘州: mqtt.enable=false |
| | | # 凉州: mqtt.enable=false |
| | | # 金川: mqtt.enable=true |
| | | # mq/sd1/338220031439/weather |
| | | mqtt.enable=true |
| | | mqtt.topicAndQos=ym/sd1/10000/control/m1,1;ym/sd1/10000/control/m2,1;ym/sd1/control/m4,1;ym/sd1/10000/control/m80,1 |
| | | |
| | |
| | | @Override |
| | | public void onApplicationEvent(@NonNull ApplicationReadyEvent event) { |
| | | try { |
| | | //等1秒,等待com.alibaba.druid.pool.DruidDataSource实始化完成 |
| | | //等1秒,等待com.alibaba.druid.pool.DruidDataSource初始化完成 |
| | | Thread.sleep(1000L); |
| | | } catch (InterruptedException e) { |
| | | e.printStackTrace(); |
| | |
| | | } |
| | | |
| | | /** |
| | | * 实始化 |
| | | * 初始化 |
| | | */ |
| | | @SuppressWarnings("unused ") |
| | | private void init(ApplicationReadyEvent event){ |
| | |
| | | @Override |
| | | public void onApplicationEvent(@NonNull ApplicationReadyEvent event) { |
| | | try { |
| | | //等1秒,等待com.alibaba.druid.pool.DruidDataSource实始化完成 |
| | | //等1秒,等待com.alibaba.druid.pool.DruidDataSource初始化完成 |
| | | Thread.sleep(1000L); |
| | | } catch (InterruptedException e) { |
| | | e.printStackTrace(); |
| | |
| | | "com.dy.pipIrrGlobal.daoFi", |
| | | "com.dy.pipIrrGlobal.daoAllRound", |
| | | "com.dy.pipIrrGlobal.daoLargeScreen", |
| | | "com.dy.pipIrrGlobal.daoIr" |
| | | "com.dy.pipIrrGlobal.daoIr", |
| | | "com.dy.pipIrrGlobal.daoVi" |
| | | }) |
| | | public class PipIrrRemoteApplication { |
| | | |
| | |
| | | @Override |
| | | public void onApplicationEvent(@NonNull ApplicationReadyEvent event) { |
| | | try { |
| | | //等1秒,等待com.alibaba.druid.pool.DruidDataSource实始化完成 |
| | | //等1秒,等待com.alibaba.druid.pool.DruidDataSource初始化完成 |
| | | Thread.sleep(1000L); |
| | | } catch (InterruptedException e) { |
| | | e.printStackTrace(); |
New file |
| | |
| | | package com.dy.pipIrrRemote.video; |
| | | |
| | | import com.dy.common.multiDataSource.DataSourceContext; |
| | | import com.dy.pipIrrGlobal.pojoVi.ViYsApp; |
| | | import com.dy.pipIrrGlobal.util.Org; |
| | | import com.dy.pipIrrGlobal.util.OrgListenerSupport; |
| | | import lombok.extern.slf4j.Slf4j; |
| | | import org.springframework.beans.factory.annotation.Autowired; |
| | | import org.springframework.core.io.ResourceLoader; |
| | | import org.springframework.web.bind.annotation.RestController; |
| | | |
| | | import java.util.List; |
| | | |
| | | /** |
| | | * @Author: liurunyu |
| | | * @Date: 2025/6/7 12:45 |
| | | * @Description 类名中包含Inner,表示内部应用的Controller |
| | | */ |
| | | @Slf4j |
| | | @RestController |
| | | public class YsAppCtrl extends OrgListenerSupport { |
| | | |
| | | @Autowired |
| | | protected ResourceLoader resourceLoader ; |
| | | |
| | | @Autowired |
| | | protected YsAppSv ysAppSv; |
| | | |
| | | public ViYsApp selectSingletonYsApp(){ |
| | | return ysAppSv.selectSingleton() ; |
| | | } |
| | | |
| | | public Long saveAccessTokenOfYs(String accessToken, Long expireTime){ |
| | | if(Org.OrgList == null || Org.OrgList.size() == 0){ |
| | | super.init(resourceLoader); |
| | | } |
| | | List<Org.OrgVo> orgList = Org.OrgList ; |
| | | if(orgList != null || orgList.size() > 0){ |
| | | for(Org.OrgVo vo : orgList){ |
| | | //遍历所有org,得到各自的萤石应用AccessToken |
| | | DataSourceContext.set(vo.tag);//设置数据源 |
| | | ysAppSv.deleteAll(); |
| | | ysAppSv.save(accessToken, expireTime) ; |
| | | } |
| | | } |
| | | return null ; |
| | | } |
| | | } |
New file |
| | |
| | | package com.dy.pipIrrRemote.video; |
| | | |
| | | |
| | | import com.dy.common.multiDataSource.DataSourceContext; |
| | | import com.dy.pipIrrGlobal.pojoVi.ViYsApp; |
| | | import com.dy.pipIrrGlobal.util.Org; |
| | | import com.dy.pipIrrGlobal.util.OrgListenerSupport; |
| | | import com.dy.pipIrrRemote.video.ys.YsAppClient; |
| | | import lombok.extern.slf4j.Slf4j; |
| | | import org.springframework.beans.factory.annotation.Autowired; |
| | | import org.springframework.boot.context.event.ApplicationReadyEvent; |
| | | import org.springframework.context.ApplicationListener; |
| | | import org.springframework.core.io.ResourceLoader; |
| | | import org.springframework.lang.NonNull; |
| | | import org.springframework.stereotype.Component; |
| | | |
| | | import java.util.*; |
| | | |
| | | /** |
| | | * @Author: liurunyu |
| | | * @Date: 2025/6/6 17:19 |
| | | * @Description 视频监控 |
| | | * 监听器,实现功能:启动日统计定时任务 |
| | | * 本监听器不能采用ServletContextListener方式,因为Servlet上下文Context创建后 |
| | | * Spring容器并没有创建完,而本类中用了Spring容器中的Bean,即*Dao 。 |
| | | * 所以采用了Spring事件监听器来实现 |
| | | */ |
| | | @Slf4j |
| | | @Component |
| | | public class YsAppListener extends OrgListenerSupport implements ApplicationListener<ApplicationReadyEvent> { |
| | | |
| | | @Autowired |
| | | protected ResourceLoader resourceLoader ; |
| | | |
| | | @Autowired |
| | | protected YsAppCtrl ysAppCtrl; |
| | | |
| | | @Autowired |
| | | protected YsAppClient ysAppClient; |
| | | |
| | | /** |
| | | * SpringBoot容器已经准备好了,执行下面方法 |
| | | * @param event 事件 |
| | | */ |
| | | @Override |
| | | public void onApplicationEvent(@NonNull ApplicationReadyEvent event) { |
| | | try { |
| | | //等1秒,等待com.alibaba.druid.pool.DruidDataSource初始化完成 |
| | | Thread.sleep(1000L); |
| | | } catch (InterruptedException e) { |
| | | e.printStackTrace(); |
| | | }finally { |
| | | try{ |
| | | super.init(resourceLoader); |
| | | this.atSysStart(event); |
| | | }catch (Exception e){ |
| | | log.error("注册萤石云定时任务出错", e); |
| | | } |
| | | } |
| | | } |
| | | /** |
| | | * 初始化 |
| | | */ |
| | | private void atSysStart(ApplicationReadyEvent event) throws Exception{ |
| | | //所有Org,共用一个萤石应用的AccessToken |
| | | boolean isNowGetNewAccessToken = false ;//当下是否获得AccessToken |
| | | List<Org.OrgVo> orgList = Org.OrgList ; |
| | | Map<String, ViYsApp> viYsAppMap = new HashMap<>() ; |
| | | if(orgList != null && orgList.size() >0){ |
| | | for(Org.OrgVo vo : orgList){ |
| | | //遍历所有org,得到各自的萤石应用AccessToken |
| | | DataSourceContext.set(vo.tag);//设置数据源 |
| | | ViYsApp po = ysAppCtrl.selectSingletonYsApp() ; |
| | | if(po == null){ |
| | | isNowGetNewAccessToken = true ; |
| | | }else{ |
| | | viYsAppMap.put(vo.tag, po) ; |
| | | } |
| | | } |
| | | this.dealAtSysStart(viYsAppMap, isNowGetNewAccessToken); |
| | | } |
| | | } |
| | | private void dealAtSysStart(Map<String, ViYsApp> viYsAppMap, boolean isNowGetNewAccessToken){ |
| | | if(!isNowGetNewAccessToken){ |
| | | if(viYsAppMap != null && viYsAppMap.size() >0){ |
| | | long nowMustAtMillis = System.currentTimeMillis() ; |
| | | Collection<ViYsApp> col = viYsAppMap.values() ; |
| | | Iterator<ViYsApp> it = col.iterator() ; |
| | | ViYsApp po ; |
| | | while (it.hasNext()){ |
| | | po = it.next() ; |
| | | if(po.expireTime != null && nowMustAtMillis > po.expireTime){ |
| | | isNowGetNewAccessToken = true ; |
| | | } |
| | | } |
| | | }else{ |
| | | isNowGetNewAccessToken = true ; |
| | | } |
| | | } |
| | | if(isNowGetNewAccessToken){ |
| | | this.ysAppClient.getAccessToken(); |
| | | this.ysAppClient.reSetNextGetAccessToken(null) ; |
| | | }else{ |
| | | long nextGetTokenAtMillis = 0L ; |
| | | Collection<ViYsApp> col = viYsAppMap.values() ; |
| | | Iterator<ViYsApp> it = col.iterator() ; |
| | | ViYsApp po ; |
| | | while (it.hasNext()){ |
| | | po = it.next() ; |
| | | if(nextGetTokenAtMillis == 0 || nextGetTokenAtMillis > po.expireTime){ |
| | | nextGetTokenAtMillis = po.expireTime ; |
| | | } |
| | | } |
| | | if(nextGetTokenAtMillis > 0L){ |
| | | this.ysAppClient.reSetNextGetAccessToken(nextGetTokenAtMillis); |
| | | } |
| | | } |
| | | } |
| | | |
| | | } |
New file |
| | |
| | | package com.dy.pipIrrRemote.video; |
| | | |
| | | import com.dy.common.util.DateTime; |
| | | import com.dy.pipIrrGlobal.daoVi.ViYsAppMapper; |
| | | import com.dy.pipIrrGlobal.pojoVi.ViYsApp; |
| | | import org.springframework.beans.factory.annotation.Autowired; |
| | | import org.springframework.stereotype.Component; |
| | | import org.springframework.transaction.annotation.Transactional; |
| | | |
| | | import java.util.List; |
| | | |
| | | /** |
| | | * @Author: liurunyu |
| | | * @Date: 2025/6/7 9:14 |
| | | * @Description |
| | | */ |
| | | @Component |
| | | public class YsAppSv { |
| | | |
| | | @Autowired |
| | | protected ViYsAppMapper viYsAppDao ; |
| | | |
| | | |
| | | public ViYsApp selectSingleton(){ |
| | | List<ViYsApp> all = this.viYsAppDao.selectAll() ; |
| | | if(all == null || all.size() == 0){ |
| | | return null ; |
| | | }else{ |
| | | return all.get(0) ; |
| | | } |
| | | } |
| | | |
| | | @Transactional(rollbackFor = Exception.class) |
| | | public Long save(String accessToken, Long expireTime){ |
| | | ViYsApp po = new ViYsApp() ; |
| | | po.accessToken = accessToken ; |
| | | po.expireTime = expireTime ; |
| | | po.expireDt = DateTime.getDate(expireTime) ; |
| | | this.viYsAppDao.insert(po) ; |
| | | return po.id ; |
| | | } |
| | | |
| | | @Transactional(rollbackFor = Exception.class) |
| | | public void deleteAll(){ |
| | | viYsAppDao.deleteAll() ; |
| | | } |
| | | } |
New file |
| | |
| | | package com.dy.pipIrrRemote.video.ys; |
| | | |
| | | import lombok.AllArgsConstructor; |
| | | import lombok.Data; |
| | | import lombok.NoArgsConstructor; |
| | | |
| | | /** |
| | | * @Author: liurunyu |
| | | * @Date: 2025/6/7 14:00 |
| | | * @Description |
| | | */ |
| | | @Data |
| | | @NoArgsConstructor |
| | | @AllArgsConstructor |
| | | public class YsAccessTokenData { |
| | | public String accessToken ; |
| | | public Long expireTime ; |
| | | } |
New file |
| | |
| | | package com.dy.pipIrrRemote.video.ys; |
| | | |
| | | import com.dy.common.schedulerTask.TaskJob; |
| | | import com.dy.common.springUtil.SpringContextUtil; |
| | | import org.quartz.JobExecutionContext; |
| | | import org.quartz.JobExecutionException; |
| | | |
| | | /** |
| | | * @Author: liurunyu |
| | | * @Date: 2025/6/7 15:39 |
| | | * @Description |
| | | */ |
| | | public class YsAccessTokenQuartzJob extends TaskJob { |
| | | /** |
| | | * Quartz定时任务,其不在Spring容器中 |
| | | * @param ctx |
| | | * @throws JobExecutionException |
| | | */ |
| | | @Override |
| | | public void execute(JobExecutionContext ctx) throws JobExecutionException { |
| | | YsAppClient ysCli = SpringContextUtil.getBean(YsAppClient.class); |
| | | ysCli.getAccessToken(); |
| | | ysCli.reSetNextGetAccessToken(null); |
| | | } |
| | | } |
New file |
| | |
| | | package com.dy.pipIrrRemote.video.ys; |
| | | |
| | | import lombok.AllArgsConstructor; |
| | | import lombok.Data; |
| | | import lombok.NoArgsConstructor; |
| | | |
| | | /** |
| | | * @Author: liurunyu |
| | | * @Date: 2025/6/7 14:00 |
| | | * @Description |
| | | */ |
| | | @Data |
| | | @NoArgsConstructor |
| | | @AllArgsConstructor |
| | | public class YsAccessTokenResponse { |
| | | public YsAccessTokenData data ; |
| | | public String code ; |
| | | public String msg ; |
| | | } |
New file |
| | |
| | | package com.dy.pipIrrRemote.video.ys; |
| | | |
| | | import com.dy.common.schedulerTask.SchedulerTaskSupport; |
| | | import com.dy.pipIrrRemote.video.YsAppCtrl; |
| | | import lombok.extern.slf4j.Slf4j; |
| | | import org.springframework.beans.factory.annotation.Autowired; |
| | | import org.springframework.beans.factory.annotation.Value; |
| | | import org.springframework.http.*; |
| | | import org.springframework.stereotype.Component; |
| | | import org.springframework.util.LinkedMultiValueMap; |
| | | import org.springframework.util.MultiValueMap; |
| | | import org.springframework.web.client.RestTemplate; |
| | | import org.springframework.web.util.UriComponentsBuilder; |
| | | |
| | | /** |
| | | * @Author: liurunyu |
| | | * @Date: 2025/6/7 11:40 |
| | | * @Description |
| | | */ |
| | | @Slf4j |
| | | @Component |
| | | public class YsAppClient { |
| | | |
| | | private static final String JobName = "VideoYsJob" ; |
| | | private static final String JobGroupName = "VideoYsGroup" ; |
| | | private static final Integer ThreadPoolMaxCount = 1 ;//线程池线程最大个数 |
| | | private static final Integer ThreadPoolPriority = 5 ;//线程优先级 |
| | | private static final boolean quartzJobRunOneTimes = true ;//定时任务只执行一次 |
| | | |
| | | @Value("${ys.accessTokenExpireDay: 7}") |
| | | protected Integer accessTokenExpireDay;//AccessToken过期时间,单位天 |
| | | |
| | | @Value("${ys.appKey}") |
| | | protected String appKey; |
| | | |
| | | @Value("${ys.secret}") |
| | | protected String secret; |
| | | |
| | | @Value("${ys.requestAccessTokenUrl}") |
| | | protected String requestAccessTokenUrl; |
| | | |
| | | @Autowired |
| | | protected RestTemplate restTemplate ; |
| | | |
| | | @Autowired |
| | | protected YsAppCtrl ysVideoCtrl; |
| | | |
| | | private Long computeNetGetAccessTokenAt(){ |
| | | Long millis = (System.currentTimeMillis() + (accessTokenExpireDay * 24 * 60 * 60 * 1000) ) ; |
| | | // millis = 10000L ; |
| | | return millis ; |
| | | } |
| | | |
| | | /** |
| | | * 获得AccessToken |
| | | */ |
| | | public void getAccessToken(){ |
| | | if((appKey != null && appKey.trim().length() > 0) |
| | | && (secret != null && secret.trim().length() > 0) |
| | | && (requestAccessTokenUrl != null && requestAccessTokenUrl.trim().length() > 0)){ |
| | | MultiValueMap<String, String> formData = new LinkedMultiValueMap<>(); |
| | | formData.add("appKey", appKey); |
| | | formData.add("appSecret", secret); |
| | | YsAccessTokenResponse response = this.postRequest2Ys(restTemplate, requestAccessTokenUrl, formData); |
| | | if(response != null){ |
| | | switch (response.code){ |
| | | case "200" :{ |
| | | this.dealSuccessOfRequestAccessTokenFromYs(response) ; |
| | | break ; |
| | | } |
| | | default: { |
| | | this.dealErrorOfRequestAccessTokenFromYs(response) ; |
| | | break ; |
| | | } |
| | | } |
| | | } |
| | | } |
| | | } |
| | | private void dealSuccessOfRequestAccessTokenFromYs(YsAccessTokenResponse response){ |
| | | if(response != null && response.data != null){ |
| | | ysVideoCtrl.saveAccessTokenOfYs(response.data.accessToken, response.data.expireTime); |
| | | } |
| | | } |
| | | |
| | | private void dealErrorOfRequestAccessTokenFromYs(YsAccessTokenResponse response){ |
| | | log.error("从萤石开放平台获得AccessToken失败,错误码:{},错误信息:{}", response.code, response.msg); |
| | | } |
| | | /** |
| | | * 设置下次获得AccessToken |
| | | */ |
| | | public void reSetNextGetAccessToken(Long getAccessTokenAt){ |
| | | if(getAccessTokenAt == null || getAccessTokenAt.longValue() == 0){ |
| | | getAccessTokenAt = this.computeNetGetAccessTokenAt() ; |
| | | } |
| | | //毫秒变成秒 |
| | | int futureSecond = (int)((getAccessTokenAt - System.currentTimeMillis()) / 1000) ; |
| | | try { |
| | | SchedulerTaskSupport.setThreadPoolPro(ThreadPoolMaxCount , ThreadPoolPriority); |
| | | //因为要重复加工作任务,所以先把上次加的同组同名任务删除 |
| | | SchedulerTaskSupport.deleteJob(JobName , JobGroupName) ; |
| | | // 只执行一次的任务 |
| | | SchedulerTaskSupport.addSecondlyJob(JobName , JobGroupName, YsAccessTokenQuartzJob.class, null, futureSecond, 1, 0) ; |
| | | } catch (Exception e) { |
| | | log.error("设置从萤石开放平台定时获得AccessToken任务时发生异常", e); |
| | | } |
| | | } |
| | | /** |
| | | * 向萤石开放平台发送Post请求 |
| | | * @param restTemplate SpringBoot的RestTemplate |
| | | * @param toMwUrl web请求Url |
| | | * @param body 数据 |
| | | * @return |
| | | */ |
| | | private YsAccessTokenResponse postRequest2Ys(RestTemplate restTemplate, String toMwUrl, Object body) { |
| | | String url = UriComponentsBuilder.fromUriString(toMwUrl) |
| | | .build() |
| | | .toUriString(); |
| | | HttpHeaders headers = new HttpHeaders(); |
| | | headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED); |
| | | |
| | | HttpEntity<?> httpEntity = new HttpEntity<>(body, headers); |
| | | ResponseEntity<YsAccessTokenResponse> resEntity = null; |
| | | try { |
| | | // 通过Post方式调用接口 |
| | | resEntity = restTemplate.exchange(url, HttpMethod.POST, httpEntity, YsAccessTokenResponse.class); |
| | | } catch (Exception e) { |
| | | log.error("从萤石开放平台定时获得AccessToken任务执行时发生异常", e); |
| | | } |
| | | if(resEntity != null){ |
| | | return resEntity.getBody(); |
| | | } |
| | | return null ; |
| | | } |
| | | |
| | | } |
| | |
| | | @Override |
| | | public void onApplicationEvent(ApplicationReadyEvent event) { |
| | | try { |
| | | //等1秒,等待com.alibaba.druid.pool.DruidDataSource实始化完成 |
| | | //等1秒,等待com.alibaba.druid.pool.DruidDataSource初始化完成 |
| | | Thread.sleep(1000L); |
| | | } catch (InterruptedException e) { |
| | | e.printStackTrace(); |
| | |
| | | */ |
| | | public class StatisticsJob extends TaskJob { |
| | | |
| | | private static Logger log = LogManager.getLogger(Test.class.getName()) ; |
| | | private static Logger log = LogManager.getLogger(StatisticsJob.class.getName()) ; |
| | | |
| | | private String orgTag ; |
| | | |
| | |
| | | @Override |
| | | public void onApplicationEvent(@NonNull ApplicationReadyEvent event) { |
| | | try { |
| | | //等1秒,等待com.alibaba.druid.pool.DruidDataSource实始化完成 |
| | | //等1秒,等待com.alibaba.druid.pool.DruidDataSource初始化完成 |
| | | Thread.sleep(1000L); |
| | | } catch (InterruptedException e) { |
| | | e.printStackTrace(); |