wangfei
2024-10-12 00f0f705a03a9c0f4d29895a7622b270f5d7e7d2
Merge branch 'master' of http://10.153.19.25:10101/r/HangZhouMes
5个文件已修改
24个文件已添加
33个文件已删除
3642 ■■■■ 已修改文件
UI-Project/src/lang/en.js 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
UI-Project/src/lang/zh.js 10 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
hangzhoumesParent/common/opcuaClient/pom.xml 40 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
hangzhoumesParent/common/opcuaClient/src/main/java/com/mes/milo/configuration/MiloAutoConfiguration.java 117 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
hangzhoumesParent/common/opcuaClient/src/main/java/com/mes/milo/configuration/MiloProperties.java 85 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
hangzhoumesParent/common/opcuaClient/src/main/java/com/mes/milo/exception/EndPointNotFoundException.java 18 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
hangzhoumesParent/common/opcuaClient/src/main/java/com/mes/milo/exception/IdentityNotFoundException.java 14 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
hangzhoumesParent/common/opcuaClient/src/main/java/com/mes/milo/model/ReadWriteEntity.java 26 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
hangzhoumesParent/common/opcuaClient/src/main/java/com/mes/milo/model/WriteEntity.java 23 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
hangzhoumesParent/common/opcuaClient/src/main/java/com/mes/milo/pool/MiloConnectFactory.java 155 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
hangzhoumesParent/common/opcuaClient/src/main/java/com/mes/milo/pool/MiloConnectPool.java 25 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
hangzhoumesParent/common/opcuaClient/src/main/java/com/mes/milo/runner/BrowseNodeRunner.java 59 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
hangzhoumesParent/common/opcuaClient/src/main/java/com/mes/milo/runner/BrowseRunner.java 36 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
hangzhoumesParent/common/opcuaClient/src/main/java/com/mes/milo/runner/ReadValuesRunner.java 60 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
hangzhoumesParent/common/opcuaClient/src/main/java/com/mes/milo/runner/WriteValuesRunner.java 50 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
hangzhoumesParent/common/opcuaClient/src/main/java/com/mes/milo/runner/subscription/SubscriptionCallback.java 16 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
hangzhoumesParent/common/opcuaClient/src/main/java/com/mes/milo/runner/subscription/SubscriptionRunner.java 111 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
hangzhoumesParent/common/opcuaClient/src/main/java/com/mes/milo/service/MiloService.java 553 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
hangzhoumesParent/common/opcuaClient/src/main/java/com/mes/milo/utils/CustomUtil.java 114 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
hangzhoumesParent/common/opcuaClient/src/main/java/com/mes/milo/utils/KeyStoreLoader.java 123 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
hangzhoumesParent/common/opcuaClient/src/main/resources/META-INF/spring.factories 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
hangzhoumesParent/common/opcuaClient/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
hangzhoumesParent/common/opcuaClient/src/main/resources/application.yml 9 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
hangzhoumesParent/common/pom.xml 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
hangzhoumesParent/moduleService/CacheGlassModule/src/main/java/com/mes/job/OpcCacheGlassTask.java 31 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
hangzhoumesParent/moduleService/CacheGlassModule/src/main/java/com/mes/job/entity/CacheGlassInfo.java 46 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
hangzhoumesParent/moduleService/CacheGlassModule/src/main/java/com/mes/opccallback/CacheGlassSubscriptionCallback.java 35 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
hangzhoumesParent/moduleService/CacheGlassModule/src/main/resources/application.yml 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
hangzhoumesParent/moduleService/pom.xml 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
hangzhoumesParent/moduleService/yiwumes/pom.xml 34 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
hangzhoumesParent/moduleService/yiwumes/src/main/java/com/mes/GlassStorageApplication.java 28 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
hangzhoumesParent/moduleService/yiwumes/src/main/java/com/mes/job/push.java 54 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
hangzhoumesParent/moduleService/yiwumes/src/main/java/com/mes/loadposition/controller/LoadPositionController.java 99 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
hangzhoumesParent/moduleService/yiwumes/src/main/java/com/mes/loadposition/entity/LoadPosition.java 79 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
hangzhoumesParent/moduleService/yiwumes/src/main/java/com/mes/loadposition/mapper/LoadPositionMapper.java 16 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
hangzhoumesParent/moduleService/yiwumes/src/main/java/com/mes/loadposition/mapper/LoadPositionMapper.xml 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
hangzhoumesParent/moduleService/yiwumes/src/main/java/com/mes/loadposition/service/LoadPositionService.java 19 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
hangzhoumesParent/moduleService/yiwumes/src/main/java/com/mes/loadposition/service/impl/LoadPositionServiceImpl.java 32 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
hangzhoumesParent/moduleService/yiwumes/src/main/java/com/mes/rawusage/controller/RawUsageController.java 119 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
hangzhoumesParent/moduleService/yiwumes/src/main/java/com/mes/rawusage/entity/RawUsage.java 110 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
hangzhoumesParent/moduleService/yiwumes/src/main/java/com/mes/rawusage/mapper/RawUsageMapper.java 15 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
hangzhoumesParent/moduleService/yiwumes/src/main/java/com/mes/rawusage/mapper/RawUsageMapper.xml 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
hangzhoumesParent/moduleService/yiwumes/src/main/java/com/mes/rawusage/service/RawUsageService.java 36 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
hangzhoumesParent/moduleService/yiwumes/src/main/java/com/mes/rawusage/service/impl/RawUsageServiceImpl.java 138 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
hangzhoumesParent/moduleService/yiwumes/src/main/java/com/mes/shelfrack/controller/ShelfRackController.java 113 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
hangzhoumesParent/moduleService/yiwumes/src/main/java/com/mes/shelfrack/entity/ShelfRack.java 68 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
hangzhoumesParent/moduleService/yiwumes/src/main/java/com/mes/shelfrack/entity/request/RawUsageAndShelfRack.java 76 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
hangzhoumesParent/moduleService/yiwumes/src/main/java/com/mes/shelfrack/mapper/ShelfRackMapper.java 23 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
hangzhoumesParent/moduleService/yiwumes/src/main/java/com/mes/shelfrack/service/ShelfRackService.java 20 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
hangzhoumesParent/moduleService/yiwumes/src/main/java/com/mes/shelfrack/service/impl/ShelfRackServiceImpl.java 61 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
hangzhoumesParent/moduleService/yiwumes/src/main/java/com/mes/storagetask/controller/StorageTaskController.java 129 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
hangzhoumesParent/moduleService/yiwumes/src/main/java/com/mes/storagetask/entity/StorageTask.java 82 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
hangzhoumesParent/moduleService/yiwumes/src/main/java/com/mes/storagetask/entity/request/StorageTaskRequest.java 77 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
hangzhoumesParent/moduleService/yiwumes/src/main/java/com/mes/storagetask/mapper/StorageTaskMapper.java 25 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
hangzhoumesParent/moduleService/yiwumes/src/main/java/com/mes/storagetask/service/StorageTaskService.java 24 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
hangzhoumesParent/moduleService/yiwumes/src/main/java/com/mes/storagetask/service/impl/StorageTaskServiceImpl.java 167 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
hangzhoumesParent/moduleService/yiwumes/src/main/resources/application-dev.yml 25 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
hangzhoumesParent/moduleService/yiwumes/src/main/resources/application-prod.yml 30 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
hangzhoumesParent/moduleService/yiwumes/src/main/resources/application.yml 18 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
hangzhoumesParent/moduleService/yiwumes/src/main/resources/mapper/ShelfRackMapper.xml 25 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
hangzhoumesParent/moduleService/yiwumes/src/main/resources/mapper/StorageTaskMapper.xml 35 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
hangzhoumesParent/moduleService/yiwumes/src/test/java/mes/GlassStorageModuleApplicationTest.java 79 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
UI-Project/src/lang/en.js
@@ -158,7 +158,6 @@
        inglassgaps:'Введите стекло зазор',
        sure:'подтверд',
        cancel:'Отмена',
        glassID:'Стеклянный ID',
        operate:'Операция',
        breakage:'Повреждение',
        delete:'Удал',
@@ -224,7 +223,6 @@
        bindingshelves:'Назначенная стеллажка',
        clear:'Чисто.',
        workstation:'Станция номер',
        shelfnumber:'Номер стойки регистрации:',
        cardnumbera:'Номер карточки процесса:',
        incardnumber:'Пожалуйста, выберите номер программы',
        clearglass:'Очистить стекло с полки',
UI-Project/src/lang/zh.js
@@ -216,12 +216,11 @@
        specifytemperinga:'是否指定钢化该条信息?',
        temperedswitch:'钢化开关',
        dutyinformation:'值班信息',
        line:'线路',
        process:'工序',
        team:'班组',
        basic:'设备',
        makesure:'确认保存',
        cancel:'取消',
        // cancel:'取消',
        temperingtotal:'钢化炉数:',
        glasstotal:'玻璃总数:',
    },
@@ -452,11 +451,9 @@
        allstatus: '全部入库状态',
        completedquantity: '完成数量',
        scrapquantity: '报废数量',
        number: '数量',
        method: '加工方式',
        innumber: '已入数量',
        productstatus: '生产状态',
        projectnumber: '工程号',
        right: '正常',
        stop: '终止',
        inquire: '查询',
@@ -490,7 +487,6 @@
        glassID :'玻璃ID',
        projectnumber :'工程号',
        layoutID :'钢化版图ID',
        productiontime :'生产时间',
        type :'类型',
        state :'状态',
        processcards :'流程卡',
@@ -525,7 +521,6 @@
        startslot:'开始工位',
        endslot:'目标工位',
        slotid:'格子ID',
        slot:'格子号',
        width:'原片宽',
        widtha:'原片宽:',
        inwidth:'请输入原片宽',
@@ -545,7 +540,6 @@
        quantitya:'数量:',
        enableid:'任务ID',
        originateslot:'起始格子',
        endslot:'目标格子',
        patternquantity:'原片数量',
        enabletype:'任务类型',
        enablestate:'工位状态',
@@ -563,10 +557,8 @@
        taskstatus :'任务状态',
        built :'新建',
        execution :'执行中',
        finish :'完成',
        tasktype :'任务类型',
        stocke :'入库',
        outbound :'出库',
        dispatch :'调度',
        inquire :'查询',
        station :'工位',
hangzhoumesParent/common/opcuaClient/pom.xml
New file
@@ -0,0 +1,40 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <artifactId>common</artifactId>
        <groupId>com.mes</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>
    <artifactId>opcuaClient</artifactId>
    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-autoconfigure</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-configuration-processor</artifactId>
        </dependency>
        <dependency>
            <groupId>org.eclipse.milo</groupId>
            <artifactId>sdk-client</artifactId>
            <version>0.6.8</version>
        </dependency>
        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-pool2</artifactId>
            <version>2.6.2</version>
        </dependency>
    </dependencies>
</project>
hangzhoumesParent/common/opcuaClient/src/main/java/com/mes/milo/configuration/MiloAutoConfiguration.java
New file
@@ -0,0 +1,117 @@
package com.mes.milo.configuration;
import com.mes.milo.pool.MiloConnectFactory;
import com.mes.milo.pool.MiloConnectPool;
import com.mes.milo.service.MiloService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.pool2.impl.GenericKeyedObjectPoolConfig;
import org.eclipse.milo.opcua.sdk.client.OpcUaClient;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.DependsOn;
import javax.annotation.PreDestroy;
/**
 * @author mes
 * @date 2020/4/25
 * @desc milo-spring-boot-starter
 * @since 0.0.1
 */
@Configuration
@EnableConfigurationProperties(MiloProperties.class)
@ConditionalOnClass({MiloService.class, MiloConnectPool.class})
@ConditionalOnProperty(prefix = MiloProperties.PREFIX, value = "enabled", havingValue = "true", matchIfMissing = true)
@Slf4j
public class MiloAutoConfiguration {
    private final MiloProperties properties;
    private MiloConnectPool connectPool;
    public MiloAutoConfiguration(MiloProperties properties) {
        this.properties = properties;
    }
    @Bean(name = "miloConnectPool")
    @ConditionalOnMissingBean({MiloConnectPool.class})
    protected MiloConnectPool miloConnectPool() {
        MiloConnectFactory objectFactory = new MiloConnectFactory(this.properties);
        //设置对象池的相关参数
        GenericKeyedObjectPoolConfig<OpcUaClient> poolConfig = new GenericKeyedObjectPoolConfig<>();
        MiloProperties.Pool pool = properties.getPool();
        // 最大空闲数
        poolConfig.setMaxIdlePerKey(pool.getMaxIdle());
        //最小空闲,设置为2表示池内至少存放2个空闲对象(当池内有2个空闲对象时调用borrowObject去对象时会立即调用创建对象的方法保证池内有2个空闲对象)
        poolConfig.setMinIdlePerKey(pool.getMinIdle());
        //最大总数 10
        poolConfig.setMaxTotal(pool.getMaxTotal());
        // 多久执行一次对象扫描,将无用的对象销毁,默认-1不扫描
        // poolConfig.setTimeBetweenEvictionRuns(Duration.ofMinutes(1));
        // 在获取对象的时候检查有效性, 默认false
        poolConfig.setTestOnBorrow(true);
        // 在归还对象的时候检查有效性, 默认false
        poolConfig.setTestOnReturn(false);
        // 在空闲时检查有效性, 默认false
        poolConfig.setTestWhileIdle(false);
        // 最大等待时间, 默认的值为-1,表示无限等待。
//        poolConfig.setMaxWait(Duration.ofSeconds(1));
        // 是否启用后进先出, 默认true
        poolConfig.setLifo(true);
        // 连接耗尽时是否阻塞, false立即抛异常,true阻塞直到超时, 默认true
        poolConfig.setBlockWhenExhausted(true);
        // 每次逐出检查时 逐出的最大数目 默认3
        poolConfig.setNumTestsPerEvictionRun(3);
        //一定要关闭jmx,不然springboot启动会报已经注册了某个jmx的错误
        poolConfig.setJmxEnabled(false);
        //新建一个对象池,传入对象工厂和配置
        connectPool = new MiloConnectPool(objectFactory, poolConfig);
        initPool(pool.getInitialSize(), pool.getMaxIdle());
        return connectPool;
    }
    @Bean
    @ConditionalOnMissingBean(MiloService.class)
    @DependsOn("miloConnectPool")
    public MiloService miloService(MiloConnectPool miloConnectPool) {
        return new MiloService(miloConnectPool, properties);
    }
    /**
     * 预先加载testObject对象到对象池中
     *
     * @param initialSize 初始化连接数
     * @param maxIdle     最大空闲连接数
     */
    private void initPool(int initialSize, int maxIdle) {
        if (initialSize <= 0) {
            return;
        }
        properties.getConfig().forEach((key, config) -> {
            for (int i = 0; i < Math.min(initialSize, maxIdle); i++) {
                try {
                    connectPool.addObject(config);
                } catch (Exception e) {
                    throw new RuntimeException(e);
                }
            }
        });
    }
    @PreDestroy
    public void destroy() {
        if (connectPool != null) {
            connectPool.close();
            log.info("all opcUaClients are closed");
        }
    }
}
hangzhoumesParent/common/opcuaClient/src/main/java/com/mes/milo/configuration/MiloProperties.java
New file
@@ -0,0 +1,85 @@
package com.mes.milo.configuration;
import lombok.Data;
import org.eclipse.milo.opcua.stack.core.security.SecurityPolicy;
import org.springframework.boot.context.properties.ConfigurationProperties;
import java.util.LinkedHashMap;
import java.util.Map;
/**
 * @author mes
 * @date 2020/4/25
 * @desc milo-spring-boot-starter
 * @since 0.0.1
 */
@Data
@ConfigurationProperties(prefix = MiloProperties.PREFIX)
public class MiloProperties {
    public static final String PREFIX = "mes.milo";
    /**
     * 是否启用组件
     */
    private Boolean enabled = true;
    /**
     * server 默认请求配置,不指定,则默认取 config中第一个
     */
    private String primary;
    /**
     * server 列表
     */
    private Map<String, Config> config = new LinkedHashMap<>();
    /**
     * 连接池配置
     */
    private Pool pool = new Pool();
    @Data
    public static class Config {
        /**
         * OPC UA地址
         */
        private String endpoint;
        /**
         * 安全策略
         */
        private SecurityPolicy securityPolicy = SecurityPolicy.None;
        /**
         * 用户名
         */
        private String username;
        /**
         * 密码
         */
        private String password;
    }
    @Data
    public static class Pool {
        /**
         * 最大空闲
         */
        private int maxIdle = 5;
        /**
         * 最大总数
         */
        private int maxTotal = 20;
        /**
         * 最小空闲
         */
        private int minIdle = 2;
        /**
         * 初始化连接数
         */
        private int initialSize = 3;
    }
}
hangzhoumesParent/common/opcuaClient/src/main/java/com/mes/milo/exception/EndPointNotFoundException.java
New file
@@ -0,0 +1,18 @@
package com.mes.milo.exception;
/**
 * 类 EndPointNotFoundException 功能描述:
 *
 * @author mes
 * @version 0.0.1
 * @date 2021/09/04 17:03
 */
public class EndPointNotFoundException extends RuntimeException {
    public EndPointNotFoundException() {
        super();
    }
    public EndPointNotFoundException(String message) {
        super(message);
    }
}
hangzhoumesParent/common/opcuaClient/src/main/java/com/mes/milo/exception/IdentityNotFoundException.java
New file
@@ -0,0 +1,14 @@
package com.mes.milo.exception;
/**
 * 类 IdentityNotFoundException 功能描述:
 *
 * @author mes
 * @version 0.0.1
 * @date 2021/09/15 09:35
 */
public class IdentityNotFoundException extends RuntimeException {
    public IdentityNotFoundException(String message) {
        super(message);
    }
}
hangzhoumesParent/common/opcuaClient/src/main/java/com/mes/milo/model/ReadWriteEntity.java
New file
@@ -0,0 +1,26 @@
package com.mes.milo.model;
import lombok.*;
import lombok.experimental.Accessors;
import org.eclipse.milo.opcua.stack.core.types.builtin.DataValue;
/**
 * @author mes
 * @version 0.0.1
 * @desc
 * @since 2020/4/13
 */
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
@Accessors(chain = true)
@ToString
public class ReadWriteEntity {
    private String identifier;
    private Object value;
    private DataValue dataValue;
}
hangzhoumesParent/common/opcuaClient/src/main/java/com/mes/milo/model/WriteEntity.java
New file
@@ -0,0 +1,23 @@
package com.mes.milo.model;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.Accessors;
import org.eclipse.milo.opcua.stack.core.types.builtin.Variant;
/**
 * @author mes
 * @version 0.0.1
 * @since 2020/4/13
 */
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
@Accessors(chain = true)
public class WriteEntity {
    private String identifier;
    private Variant variant;
}
hangzhoumesParent/common/opcuaClient/src/main/java/com/mes/milo/pool/MiloConnectFactory.java
New file
@@ -0,0 +1,155 @@
package com.mes.milo.pool;
import com.mes.milo.configuration.MiloProperties;
import com.mes.milo.exception.EndPointNotFoundException;
import com.mes.milo.exception.IdentityNotFoundException;
import com.mes.milo.utils.CustomUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.pool2.KeyedPooledObjectFactory;
import org.apache.commons.pool2.PooledObject;
import org.apache.commons.pool2.impl.DefaultPooledObject;
import org.eclipse.milo.opcua.sdk.client.OpcUaClient;
import org.eclipse.milo.opcua.sdk.client.api.identity.AnonymousProvider;
import org.eclipse.milo.opcua.sdk.client.api.identity.IdentityProvider;
import org.eclipse.milo.opcua.sdk.client.api.identity.UsernameProvider;
import org.eclipse.milo.opcua.stack.core.security.SecurityPolicy;
import org.eclipse.milo.opcua.stack.core.types.builtin.LocalizedText;
import org.eclipse.milo.opcua.stack.core.types.builtin.unsigned.UInteger;
import org.eclipse.milo.opcua.stack.core.types.structured.EndpointDescription;
import java.net.URI;
import java.net.URISyntaxException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Optional;
/**
 * 类 MiloConnectFactory 功能描述:<br/>
 *
 * @author mes
 * @version 0.0.1
 * @date 2023/5/4 18:56
 */
@Slf4j
public class MiloConnectFactory implements KeyedPooledObjectFactory<MiloProperties.Config, OpcUaClient> {
    public MiloConnectFactory(MiloProperties properties) {
        CustomUtil.verifyProperties(properties);
    }
    /**
     * 创建对象
     *
     * @return
     * @throws Exception
     */
    @Override
    public PooledObject<OpcUaClient> makeObject(MiloProperties.Config key) throws Exception {
        OpcUaClient client = null;
        try {
            client = createClient(key);
            client.connect().get();
            return new DefaultPooledObject<>(client);
        } catch (Exception e) {
            if (client != null) {
                client.disconnect().get();
            }
            throw new InterruptedException(e.getMessage());
        }
    }
    /**
     * 对象要被销毁时(validateObject方法返回false或者超时)后被调用
     *
     * @param pooledObject
     * @throws Exception
     */
    @Override
    public void destroyObject(MiloProperties.Config key, PooledObject<OpcUaClient> pooledObject) throws Exception {
        OpcUaClient opcUaClient = pooledObject.getObject();
        log.info("disconnect opcUaClient {}", opcUaClient.getConfig().getApplicationName().getText());
        opcUaClient.disconnect().get();
    }
    /**
     * 每次获取对象和还回对象时会被调用,如果返回false会销毁对象
     */
    @Override
    public boolean validateObject(MiloProperties.Config key, PooledObject<OpcUaClient> pooledObject) {
        return true;
    }
    /**
     * 调用获取对象方法前被调用
     * 此方法一般进行一些前置操作
     */
    @Override
    public void activateObject(MiloProperties.Config key, PooledObject<OpcUaClient> pooledObject) throws Exception {
    }
    /**
     * 当还回对象并且validateObject方法返回true后被调用
     * 一般在此方法中对刚刚使用完成的对象进行重置
     */
    @Override
    public void passivateObject(MiloProperties.Config key, PooledObject<OpcUaClient> pooledObject) throws Exception {
    }
    private OpcUaClient createClient(MiloProperties.Config key) throws Exception {
        Path securityTempDir = Paths.get(System.getProperty("java.io.tmpdir"), "security");
        Files.createDirectories(securityTempDir);
        if (!Files.exists(securityTempDir)) {
            throw new Exception("unable to create security dir: " + securityTempDir);
        }
        return OpcUaClient.create(key.getEndpoint(),
                endpoints -> {
                    final Optional<EndpointDescription> endpoint = endpoints
                            .stream()
//                            .filter(e -> e.getSecurityPolicyUri().equals(SecurityPolicy.None.getUri()))
                            .findFirst();
                    EndpointDescription newEndpoint = new EndpointDescription(key.getEndpoint(), endpoint.get().getServer(), endpoint.get().getServerCertificate(),
                            endpoint.get().getSecurityMode(), endpoint.get().getSecurityPolicyUri(), endpoint.get().getUserIdentityTokens(),
                            endpoint.get().getTransportProfileUri(), endpoint.get().getSecurityLevel());
                    return Optional.of(newEndpoint);
                },
                configBuilder ->
                        configBuilder
                                .setApplicationName(LocalizedText.english("eclipse milo opc-ua client"))
                                .setApplicationUri("urn:eclipse:milo:examples:client")
                                //访问方式
                                .setIdentityProvider(new UsernameProvider(key.getUsername(), key.getPassword()))
                                .setRequestTimeout(UInteger.valueOf(5000))
                                .build()
        );
    }
    private URI getUri(MiloProperties.Config key) {
        try {
            return new URI(endpointUrl(key));
        } catch (URISyntaxException e) {
            throw new EndPointNotFoundException("endpoint 配置异常");
        }
    }
    private String endpointUrl(MiloProperties.Config key) {
        return key.getEndpoint();
    }
    private SecurityPolicy securityPolicy(MiloProperties.Config key) {
        return key.getSecurityPolicy();
    }
    private IdentityProvider identityProvider(MiloProperties.Config key) {
        if (securityPolicy(key).equals(SecurityPolicy.None)) {
            return new AnonymousProvider();
        }
        if (key.getUsername() == null || key.getPassword() == null) {
            throw new IdentityNotFoundException("连接信息未完善");
        } else {
            return new UsernameProvider(key.getUsername(), key.getPassword());
        }
    }
}
hangzhoumesParent/common/opcuaClient/src/main/java/com/mes/milo/pool/MiloConnectPool.java
New file
@@ -0,0 +1,25 @@
package com.mes.milo.pool;
import com.mes.milo.configuration.MiloProperties;
import org.apache.commons.pool2.KeyedPooledObjectFactory;
import org.apache.commons.pool2.impl.GenericKeyedObjectPool;
import org.apache.commons.pool2.impl.GenericKeyedObjectPoolConfig;
import org.eclipse.milo.opcua.sdk.client.OpcUaClient;
/**
 * 类 MiloConnectPool 功能描述:<br/>
 *
 * @author mes
 * @version 0.0.1
 * @date 2023/5/4 19:17
 */
public class MiloConnectPool extends GenericKeyedObjectPool<MiloProperties.Config, OpcUaClient> {
    public MiloConnectPool(KeyedPooledObjectFactory<MiloProperties.Config, OpcUaClient> factory) {
        super(factory);
    }
    public MiloConnectPool(KeyedPooledObjectFactory<MiloProperties.Config, OpcUaClient> factory, GenericKeyedObjectPoolConfig<OpcUaClient> config) {
        super(factory, config);
    }
}
hangzhoumesParent/common/opcuaClient/src/main/java/com/mes/milo/runner/BrowseNodeRunner.java
New file
@@ -0,0 +1,59 @@
package com.mes.milo.runner;
import com.mes.milo.utils.CustomUtil;
import lombok.extern.slf4j.Slf4j;
import org.eclipse.milo.opcua.sdk.client.OpcUaClient;
import org.eclipse.milo.opcua.sdk.client.nodes.UaNode;
import org.eclipse.milo.opcua.stack.core.UaException;
import org.eclipse.milo.opcua.stack.core.types.builtin.NodeId;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;
/**
 * @author mes
 * @version 0.0.1
 * @since 2020/4/14
 */
@Slf4j
public class BrowseNodeRunner {
    /**
     * 要读的节点
     */
    private final String browseRoot;
    public BrowseNodeRunner(String browseRoot) {
        this.browseRoot = browseRoot;
    }
    public List<String> run(OpcUaClient opcUaClient) {
        NodeId nodeId = CustomUtil.parseNodeId(browseRoot);
        return browseNode(browseRoot, opcUaClient, nodeId);
    }
    private List<String> browseNode(String prefix, OpcUaClient client, NodeId browseRoot) {
        List<String> nodesList = new ArrayList<>();
        try {
            List<? extends UaNode> nodes = client.getAddressSpace().browseNodes(browseRoot);
            nodes = nodes.stream().filter(item -> !Objects.requireNonNull(item.getBrowseName().getName()).startsWith("_")).collect(Collectors.toList());
            for (UaNode node : nodes) {
                String sub = prefix + "." + node.getBrowseName().getName();
                // recursively browse to children
                List<String> browseNode = browseNode(sub, client, node.getNodeId());
                if (browseNode.isEmpty()) {
                    nodesList.add(sub);
                } else {
                    nodesList.addAll(browseNode(sub, client, node.getNodeId()));
                }
            }
        } catch (UaException e) {
            log.error("Browsing nodeId={} failed: {}", browseRoot, e.getMessage(), e);
        }
        return nodesList;
    }
}
hangzhoumesParent/common/opcuaClient/src/main/java/com/mes/milo/runner/BrowseRunner.java
New file
@@ -0,0 +1,36 @@
package com.mes.milo.runner;
import lombok.extern.slf4j.Slf4j;
import org.eclipse.milo.opcua.sdk.client.OpcUaClient;
import org.eclipse.milo.opcua.sdk.client.nodes.UaNode;
import org.eclipse.milo.opcua.stack.core.Identifiers;
import org.eclipse.milo.opcua.stack.core.UaException;
import org.eclipse.milo.opcua.stack.core.types.builtin.unsigned.UShort;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;
/**
 * @author mes
 * @version 0.0.1
 * @since 2020/4/14
 */
@Slf4j
public class BrowseRunner {
    public List<String> run(OpcUaClient opcUaClient) {
        List<String> nodesList = new ArrayList<>();
        try {
            List<? extends UaNode> nodes = opcUaClient.getAddressSpace().browseNodes(Identifiers.ObjectsFolder);
            nodesList.addAll(nodes.stream().filter(item -> !Objects.requireNonNull(item.getBrowseName().getName()).startsWith("_")
                    && Objects.equals(item.getBrowseName().getNamespaceIndex(), UShort.valueOf(2)))
                    .map(item -> item.getBrowseName().getName()).collect(Collectors.toList()));
        } catch (UaException e) {
            log.error("遍历根节点异常:{}", e.getMessage(), e);
        }
        return nodesList;
    }
}
hangzhoumesParent/common/opcuaClient/src/main/java/com/mes/milo/runner/ReadValuesRunner.java
New file
@@ -0,0 +1,60 @@
package com.mes.milo.runner;
import com.mes.milo.model.ReadWriteEntity;
import com.mes.milo.utils.CustomUtil;
import lombok.extern.slf4j.Slf4j;
import org.eclipse.milo.opcua.sdk.client.OpcUaClient;
import org.eclipse.milo.opcua.stack.core.types.builtin.DataValue;
import org.eclipse.milo.opcua.stack.core.types.builtin.NodeId;
import org.eclipse.milo.opcua.stack.core.types.builtin.StatusCode;
import org.eclipse.milo.opcua.stack.core.types.enumerated.TimestampsToReturn;
import java.util.ArrayList;
import java.util.List;
/**
 * @author mes
 * @version 0.0.1
 * @desc
 * @since 2020/4/14
 */
@Slf4j
public class ReadValuesRunner {
    /**
     * 要读的点位list
     */
    private final List<String> identifiers;
    public ReadValuesRunner(List<String> identifiers) {
        this.identifiers = identifiers;
    }
    public List<ReadWriteEntity> run(OpcUaClient opcUaClient) {
        List<ReadWriteEntity> entityList = new ArrayList<>();
        try {
            List<NodeId> nodeIds = new ArrayList<>();
            identifiers.forEach(identifier -> nodeIds.add(CustomUtil.parseNodeId(identifier)));
            // 读取指定点位的值,10s超时
            List<DataValue> dataValues = opcUaClient.readValues(10000, TimestampsToReturn.Both, nodeIds).get();
            if (dataValues.size() == identifiers.size()) {
                for (int i = 0; i < identifiers.size(); i++) {
                    String id = identifiers.get(i);
                    Object value = dataValues.get(i).getValue().getValue();
                    StatusCode status = dataValues.get(i).getStatusCode();
                    assert status != null;
                    if (status.isGood()) {
                        log.info("读取点位 '{}' 的值为 {}", id, value);
                    }
                    entityList.add(ReadWriteEntity.builder()
                            .identifier(id)
                            .value(value)
                            .dataValue(dataValues.get(i))
                            .build());
                }
            }
        } catch (Exception e) {
            log.error("读值时出现了异常:{}", e.getMessage(), e);
        }
        return entityList;
    }
}
hangzhoumesParent/common/opcuaClient/src/main/java/com/mes/milo/runner/WriteValuesRunner.java
New file
@@ -0,0 +1,50 @@
package com.mes.milo.runner;
import com.mes.milo.model.WriteEntity;
import com.mes.milo.utils.CustomUtil;
import lombok.extern.slf4j.Slf4j;
import org.eclipse.milo.opcua.sdk.client.OpcUaClient;
import org.eclipse.milo.opcua.stack.core.types.builtin.DataValue;
import org.eclipse.milo.opcua.stack.core.types.builtin.NodeId;
import org.eclipse.milo.opcua.stack.core.types.builtin.StatusCode;
import java.util.LinkedList;
import java.util.List;
/**
 * @author mes
 * @version 0.0.1
 * @since 2020/4/14
 */
@Slf4j
public class WriteValuesRunner {
    private final List<WriteEntity> entities;
    public WriteValuesRunner(List<WriteEntity> entities) {
        this.entities = entities;
    }
    public void run(OpcUaClient opcUaClient) {
        try {
            if (!entities.isEmpty()) {
                List<NodeId> nodeIds = new LinkedList<>();
                List<DataValue> dataValues = new LinkedList<>();
                for (WriteEntity entity : entities) {
                    nodeIds.add(CustomUtil.parseNodeId(entity.getIdentifier()));
                    dataValues.add(new DataValue(entity.getVariant(), null, null));
                }
                List<StatusCode> statusCodeList = opcUaClient.writeValues(nodeIds, dataValues).join();
                for (int i = 0; i < statusCodeList.size(); i++) {
                    if (statusCodeList.get(i).isGood()) {
                        log.info("将值 '{}' 写入到点位:{} 成功", dataValues.get(i).getValue(), nodeIds.get(i));
                    } else {
                        log.error("点位:{} 写入时出现了异常:{}", nodeIds.get(i), statusCodeList.get(i));
                    }
                }
            }
        } catch (Exception e) {
            log.error("批量写值出现异常出现了异常:{}", e.getMessage(), e);
        }
    }
}
hangzhoumesParent/common/opcuaClient/src/main/java/com/mes/milo/runner/subscription/SubscriptionCallback.java
New file
@@ -0,0 +1,16 @@
package com.mes.milo.runner.subscription;
import org.eclipse.milo.opcua.sdk.client.subscriptions.ManagedDataItem;
import org.eclipse.milo.opcua.stack.core.types.builtin.DataValue;
/**
 * 类 SubscriptionCallback 功能描述:<br/>
 *
 * @author mes
 * @version 0.0.1
 * @date 2023/5/8 22:14
 */
public interface SubscriptionCallback {
    void onSubscribe(ManagedDataItem dataItem, DataValue value) throws Exception;
}
hangzhoumesParent/common/opcuaClient/src/main/java/com/mes/milo/runner/subscription/SubscriptionRunner.java
New file
@@ -0,0 +1,111 @@
package com.mes.milo.runner.subscription;
import com.mes.milo.utils.CustomUtil;
import lombok.extern.slf4j.Slf4j;
import org.eclipse.milo.opcua.sdk.client.OpcUaClient;
import org.eclipse.milo.opcua.sdk.client.api.subscriptions.UaSubscription;
import org.eclipse.milo.opcua.sdk.client.api.subscriptions.UaSubscriptionManager;
import org.eclipse.milo.opcua.sdk.client.subscriptions.ManagedDataItem;
import org.eclipse.milo.opcua.sdk.client.subscriptions.ManagedSubscription;
import org.eclipse.milo.opcua.stack.core.types.builtin.NodeId;
import org.eclipse.milo.opcua.stack.core.types.builtin.StatusCode;
import org.eclipse.milo.opcua.stack.core.types.builtin.unsigned.UInteger;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CountDownLatch;
/**
 * 类 SubscriptionRunner 功能描述:
 *
 * @author mes
 * @version 0.0.1
 * @date 2022/01/01 23:49
 */
@Slf4j
public class SubscriptionRunner {
    /**
     * 点位list
     */
    private final List<String> identifiers;
    private final double samplingInterval;
    public SubscriptionRunner(List<String> identifiers) {
        this.identifiers = identifiers;
        this.samplingInterval = 1000.0D;
    }
    public SubscriptionRunner(List<String> identifiers, double samplingInterval) {
        this.identifiers = identifiers;
        this.samplingInterval = samplingInterval;
    }
    public void run(OpcUaClient opcUaClient, SubscriptionCallback callback) {
        final CountDownLatch downLatch = new CountDownLatch(1);
        //添加订阅监听器,用于处理断线重连后的订阅问题
        opcUaClient.getSubscriptionManager().addSubscriptionListener(new CustomSubscriptionListener(opcUaClient, callback));
        //处理订阅逻辑
        handler(opcUaClient, callback);
        try {
            //持续监听
            downLatch.await();
        } catch (Exception e) {
            log.error("订阅时出现了异常:{}", e.getMessage(), e);
        }
    }
    private void handler(OpcUaClient opcUaClient, SubscriptionCallback callback) {
        try {
            //创建订阅
            ManagedSubscription subscription = ManagedSubscription.create(opcUaClient, samplingInterval);
            subscription.setDefaultSamplingInterval(samplingInterval);
            subscription.setDefaultQueueSize(UInteger.valueOf(10));
            List<NodeId> nodeIdList = new ArrayList<>();
            for (String identifier : identifiers) {
                nodeIdList.add(CustomUtil.parseNodeId(identifier));
            }
            List<ManagedDataItem> dataItemList = subscription.createDataItems(nodeIdList);
            for (ManagedDataItem dataItem : dataItemList) {
                dataItem.addDataValueListener((item) -> {
                    try {
                        callback.onSubscribe
                                (dataItem, item);
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                });
            }
        } catch (Exception e) {
            log.error("订阅时出现了异常:{}", e.getMessage(), e);
        }
    }
    private class CustomSubscriptionListener implements UaSubscriptionManager.SubscriptionListener {
        private final OpcUaClient client;
        private final SubscriptionCallback callback;
        public CustomSubscriptionListener(OpcUaClient client, SubscriptionCallback callback) {
            this.client = client;
            this.callback = callback;
        }
        /**
         * 重连时 尝试恢复之前的订阅失败时 会调用此方法
         *
         * @param uaSubscription 订阅
         * @param statusCode     状态
         */
        @Override
        public void onSubscriptionTransferFailed(UaSubscription uaSubscription, StatusCode statusCode) {
            log.debug("恢复订阅失败 需要重新订阅");
            //在回调方法中重新订阅
            handler(client, callback);
        }
    }
}
hangzhoumesParent/common/opcuaClient/src/main/java/com/mes/milo/service/MiloService.java
New file
@@ -0,0 +1,553 @@
package com.mes.milo.service;
import com.mes.milo.configuration.MiloProperties;
import com.mes.milo.model.ReadWriteEntity;
import com.mes.milo.model.WriteEntity;
import com.mes.milo.pool.MiloConnectPool;
import com.mes.milo.runner.BrowseNodeRunner;
import com.mes.milo.runner.BrowseRunner;
import com.mes.milo.runner.ReadValuesRunner;
import com.mes.milo.runner.WriteValuesRunner;
import com.mes.milo.runner.subscription.SubscriptionCallback;
import com.mes.milo.runner.subscription.SubscriptionRunner;
import com.mes.milo.utils.CustomUtil;
import lombok.extern.slf4j.Slf4j;
import org.eclipse.milo.opcua.sdk.client.OpcUaClient;
import org.eclipse.milo.opcua.stack.core.types.builtin.Variant;
import org.eclipse.milo.opcua.stack.core.types.builtin.unsigned.Unsigned;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
/**
 * @author mes
 * @date 2020/4/25
 * @desc milo-spring-boot-starter
 * @since 0.0.1
 */
@Service
@Slf4j
public class MiloService {
    private final MiloConnectPool connectPool;
    private final MiloProperties properties;
    public MiloService(MiloConnectPool connectPool, MiloProperties properties) {
        this.connectPool = connectPool;
        this.properties = properties;
    }
    /**
     * 遍历OPC UA服务器根节点
     *
     * @return 根节点列表
     */
    public List<String> browseRoot() throws Exception {
        return browseRoot(null);
    }
    /**
     * 遍历OPC UA服务器根节点
     *
     * @param clientName 配置key
     * @return 根节点列表
     */
    public List<String> browseRoot(String clientName) throws Exception {
        MiloProperties.Config config = CustomUtil.getConfig(properties, clientName);
        BrowseRunner runner = new BrowseRunner();
        OpcUaClient client = connectPool.borrowObject(config);
        if (client != null) {
            try {
                return runner.run(client);
            } finally {
                connectPool.returnObject(config, client);
            }
        }
        return Collections.emptyList();
    }
    /**
     * 遍历OPC UA服务器指定节点
     *
     * @param browseRoot 节点名称
     * @return 指定节点 tag列表
     */
    public List<String> browseNode(String browseRoot) throws Exception {
        return browseNode(browseRoot, null);
    }
    /**
     * 遍历OPC UA服务器指定节点
     *
     * @param browseRoot 节点名称
     * @param clientName 配置key
     * @return 指定节点 tag列表
     */
    public List<String> browseNode(String browseRoot, String clientName) throws Exception {
        MiloProperties.Config config = CustomUtil.getConfig(properties, clientName);
        BrowseNodeRunner runner = new BrowseNodeRunner(browseRoot);
        OpcUaClient client = connectPool.borrowObject(config);
        if (client != null) {
            try {
                return runner.run(client);
            } finally {
                connectPool.returnObject(config, client);
            }
        }
        return Collections.emptyList();
    }
    /**
     * 指定类型 写入kep点位值
     *
     * @param entity 待写入数据
     */
    public void writeSpecifyType(WriteEntity entity) throws Exception {
        writeSpecifyType(Collections.singletonList(entity));
    }
    /**
     * 指定类型 写入kep点位值
     *
     * @param entity     待写入数据
     * @param clientName 配置key
     */
    public void writeSpecifyType(WriteEntity entity, String clientName) throws Exception {
        writeSpecifyType(Collections.singletonList(entity), clientName);
    }
    /**
     * 指定类型 写入kep点位值,可批量写入不同类型的值
     *
     * @param entities 待写入数据
     */
    public void writeSpecifyType(List<WriteEntity> entities) throws Exception {
        writeSpecifyType(entities, null);
    }
    /**
     * 指定类型 写入kep点位值,可批量写入不同类型的值
     *
     * @param entities   待写入数据
     * @param clientName 配置key
     */
    public void writeSpecifyType(List<WriteEntity> entities, String clientName) throws Exception {
        MiloProperties.Config config = CustomUtil.getConfig(properties, clientName);
        WriteValuesRunner runner = new WriteValuesRunner(entities);
        OpcUaClient client = connectPool.borrowObject(config);
        if (client != null) {
            try {
                runner.run(client);
            } finally {
                connectPool.returnObject(config, client);
            }
        }
    }
    /**
     * 写入kep点位值
     *
     * @param entity 待写入数据
     */
    public void writeToOpcUa(ReadWriteEntity entity) throws Exception {
        writeToOpcUa(Collections.singletonList(entity));
    }
    /**
     * 写入kep点位值
     *
     * @param entity     待写入数据
     * @param clientName 配置key
     */
    public void writeToOpcUa(ReadWriteEntity entity, String clientName) throws Exception {
        writeToOpcUa(Collections.singletonList(entity), clientName);
    }
    /**
     * 写入kep点位值
     *
     * @param entities 待写入数据
     */
    public void writeToOpcUa(List<ReadWriteEntity> entities) throws Exception {
        writeToOpcUa(entities, null);
    }
    /**
     * 写入kep点位值
     *
     * @param entities   待写入数据
     * @param clientName 配置key
     */
    public void writeToOpcUa(List<ReadWriteEntity> entities, String clientName) throws Exception {
        MiloProperties.Config config = CustomUtil.getConfig(properties, clientName);
        List<WriteEntity> writeEntityList = new ArrayList<>();
        if (!entities.isEmpty()) {
            for (ReadWriteEntity entity : entities) {
                writeEntityList.add(WriteEntity.builder()
                        .identifier(entity.getIdentifier())
                        .variant(new Variant(entity.getValue()))
                        .build());
            }
        }
        WriteValuesRunner runner = new WriteValuesRunner(writeEntityList);
        OpcUaClient client = connectPool.borrowObject(config);
        if (client != null) {
            try {
                runner.run(client);
            } finally {
                connectPool.returnObject(config, client);
            }
        }
    }
    /**
     * kepware 数据类型为:Char<br/>
     * 8位带符号整数
     *
     * @param entity 待写入数据
     */
    public void writeToOpcChar(ReadWriteEntity entity) throws Exception {
        writeToOpcChar(Collections.singletonList(entity));
    }
    /**
     * kepware 数据类型为:Char<br/>
     * 8位带符号整数
     *
     * @param entity     待写入数据
     * @param clientName 配置key
     */
    public void writeToOpcChar(ReadWriteEntity entity, String clientName) throws Exception {
        writeToOpcChar(Collections.singletonList(entity), clientName);
    }
    /**
     * kepware 数据类型为:Char<br/>
     * 8位带符号整数
     *
     * @param entities 待写入数据
     */
    public void writeToOpcChar(List<ReadWriteEntity> entities) throws Exception {
        writeToOpcChar(entities, null);
    }
    /**
     * kepware 数据类型为:Char<br/>
     * 8位带符号整数
     *
     * @param entities   待写入数据
     * @param clientName 配置key
     */
    public void writeToOpcChar(List<ReadWriteEntity> entities, String clientName) throws Exception {
        MiloProperties.Config config = CustomUtil.getConfig(properties, clientName);
        List<WriteEntity> writeEntityList = new ArrayList<>();
        if (!entities.isEmpty()) {
            for (ReadWriteEntity entity : entities) {
                writeEntityList.add(WriteEntity.builder()
                        .identifier(entity.getIdentifier())
                        .variant(new Variant(((Integer) entity.getValue()).byteValue()))
                        .build());
            }
        }
        WriteValuesRunner runner = new WriteValuesRunner(writeEntityList);
        OpcUaClient client = connectPool.borrowObject(config);
        if (client != null) {
            try {
                runner.run(client);
            } finally {
                connectPool.returnObject(config, client);
            }
        }
    }
    /**
     * kepware 数据类型为:Byte<br/>
     * 8位无符号整数
     *
     * @param entity 待写入数据
     */
    public void writeToOpcByte(ReadWriteEntity entity) throws Exception {
        writeToOpcByte(Collections.singletonList(entity));
    }
    /**
     * kepware 数据类型为:Byte<br/>
     * 8位无符号整数
     *
     * @param entity     待写入数据
     * @param clientName 配置key
     */
    public void writeToOpcByte(ReadWriteEntity entity, String clientName) throws Exception {
        writeToOpcByte(Collections.singletonList(entity), clientName);
    }
    /**
     * kepware 数据类型为:Byte<br/>
     * 8位无符号整数
     *
     * @param entities 待写入数据
     */
    public void writeToOpcByte(List<ReadWriteEntity> entities) throws Exception {
        writeToOpcByte(entities, null);
    }
    /**
     * kepware 数据类型为:Byte<br/>
     * 8位无符号整数
     *
     * @param entities   待写入数据
     * @param clientName 配置key
     */
    public void writeToOpcByte(List<ReadWriteEntity> entities, String clientName) throws Exception {
        MiloProperties.Config config = CustomUtil.getConfig(properties, clientName);
        List<WriteEntity> writeEntityList = new ArrayList<>();
        if (!entities.isEmpty()) {
            for (ReadWriteEntity entity : entities) {
                writeEntityList.add(WriteEntity.builder()
                        .identifier(entity.getIdentifier())
                        .variant(new Variant(Unsigned.ubyte((Integer) entity.getValue())))
                        .build());
            }
        }
        WriteValuesRunner runner = new WriteValuesRunner(writeEntityList);
        OpcUaClient client = connectPool.borrowObject(config);
        if (client != null) {
            try {
                runner.run(client);
            } finally {
                connectPool.returnObject(config, client);
            }
        }
    }
    /**
     * kepware 数据类型为:Short<br/>
     * 16位带符号整数
     *
     * @param entity 待写入数据
     */
    public void writeToOpcShort(ReadWriteEntity entity) throws Exception {
        writeToOpcShort(Collections.singletonList(entity));
    }
    /**
     * kepware 数据类型为:Short<br/>
     * 16位带符号整数
     *
     * @param entity     待写入数据
     * @param clientName 配置key
     */
    public void writeToOpcShort(ReadWriteEntity entity, String clientName) throws Exception {
        writeToOpcShort(Collections.singletonList(entity), clientName);
    }
    /**
     * kepware 数据类型为:Short<br/>
     * 16位带符号整数
     *
     * @param entities 待写入数据
     */
    public void writeToOpcShort(List<ReadWriteEntity> entities) throws Exception {
        writeToOpcShort(entities, null);
    }
    /**
     * kepware 数据类型为:Short<br/>
     * 16位带符号整数
     *
     * @param entities   待写入数据
     * @param clientName 配置key
     */
    public void writeToOpcShort(List<ReadWriteEntity> entities, String clientName) throws Exception {
        MiloProperties.Config config = CustomUtil.getConfig(properties, clientName);
        List<WriteEntity> writeEntityList = new ArrayList<>();
        if (!entities.isEmpty()) {
            for (ReadWriteEntity entity : entities) {
                writeEntityList.add(WriteEntity.builder()
                        .identifier(entity.getIdentifier())
                        .variant(new Variant(((Integer) entity.getValue()).shortValue()))
                        .build());
            }
        }
        WriteValuesRunner runner = new WriteValuesRunner(writeEntityList);
        OpcUaClient client = connectPool.borrowObject(config);
        if (client != null) {
            try {
                runner.run(client);
            } finally {
                connectPool.returnObject(config, client);
            }
        }
    }
    /**
     * kepware 数据类型为:Word<br/>
     * 16位无符号整数
     *
     * @param entity 待写入数据
     */
    public void writeToOpcWord(ReadWriteEntity entity) throws Exception {
        writeToOpcWord(Collections.singletonList(entity));
    }
    /**
     * kepware 数据类型为:Word<br/>
     * 16位无符号整数
     *
     * @param entity     待写入数据
     * @param clientName 配置key
     */
    public void writeToOpcWord(ReadWriteEntity entity, String clientName) throws Exception {
        writeToOpcWord(Collections.singletonList(entity), clientName);
    }
    /**
     * kepware 数据类型为:Word<br/>
     * 16位无符号整数
     *
     * @param entities 待写入数据
     */
    public void writeToOpcWord(List<ReadWriteEntity> entities) throws Exception {
        writeToOpcWord(entities, null);
    }
    /**
     * kepware 数据类型为:Word<br/>
     * 16位无符号整数
     *
     * @param entities   待写入数据
     * @param clientName 配置key
     */
    public void writeToOpcWord(List<ReadWriteEntity> entities, String clientName) throws Exception {
        MiloProperties.Config config = CustomUtil.getConfig(properties, clientName);
        List<WriteEntity> writeEntityList = new ArrayList<>();
        if (!entities.isEmpty()) {
            for (ReadWriteEntity entity : entities) {
                writeEntityList.add(WriteEntity.builder()
                        .identifier(entity.getIdentifier())
                        .variant(new Variant(Unsigned.ushort((Integer) entity.getValue())))
                        .build());
            }
        }
        WriteValuesRunner runner = new WriteValuesRunner(writeEntityList);
        OpcUaClient client = connectPool.borrowObject(config);
        if (client != null) {
            try {
                runner.run(client);
            } finally {
                connectPool.returnObject(config, client);
            }
        }
    }
    /**
     * 读取kep点位值
     *
     * @param id 点位id
     * @return
     */
    public ReadWriteEntity readFromOpcUa(String id) throws Exception {
        return readFromOpcUa(id, null);
    }
    /**
     * 读取kep点位值
     *
     * @param id         点位id
     * @param clientName 配置key
     * @return
     */
    public ReadWriteEntity readFromOpcUa(String id, String clientName) throws Exception {
        List<ReadWriteEntity> entityList = readFromOpcUa(Collections.singletonList(id), clientName);
        if (!entityList.isEmpty()) {
            return entityList.get(0);
        }
        return null;
    }
    /**
     * 读取kep点位值
     *
     * @param ids 点位id数组
     * @return
     */
    public List<ReadWriteEntity> readFromOpcUa(List<String> ids) throws Exception {
        return readFromOpcUa(ids, null);
    }
    /**
     * 读取kep点位值
     *
     * @param ids        点位id数组
     * @param clientName 配置key
     * @return
     */
    public List<ReadWriteEntity> readFromOpcUa(List<String> ids, String clientName) throws Exception {
        MiloProperties.Config config = CustomUtil.getConfig(properties, clientName);
        ReadValuesRunner runner = new ReadValuesRunner(ids);
        OpcUaClient client = connectPool.borrowObject(config);
        if (client != null) {
            try {
                return runner.run(client);
            } finally {
                connectPool.returnObject(config, client);
            }
        }
        return new ArrayList<>();
    }
    /**
     * 订阅kep点位值
     *
     * @param ids 点位id数组
     * @return
     */
    public void subscriptionFromOpcUa(List<String> ids, SubscriptionCallback callback) throws Exception {
        subscriptionFromOpcUa(ids, 1000.0, callback);
    }
    /**
     * 订阅kep点位值
     *
     * @param ids        点位id数组
     * @param clientName 配置key
     * @return
     */
    public void subscriptionFromOpcUa(List<String> ids, String clientName, SubscriptionCallback callback) throws Exception {
        subscriptionFromOpcUa(ids, 1000.0, clientName, callback);
    }
    /**
     * 订阅kep点位值
     *
     * @param ids              点位id数组
     * @param samplingInterval 订阅时间间隔 默认1000 ms
     * @return
     */
    public void subscriptionFromOpcUa(List<String> ids, double samplingInterval, SubscriptionCallback callback) throws Exception {
        subscriptionFromOpcUa(ids, samplingInterval, null, callback);
    }
    /**
     * 订阅kep点位值
     *
     * @param ids              点位id数组
     * @param samplingInterval 订阅时间间隔 默认1000 ms
     * @param clientName       配置key
     * @return
     */
    public void subscriptionFromOpcUa(List<String> ids, double samplingInterval, String clientName, SubscriptionCallback callback) throws Exception {
        MiloProperties.Config config = CustomUtil.getConfig(properties, clientName);
        SubscriptionRunner runner = new SubscriptionRunner(ids, samplingInterval);
        OpcUaClient client = connectPool.borrowObject(config);
        if (client != null) {
            try {
                runner.run(client, callback);
            } finally {
                connectPool.returnObject(config, client);
            }
        }
    }
}
hangzhoumesParent/common/opcuaClient/src/main/java/com/mes/milo/utils/CustomUtil.java
New file
@@ -0,0 +1,114 @@
package com.mes.milo.utils;
import com.google.common.collect.Sets;
import com.mes.milo.configuration.MiloProperties;
import com.mes.milo.exception.EndPointNotFoundException;
import com.mes.milo.exception.IdentityNotFoundException;
import lombok.extern.slf4j.Slf4j;
import org.eclipse.milo.opcua.stack.core.types.builtin.NodeId;
import org.springframework.util.StringUtils;
import java.net.*;
import java.util.*;
/**
 * @author mes
 * @version 0.0.1
 * @desc
 * @since 2020/4/13
 */
@Slf4j
public class CustomUtil {
    private static final String OPC_UA_NOT_CONFIG = "请配置OPC UA地址信息";
    private CustomUtil() {
    }
    public static String getHostname() {
        try {
            return InetAddress.getLocalHost().getHostName();
        } catch (UnknownHostException var1) {
            return "localhost";
        }
    }
    public static Set<String> getHostnames(String address) {
        return getHostnames(address, true);
    }
    public static Set<String> getHostnames(String address, boolean includeLoopback) {
        HashSet<String> hostnames = Sets.newHashSet();
        try {
            InetAddress inetAddress = InetAddress.getByName(address);
            if (inetAddress.isAnyLocalAddress()) {
                try {
                    Enumeration<NetworkInterface> nis = NetworkInterface.getNetworkInterfaces();
                    for (NetworkInterface ni : Collections.list(nis)) {
                        Collections.list(ni.getInetAddresses()).forEach((ia) -> {
                            if (ia instanceof Inet4Address) {
                                boolean loopback = ia.isLoopbackAddress();
                                if (!loopback || includeLoopback) {
                                    hostnames.add(ia.getHostName());
                                    hostnames.add(ia.getHostAddress());
                                    hostnames.add(ia.getCanonicalHostName());
                                }
                            }
                        });
                    }
                } catch (SocketException var7) {
                    log.warn("Failed to NetworkInterfaces for bind address: {}", address, var7);
                }
            } else {
                boolean loopback = inetAddress.isLoopbackAddress();
                if (!loopback || includeLoopback) {
                    hostnames.add(inetAddress.getHostName());
                    hostnames.add(inetAddress.getHostAddress());
                    hostnames.add(inetAddress.getCanonicalHostName());
                }
            }
        } catch (UnknownHostException var8) {
            log.warn("Failed to get InetAddress for bind address: {}", address, var8);
        }
        return hostnames;
    }
    public static NodeId parseNodeId(String identifier) {
        NodeId nodeId = new NodeId(2, identifier);
        if (identifier.startsWith("ns=") && identifier.contains(";")) {
            nodeId = NodeId.parseOrNull(identifier);
        }
        if (nodeId == null) {
            throw new IdentityNotFoundException("NodeId 解析失败,请检查");
        }
        return nodeId;
    }
    public static void verifyProperties(MiloProperties properties) {
        if (properties.getConfig().isEmpty()) {
            throw new EndPointNotFoundException(OPC_UA_NOT_CONFIG);
        }
        if (!StringUtils.hasText(properties.getPrimary())) {
            Set<String> keySet = properties.getConfig().keySet();
            properties.setPrimary(keySet.stream().findFirst().orElseThrow(() -> new EndPointNotFoundException(OPC_UA_NOT_CONFIG)));
        }
        properties.getConfig().forEach((key, config) -> {
            if (!StringUtils.hasText(config.getEndpoint())) {
                throw new EndPointNotFoundException(OPC_UA_NOT_CONFIG + ": " + key);
            }
        });
    }
    public static MiloProperties.Config getConfig(MiloProperties properties) {
        return getConfig(properties, null);
    }
    public static MiloProperties.Config getConfig(MiloProperties properties, String clientName) {
        Map<String, MiloProperties.Config> config = properties.getConfig();
        return StringUtils.hasText(clientName) ? config.get(clientName) : config.get(properties.getPrimary());
    }
}
hangzhoumesParent/common/opcuaClient/src/main/java/com/mes/milo/utils/KeyStoreLoader.java
New file
@@ -0,0 +1,123 @@
package com.mes.milo.utils;
import lombok.extern.slf4j.Slf4j;
import org.eclipse.milo.opcua.stack.client.security.DefaultClientCertificateValidator;
import org.eclipse.milo.opcua.stack.core.security.DefaultTrustListManager;
import org.eclipse.milo.opcua.stack.core.util.SelfSignedCertificateBuilder;
import org.eclipse.milo.opcua.stack.core.util.SelfSignedCertificateGenerator;
import java.io.File;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.security.*;
import java.security.cert.X509Certificate;
import java.util.Arrays;
import java.util.regex.Pattern;
@Slf4j
public class KeyStoreLoader {
    private static final Pattern IP_ADDR_PATTERN = Pattern.compile(
            "^(([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\.){3}([01]?\\d\\d?|2[0-4]\\d|25[0-5])$");
    private static final String CLIENT_ALIAS = "client-ai";
    private static final char[] PASSWORD = "password".toCharArray();
    private X509Certificate clientCertificate;
    private X509Certificate[] clientCertificateChain;
    private KeyPair clientKeyPair;
    private DefaultClientCertificateValidator certificateValidator;
    public KeyStoreLoader load() throws Exception {
        Path securityTempDir = Paths.get(System.getProperty("java.io.tmpdir"), "security");
        Files.createDirectories(securityTempDir);
        if (!Files.exists(securityTempDir)) {
            throw new Exception("unable to create security dir: " + securityTempDir);
        }
        File pkiDir = securityTempDir.resolve("pki").toFile();
        log.info("security temp dir: {}", securityTempDir.toAbsolutePath());
        KeyStore keyStore = KeyStore.getInstance("PKCS12");
        Path serverKeyStore = securityTempDir.resolve("milo-client.pfx");
        DefaultTrustListManager trustListManager = new DefaultTrustListManager(pkiDir);
        certificateValidator = new DefaultClientCertificateValidator(trustListManager);
        log.info("Loading KeyStore at {}", serverKeyStore);
        if (!Files.exists(serverKeyStore)) {
            keyStore.load(null, PASSWORD);
            KeyPair keyPair = SelfSignedCertificateGenerator.generateRsaKeyPair(2048);
            SelfSignedCertificateBuilder builder = new SelfSignedCertificateBuilder(keyPair)
                    .setCommonName("Milo Client")
                    .setOrganization("kangaroohy")
                    .setOrganizationalUnit("dev")
                    .setLocalityName("Folsom")
                    .setStateName("CA")
                    .setCountryCode("US")
                    .setApplicationUri("urn:kangaroohy:milo:client")
                    .addDnsName("localhost")
                    .addIpAddress("127.0.0.1");
            // Get as many hostnames and IP addresses as we can listed in the certificate.
            for (String hostname : CustomUtil.getHostnames("0.0.0.0")) {
                if (IP_ADDR_PATTERN.matcher(hostname).matches()) {
                    builder.addIpAddress(hostname);
                } else {
                    builder.addDnsName(hostname);
                }
            }
            X509Certificate certificate = builder.build();
            keyStore.setKeyEntry(CLIENT_ALIAS, keyPair.getPrivate(), PASSWORD, new X509Certificate[]{certificate});
            try (OutputStream out = Files.newOutputStream(serverKeyStore)) {
                keyStore.store(out, PASSWORD);
            }
        } else {
            try (InputStream in = Files.newInputStream(serverKeyStore)) {
                keyStore.load(in, PASSWORD);
            }
        }
        Key clientPrivateKey = keyStore.getKey(CLIENT_ALIAS, PASSWORD);
        if (clientPrivateKey instanceof PrivateKey) {
            clientCertificate = (X509Certificate) keyStore.getCertificate(CLIENT_ALIAS);
            clientCertificateChain = Arrays.stream(keyStore.getCertificateChain(CLIENT_ALIAS))
                    .map(X509Certificate.class::cast)
                    .toArray(X509Certificate[]::new);
            PublicKey clientPublicKey = clientCertificate.getPublicKey();
            clientKeyPair = new KeyPair(clientPublicKey, (PrivateKey) clientPrivateKey);
        }
        return this;
    }
    public X509Certificate getClientCertificate() {
        return clientCertificate;
    }
    public X509Certificate[] getClientCertificateChain() {
        return clientCertificateChain;
    }
    public DefaultClientCertificateValidator getCertificateValidator() {
        return certificateValidator;
    }
    public KeyPair getClientKeyPair() {
        return clientKeyPair;
    }
}
hangzhoumesParent/common/opcuaClient/src/main/resources/META-INF/spring.factories
New file
@@ -0,0 +1,3 @@
# Auto Configure
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
  com.mes.milo.configuration.MiloAutoConfiguration
hangzhoumesParent/common/opcuaClient/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
New file
@@ -0,0 +1 @@
com.mes.milo.configuration.MiloAutoConfiguration
hangzhoumesParent/common/opcuaClient/src/main/resources/application.yml
New file
@@ -0,0 +1,9 @@
mes:
  milo:
    primary: default
    config:
      default:
        endpoint: opc.tcp://zidonghua:49320
        security-policy: basic256sha256
        username: zsh
        password: 1qaz2wsx3edc4rfv
hangzhoumesParent/common/pom.xml
@@ -15,6 +15,7 @@
    <modules>
        <module>servicebase</module>
        <module>springsecurity</module>
        <module>opcuaClient</module>
    </modules>
    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
hangzhoumesParent/moduleService/CacheGlassModule/src/main/java/com/mes/job/OpcCacheGlassTask.java
New file
@@ -0,0 +1,31 @@
package com.mes.job;
import com.mes.milo.runner.subscription.SubscriptionCallback;
import com.mes.milo.service.MiloService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import java.util.Arrays;
/**
 * @Author : zhoush
 * @Date: 2024/10/10 8:05
 * @Description:
 */
@Component
@Slf4j
public class OpcCacheGlassTask {
    @Autowired
    MiloService miloService;
    @Autowired
    SubscriptionCallback cacheGlassSubscriptionCallback;
    @Scheduled(fixedDelay = Long.MAX_VALUE)
    public void startOpcTask() throws Exception {
        miloService.subscriptionFromOpcUa(Arrays.asList("my.device.x1", "my.device.x2"), cacheGlassSubscriptionCallback);
    }
}
hangzhoumesParent/moduleService/CacheGlassModule/src/main/java/com/mes/job/entity/CacheGlassInfo.java
New file
@@ -0,0 +1,46 @@
package com.mes.job.entity;
import lombok.Data;
/**
 * @Author : zhoush
 * @Date: 2024/9/20 10:56
 * @Description:
 */
@Data
public class CacheGlassInfo {
    /**
     * 请求字
     */
    private String requestWord;
    /**
     * 请求字
     */
    private String confirmationWrod;
    /**
     * 玻璃id
     */
    private String glassId;
    /**
     * 机1状态
     */
    private String oneMachineState;
    /**
     * 机2状态
     */
    private String twoMachineState;
    /**
     * 一号卧式当前格子
     */
    private int oneCurrentSlot;
    /**
     * 二号卧式当前格子
     */
    private int twoCurrentSlot;
}
hangzhoumesParent/moduleService/CacheGlassModule/src/main/java/com/mes/opccallback/CacheGlassSubscriptionCallback.java
New file
@@ -0,0 +1,35 @@
package com.mes.opccallback;
import com.mes.milo.model.ReadWriteEntity;
import com.mes.milo.runner.subscription.SubscriptionCallback;
import com.mes.milo.service.MiloService;
import lombok.extern.slf4j.Slf4j;
import org.eclipse.milo.opcua.sdk.client.subscriptions.ManagedDataItem;
import org.eclipse.milo.opcua.stack.core.types.builtin.DataValue;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
/**
 * @Author : zhoush
 * @Date: 2024/10/10 14:13
 * @Description:
 */
@Service
@Slf4j
public class CacheGlassSubscriptionCallback implements SubscriptionCallback {
    @Autowired
    MiloService miloService;
    @Override
    public void onSubscribe(ManagedDataItem dataItem, DataValue value) {
        try {
            log.info("{}___________{}" + dataItem, value);
            ReadWriteEntity readWriteEntity = miloService.readFromOpcUa("my.device.x1");
            log.info("{}___________{}" + readWriteEntity);
        } catch (Exception e) {
        }
    }
}
hangzhoumesParent/moduleService/CacheGlassModule/src/main/resources/application.yml
@@ -27,4 +27,12 @@
      secondLength: 400
  sequence:
    order: false
  milo:
    primary: default
    config:
      default:
        endpoint: opc.tcp://127.0.0.1:49320
        security-policy: basic256sha256
        username: zsh
        password: 1qaz2wsx3edc4rfv
hangzhoumesParent/moduleService/pom.xml
@@ -55,6 +55,11 @@
            <groupId>com.mes</groupId>
            <version>1.0-SNAPSHOT</version>
        </dependency>
        <dependency>
            <artifactId>opcuaClient</artifactId>
            <groupId>com.mes</groupId>
            <version>1.0-SNAPSHOT</version>
        </dependency>
        <!--开发者工具-->
        <!--        <dependency>-->
hangzhoumesParent/moduleService/yiwumes/pom.xml
File was deleted
hangzhoumesParent/moduleService/yiwumes/src/main/java/com/mes/GlassStorageApplication.java
File was deleted
hangzhoumesParent/moduleService/yiwumes/src/main/java/com/mes/job/push.java
File was deleted
hangzhoumesParent/moduleService/yiwumes/src/main/java/com/mes/loadposition/controller/LoadPositionController.java
File was deleted
hangzhoumesParent/moduleService/yiwumes/src/main/java/com/mes/loadposition/entity/LoadPosition.java
File was deleted
hangzhoumesParent/moduleService/yiwumes/src/main/java/com/mes/loadposition/mapper/LoadPositionMapper.java
File was deleted
hangzhoumesParent/moduleService/yiwumes/src/main/java/com/mes/loadposition/mapper/LoadPositionMapper.xml
File was deleted
hangzhoumesParent/moduleService/yiwumes/src/main/java/com/mes/loadposition/service/LoadPositionService.java
File was deleted
hangzhoumesParent/moduleService/yiwumes/src/main/java/com/mes/loadposition/service/impl/LoadPositionServiceImpl.java
File was deleted
hangzhoumesParent/moduleService/yiwumes/src/main/java/com/mes/rawusage/controller/RawUsageController.java
File was deleted
hangzhoumesParent/moduleService/yiwumes/src/main/java/com/mes/rawusage/entity/RawUsage.java
File was deleted
hangzhoumesParent/moduleService/yiwumes/src/main/java/com/mes/rawusage/mapper/RawUsageMapper.java
File was deleted
hangzhoumesParent/moduleService/yiwumes/src/main/java/com/mes/rawusage/mapper/RawUsageMapper.xml
File was deleted
hangzhoumesParent/moduleService/yiwumes/src/main/java/com/mes/rawusage/service/RawUsageService.java
File was deleted
hangzhoumesParent/moduleService/yiwumes/src/main/java/com/mes/rawusage/service/impl/RawUsageServiceImpl.java
File was deleted
hangzhoumesParent/moduleService/yiwumes/src/main/java/com/mes/shelfrack/controller/ShelfRackController.java
File was deleted
hangzhoumesParent/moduleService/yiwumes/src/main/java/com/mes/shelfrack/entity/ShelfRack.java
File was deleted
hangzhoumesParent/moduleService/yiwumes/src/main/java/com/mes/shelfrack/entity/request/RawUsageAndShelfRack.java
File was deleted
hangzhoumesParent/moduleService/yiwumes/src/main/java/com/mes/shelfrack/mapper/ShelfRackMapper.java
File was deleted
hangzhoumesParent/moduleService/yiwumes/src/main/java/com/mes/shelfrack/service/ShelfRackService.java
File was deleted
hangzhoumesParent/moduleService/yiwumes/src/main/java/com/mes/shelfrack/service/impl/ShelfRackServiceImpl.java
File was deleted
hangzhoumesParent/moduleService/yiwumes/src/main/java/com/mes/storagetask/controller/StorageTaskController.java
File was deleted
hangzhoumesParent/moduleService/yiwumes/src/main/java/com/mes/storagetask/entity/StorageTask.java
File was deleted
hangzhoumesParent/moduleService/yiwumes/src/main/java/com/mes/storagetask/entity/request/StorageTaskRequest.java
File was deleted
hangzhoumesParent/moduleService/yiwumes/src/main/java/com/mes/storagetask/mapper/StorageTaskMapper.java
File was deleted
hangzhoumesParent/moduleService/yiwumes/src/main/java/com/mes/storagetask/service/StorageTaskService.java
File was deleted
hangzhoumesParent/moduleService/yiwumes/src/main/java/com/mes/storagetask/service/impl/StorageTaskServiceImpl.java
File was deleted
hangzhoumesParent/moduleService/yiwumes/src/main/resources/application-dev.yml
File was deleted
hangzhoumesParent/moduleService/yiwumes/src/main/resources/application-prod.yml
File was deleted
hangzhoumesParent/moduleService/yiwumes/src/main/resources/application.yml
File was deleted
hangzhoumesParent/moduleService/yiwumes/src/main/resources/mapper/ShelfRackMapper.xml
File was deleted
hangzhoumesParent/moduleService/yiwumes/src/main/resources/mapper/StorageTaskMapper.xml
File was deleted
hangzhoumesParent/moduleService/yiwumes/src/test/java/mes/GlassStorageModuleApplicationTest.java
File was deleted