2 文件已重命名
9个文件已修改
10个文件已添加
New file |
| | |
| | | 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); |
| | | |
| | | } |
| | |
| | | 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; |
| | |
| | | */ |
| | | 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); |
New file |
| | |
| | | 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; |
| | | |
| | | } |
New file |
| | |
| | | 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 ; |
| | | } |
| | |
| | | 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: |
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.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> |
| | |
| | | </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 >= #{startId} |
| | | </if> |
| | | <if test="endId != null"> |
| | | AND tb.id <= #{endId} |
| | | </if> |
| | | </where> |
| | | </select> |
| | | |
| | | <delete id="deleteByPrimaryKey" parameterType="java.lang.Long"> |
| | | <!--@mbg.generated--> |
| | | delete from rm_weather_history |
| | |
| | | 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; |
| | |
| | | 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{ |
| | |
| | | } |
| | | } |
| | | 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){ |
| | |
| | | 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; |
| | |
| | | * @LastEditTime 2023/12/21 20:28 |
| | | * @Description 通信中间件对外进行web调用,把命令结果发送出去 |
| | | */ |
| | | @Slf4j |
| | | @Component() |
| | | public class CommandResultDeal { |
| | | |
New file |
| | |
| | | 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); |
| | | } |
| | | |
| | | } |
New file |
| | |
| | | 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) ; |
| | | } |
| | | } |
| | | } |
New file |
| | |
| | | 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 ; |
| | | } |
| | | } |
File was renamed from pipIrr-platform/pipIrr-web/pipIrr-web-model/src/main/java/com/dy/pipIrrModel/modelCalculate/CalculateJob.java |
| | |
| | | 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; |
| | |
| | | return ; |
| | | } |
| | | DataSourceContext.set(orgTag);//设置数据源 |
| | | ModelCalculator bean = (ModelCalculator)SpringContextUtil.getBean(ModelCalculator.selfBeanName); |
| | | if(bean != null){ |
| | | bean.execute(); |
| | | } |
| | | } |
| | | } |
File was renamed from pipIrr-platform/pipIrr-web/pipIrr-web-model/src/main/java/com/dy/pipIrrModel/modelCalculate/ModelListener.java |
| | |
| | | package com.dy.pipIrrModel.modelCalculate; |
| | | package com.dy.pipIrrModel.timingTask; |
| | | |
| | | import com.dy.common.schedulerTask.SchedulerTaskSupport; |
| | | import com.dy.pipIrrGlobal.util.Org; |
| | |
| | | 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 ) ; |
| | | } |
| | | } |
| | | } |
New file |
| | |
| | | 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()) ; |
| | | } |
| | | } |
| | | |
| | | } |
New file |
| | |
| | | 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; |
| | | |
| | | } |
New file |
| | |
| | | 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); |
| | | } |
| | | |
| | | |
| | | } |
| | |
| | | */ |
| | | @OnError |
| | | public void onError(Session session, Throwable error) { |
| | | log.error("客户端:" + this.token + ",websocket会话异常,原因:" + error.getMessage()); |
| | | //log.error("客户端:" + this.token + ",websocket会话异常,原因:" + error.getMessage()); |
| | | } |
| | | |
| | | /** |
| | |
| | | <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> |
| | |
| | | <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> |
| | |
| | | <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> |