czt
2026-01-09 84043dad83ea5193179e82227b191e522496bae5
料位总览提交2-IOT协议
已重命名2个文件
已修改13个文件
已添加21个文件
1753 ■■■■■ 文件已修改
fzzy-igdss-core/src/main/java/com/fzzy/igds/domain/Depot.java 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
fzzy-igdss-core/src/main/java/com/fzzy/igds/domain/DepotConf.java 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
fzzy-igdss-core/src/main/java/com/fzzy/igds/domain/WeatherCity.java 58 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
fzzy-igdss-core/src/main/java/com/fzzy/igds/domain/WeatherConf.java 93 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
fzzy-igdss-core/src/main/java/com/fzzy/igds/domain/WeatherInfo.java 85 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
fzzy-igdss-core/src/main/java/com/fzzy/igds/mapper/WeatherCityMapper.java 14 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
fzzy-igdss-core/src/main/java/com/fzzy/igds/mapper/WeatherConfMapper.java 14 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
fzzy-igdss-core/src/main/java/com/fzzy/igds/mapper/WeatherInfoMapper.java 14 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
fzzy-igdss-core/src/main/java/com/fzzy/igds/service/FileService.java 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
fzzy-igdss-core/src/main/java/com/fzzy/igds/service/GrainService.java 116 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
fzzy-igdss-core/src/main/java/com/fzzy/igds/service/QuantityService.java 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
fzzy-igdss-core/src/main/java/com/fzzy/igds/service/WeatherService.java 284 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
fzzy-igdss-core/src/main/java/com/fzzy/igds/utils/ContextUtil.java 29 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
fzzy-igdss-core/src/main/java/com/fzzy/igds/utils/SpringUtil.java 58 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
fzzy-igdss-io/src/main/java/com/fzzy/igds/ServerRunner.java 11 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
fzzy-igdss-io/src/main/java/com/fzzy/igds/io/notify/NotifyGrainInvoker.java 57 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
fzzy-igdss-io/src/main/java/com/fzzy/igds/io/notify/NotifyGrainInvokerImpl.java 167 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
fzzy-igdss-io/src/main/java/com/fzzy/igds/io/notify/NotifyWebInvoker.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
fzzy-igdss-io/src/main/java/com/fzzy/igds/io/notify/NotifyWebInvokerImpl.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
fzzy-igdss-io/src/main/java/com/fzzy/igds/io/notify/NotifyWebParent.java 20 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
fzzy-igdss-io/src/main/java/com/fzzy/igds/io/notify/ServerNotifyInvoker.java 39 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
fzzy-igdss-io/src/main/java/com/fzzy/igds/iot/analysis/AnalysisService.java 265 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
fzzy-igdss-io/src/main/java/com/fzzy/igds/iot/analysis/builder/ReMessageBuilder.java 72 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
fzzy-igdss-io/src/main/java/com/fzzy/igds/iot/analysis/message/DeviceAttr.java 26 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
fzzy-igdss-io/src/main/java/com/fzzy/igds/iot/analysis/message/DeviceAttrInfo.java 16 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
fzzy-igdss-io/src/main/java/com/fzzy/igds/iot/analysis/message/IoMessage.java 30 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
fzzy-igdss-io/src/main/java/com/fzzy/igds/iot/server/IotMessageConsumer.java 42 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
fzzy-igdss-io/src/main/java/com/fzzy/igds/iot/server/IotServerEngine.java 69 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
fzzy-igdss-io/src/main/java/com/fzzy/igds/iot/server/IotSessionListener.java 40 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
fzzy-igdss-io/src/main/java/com/fzzy/igds/iot/server/ServerUtils.java 23 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
fzzy-igdss-io/src/main/java/com/fzzy/igds/quantity/analysis/AnalysisService.java 3 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
fzzy-igdss-io/src/main/java/com/fzzy/igds/quantity/command/BhznRemoteQuantityImpl.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
fzzy-igdss-view/src/main/java/com/fzzy/igds/Depot.view.xml 29 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
fzzy-igdss-view/src/main/java/com/fzzy/igds/DepotConf.view.xml 15 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
fzzy-igdss-view/src/main/java/com/fzzy/igds/DeviceIot.view.xml 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
fzzy-igdss-view/src/main/java/models/core.model.xml 27 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
fzzy-igdss-core/src/main/java/com/fzzy/igds/domain/Depot.java
@@ -97,6 +97,18 @@
    @TableField("bulk_weight")
    private Double bulkWeight;
    @Column(name = "length", columnDefinition = "decimal(20,2) COMMENT '长/直径(单位:米)'")
    @TableField("length")
    private Double length = 0.0;
    @Column(name = "width", columnDefinition = "decimal(20,2) COMMENT '宽(单位:米)'")
    @TableField("width")
    private Double width = 0.0;
    @Column(name = "height", columnDefinition = "decimal(20,2) COMMENT '高度(单位:米)'")
    @TableField("height")
    private Double height = 0.0;
    @Column(name = "store_keeper", columnDefinition = "varchar(40) COMMENT '保管员'")
    @TableField("store_keeper")
    private String storeKeeper;
fzzy-igdss-core/src/main/java/com/fzzy/igds/domain/DepotConf.java
@@ -107,12 +107,4 @@
    @TableField("is_only_th")
    private String isOnlyTH = Constant.YN_N;
    @Column(name = "diameter", columnDefinition = "decimal(20,2) COMMENT '筒仓直径(单位:米)'")
    @TableField("diameter")
    private Double diameter = 0.0;
    @Column(name = "height", columnDefinition = "decimal(20,2) COMMENT '筒仓高度(单位:米)'")
    @TableField("height")
    private Double height = 0.0;
}
fzzy-igdss-core/src/main/java/com/fzzy/igds/domain/WeatherCity.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,58 @@
package com.fzzy.igds.domain;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import lombok.EqualsAndHashCode;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;
import java.io.Serializable;
/**
 * @Description
 * @Author CZT
 * @Date 2026/01/09 11:55
 */
@Data
@Entity
@Table(name = "d_weather_city")
@TableName("d_weather_city")
@EqualsAndHashCode(callSuper = false)
public class WeatherCity  extends BizBaseEntity implements Serializable {
    /**
     *
     */
    private static final long serialVersionUID = 1L;
    @Id
    @Column(name = "id", columnDefinition = "varchar(40) COMMENT '主键'")
    @TableField("id")
    private String id;
    @Column(name = "city_en", columnDefinition = "varchar(40) COMMENT '城市编码'")
    @TableField("city_en")
    private String cityEn;
    @Column(name = "city_zh", columnDefinition = "varchar(40) COMMENT '城市名称'")
    @TableField("city_zh")
    private String cityZh;
    @Column(name = "province_en", columnDefinition = "varchar(40) COMMENT '省份编码'")
    @TableField("province_en")
    private String provinceEn;
    @Column(name = "province_zh", columnDefinition = "varchar(40) COMMENT '省份名称'")
    @TableField("province_zh")
    private String provinceZh;
    @Column(name = "lat", columnDefinition = "varchar(40) COMMENT '坐标'")
    @TableField("lat")
    private String lat;
    @Column(name = "lon", columnDefinition = "varchar(40) COMMENT '坐标'")
    @TableField("lon")
    private String lon;
}
fzzy-igdss-core/src/main/java/com/fzzy/igds/domain/WeatherConf.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,93 @@
package com.fzzy.igds.domain;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableName;
import com.fzzy.igds.constant.Constant;
import lombok.Data;
import lombok.EqualsAndHashCode;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;
import java.io.Serializable;
/**
 * @Description
 * @Author CZT
 * @Date 2026/01/09 11:55
 */
@Data
@Entity
@Table(name = "d_weather_conf")
@TableName("d_weather_conf")
@EqualsAndHashCode(callSuper = false)
public class WeatherConf extends BizBaseEntity implements Serializable  {
    /**
     *
     */
    private static final long serialVersionUID = 1L;
    @Id
    @Column(name = "id", columnDefinition = "varchar(40) COMMENT '主键'")
    @TableField("id")
    private String id;
    @Column(name = "dept_id", columnDefinition = "varchar(40) COMMENT '所属库区'")
    @TableField("dept_id")
    private String deptId;
    @Column(name = "name", columnDefinition = "varchar(40) COMMENT '设备名称'")
    @TableField("name")
    private String name;
    @Column(name = "ip", columnDefinition = "varchar(40) COMMENT 'IP地址'")
    @TableField("ip")
    private String ip;
    @Column(name = "port", columnDefinition = "int COMMENT '端口号'")
    @TableField("port")
    private Integer port;
    @Column(name = "mac_status", columnDefinition = "varchar(40) COMMENT '设备状态'")
    @TableField("mac_status")
    private String macStatus = Constant.STATUS_NONE;
    @Column(name = "protocol", columnDefinition = "varchar(40) COMMENT '所属协议'")
    @TableField("protocol")
    private String protocol;
    @Column(name = "wan_tag", columnDefinition = "varchar(40) COMMENT '外网气象'")
    @TableField("wan_tag")
    private String wanTag = Constant.YN_N;
    @Column(name = "city", columnDefinition = "varchar(40) COMMENT '气象城市'")
    @TableField("city")
    private String city;
    @Column(name = "city_id", columnDefinition = "varchar(40) COMMENT '气象城市'")
    @TableField("city_id")
    private String cityId;
    @Column(name = "account", columnDefinition = "varchar(40) COMMENT '账号'")
    @TableField("account")
    private String account;
    @Column(name = "password", columnDefinition = "varchar(40) COMMENT '密码'")
    @TableField("password")
    private String password;
    public WeatherConf() {
        super();
    }
    public WeatherConf(String deptId) {
        super();
        this.deptId = deptId;
    }
    public WeatherConf(String deptId, String cityId) {
        super();
        this.deptId = deptId;
        this.cityId = cityId;
    }
}
fzzy-igdss-core/src/main/java/com/fzzy/igds/domain/WeatherInfo.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,85 @@
package com.fzzy.igds.domain;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import lombok.EqualsAndHashCode;
import javax.persistence.*;
import java.io.Serializable;
/**
 * @Description æ°”象信息,气象信息来源包括外网和库区气象站,当前定义即作为DATA又作为DTO使用因此会定义虚拟的扩展字段
 * @Author CZT
 * @Date 2026/01/09 11:55
 */
@Data
@Entity
@Table(name = "d_weather_info")
@TableName("d_weather_info")
@EqualsAndHashCode(callSuper = false)
public class WeatherInfo extends BizBaseEntity implements Serializable {
    /**
     *
     */
    private static final long serialVersionUID = 1L;
    @Id
    @Column(name = "id", columnDefinition = "varchar(40) COMMENT '主键'")
    @TableField("id")
    private String id;
    @Column(name = "dept_id", columnDefinition = "varchar(40) COMMENT '所属库区'")
    @TableField("dept_id")
    private String deptId;
    @Column(name = "city", columnDefinition = "varchar(40) COMMENT '所属城市'")
    @TableField("city")
    private String city;
    @Column(name = "temp", columnDefinition = "varchar(40) COMMENT '温度'")
    @TableField("temp")
    private String temp = "0.0℃";
    @Column(name = "humidity", columnDefinition = "varchar(40) COMMENT '湿度'")
    @TableField("humidity")
    private String humidity = "0.0%";
    @Column(name = "wind_speed", columnDefinition = "varchar(40) COMMENT '风级'")
    @TableField("wind_speed")
    private String windSpeed = "0级";
    @Column(name = "wind_meter", columnDefinition = "varchar(40) COMMENT '风速'")
    @TableField("wind_meter")
    private String windMeter = "0km/h";
    @Column(name = "wind_direction", columnDefinition = "varchar(40) COMMENT '风向'")
    @TableField("wind_direction")
    private String windDirection = "无风";
    @Column(name = "weather", columnDefinition = "varchar(40) COMMENT '天气'")
    @TableField("weather")
    private String weather = "晴天";
    @Column(name = "rainfall", columnDefinition = "varchar(40) COMMENT '雨量'")
    @TableField("rainfall")
    private String rainfall = "0.0mm/h";
    @Column(name = "pm25", columnDefinition = "varchar(40) COMMENT 'PM2.5'")
    @TableField("pm25")
    private String pm25 = "0μg/m3";
    @Column(name = "air_level", columnDefinition = "varchar(40) COMMENT '空气质量等级'")
    @TableField("air_level")
    private String airLevel = "优";
    @Column(name = "pressure", columnDefinition = "varchar(40) COMMENT '大气压'")
    @TableField("pressure")
    private String pressure;
    @Column(name = "source", columnDefinition = "varchar(40) COMMENT '信息来源:01-库区气象站,02-外网'")
    @TableField("source")
    private String source = "01";
}
fzzy-igdss-core/src/main/java/com/fzzy/igds/mapper/WeatherCityMapper.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,14 @@
package com.fzzy.igds.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.fzzy.igds.domain.WeatherCity;
import org.apache.ibatis.annotations.Mapper;
/**
 * @Description
 * @Author CZT
 * @Date 2026/01/09 11:55
 */
@Mapper
public interface WeatherCityMapper extends BaseMapper<WeatherCity> {
}
fzzy-igdss-core/src/main/java/com/fzzy/igds/mapper/WeatherConfMapper.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,14 @@
package com.fzzy.igds.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.fzzy.igds.domain.WeatherConf;
import org.apache.ibatis.annotations.Mapper;
/**
 * @Description
 * @Author CZT
 * @Date 2026/01/09 11:55
 */
@Mapper
public interface WeatherConfMapper extends BaseMapper<WeatherConf> {
}
fzzy-igdss-core/src/main/java/com/fzzy/igds/mapper/WeatherInfoMapper.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,14 @@
package com.fzzy.igds.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.fzzy.igds.domain.WeatherInfo;
import org.apache.ibatis.annotations.Mapper;
/**
 * @Description
 * @Author CZT
 * @Date 2026/01/09 11:55
 */
@Mapper
public interface WeatherInfoMapper extends BaseMapper<WeatherInfo> {
}
fzzy-igdss-core/src/main/java/com/fzzy/igds/service/FileService.java
@@ -79,6 +79,7 @@
            //文件全路径
            String filePath = getFileSavePath(pathTag) + data.getFileName();
            filePath = filePath.replace(FrameworkConfig.getProfile(), "/profile/");
            data.setFilePath(filePath);
fzzy-igdss-core/src/main/java/com/fzzy/igds/service/GrainService.java
@@ -2,21 +2,25 @@
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.fzzy.igds.constant.OrderRespEnum;
import com.fzzy.igds.constant.RedisConst;
import com.fzzy.igds.data.GrainData;
import com.fzzy.igds.data.GrainParam;
import com.fzzy.igds.data.InoutParam;
import com.fzzy.igds.domain.Depot;
import com.fzzy.igds.domain.Grain;
import com.fzzy.igds.domain.InoutRecord;
import com.fzzy.igds.mapper.GrainMapper;
import com.fzzy.igds.utils.ContextUtil;
import com.fzzy.igds.utils.DateUtil;
import com.fzzy.igds.websocket.WebSocketPacket;
import com.fzzy.igds.websocket.WebSocketServer;
import com.ruoyi.common.core.redis.RedisCache;
import com.ruoyi.common.utils.StringUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.time.DateFormatUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.*;
/**
 * @Description
@@ -29,6 +33,10 @@
    @Resource
    private GrainMapper grainMapper;
    @Resource
    private RedisCache redisCache;
    @Resource
    private DepotService depotService;
    /**
     * æŸ¥è¯¢æ•°æ®
@@ -93,4 +101,100 @@
        grainMapper.selectPage(page, queryWrapper);
    }
    /**
     * JPA - æ›´æ–°æ•°æ®
     * @param data
     */
    public void saveOrUpdateGrain(Grain data, String batchTag) {
        if (StringUtils.isEmpty(data.getCompanyId())) {
            data.setCompanyId(ContextUtil.getCompanyId());
        }
        if (StringUtils.isEmpty(data.getBatchId())) {
            data.setBatchId(DateFormatUtils.format(data.getReceiveDate(), "yyyyMMddHHmm"));
        }
        if(StringUtils.isEmpty(batchTag)){
            //自动生成
            batchTag = "01";
        }
        if(StringUtils.isBlank(data.getCreateBy())){
            data.setCreateBy(ContextUtil.getLoginUserName());
            data.setCreateTime(new Date());
        }
        data.setUpdateBy(ContextUtil.getLoginUserName());
        data.setUpdateTime(new Date());
        data.setBatchTag(batchTag);
        int insert = grainMapper.updateById(data);
        if(insert == 0){
            grainMapper.insert(data);
        }
        updateCacheGrainData(data);
    }
    /**
     * æ›´æ–°ç¼“存中最新的粮情检测数据
     *
     * @param data å½“前数据为标准的Grain数据,没有做更新点位信息
     * @return key=参考编码
     */
    public void updateCacheGrainData(Grain data) {
        GrainData grainData = new GrainData();
        BeanUtils.copyProperties(data, grainData);
        String key = RedisConst.buildKey(data.getCompanyId(),
                RedisConst.KEY_GRAIN, grainData.getDepotId());
        redisCache.setCacheObject(key, grainData);
        //推送大屏
        String deptId = data.getDeptId();
        if (null == deptId) {
            Depot depot = depotService.getCacheDepot(data.getCompanyId(), data.getDepotId());
            if (null == depot) {
                return;
            }
            deptId = depot.getDeptId();
        }
        Map<String, GrainData> mapData = this.getCacheGrainDateMap(data.getCompanyId(), deptId);
        WebSocketPacket packet = new WebSocketPacket();
        packet.setBizType("screen");
        packet.setCompanyId(ContextUtil.getCompanyId());
        packet.setDeptId(deptId);
        packet.setBizId("grain");
        packet.setOrderResp(OrderRespEnum.ORDER_INPROGRESS.getCode());
        packet.setData(mapData);
        WebSocketServer.sendByPocket(packet);
    }
    /**
     * èŽ·å–ç¼“å­˜ä¸­æœ€æ–°çš„ç²®æƒ…æ£€æµ‹æ•°æ®
     *
     * @param companyId
     * @return key=参考编码
     */
    public Map<String, GrainData> getCacheGrainDateMap(String companyId, String deptId) {
        if (null == companyId || null == deptId) return null;
        String pattern = RedisConst.buildKey(companyId, RedisConst.KEY_GRAIN) + "*";
        Collection<String> keys = redisCache.keys(pattern);
        if (null == keys || keys.isEmpty()) return null;
        Map<String, GrainData> result = new HashMap<>();
        GrainData data;
        for (String key : keys) {
            data = (GrainData) redisCache.getCacheObject(key);
            if (null == data) continue;
            result.put(data.getDepotId(), data);
        }
        return result;
    }
}
fzzy-igdss-core/src/main/java/com/fzzy/igds/service/QuantityService.java
@@ -94,6 +94,14 @@
     * @param data
     */
    public void saveData(Quantity data) {
        data.setUpdateBy(ContextUtil.getLoginUserName());
        data.setUpdateTime(new Date());
        if(StringUtils.isBlank(data.getCreateBy())){
            data.setCreateBy(ContextUtil.getLoginUserName());
            data.setCreateTime(new Date());
        }
        quantityMapper.insert(data);
    }
fzzy-igdss-core/src/main/java/com/fzzy/igds/service/WeatherService.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,284 @@
package com.fzzy.igds.service;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.fzzy.igds.constant.RedisConst;
import com.fzzy.igds.domain.WeatherCity;
import com.fzzy.igds.domain.WeatherConf;
import com.fzzy.igds.domain.WeatherInfo;
import com.fzzy.igds.mapper.WeatherCityMapper;
import com.fzzy.igds.mapper.WeatherConfMapper;
import com.fzzy.igds.mapper.WeatherInfoMapper;
import com.fzzy.igds.utils.ContextUtil;
import com.ruoyi.common.core.redis.RedisCache;
import com.ruoyi.common.utils.StringUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.time.DateFormatUtils;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
/**
 * @Description
 * @Author CZT
 * @Date 2026/01/09 11:55
 */
@Slf4j
@Service
public class WeatherService {
    @Resource
    private WeatherInfoMapper weatherInfoMapper;
    @Resource
    private WeatherConfMapper weatherConfMapper;
    @Resource
    private WeatherCityMapper weatherCityMapper;
    @Resource
    private RedisCache redisCache;
    /**
     * æŸ¥è¯¢é…ç½®ä¿¡æ¯
     *
     * @param companyId
     * @param deptId
     * @return
     */
    public List<WeatherConf> getConfData(String companyId, String deptId) {
        if (StringUtils.isEmpty(companyId)) {
            companyId = ContextUtil.getCompanyId();
        }
        if (StringUtils.isEmpty(deptId)) {
            deptId = ContextUtil.subDeptId(null);
        }
        QueryWrapper<WeatherConf> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("company_id", companyId);
        queryWrapper.eq("dept_id", deptId);
        return weatherConfMapper.selectList(queryWrapper);
    }
    /**
     * æŸ¥è¯¢é…ç½®ä¿¡æ¯
     *
     * @return
     */
    public List<WeatherConf> getConfData() {
        QueryWrapper<WeatherConf> queryWrapper = new QueryWrapper<>();
        return weatherConfMapper.selectList(queryWrapper);
    }
    /**
     * ä¿å­˜é…ç½®ä¿¡æ¯
     *
     * @param data
     * @return
     */
    public String saveConf(WeatherConf data) {
        if (StringUtils.isEmpty(data.getId())) {
            data.setId(ContextUtil.generateId());
            data.setCompanyId(ContextUtil.getCompanyId());
            data.setDeptId(ContextUtil.subDeptId(null));
        }
        if(StringUtils.isBlank(data.getCreateBy())){
            data.setCreateBy(ContextUtil.getLoginUserName());
            data.setCreateTime(new Date());
        }
        if(StringUtils.isBlank(data.getUpdateBy())){
            data.setUpdateBy(ContextUtil.getLoginUserName());
            data.setUpdateTime(new Date());
        }
        weatherConfMapper.insert(data);
        return null;
    }
    /**
     * åˆ é™¤é…ç½®ä¿¡æ¯
     *
     * @param data
     * @return
     */
    public String delConf(WeatherConf data) {
        weatherConfMapper.deleteById(data);
        return null;
    }
    /**
     * ä¿å­˜æ°”息信息
     *
     * @param data
     */
    private void addWeatherInfo(WeatherInfo data) {
        if(StringUtils.isBlank(data.getId())){
            data.setId(ContextUtil.UUID());
        }
        if(StringUtils.isBlank(data.getCreateBy())){
            data.setCreateBy(ContextUtil.getLoginUserName());
            data.setCreateTime(new Date());
        }
        if(StringUtils.isBlank(data.getUpdateBy())){
            data.setUpdateBy(ContextUtil.getLoginUserName());
            data.setUpdateTime(new Date());
        }
        weatherInfoMapper.insert(data);
    }
    /**
     * åˆ†é¡µæŸ¥è¯¢æ•°æ®
     * @param page
     * @param param
     */
    public void getInfoData(Page<WeatherInfo> page, Map<String, Object> param) {
        QueryWrapper<WeatherInfo> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("company_id", ContextUtil.getCompanyId());
        queryWrapper.eq("dept_id", ContextUtil.subDeptId(null));
        weatherInfoMapper.selectPage(page, queryWrapper);
    }
    /**
     * åˆ†é¡µæŸ¥è¯¢æ•°æ®
     * @param page
     * @param param
     */
    public void pageCity(Page<WeatherCity> page, Map<String, Object> param) {
        QueryWrapper<WeatherCity> queryWrapper = new QueryWrapper<>();
        weatherCityMapper.selectPage(page, queryWrapper);
    }
    /**
     * åˆ¤æ–­æ°”象信息是否需要保存
     *
     * @param weather
     */
    public void updateCacheAndSave(WeatherInfo weather) {
        if (null == weather.getCompanyId()) {
            weather.setCompanyId(ContextUtil.getCompanyId());
        }
        try {
            // æ›´æ–°ç¼“å­˜
            updateCacheWeather(weather);
            // åˆ¤æ–­æ˜¯ä¸æ˜¯éœ€è¦ä¿å­˜
            if (this.isSave(weather.getUpdateTime())) {
                addWeatherInfo(weather);
            }
        } catch (Exception e) {
            String msg = e.getMessage();
            if (msg.indexOf("PRIMARY") > 0) {
                log.error("持久化气象信息异常,主键冲突,请注意更新时间,出现异常是否合理");
            } else {
                log.error("更新保存气象信息异常:", e);
            }
        }
    }
    /**
     * æ ¹æ®ç»„织编码设置缓存
     *
     * @param weather
     */
    public void updateCacheWeather(WeatherInfo weather) {
        if (null == weather.getCompanyId()) {
            weather.setCompanyId(ContextUtil.getCompanyId());
        }
        String key = RedisConst.buildKey(weather.getCompanyId(), RedisConst.KEY_WEATHER_INFO);
        log.debug("气象信息更新到缓存中,info={}", weather.toString());
        redisCache.setCacheObject(key, weather);
    }
    /**
     * æ ¹æ®cityId设置缓存
     *
     * @param weather
     * @param cityId
     */
    public void setCacheWeatherByCityId(WeatherInfo weather, String cityId) {
        String key = RedisConst.buildKey(RedisConst.KEY_WEATHER_INFO, cityId);
        log.debug("气象信息更新到缓存中,info={}", weather.toString());
        redisCache.setCacheObject(key, weather, 60 * 30, TimeUnit.MICROSECONDS);
    }
    /**
     * æ ¹æ®cityId获取缓存信息
     *
     * @param cityId
     * @return
     */
    public WeatherInfo getCacheWeatherByCityId(String cityId) {
        String key = RedisConst.buildKey(RedisConst.KEY_WEATHER_INFO, cityId);
        WeatherInfo info = (WeatherInfo) redisCache.getCacheObject(key);
        if (null == info) {
            log.error("缓存中没有获取到气象信息!!");
        }
        return info;
    }
    /**
     * æ ¹æ®companyId获取缓存信息
     *
     * @param companyId
     * @return
     */
    public WeatherInfo getCacheWeather(String companyId) {
        String key = RedisConst
                .buildKey(companyId, RedisConst.KEY_WEATHER_INFO);
        WeatherInfo info = (WeatherInfo) redisCache.getCacheObject(key);
        if (null == info) {
            log.error("缓存中没有获取到气象信息!!");
        }
        return info;
    }
    /**
     * åˆ›å»ºè¿žæŽ¥
     *
     * @param address
     * @param port
     */
    public void onCreate(String address, Integer port) {
        log.debug("气象站自动连接通知暂不处理……");
    }
    /**
     * é”€æ¯é“¾æŽ¥
     *
     * @param address
     * @param port
     */
    public void onDestroy(String address, Integer port) {
        log.debug("气象站自动断开通知暂不处理……");
    }
    /**
     * åˆ¤æ–­å½“前气象信息是否需要持久化,默认系统只保存在上午8点 å’Œä¸‹åˆ3点的气象信。
     *
     * @param updateTime
     * @return
     */
    public static boolean isSave(Date updateTime) {
        String tag = DateFormatUtils.format(updateTime, "HHmm");
        String tag1 = "0800";
        String tag2 = "1500";
        if (tag.equals(tag1) || tag.equals(tag2)) {
            return true;
        }
        return false;
    }
}
fzzy-igdss-core/src/main/java/com/fzzy/igds/utils/ContextUtil.java
@@ -1,6 +1,7 @@
package com.fzzy.igds.utils;
import com.fzzy.igds.camera.data.ydqly.YdQlyNode;
import com.fzzy.igds.constant.GrainFrequence;
import com.ruoyi.common.config.FrameworkConfig;
import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.utils.ShiroUtils;
@@ -197,6 +198,34 @@
    }
    /**
     * æ ¹æ®ç³»ç»Ÿé…ç½®çš„æ‰¹æ¬¡é¢‘率获取批次编号
     *
     * @param freq
     * @return
     */
    public static String getBatchIdByFireq(String freq) {
        // ä¸€å¤©ä¸€æ¬¡
        if (GrainFrequence.FREQ_02.getCode().equals(freq)) {
            return DateFormatUtils.format(new Date(), "yyyyMMdd") + "1801";
        }
        // ä¸€å¤©ä¸¤æ¬¡
        if (GrainFrequence.FREQ_03.getCode().equals(freq)) {
            String hour = DateFormatUtils.format(new Date(), "HH");
            if (Integer.valueOf(hour) >= 0 && Integer.valueOf(hour) <= 12) {
                return DateFormatUtils.format(new Date(), "yyyyMMdd") + "1301";
            } else {
                return DateFormatUtils.format(new Date(), "yyyyMMdd") + "1802";
            }
        }
        return getDefaultBatchId();
    }
    public static String getDefaultBatchId() {
        return DateFormatUtils.format(new Date(), "yyyyMMddHHmm");
    }
    public static void main(String[] args) {
        for (int i = 0; i < 10; i++){
            String id = generateId();
fzzy-igdss-core/src/main/java/com/fzzy/igds/utils/SpringUtil.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,58 @@
package com.fzzy.igds.utils;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;
@Component
public class SpringUtil implements ApplicationContextAware {
    private static ApplicationContext applicationContext;
    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        if (SpringUtil.applicationContext == null) {
            SpringUtil.applicationContext = applicationContext;
        }
    }
    /**
     * èŽ·å–applicationContext
     * @return
     */
    public static ApplicationContext getApplicationContext() {
        return applicationContext;
    }
    /**
     * é€šè¿‡name获取 Bean.
     * @param name
     * @return
     */
    public static Object getBean(String name) {
        return getApplicationContext().getBean(name);
    }
    /**
     * é€šè¿‡class获取Bean.
     * @param clazz
     * @param <T>
     * @return
     */
    public static <T> T getBean(Class<T> clazz) {
        return getApplicationContext().getBean(clazz);
    }
    /**
     * é€šè¿‡name,以及Clazz返回指定的Bean
     * @param name
     * @param clazz
     * @param <T>
     * @return
     */
    public static <T> T getBean(String name, Class<T> clazz) {
        return getApplicationContext().getBean(name, clazz);
    }
}
fzzy-igdss-io/src/main/java/com/fzzy/igds/ServerRunner.java
@@ -1,5 +1,6 @@
package com.fzzy.igds;
import com.fzzy.igds.iot.server.IotServerEngine;
import com.fzzy.igds.quantity.server.BhznQuantityServerEngine;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
@@ -20,12 +21,18 @@
    public static final String BEAN_ID = "quantity.serverRunner";
    @Resource
    private BhznQuantityServerEngine serverEngine;
    private BhznQuantityServerEngine quantityServerEngine;
    @Resource
    private IotServerEngine iotServerEngine;
    @Override
    public void run(String... strings) throws Exception {
        serverEngine.start(BhznQuantityServerEngine.PORT);
        //数量检测端口
        quantityServerEngine.start(BhznQuantityServerEngine.PORT);
        //IOT设备端口
        iotServerEngine.start(IotServerEngine.PORT);
    }
}
fzzy-igdss-io/src/main/java/com/fzzy/igds/io/notify/NotifyGrainInvoker.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,57 @@
package com.fzzy.igds.io.notify;
import com.fzzy.igds.constant.OrderRespEnum;
import com.fzzy.igds.domain.Depot;
import com.fzzy.igds.domain.DepotConf;
import com.fzzy.igds.domain.Grain;
import com.fzzy.igds.request.ExeBaseRequest;
/**
 * @author Andy
 */
public interface NotifyGrainInvoker {
    /**
     * ç²®æƒ…解析成功后通知,系统开始执行保存判断等操作
     *
     * @param grain          è§£æžåŽçš„粮情信息
     * @param depotConf      ä»“库配置信息,不可为空
     * @return æ‰§è¡Œå¼‚常信息,正常返回NULL
     */
    String analysisSuccess(Grain grain, DepotConf depotConf, Depot depot, boolean isNotifyWeb, ExeBaseRequest request);
    /**
     * æ›´æ–°ç²®æƒ…,仅仅粮情信息
     *
     * @param grain
     * @param depot   ä»“库信息
     */
    String analysisSuccess(Grain grain, Depot depot);
    /**
     * æ›´æ–°ç²®æƒ…,仅仅粮情信息
     *
     * @param grain
     * @param request è¯·æ±‚命令信息
     */
    String analysisSuccess(Grain grain, Depot depot, ExeBaseRequest request);
    /**
     * æ›´æ–°ç²®æƒ…,仅仅粮情信息
     *
     * @param grain
     * @param request è¯·æ±‚命令信息
     */
    String analysisSuccess(Grain grain, Depot depot, ExeBaseRequest request, DepotConf depotConf);
    /**
     * ç›´æŽ¥é€šçŸ¥é¡µé¢
     *
     * @param companyId
     * @param orderResp
     * @param notifyMsg
     */
    void notifyWeb(String companyId, OrderRespEnum orderResp, String bizType, String notifyMsg);
}
fzzy-igdss-io/src/main/java/com/fzzy/igds/io/notify/NotifyGrainInvokerImpl.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,167 @@
package com.fzzy.igds.io.notify;
import com.fzzy.igds.constant.GrainFrequence;
import com.fzzy.igds.constant.OrderRespEnum;
import com.fzzy.igds.domain.Depot;
import com.fzzy.igds.domain.DepotConf;
import com.fzzy.igds.domain.Grain;
import com.fzzy.igds.domain.WeatherInfo;
import com.fzzy.igds.io.order.ExeOrderService;
import com.fzzy.igds.request.ExeBaseRequest;
import com.fzzy.igds.service.GrainService;
import com.fzzy.igds.service.WeatherService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
@Slf4j
@Component
public class NotifyGrainInvokerImpl extends NotifyWebParent implements NotifyGrainInvoker {
    @Resource
    private GrainService grainService;
    @Resource
    private ExeOrderService exeRequestService;
    @Resource
    private WeatherService weatherService;
    @Override
    public String analysisSuccess(Grain grain, DepotConf depotConf, Depot depot, boolean isNotifyWeb, ExeBaseRequest exeRequest) {
        grain = addWeatherInfo(grain);
        try {
            // å¦‚果是一日多次
            if (null == depotConf) {
                grainService.saveOrUpdateGrain(grain, null);
            } else {
                if (depotConf.getGrainFreq().equals(
                        GrainFrequence.FREQ_01.getCode())) {
                    grainService.saveOrUpdateGrain(grain, null);
                } else {
                    grainService.saveOrUpdateGrain(grain, null);
                }
            }
            String notifyMsg = depot.getName() + " ç²®æƒ…采集并解析成功,批次号=" + grain.getBatchId();
            //完成
            exeRequest.setExeMsg(notifyMsg);
            exeRequestService.completeCache(exeRequest, false);
            notifyWeb(depotConf.getCompanyId(), OrderRespEnum.MSG_SUCCESS, "grain", notifyMsg);
            log.info(depot.getName() + "粮情解析成功:" + grain.getBatchId());
        } catch (Exception e) {
            String notifyMsg = depot.getName() + "-保存失败,请勿2分钟内重复采集";
            //完成
            exeRequest.setErrorMsg(notifyMsg);
            exeRequestService.completeCache(exeRequest, false);
            notifyWeb(depotConf.getCompanyId(), OrderRespEnum.MSG_ERROR, "grain", notifyMsg);
            log.error(depot.getName() + "粮情解析保存失败:" + e);
        }
        return null;
    }
    @Override
    public String analysisSuccess(Grain grain, Depot depot) {
        grain = addWeatherInfo(grain);
        try {
            grainService.saveOrUpdateGrain(grain,null);
            String notifyMsg = depot.getName() + " æ”¶åˆ°æŽ¨é€ç²®æƒ…信息并解析成功,批次号=" + grain.getBatchId();
            notifyWeb(grain.getCompanyId(), OrderRespEnum.MSG_SUCCESS, "grain", notifyMsg);
        } catch (Exception e) {
            String notifyMsg = depot.getName() + "-保存失败,请勿2分钟内重复采集";
            this.notifyWeb(grain.getCompanyId(), OrderRespEnum.MSG_ERROR, "grain", notifyMsg);
            log.error("粮情解析保存失败:" + e);
            return notifyMsg;
        }
        return null;
    }
    @Override
    public String analysisSuccess(Grain grain, Depot depot, ExeBaseRequest exeRequest) {
        grain = addWeatherInfo(grain);
        try {
            grainService.saveOrUpdateGrain(grain,null);
            String notifyMsg = exeRequest.getDepotName() + " ç²®æƒ…采集并解析成功,批次号=" + grain.getBatchId();
            //完成
            exeRequest.setExeMsg(notifyMsg);
            exeRequestService.completeCache(exeRequest, false);
        } catch (Exception e) {
            String notifyMsg = exeRequest.getDepotName() + "-保存失败,请勿2分钟内重复采集";
            //完成
            exeRequest.setErrorMsg(notifyMsg);
            exeRequestService.completeCache(exeRequest, false);
            return notifyMsg;
        }
        return null;
    }
    @Override
    public String analysisSuccess(Grain grain, Depot depot, ExeBaseRequest exeRequest, DepotConf depotConf) {
        grain = addWeatherInfo(grain);
        try {
            grainService.saveOrUpdateGrain(grain,null);
            String notifyMsg = exeRequest.getDepotName() + " ç²®æƒ…采集并解析成功,批次号=" + grain.getBatchId();
            //完成
            exeRequest.setExeMsg(notifyMsg);
            exeRequestService.completeCache(exeRequest, false);
            notifyWeb(depotConf.getCompanyId(), OrderRespEnum.MSG_SUCCESS, "grain", notifyMsg);
            log.info(depot.getName() + "粮情解析成功:" + grain.getBatchId());
        } catch (Exception e) {
            String notifyMsg = exeRequest.getDepotName() + "-保存失败,请勿2分钟内重复采集";
            //完成
            exeRequest.setErrorMsg(notifyMsg);
            exeRequestService.completeCache(exeRequest, false);
            notifyWeb(depotConf.getCompanyId(), OrderRespEnum.MSG_ERROR, "grain", notifyMsg);
            log.error(depot.getName() + "粮情解析保存失败:" + e);
            return notifyMsg;
        }
        return null;
    }
    // ä»Žç¼“存中获取当前的外温度外部湿度
    private Grain addWeatherInfo(Grain grain) {
        if(grain.getHumidityOut() != null && grain.getTempOut() != null){
            return grain;
        }
        WeatherInfo weatherInfo = weatherService.getCacheWeather(grain.getCompanyId());
        Double tOut = -100.0, hOut = -100.0;
        if (null != weatherInfo) {
            if (weatherInfo.getTemp().indexOf("℃") > 0) {
                weatherInfo.setTemp(weatherInfo.getTemp().replace("℃", ""));
            }
            if (weatherInfo.getHumidity().indexOf("%") > 0) {
                weatherInfo.setHumidity(weatherInfo.getHumidity().replace("%",
                        ""));
            }
            tOut = Double.valueOf(weatherInfo.getTemp());
            hOut = Double.valueOf(weatherInfo.getHumidity());
            grain.setWeather(weatherInfo.getWeather());
        }
        if(grain.getHumidityOut() == null || grain.getHumidityOut() == 0.0){
            grain.setHumidityOut(hOut);
        }
        if(grain.getTempOut() == null || grain.getTempOut() == 0.0){
            grain.setTempOut(tOut);
        }
        return grain;
    }
}
fzzy-igdss-io/src/main/java/com/fzzy/igds/io/notify/NotifyWebInvoker.java
ÎļþÃû´Ó fzzy-igdss-core/src/main/java/com/fzzy/igds/notify/NotifyWebInvoker.java ÐÞ¸Ä
@@ -1,4 +1,4 @@
package com.fzzy.igds.notify;
package com.fzzy.igds.io.notify;
import com.fzzy.igds.constant.OrderRespEnum;
import com.fzzy.igds.data.QuantityProgressData;
fzzy-igdss-io/src/main/java/com/fzzy/igds/io/notify/NotifyWebInvokerImpl.java
ÎļþÃû´Ó fzzy-igdss-core/src/main/java/com/fzzy/igds/notify/NotifyWebInvokerImpl.java ÐÞ¸Ä
@@ -1,4 +1,4 @@
package com.fzzy.igds.notify;
package com.fzzy.igds.io.notify;
import com.fzzy.igds.constant.OrderRespEnum;
import com.fzzy.igds.data.QuantityProgressData;
fzzy-igdss-io/src/main/java/com/fzzy/igds/io/notify/NotifyWebParent.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,20 @@
package com.fzzy.igds.io.notify;
import com.fzzy.igds.constant.OrderRespEnum;
import com.fzzy.igds.websocket.WebSocketPacket;
import com.fzzy.igds.websocket.WebSocketServer;
public class NotifyWebParent {
    public void notifyWeb(String companyId, OrderRespEnum orderResp,
            String bizType, String notifyMsg) {
        // é€šçŸ¥å‰ç«¯
        WebSocketPacket packet = new WebSocketPacket();
        packet.setBizType(bizType);
        packet.setCompanyId(companyId);
        packet.setOrderResp(orderResp.getCode());
        packet.setData(notifyMsg);
        WebSocketServer.sendByPocket(packet);
    }
}
fzzy-igdss-io/src/main/java/com/fzzy/igds/io/notify/ServerNotifyInvoker.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,39 @@
package com.fzzy.igds.io.notify;
import com.fzzy.igds.domain.DeviceSer;
/**
 * æœåŠ¡é€šçŸ¥ç¨‹åºè°ƒç”¨ï¼Œç”¨äºŽé€šçŸ¥åˆ†æœºä¸Šçº¿å’Œç¦»çº¿å¤„ç†
 * @author Andy
 *
 */
public interface ServerNotifyInvoker {
    public static final String BEAN_ID = "serverNotifyInvoker";
    /**
     * è¿žæŽ¥è¢«é”€æ¯åŽé€šçŸ¥ä¿¡æ¯
     * @param businessKey TCP业务KEY
     * @param ip è®¾å¤‡IP
     * @param port è®¾å¤‡ç«¯å£å·
     */
    void connectDestory(String businessKey, String ip, Integer port);
    /**
     * è¿žæŽ¥è¢«æ¿€æ´»çš„通知
     * @param businessKey TCP业务KEY
     * @param address è®¾å¤‡IP
     * @param port è®¾å¤‡ç«¯å£å·
     */
    void connectActive(String businessKey, String address, Integer port);
    /**
     * æ ¹æ®ä¿¡æ¯èŽ·å–æŽ§åˆ¶æŸœä¿¡æ¯
     * @param companyId
     * @param address
     * @param port
     * @return
     */
    DeviceSer getDeviceSer(String companyId, String address, Integer port);
}
fzzy-igdss-io/src/main/java/com/fzzy/igds/iot/analysis/AnalysisService.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,265 @@
package com.fzzy.igds.iot.analysis;
import com.fzzy.igds.constant.Constant;
import com.fzzy.igds.constant.OrderRespEnum;
import com.fzzy.igds.constant.RedisConst;
import com.fzzy.igds.data.GrainData;
import com.fzzy.igds.domain.*;
import com.fzzy.igds.io.notify.NotifyGrainInvoker;
import com.fzzy.igds.iot.analysis.builder.ReMessageBuilder;
import com.fzzy.igds.iot.analysis.message.DeviceAttr;
import com.fzzy.igds.iot.analysis.message.DeviceAttrInfo;
import com.fzzy.igds.io.notify.NotifyWebInvoker;
import com.fzzy.igds.service.*;
import com.fzzy.igds.utils.ContextUtil;
import com.ruoyi.common.core.redis.RedisCache;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
import java.util.Date;
import java.util.List;
/**
 * @Description è§£æžå…¥å£
 * @Author CZT
 * @Date 2025/11/11 18:20
 */
@Slf4j
@Component(AnalysisService.BEAN_ID)
public class AnalysisService {
    public static final String BEAN_ID = "iot.analysisService";
    @Resource
    private DeviceSerService deviceSerService;
    @Resource
    private DeviceIotService deviceIotService;
    @Autowired
    private DepotService depotService;
    @Autowired
    private NotifyWebInvoker notifyWebInvoker;
    @Autowired
    private DepotConfService depotConfService;
    @Autowired
    private NotifyGrainInvoker notifyGrainInvoker;
    @Resource
    private QuantityService quantityService;
    @Resource
    private RedisCache redisCache;
    /**
     * @param sessionKey ip:port
     * @param msg
     */
    public void analysis(String sessionKey, String msg) throws Exception {
        String[] attr = sessionKey.split(":");
        String ip = attr[0];
        Integer port = Integer.valueOf(attr[1]);
        DeviceAttr reMessage = ReMessageBuilder.getInstance().buildMessage( ip, port, msg);
        if (null == reMessage || null == reMessage.getOrgId()) {
            log.error("IOT网关----->>>平台:返回信息没有获取组织编码信息,无法继续解析----{}", sessionKey);
            return;
        }
        DeviceSer ser = deviceSerService.getCacheSerBySn(reMessage.getOrgId(),reMessage.getSn());
        if (null == ser) {
            String info = "IOT网关=" + reMessage.getDeviceId() + "返回信息没有匹配到分机,忽略消息。";
            log.error("IOT网关----->>>平台:" + info);
            notifyWebInvoker.notifyWeb(reMessage.getOrgId(), OrderRespEnum.MSG_ERROR,"SYS", info);
            // æ¸…除缓存并销毁链接
            return;
        }
        //更新分机状态
        ser.setIp(ip);
        ser.setPort(port);
        ser.setStatus(Constant.YN_Y);
        deviceSerService.updateByData(ser);
        log.debug("IOT网关----->>>平台:所属组织-{},分机-{} è¿”回的命令信息={}", ser.getCompanyId(), ser.getName(), reMessage.toString());
        List<DeviceIot> deviceIots = deviceIotService.getCacheDeviceIotBySerId(ser.getCompanyId(),ser.getId());
        if(deviceIots == null || deviceIots.size() <= 0){
            log.error("IOT网关----->>>平台:" + "没有获取到分机下面有设备!");
            return ;
        }
        DeviceIot deviceIot = deviceIots.stream().filter(item -> (item.getPassCode()+"").equals(reMessage.getDeviceId())).findAny().orElse(null);
        if(deviceIot == null ){
            log.error("IOT网关----->>>平台:" + "没有获取到设备单个!");
            return ;
        }
        log.info("IOT网关----->>>平台:"+ "开始解析数据" + reMessage.toString());
        if(StringUtils.isEmpty(reMessage.getType())){
            //液位解析
            analysisHeight(reMessage, ser,deviceIot);
        }
        if("2".equals(reMessage.getType()) || "02".equals(reMessage.getType())){
            //油温解析
            analysisOilGrain(reMessage, ser,deviceIot);
        }else {
            //液位解析
            analysisHeight(reMessage, ser,deviceIot);
        }
    }
    /**
     * ç½‘管油情解析
     * @param deviceAttr
     * @param ser
     */
    public void analysisOilGrain(DeviceAttr deviceAttr, DeviceSer ser, DeviceIot deviceIot) {
        try {
            log.info("IOT网关----->>>平台:"+ "开始解析温度数据" + deviceAttr.toString());
            List<DeviceAttrInfo> list = deviceAttr.getTerminalAttrInfoList();
            if(null ==  list || list.isEmpty()){
                log.error("IOT网关----->>>平台:" + "油情数据为空,不解析!");
                return;
            }
            Integer ceng = 0;
            String points = "";
            Double max = null, min = null, sumT = 0.0;
            Double temp = 0.0;
            for (DeviceAttrInfo iotInfo : list) {
                if("1".equals(iotInfo.getPasscode()) || "2".equals(iotInfo.getPasscode())){
                    //通道号为1或者2时,是通信状态和告警状态,不解析
                    continue;
                }
                points += iotInfo.getValue() + ",";
                ceng ++;
                temp = Double.valueOf(iotInfo.getValue());
                if(null == max){
                    max = temp;
                }
                if(null == min){
                    min = temp;
                }
                if (temp > max) {
                    max = temp;
                }
                if (temp < min) {
                    min = temp;
                }
                sumT += temp;
            }
            DepotConf depotConf = depotConfService.getCacheDepotConfByDepotId(ser.getCompanyId(), deviceIot.getDepotId());
            Depot depot = depotService.getCacheDepot(ser.getCompanyId(), deviceIot.getDepotId());
            Grain grain = new Grain();
            grain.setBatchId(ContextUtil.getBatchIdByFireq(depotConf.getGrainFreq()));
            grain.setReceiveDate(new Date());
            grain.setCable("1");
            grain.setCableCir(ceng + "");
            grain.setPoints(points);
            grain.setCheckUser("系统");
            grain.setDepotId(deviceIot.getDepotId());
            grain.setCompanyId(depotConf.getCompanyId());
            grain.setHumidityIn(-100.0);
            grain.setTempIn(-100.0);
            grain.setTempAve(sumT/ceng);
            grain.setTempMax(max);
            grain.setTempMin(min);
            grain.setDeptId(depot.getDeptId());
            //油罐 æ¶²ä½é«˜åº¦ï¼Œæœ‰å°±èµ‹å€¼
            GrainData data = (GrainData) redisCache.getCacheObject(RedisConst.buildKey(ser.getCompanyId(),RedisConst.KEY_DEPOT_HEIGHT,grain.getDepotId()));
            if(data!= null && StringUtils.isNotEmpty(data.getOilHeight())){
                grain.setOilHeight(data.getOilHeight());
            }
            // ç”¨æˆ·å°è£…好数据即可
            notifyGrainInvoker.analysisSuccess(grain, depot);
            log.info("IOT网关----->>>平台:油温解析完成:" + data);
        } catch (Exception e) {
            log.error(e.getMessage(), e);
        }
    }
    /**
     * ç½‘管液位高度解析
     * @param deviceAttr
     * @param ser
     */
    public void analysisHeight(DeviceAttr deviceAttr, DeviceSer ser, DeviceIot deviceIot) {
        try {
            Depot depot = depotService.getCacheDepot(ser.getCompanyId(), deviceIot.getDepotId());
            if(null == depot){
                log.error("IOT网关----->>>平台:" + "未获取仓库信息,不解析!");
                return;
            }
            List<DeviceAttrInfo> list = deviceAttr.getTerminalAttrInfoList();
            if(null ==  list || list.isEmpty()){
                log.error("IOT网关----->>>平台:" + "油情数据为空,不解析!");
                return;
            }
            Double diameter = 0.0;   //直径
            Double volume = 0.0;     //体积
            Double bulkWeight = 0.0; //容重
            Double realHeight = 0.0; //页面高度
            Double maxHeight = 0.0;  //最大高度
            Double storage = 0.0;    //计算储量
            Double heightPer = 0.0;    //高度百分比
            if(null != depot.getHeight()){
                maxHeight = depot.getHeight();
            }
            if(null != depot.getLength()){
                diameter = depot.getLength();
            }
            if(null != depot.getBulkWeight()){
                bulkWeight = depot.getBulkWeight();
            }
            //解析真实高度
            realHeight = Double.valueOf(list.get(2).getValue());
            //计算体积
            volume = 3.14159 * Math.pow(diameter / 2, 2) * realHeight;
            //判断体积是否为负,为负值则不计算,重置为0
            if (volume < 0) {
                volume = 0.0;
            }
            //计算重量
            storage = volume * bulkWeight;
            storage = Double.valueOf(String.format("%.2f", storage));
            //高度百分比
            if(maxHeight > 0){
                heightPer = Double.valueOf(String.format("%.2f", realHeight/maxHeight * 100));
            }
            Quantity data = new Quantity();
            data.setBatchId(depot + ContextUtil.generateId());
            data.setCompanyId(ser.getCompanyId());
            data.setDeptId(depot.getDeptId());
            data.setDepotId(deviceIot.getDepotId());
            data.setDiameter(depot.getLength());
            data.setHeightPer(heightPer);
            data.setHeight(realHeight);
            data.setBulk(volume);
            data.setWeight(storage);
            data.setReceiveDate(new Date());
            data.setCheckUser("系统");
            quantityService.saveData( data);
            log.info("高度解析完成:" + data);
        } catch (Exception e) {
            log.error(e.getMessage(), e);
        }
    }
}
fzzy-igdss-io/src/main/java/com/fzzy/igds/iot/analysis/builder/ReMessageBuilder.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,72 @@
package com.fzzy.igds.iot.analysis.builder;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.fzzy.igds.iot.analysis.message.DeviceAttr;
import com.fzzy.igds.iot.analysis.message.DeviceAttrInfo;
import com.fzzy.igds.iot.analysis.message.IoMessage;
import java.util.ArrayList;
import java.util.List;
/**
 * @Description  æ ¹æ®æŽ¥æ”¶åˆ°çš„信息进行封装
 * @Author CZT
 * @Date 2025/11/11 18:15
 */
public class ReMessageBuilder {
    public static final String CHARSET = "UTF-8";
    public static final String PREFIX = "<FZZY>";
    public static final String SUFFIX = "<EEEE>";
    public  final static  String ERROR_TAG = "null";
    public  final static  String ERROR_STR = "#";
    private final static ReMessageBuilder instance = new ReMessageBuilder();
    private ReMessageBuilder() {
    }
    public static ReMessageBuilder getInstance() {
        return instance;
    }
    /**
     * @param ip
     * @param port
     * @param message
     * @return
     */
    public DeviceAttr buildMessage( String ip, int port, String message) throws Exception {
        IoMessage ioMessage = JSON.parseObject(message, IoMessage.class);
        JSONArray passCodeArray = JSON.parseArray(ioMessage.getContent());
        if (passCodeArray == null || passCodeArray .size() == 0) {
            return null;
        }
        List<DeviceAttrInfo> terminalAttrInfoList = new ArrayList<>();
        JSONObject passCode = null;
        for(int i = 0; i< passCodeArray.size(); i++ ){
            passCode = passCodeArray.getJSONObject(i);
            if(passCode == null){
                continue;
            }
            DeviceAttrInfo terminalAttrInfo = new DeviceAttrInfo();
            terminalAttrInfo.setPasscode(passCode.getString("passcode"));
            terminalAttrInfo.setTime(ioMessage.getTime());
            String value = passCode.getString("value");
            // null å€¼æ›¿æ¢ä¸º#号
            if(ERROR_TAG.equals(value))value = ERROR_STR;
            terminalAttrInfo.setValue(value);
            terminalAttrInfoList.add(terminalAttrInfo);
        }
        DeviceAttr request = new DeviceAttr();
        request.setSn(ioMessage.getSn());
        request.setOrderId(ioMessage.getOrderId());
        request.setOrgId(ioMessage.getOrgId());
        request.setGroupId(ioMessage.getGroupId());
        request.setGatewayId(ioMessage.getIedId());
        request.setDeviceId(ioMessage.getDeviceId());
        request.setTerminalAttrInfoList(terminalAttrInfoList);
        request.setType(ioMessage.getType());
        return request;
    }
}
fzzy-igdss-io/src/main/java/com/fzzy/igds/iot/analysis/message/DeviceAttr.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,26 @@
package com.fzzy.igds.iot.analysis.message;
import lombok.Data;
import lombok.EqualsAndHashCode;
import java.util.List;
/**
 * @Description è¿œç¨‹æ›´æ–°ç»ˆç«¯è®¾å¤‡çš„属性值,写入和控制使用
 * @Author CZT
 * @Date 2025/11/11 18:12
 */
@Data
@EqualsAndHashCode(callSuper = false)
public class DeviceAttr {
    private String orderId;// è®¢å•号,客户端保证唯一
    private String orgId;//所属组织
    private String groupId;//所属分组
    private String gatewayId;//网关一标识
    private String sn;
    private String deviceId;// ç»ˆç«¯ç¼–号
    private String type;// ç±»åž‹:01-液位高度,02-温度信息
    private List<DeviceAttrInfo> terminalAttrInfoList;
    private DeviceAttrInfo deviceAttrInfo;
}
fzzy-igdss-io/src/main/java/com/fzzy/igds/iot/analysis/message/DeviceAttrInfo.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,16 @@
package com.fzzy.igds.iot.analysis.message;
import lombok.Data;
/**
 * @Description ç»ˆç«¯è®¾å¤‡çš„属性信息
 * @Author CZT
 * @Date 2025/11/11 18:09
 */
@Data
public class DeviceAttrInfo {
    private String name;//通道名称,即属性名称
    private String passcode;//通道编码,即属性编码
    private String value;//属性值
    private String time;//时间 ç”¨æ¥æ ‡è¯†å±žæ€§æ˜¯å¦äº§ç”Ÿäº†å˜åŒ–
}
fzzy-igdss-io/src/main/java/com/fzzy/igds/iot/analysis/message/IoMessage.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,30 @@
package com.fzzy.igds.iot.analysis.message;
import lombok.Data;
/**
 * @Description ç»ˆç«¯è®¾å¤‡çš„属性信息
 * @Author CZT
 * @Date 2025/11/11 18:09
 */
@Data
public class IoMessage {
    private String orgId;
    private String groupId;
    private String iedId;
    private String functionId;
    private String deviceId;
    private String result;
    private String orderId;
    private String time;
    private String signHeader;
    private String len;
    private String content;
    private String signBody;
    private String file;//附件
    private byte[] fileBytes;
    private String sn;
    private String type;
    //2021å¹´6月11日 12:13:00 æ·»åŠ 
    private String sessionId;
}
fzzy-igdss-io/src/main/java/com/fzzy/igds/iot/server/IotMessageConsumer.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,42 @@
package com.fzzy.igds.iot.server;
import com.fzzy.igds.iot.analysis.AnalysisService;
import com.fzzy.igds.iot.analysis.builder.ReMessageBuilder;
import com.ld.io.api.IoMsgConsumer;
import com.ld.io.api.IoSession;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
/**
 * @Description  FZZT-IOT æ¶ˆæ¯æŽ¥æ”¶ç±»
 * @Author CZT
 * @Date 2025/11/11 18:17
 */
@Service
@Slf4j
public class IotMessageConsumer implements IoMsgConsumer {
    @Autowired
    private AnalysisService analysisService;
    /**
     * é˜Ÿåˆ—里面处理消息
     * @param ioSession
     * @param bytes
     */
    public void consume(IoSession ioSession, byte[] bytes) {
        if (null == bytes) {
            log.error("Reply bytes is null");
            return;
        }
        try {
            String message = new String(bytes, ReMessageBuilder.CHARSET);
            message = message.substring(ReMessageBuilder.PREFIX.length());
            log.info("收到IOT网关消息:" + message);
            analysisService.analysis(ioSession.getBusinessKey(),message);
        }catch (Exception e){
            log.error(e.getMessage(),e);
        }
    }
}
fzzy-igdss-io/src/main/java/com/fzzy/igds/iot/server/IotServerEngine.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,69 @@
package com.fzzy.igds.iot.server;
import com.fzzy.igds.iot.analysis.builder.ReMessageBuilder;
import com.ld.io.api.IoServerOption;
import com.ld.io.api.IoSession;
import com.ld.io.api.IoSessionQuery;
import com.ld.io.netty.NettyServer;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
/**
 * @Description  FZZT-IOT æœåŠ¡å¯åŠ¨ç±»
 * @Author CZT
 * @Date 2025/11/11 18:09
 */
@Slf4j
@Service
public class IotServerEngine {
    public static final Integer PORT = 9302;
    @Autowired
    private IotMessageConsumer defaultMessageConsumer;
    @Autowired
    private IotSessionListener defaultSessionListener;
    private IoSessionQuery sessionQuery;
    public void start(Integer port) {
        IoServerOption ioServerOption = new IoServerOption();
        if (null != port) {
            ioServerOption.setPort(port);
        } else {
            ioServerOption.setPort(PORT);
        }
        ioServerOption.setDelimiter(ReMessageBuilder.SUFFIX.getBytes());
        NettyServer ioServer = new NettyServer(ioServerOption, defaultMessageConsumer, defaultSessionListener);
        ioServer.startup();
        sessionQuery = ioServer.getSessionQuery();
        log.info("* ");
        log.info("* ========================");
        log.info("* ");
        log.info("* [SERVER:FZZY_IOT,PORT={}]", PORT);
        log.info("* ");
        log.info("* ========================");
        log.info("* ");
        System.out.println("* ========================");
        System.out.println("* ");
        System.out.println("* [SERVER:FZZY_IOT,PORT={}]" + port);
        System.out.println("* ");
        System.out.println("* ========================");
    }
    public IoSessionQuery getSessionQuery() {
        return sessionQuery;
    }
    public IoSession getSessionById(String sessionId) {
        return this.getSessionQuery().getSession(sessionId);
    }
}
fzzy-igdss-io/src/main/java/com/fzzy/igds/iot/server/IotSessionListener.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,40 @@
package com.fzzy.igds.iot.server;
import com.fzzy.igds.io.notify.ServerNotifyInvoker;
import com.fzzy.igds.utils.SpringUtil;
import com.ld.io.api.IoSession;
import com.ld.io.api.IoSessionListener;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
/**
 * @Description
 * @Author CZT
 * @Date 2025/11/11 18:09
 */
@Slf4j
@Service
public class IotSessionListener implements IoSessionListener {
    private ServerNotifyInvoker serverNotifyInvoker;
    @Override
    public void onCreate(IoSession session) {
        log.info("++++新建连接++++-IP={},PORT={}", session.getAddress(), session.getPort());
        // æ·»åŠ è‡ªå®šä¹‰ä¸šåŠ¡ID
        session.setBusinessKey(ServerUtils.getServerKey(session.getAddress(), session.getPort()));
    }
    @Override
    public void onDestroy(IoSession session) {
        log.info("----连接断开-----IP={},PORT={}", session.getAddress(), session.getPort());
        if (null == serverNotifyInvoker) {
            serverNotifyInvoker = SpringUtil.getBean(ServerNotifyInvoker.class);
        }
        serverNotifyInvoker.connectDestory(session.getBusinessKey(),
                session.getAddress(), session.getPort());
    }
}
fzzy-igdss-io/src/main/java/com/fzzy/igds/iot/server/ServerUtils.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,23 @@
package com.fzzy.igds.iot.server;
/**
 * @Description å·¥å…·ç±»
 * @Author CZT
 * @Date 2025/11/11 18:07
 */
public class ServerUtils {
    /**
     * ç”ŸæˆTCP连接的KEY
     *
     * @param ip
     * @param port
     * @return
     */
    public static String getServerKey(String ip, Integer port) {
        return ip + ":" + port;
    }
}
fzzy-igdss-io/src/main/java/com/fzzy/igds/quantity/analysis/AnalysisService.java
@@ -7,7 +7,7 @@
import com.fzzy.igds.domain.FileInfo;
import com.fzzy.igds.domain.Quantity;
import com.fzzy.igds.domain.QuantityConf;
import com.fzzy.igds.notify.NotifyWebInvoker;
import com.fzzy.igds.io.notify.NotifyWebInvoker;
import com.fzzy.igds.quantity.command.BhznRemoteQuantityImpl;
import com.fzzy.igds.quantity.command.CommandBuilder;
import com.fzzy.igds.quantity.dto.IoMessage;
@@ -224,6 +224,7 @@
        quantityData.setDeptId(depot.getDeptId());
        quantityData.setCompanyId(depot.getCompanyId());
        quantityData.setPoints("");
        quantityData.setCheckUser(request.getExeUser());
        quantityService.saveData(quantityData);
        //直接返回
        remoteQuantity.sendMsg(ip, port, CommandBuilder.getInstance().build2004Message(message));
fzzy-igdss-io/src/main/java/com/fzzy/igds/quantity/command/BhznRemoteQuantityImpl.java
@@ -3,7 +3,7 @@
import com.fzzy.igds.constant.OrderRespEnum;
import com.fzzy.igds.constant.ProtocolEnum;
import com.fzzy.igds.io.service.RemoteQuantityService;
import com.fzzy.igds.notify.NotifyWebInvoker;
import com.fzzy.igds.io.notify.NotifyWebInvoker;
import com.fzzy.igds.quantity.dto.IoMessage;
import com.fzzy.igds.quantity.server.BhznQuantityServerEngine;
import com.fzzy.igds.quantity.util.ServerUtils;
fzzy-igdss-view/src/main/java/com/fzzy/igds/Depot.view.xml
@@ -348,7 +348,7 @@
          </Children>
        </FieldSet>
        <FieldSet layout="padding:5">
          <Property name="caption">质检信息</Property>
          <Property name="caption">其他信息</Property>
          <Buttons/>
          <Children>
            <AutoForm>
@@ -357,7 +357,27 @@
              <Property name="labelSeparator"> : </Property>
              <Property name="labelAlign">right</Property>
              <Property name="cols">*,*,*,*,*,*,*,*</Property>
              <Property name="labelWidth">80</Property>
              <Property name="labelWidth">100</Property>
              <AutoFormElement layoutConstraint="colSpan:2">
                <Property name="name">length</Property>
                <Property name="property">length</Property>
                <Editor/>
              </AutoFormElement>
              <AutoFormElement layoutConstraint="colSpan:2">
                <Property name="name">width</Property>
                <Property name="property">width</Property>
                <Editor/>
              </AutoFormElement>
              <AutoFormElement layoutConstraint="colSpan:2">
                <Property name="name">height</Property>
                <Property name="property">height</Property>
                <Editor/>
              </AutoFormElement>
              <AutoFormElement layoutConstraint="colSpan:2">
                <Property name="name">bulkWeight</Property>
                <Property name="property">bulkWeight</Property>
                <Editor/>
              </AutoFormElement>
              <AutoFormElement layoutConstraint="colSpan:2">
                <Property name="name">perWet</Property>
                <Property name="property">perWet</Property>
@@ -366,11 +386,6 @@
              <AutoFormElement layoutConstraint="colSpan:2">
                <Property name="name">perImpurity</Property>
                <Property name="property">perImpurity</Property>
                <Editor/>
              </AutoFormElement>
              <AutoFormElement layoutConstraint="colSpan:2">
                <Property name="name">bulkWeight</Property>
                <Property name="property">bulkWeight</Property>
                <Editor/>
              </AutoFormElement>
              <AutoFormElement layoutConstraint="colSpan:2">
fzzy-igdss-view/src/main/java/com/fzzy/igds/DepotConf.view.xml
@@ -262,21 +262,6 @@
                <Editor/>
              </AutoFormElement>
              <AutoFormElement>
                <Property name="property">diameter</Property>
                <Property name="name">diameter</Property>
                <Editor/>
              </AutoFormElement>
              <AutoFormElement>
                <Property name="property">height</Property>
                <Property name="name">height</Property>
                <Editor/>
              </AutoFormElement>
              <AutoFormElement>
                <Property name="name">updateBy</Property>
                <Property name="property">updateBy</Property>
                <Editor/>
              </AutoFormElement>
              <AutoFormElement>
                <Property name="name">grainFreq</Property>
                <Property name="property">grainFreq</Property>
                <Editor/>
fzzy-igdss-view/src/main/java/com/fzzy/igds/DeviceIot.view.xml
@@ -170,7 +170,7 @@
      <ClientEvent name="onHide">view.id(&quot;dsDeviceIot&quot;).getData().cancel();</ClientEvent>
      <Property name="iconClass">fa fa-tasks</Property>
      <Property name="caption">设备信息</Property>
      <Property name="width">35%</Property>
      <Property name="width">60%</Property>
      <Buttons>
        <Button>
          <Property name="action">actionDeviceIotSave</Property>
fzzy-igdss-view/src/main/java/models/core.model.xml
@@ -302,7 +302,22 @@
    <PropertyDef name="bulkWeight">
      <Property name="dataType">Double</Property>
      <Property name="label">容重</Property>
      <Property name="displayFormat">0.0 g/L</Property>
      <Property name="displayFormat">#0.00 g/L</Property>
    </PropertyDef>
    <PropertyDef name="length">
      <Property name="dataType">Double</Property>
      <Property name="label">长度/直径</Property>
      <Property name="displayFormat">#0.00 ç±³</Property>
    </PropertyDef>
    <PropertyDef name="width">
      <Property name="dataType">Double</Property>
      <Property name="label">宽度</Property>
      <Property name="displayFormat">#0.00 ç±³</Property>
    </PropertyDef>
    <PropertyDef name="height">
      <Property name="dataType">Double</Property>
      <Property name="label">高度</Property>
      <Property name="displayFormat">#0.00 ç±³</Property>
    </PropertyDef>
    <PropertyDef name="storeKeeper">
      <Property></Property>
@@ -878,16 +893,6 @@
    <PropertyDef name="startRow">
      <Property name="dataType">Integer</Property>
      <Property name="label">起始根号</Property>
    </PropertyDef>
    <PropertyDef name="diameter">
      <Property name="dataType">Double</Property>
      <Property name="label">筒仓直径</Property>
      <Property name="displayFormat">#0.00 ç±³</Property>
    </PropertyDef>
    <PropertyDef name="height">
      <Property name="dataType">Double</Property>
      <Property name="label">筒仓高度</Property>
      <Property name="displayFormat">#0.00 ç±³</Property>
    </PropertyDef>
    <PropertyDef name="grainAuto">
      <Property></Property>