目录
•1.........简介
•1.1......目标
•2.........PVIServices基础知识
•2.1......PVIServices安装文件
•2.1.1...对PVIServices编程的要求
•2.1.2...Visual Studio.NET编程环境
•2.1.3...添加 "BR.AN.PviServices.dll"
•3.........PVIServices通信对象
•3.1......属性、事件和方法
•3.1.1...属性
•3.1.2...Methods
•3.1.3...Events
•3.2......PVIServices类和PVI对象的层次结构
•3.3......PVIServices - 变量声明
•3.4......PVIServices - 服务类
•3.5......PVIServices - CPU类
•3.6......PVIServices – Task class
•3.7......PVIServices – Variable class
•3.7.1...变量对象的主动/被动切换
•3.7.2...评估数据变化
•3.7.3...读和写访问
•3.8......PVIServices – Module class
•3.9......Collections
•3.10....使用结构体工作
•4.........PVIServices示例程序
•4.1......创建一个新的Visual Studio.NET应用程序
•4.2......创建PVIServices通信对象
•4.3......错误评估
•4.4......评估数据变化
•4.5......读和写访问
•4.5.1...读取变量
•4.5.2...从控制器读取时间
•4.5.3...写入一个值
•4.6......使用一个结构
•5.........概述
本培训模块介绍了Visual Studio .NET编程环境下的PVI访问。所有的通信和诊断服务,从PVICOM接口到B&R控制器都可以使用。
PVI的功能为用户集中在PVIServices命名空间中易于使用的类中。
图: 1: PVIServices
学员将能够在Visual Studio .NET中使用实践案例创建自己的PVI客户端应用程序。
关于PVI客户端应用的现有PVIServices类的应用可能性,可以参考PVIServices用户文档。
Fig. 2: Overview
PVIServices被所有基于Visual Studio.NET的Windows应用程序用于B&R控制器的通信和诊断服务。
它们以PVICOM接口为基础,在编程环境中以面向对象的结构表示。
Fig. 3: PVIServices classes
Note:
PviServices组件可用于Windows XP/2000以及Windows CE应用程序。
PVIServices DLLs在安装完PVI Server&Runtime / Development软件包后安装在以下目录。
PVI Server&Runtime:
BrAutomation/Pvi/PviServices/Win32 for Windows XP/2000
BrAutomation/Pvi/PviServices/WinCE for Windows CE
PVI Development (starting with PVI 2.5.2.3060):
Program Files\BrAutomation\PVI\%Version%\PVI\PviServices\Win32
Program Files\BrAutomation\PVI\%Version%\PVI\PviServices\WinCE
组件 "BR.AN.PVIServices.dll"被添加到Visual Studio.NET项目中作为参考。
由于PVIServices组件是与应用程序的安装一起提供的,所以项目的运行时间只需要安装一个PVI Runtime。
在本培训模块中,AR000将被用于与控制器进行通信。本培训模块中记录了用于此目的的变量和相应的数据类型。
然而,任何现有的Automation Studio项目都可以使用--只有变量名称需要相应的替换。
需要一个带有变量 "Lifesign"和 "PV1"的任务 "pvitest"。
Fig. 4: Automation Studio test project
本培训模块中描述的所有功能都是用C#程序代码来解释的。
任何与VB.NET编程的差异都将被明确指出和描述。
用户还可以获得许多用C#编程语言创建的PVIServices实例。
这些例子可以在安装PVIServices时在目录"...\Samples\PviServices "中找到。
2.1.3 添加 "BR.AN.PviServices.dll"
必须添加相应DLL的引用,以访问PVIServices。
Fig. 5: Adding the BR.AN.PviServices.dll reference
在 "添加参考资料 "对话框中按下<浏览>按钮,可以从 "BrAutomation\Pvi\PviServices\Win32"目录(PVI Server&Runtime安装)或 "Program Files\BrAutomation\PVI\%Version%\PVI\PviServices\Win32"(PVI开发)中选择参考。
注意事项。
如果该组件显示在组件列表中,请确保PviControl.NET也使用该DLL。不能保证这两个版本是相同的。
这就是为什么应始终使用上述目录的原因。
通信对象表示位于控制器上的一个对象,如任务对象或变量对象。
PVIServices可以识别以下通信对象或类。
•Service class
•CPU class
•Task class
•Variable class
•Module class
每个通信对象都是由以下内容组成的。
•Properties
•Methods
•Events
这使得对象的应用能够一致和完整。
Fig. 6: PVIServices communication objects
注意。
所有的任务都是 异步处理的 。一个任务的响应是通过事件做出的。例如,一个变量对象的"读取"方法会在 "ValueRead"事件中发送响应数据。
所有通信类的方法、属性和事件都记录在PVIServices帮助文件中。
每个对象都写有其特定的属性。
在创建一个新的对象(在这个例子中,是一个 "Cpu "类型)后,根据要求定义属性。
必须使用对象的所需方法或功能来执行对特定对象的操作。
这就是使用 "连接"方法在CPU对象上建立与控制器的连接的方式。
"断开"方法用于终止与控制器的连接。
应用程序通过设置事件(EventHandlers)来了解对象的状态。
在Visual Basic.NET和C#中,如何做到这一点有一些区别。
在C#中,事件处理程序的设置是通过指定所需的事件,写上+=,然后按两次<TAB>键。
事件 处理程序 是 自动 设置 了 和 相应的 程序 代码被添加。
Note:
应该为每个对象添加"连接Connected"事件。只有在这样做了之后,才能进一步访问这些对象。
请注意
事件处理程序应该总是在调用方法之前被设置好。
否则,在方法调用中发送的事件可能不会被接收。
在Visual Basic.NET中, 事件处理程序 是通过指定 WithEvents来设置的。
从这一点来看, 现在可以从指定的类 "myCpu" 中选择事件,并输入事件所需的程序代码。
正如先前的培训模块TM700和TM710所描述的,所有的对象都是使用PVI对象层次结构在PVI应用中映射的。
在PVIServices类中,线路对象、设备对象、站点对象和CPU对象被映射到CPU类中。
Fig. 7: PVIServices – PVI object hierarchy
注意
PVIServices只支持INA2000 / ANSL系列。
为了创建PVIService对象,必须创建相应类的变量。
通过在C#中声明命名空间 "BR.AN.PviServices",可以直接访问这些类和成员。
从这一点上看,可以设置相应类别的PVIServices对象。
在Visual Basic.NET中,该声明看起来像这样:
当进行声明时,你必须确定这个对象中的事件是否应该被评估。
与PVI管理器的连接是通过服务类对象建立的。这个对象是客户端应用程序中所有后续对象(CPU、任务、变量)的基础。
一个新的服务对象 "myService"被设置为逻辑名称 "service"。
如果在 "Connected"方法中没有传输参数,就会创建一个与PVI管理器的本地连接。
通过指定远程PC的IP地址和端口号,可以建立一个远程连接。
与控制器的连接是通过CPU类对象建立的。此外,CPU对象上的所有全局变量和所有任务对象都由本地或全局变量管理。
诊断服务(内存、传输模块等)也由该类管理。
对上级服务对象的引用是通过指定 父级名称 (本例中为 "myService")进行的。
连接的类型(即介质)是通过 "Connection.DeviceType"属性定义的。
这些属性应该根据所选择的 "DeviceType"来定义。
PVIServices任务类对象代表控制器上的一个任务。任务中的全局和局部变量都在这个对象下管理。
对相应的 CPU对象的分配 是通过指定 上级对象的父级 名称 进行的 。
3.7 PVIServices – Variable class
PVIServices变量类对象代表控制器上的一个变量。
以下是可用的变量类型。
•Internal variables
•Global variables
•Local variables
通过指定 上级对象的父级名称 来分配一个变量 。
如果服务对象被输入为父名,就会创建一个内部变量。
在这个例子中创建了一个全局变量,因为Cpu对象被指定为父名称。
一个变量对象通过 "主动Active"属性切换为主动/被动。若Active参数被设置为False,则读写操作对此变量无效。
应用程序通过设置 "ValueChanged"事件处理程序获知数据变化。
ValueChanged"事件被调用,除非变量对象发生"断开连接"或 "激活Active"属性被设置为=false。
使用 "ReadValue"方法可以实现对变量对象的有针对性的、异步的访问。
另一种可能性是(使用活动变量)直接访问"值"属性。
注意事项
确保在读取变量对象的值属性时,为PVIServices变量对象收到的最后一个值被读取--无论该对象是否处于活动状态(活动属性)。
通过定义"值"属性,将分配的值写入变量中。
如果需要,也可以进行响应,因为写访问是异步的。这可以通过设置 "ValueWritten"事件的处理程序来实现。
注意。
在Visual Basic.NET(7.0)中不能分配运算符。然而,有两个选择。
3.8 PVIServices – Module class
PVIServices模块类对象定义了一个位于控制器上的BR模块及其属性。
对模块对象可以进行以下操作。
•Module upload
•Module download
•Delete module
从这个例子中可以看出,一个对象是由PVIServices模块类创建的。CPU对象被用作父名称。
该模块对象使用 "连接Connect"方法进行设置。在 "连接Conected"事件中,应用程序被告知设置成功。
在这个事件中,控制器上的模块使用 "Delete"方法被删除,应用程序在 "Deleted"事件中被告知成功的删除程序。
注意。
评估 "Error"事件也是必要的,因为在设置时可能发生错误(例如由于模块名称不正确)。因此,"已连接Connected"事件不被调用。
集合允许用户将具有相同类型的多个对象放在一起管理。
例如,如果变量被分组到一个集合中,那么这个集合就具有与基础变量类相似的属性、方法和事件。
这意味着每个变量不必被单独管理。相反,当调用该集合的方法(例如 "连接"方法)时,集合中的所有变量都会被自动管理。
多个屏幕的变量管理可以被看作是一个例子。一个屏幕的变量可以在一个集合中管理,以便同时将这些变量切换为主动/被动。
目录 "BrAutomation/Samples/PviServices"包含了一些使用集合的例子。
更详细的信息也可以在PVIServices用户文档中找到。
Fig. 8: PVIServices - Collections
如果已经创建了一个 "结构 "类型的变量对象,那么在收到 "连接"事件后,可以访问结构成员。
在 "连接" 时,PVIServices从结构中读取所有的信息,并在 哈希表中进行管理 。
这使得使用元素名称或数组的索引直接寻址结构元素成为可能。在PVIServices示例程序(第4项)中解释了一个带有结构的例子。
详细的信息可以在PVIServices用户文档中找到。
在 "BrAutomation/Samples/PviServices"目录下提供了一些结构的例子。需要一个包含结构变量的控制程序。
在本节中,将创建一个PVIServices应用程序,而不是进行练习和任务。
在这个例子中,将完成什么。
•创建一个Visual Studio.NET应用程序
•创建PVIServices对象
•错误评估
•评估数据变化
•读和写访问
•使用一个结构
4.1 创建一个新的Visual Studio.NET应用程序
我们现在将创建一个新的Visual Studio.NET应用程序。这个例子将使用一个C#应用程序来解释。然而,用户也应该可以利用上一节的信息用Visual Basic.NET来创建应用程序。
任务: 创建Visual Studio.NET应用程序并插入PVIServices引用。 这项任务的步骤应在第2章说明的帮助下进行。 对PVIServices的引用应该定义在命名空间中。 |
结果 从这一点上来说,PVIServices的类和成员都可以被访问。 |
在下一步,必须在表格类中声明程序实例所需的PVIServices变量。
例子: 在表单加载事件中创建服务对象。 Connected"事件的设置是为了在 "Connect"成功执行后,可以设置CPU对象。 我们将在这个例子中使用静态对象。 |
"IsStatic"属性用于确定后续对象是否被设置 为静态static=true 或 临时temporary=false (默认)。
当连接一个没有参数的新PVIServices对象时,将自动执行"创建Create"和 "链接Link"(即在创建过程对象的同时,放置一个链接对象)。
对于带有 "连接类型"参数的静态过程对象,可以进行以下定义。
ConnectionType |
说明 |
Create |
设置进程对象。 |
CreateAndLink |
设置流程对象和链接对象。 |
Link |
在现有流程对象上设置一个链接对象。 |
在设置变量对象时介绍了一个单独的 "创建Create"和 "链接Link"的例子。所有其他对象的设置都没有参数。
例子: 创建CPU对象和任务对象 为CPU对象与AR000建立一个TCPIP连接。用户任务的名称 "pvitest"被用作任务名称。 每个后续对象都是在前一个对象的 "连接 "事件中创建的。这确保了对象已经被成功创建。 "错误"事件对CPU和任务对象进行额外评估,以评估通信或配置错误。 错误信息和 "连接"事件被输出到一个名为 "txtStatus"的多行文本框控件。 |
启动应用程序后,相应对象的连接事件会显示在文本框中。
Fig. 9: Set up objects
如果在执行程序时发生错误,相应的错误代码和对象将显示在 "txtStatus"文本框中。
Fig. 10: Error event – Connection lost
一旦连接被重新建立,"连接"事件将被再次调用。
然而,这也意味着这些对象又是新建立的,因为它们是在前一个对象的"连接"事件中创建的。
为了防止这种情况发生,在创建对象时必须进行查询,以确定该对象是否已经存在。
如果在与控制器通信时失去连接,则调用"错误"事件(E=4808)。
这个事件是为所有活动对象创建的。这意味着当一个变量对象的 "活动Active"属性被设置为 "true"时,这个变量和所有更高级别的对象(任务对象和CPU对象)都会被调用。
一旦连接被重新建立,这些对象的 "连接 "事件会被自动调用。这时,可以再次访问各自的对象。
两个变量 "Lifesign"和 "PV1"在下一步被注册。
例子:设置变量 "LifeSign "和 "PV1"。 变量 "PV1"暂时只设置了 "ConnectionType.Create"。 应该使用"ValueChanged"和 "Error"事件。 |
PVIService类的 "变量"需要一个新的变量,用于 "PV1"变量。
有错误的变量名称 在PviEvent参数 "e.Name"中返回。错误号码在PviEvent参数 "e.ErrorCode"中返回。
在 "ValueChanged " 事件中, PviEvent 参数 "e.Name" 也 决定哪些变量已经改变。
注意。
变量 "linkVarPV1"将在下一个练习中创建链接对象时被创建。
启动程序后,"Lifesign"变量的值会显示在标签控件上。
变量 "PV1"的值仍然没有变化,因为它只是被创建,还没有被连接。
例子。为变量 "PV1 "创建一个连接对象 使用 "cmdConnectPV1"按钮创建一个链接对象。一个新的链接对象 "myLinkPV1"被创建,其连接类型为 "链接"。 |
为了创建一个指向已经存在的对象的链接, 链接变量对象的LinkName 属性必须被设置为要引用的变量对象(FullName),作为层次名称的值。
在调用连接方法时,还必须给出链接连接类型,以便启用LinkName属性。
与 "Lifesign"变量相同的事件被应用于 "ValueChanged"和 "Error "事件处理器。
结果 通过按下 "cmdConnectPV1"按钮,在 "PV1"链接对象上创建一个链接对象。"Active"属性用于确定 "ValueChanged"事件中的每个数值变化都应该被注册。 |
必须调用"断开连接"方法来再次删除链接对象。
通过 "Active = true "属性(事件掩码EV=ed)激活的变量对象被PVI管理器自动监测数据变化 -- 不管这些变量是由PVI线轮询(默认)还是由控制器通过 "Polling = false"属性(属性AT=re)作为事件变量监测。
这意味着,这些变量不再需要被应用程序额外读取。应用程序会在 "ValueChanged"事件中自动获知任何数据变化。
本培训模块将使用不同的例子来介绍读和写访问的三种访问方法。
使用 "ReadValue"方法可以读取一个变量对象。由于PVIServices是异步处理所有的任务,所以该值会在 "ValueRead "事件中返回。
例子: 读取 "Lifesign "变量的值 通过按下 "cmdReadVar"按钮来启动 "Lifesign "变量的读取过程。通过设置 "ValueRead"事件的处理程序,该值被输出到标签控件 "lblReadVar"。 |
结果 按下 "cmdReadVar"按钮,"Lifesign"变量的当前值被读取并输出到标签控件。 |
日期/时间是在PVIServices CPU类中读取的。
在CPU对象上调用"ReadDateTime"方法来读取时间。通过设置事件处理程序 "DateTimeRead",应用程序被告知该事件。
例子。读取控制器上的日期和时间 按新按钮 "cmdReadTime"启动时间的读取程序。读取的时间被输出到表格的文本属性中。 |
要定义一个变量,必须在"值"属性中定义所需的值。
例子:重置 "Lifesign "变量 通过按下新的 "cmdWriteVal "按钮,"Lifesign "变量被设置为 "0 "值。 写入任务通过事件 "ValueWritten"被确认。 |
在定义此属性后,会立即执行一个写入任务。
例如,可以通过设置属性 "WriteValueAutomatic = false "来抑制自动定义, 以便写入一个数组或结构的成员。
当 "WriteValue"方法被调用时,数组或结构只被写入一次。
Automation Studio项目可以用一个结构来扩展练习的例子。一个名为 "Pv_Struct"的结构被创建,有三个成员(元素)。
Fig. 11: AS test project with a structure
例子: 定义变量并创建结构变量 为PVIServices类变量创建一个结构变量。结构变量 "myStructPV"在任务的 "Connected"事件中被创建。 |
新的BR.AN.PviServices变量被定义在表单类中。
然后,该变量就被设置了。对"ValueChanged"和"Error"事件使用的事件处理程序与其他变量相同
例子:评估结构中的值变化 结构中的每一个数值变化都被登记在 "ValueChanged "事件中。结构中每个成员的值在文本框 "txtStatus "中输出。 |
在 "ValueChanged"事件中,检查变量是否为 "结构Structure "数据类型 ,并读取每个成员的值。
"e.ChangedMember"用于通知应用程序发生数值变化的成员名称,如果只应输出受影响成员中的数据变化。
例子:定义一个结构元素 使用新按钮"cmdSetStruct",用"Lifesign"变量的值定义了结构变量"Pv_Struct.Member3"。 |
整个结构是通过定义 "Value"属性来写入的--而不是像这里假设的那样只写入单个成员。
要想同时写入结构中的多个成员,请将 "WriteValueAutomatic"属性设置为 "false"值,在进行设置后,所有成员都用 "WriteValue"方法写入。
也可以在调用 "WriteValue"方法之前分配一个值,例如,使用 "myStructPV.Value["Member2"].Assign(20)"。
PVIServices可以用来创建一个Windows客户端应用程序,从可视化到在VisualStudio.NET编程环境中创建服务工具。
本培训模块涵盖了PVIServices类的一个小范围。请参考PVIServices用户文档和PVIServices样本,包括在PVI服务器和运行时间/开发安装中,以扩大该主题的基本知识。
Fig. 12: PVIServices