Java OPC 代碼

這是我項目的代碼,算是真實業務實現,記錄備份一下實現思路
由於業務就是簡單的獲取數據而後保存,因此仍是容易理解的html

1.任務詳情

  • Java實現OPC通訊的代碼實現
  • 最終實現對西門子的S7-300的PLC變量的值讀寫

2.實現狀況

示例java

OPCServer標記名稱 地址 數據類型 說明
TAG1 DB1.INT00 short 心跳
TAG2 DB1.INT02 short 控制字
TAG3 DB1.STRING4,10 string 箱體信息
TAG4 DB1.D14 float 結果

實際spring

  • 制定交互流程:控制字的狀態

PLC地址數據庫

3. 代碼實現

通訊上:定義了地址變量,包括數據類型,就能拿到數。數組

不一樣client之間通訊:確定有個心跳,你寫什麼,我寫什麼,斷了能看出來。還要有控制字,讀到控制字某個值,去讀取或者寫入一些變量服務器

  • 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");
}

地址寫在了配置文件裏dom

opc_list.propertieside

#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);
    // }
}
相關文章
相關標籤/搜索