1、 引子git
首先感謝博客園:第一篇文章、第一個開源項目,算是旗開得勝。能夠看到,項目大部分流量來自於博客園,碼農樂園,名不虛傳^^。github
園友給了我不少支持,並提出了很好的改進意見。現加入屏幕分辨率自適應和OPC Server可CLSID和ProgID自適應加載功能。屏幕自適應本是廣泛問題,由於以前都是標配硬件,舉手之勞,一懶就忽略了。算法
僅僅十天前,我仍是上github只會點擊的菜鳥。Readme文件如何編輯都是現學現賣。數據庫
第一次向github上傳倉庫,下載了發現竟然沒有任何exe,dll,bak文件!度之,更改忽略文件。總之是趕鴨子上架,各類囧。架構
然則有園友捧場,我也就不揣淺陋,以見教於大方了。框架
2、 如何加入一個新驅動函數
我更新了dll文件夾:增長了libnodave.dll、libnodave.net.dll、SiemensPLCDriver.dll。這個SiemensPLCDriver.dll,性能
就是西門子S7系列PLC的驅動程序(包括源代碼,在Program裏面)。請先同步或者從新下載最新版本。優化
libnodave開源庫(https://github.com/netdata/libnodave)聽說是來自西門子的德國大神所做。某前輩當年一句話:能搞定驅動就是大牛。我找到了libnodave,封裝後成功的實現了與西門子200PLC通信,很受鼓舞,也成爲了項目的起點。spa
打開變量管理器TagConfig,點註冊,雙擊【路徑】框,在dll文件夾裏找到SiemensPLCDriver.dll。
若是出如今下方列表,打鉤,點註冊,通常會提示成功。
這時候,右鍵點樹節點S1->參數設置,就會看到S7以太網協議已經成爲可選項。
實際上述一系列動做,就是驅動dll的信息,已經寫入了數據庫的RegisterModule表。
這張表就是爲系統服務反射加載驅動程序提供基本信息:加載的位置、類名 、描述,以便實例化爲具體的驅動類。
在DAServer內有一個AddDriver方法,就是Activator.CreateInstance加載驅動並轉換爲IDriver。
使用反射加載,最大優勢就是用戶能夠本身實現一個驅動,或者引用第三方驅動,並用TagConfig註冊,而不須要改動源代碼。
3、 如何實現一個新驅動
[Description("S7 以太網協議")] public sealed class SiemensTCPReader : IPLCDriver, IMultiReadWrite
我在前一篇文章裏提到,IPLCDriver 是全部PLC都實現的接口。IMultiReadWrite 是支持批量讀寫的下位機必須實現的接口。
由於PLC都具備可鏈接性、可讀寫性,同時西門子的協議還支持批量讀寫。
SiemensTCPReader 裏的Connect方法,就是對libnodave中connectPLC方法的封裝。
Dispose方法,就是釋放libnodave的非託管資源。
ReadBytes、ReadInt3二、ReadBit、ReadFloat、WriteFloat等方法,就是對IReaderWriter接口的實現。也就是單獨讀寫。
ReadMultiple、WriteMultiple方法是對IMultiReadWrite 接口的實現,也是對libnodave中批量讀寫方法的封裝。
GetDeviceAddress/GetAddress方法很重要,在TagConfig裏編輯的地址是西門子約定俗成的,好比DB3,DD122.1,要翻譯成下位機理解的設備地址DeviceAddress。
這個Description 屬性描述符,在註冊以後會被反射爲驅動的描述字符,存入數據庫。
批量讀寫的目的,就是爲了提升性能。
不少人老是拿C#、.NET的所謂性能說事。首先我認爲.NET性能優良。關鍵是你怎麼寫。
而對性能影響最大的每每不是語言、框架,而是IO。IO的性能成本每每是語言自己的十倍、百倍、甚至千倍。
在PLC通信過程當中,請求往返就是性能瓶頸。由於大部分下位機不支持訂閱-發佈(推送)模式,只能採用按期輪詢方式。
既然是輪詢,若是變量不少,若是一個個去讀寫,讀1000個變量要輪詢1000次,一次往返起碼幾十毫秒,效率差的驚人,還佔用PLC大量資源。這是行不通的。
但若是你想一次就能讀入1000個變量,要考慮到變量地址多是不連續的,散亂的。而每次讀取的大小受PDU所限。
因此,就必定要對變量的分佈分析整理,相似送快遞,客戶雖然分佈在各個小區,但並不能像醉漢同樣漫無目的的投遞,而是根據客戶的分佈,執行最優化的路線選擇。
整理的結果,就是將全部要讀寫的變量分割爲塊,每塊大小不能超過PLC 的PDU。力求往返次數最少、一次讀入的區塊最大、包含的變量最多。
分割整理變量區塊的功能,就是PLCGroup 的UpdatePDUArea函數實現的。不過我在這裏只是進行簡單的地址概括,並無作最優解。最優算法確定是存在的,但可能與現行方法出入不會太大。
4、 下面的計劃
寫一系列帖子,把架構、原理講清楚。大體以下:
github地址:https://github.com/GavinYellow/SharpSCADA。歡迎你們提出寶貴意見和建議!