zoukankan      html  css  js  c++  java
  • Java OPC 代码

    来源:https://www.cnblogs.com/ioufev/p/9929170.html

    1.任务详情

    • Java实现OPC通信的代码实现
    • 最终实现对西门子的S7-300的PLC变量的值读写

    2.实现情况

    说明

    • PC和PLC通信,PC用TAG1之类的地址,PLC用BD1.INT05之类的地址,个人总结的表格,方便说明
    OPCServer上定义的地址名称硬件PLC上的地址数据类型说明:这个地址做什么用的
    TAG1 DB1.INT00 short 心跳
    TAG2 DB1.INT02 short 控制字
    TAG3 DB1.STRING4,10 string 箱体信息
    TAG4 DB1.D14 float 结果
    • 地址定义在OPCServer上,实际截图

    • 制定交互流程:控制字的状态
    • 心跳变量:TAG1,表示软件和硬件(这里是PLC)连接状态,这个是自己随便定义的,我的是:PLC一直写1,PC收到1写2,5秒内一直收不到1就是断开了。
    • 控制字(状态变量):TAG2,作用是作为一个控制字,控制整个交互的流程,当是不同值时,PLC和PC要进行指定的读写动作。

    这是我一开始画的

    这是后来画的,就是PC和PLC的交互,比较清晰了

    实际的PLC地址编辑界面截图

    3. 代码实现

    • 按照官方例子写了一个通信类:通过配置信息,启动server,添加要读取的地址
    • 配置信息是单独一个类:从配置文件读取IP什么的
    • 然后是回调函数:某个地址,读到了某个值要怎么做,,在这就2个回调,心跳TAG1:读到1写入2,5秒超时,TAG2:是某个值时,怎么做。。。
    • 读值和写值可以单独算一个方法类:我用到的数据类型就是几个,short,string,Long Array,对应写了几个方法
    • OPCServer上的地址配置也算是一个单独的类:我写在配置文件了,当时犹豫是不是放到数据库,感觉差别不大
    • Utgard有两种数据访问方式——直接通过item的read/write方法或者使用AccessBase(读取数据)
    • 心跳TAG1:PC写2,PLC写1,逻辑是PC收到1写2,超时提示
    • 控制字TAG2:PLC写0,1,3,4,5,6/7,PC写2,8
      • PC在写TAG2=1时,同时写入TAG3值
      • PLC在写TAG2=6/7时,同时写入TAG4值
    • 读线程:每隔500ms读一次值,读到值后执行回调方法DataCallback()
      • 不用另起线程,直接用这个Access线程循环读取控制字的值,回调方法对应调用item的read/write方法读写值
    final AccessBase access = new SyncAccess(server, 500);
    access.addItem(itemId, new DataCallback() {
        @Override
        public void changed(Item item, ItemState state) {
            System.out.println("-----" + state);
        }
    });
    // start reading
    access.bind();
    

    4.代码:OPCserver连接配置类

    import java.io.IOException;
    import java.util.Properties;
    import org.openscada.opc.lib.common.ConnectionInformation;
    /**
     * 配置文件工具类
     */
    public final class OPCConfiguration {
        private final static ConnectionInformation ci;
        private final static Properties prop;
        public final static String CONFIG_USERNAME = "username";
        public final static String CONFIG_PASSWORD = "password";
        public final static String CONFIG_HOST = "host";
        public final static String CONFIG_DOMAIN = "domain";
        public final static String CONFIG_CLSID = "clsid";
        public final static String CONFIG_PROGID = "progid";
        private final static String CONFIG_FILE_NAME = "opc.properties";
        /**
         * 加载配置文件
         */
        static {
            ci = new ConnectionInformation();
            prop = new Properties();
            try {
                prop.load(OPCConfiguration.class.getClassLoader().getResourceAsStream(CONFIG_FILE_NAME));
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        /**
         * 通过名字获得配置的值
         */
        public static String getEntryValue(String name) {
            return prop.getProperty(name);
        }
        /**
         * 获得包含ClsId的连接信息
         */
        public static ConnectionInformation getCLSIDConnectionInfomation() {
            ci.setProgId(null);
            getConnectionInfomation();
            ci.setClsid(prop.getProperty(CONFIG_CLSID));
            return ci;
        }
        /**
         * 获得包含ProgId的连接信息
         */
        public static ConnectionInformation getPROGIDConnectionInfomation() {
            ci.setClsid(null);
            getConnectionInfomation();
            ci.setProgId(prop.getProperty(CONFIG_PROGID));
            return ci;
        }
        /**
         * 获得基础的连接信息
         */
        private static void getConnectionInfomation() {
            ci.setHost(prop.getProperty(CONFIG_HOST));
            ci.setDomain(prop.getProperty(CONFIG_DOMAIN));
            ci.setUser(prop.getProperty(CONFIG_USERNAME));
            ci.setPassword(prop.getProperty(CONFIG_PASSWORD));
        }
    }
    

    5.代码:通信实现类

    package cn.com.tcb.assembly.management.listener;
    import static cn.com.tcb.assembly.management.listener.OPCConfiguration.getCLSIDConnectionInfomation;
    import java.util.concurrent.Executors;
    import org.jinterop.dcom.common.JIException;
    import org.openscada.opc.lib.common.ConnectionInformation;
    import org.openscada.opc.lib.da.AccessBase;
    import org.openscada.opc.lib.da.Group;
    import org.openscada.opc.lib.da.Item;
    import org.openscada.opc.lib.da.Server;
    import org.openscada.opc.lib.da.SyncAccess;
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    /**
     * 功能:OPC通信线程 描述:通过循环读取心跳和状态控制字,按照商议好的交互流程读写变量
     */
    public class OPCComm {
        private static Logger logger = LoggerFactory.getLogger(OPCComm.class);
        private Item item_heartbeat;
        private Item item_status;
        private Item item_ordernum;
        private Item item_sn;
        private Item item_boxnum;
        private Item item_abnormal;
        private Item item_finish;
        private Item item_result;
        private Server server;
        /**
         * 单例模式
         */
        private static class SingletonHolder {
            static final OPCComm doOPCComm = new OPCComm();
        }
        public static OPCComm getInstance() {
            return SingletonHolder.doOPCComm;
        }
        /**
         * 启动server 创建一个监控线程 创建一个写入线程
         */
        public void init() throws Exception {
            // 加载配置文件
            final ConnectionInformation ci = getCLSIDConnectionInfomation();
            // 创建server
            final Server server = new Server(ci, Executors.newSingleThreadScheduledExecutor());
            try {
                // 启动server
                server.connect();
                logger.info("This is {} message.", "OPCserver connect success");
                this.server = server;
                // 同步读取,500ms一次
                final AccessBase access = new SyncAccess(server, 500);
                access.addItem(OPCElement.ITEMID_HEARTBEAT, new DataCallBack_HeartBeat());
                access.addItem(OPCElement.ITEMID_STATUS, new DataCallBack_Status());
                // 添加一个组
                final Group group = server.addGroup("sew");
                item_heartbeat = group.addItem(OPCElement.ITEMID_HEARTBEAT);
                item_status = group.addItem(OPCElement.ITEMID_STATUS);
                item_ordernum = group.addItem(OPCElement.ITEMID_ORDERNUM);
                item_sn = group.addItem(OPCElement.ITEMID_SN);
                item_boxnum = group.addItem(OPCElement.ITEMID_BOXNUM);
                item_abnormal = group.addItem(OPCElement.ITEMID_ABNORMAL);
                item_finish = group.addItem(OPCElement.ITEMID_FINISH);
                item_result = group.addItem(OPCElement.ITEMID_RESULT);
                // start reading
                access.bind();
            } catch (final JIException e) {
                System.out.println(String.format("%08X: %s", e.getErrorCode(), server.getErrorMessage(e.getErrorCode())));
            }
        }
        public Item getItem_heartbeat() {
            return item_heartbeat;
        }
        public Item getItem_status() {
            return item_status;
        }
        public Item getItem_ordernum() {
            return item_ordernum;
        }
        public Item getItem_sn() {
            return item_sn;
        }
        public Item getItem_boxnum() {
            return item_boxnum;
        }
        public Item getItem_abnormal() {
            return item_abnormal;
        }
        public Item getItem_finish() {
            return item_finish;
        }
        public Item getItem_result() {
            return item_result;
        }
        public Server getServer() {
            return server;
        }
    }
    

    6.代码:工具类:读写值

    package cn.com.tcb.assembly.management.listener;
    
    import java.text.DecimalFormat;
    
    import org.jinterop.dcom.common.JIException;
    import org.jinterop.dcom.core.JIArray;
    import org.jinterop.dcom.core.JIVariant;
    import org.openscada.opc.lib.da.Item;
    import org.openscada.opc.lib.da.ItemState;
    
    public class OPCUnit {
    
        /**
         * 写值到变量
         */
        public static void write(Item item, String val) {
            try {
                JIVariant value = new JIVariant(val);
                item.write(value);
            } catch (JIException e) {
                e.printStackTrace();
            }
        }
    
        /**
         * 写值到变量:数组
         */
        public static void write(Item item, String[] snArray) {
            try {
    
                /** 构造写入数据 */
                Long[] integerData = new Long[snArray.length];
                for (int i = 0; i < snArray.length; i++) {
                    integerData[i] = Long.valueOf(snArray[i]);
                }
                final JIArray array = new JIArray(integerData, false);
                final JIVariant value = new JIVariant(array);
    
                item.write(value);
            } catch (JIException e) {
                e.printStackTrace();
            }
        }
    
        /**
         * 读变量的值 如果是short和int直接返回字符串; 如果是long类型的数组,返回数字内容间加点,对应long,数组,大小为6
         * 如果是float类型的数组,返回数字内容间加逗号,对应float,数组,大小为20
         */
        public static String read(Item item) {
            String result = "";
            try {
                ItemState state = item.read(true);
                int type = state.getValue().getType();
    
                if (type == JIVariant.VT_UI4) {
                    int value = state.getValue().getObjectAsInt();
                    return value + "";
                } else if (type == JIVariant.VT_I2) {
                    short value = state.getValue().getObjectAsShort();
                    return value + "";
                } else if (type == 8195) {
                    JIArray jarr = state.getValue().getObjectAsArray();
                    Integer[] arr = (Integer[]) jarr.getArrayInstance();
                    String value = "";
                    for (Integer i : arr) {
                        value = value + i + ".";
                    }
                    String res = value.substring(0, value.length() - 1);
                    // "25.36087601.1.1.18.36"-->"25.36087601.01.0001.18.36"
                    String[] array = res.split("[.]");
                    String ress = array[0] + "." + array[1] + "." + new DecimalFormat("00").format(Long.valueOf(array[2]))
                            + "." + new DecimalFormat("0000").format(Long.valueOf(array[3])) + "." + array[4] + "."
                            + array[5];
                    return ress;
    
                } else if (type == 8196) {
                    JIArray jarr = state.getValue().getObjectAsArray();
                    Float[] arr = (Float[]) jarr.getArrayInstance();
                    String value = "";
                    for (Float f : arr) {
                        value = value + f + ",";
                    }
                    return value.substring(0, value.length() - 1);
                }
    
            } catch (JIException e) {
                e.printStackTrace();
            }
            return result;
        }
    
    }
    

    7.代码:回调函数:实现心跳

    package cn.com.tcb.assembly.management.listener;
    import java.awt.Color;
    import org.jinterop.dcom.common.JIException;
    import org.jinterop.dcom.core.JIVariant;
    import org.openscada.opc.lib.da.DataCallback;
    import org.openscada.opc.lib.da.Item;
    import org.openscada.opc.lib.da.ItemState;
    import cn.com.tcb.assembly.base.core.AppContext;
    import cn.com.tcb.assembly.base.utils.GlobalVariable;
    import cn.com.tcb.assembly.management.ui.main.MainFrame;
    public class DataCallBack_HeartBeat implements DataCallback {
        private OPCComm opc = OPCComm.getInstance();
        private int count = 0;@
        Override
        public void changed(Item item, ItemState state) {
            // 读取心跳变量的值
            try {
                if (state.getValue().getType() == JIVariant.VT_I2) {
                    short n = state.getValue().getObjectAsShort();
                    setHeartbeat(n);
                }
            } catch (JIException e) {
                e.printStackTrace();
            }
        }
        /**
         * 设置心跳标志位,保存到全局变量
         */
        public void setHeartbeat(short n) {
            MainFrame main = (MainFrame) AppContext.getParam(GlobalVariable.MAIN_UI);
            if (n == 1) {
                OPCUnit.write(opc.getItem_heartbeat(), "2");
                GlobalVariable.heartbeat = true;
                main.getHeartbeat().setBackground(Color.GREEN);
                count = 0;
            } else {
                count++;
            }
            // 循环读取频率是:500ms一次,如果超过6次,也就是3s认定超时
            if (count > 6) {
                GlobalVariable.heartbeat = false;
                main.getHeartbeat().setBackground(Color.RED);
            }
        }
    }
    

    8.代码:回调函数:实现业务

    package cn.com.tcb.assembly.management.listener;
    
    import java.awt.Color;
    
    import org.jinterop.dcom.common.JIException;
    import org.jinterop.dcom.core.JIVariant;
    import org.openscada.opc.lib.da.DataCallback;
    import org.openscada.opc.lib.da.Item;
    import org.openscada.opc.lib.da.ItemState;
    import cn.com.tcb.assembly.base.core.AppContext;
    import cn.com.tcb.assembly.base.core.BeanContainer;
    import cn.com.tcb.assembly.base.model.JobCard;
    import cn.com.tcb.assembly.base.model.TestResult;
    import cn.com.tcb.assembly.base.service.JobCardService;
    import cn.com.tcb.assembly.base.service.TestResultService;
    import cn.com.tcb.assembly.base.utils.GlobalVariable;
    import cn.com.tcb.assembly.base.utils.StringUtil;
    import cn.com.tcb.assembly.management.ui.main.MainFrame;
    
    /**
     * 根据控制字:向PLC写入工单信息,保存结果
     */
    public class DataCallBack_Status implements DataCallback {
        private OPCComm opc = OPCComm.getInstance();
        private TestResultService testResultService = (TestResultService) BeanContainer.getBean("testResultService");
        private MainFrame main = (MainFrame) AppContext.getParam(GlobalVariable.MAIN_UI);
    
        @Override
        public void changed(Item item, ItemState itemState) {
    
            // 读取状态变量的值
            try {
                if (itemState.getValue().getType() == JIVariant.VT_I2) {
                    short n = itemState.getValue().getObjectAsShort();
    
                    // 前提是有心跳
                    if (GlobalVariable.heartbeat) {
                        doProcess(n);
                    }
                }
            } catch (JIException e) {
                e.printStackTrace();
            }
        }
    
        /**
         * 状态控制字: 0:PLC上电,1:允许新工单,2:新任务,3:收到任务,4:准备执行,5:开始执行 6:正常完成,7:异常玩常完成,8:收到完成信号
         */
        private void doProcess(short n) {
            if (n == 0) {
                setStatus(Color.GREEN, "等待设备初始化");
                GlobalVariable.isAllowInput = true;
            } else if (n == 1) {
                setStatus(Color.GREEN, "请输入工单");
                GlobalVariable.isAllowInput = true;
            } else if (n == 2) {
                setStatus(Color.GREEN, "发送成功,等待设备处理");
            } else if (n == 3) {
                setStatus(Color.GREEN, "设备收到工单");
                GlobalVariable.isAllowInput = false;
            } else if (n == 4) {
                setStatus(Color.GREEN, "设备准备执行");
                GlobalVariable.isAllowInput = false;
            } else if (n == 5) {
                setStatus(Color.GREEN, "设备开始执行");
                GlobalVariable.isAllowInput = false;
                // 写入初始结果,记录开始时间
                if (!GlobalVariable.isHaveOrder) {
                    reconnectAction();
                } else {
                    saveStartResult();
                }
    
            } else if (n == 6) {
                setStatus(Color.GREEN, "正常完成");
    
                // 写入最终结果,记录结束时间
                if (!GlobalVariable.isHaveOrder) {
                    reconnectAction();
                }
                saveEndResult(OPCControllerState.NORMALEND);
    
            } else if (n == 7) {
                setStatus(Color.RED, "异常完成");
    
                // 写入最终结果,记录结束时间
                if (!GlobalVariable.isHaveOrder) {
                    reconnectAction();
                }
                saveEndResult(OPCControllerState.ABNORMALEND);
    
            } else if (n == OPCControllerState.SAVESUCCESS) {
                setStatus("结果保存成功");
            } else {
                setStatus(Color.RED, "异常");
            }
        }
    
        /**
         * 设置主界面状态信息
         */
        private void setStatus(Color color, String status) {
            main.getStatus().setText(status);
            main.getStatus().setBackground(color);
        }
    
        private void setStatus(String status) {
            main.getStatus().setText(status);
        }
    
        /**
         * 保存初始结果:5
         */
        private void saveStartResult() {
            if (!GlobalVariable.isSaveStartSuccess) {
                // 从全局变量获取结果表
                TestResult t = (TestResult) AppContext.getParam(GlobalVariable.PARAM_KEY_TESTRESULT);
    
                // 开始时间
                String startTime = testResultService.getDate();
                t.setStartTime(startTime);
                main.getStartTime().setText(startTime);
    
                // 装配日期
                t.setDate(startTime.split("[ ]")[0]);
    
                // 保存结果表到全局变量
                AppContext.setParam(GlobalVariable.PARAM_KEY_TESTRESULT, t);
    
                // 保存结果到数据库
                int n = testResultService.getSqlServerCountBySerialNumber(t.getSerialNumber());
                if (n == 0) {
                    testResultService.saveResult(t);
                } else {
                    testResultService.updateResult(t);
                }
    
                GlobalVariable.isSaveStartSuccess = true;
            }
        }
    
        /**
         * 保存最终结果:6或者7
         */
        private void saveEndResult(int n) {
            if (!GlobalVariable.isSaveEndSuccess) {
    
                // 从全局变量获取结果表
                TestResult t = (TestResult) AppContext.getParam(GlobalVariable.PARAM_KEY_TESTRESULT);
    
                // 保存结果到界面
                String endTime = testResultService.getDate();
                t.setEndTime(endTime);
                main.getEndTime().setText(endTime);
    
                String time = StringUtil.getTimeBetween(t.getStartTime(), endTime);
                t.setTime(time);
                main.getTime().setText(time);
    
                String value = OPCUnit.read(opc.getItem_result());
                String result = "";
                String[] arr = value.split("[,]");
                result = arr[0] + "-" + arr[1];
                for (int i = 2; i < arr.length; i = i + 2) {
                    result = result + dealWith(arr[i], arr[i + 1]);
                }
                main.getResult01().setText(dealWithShow(arr[0], arr[1]));
                main.getResult02().setText(dealWithShow(arr[2], arr[3]));
                main.getResult03().setText(dealWithShow(arr[4], arr[5]));
                main.getResult04().setText(dealWithShow(arr[6], arr[7]));
                main.getResult05().setText(dealWithShow(arr[8], arr[9]));
                main.getResult06().setText(dealWithShow(arr[10], arr[11]));
                main.getResult07().setText(dealWithShow(arr[12], arr[13]));
                main.getResult08().setText(dealWithShow(arr[14], arr[15]));
                main.getResult09().setText(dealWithShow(arr[16], arr[17]));
                main.getResult10().setText(dealWithShow(arr[18], arr[19]));
    
                t.setResult(result);
    
                // 异常
                if (n == OPCControllerState.NORMALEND) {
                    t.setAbnormal("否");
                } else {
                    t.setAbnormal("是");
                }
    
                // 保存最终结果到数据库
                testResultService.updateResult(t);
    
                // 当前工单已经完成
                GlobalVariable.isHaveOrder = false;
    
                // 写入状态字
                OPCUnit.write(opc.getItem_status(), “8”);
    
                // 读取成功后不再重复读取
                GlobalVariable.isSaveEndSuccess = true;
            }
        }
    
        /**
         * 断线重连动作
         */
        private void reconnectAction() {
            String sn = OPCUnit.read(opc.getItem_sn());
            // 根据序列号查询初始保存的结果
            TestResult t = testResultService.getOneDataBySerialNumber(sn);
            AppContext.setParam(GlobalVariable.PARAM_KEY_TESTRESULT, t);
    
            // 工单恢复
            JobCardService jcs = (JobCardService) BeanContainer.getBean("jobCardService");
            JobCard job = jcs.getJobCardData(t.getOrderNum());
            job.setSerialNumber(t.getSerialNumber());
            AppContext.setParam(GlobalVariable.PARAM_KEY_JOBCARD, job); // 保存工单信息到全局变量
    
            // 界面恢复
            main.getOrderNumber().setText(t.getOrderNum());
            main.getSn().setText(t.getSerialNumber());
            main.getUnitType().setText(t.getUnitSize());
            main.getBoxNumber().setText(t.getUnitSize().split(" ")[0]);
            main.getSn_count().setText(Integer.parseInt(t.getSerialNumber().split("[.]")[3]) + "");
            main.getCount().setText(job.getCount());
            main.getStartTime().setText(t.getStartTime());
    
            GlobalVariable.isHaveOrder = true;
        }
    
        /**
         * 处理结果字符串
         */
        private String dealWith(String str1, String str2) {
            if (str1.equals("0.0") && str2.equals("0.0")) {
                return "";
            }
            return ", " + str1 + "-" + str2;
        }
    
        private String dealWithShow(String str1, String str2) {
            if (str1.equals("0.0") && str2.equals("0.0")) {
                return "";
            }
            return str1 + "-" + str2;
        }
    }
    

    9.配合业务:发送信息到PLC

    package cn.com.tcb.assembly.management.action.main;
    
    import java.awt.Color;
    import java.awt.event.ActionEvent;
    import java.awt.event.ActionListener;
    
    import cn.com.tcb.assembly.base.core.AppContext;
    import cn.com.tcb.assembly.base.core.BeanContainer;
    import cn.com.tcb.assembly.base.core.LocalDataStore;
    import cn.com.tcb.assembly.base.core.ui.PopupDialog;
    import cn.com.tcb.assembly.base.core.ui.PopupManager;
    import cn.com.tcb.assembly.base.model.JobCard;
    import cn.com.tcb.assembly.base.model.TestResult;
    import cn.com.tcb.assembly.base.model.User;
    import cn.com.tcb.assembly.base.service.TestResultService;
    import cn.com.tcb.assembly.base.utils.GlobalVariable;
    import cn.com.tcb.assembly.management.listener.OPCComm;
    import cn.com.tcb.assembly.management.listener.OPCUnit;
    import cn.com.tcb.assembly.management.ui.main.MainFrame;
    
    /**
     * 发送按钮,发送工单信息到PLC
     */
    public class SendAction implements ActionListener {
        private TestResultService testResultService = (TestResultService) BeanContainer.getBean("testResultService");
        private OPCComm opc = OPCComm.getInstance();
        private MainFrame main;
    
        public SendAction(MainFrame mainFrame) {
            main = mainFrame;
        }
    
        @Override
        public void actionPerformed(ActionEvent e) {
            inputJobCard();
        }
    
        private void inputJobCard() {
    
            // 如果设备正在运行,则不允许发送
    
            // 如果有工单就能发送
            if (GlobalVariable.isHaveOrder) {
    
                // 从全局变量获取工单信息
                JobCard job = (JobCard) AppContext.getParam(GlobalVariable.PARAM_KEY_JOBCARD);
                
                // 判定是否重做
                int n = testResultService.getSqlServerCountBySerialNumber(job.getSerialNumber());
                if(n != 0 && !optionDialog("已有工单,是否重做?")) {
                    return;
                }
                
                // 创建结果表
                TestResult t = new TestResult();
    
                // 写入工单号
                String orderNum = job.getOrderNum();
                t.setOrderNum(orderNum);
                OPCUnit.write(opc.getItem_ordernum(), orderNum);
    
                // 写入序列号
                String sn = job.getSerialNumber();
                t.setSerialNumber(sn);
                OPCUnit.write(opc.getItem_sn(), sn.split("[.]"));
    
                // 写入箱体号
                String unitSize = job.getUnitSize();
                t.setUnitSize(unitSize);
                OPCUnit.write(opc.getItem_boxnum(), unitSize.split(" ")[0]);
    
                // 装配机
                String assembly = LocalDataStore.read("localName");
                t.setAssembly(assembly);
                // 操作员
                User user = (User) AppContext.getParam(GlobalVariable.PARAM_KEY_USER);
                t.setOperator(user.getUserName());
                // 异常
                t.setAbnormal("是");
    
                // 保存结果表到全局变量
                AppContext.setParam(GlobalVariable.PARAM_KEY_TESTRESULT, t);
    
                // 写入状态字
                OPCUnit.write(opc.getItem_status(), "2");
    
                // 焦点返回扫码框
                main.getScanCode().requestFocus();
    
                // 状态信息
                setStatus(Color.GREEN, "发送成功,等待设备处理");
            }
        }
    
        /**
         * 设置主界面状态信息
         */
        private void setStatus(Color color, String status) {
            main.getStatus().setText(status);
            main.getStatus().setBackground(color);
        }
        
        /**
         * @Title: optionDialog
         * @Description: 选择弹窗,默认选择:是
         */
        private boolean optionDialog(String message) {
            int i = PopupDialog.open(PopupManager.DEFAULT, "提醒窗口", message, new String[] { "是", "否" }, new int[] { 1, 2 },
                    1, 2);
            if (i == 1) {
                return true;
            } else {
                return false;
            }
        }
    }
    

    10.地址变量

    package cn.com.tcb.assembly.management.listener;
    
    import java.io.IOException;
    import java.util.Properties;
    
    /**
     * @ClassName: OPCElement
     * @Description: PC和PLC通信使用的OPCserver上的标记名称列表
     */
    public class OPCElement {
    	private final static Properties prop;
    	private final static String CONFIG_FILE_NAME = "opc_list.properties";
    
    	/**
    	 * 加载配置文件
    	 */
    	static {
    		prop = new Properties();
    		try {
    			prop.load(OPCElement.class.getClassLoader().getResourceAsStream(CONFIG_FILE_NAME));
    		} catch (IOException e) {
    			e.printStackTrace();
    		}
    	}
    
    	/**
    	 * 心跳: 读到1,写入2
    	 */
    	public static final String ITEMID_HEARTBEAT = prop.getProperty("addr01");
    
    	/**
    	 * 状态控制字: 0:PLC上电,1:允许新工单,2:新任务,3:收到任务,4:准备执行,5:开始执行 6:正常完成,7:异常玩常完成,8:收到完成信号
    	 */
    	public static final String ITEMID_STATUS = prop.getProperty("addr02");
    
    	/**
    	 * 工单号:7位工单号,如:5332087
    	 */
    	public static final String ITEMID_ORDERNUM = prop.getProperty("addr03");
    
    	/**
    	 * 序列号,长整型,数组[6]
    	 */
    	public static final String ITEMID_SN = prop.getProperty("addr04");
    
    	/**
    	 * 箱体号:字符串,如:“R27”
    	 */
    	public static final String ITEMID_BOXNUM = prop.getProperty("addr12");
    
    	/**
    	 * 异常代码:暂时没用
    	 */
    	public static final String ITEMID_ABNORMAL = prop.getProperty("addr06");
    
    	/**
    	 * 完成信号:暂时没用
    	 */
    	public static final String ITEMID_FINISH = prop.getProperty("addr07");
    
    	/**
    	 * 结果:浮点型,数组[20]
    	 */
    	public static final String ITEMID_RESULT = prop.getProperty("addr08");
    	
    	/**
    	 * 装配策略,内容:箱体号-轴s数量:字符串,如:“R107-2”
    	 */
    	public static final String ITEMID_STRATEGY = prop.getProperty("addr05");
    
    	/**
    	 * 工单号:7位工单号,如:5332087,,用来扫码发送
    	 */
    	public static final String ITEMID_BARCODE = prop.getProperty("addr10");
    	
    	/**
    	 * 垫片值:浮点型,数组[8]
    	 */
    	public static final String ITEMID_GASKET = prop.getProperty("addr11");
    	
    	/**
    	 * 安装方式:字符串,如:“M1”
    	 */
    	public static final String ITEMID_MP = prop.getProperty("addr09");
    	
    	/**
    	 * 轴数量:字符串,如:“2”,“3”
    	 */
    	public static final String ITEMID_SHAFT = prop.getProperty("addr13");
    }
    

    地址写在了配置文件里

    opc_list.properties

    #heartbeat:short
    addr01=PLC.S7-300.TAG1
    #control:short
    addr02=PLC.S7-300.TAG2
    #orderNum:long
    addr03=PLC.S7-300.TAG3
    #sn:long,array[6]
    addr04=PLC.S7-300.TAG4
    #Strategy:string
    addr05=PLC.S7-300.TAG5
    #abnormal:short
    addr06=PLC.S7-300.TAG6
    #finish:short
    addr07=PLC.S7-300.TAG7
    #result:float,array[20]
    addr08=PLC.S7-300.TAG8
    #MP:string
    addr09=PLC.S7-300.TAG9
    #barcode:long
    addr10=PLC.S7-300.TAG10
    #gasket:float,array[8]
    addr11=PLC.S7-300.TAG11
    #boxNum:string
    addr12=PLC.S7-300.TAG12
    #shaft:string
    addr13=PLC.S7-300.TAG13
    

    11.其他

    另一个项目的,配置地址写在了代码里

    OPCClient.java

    package cn.com.tcb.uavpcs.datacenter.comm.plc.opcclient;
    
    import java.util.HashMap;
    import java.util.Map;
    import java.util.concurrent.Executors;
    
    import org.jinterop.dcom.common.JIException;
    import org.openscada.opc.lib.common.ConnectionInformation;
    import org.openscada.opc.lib.da.AccessBase;
    import org.openscada.opc.lib.da.Group;
    import org.openscada.opc.lib.da.Item;
    import org.openscada.opc.lib.da.Server;
    import org.openscada.opc.lib.da.SyncAccess;
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Component;
    
    import cn.com.tcb.uavpcs.datacenter.comm.plc.opcclient.callbacks.OvenCrossCallback;
    import cn.com.tcb.uavpcs.datacenter.comm.plc.opcclient.callbacks.CrossCallbackFactory;
    import cn.com.tcb.uavpcs.datacenter.comm.plc.opcclient.callbacks.OvenMoveCallBackFactory;
    import cn.com.tcb.uavpcs.datacenter.comm.plc.opcclient.callbacks.StationCallBack;
    import cn.com.tcb.uavpcs.datacenter.comm.plc.opcclient.items.OPCItems;
    import cn.com.tcb.uavpcs.datacenter.linecontrol.LineModel;
    
    /**
     * OPC客户端,用于同PLC通信,通过OPC服务器,
     * 
     */
    @Component
    public class OPCClient {
    	private static Logger logger = LoggerFactory.getLogger(OPCClient.class);
    
    	public final static Map<String, Item> ITEMS = new HashMap<String, Item>();// 所有的变量对象
    	@Autowired
    	private OPCConfig config;
    
    	private AccessBase access;
    
    	public void start() throws Exception {
    		logger.info("OPC客户端初始化启动");
    
    		// 连接信息
    		ConnectionInformation ci = new ConnectionInformation();
    		ci.setHost(config.getHost());// 主机地址
    		ci.setUser(config.getUser());// 用户名
    		ci.setPassword(config.getPassword());// 密码
    		ci.setClsid(config.getClsid());// clsId,使用DCOM组件的clsId连接OPC服务器
    		// 连接服务器
    		Server server = new Server(ci, Executors.newSingleThreadScheduledExecutor());
    		server.connect();
    		// 变量组
    		Group group = server.addGroup();
    
    		// 变量统一加入组,方便以后读写
    		// 路口动作
    		addItem(group, OPCItems.ITEM_CROSS_ACTION_1);
    		addItem(group, OPCItems.ITEM_CROSS_ACTION_2);
    		addItem(group, OPCItems.ITEM_CROSS_ACTION_3);
    		addItem(group, OPCItems.ITEM_CROSS_ACTION_4);
    		addItem(group, OPCItems.ITEM_CROSS_ACTION_5);
    		addItem(group, OPCItems.ITEM_CROSS_ACTION_6);
    		addItem(group, OPCItems.ITEM_CROSS_ACTION_7);
    		addItem(group, OPCItems.ITEM_CROSS_ACTION_8);
    		// 托盘进出gongwei
    		addItem(group, OPCItems.ITEM_CROSS_FROM_1);
    		addItem(group, OPCItems.ITEM_CROSS_FROM_2);
    		addItem(group, OPCItems.ITEM_CROSS_FROM_3);
    		addItem(group, OPCItems.ITEM_CROSS_FROM_4);
    		addItem(group, OPCItems.ITEM_CROSS_FROM_5);
    		addItem(group, OPCItems.ITEM_CROSS_FROM_6);
    		addItem(group, OPCItems.ITEM_CROSS_FROM_7);
    		addItem(group, OPCItems.ITEM_CROSS_FROM_8);
    		// 线体1烘箱存取
    		addItem(group, OPCItems.ITEM_OVEN_ACTION_1);
    		addItem(group, OPCItems.ITEM_OVEN_COLUMN_1);
    		addItem(group, OPCItems.ITEM_OVEN_LAYER_1);
    		addItem(group, OPCItems.ITEM_OVEN_ROW_1);
    		addItem(group, OPCItems.ITEM_OVEN_STATE_1);
    		// 线体2烘箱存取
    		addItem(group, OPCItems.ITEM_OVEN_ACTION_2);
    		addItem(group, OPCItems.ITEM_OVEN_COLUMN_2);
    		addItem(group, OPCItems.ITEM_OVEN_LAYER_2);
    		addItem(group, OPCItems.ITEM_OVEN_ROW_2);
    		addItem(group, OPCItems.ITEM_OVEN_STATE_2);
    
    		access = new SyncAccess(server, 500);
    
    		// 路口动作
    		access.addItem(OPCItems.ITEM_CROSS_1, CrossCallbackFactory.build(LineModel.CROSS_ID_1));
    		access.addItem(OPCItems.ITEM_CROSS_2, CrossCallbackFactory.build(LineModel.CROSS_ID_2));
    		access.addItem(OPCItems.ITEM_CROSS_3, CrossCallbackFactory.build(LineModel.CROSS_ID_3));
    		access.addItem(OPCItems.ITEM_CROSS_4, new OvenCrossCallback(LineModel.LINE_ID_1));// 烘箱路口,线体1
    
    		access.addItem(OPCItems.ITEM_CROSS_5, CrossCallbackFactory.build(LineModel.CROSS_ID_5));
    		access.addItem(OPCItems.ITEM_CROSS_6, CrossCallbackFactory.build(LineModel.CROSS_ID_6));
    		access.addItem(OPCItems.ITEM_CROSS_7, CrossCallbackFactory.build(LineModel.CROSS_ID_7));
    		access.addItem(OPCItems.ITEM_CROSS_8, new OvenCrossCallback(LineModel.LINE_ID_2));// 烘箱路口,线体2
    
    		// 线体1,烘箱存取
    		access.addItem(OPCItems.ITEM_OVEN_STATE_1, OvenMoveCallBackFactory.build(LineModel.LINE_ID_1));// 烘箱存取托盘,线体1
    
    		// 线体2,烘箱存取
    		access.addItem(OPCItems.ITEM_OVEN_STATE_2, OvenMoveCallBackFactory.build(LineModel.LINE_ID_2));// 烘箱存取托盘,线体2
    
    		// 工位按钮动作
    		access.addItem(OPCItems.ITEM_STATION_1, new StationCallBack(LineModel.STATION_ID_1));
    		access.addItem(OPCItems.ITEM_STATION_2, new StationCallBack(LineModel.STATION_ID_2));
    		access.addItem(OPCItems.ITEM_STATION_3, new StationCallBack(LineModel.STATION_ID_3));
    		access.addItem(OPCItems.ITEM_STATION_4, new StationCallBack(LineModel.STATION_ID_4));
    		access.addItem(OPCItems.ITEM_STATION_5, new StationCallBack(LineModel.STATION_ID_5));
    		access.addItem(OPCItems.ITEM_STATION_6, new StationCallBack(LineModel.STATION_ID_6));
    		access.addItem(OPCItems.ITEM_STATION_7, new StationCallBack(LineModel.STATION_ID_7));
    		access.addItem(OPCItems.ITEM_STATION_8, new StationCallBack(LineModel.STATION_ID_8));
    		access.addItem(OPCItems.ITEM_STATION_9, new StationCallBack(LineModel.STATION_ID_9));
    		access.addItem(OPCItems.ITEM_STATION_10, new StationCallBack(LineModel.STATION_ID_10));
    		access.addItem(OPCItems.ITEM_STATION_11, new StationCallBack(LineModel.STATION_ID_11));
    		access.addItem(OPCItems.ITEM_STATION_12, new StationCallBack(LineModel.STATION_ID_12));
    
    		// 绑定,开始读取
    		access.bind();
    
    		// Thread.sleep(100 * 1000);// 延时停止
    		// access.unbind();// 结束绑定
    		logger.info("OPC客户端初始化启动完成");
    	}
    
    	private void addItem(Group group, String itemId) throws Exception {
    		Item item = group.addItem(itemId);
    		ITEMS.put(itemId, item);
    	}
    
    	public void stop() {
    		try {
    			access.unbind();
    		} catch (JIException e) {
    			// TODO Auto-generated catch block
    			e.printStackTrace();
    		}
    	}
    }
    
    

    OPCItems.java

    package cn.com.tcb.uavpcs.datacenter.comm.plc.opcclient.items;
    
    import java.util.HashMap;
    import java.util.Map;
    
    /**
     * 相关PLC变量在OPC服务器上的标签
     *
     */
    public class OPCItems {
    	// 路口,状态,对应8个路口,int
    	public final static String ITEM_CROSS_1 = "u.u.cross1";
    	public final static String ITEM_CROSS_2 = "u.u.cross2";
    	public final static String ITEM_CROSS_3 = "u.u.cross3";
    	public final static String ITEM_CROSS_4 = "u.u.cross4";
    	public final static String ITEM_CROSS_5 = "u.u.cross5";
    	public final static String ITEM_CROSS_6 = "u.u.cross6";
    	public final static String ITEM_CROSS_7 = "u.u.cross7";
    	public final static String ITEM_CROSS_8 = "u.u.cross8";
    	// 路口,动作,对应8个路口,int
    	public final static String ITEM_CROSS_FROM_1 = "u.u.from1";
    	public final static String ITEM_CROSS_FROM_2 = "u.u.from2";
    	public final static String ITEM_CROSS_FROM_3 = "u.u.from3";
    	public final static String ITEM_CROSS_FROM_4 = "u.u.from4";
    	public final static String ITEM_CROSS_FROM_5 = "u.u.from5";
    	public final static String ITEM_CROSS_FROM_6 = "u.u.from6";
    	public final static String ITEM_CROSS_FROM_7 = "u.u.from7";
    	public final static String ITEM_CROSS_FROM_8 = "u.u.from8";
    	// 路口,条码,对应8个路口,String
    	// public final static String ITEM_CROSS_BARCODE_1 = "u.u.barcode1";
    	// public final static String ITEM_CROSS_BARCODE_2 = "u.u.barcode2";
    	// public final static String ITEM_CROSS_BARCODE_3 = "u.u.barcode3";
    	// public final static String ITEM_CROSS_BARCODE_4 = "u.u.barcode4";
    	// public final static String ITEM_CROSS_BARCODE_5 = "u.u.barcode5";
    	// public final static String ITEM_CROSS_BARCODE_6 = "u.u.barcode6";
    	// public final static String ITEM_CROSS_BARCODE_7 = "u.u.barcode7";
    	// public final static String ITEM_CROSS_BARCODE_8 = "u.u.barcode8";
    	// 路口,动作,对应8个路口,int
    	public final static String ITEM_CROSS_ACTION_1 = "u.u.action1";
    	public final static String ITEM_CROSS_ACTION_2 = "u.u.action2";
    	public final static String ITEM_CROSS_ACTION_3 = "u.u.action3";
    	public final static String ITEM_CROSS_ACTION_4 = "u.u.action4";
    	public final static String ITEM_CROSS_ACTION_5 = "u.u.action5";
    	public final static String ITEM_CROSS_ACTION_6 = "u.u.action6";
    	public final static String ITEM_CROSS_ACTION_7 = "u.u.action7";
    	public final static String ITEM_CROSS_ACTION_8 = "u.u.action8";
    	// 工位按钮,12个工位
    	public final static String ITEM_STATION_1 = "u.u.station1";
    	public final static String ITEM_STATION_2 = "u.u.station2";
    	public final static String ITEM_STATION_3 = "u.u.station3";
    	public final static String ITEM_STATION_4 = "u.u.station4";
    	public final static String ITEM_STATION_5 = "u.u.station5";
    	public final static String ITEM_STATION_6 = "u.u.station6";
    	public final static String ITEM_STATION_7 = "u.u.station7";
    	public final static String ITEM_STATION_8 = "u.u.station8";
    	public final static String ITEM_STATION_9 = "u.u.station9";
    	public final static String ITEM_STATION_10 = "u.u.station10";
    	public final static String ITEM_STATION_11 = "u.u.station11";
    	public final static String ITEM_STATION_12 = "u.u.station12";
    	// 线体1,烘箱存取控制
    	public final static String ITEM_OVEN_STATE_1 = "u.u.oven1";
    	public final static String ITEM_OVEN_ACTION_1 = "u.u.ovenaction1";
    	public final static String ITEM_OVEN_COLUMN_1 = "u.u.column1";
    	public final static String ITEM_OVEN_LAYER_1 = "u.u.layer1";
    	public final static String ITEM_OVEN_ROW_1 = "u.u.row1";
    	// 线体2,烘箱存取控制
    	public final static String ITEM_OVEN_STATE_2 = "u.u.oven2";
    	public final static String ITEM_OVEN_ACTION_2 = "u.u.ovenaction2";
    	public final static String ITEM_OVEN_COLUMN_2 = "u.u.column2";
    	public final static String ITEM_OVEN_LAYER_2 = "u.u.layer2";
    	public final static String ITEM_OVEN_ROW_2 = "u.u.row2";
    
    	// // 路口和条码的对应关系
    	// public final static Map<String, String> CROSS_BARCODES = new HashMap<String,
    	// String>();
    	// static {
    	// CROSS_BARCODES.put(ITEM_CROSS_1, ITEM_CROSS_BARCODE_1);
    	// CROSS_BARCODES.put(ITEM_CROSS_2, ITEM_CROSS_BARCODE_2);
    	// CROSS_BARCODES.put(ITEM_CROSS_3, ITEM_CROSS_BARCODE_3);
    	// CROSS_BARCODES.put(ITEM_CROSS_4, ITEM_CROSS_BARCODE_4);
    	// CROSS_BARCODES.put(ITEM_CROSS_5, ITEM_CROSS_BARCODE_5);
    	// CROSS_BARCODES.put(ITEM_CROSS_6, ITEM_CROSS_BARCODE_6);
    	// CROSS_BARCODES.put(ITEM_CROSS_7, ITEM_CROSS_BARCODE_7);
    	// CROSS_BARCODES.put(ITEM_CROSS_8, ITEM_CROSS_BARCODE_8);
    	// }
    	// // 路口和动作的对应关系
    	// public final static Map<String, String> CROSS_ACTIONS = new HashMap<String,
    	// String>();
    	// static {
    	// CROSS_BARCODES.put(ITEM_CROSS_1, ITEM_CROSS_ACTION_1);
    	// CROSS_BARCODES.put(ITEM_CROSS_2, ITEM_CROSS_ACTION_2);
    	// CROSS_BARCODES.put(ITEM_CROSS_3, ITEM_CROSS_ACTION_3);
    	// CROSS_BARCODES.put(ITEM_CROSS_4, ITEM_CROSS_ACTION_4);
    	// CROSS_BARCODES.put(ITEM_CROSS_5, ITEM_CROSS_ACTION_5);
    	// CROSS_BARCODES.put(ITEM_CROSS_6, ITEM_CROSS_ACTION_6);
    	// CROSS_BARCODES.put(ITEM_CROSS_7, ITEM_CROSS_ACTION_7);
    	// CROSS_BARCODES.put(ITEM_CROSS_8, ITEM_CROSS_ACTION_8);
    	// }
    }
    
    
    
    
     
  • 相关阅读:
    vijos1746 floyd
    总结
    用javascript代码拼html
    异步编程学习
    SELECT
    设计 Azure SQL 数据库,并使用 C# 和 ADO.NET 进行连接
    H2数据库
    ASP.NET 文档
    ASP.NET MVC
    ASP.NET Core 中的 Razor 页面介绍
  • 原文地址:https://www.cnblogs.com/zouhao/p/13997237.html
Copyright © 2011-2022 走看看