本案例用来演示,通过Visual Studio 2022创建C#的WPF工程,使用ACP的接口来读取变量、写入变量、批量读取变量、订阅变量、取消订阅的功能。
硬件示意如下图所示:
下表概述了本手册各个产品组件
产品组件 | 描述说明 |
---|---|
Device Manager 0.0.1.9 | 插件管理工具 |
ACP_Project.projectarchive | PLC工程存档(客户端) |
WPF_ACP | C#程序源文件 |
安装要求
安装过程
1、工智机安装acpplcaccess.deb组件
1.打开Device Manager软件
2.初次使用,需要安装ACP通讯服务。点击左下角“安装ACP服务”。
3.输入工智机固定IP地址、端口、用户名和密码后,点击“在线安装”。
IP地址 | 192.168.1.200 |
---|---|
端口 | 2224 |
用户 | sinsegye |
密码 | 1 |
等待安装完成。
4.安装完成后,点击“扫描”,即可扫描出固定网口192.168.1.200连接的工智机。
点击进入工智机后,左下角显示“已连接”状态。
5.点击“安装RTE插件服务”
6.输入用户名:sinsegye,密码:1,点击“在线安装”
7.安装完成后,点击“软件”,在下拉菜单下选择“组件管理”
8.点击浏览,可以在线浏览可以安装的组件。
9.在组件中找到“SF1000-acpplcaccess”--点击“安装”
10.等待deb包传送到工智机中,传送完成后点击“确定”进行安装。
11.安装完成后,点击“确认”重启生效。
12.安装完成后,可以在“本地”页面浏览到SF1000-acpplcaccess已安装成功。
2、C#工程安装Sinsegye ACP的NuGet包
打开Visual Studio 2022新建C#的WPF应用程序:
添加工程名:
在工程中添加程序包源:
右键选择工程的“依赖项”—“管理NuGet程序包”
选择设置:
添加源:
名称:acp
源:http://gitlab.sinsegye.com.cn:8081/artifactory/api/nuget/v3/si-nuget-release-ecs
源:https://api.nuget.org/v3/index.json
搜索到sinsegye.acpsharp程序包,选择最新稳定版——“安装”。
3、PLC示例程序编辑
本PLC程序示例可以从中科时代官网进行下载,也可以按如下方法进行创建。
打开中科时代IDE MetaFacture
选择“新建工程”
选择“标准工程”--命名为“ACP_Project”--点击“确定”。
设备选择“Sinsegye”--选择PLC_RRG编程语言,本例为ST语言,点击“确定”即可完成创建。
创建的新工程:
鼠标右键“Application”—“添加对象”—“DUT”。添加读写和订阅用的结构体类型。
命名为“CS_Struct”—点击“添加”
添加两个子成员:S1和S2。类型分别为DWORD和TIME。
再次鼠标右键“Application”—“添加对象”—“全局变量列表”。
命名为“GVL”—“添加”
添加如下变量,用于ACP订阅变量功能测试:
变量名 | 类型 |
---|---|
Var11 | BOOL |
Var12 | INT |
Var13 | REAL |
Var14 | STRING |
Var15 | ARRAY\[0..9] OF BYTE |
Var16 | CS_Struct |
点击"PLC_PRG",声明如下变量,用于ACP读写功能测试:
变量名 | 类型 | 初始值 |
---|---|---|
Var1 | BOOL | TRUE |
Var2 | INT | -40 |
Var3 | REAL | 3.1415 |
Var4 | STRING | Sinsegye |
Var5 | ARRAY\[0..4] OF INT | \[7,6,5,4,3] |
Var6 | CS_Struct | (S1:=4294967295, S2:=T#5D22H37M28S7MS) |
i | LINT | 0(用于订阅功能) |
在PLC_PRG中编辑如下程序:
i:=i+1
GVL.Var11:=NOT GVL.Var11
GVL.Var12:=LINT\_TO\_INT(i)
GVL.Var13:=3.1415926\*LINT\_TO\_REAL(i)/1000
GVL.Var14:=CONCAT('Var i is ',LINT\_TO\_STRING(i))
GVL.Var15\[3]:=LINT\_TO\_BYTE(i)
GVL.Var16.S1:=LINT\_TO\_WORD(i)
GVL.Var16.S2:=LINT\_TO\_TIME(i)
再次鼠标右键“Application”—“添加对象”—“符号配置”。
默认设置,点击“添加”
添加完成后,点击“编译”
勾选如下变量:
双击“Device”—“扫描网络”—选择登录的ACP工智机—“确定”
点击“登录”
点击“启动”
三、更新安装
在插件管理器Device Mananger--组件管理--本地组件中,点击SF1000-acpplcaccess,选择可更新的版本后,点击“更新”。
四、卸载过程
卸载工智机deb组件
在插件管理器Device Mananger--组件管理--本地组件中,点击SF1000-acpplcaccess,选择“卸载”
点击“确定”
卸载成功后,点击“确定”重启生效。
卸载成功后,“本地”页面组件消失。
快速启动
(一)本例软、硬件配置
硬件: | 软件: |
---|---|
工智机SX21-A01 | 1.工智机PLC存档工程ACP_Project.projectarchive |
个人电脑 | 2.中科时代MetaFacture V1.0.6.6 |
Visual Studio 2022 |
(二)本例实验操作步骤
1.实验要求
a.工智机成功安装SF1000-acpplcaccess组件;
b.个人电脑安装Visual Studio 2022和中科时代MetaFacture软件;
c.个人电脑可以联网且与工智机固定地址192.168.1.200网口连接。
2.实验原理图
3.实验步骤
3.1 解压官网下载的工程存档文件“ACP_Project.projectarchive”,登录工智机,下载运行程序。
其中,PLC_PGR中的变量Var1~Var6,作为测试读写变量使用。
GVL中的变量Var11~Var16作为测试订阅变量使用。
3.2 打开中科时代下载的C#源文件--“WPF_ACP.sln”
3.3 打开“MainWindow.xaml.cs”程序,修改成ACP工智机的IP地址。
3.4 完成IP地址修改后,点击运行“WPF_ACP”
3.5 点击“连接”—显示“连接成功”—点击“确定”
3.6点击“读取变量”,文本框显示PLC_PRG程序中的变量。
3.7 点击“订阅”,订阅PLC程序中的GVL变量,而且数值不断变化。
3.8 点击“取消订阅”,变量数值不再变化保持当前值。
3.9 双击左列文本框,可以修改变量值,修改完成后需要将鼠标焦点移除文本框。
3.10 修改完成后,点击“批量读取”,读取出的值与修改的值相同。
3.11 在线查看PLC程序,变量修改成功。
按照上一章节《安装卸载》中的"C#工程安装Sinsegye ACP的Nuget包"中创建新工程并安装Nuget包。
打开创建的C#程序,点击左侧工具箱,添加一个Label和一个TextBox。
修改Label的属性Content="BOOL",TextBox的属性Name="Var1",Text=""
同理,将Label标签复制6个,竖向排列,修改Content属性为INT、Real、String、Array3、Struct1和Struct2
将TextBox复制6个,并与Label相对应,修改属性Name。
添加一个Button控件,修改属性Content=“连接”
双击按键,VS会自动跳转到CS程序,并生成按钮点击事件的方法。
创建客户端函数:
public AcpClient(string deviceID, uint Port, ConnectionType connectionType.Tcp, bool isReConnect = false, int send_timeout_ms = 500, int rec_timeout_ms = 500)
acpClient通过字段ConnState可以查看连接状态,输出提示:
ConnStat为枚举类型,有如下连接状态:
为了后续程序使用client实例,可以将client声明在方法外:
连接客户端代码如下:
AcpClient \_acpClient;
private void button\_Click(object sender, RoutedEventArgs e)
{
_acpClient = new AcpClient("192.168.1.200.1.1", 600, ConnectionType.Tcp, false, 500, 500)
if (\_acpClient.ConnState == ConnState.SuccessfulConnection)
{
MessageBox.Show("连接成功")
}
else
{
MessageBox.Show("连接失败")
}
}
在WPF界面增加一个读取变量的按钮,修改属性Name="btnread" Content="读取变量",双击进入按钮点击方法编辑:
双击进入方法:
使用读取变量接口
Errors ReadVar(string VarName, IPlcOpenType VarInstance, out string innerError);
PLC工程中所对应的IplcOpenType类型见附录二。
对于PLC程序中结构体类型,需要在C#程序中新建与之相对应的结构体。本例中,PLC的结构体含有两个成员,分别是DWORD和TIME类型。在C#程序中也建立一个包含这两个类型成员的结构体。
设定读取变量名和对应的IPlcOpenType类型:
通过ReadVar方法读取相应的变量:
将读取的结果输出到WPF的Text文本框中:
运行程序,先点击“连接”按钮,再点击“读取变量”按钮:
读取变量成功:
读取变量的C#代码如下:
class PLCStruct : STRUCT
{
public DWORD child1 = new DWORD()
public TIME child2 = new TIME()
}//结构体类型
string ReadVar1 = "Application.PLC\_PRG.Var1";//读取变量1的路径
string ReadVar2 = "Application.PLC\_PRG.Var2";//读取变量2的路径
string ReadVar3 = "Application.PLC\_PRG.Var3";//读取变量3的路径
string ReadVar4 = "Application.PLC\_PRG.Var4";//读取变量4的路径
string ReadVar5 = "Application.PLC\_PRG.Var5";//读取变量5的路径
string ReadVar6 = "Application.PLC\_PRG.Var6";//读取变量61的路径
string errorUnmarshal;
BOOL bool1 = new BOOL();//实例IplcOpenType Bool类型
INT INT1 = new INT();//实例IplcOpenType Int类型
REAL REAL1 = new REAL();//实例IplcOpenType Real类型
STRING STRING1 = new STRING();//实例IplcOpenType String类型
ARRAY\<INT> intARRAY1 = new ARRAY\<INT>(new\[] { (0, 4) });//实例IplcOpenType一维int类型数组,数组起始角标为0,结束标为4.
PLCStruct Struct1 = new PLCStruct();//实例化结构体;
private void btnread\_Click(object sender, RoutedEventArgs e)
{
var ReadError = \_acpClient.ReadVar(ReadVar1, bool1, out errorUnmarshal);//开始读取变量1布尔
ReadError = \_acpClient.ReadVar(ReadVar2, INT1, out errorUnmarshal);//开始读取变量2整数
ReadError = \_acpClient.ReadVar(ReadVar3, REAL1, out errorUnmarshal);//开始读取变量3实数
ReadError = \_acpClient.ReadVar(ReadVar4, STRING1, out errorUnmarshal);//开始读取变量4字符串
ReadError = \_acpClient.ReadVar(ReadVar5, intARRAY1, out errorUnmarshal);//开始读取变量5数组
ReadError = \_acpClient.ReadVar(ReadVar6, Struct1, out errorUnmarshal);//开始读取变量6结构体
;
Var1.Text = bool1.ToString(); //将变量1的数据显示到界面Var1的文本框中
Var2.Text = INT1.ToString();//将变量2的数据显示到界面Var2的文本框中
Var3.Text = REAL1.ToString();//将变量3的数据显示到界面Var3的文本框中
Var4.Text = STRING1; //将变量4的数据显示到界面Var4的文本框中
Var5.Text = intARRAY1\[2].ToString();//将变量5数组的第三个元素显示到界面Var5的文本框中
Var6.Text = Struct1.child1.ToString();//将结构体的第一个子元素的显示到界面Var6的文本框中
Var7.Text = Struct1.child2.ToString();//将结构体的第二个子元素的显示到界面Var7的文本框中
}
在WPF界面复制一列TextBox控件,从上到下修改属性:Name="MultiVar1"到"MutiVar7"
新建一个按钮,修改属性Name="btnMultiRead" Content="批量读取"。双击按钮进入方法编程:
双击按钮进入方法编程:
新建批量读取的List
设置每个accessVarMode属性,包括读取路径和变量类型:
添加到List中:
使用批量读取方法AccessVars进行读取并显示到TextBox中:
运行程序,先后点击“连接”—“批量读取”按钮。
点击“批量读取”
批量读取C#代码如下:
private void btnMultiRead\_Click(object sender, RoutedEventArgs e)
{
List\<AccessVarModel> accessVarModels = new List\<AccessVarModel>()
AccessVarModel accessVarModel = new AccessVarModel()
AccessVarModel accessVarMode2 = new AccessVarModel()
AccessVarModel accessVarMode3 = new AccessVarModel()
AccessVarModel accessVarMode4 = new AccessVarModel()
AccessVarModel accessVarMode5 = new AccessVarModel()
AccessVarModel accessVarMode6 = new AccessVarModel()
accessVarModel.VarName = "Application.PLC\_PRG.Var1"
accessVarModel.VarInstance = bool1
accessVarMode2.VarName = "Application.PLC\_PRG.Var2";
accessVarMode2.VarInstance = INT1
accessVarMode3.VarName = "Application.PLC\_PRG.Var3"
accessVarMode3.VarInstance = REAL1;
accessVarMode4.VarName = "Application.PLC\_PRG.Var4";
accessVarMode4.VarInstance = STRING1;


accessVarMode5.VarName = "Application.PLC\_PRG.Var5"
accessVarMode5.VarInstance = intARRAY1
accessVarMode6.VarName = "Application.PLC\_PRG.Var6"
accessVarMode6.VarInstance = Struct1
accessVarModels.Add(accessVarModel)
accessVarModels.Add(accessVarMode2)
accessVarModels.Add(accessVarMode3)
accessVarModels.Add(accessVarMode4)
accessVarModels.Add(accessVarMode5)
accessVarModels.Add(accessVarMode6)
var MultiReadError = \_acpClient.AccessVars(accessVarModels);//批量读取方法
MultiVar1.Text = accessVarModel.VarInstance.ToString()
MultiVar2.Text = accessVarMode2.VarInstance.ToString()
MultiVar3.Text = accessVarMode3.VarInstance.ToString()
MultiVar4.Text = accessVarMode4.VarInstance.ToString();
MultiVar5.Text = ((ARRAY\<INT>)accessVarMode5.VarInstance)\[3].Value.ToString()
MultiVar6.Text = ((PLCStruct)accessVarMode6.VarInstance).child1.Value.ToString()
MultiVar7.Text = ((PLCStruct)accessVarMode6.VarInstance).child2.Value.ToString()
}
在WPF界面复制一列TextBox控件,从上到下修改属性:Name="SubVar1"到"SubVar7"。
新建一个按钮,修改属性Name="btnSub" Content="订阅",
双击按钮进入方法编程:
在C#程序中添加如下变量:
初始化注册回调函数:
添加订阅变量:
其中,15代表订阅间隔周期15ms。
订阅变量C#代码如下:
int req = 0;//添加订阅的请求号
long \_Subid = new long(); //用于接受回调函数ID号
bool isReg = true;//用于初始化注册回调函数
string\[] strings = new string\[6];//用于订阅PLC程序变量
private void btnSub\_Click(object sender, RoutedEventArgs e)
{
if (isReg) //如果初次调用程序,注册回调函数
{
var RegError = \_acpClient.RegisterRouterEvent(SubCallBack);//注册回调函数
isReg = false; //注册完成后,设为false,不再进行注册
}
strings\[0] = "Application.GVL.Var11"
strings\[1] = "Application.GVL.Var12"
strings\[2] = "Application.GVL.Var13"
strings\[3] = "Application.GVL.Var14"
strings\[4] = "Application.GVL.Var15"
strings\[5] = "Application.GVL.Var16"
var AddSubError = \_acpClient.AddBatchSubVar(strings, req, 15)
}
当变量值发生变化时,会执行回调函数SubCallBack。
点击红色波浪线,选择下拉菜单—“生成方法SubCallBack”
自动生成SubCallBack:
在回调函数的方法中,先记录ID号,将来用于取消订阅:
当订阅的变量值发生改变时,dates的数据也会发生改变,使用foreach遍历dates的数据,来获得想要的变量:
添加剩余的PLC变量显示到TextBox文本框中:
运行程序,点击“连接”—连接成功。
点击“订阅”测试,可以看到变量不断在改变。
回调函数C#代码如下:
BOOL Subbool = new BOOL(); //创建订阅的BOOL类型
INT Subint = new INT(); //创建订阅的Int类型
REAL SubReal = new REAL(); //创建订阅的Real类型
STRING Substring = new STRING();//创建订阅的String类型
ARRAY\<BYTE> SubbyteArray = new ARRAY\<BYTE>(new\[] { (0, 9) });//创建订阅的一维BYTE类型数组,下角标从0\~9
PLCStruct Substruct = new PLCStruct();//创建订阅的结构体类型
private void SubCallBack(ValueChangeDates dates)
{
\_Subid = dates.subid;//回调函数ID号
foreach (var item in dates.ValueChangeDateList)
{
if (item.VarName == "Application.GVL.Var11")//如果数据变量名为Var1
{
Subbool.Unmarshal(item.Bytes); //将数据转换为Bool类型
Application.Current?.Dispatcher.InvokeAsync(new Action(() =>
{
SubVar1.Text = Subbool.ToString(); //输出到SubVar1的文本框中
}));
}
if (item.VarName == "Application.GVL.Var12")//如果数据变量名为Var12
{
Subint.Unmarshal(item.Bytes); //将数据转换为int类型
Application.Current?.Dispatcher.InvokeAsync(new Action(() =>
{
SubVar2.Text = Subint.ToString(); //输出到SubVar2的文本框中
}));
}
if (item.VarName == "Application.GVL.Var13")//如果数据变量名为Var13
{
SubReal.Unmarshal(item.Bytes); //将数据转换为Real类型
Application.Current?.Dispatcher.InvokeAsync(new Action(() =>
{
SubVar3.Text = SubReal.ToString(); //输出到SubVar3的文本框中
}))
}
if (item.VarName == "Application.GVL.Var14")//如果数据变量名为Var14
{
Substring.Unmarshal(item.Bytes); //将数据转换为string类型
Application.Current?.Dispatcher.InvokeAsync(new Action(() =>
{
SubVar4.Text = Substring.ToString();//输出到SubVar4的文本框中
}));
}
if (item.VarName == "Application.GVL.Var15")//如果数据变量名为Var15
{
SubbyteArray.Unmarshal(item.Bytes); //将数据转换为一维BYTE数组SubbyteArra
Application.Current?.Dispatcher.InvokeAsync(new Action(() =>
{
SubVar5.Text = SubbyteArray\[3].ToString();//将SubbyteArray的第4个元素输出到SubVar5的文本框中
}));
}
if (item.VarName == "Application.GVL.Var16")//如果数据变量名为Var16
{
Substruct.Unmarshal(item.Bytes); //将数据转换为结构体Substruct
Application.Current?.Dispatcher.InvokeAsync(new Action(() =>
{
SubVar6.Text = Substruct.child1.ToString();//将Substruct的第一个子成员输出到SubVar6的文本框中
SubVar7.Text = Substruct.child2.ToString();//将Substruct的第二个子成员输出到SubVar7的文本框中
}));
}
}
}
在WPF界面新建一个按钮,修改属性Name="btnUnSub" Content="取消订阅"。
双击按钮进入方法编程:
使用DelBatchSubVar方法取消订阅,需要传递订阅时的ID号:
运行程序,点击“连接”—“订阅”变量值更新,点击“取消订阅”变量值停止更新。
取消订阅的C#代码如下:
private void btnUnSub\_Click(object sender, RoutedEventArgs e)
{
var UnSubError = \_acpClient.DelBatchSubVar(\_Subid);//\_Subid为SubCallBack函数获取的ID号
}
选择“Var1”的TextBox控件。
在属性中选择事件,在LostFocus中写入ValueWrite。C#自动创建ValueWrite方法。
C#自动创建ValueWrite方法。
当TextBox焦点丢失时,会执行ValueWrite方法。在ValueWrite方法中,使用WriteVar方法即可将TextBox的值写入PLC的变量中。
同理,将其余的6个TextBox控件的LostFocus事件都填入ValueWrite方法:
由于现在多个控件在焦点丢失时都使用ValueWrite方法。所以在ValueWrite方法中,需要先判断是哪一个TextBox控件触发的事件,再进行写变量:
使用TryParse将PLC类型转换为C#类型:
对于本例中的数组和结构体单一修改某一成员,需要先将数组和结构体整体读取,再单独修改成员值,否则其余成员值会变为空。
PLC类型转换为C#类型的TryParse见下表:
PLC中IEC类型 | C#类型(小写) |
---|---|
Bool | bool |
Byte | byte |
Word | ushort |
Dword | uint |
Lword | ulong |
Sint | sbyte |
Usint | byte |
Int | short |
Uint | ushort |
Dint | int |
Udint | uint |
Lint | long |
Real | float |
Lreal | double |
String | string |
Array OF xxx | 根据数组类型 |
Struct | 根据成员类型 |
Time | TimeSpan |
Date | TimeSpan |
运行程序,“连接”—“读取变量”。鼠标点击文本框,修改变量值—当鼠标焦点丢失后,变量写入。
修改Struct2
写入变量的C#代码如下:
private void ValueWrite(object sender, RoutedEventArgs e)
{
TextBox tb = (TextBox)sender;
if (tb.Name == "Var1")
{
bool.TryParse(Var1.Text, out bool boolwrite);//将Text控件Var1的文本内容转成bool类型存入boolwrite变量
bool1.Value = boolwrite;//将boolwrite赋值给IplcOpenType类型的实例bool1
var WriteError = \_acpClient.WriteVar(ReadVar1, bool1, out errorUnmarshal);//写入变量
}
else if (tb.Name == "Var2")
{
short.TryParse(Var2.Text, out short shortwrite);

INT1.Value = shortwrite
var WriteError = \_acpClient.WriteVar(ReadVar2, INT1, out errorUnmarshal)
}
else if (tb.Name == "Var3")
{
float.TryParse(Var3.Text, out float floatwrite)
REAL1.Value = floatwrite
var WriteError = \_acpClient.WriteVar(ReadVar3, REAL1, out errorUnmarshal)
}
else if (tb.Name == "Var4")
{
STRING1.Value = Var4.Text.Replace("\0", "");
var WriteError = \_acpClient.WriteVar(ReadVar4, STRING1, out errorUnmarshal);
}
else if (tb.Name == "Var5")
var ReadError = \_acpClient.ReadVar(ReadVar5, intARRAY1, out errorUnmarshal);//读取数组intARRAY1
short.TryParse(Var5.Text, out short intArray2write);//将Text文本转换成Int类型&
intARRAY1\[2].Value = intArray2write;//修改数组intARRAY1\[2]的值
var WriteError = \_acpClient.WriteVar(ReadVar5, intARRAY1, out errorUnmarshal);//写入数组intARRAY1
}
else if (tb.Name == "Var6")
{
var ReadError = \_acpClient.ReadVar(ReadVar6, Struct1, out errorUnmarshal);//读取结构体
uint.TryParse(Var6.Text, out uint StuctChild1write);//将文本转换为成员1类型
Struct1.child1.Value = StuctChild1write;//修改成员1的值
var WriteError = \_acpClient.WriteVar(ReadVar6, Struct1, out errorUnmarshal);//写入
}
else if (tb.Name == "Var7")
{
var ReadError = \_acpClient.ReadVar(ReadVar6, Struct1, out errorUnmarshal);//读取结构体
TimeSpan timechange = new TimeSpan(); //新建TimeSpan类型用于接收修改值
TimeSpan.TryParse(Var7.Text, out timechange);//将Text文本转成TimeSpan类型
Struct1.child2.Value = timechange;//赋值结构体成员2
var WriteError = \_acpClient.WriteVar(ReadVar6, Struct1, out errorUnmarshal);//写入
}
}
1、初始化客户端
AcpClient \_acpClient= new AcpClient(string deviceID, uint Port, ConnectionType.Tcp,
bool isReConnect, int send\_timeout\_ms, int rec\_timeout\_ms)
2、读取变量
Errors ReadVar(string VarName, IPlcOpenType VarInstance,out string innerError);
3、写入变量
Errors WriteVar(string VarName, IPlcOpenType VarInstance, out string innerError);
4、批量读写
//实例化一个AccessVarModel列表
List\<AccessVarModel> accessVarModels = new List\<AccessVarModel>();
//实例化一个AccessVarModel对象
AccessVarModel accessVarModel = new AccessVarModel()
//设定AccessVarModel对象的路径和类型
accessVarModel.VarName = "Application.PLC\_PRG.Var1"
accessVarModel.VarInstance = bool1
//设定处理方式,默认为读取变量不需要设定,写入变量需要设定
accessVarModel.AccessType = acp\_idl.PlcAccess.AccessType.Write
//将accessVarModel对象添加到列表中
accessVarModels.Add(accessVarModel)
//批量读写
var Error = \_acpClient.AccessVars(accessVarModels)
5、读写结构体
//定义一个结构体,成员变量的类型,定义顺序必须与PLC中结构体一样
class PLCStruct : STRUCT //创建结构体,用于读写和订阅结构体数据
public DWORD child1 = new DWORD(); //结构体子成员1类型与PLC类型DWORD相同
public TIME child2 = new TIME(); //结构体子成员2类型与PLC类型TIME相同
}
//结构体类型
//定义string变量来存储PLC中结构体的路径string ReadStruPath = "Application.PLC\_PRG.Var5";/
/设置读取结构体路径
//实例化结构体
PLCStruct Struct1 = new PLCStruct();
//实例化结构体
//读写结构体
Var Error=\_acpClient.ReadVar(ReadStruPath, Struct1, out errorUnmarshal);
Var Error=\_acpClient.WriteVar(ReadStruPath, Struct1, out errorUnmarshal);
6、读写数组
//支持一维至三维数组,定义一个与PLC类型、维度、始末数字相同的数组
ARRAY\<INT> ArrayName = new ARRAY\<INT>(new\[] { (0,4) });
//一维数组
ARRAY\<INT> ArrayName = new ARRAY\<INT>(new\[] { (3, 10), (3, 10) })
//二维数组
ARRAY\<INT> ArrayName = new ARRAY\<INT>(new\[] { (2, 5), (0, 9),(0, 9) });
//三维数组
//定义string变量来存储PLC中数组的路径
string ReadArrayPath = "Application.PLC\_PRG.Var6"
//读写数组
Var Error=\_acpClient.ReadVar(ReadArrayPath, ArrayName, out errorUnmarshal)
Var Error=\_acpClient.WriteVar(ReadArrayPath, ArrayName, out errorUnmarshal);
7、订阅变量
| //使用RegisterRouterEvent方法注册回调函数SubCallBack
var RegError = \_acpClient.RegisterRouterEvent(SubCallBack);//注册回调函数
//添加字符串数组用于设定订阅变量的路径
string\[] strings = new string\[10];//string类型数组
strings\[0] = "Application.GVL.Var11";//订阅变量路径1
strings\[1] = "Application.GVL.Var12";//订阅变量路径2
strings\[2] = "Application.GVL.Var13";//订阅变量路径3
//添加订阅,req代表请求号,15代表订阅周期15
var AddSubError = \_acpClient.AddBatchSubVar(strings,0,15);
8、回调函数
//创建订阅的变量类型以及回调函数ID号
BOOL Subbool = new BOOL(); //创建回调函数接收的Bool类型
INT Subint = new INT(); //创建回调函数接收的Int类型
REAL Subreal = new REAL(); //创建回调函数接收的Real类型
long \_Subid = new long(); //用于接受回调函数ID号
//回调函
private void SubCallBack(ValueChangeDates dates)
{
_Subid = dates.subid;//保存回调ID号
foreach (var item in dates.ValueChangeDateList)//遍历找到变量,接收数据
{
if (item.VarName == "Application.GVL.Var11")//如果数据变量名为Var11&
{
Subbool.Unmarshal(item.Bytes); //将数据转换为Bool类型
}
if (item.VarName == "Application.GVL.Var12")//如果数据变量名为Var12
{
Subint.Unmarshal(item.Bytes); //将数据转换为Int类型
}
if (item.VarName == "Application.GVL.Var13")//如果数据变量名为Var13
{
Subreal.Unmarshal(item.Bytes); //将数据转换为Real类型
}
}
9、取消订阅
//使用DelBatchSubVar方法取消订阅,需要传递回调函数ID
var UnSubError = \_acpClient.DelBatchSubVar(\_Subid);//\_Subid为SubCallBack方法获取的ID号