在组态软件中开发脚本功能的方法 | 您所在的位置:网站首页 › 软件脚本开发 › 在组态软件中开发脚本功能的方法 |
一、概述
大多数的组态软件都具有脚本功能,脚本可能是VBS、Lua、C#等语言,也可能是厂家自定义的一种语言。通过脚本,组态软件可以实现非常灵活的功能。 脚本的功能,基本可以定义为:读入外部数据,改变可视化元素。外部数据,最重要的是采集到的数据,也可能是用户创建的配置文件。而改变可视化元素,则包括创建、改变位置、改变状态、删除等操作。 本文通过一个示例,介绍在组态软件中实现脚本功能的方法。示例有以下假定: 开发语言C#脚本语言C#软件类型WPF 二、示例描述本文所使用的示例是简单且具有代表性的。本文所使用的脚本为: string x = GetParameter("A"); //读取参数A,作为X位移 string y = GetParameter("B"); //读取参数B,作为Y位移 string id = CreateComponent("rect"); //在画布中创建一个矩形 MoveComponent(id, x, y); //将矩形移动到参数所定义的位置可以看出,脚本首先读入外部数据(通过GetParameter方法),然后对可视化元素进行了改变(通过CreateComponent创建,通过MoveComponent移动)。读者在此肯定会提出疑问,GetParameter这些函数是哪里来的?这些是脚本跟主程序交互的API,我们会在一个类中事先定义好,然后传递到脚本中,下文会有详细介绍。 然后我们看软件的界面,如下图所示: 界面左侧,有两个框输入两个参数,然后是输入脚本内容,还有一个运行按钮。在右侧,则是一个画布,用于绘制脚本产生的效果。 三、开发过程 3.1 项目准备1、新建一个WPF工程,然后通过NuGet获取Microsoft.CodeAnalysis.CSharp.Scripting包。 2、在WPF中创建好界面需要的内容(也就是各输入框、按钮、Canvas)。 3.2 书写实际执行代码对应于脚本,实际执行的代码包括获取参数、创建矩形和移动矩形。在本示例中,我们全在MainWindow.cs中实现功能。 private string GetParameter(string name) { switch (name) { case "A": return ParaA.Text; case "B": return ParaB.Text; default: return ""; } } private string CreateComponent(string type) { if (type == "rect") { Random rand = new Random(); string id = $"com{rand.Next(10000):D4}"; var rect = new Rectangle() { Name = id, Width = 200, Height = 100, Fill = Brushes.Red }; RegisterName(id, rect); DisplayCanvas.Children.Add(rect); return id; } return ""; } private void MoveComponent(string para) { string[] parts = para.Split(','); string id = parts[0]; double x = double.Parse(parts[1]); double y = double.Parse(parts[2]); var rect = FindName(id) as Rectangle; Canvas.SetLeft(rect, x); Canvas.SetTop(rect, y); }GetParameter方法,根据参数的内容,返回相应输入框的内容。在实际情况中,也可能是根据采集数据的ID,获取采集数据的值。 CreateComponent方法,创建了一个红色矩形,添加到画布中,并返回了矩形的Name。 MoveComponent方法,假定参数的格式是"id,x,y",分解后,找到矩形并移动它。 3.3 书写脚本交互类也就是定义脚本与主程序交互的API。本示例中,没有传入数据对象,而是直接传入函数委托,这样的脚本中可以主动拉取数据或推送动作。 新建一个ScriptInteract类,内容如下所示: public class ScriptInteract { private Func Callback; public ScriptInteract(Func callback) { Callback = callback; } public string GetParameter(string name) { return Callback("GetParameter", name); } public string CreateComponent(string type) { return Callback("CreateComponent", type); } public void MoveComponent(string id, string x, string y) { Callback("MoveComponent", $"{id},{x},{y}"); } }由于API很多,为每一个API方法创建一个委托过于繁琐,故只创建一个通用委托,输入函数名和参数,返回一个字符串。 可以看到,上文中的脚本所调用的“未知函数”,就是ScriptInteract类中的方法。 3.4 主程序与交互类的关联交互类中只有一个通用委托,我们在MainWindow.cs中定义此委托的实现: private string Callback(string func, string para) { switch (func) { case "GetParameter": return GetParameter(para); case "CreateComponent": return CreateComponent(para); case "MoveComponent": MoveComponent(para); return ""; default: return ""; } }可以看到,通过回调函数调用了之前在MainWindow.cs中定义的实际执行函数。 然后把此函数作为参数传入到ScriptInteract对象中即可。 ScriptInteract interact = new ScriptInteract(Callback); 3.5 执行脚本执行脚本,也就是点击运行按钮的动作。先摆出代码: private void RunBtn_Click(object sender, RoutedEventArgs e) { ScriptInteract interact = new ScriptInteract(Callback); var code = ScriptText.Text; var options = ScriptOptions.Default .WithImports("System") .WithReferences(typeof(ScriptInteract).Assembly); var script = CSharpScript.Create(code, options, typeof(ScriptInteract)); script.RunAsync(interact).Wait(); }此代码,先创建一个ScriptInteract对象,关联了MainWindow.cs中的回调函数。然后把此参数传给脚本对象。那么,在脚本中就可以调用ScriptInteract所定义的API。 至此,所有功能开发完成。 示例Demo下载 |
CopyRight 2018-2019 实验室设备网 版权所有 |