天河电子商务网站建设,网站目录 整理,网站发布时间更改,浙江通管局 网站备案如何好注销一、 引子监控画面的主要功能之一就是跟踪下位机变量变化#xff0c;并将这些变化展现为动画。大部分时候#xff0c;界面上一个图元组件的某个状态#xff0c;与单一变量Tag绑定#xff0c;比如电机的运行态#xff0c;绑定一个MotorRunning信号#xff1b;但有些时候… 一、 引子 监控画面的主要功能之一就是跟踪下位机变量变化并将这些变化展现为动画。大部分时候界面上一个图元组件的某个状态与单一变量Tag绑定比如电机的运行态绑定一个MotorRunning信号但有些时候不会这么简单比如温度计在温度高于50℃显示红色;某设备报警可能是多个条件其中之一触发的结果变量变化触发一系列连锁反应…如此种种。考虑到工控行业大部分技术人员并非计算机专业出身如何能够用最少的编码解决各种复杂的变量-动画绑定问题无疑要费一番心思。二、 方案选型针对变量动画绑定问题可以选择的方案包括如下几种脚本编译器不少大型组态软件包含强大的脚本编辑器支持诸如VBS、Python甚至C脚本语言。脚本自带语法编辑器、调试器和编译器调用的API包罗万象如数据库API通讯API画面组态API…可以用脚本实现非常复杂的逻辑。但基于下面几种考虑我没有实现这类的脚本编译器不同于大部分组态软件包含一个独立的界面设计器我用Visual Studio来肩挑语法编辑、调试、编译和界面设计的重任没必要多此一举的搞一个独立的脚本编译器。C#结合Visual Studio来调用通讯、数据库链接的各类函数C#包含强大的语法功能配合.NET 类库几乎无所不能同时C#也支持脚本化没有必要在使用其他脚本语言。对于复杂的逻辑就让C#配合VS神器来完成吧。运算符重载。曾经研究过一个C#写的脚本编译系统它可以实现两个特定集合间的四则运算和逻辑运算如List1.AList2.A;List1.AList2.B。看上去集合就像一个普通的数值那样参与运算和操作。运算符重载是C#一个强大的语法功能可以重载的操作符如下运算符可重载性、-、!、~、、--、true、false可以重载这些一元运算符。 true和false运算符必须成对重载。、-、*、/、%、、|、^、、可以重载这些二元运算符。、!、、、、可以重载比较运算符。必须成对重载。、||不能重载条件逻辑运算符。 但可以使用能够重载的和|进行计算。[]不能重载数组索引运算符但可以定义索引器。()不能重载转换运算符但可以定义新的转换运算符。、-、*、/、%、、|、^、、不能显式重载赋值运算符。 在重写单个运算符如、-、%时它们会被隐式重写。、.、?:、-、new、is、sizeof、typeof无疑运算符重载用的好可以写出语义更清晰、更简洁的代码。比如有一种复数类型Complex有两个坐标x和y定义ComplexA大于ComplexB为 A的xy中至少有一个大于B的xy。我只需要重载操作符相应的最好重载,,以后只需要AB就能代替重复啰嗦的A.xB.x||A.yB.y。更可喜的是重载后的,这些运算符在.Net表达式树(ExpressionTree)中已经替换了它原来的语义。因此运算符重载在我这个编译器也有它用武之地。但出于下面两个原因它只适合作为编译引擎的辅助而不适合单独使用首先运算符重载只针对特定的类型对于不熟悉C#语法特性的编程者理解并正确的使用运算符重载不是件容易的事。运算符重载可以减少重复的代码让语法更简洁但依然要写C#代码不适合大部分工控人员。 订阅事件如果想省事最简单的办法是直接写代码例如如果一台电机的运行需要A,B,C三个前提条件均满足我就分别订阅A、B、C的变量变化事件如果A由fasle变为true再看看其他两个变量触发没有。也就是写这样几行代码 var tag1 App.Server[A]; var tag2 App.Server[B]; var tag3 App.Server[C]; if (tag1 ! null tag2 ! null tag3 ! null { tag1.ValueChanged (s, e) { if (tag1.Value.Boolean tag2.Value.Boolean tag3.Value.Boolean) { //执行 } }; tag2.ValueChanged (s, e) { if (tag1.Value.Boolean tag2.Value.Boolean tag3.Value.Boolean) { //执行 } }; tag3.ValueChanged (s, e) { if (tag1.Value.Boolean tag2.Value.Boolean tag3.Value.Boolean) { //执行 } }; }看上去不算复杂吧如果界面上有50个动画这样的代码就要写50次。不但浪费时间改起来麻烦查起来也麻烦。更糟糕的是不懂编程的人还用不了。 表达式编译器对于大部分零编程基础的上位机设计人员他们需要的是一种没有学习和理解成本的、简单直观的变量绑定方式。比如温度计在温度高于50℃显示红色就一句话【temperature50】;某设备显示报警可能是多个报警变量其中之一触发的结果只需写【Alarm1||Alarm2||Alarm3】…借助微软强大的表达式引擎如果能解析这类变量表达式设计者只需要知道图元与变量的逻辑关系而极少数表达式也难以企及的功能略微懂一点C#就可以实现。这样就可以做到使用简单上手容易同时又可以满足复杂的需求。同时还有下面几个额外的好处最少的编码量在一个界面的cs文件里几乎没有代码。绑定逻辑在XAML内用直观的方式嵌入 可以用复制、粘贴和文本替换等功能减少重复编码可以充分利用WPF的设计器扩展实现一个简单的语法编辑器实现语法高亮、自动完成并执行语法检查查找变量逻辑和修改很方便。这个编译器的主要代码在Eval类。三、 自己实现一个编译器编译原理大学计算机都有一门编译原理课程。当年我也捧着一本教材被“波兰表达式”、“逆波兰表达式”绕的云里雾里然而逆波兰表达式是实现编译器的关键。逆波兰表达式的优势在于只用两种简单操作入栈和出栈就可以搞定任何普通表达式的运算。其运算方式如下如果当前字符为变量或者为数字则压栈如果是运算符则将栈顶两个元素弹出作相应运算结果再入栈最后当表达式扫描完后栈里的就是结果。如何实现自己的编译器微软已经给大家现成的轮子了。微软的Expression类提供了一套拼接、编译Lambda表达式的完整方法可以用它轻松定义你自己的语法。相关知识可以参考博客园 装配脑袋 的自己动手开发编译器系列文章http://www.cnblogs.com/Ninputer/archive/2011/06/18/2084383.html。下面就以这个SCADA项目为例定义语法在这一版我只实现了最基本最常用的一些操作如四则运算-*/、逻辑运算(|!)、取反取模、三目条件等运算。GetOperatorLevel函数按照C#的运算符优先级定义运算优先级。定义了开头的自定义函数如Date取当前日期、App取当前路径等。IsConstant方法定义系统常数其中True/False表示逻辑常量字符串常量用’’。编译过程编译过程就是将一个字符串转换为一个带返回值的函数函数的参数就是表达式相关的Tag的值。依次为RpnExpression方法将中缀表达式转换为逆波兰表达式。用关键字将表达式字符串分割为一个数组按照优先级出栈入栈返回一个逆波兰表达式顺序的字符串列表。ComplieRpnExp方法根据逆波兰表达式顺序依次弹出运算符转换为Expression的各子类如二元表达式BinaryExpression、条件表达式ConditionalExpression、常数表达式ConstantExpression等参数首先判断是否常数如果不是则调用GetTagExpression方法将字符串转换为方法调用MethodCallExpression最终会将该参数编译为一个Tag。经过处理最终返回一个LambdaExpression。Eval方法将LambdaExpression编译为一个委托相关的Tag加入列表TagList。四、 应用场景 表达式与动画绑定在每一个界面窗体都有几乎一样的几行代码ListTagNodeHandle _valueChangedList; private void HMI_Loaded(object sender, RoutedEventArgs e) { lock (this) { _valueChangedList cvs1.BindingToServer(App.Server); } } private void HMI_Unloaded(object sender, RoutedEventArgs e) { lock (this) { App.Server.RemoveHandles(_valueChangedList); } }其中, BindingToServer就是对当前界面所有图元进行地毯式扫描搜索出各控件相关的TagReadText表达式并用Eval类编译之编译的结果转换为带返回值的函数和一个相关Tag的列表遍历这个Tag列表将其值变化事件ValueChanged与这个函数链接起来。这样在加载界面的时候已经完成了编译过程相关变量的值一旦改变就会根据表达式返回一个值如果这个值是布尔量同时与电机的运行动画绑定就完成了从表达式到动画的触发过程。 复杂报警条件报警一般包括超限报警、变量触发报警、差值报警等。但也可能有复杂的报警条件不能用超限、超差等简单方式表述的就可以归结为复杂报警其条件可以用类似动画绑定的表达式来描述在系统初始化时刻加载、编译为报警条件。 未来改进编辑器改进支持命令自动完成、语法高亮、更完善的语法检查。可考虑Sharpdevelop的编辑控件。支持复杂语法目前的语法仅仅是简单的四则运算和逻辑表达式。未来考虑支持多段表达式、函数如正余弦、属性引用等复杂语法。 github地址https://github.com/GavinYellow/SharpSCADA。QQ群102486275相关文章 .NET十年回顾开源纯C#工控网关组态软件开源纯C#工控网关组态软件(三)加入一个新驱动西门子S7开源纯C#工控网关组态软件(四)上下位机通讯原理开源纯C#工控网关组态软件(五)从网关到人机界面开源纯C#工控网关组态软件(六)图元组件开源纯C#工控网关组态软件(七)数据采集与归档原文地址:http://www.cnblogs.com/evilcat/p/8379640.html.NET社区新闻深度好文欢迎访问公众号文章汇总 http://www.csharpkit.com