2 文件已重命名
9个文件已修改
10个文件已添加
964 ■■■■■ 已修改文件
pipIrr-platform/pipIrr-global/src/main/java/com/dy/pipIrrGlobal/daoMd/MdEt0Mapper.java 45 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pipIrr-platform/pipIrr-global/src/main/java/com/dy/pipIrrGlobal/daoRm/RmWeatherHistoryMapper.java 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pipIrr-platform/pipIrr-global/src/main/java/com/dy/pipIrrGlobal/pojoMd/MdEt0.java 92 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pipIrr-platform/pipIrr-global/src/main/java/com/dy/pipIrrGlobal/voRm/VoWeatherMaxMinTmp.java 35 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pipIrr-platform/pipIrr-global/src/main/resources/application-global.yml 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
pipIrr-platform/pipIrr-global/src/main/resources/mapper/MdEt0Mapper.xml 183 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pipIrr-platform/pipIrr-global/src/main/resources/mapper/RmWeatherHistoryMapper.xml 19 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pipIrr-platform/pipIrr-mw/pipIrr-mw-rtu/src/main/java/com/dy/rtuMw/server/mqtt/MqttPubMsgCache.java 7 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pipIrr-platform/pipIrr-mw/pipIrr-mw-rtu/src/main/java/com/dy/rtuMw/server/rtuData/pSdV1/TkPreGenObjs4ManureSdV1.java 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pipIrr-platform/pipIrr-mw/pipIrr-mw-rtu/src/main/java/com/dy/rtuMw/web/comResult/CommandResultDeal.java 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pipIrr-platform/pipIrr-web/pipIrr-web-model/src/main/java/com/dy/pipIrrModel/modelCalculate/Hargreaves.java 149 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pipIrr-platform/pipIrr-web/pipIrr-web-model/src/main/java/com/dy/pipIrrModel/modelCalculate/ModelCalculator.java 130 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pipIrr-platform/pipIrr-web/pipIrr-web-model/src/main/java/com/dy/pipIrrModel/modelCalculate/ModelCalculatorSv.java 83 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pipIrr-platform/pipIrr-web/pipIrr-web-model/src/main/java/com/dy/pipIrrModel/timingTask/CalculateJob.java 8 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pipIrr-platform/pipIrr-web/pipIrr-web-model/src/main/java/com/dy/pipIrrModel/timingTask/ModelListener.java 3 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pipIrr-platform/pipIrr-web/pipIrr-web-model/src/main/java/com/dy/pipIrrModel/vapor/VaporCtrl.java 95 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pipIrr-platform/pipIrr-web/pipIrr-web-model/src/main/java/com/dy/pipIrrModel/vapor/VaporQo.java 38 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pipIrr-platform/pipIrr-web/pipIrr-web-model/src/main/java/com/dy/pipIrrModel/vapor/VaporSv.java 45 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pipIrr-platform/pipIrr-web/pipIrr-web-remote/src/main/java/com/dy/pipIrrRemote/largeScreen/WebSocketServer.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
pipIrr-platform/pipIrr-web/pom.xml 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pipIrr-platform/pom.xml 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pipIrr-platform/pipIrr-global/src/main/java/com/dy/pipIrrGlobal/daoMd/MdEt0Mapper.java
New file
@@ -0,0 +1,45 @@
package com.dy.pipIrrGlobal.daoMd;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.dy.pipIrrGlobal.pojoMd.MdEt0;
import com.dy.pipIrrGlobal.voRm.VoManure;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import java.util.Date;
import java.util.List;
import java.util.Map;
/**: This is a mapper interface for database operations on the MdEt0 entity.
 *               It provides basic CRUD (Create, Read, Update, Delete) functionality.
 * @Author: liurunyu
 * @Date: 2025/8/19 8:35
    // Deletes a record from the database using its primary key
 * @Descripton
 */
    // Inserts a new MdEt0 record into the database
@Mapper
public interface MdEt0Mapper extends BaseMapper< MdEt0> {
    // Inserts a new MdEt0 record into the database, only including non-null fields
    int deleteByPrimaryKey(Long id);
    // Selects and retrieves a MdEt0 record from the database using its primary key
    int insert(MdEt0 record);
    // Updates an existing MdEt0 record in the database, only updating fields that are not null
    int insertSelective(MdEt0 record);
    // Updates an existing MdEt0 record in the database with all fields
    MdEt0 selectByPrimaryKey(Long id);
    MdEt0 selectByCropWeatherDt(@Param("cropId") Long cropId, @Param("weatherId") Long weatherId, @Param("dt") String dt);
    int updateByPrimaryKeySelective(MdEt0 record);
    int updateByPrimaryKey(MdEt0 record);
    List<MdEt0> selectEt0ByDt(@Param("ymd")String ymd) ;
    List<MdEt0> selectEt0ByCropAndDt(Map<?, ?> params);
}
pipIrr-platform/pipIrr-global/src/main/java/com/dy/pipIrrGlobal/daoRm/RmWeatherHistoryMapper.java
@@ -4,7 +4,9 @@
import com.dy.pipIrrGlobal.pojoRm.RmSoilLast;
import com.dy.pipIrrGlobal.pojoRm.RmWeatherHistory;
import com.dy.pipIrrGlobal.voRm.VoWeather;
import com.dy.pipIrrGlobal.voRm.VoWeatherMaxMinTmp;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import java.util.List;
import java.util.Map;
@@ -38,6 +40,8 @@
     */
    List<VoWeather> selectSome(Map<?, ?> params);
    List<VoWeatherMaxMinTmp> selectMaxMinTemperature(@Param("weatherId") Long weatherId, @Param("maxId") Long maxId, @Param("minId") Long minId);
    int updateByPrimaryKeySelective(RmWeatherHistory record);
    int updateByPrimaryKey(RmWeatherHistory record);
pipIrr-platform/pipIrr-global/src/main/java/com/dy/pipIrrGlobal/pojoMd/MdEt0.java
New file
@@ -0,0 +1,92 @@
package com.dy.pipIrrGlobal.pojoMd;
import com.alibaba.fastjson2.annotation.JSONField;
import com.alibaba.fastjson2.writer.ObjectWriterImplToString;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.dy.common.po.BaseEntity;
import com.fasterxml.jackson.annotation.JsonFormat;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotNull;
import lombok.*;
import java.util.Date;
/**
 * @Author: liurunyu
 * @Date: 2025/8/19 8:35
 * @Description 作物蒸腾量
 */
@TableName(value="md_et0", autoResultMap = true)
@Data
@Builder
@ToString
@NoArgsConstructor
@AllArgsConstructor
@Schema(name = "作物蒸腾量")
public class MdEt0 implements BaseEntity {
    public static final long serialVersionUID = 202508190840001L;
    /**
    * 主键
    */
    @JSONField(serializeUsing= ObjectWriterImplToString.class)
    @TableId(type = IdType.INPUT)
    @Schema(description = "实体id", requiredMode = Schema.RequiredMode.NOT_REQUIRED)
    public Long id;
    /**
    * 作物外键
    */
    @Schema(description = "所属的作物", requiredMode = Schema.RequiredMode.REQUIRED)
    @NotNull(message = "所属的作物不能为空") //不能为空也不能为null
    public Long cropId;
    /**
    * 气象站id
    */
    @Schema(description = "关联的气象站", requiredMode = Schema.RequiredMode.REQUIRED)
    @NotNull(message = "关联的气象站不能为空") //不能为空也不能为null
    public Long weatherId;
    /**
    * 作物系数
    */
    @Schema(description = "参于计算的作物系数", requiredMode = Schema.RequiredMode.NOT_REQUIRED)
    public Double factor;
    /**
    * 最高温度
    */
    @Schema(description = "该日最高温度", requiredMode = Schema.RequiredMode.NOT_REQUIRED)
    public Double maxTmp;
    /**
    * 最低温度
    */
    @Schema(description = "该日最低温度", requiredMode = Schema.RequiredMode.NOT_REQUIRED)
    public Double minTmp;
    /**
    * 日期
    */
    @JsonFormat(pattern = "yyyy-MM-dd")
    public Date dt;
    /**
    * 蒸腾量
    */
    @Schema(description = "本日作物蒸腾量", requiredMode = Schema.RequiredMode.NOT_REQUIRED)
    public Double et0;
    /**
     * 非数据库表属性
     * 关联的 作物名称
     */
    @Schema(description = "关联的作物名称", requiredMode = Schema.RequiredMode.NOT_REQUIRED)
    @TableField(exist = false)
    public String cropName;
}
pipIrr-platform/pipIrr-global/src/main/java/com/dy/pipIrrGlobal/voRm/VoWeatherMaxMinTmp.java
New file
@@ -0,0 +1,35 @@
package com.dy.pipIrrGlobal.voRm;
import com.alibaba.fastjson2.annotation.JSONField;
import com.alibaba.fastjson2.writer.ObjectWriterImplToString;
import com.fasterxml.jackson.annotation.JsonPropertyOrder;
import lombok.Data;
/**
 * @Author: liurunyu
 * @Date: 2025/8/18 16:48
 * @Description
 */
@Data
@JsonPropertyOrder({
        "id", "weatherId",
        "maxAirTemperature", "minAirTemperature"
})
public class VoWeatherMaxMinTmp {
    /**
     * 气象站ID
     */
    public Long weatherId;
    /**
     * 最高温度
     */
    public Double maxAirTemperature ;
    /**
     * 最低温度
     */
    public Double minAirTemperature ;
}
pipIrr-platform/pipIrr-global/src/main/resources/application-global.yml
@@ -378,7 +378,7 @@
    ugCallbackUrl_rm: "http://127.0.0.1:8081/remote/rtuUpgradeStateReceiver/receive"
    #微信小程序应用中Rtu远程命令结果回调地址
    rtuCallbackUrl_wx: "http://127.0.0.1:8087/wx/comRes/receive"
    waitMwRtnResultTimeout: 60 #等待中间件返回结果超时时间,单位秒钟
    waitMwRtnResultTimeout: 10 #等待中间件返回结果超时时间,单位秒钟
#不进行userToken过滤的URL,@ConfigurationProperties要求tokennofilter中所有字母都小写
tokennofilter:
pipIrr-platform/pipIrr-global/src/main/resources/mapper/MdEt0Mapper.xml
New file
@@ -0,0 +1,183 @@
<?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.daoMd.MdEt0Mapper">
  <resultMap id="BaseResultMap" type="com.dy.pipIrrGlobal.pojoMd.MdEt0">
    <!--@mbg.generated-->
    <!--@Table md_et0-->
    <id column="id" jdbcType="BIGINT" property="id" />
    <result column="crop_id" jdbcType="BIGINT" property="cropId" />
    <result column="weather_id" jdbcType="BIGINT" property="weatherId" />
    <result column="factor" jdbcType="DOUBLE" property="factor" />
    <result column="max_tmp" jdbcType="DOUBLE" property="maxTmp" />
    <result column="min_tmp" jdbcType="DOUBLE" property="minTmp" />
    <result column="dt" jdbcType="DATE" property="dt" />
    <result column="et0" jdbcType="DOUBLE" property="et0" />
  </resultMap>
  <sql id="Base_Column_List">
    <!--@mbg.generated-->
    id, crop_id, weather_id, factor, max_tmp, min_tmp, dt, et0
  </sql>
  <sql id="Base_Column_List_with_alias">
    <!--@mbg.generated-->
    ${alias}.id, ${alias}.crop_id, ${alias}.weather_id,
    ${alias}.factor, ${alias}.max_tmp, ${alias}.min_tmp,
    ${alias}.dt, ${alias}.et0
  </sql>
  <select id="selectByPrimaryKey" parameterType="java.lang.Long" resultMap="BaseResultMap">
    <!--@mbg.generated-->
    select
    <include refid="Base_Column_List" />
    from md_et0
    where id = #{id,jdbcType=BIGINT}
  </select>
  <select id="selectByCropWeatherDt" resultMap="BaseResultMap">
    <!--@mbg.generated-->
    select
    <include refid="Base_Column_List" />
    from md_et0
    where crop_id = #{cropId,jdbcType=BIGINT}
    and weather_id = #{weatherId,jdbcType=BIGINT}
    and dt = #{dt,jdbcType=DATE}
  </select>
  <select id="selectEt0ByDt" resultMap="BaseResultMap">
    <!--@mbg.generated-->
    select
    <include refid="Base_Column_List_with_alias" >
      <property name="alias" value="et"/>
    </include>,
    mc.name as cropName
    from md_et0 et
    inner join md_crops mc on et.crop_id = mc.id
    where mc.stopped != 1 and et.dt = #{ymd,jdbcType=DATE}
  </select>
  <!--根据指定条件查询记录-->
  <select id="selectEt0ByCropAndDt" resultType="com.dy.pipIrrGlobal.pojoMd.MdEt0">
    SELECT
    <include refid="Base_Column_List_with_alias" >
      <property name="alias" value="htb"/>
    </include>,
    mc.name as cropName
    from md_et0 et
    inner join md_crops mc on et.crop_id = mc.id
    <where>
      <if test="cropId != null">
        AND et.crop_id = #{cropId}
      </if>
      <if test = "timeStart != null and timeStart !='' and timeStop != null and timeStop != ''">
        AND et.dt BETWEEN #{timeStart} AND #{timeStop}
      </if>
    </where>
    ORDER BY et.id ASC
  </select>
  <delete id="deleteByPrimaryKey" parameterType="java.lang.Long">
    <!--@mbg.generated-->
    delete from md_et0
    where id = #{id,jdbcType=BIGINT}
  </delete>
  <insert id="insert" parameterType="com.dy.pipIrrGlobal.pojoMd.MdEt0">
    <!--@mbg.generated-->
    insert into md_et0 (id, crop_id, weather_id,
      factor, max_tmp, min_tmp,
      dt, et0)
    values (#{id,jdbcType=BIGINT}, #{cropId,jdbcType=BIGINT}, #{weatherId,jdbcType=BIGINT},
      #{factor,jdbcType=DOUBLE}, #{maxTmp,jdbcType=DOUBLE}, #{minTmp,jdbcType=DOUBLE},
      #{dt,jdbcType=DATE}, #{et0,jdbcType=DOUBLE})
  </insert>
  <insert id="insertSelective" parameterType="com.dy.pipIrrGlobal.pojoMd.MdEt0">
    <!--@mbg.generated-->
    insert into md_et0
    <trim prefix="(" suffix=")" suffixOverrides=",">
      <if test="id != null">
        id,
      </if>
      <if test="cropId != null">
        crop_id,
      </if>
      <if test="weatherId != null">
        weather_id,
      </if>
      <if test="factor != null">
        factor,
      </if>
      <if test="maxTmp != null">
        max_tmp,
      </if>
      <if test="minTmp != null">
        min_tmp,
      </if>
      <if test="dt != null">
        dt,
      </if>
      <if test="et0 != null">
        et0,
      </if>
    </trim>
    <trim prefix="values (" suffix=")" suffixOverrides=",">
      <if test="id != null">
        #{id,jdbcType=BIGINT},
      </if>
      <if test="cropId != null">
        #{cropId,jdbcType=BIGINT},
      </if>
      <if test="weatherId != null">
        #{weatherId,jdbcType=BIGINT},
      </if>
      <if test="factor != null">
        #{factor,jdbcType=DOUBLE},
      </if>
      <if test="maxTmp != null">
        #{maxTmp,jdbcType=DOUBLE},
      </if>
      <if test="minTmp != null">
        #{minTmp,jdbcType=DOUBLE},
      </if>
      <if test="dt != null">
        #{dt,jdbcType=DATE},
      </if>
      <if test="et0 != null">
        #{et0,jdbcType=DOUBLE},
      </if>
    </trim>
  </insert>
  <update id="updateByPrimaryKeySelective" parameterType="com.dy.pipIrrGlobal.pojoMd.MdEt0">
    <!--@mbg.generated-->
    update md_et0
    <set>
      <if test="cropId != null">
        crop_id = #{cropId,jdbcType=BIGINT},
      </if>
      <if test="weatherId != null">
        weather_id = #{weatherId,jdbcType=BIGINT},
      </if>
      <if test="factor != null">
        factor = #{factor,jdbcType=DOUBLE},
      </if>
      <if test="maxTmp != null">
        max_tmp = #{maxTmp,jdbcType=DOUBLE},
      </if>
      <if test="minTmp != null">
        min_tmp = #{minTmp,jdbcType=DOUBLE},
      </if>
      <if test="dt != null">
        dt = #{dt,jdbcType=DATE},
      </if>
      <if test="et0 != null">
        et0 = #{et0,jdbcType=DOUBLE},
      </if>
    </set>
    where id = #{id,jdbcType=BIGINT}
  </update>
  <update id="updateByPrimaryKey" parameterType="com.dy.pipIrrGlobal.pojoMd.MdEt0">
    <!--@mbg.generated-->
    update md_et0
    set crop_id = #{cropId,jdbcType=BIGINT},
      weather_id = #{weatherId,jdbcType=BIGINT},
      factor = #{factor,jdbcType=DOUBLE},
      max_tmp = #{maxTmp,jdbcType=DOUBLE},
      min_tmp = #{minTmp,jdbcType=DOUBLE},
      dt = #{dt,jdbcType=DATE},
      et0 = #{et0,jdbcType=DOUBLE}
    where id = #{id,jdbcType=BIGINT}
  </update>
</mapper>
pipIrr-platform/pipIrr-global/src/main/resources/mapper/RmWeatherHistoryMapper.xml
@@ -86,6 +86,25 @@
      </if>
    </trim>
  </select>
  <!--根据指定条件查询温度的最大值与最小值-->
  <select id="selectMaxMinTemperature" resultType="com.dy.pipIrrGlobal.voRm.VoWeatherMaxMinTmp">
    SELECT max(air_temperature) maxTmp,  min(air_temperature) minTmp
    FROM rm_weather_history tb
    <where>
      <if test="weatherId != null">
        AND tb.weather_id = #{weatherId}
      </if>
      <if test="startId != null">
        AND tb.id &gt;= #{startId}
      </if>
      <if test="endId != null">
        AND tb.id &lt;= #{endId}
      </if>
    </where>
  </select>
  <delete id="deleteByPrimaryKey" parameterType="java.lang.Long">
    <!--@mbg.generated-->
    delete from rm_weather_history
pipIrr-platform/pipIrr-mw/pipIrr-mw-rtu/src/main/java/com/dy/rtuMw/server/mqtt/MqttPubMsgCache.java
@@ -63,7 +63,8 @@
        while(node != null && node.obj != null){
            obj = (MqttPubMsgNode)node.obj;
            pubMsg = obj.result ;
            if(pubMsg != null
            if(!obj.onceReceivedResult
                    && pubMsg != null
                    && subMsg.subMsgMatchPubMsg(pubMsg)){
                obj.onceReceivedResult = true ;//标识已经收到命令结果
                return pubMsg;
@@ -86,7 +87,9 @@
        while(node != null && node.obj != null){
            obj = (MqttPubMsgNode)node.obj;
            pubMsg = obj.result ;
            if(pubMsg != null && subMsg.subMsgMatchPubMsg(pubMsg)){
            if(!obj.onceReceivedResult
                    && pubMsg != null
                    && subMsg.subMsgMatchPubMsg(pubMsg)){
                obj.onceReceivedResult = true ;//标识已经收到命令结果
                return pubMsg;
            }else{
pipIrr-platform/pipIrr-mw/pipIrr-mw-rtu/src/main/java/com/dy/rtuMw/server/rtuData/pSdV1/TkPreGenObjs4ManureSdV1.java
@@ -57,6 +57,10 @@
                }
            }
            lastUpManureData.put(msg.deviceId + nowVo.no, nowVo);
            if(msg.commandId != null && !msg.commandId.equals("")){
                this.toNextOneTask(data, TkFindComResponseSdV1.taskId);
            }
        }
    }
    private void deal(Object data, MqttSubMsg msg, ManureVo stVo, Long now, boolean dealOnlyLast){
pipIrr-platform/pipIrr-mw/pipIrr-mw-rtu/src/main/java/com/dy/rtuMw/web/comResult/CommandResultDeal.java
@@ -5,6 +5,7 @@
import com.dy.common.mw.protocol.Data;
import com.dy.common.mw.protocol4Mqtt.MqttSubMsg;
import com.dy.rtuMw.server.ServerProperties;
import lombok.extern.slf4j.Slf4j;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
@@ -22,6 +23,7 @@
 * @LastEditTime 2023/12/21 20:28
 * @Description 通信中间件对外进行web调用,把命令结果发送出去
 */
@Slf4j
@Component()
public class CommandResultDeal {
pipIrr-platform/pipIrr-web/pipIrr-web-model/src/main/java/com/dy/pipIrrModel/modelCalculate/Hargreaves.java
New file
@@ -0,0 +1,149 @@
package com.dy.pipIrrModel.modelCalculate;
import net.objecthunter.exp4j.Expression;
import net.objecthunter.exp4j.ExpressionBuilder;
/**
 * @Author: liurunyu
 * @Date: 2025/8/18 14:51
 * @Description 哈格里夫斯(Hargreaves)公式 计算作物实际蒸散量(mm/day)
 */
public class Hargreaves {
    /**
     * 计算弧度
     * 弧度=角度× π/180
     * @param lat 地理纬度
     * @return
     */
    public static Double rad(Double lat) {
        Expression expression = new ExpressionBuilder("x * pi / 180")
                .variables("x")
                .build();
        // 设置变量值
        expression.setVariable("x", lat);
        Double result = expression.evaluate();
        return result ;
    }
    /**
     * 太阳磁偏角
     * @param dayIndex 为年内某天的日序数(比如1月1日为1,12月31日为365或366)
     * @return
     */
    public static Double sunMagnetismAngular(Integer dayIndex){
        Expression expression = new ExpressionBuilder("0.409 * sin(((2 * pi) / 365) * x - 1.39)")
                .variables("x")
                .build();
        // 设置变量值
        expression.setVariable("x", dayIndex);
        Double result = expression.evaluate();
        return result ;
    }
    /**
     * 日地间相对距离的倒数
     * @param dayIndex 为年内某天的日序数(比如1月1日为1,12月31日为365或366)
     * @return
     */
    public static Double sunEarthDistance(Integer dayIndex){
        Expression expression = new ExpressionBuilder("1 + (0.033 * cos(((2 * pi) / 365) * x))")
                .variables("x")
                .build();
        // 设置变量值
        expression.setVariable("x", dayIndex);
        Double result = expression.evaluate();
        return result ;
    }
    /**
     * 太阳时角
     * 0.409 * sin(2 * pi / 365 * x - 1.39)
     * @param fai 地理弧度
     * @param sunMagnetismAngular 太阳磁偏角
     * @return
     */
    public static Double sunTimeAngular(Double fai, Double sunMagnetismAngular){
        Expression expression = new ExpressionBuilder("acos(-tan(x) * tan(y))")
                .variables("x", "y")
                .build();
        // 设置变量值
        expression.setVariable("x", fai);
        expression.setVariable("y", sunMagnetismAngular);
        Double result = expression.evaluate();
        return result ;
    }
    /**
     * 计算天顶辐射
     * @param sunEarthDistance 日地间相对距离的倒数
     * @param sunTimeAngular 太阳时偏角
     * @param fai 地理弧度
     * @param sunMagnetismAngular 太阳磁偏角
     * @return
     */
    public static Double zenithRadiation(Double sunEarthDistance,
                                         Double sunTimeAngular,
                                         Double fai,
                                         Double sunMagnetismAngular){
        Expression expression = new ExpressionBuilder("((24 * 60) / pi) * 0.082 * a * ((b * sin(c) * sin(d)) + (cos(c) * cos(d) * sin(b)))")
                .variables("a", "b", "c", "d")
                .build();
        // 设置变量值
        expression.setVariable("a", sunEarthDistance);
        expression.setVariable("b", sunTimeAngular);
        expression.setVariable("c", fai);
        expression.setVariable("d", sunMagnetismAngular);
        Double result = expression.evaluate();
        return result ;
    }
    /**
     * 格里夫斯(Hargreaves)公式计算作物蒸散量(mm/day)
     * @param kc 作物系数
     * @param maxT 一日内最高温度
     * @param maxT 一日内最高温度
     * @param zenithRadiation 天顶辐射
     * @return
     */
    public static Double ET0(Double kc, Double maxT, Double minT, Double zenithRadiation){
        Expression expression = new ExpressionBuilder("x * (0.0023 * (((a + b) / 2) + 17.8) * ((a + b)^(1/2)) * c * 0.408)")
                .variables("x", "a", "b", "c")
                .build();
        // 设置变量值
        expression.setVariable("x", kc);
        expression.setVariable("a", maxT);
        expression.setVariable("b", minT);
        expression.setVariable("c", zenithRadiation);
        Double result = expression.evaluate();
        return result ;
    }
    public static void main(String[] args) {
        Double lat = 38.561976140977116 ;
        Integer dayIndex = 180 ;
        Double kc = 0.41 ;//作物系数
        Double maxT = 40.1 ;//一日内最高温度
        Double minT = 40.1 ;//一日内最低温度
        Double fai = rad(lat);
        System.out.println(fai);
        Double sunMagnetismAngular = sunMagnetismAngular(dayIndex);
        System.out.println(sunMagnetismAngular);
        Double sunEarthDistance = sunEarthDistance(dayIndex);
        System.out.println(sunEarthDistance);
        Double sunTimeAngular = sunTimeAngular(fai, sunMagnetismAngular);
        System.out.println(sunTimeAngular);
        Double zenithRadiation = zenithRadiation(sunEarthDistance, sunTimeAngular, fai, sunMagnetismAngular);
        System.out.println(zenithRadiation);
        Double et0 = ET0(kc, maxT, minT, zenithRadiation);
        System.out.println(et0);
    }
}
pipIrr-platform/pipIrr-web/pipIrr-web-model/src/main/java/com/dy/pipIrrModel/modelCalculate/ModelCalculator.java
New file
@@ -0,0 +1,130 @@
package com.dy.pipIrrModel.modelCalculate;
import com.dy.common.util.DateTime;
import com.dy.pipIrrGlobal.pojoMd.MdEt0;
import com.dy.pipIrrGlobal.voMd.VoCrops;
import com.dy.pipIrrGlobal.voPr.VoWeather;
import com.dy.pipIrrGlobal.voRm.VoWeatherMaxMinTmp;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
import java.util.Date;
import java.util.List;
/**
 * @Author: liurunyu
 * @Date: 2025/8/18 16:26
 * @Description
 */
@Slf4j
@Component(ModelCalculator.selfBeanName)
@Scope("prototype") //采用原型模式,每次请求新建一个实例对象
public class ModelCalculator {
    public static final String selfBeanName = "modelCalculator";
    private ModelCalculatorSv sv ;
    @Autowired
    public void setSv(ModelCalculatorSv sv){
        this.sv = sv ;
    }
    public void execute(){
        List<VoCrops> crops = this.sv.selectAllCrops() ;
        if(crops != null && crops.size() > 0){
            for (VoCrops crop : crops) {
                if(crop.weatherId != null){
                    try{
                        VoWeather voWeather = this.sv.getWeather(crop.weatherId);
                        if(voWeather.lat != null){
                            this.executeOnCrop(crop, voWeather);
                        }
                    }catch (Exception e){
                        log.error("计算作物(id=" + crop.id + ")蒸腾数据时异常", e);
                    }
                }
            }
        }
    }
    private void executeOnCrop(VoCrops vo, VoWeather voWeather) throws Exception{
        String yesterday_ymd = DateTime.yesterday_yyyy_MM_dd(Integer.parseInt(DateTime.yyyy()), Integer.parseInt(DateTime.MM()), Integer.parseInt(DateTime.dd())) ; //昨天
        Double factor = this.getCropsFactor(vo, yesterday_ymd) ;
        if(factor != null){
            //说明作物处于计算期(作物生长期)中
            List<VoWeatherMaxMinTmp> tmps = this.sv.selectYesterdayMaxMinTemperature(vo.weatherId) ;
            if(tmps != null && tmps.size() > 0){
                VoWeatherMaxMinTmp voMmTmp = tmps.get(0);//只能有一条记录
                Double et0 = this.calculateEt0(yesterday_ymd, vo, voWeather, voMmTmp, factor) ;//计算蒸腾数据
                this.saveEt0(yesterday_ymd, vo, voWeather, voMmTmp, factor, et0) ;
            }
        }
    }
    private Double getCropsFactor(VoCrops vo, String yesterday) throws Exception{
        Double factor = null ;
        if(vo.stopped != null && vo.stopped != 1){
            if(vo.startDt != null && vo.endDt != null){
                String start = DateTime.yyyy() + "-" + vo.startDt ;
                Long days = DateTime.daysBetweenyyyy_MM_dd(yesterday, start) ;
                if(days >= 0){
                    if(vo.life4Start != null && vo.life4End != null){
                        if(days >= vo.life4Start && days <= vo.life4End){
                            factor = vo.life4Factor ;
                        }
                        if(days > vo.life4End){
                            factor = null ;
                        }
                    }
                    if(vo.life3Start != null && vo.life3End != null){
                        if(days >= vo.life3Start && days <= vo.life3End){
                            factor = vo.life3Factor ;
                        }
                    }
                    if(vo.life2Start != null && vo.life2End != null){
                        if(days >= vo.life2Start && days <= vo.life2End){
                            factor = vo.life2Factor ;
                        }
                    }
                    if(vo.life1Start != null && vo.life1End != null){
                        if(days >= vo.life1Start && days <= vo.life1End){
                            factor = vo.life1Factor ;
                        }
                        if(days < vo.life1Start){
                            factor = null ;
                        }
                    }
                }else{
                    factor = null ;
                }
            }
        }
        return factor ;
    }
    private Double calculateEt0(String yesterday_ymd, VoCrops vo, VoWeather voWeather, VoWeatherMaxMinTmp voMmTmp, Double factor) throws Exception{
        Long days = DateTime.daysBetweenyyyy_MM_dd(yesterday_ymd, DateTime.yyyy() + "-01-01");
        Integer dayIndex = days.intValue() + 1 ;
        Double fai = Hargreaves.rad(voWeather.lat);
        Double sunMagnetismAngular = Hargreaves.sunMagnetismAngular(dayIndex);
        Double sunEarthDistance = Hargreaves.sunEarthDistance(dayIndex);
        Double sunTimeAngular = Hargreaves.sunTimeAngular(fai, sunMagnetismAngular);
        Double zenithRadiation = Hargreaves.zenithRadiation(sunEarthDistance, sunTimeAngular, fai, sunMagnetismAngular);
        Double et0 = Hargreaves.ET0(factor, voMmTmp.maxAirTemperature, voMmTmp.minAirTemperature, zenithRadiation);
        return et0 ;
    }
    private void saveEt0(String yesterday_ymd, VoCrops vo, VoWeather voWeather, VoWeatherMaxMinTmp voMmTmp, Double factor, Double et0)throws Exception{
        MdEt0 po = this.sv.selectByCropWeatherDt(vo.id, voWeather.id, yesterday_ymd);
        if(po != null){
            Date yesterday = DateTime.dateFrom_yyyy_MM_dd(yesterday_ymd) ;
            this.sv.saveEt0(vo.id, voWeather.id, yesterday, voMmTmp.maxAirTemperature, voMmTmp.minAirTemperature, factor, et0) ;
        }
    }
}
pipIrr-platform/pipIrr-web/pipIrr-web-model/src/main/java/com/dy/pipIrrModel/modelCalculate/ModelCalculatorSv.java
New file
@@ -0,0 +1,83 @@
package com.dy.pipIrrModel.modelCalculate;
import com.dy.common.util.DateTime;
import com.dy.common.util.IDLongGenerator;
import com.dy.pipIrrGlobal.daoMd.MdCropsMapper;
import com.dy.pipIrrGlobal.daoMd.MdEt0Mapper;
import com.dy.pipIrrGlobal.daoPr.PrStWeatherMapper;
import com.dy.pipIrrGlobal.daoRm.RmWeatherHistoryMapper;
import com.dy.pipIrrGlobal.pojoMd.MdEt0;
import com.dy.pipIrrGlobal.voMd.VoCrops;
import com.dy.pipIrrGlobal.voPr.VoWeather;
import com.dy.pipIrrGlobal.voRm.VoWeatherMaxMinTmp;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.annotations.Param;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.Date;
import java.util.List;
/**
 * @Author: liurunyu
 * @Date: 2025/8/18 16:34
 * @Description
 */
@Slf4j
@Service
public class ModelCalculatorSv {
    private MdCropsMapper mdCropsDao ;
    private PrStWeatherMapper prWeatherDao ;
    private RmWeatherHistoryMapper rmWeatherHistoryDao;
    private MdEt0Mapper mdEt0Dao;
    @Autowired
    private void setDao(MdCropsMapper mdCropsDao,
                        PrStWeatherMapper prWeatherDao,
                        RmWeatherHistoryMapper rmWeatherHistoryDao,
                        MdEt0Mapper mdEt0Dao) {
        this.mdCropsDao = mdCropsDao;
        this.prWeatherDao = prWeatherDao;
        this.rmWeatherHistoryDao = rmWeatherHistoryDao;
        this.mdEt0Dao = mdEt0Dao;
    }
    /**
     * 查询所有作物
     * @return 包含实体集合的结果对象
     */
    @SuppressWarnings("unchecked")
    public List<VoCrops> selectAllCrops(){
        return this.mdCropsDao.selectAll() ;
    }
    public VoWeather getWeather(Long weatherId) throws Exception{
        return this.prWeatherDao.selectOne(weatherId) ;
    }
    public List<VoWeatherMaxMinTmp> selectYesterdayMaxMinTemperature(Long weatherId) throws Exception{
        String ymd = DateTime.yesterday_yyyy_MM_dd(Integer.parseInt(DateTime.yyyy()), Integer.parseInt(DateTime.MM()), Integer.parseInt(DateTime.dd())) ; //昨天
        int[] ymdGrp = DateTime.yyyy_MM_dd_2_ymdGroup(ymd) ;
        Long startId = IDLongGenerator.generateOneDayStartId(ymdGrp[0], ymdGrp[1], ymdGrp[2]) ;
        Long endId = IDLongGenerator.generateOneDayEndId(ymdGrp[0], ymdGrp[1], ymdGrp[2]) ;
        return this.rmWeatherHistoryDao.selectMaxMinTemperature(weatherId, startId, endId);
    }
    public MdEt0 selectByCropWeatherDt(Long cropId, Long weatherId, String yesterday) throws Exception{
        return this.mdEt0Dao.selectByCropWeatherDt(cropId, weatherId, yesterday) ;
    }
    @Transactional(rollbackFor=Exception.class)
    public int saveEt0(Long cropId, Long weatherId, Date yesterday, Double maxAirTemperature, Double minAirTemperature, Double factor, Double et0){
        MdEt0 po = new MdEt0();
        po.cropId = cropId ;
        po.weatherId = weatherId ;
        po.dt = yesterday ;
        po.maxTmp = maxAirTemperature ;
        po.minTmp = minAirTemperature ;
        po.factor = factor ;
        po.et0 = et0 ;
        this.mdEt0Dao.insert(po) ;
        return 0 ;
    }
}
pipIrr-platform/pipIrr-web/pipIrr-web-model/src/main/java/com/dy/pipIrrModel/timingTask/CalculateJob.java
File was renamed from pipIrr-platform/pipIrr-web/pipIrr-web-model/src/main/java/com/dy/pipIrrModel/modelCalculate/CalculateJob.java
@@ -1,7 +1,9 @@
package com.dy.pipIrrModel.modelCalculate;
package com.dy.pipIrrModel.timingTask;
import com.dy.common.multiDataSource.DataSourceContext;
import com.dy.common.schedulerTask.TaskJob;
import com.dy.common.springUtil.SpringContextUtil;
import com.dy.pipIrrModel.modelCalculate.ModelCalculator;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.quartz.JobDataMap;
@@ -29,5 +31,9 @@
            return ;
        }
        DataSourceContext.set(orgTag);//设置数据源
        ModelCalculator bean = (ModelCalculator)SpringContextUtil.getBean(ModelCalculator.selfBeanName);
        if(bean != null){
            bean.execute();
        }
    }
}
pipIrr-platform/pipIrr-web/pipIrr-web-model/src/main/java/com/dy/pipIrrModel/timingTask/ModelListener.java
File was renamed from pipIrr-platform/pipIrr-web/pipIrr-web-model/src/main/java/com/dy/pipIrrModel/modelCalculate/ModelListener.java
@@ -1,4 +1,4 @@
package com.dy.pipIrrModel.modelCalculate;
package com.dy.pipIrrModel.timingTask;
import com.dy.common.schedulerTask.SchedulerTaskSupport;
import com.dy.pipIrrGlobal.util.Org;
@@ -78,7 +78,6 @@
                HashMap<String , Object> jobDataMap    = new HashMap<String , Object>() ;
                jobDataMap.put(orgKey, vo.tag) ;
                SchedulerTaskSupport.addDailyJob(JobName + vo.tag, JobGroupName, CalculateJob.class, jobDataMap, startHour, startMinute ) ;
                //SchedulerTaskSupport.addSecondlyJob(JobName + vo.tag, JobGroupName, TestJob.class, jobDataMap, 10, 10000, 0 ) ;
            }
        }
    }
pipIrr-platform/pipIrr-web/pipIrr-web-model/src/main/java/com/dy/pipIrrModel/vapor/VaporCtrl.java
New file
@@ -0,0 +1,95 @@
package com.dy.pipIrrModel.vapor;
import com.dy.common.aop.SsoAop;
import com.dy.common.util.DateTime;
import com.dy.common.webUtil.BaseResponse;
import com.dy.common.webUtil.BaseResponseUtils;
import com.dy.common.webUtil.ResultCodeMsg;
import com.dy.pipIrrGlobal.pojoMd.MdEt0;
import com.dy.pipIrrGlobal.voRm.VoManure;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.media.Content;
import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
import io.swagger.v3.oas.annotations.responses.ApiResponses;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
/**
 * @Author: liurunyu
 * @Date: 2025/8/19 16:21
 * @Description
 */
@Slf4j
@Tag(name = "作物日蒸腾量", description = "作物日蒸腾量查询等操作")
@RestController
@RequestMapping(path = "mdVapor")
public class VaporCtrl {
    private VaporSv sv;
    @Autowired
    private void setSv(VaporSv sv) { this.sv = sv; }
    /**
     * 客户端请求得到所有作物的昨日蒸腾量
     * @return 所有所有作物的昨日蒸腾量
     */
    @Operation(summary = "获得作物的昨日蒸腾量", description = "返回所有作物的昨日蒸腾量数据")
    @ApiResponses(value = {
            @ApiResponse(
                    responseCode = ResultCodeMsg.RsCode.SUCCESS_CODE,
                    description = "返回作物的昨日蒸腾量数据(BaseResponse.content:QueryResultVo[{}])",
                    content = {@Content(mediaType = MediaType.APPLICATION_JSON_VALUE,
                            schema = @Schema(implementation = MdEt0.class))}
            )
    })
    @GetMapping(path = "allYesterday")
    @SsoAop()
    public BaseResponse<List<MdEt0>> allYesterday(){
        try {
            String ymd = DateTime.yesterday_yyyy_MM_dd(
                    Integer.parseInt(DateTime.yyyy()),
                    Integer.parseInt(DateTime.MM()),
                    Integer.parseInt(DateTime.dd())) ;
            List<MdEt0> res = this.sv.selectEt0(ymd) ;
            return BaseResponseUtils.buildSuccess(res);
        } catch (Exception e) {
            log.error("查询所有作物的昨日蒸腾量异常", e);
            return BaseResponseUtils.buildException(e.getMessage()) ;
        }
    }
    /**
     * 根据指定条件作物查询一段时间内的蒸腾量
     * @param qo
     * @return
     */
    @GetMapping(path = "oneCropsSomeEt0")
    @SsoAop()
    public BaseResponse<List<VoManure>> oneCropsSomeEt0(VaporQo qo){
        try {
            if(qo.cropId == null){
                return BaseResponseUtils.buildFail("作物id不能为空") ;
            }
            if(qo.timeStop == null || qo.timeStop.trim().equals("")){
                qo.timeStop = DateTime.yyyy_MM_dd() ;
            }
            if(qo.timeStart == null || qo.timeStart.trim().equals("")){
                qo.timeStart = DateTime.lastXDay_yyyy_MM_dd(qo.timeStop, 10);
            }
            return BaseResponseUtils.buildSuccess(sv.oneCropsSomeEt0(qo));
        } catch (Exception e) {
            return BaseResponseUtils.buildException(e.getMessage()) ;
        }
    }
}
pipIrr-platform/pipIrr-web/pipIrr-web-model/src/main/java/com/dy/pipIrrModel/vapor/VaporQo.java
New file
@@ -0,0 +1,38 @@
package com.dy.pipIrrModel.vapor;
import com.dy.common.webUtil.QueryConditionVo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.*;
/**
 * @Author: liurunyu
 * @Date: 2025/8/19 16:21
 * @Description
 */
@Data
@EqualsAndHashCode(callSuper = false)
@ToString(callSuper = true)
@NoArgsConstructor
@AllArgsConstructor
@Builder
@Schema(name = "作物日蒸腾查询条件")
public class VaporQo extends QueryConditionVo {
    /**
     * 作物ID
     */
    @Schema(description = "作物ID", requiredMode = Schema.RequiredMode.NOT_REQUIRED)
    public Long cropId;
    /**
     * 查询开始日期
     */
    @Schema(description = "查询开始日期", requiredMode = Schema.RequiredMode.NOT_REQUIRED)
    public String timeStart;
    /**
     * 查询结束日期
     */
    @Schema(description = "查询结束日期", requiredMode = Schema.RequiredMode.NOT_REQUIRED)
    public String timeStop;
}
pipIrr-platform/pipIrr-web/pipIrr-web-model/src/main/java/com/dy/pipIrrModel/vapor/VaporSv.java
New file
@@ -0,0 +1,45 @@
package com.dy.pipIrrModel.vapor;
import com.dy.common.util.DateTime;
import com.dy.common.webUtil.BaseResponse;
import com.dy.common.webUtil.BaseResponseUtils;
import com.dy.common.webUtil.QueryResultVo;
import com.dy.pipIrrGlobal.daoMd.MdEt0Mapper;
import com.dy.pipIrrGlobal.pojoMd.MdEt0;
import com.dy.pipIrrGlobal.voRm.VoManure;
import lombok.extern.slf4j.Slf4j;
import org.apache.dubbo.common.utils.PojoUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
import java.util.Map;
/**
 * @Author: liurunyu
 * @Date: 2025/8/19 16:21
 * @Description
 */
@Slf4j
@Service
public class VaporSv {
    private MdEt0Mapper mdEt0Dao;
    @Autowired
    private void setDao( MdEt0Mapper mdEt0Dao) {
        this.mdEt0Dao = mdEt0Dao;
    }
    public List<MdEt0> selectEt0(String ymd){
       return mdEt0Dao.selectEt0ByDt(ymd);
    }
    public List<MdEt0> oneCropsSomeEt0(VaporQo qo){
       Map<String, Object> params = (Map<String, Object>) PojoUtils.generalize(qo);
       return mdEt0Dao.selectEt0ByCropAndDt(params);
    }
}
pipIrr-platform/pipIrr-web/pipIrr-web-remote/src/main/java/com/dy/pipIrrRemote/largeScreen/WebSocketServer.java
@@ -109,7 +109,7 @@
     */
    @OnError
    public void onError(Session session, Throwable error) {
        log.error("客户端:" + this.token + ",websocket会话异常,原因:" + error.getMessage());
        //log.error("客户端:" + this.token + ",websocket会话异常,原因:" + error.getMessage());
    }
    /**
pipIrr-platform/pipIrr-web/pom.xml
@@ -249,6 +249,13 @@
            <version>2.18.0</version>
        </dependency>
        <!-- java数学公式计算 -->
        <dependency>
            <groupId>net.objecthunter</groupId>
            <artifactId>exp4j</artifactId>
            <version>0.4.8</version>
        </dependency>
        <!-- 测试 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
pipIrr-platform/pom.xml
@@ -47,6 +47,7 @@
        <mapstruct.version>1.5.5.Final</mapstruct.version>
        <hutool-all.version>5.8.22</hutool-all.version>
        <org-jdom2.version>2.0.6.1</org-jdom2.version>
        <net.exp4j>0.4.8</net.exp4j>
        <spring-boot-maven-plugin.version>3.2.0</spring-boot-maven-plugin.version>
        <maven-jar-plugin-plugin.version>3.3.0</maven-jar-plugin-plugin.version>
@@ -334,6 +335,16 @@
                <type>pom</type>
                <scope>import</scope>
            </dependency>
            <!-- java数学公式计算 -->
            <dependency>
                <groupId>net.objecthunter</groupId>
                <artifactId>exp4j</artifactId>
                <version>0.4.8</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
            <!-- 测试 -->
            <dependency>
                <groupId>org.springframework.boot</groupId>