IEC-104協(xié)議
一 IEC104協(xié)議介紹
1 IEC104簡要說明
IEC104是一種基于TCP/IP的電力行業(yè)通信協(xié)議,主要用于數(shù)據(jù)遠(yuǎn)程監(jiān)控等功能。通信有一般有主要發(fā)送數(shù)據(jù)、接收命令的從站服務(wù)端和接收數(shù)據(jù)、發(fā)送命令的主站客戶端構(gòu)成。采用應(yīng)答式數(shù)據(jù)傳輸,一般上行數(shù)據(jù)為遙信、遙測,下行信息為遙控、遙調(diào)。
2 IEC104幀格式
IEC104的通用幀格式如圖

其中APCI為控制信息部分,ASDU為存儲(chǔ)數(shù)據(jù)單元,APDU為長度等于APCI+ASDU-2,即減去起始字節(jié)和APDU長度字節(jié)。 IEC104有3種幀格式,分別為U幀即控制報(bào)文幀、S幀即監(jiān)視幀和I幀即信息傳輸幀。
- U幀:只包括APCI部分,主要有啟動(dòng)幀、停止幀、測試幀。U幀具體格式如圖

- S幀:只包含APCI部分。S幀格式如圖

- I幀:包含APCI+APDU部分。I幀格式如圖

發(fā)送序號(hào)和接收序列號(hào)是保證數(shù)據(jù)完整性的條件。 類型標(biāo)識(shí)定義發(fā)送數(shù)據(jù)的格式。 可變結(jié)構(gòu)體定義發(fā)送數(shù)據(jù)信息是有序還是無序,有序即一個(gè)信息體地址,元素的對(duì)應(yīng)地址會(huì)在此信息地址基礎(chǔ)上依次加1。無序即1個(gè)地址對(duì)應(yīng)一個(gè)元素。 傳輸原因定義記錄傳送的原因,用以對(duì)傳輸數(shù)據(jù)進(jìn)行歸類。
3 IEC104規(guī)約流程
- 由客戶端向服務(wù)器建立連接,同時(shí),發(fā)送鏈路啟動(dòng)幀。
- 服務(wù)端在收到鏈路啟動(dòng)幀后,向客戶端發(fā)送啟動(dòng)確認(rèn)幀。
- 客戶端收到啟動(dòng)確認(rèn)幀后,發(fā)送總召喚命令數(shù)據(jù)請(qǐng)求幀。
- 服務(wù)端收到總召喚命令數(shù)據(jù)請(qǐng)求后,發(fā)送總召喚命令數(shù)據(jù)響應(yīng)幀,然后繼續(xù)發(fā)送總召喚命令數(shù)據(jù)。總召喚命令數(shù)據(jù)發(fā)送完成后,發(fā)送總召喚命令數(shù)據(jù)結(jié)束幀。
- 客戶端在收到總召喚命令數(shù)據(jù)結(jié)束幀后,發(fā)送對(duì)時(shí)請(qǐng)求幀。
- 服務(wù)器收到對(duì)時(shí)請(qǐng)求幀后,發(fā)送對(duì)時(shí)響應(yīng)幀。
- 由服務(wù)器主動(dòng)向客戶端發(fā)送變化數(shù)據(jù)幀。同時(shí),收到客戶端發(fā)送的控制類命令,回復(fù)相應(yīng)的操作結(jié)果。
- 客戶端等到下一個(gè)數(shù)據(jù)總召喚命令數(shù)據(jù)周期,重復(fù)第4步之后的流程。
二 IEC104通信主站程序總體設(shè)計(jì)實(shí)現(xiàn)
根據(jù)項(xiàng)目需求和IEC104通信規(guī)約設(shè)計(jì),主要包括遙信、遙測的解析程序功能,遙控、遙調(diào)的組合程序功能,數(shù)據(jù)庫并發(fā)操作。涉及技術(shù)Java面對(duì)對(duì)象編程,多線程,socket編程,JDBC數(shù)據(jù)庫操作映射API,C3P0高并發(fā)數(shù)據(jù)庫連接池。 首先設(shè)計(jì)如圖的目錄結(jié)構(gòu): 其中jdbc 庫文件存儲(chǔ)數(shù)據(jù)庫連接相關(guān)配置的類文件,model庫文件存儲(chǔ)著數(shù)據(jù)庫的對(duì)應(yīng)模型的類結(jié)構(gòu)文件,dao庫文件存儲(chǔ)著數(shù)據(jù)庫操作的類函數(shù)文件,iec104.util存儲(chǔ)著程序處理中所用到的工具類,iec104為程序邏輯主體,存儲(chǔ)著程序的主要處理類函數(shù)文件。 設(shè)計(jì)如圖的配置文件目錄
其中typeId.properties存儲(chǔ)著功能類型的數(shù)字對(duì)應(yīng)信息漢字關(guān)系,cause.properties存儲(chǔ)著原因類型數(shù)字對(duì)應(yīng)信息漢字關(guān)系,用于幀格式解析。remote_signal、remote_measure、remote_control、remote_adjust是存儲(chǔ)信息體地址和對(duì)應(yīng)存儲(chǔ)數(shù)據(jù)庫字段關(guān)系文件,用于將設(shè)備狀態(tài)信息存儲(chǔ)到數(shù)據(jù)庫對(duì)應(yīng)數(shù)據(jù)模型或從對(duì)應(yīng)數(shù)據(jù)進(jìn)行數(shù)據(jù)提取。 設(shè)計(jì)主體程序有3部分構(gòu)成,主程序包括配置信息初始化,Socket端口連接初始化,數(shù)據(jù)庫連接配置初始化,線程定時(shí)器初始化,啟動(dòng)鏈路,接收遙信、遙測幀信息解析緩存到對(duì)應(yīng)對(duì)象結(jié)構(gòu)體;定時(shí)將緩存在遙信、遙測對(duì)象結(jié)構(gòu)體的數(shù)據(jù)寫入數(shù)據(jù)庫;遙控、遙調(diào)定時(shí)器程序包括根據(jù)讀取數(shù)據(jù)庫對(duì)應(yīng)數(shù)據(jù)信息與緩存字典比較,發(fā)現(xiàn)變化信息組合幀信息并發(fā)送。設(shè)計(jì)總體流程圖如圖

三 IEC104主站數(shù)據(jù)庫相關(guān)程序設(shè)計(jì)
1 設(shè)備數(shù)據(jù)庫模型類實(shí)現(xiàn)
IEC104數(shù)據(jù)庫與Web管理系統(tǒng)共用一個(gè)數(shù)據(jù)庫,IEC104需建立的數(shù)據(jù)庫模型與web模型的屬性、字段都相同,在此基礎(chǔ)建立數(shù)據(jù)庫映射操作庫model中的映射實(shí)現(xiàn)類如圖

其中DevControl為存儲(chǔ)所有設(shè)備信息及其控制部分的映射實(shí)現(xiàn)類,PVAnalogQuantotyData1, PVAnalogQuantotyData1,PVDigtialQuantityData為具體設(shè)備(光伏逆變器)類的數(shù)字信息和模擬量信息映射實(shí)現(xiàn)類。
2 IEC104設(shè)備數(shù)據(jù)庫操作類實(shí)現(xiàn)
model每個(gè)類文件會(huì)對(duì)應(yīng)數(shù)據(jù)庫操作dao庫中一個(gè)類文件,dao的類中會(huì)記錄數(shù)據(jù)庫操作所需要執(zhí)行的增刪改查操作。目錄結(jié)構(gòu)如圖:
以DevControlDao實(shí)現(xiàn)類為例簡要說明: 添加設(shè)備實(shí)現(xiàn)函數(shù)核心sql操作語句
Strning sql = "insert into microgrids_devcontrol (num, dev_type) values(?,?)";
更新設(shè)備類型號(hào)碼實(shí)現(xiàn)函數(shù)核心sql操作語句
Strning sql = "update microgrids_devcontrol set dev_type=? where num=?";
刪除設(shè)備類實(shí)現(xiàn)函數(shù)核心sql操作語句
String sql="delete from microgrid_devcontrol where num=?"
查詢設(shè)備是否存在函數(shù)的核心sql操作語句
String sql="select num from microgrid_devcontrol where num=?"
3 IEC104數(shù)據(jù)庫連接初始化
數(shù)據(jù)庫為考慮大量數(shù)據(jù)寫入時(shí)的性能要求,使用了C3P0數(shù)據(jù)庫連接池的方法來增強(qiáng)數(shù)據(jù)庫操作的性能。其中C3P0連接池初始化獲得mysql操作對(duì)象的類為jdbc包的C3P0Utils類
public class C3P0Utils {
private static ComboPooledDataSource dataSource = new ComboPooledDataSource("mysql");
public static DataSource getDataSource() {
return dataSource;
}
public static Connection getConnection() {
try {
return dataSource.getConnection();
}catch (SQLException e) {
throw new RuntimeException(e);
}
}
}
其中,系統(tǒng)會(huì)調(diào)用主目錄下的c3p0-config.xml文件進(jìn)行數(shù)據(jù)庫初始化配置,包括連接數(shù)據(jù)庫地址,數(shù)據(jù)庫用戶和密碼。
四 主站核心程序設(shè)計(jì)
1 主站設(shè)備信息初始化
首先,程序會(huì)在初始化完成時(shí)加載配置文件dev.json,dev.json數(shù)據(jù)格式為設(shè)備編號(hào),設(shè)備名,設(shè)備類型編號(hào)。(設(shè)備類型對(duì)應(yīng)編號(hào)在Django model中進(jìn)行定義,這里寫入是為便于Web管理操作)
{
"PVI0101":{"name":"光伏1區(qū)光伏逆變器1號(hào)", "DEV_TYPE":1},
}
根據(jù)配置文件的設(shè)備信息會(huì)去更新數(shù)據(jù)庫DevControl中的設(shè)備信息,對(duì)配置信息存在數(shù)據(jù)庫卻不存在的設(shè)備使用dao庫DevControl類下的addDev方法進(jìn)行添加,對(duì)配置信息中不存在設(shè)備數(shù)據(jù)庫卻存在的設(shè)備使用delDev方法進(jìn)行刪除。根據(jù)設(shè)備類型編號(hào)去創(chuàng)建對(duì)應(yīng)設(shè)備遙信,遙測需要的設(shè)備信息結(jié)構(gòu)體,以便在后面獲取數(shù)據(jù)存入對(duì)應(yīng)結(jié)構(gòu)體存儲(chǔ)。
2 主站遙信、遙測程序設(shè)計(jì)實(shí)現(xiàn)
首先,程序會(huì)在初始化加載remote_signal.json、remote_measure.json、遙信、遙測配置文件,配置信息格式主要為信息體地址,對(duì)應(yīng)數(shù)據(jù)庫字段名,對(duì)應(yīng)數(shù)據(jù)庫表單名,對(duì)應(yīng)數(shù)據(jù)庫設(shè)備編號(hào)。
{
"14":{"field":"status_down","num":"PVI0101","table_name":"pvdigitalquantitydata","descript":"西科逆變器1_停機(jī)","注釋":""},
}
然后,使用多線程Runable類定義遙信、遙測數(shù)據(jù)寫入數(shù)據(jù)庫的方法即將設(shè)備對(duì)應(yīng)數(shù)據(jù)信息結(jié)構(gòu)體(在設(shè)備信息初始化中產(chǎn)生)使用對(duì)應(yīng)sql方法寫入數(shù)據(jù)庫。使用ScheduledExecutorService類初始化遙信、遙測的多線程定時(shí)器得到對(duì)象service,再使用service下的scheduleAtFixedRate方法定時(shí)執(zhí)行信息結(jié)構(gòu)體數(shù)據(jù)寫入數(shù)據(jù)庫方法。
程序在發(fā)送完總召喚命令后會(huì)一直使用socket的方法去讀取從站發(fā)送過來的幀數(shù)據(jù)并進(jìn)行解析,首先會(huì)使用Apdu類下的Apdu方法進(jìn)行解析,獲得幀的啟動(dòng)幀,APDU長度,發(fā)送序號(hào),接收序列號(hào),控制域信息,根據(jù)控制域信息會(huì)進(jìn)行判斷幀類型,即為I幀,S幀,還是U幀。如果是S幀,或U幀獲取后基本不做處理,主要會(huì)進(jìn)行I幀解析。再判斷是I幀后,會(huì)使用Asdu類下的Asdu進(jìn)行解析,獲取幀的類型標(biāo)識(shí),傳輸原因,公共地址,可變結(jié)構(gòu)體等信息,然后使用InformationObject類的InformationObject方法去根據(jù)幀的類型標(biāo)識(shí)去把數(shù)據(jù)信息存入到InformationElement,再獲取存在信息體地址和數(shù)據(jù)的InformationObject對(duì)象。最后,再使用Client類中handleData方法,根據(jù)信息體地址從遙信、遙測配置文件獲取其在數(shù)據(jù)庫的表單名,對(duì)應(yīng)字段,對(duì)應(yīng)設(shè)備,把信息體對(duì)應(yīng)的數(shù)據(jù)寫入到對(duì)應(yīng)的設(shè)備信息結(jié)構(gòu)體中。 使用PMA軟件模擬從站進(jìn)行遙信測試如下: 首先啟動(dòng)程序建立鏈接,并發(fā)送總召喚命令,如圖

從站PMA地址發(fā)送地址為14,值為0的遙信數(shù)據(jù)(逆變器PV0101停機(jī)信號(hào)),如圖


主站接收遙信幀并進(jìn)行解析,打印解析信息如圖

數(shù)據(jù)庫對(duì)應(yīng)更新遙調(diào)信息所需要修改數(shù)據(jù)庫數(shù)據(jù)如圖

web管理系統(tǒng)界面PVI0101對(duì)應(yīng)數(shù)據(jù)信息改變?nèi)鐖D

3 主站遙控、遙調(diào)程序設(shè)計(jì)實(shí)現(xiàn)
首先,程序會(huì)在初始化加載remote_control.json、remote_adjust.json、遙控、遙調(diào)配置文件,配置信息格式主要為信息體地址,對(duì)應(yīng)數(shù)據(jù)庫字段名,對(duì)應(yīng)數(shù)據(jù)庫設(shè)備編號(hào)。
{
"25089":{"field":"active_power","num":"PVI0101","descript":"西科逆變器1_有功功率遙調(diào)值","注釋":""},
}
然后,定義存儲(chǔ)遙控、遙調(diào)信息即地址信息和數(shù)據(jù)信息實(shí)時(shí)值的字典(記錄實(shí)時(shí)值,是為了只在數(shù)據(jù)庫數(shù)據(jù)狀態(tài)改變的情況下,才會(huì)去發(fā)送遙控或遙信命令)
// 記錄存儲(chǔ)遙控、遙調(diào)實(shí)時(shí)值
Map<String, Integer> remoteControlValues = new HashMap<String,Integer>();
Map<String, Double> remoteAdjustVlaues = new HashMap<String,Double>();
之后,會(huì)使用多線程Runable類定義遙控、遙調(diào)信息幀組合并發(fā)送的runnable_db_send方法。同樣使用ScheduledExecutorService類初始化遙信、遙測的多線程定時(shí)器得到對(duì)象service_A,再使用service_A下的scheduleAtFixedRate方法定時(shí)執(zhí)行。 Runnable_db_send方法會(huì)提取remote_control.json、remote_adjust.json配置文件信息,根據(jù)地址信息的字段和編號(hào)去數(shù)據(jù)庫對(duì)應(yīng)的表單下去提取數(shù)據(jù),對(duì)比remoteControlValues、remoteAdjustVlaues字典,如果和字典中信息不同,則更新字典信息并發(fā)送遙控、遙調(diào)命令。 使用PMA模擬從站測試如下: Web管理界面修改逆變器PV0101的控制信息(會(huì)更改對(duì)應(yīng)數(shù)據(jù)庫數(shù)據(jù)),如圖

IEC104主站發(fā)送相關(guān)遙控、遙調(diào)命令,并打印信息,如圖

PMA從站會(huì)接收到IEC104主站的遙控、遙調(diào)信息,如圖
