又是一年春暖花开的三月,外面的桃花,樱花都已经盛开了,是时候出去感受一下春天的气息,迎来万物复苏的景象,生机勃勃的景象,一扫工作上的沉闷心情。上两周参加了Niagara的培训,包括Niagara的TCP培训和开发者培训,这也是工作十几年来最长的一次培训,收货满满,之前接触过Niagara,知道它很强大,但没有具体实操过,只看到别人拖拖拽拽一个复杂的控制逻辑就轻松完成了。在IOT概念满天飞的年代,我觉得Niagara确实是一个很成熟的IOT开发框架,而且这个技术已经十几年了,也就是说现在我们经常谈到的物联网,IOT,其实国外早就做的很成熟,只是现在可能更加强调的是平台化,而Niagara可能更加侧重于设备接入,充当网关,其实Niagara也可以作为平台。下面我将这两周的学习的一些主要内容总结一下,主要是来自老师的培训材料和自己的一些理解,很多东西我也还没有搞太明白,特别是Niagara驱动那块的功能,东西很多,估计需要上手一个真正的驱动才能更好的理解设计原理,管中窥豹,可见一斑,需要深入的学习还是需要亲自参加培训,给我们公司打一个广告,呵呵。
Niagara的架构
从上面的这张图,我们可以看出Niagara的架构,是不是很全面。
- 下到底层的运行时框架(Baja),你可以理解为一个Java运行时,里面除了Java运行时提供的功能外,还有Niagara提供的一套类库封装。
- 上到界面开发Web UI和widget,work bench界面开发,可以基于底层接入的数据设计自己的web界面,Niagara本身提供了一套界面生成框架,配置人员可以拖拖拽拽就能呈现出一个web界面,当然也可以基于Niagara框架来使用HTML5等技术来开发自己的Web页面。除了为用户设计或者配置页面,Niagara也考虑到方便配置工程师实施的效率,提供了配置开发页面,它是基于Niagara workbench来开发widget,方便实施工程师使用。
- 接入就更全面了,向上可以和企业对接,包括对接企业的关系型数据库,LDAP,Web service,邮箱系统等等。
- 向下可以支持各种标准协议的设备接入。包括比如Bacnet,OPC,Lonworks,modbus等,也可以接入非标准协议的设备,只要按照Niagara的驱动模型框架来开发驱动,Niagara就可以提供统一的数据模型来为上层应用服务。
-中间这层,我认为是现在IOT平台和Niagara的不同所在。为什么说Niagara更加侧重于设备接入和网关,它能收集到这些数据,比如报警,点值数据,日程等这些信息,但它能做的就是存储,而现在IOT平台更侧重的是对这些数据进行大数据分析,流式计算等分析出有价值的东西提供给用户,Niagara在这方面不是强项,它可以做到分布式的存储,把各个网关层的数据一层一层的收集到一个Supervisor上,仅仅如此。我认为这是Niagara跟IOT平台最大的不同。 - 另外在这个架构里,我觉得比较有意思的是两个东西,一个是Tag,也就是标签,这个是Niagara提供的,为什么说这个很有意思,因为现在互联网上的东西,都喜欢贴上一个标签,甚至人都会打上各种标签(帅哥,美女,年轻,冷酷....),物联网的世界更是如此,包括每一个设备,每一个属性,每一条数据都可以打上各种标签,而这些标签Niagara可以提供工具帮你打上,可以使用Niagara提供的标签,也可以使用开源的HayStack标签,也可以自定义标签。有了这些标签,就给上层应用提供了更加方便的检索和分析。
- 另外一个是BQL,这也是Niagara框架提供的另一个利器,它能帮助你检索到任意的东西,你可以理解为Niagara里面的任意组件,服务,以及用户配置的任何东西,设备,点值,驱动,服务等等,都可以通过BQL搜索到,因此为开发提供了极大的方便。
- 还有一个很重要的特性,我认为没有体现在这种架构图上的是Niagara的强大的集成能力,这个集成能力我觉得有三个方面,一个是上面提到的设备接入能力和企业服务集成能力,另外一个是整体接入能力,因为Niagara是一个分布式的系统,可以通过一个个的Niagara网关(JACE)来接入一个个的楼宇,然后Niagara提供了一个Supervisor来接入这些JACE,每个JACE网关的数据又可以同步到Supervisor来进行统一管理,Supervisor也可以管理这些网关设备,在Supervisor端的配置也可以下发到每一个网关,也可以实现JACE网关的OTA,相当于有个统一中心控制平台。
- 作为IOT设备的接入网关,安全肯定也少不了,Niagara在这方面也做了很多的事情,比如模块签名,每个自己开发的模块,需要做签名,Niagara提供了签名证书的管理和签名工具。Niagara也提供了license验证,每个开发的模块都可以使用Niagara提供的license框架来为自己开发的模块设置license。权限管理,Niagara为每一个功能模块和操作都可以设置细粒度的权限控制。
上面是我对Niagara整体架构的理解,还有很多的功能我也不是很了解,以后有时间会继续挖掘,一句话,Niagara作为10几年的成熟框架,你能想到的Niagara都帮你实现了,Niagara没有实现的,它也提供了可扩展的框架让你自己去实现。
Niagara主要功能
Niagara的主要功能包括
- 设备集成,可以发现各种标准协议的点,比如bacnet,opc,modbus等
- 创建点,Niagara可以创建点,有四种类型Numeric,String,Boolean和Enum四种,这些点可以是实际的物理点,也可以是虚点。
- 逻辑控制,可以在发现到的点的基础上,做各种控制逻辑,Niagara提供了很多的组件也可以自己开发组件,每种组件都可以自由的拖拽到wiresheet上做各种控制逻辑。
- 报警扩展,可以为点设置报警规则,并通过alarmclass来设置报警存储。
- 点历史扩展,可以为每个点值存储历史,并可以设置历史的存储机制。
- linkmark,可以为实际的物理点和虚点建立linkmark。
- PX sheet页面,可以创建PX Sheet页面,通过Niagara提供的界面元素,包括图片,Schematic图,label,Charts等来绑定点值来设计UI,并可以通过浏览器查看。
- 数据同步,Niagara supervisor可以将Jace里的数据同步到Supervisor上,包括报警,点历史等,Supervisor也可以管理Jace。
Niagara是一个开发的框架,所有的功能都可以在原有的基础上做扩展,也可以基于Niagara提供的功能来实现自己的组件。
Niagara模块开发
Niagara里的模块开发,主要有两类,一类是普通的组件,也可以是服务组件。另一类是驱动模块,这个下面再讲。服务和普通组件开发方式基本一样,唯一的差别就是服务组件一般派生于BAbstractService,这个抽象类里面实现了一些服务相关的方法,就相当于我们在些windows service时需要实现的一些方法,比如onStart,onStop等等,其他和基本组件基本相似。开发流程如下:
第一步,使用Niagara workbench里的工具新建一个空白的模块模板,这一步完成了一个模块的基本框架,以及Gradle打包和编译的脚本。
第二步,开发自己的模块,为模块指定palette item,palette item包括模块的属性和Action。这些item可以在模块的palette里进行设置,使用的方式是Annotation注解方式声明。
第三步,使用Gradle插件slotmatic来为上一步定义的palette item自动生成java代码。
第四步,开发自己的module,这一步就跟正常的java代码开发没什么两样,需要掌握Java编程技术,也需要了解Baja里的一些功能库,在开发过程中,也可以使用logger来打印调试信息。
第五步,模块签名,使用Niagara提供的签名工具来为自己开发的模块使用自签证书或者CA证书签名。
第六步,发布模块,通过workbench工具来将模块安装到JACE中。
Niagara模块异步编程
这块也是在Niagara开发中一个比较重要的知识点,Niagara有一个主线程,任何比较耗时的操作应该放在工作线程中,这个任何语言的开发模式都很类似。因为Niagara是基于Java框架,因此可以使用Java中的线程和线程池来实现异步。Niagara也提供了两种比较容易实现的方式,一个是Job,另一个是异步Action,使用workerthread来实现异步。Job方式可以对Job进行管理,比如取消,查看进度等。异步Action不能管理异步线程。
BSimpleJob
BSimpleJob 提供了一个基本的Job实现,包括
- 对后台线程进行管理,包括取消,查看进度等
-
需要实现run方法,需要考虑
1)包括当Job失败是抛出异常
2)run成功执行,调用success方法
3)调用progress() or heartbeat()来上报进度
public class BDiscoveryJob extends BSimpleJob
{
public BDiscoveryJob() { }
public void run(Context cx) throws Exception{
log().start(“Starting discovery"); ...
progress(50);
...
log().success(“Discovery complete”);
}
/**
* Callback when the user cancels this active job.
*/
public void doCancel(Context cx){
// Overridden here to set the canceled flag
canceled = true;
super.doCancel(cx);
}
}
异步Action
使用async flag来标志Action,使得控制引擎使用异步方式执行此Action。使用异步Action需要完成以下步骤,
- 使用Async flag来标志Action
- BComponent的post方法将次Action封装在worker里执行,并return null
public IFuture post(Action action, BValue argument, Context cx){
getWorker().postAsync(new Invocation(this, action, argument, cx));
return null;
}
- 在Bwork的子类里提供一个queue来post work并且在后台处理队列的work
@Override
public Worker getWorker() {
if(null == worker){
queue = new CoalesceQueue(1000);
worker = new Worker(queue);
}
return worker;
}
public void postAsync(Runnable r){
if (!isRunning() || queue == null){
throw new NotRunningException();
}
queue.enqueue(r);
}
private CoalesceQueue queue;
private Worker worker;
Niagara驱动开发
在Niagara中有两种驱动开发方法,一种是Niagara基本驱动开发,另一种是NDriver开发。这两种开发模式原理是相通的,只是NDriver提供了一套开发框架,为开发者减少了重复的工作量,开发者可以在此框架上开发驱动,更多的精力可以集中在驱动协议和消息的解析上面,其他交给开发框架来完成,有点类似于windows驱动开发,有原生的驱动开发,需要了解很多windows驱动开发技术,调用原生的API,但后来有WDK这种SDK,开发就变成了调用SDK来实现,相比起来就能简单一些。
Niagara驱动开发介绍
在做设备系统集成时,有各种驱动协议,modubus,bacnet,opc DA/UA等,各种上位机系统,比如门禁,防盗,能源等各种已有系统,如果上层应用都需要和这些不同子系统打交到,那对应用层就是灾难性的并且很难已维护。如何集成各种子系统并为上层应用提供统一的数据模型,这就是Niagara驱动做的事情。Niagara提供了一个驱动开发框架,按照这个开发框架和数据模型,按照这个框架来实现各种协议的驱动,就能为上层应用提供统一的数据模型。
下面就是一个Niagara驱动开发后的层次结构:
这里面的每个节点都是对应Niagara驱动开发的一个类,需要在每个类里面实现驱动的逻辑。这块功能现在体会还不是很深,以后有机会写一个自己的驱动,再补上一个完整的实例来理解这块内容。