BACnet MSTP自动地址分配

因为固件版本3.x,于2020.3.25添加:

因为不能保证所有设备同时上电,目前没有任何一种自动地址分配方案能够完全避免MAC地址冲突,所以我们从固件3.x版中移除了自动地址分配特性。为了帮助确定当前总线的“最大扫描地址”与空闲的MAC地址,用户可以启用“侦听”模式,然后在“运行信息”页面中,找到“当前最大扫描地址”,再通过“最近活动的其它站点”,找到未使用的MAC地址。

MSTP总线上的每一个设备必须有一个独特的MAC地址。对于主站设备,合法的地址范围为0~127,而对于从站设备的范围为128~254。

通常MAC地址采有以下几种方式确定:拨码开关,板上跳线,HMI界面,固件传输等。有的设备支持通过BACnet写属性服务修改MAC地址,但是这之前,设备必须要有合法的MAC地址以接入BACnet网络。

如果独特的MAC地址能够自动获得,就象我们将笔记本接入家庭或办公网络一样通过DHCP服务自动获取,我们就可以节省大量的调试时间。

这里讨论了好几种方案.    目前看来委员会更倾向于 “零配置方案” (附录135-2012bb)

开源的BACnet stack已经实现了 “零配置方案”.

“零配置方案” 只适用于最大扫描地址为127的情况,且自动地址分配范围为64~127。如不满足,可能带来混乱。

为了避免以上限制, BACRouter实现了私有的自动地址分配方案,并且与“零配置方案”保持兼容。它有以下吸引人的特性:

  1. 从总线流量中学习最大扫描地址。
  2. 从最大的未使用地址开始分配。

所以用户可以更加自由地规划地址,例如,将0~30留给固定地址的设备,将最大扫描地址设为40。这样自动获取地址的设备接入总线后,将从高到低依次使用40~31的地址。

不管是“零配置方案”还是BACRouter的方案,当已经自动获得地址的设备从总线中断开后,再重新接入总线,非常有可能遇到地址冲突,因为在断开期间,其地址可能被其它新接入的自动获取地址的设备占用。(BACRouter可能更容易遇到问题,因为它的地址分配不是随机的), 所以

一定要在接入总线的情况下,给自动获取地址的设备上电。

MSTP支持扩展帧设备与旧设备的互操作问题

最早的BACnet MS/TP设计只支持NPDU长度到501字节,大幅地小于IP与Ethernet链路层的1497字节长度。这限制了MS/TP的传输效率,增加了应用层的复杂度,特别当两个IP或Ethernet子网通过MS/TP子网连接在一起的时候。

扩展帧设计用于解决这个问题。标准附录此处可见. 简要地说, 此附录增加了两种帧类型:

  • 32: BACnet扩展帧须应答
  • 33: BACnet扩展帧无须应答

帧类型32由帧类型5(BACnet帧须应答)扩展而来,特殊之处在于它以COBS规则编码及NPDU长度为502到1497字节。

同样地,帧类型33由帧类型6 (BACnet帧无须应答)扩展而来。

扩展帧支持从修订版16开始正式引入标准。但是现场及市场上仍然有大量的旧设备不支持。支持扩展帧设备与旧设备之间的互操作性值得探讨。

  • 非路由旧设备与支持扩展帧设备:因为所有发往旧设备的NPDU都是应用层包,在旧设备的Device对象或发出的确认服务请求中的”最大可接受APDU长度”参数限制了NPDU包的大小,所以这种配置没有问题。
  • 旧路由与支持扩展帧设备: 须经由旧路由转发到其它子网的NPDU,如果其长度超过501字节将无法被旧路由识别而丢弃,发送方也收不到”包长超出”的网络层拒绝包。甚而,旧路由的”最大可接受APDU长度” 参数有可能是由其它路由口的参数决定的 (BACnet标准允许这种做法),因而其封包长度可能超出501字节,此时发往旧路由的应用层包也可能被丢弃。因此这种配置可能造成互操作问题。

BACRouter在非常早的版本就支持了扩展帧。从固件版本3.18开始,我们在BACRouter的MS/TP配置中引入了”扩展帧支持“选项,如果在总线上有不支持扩展帧的旧路由,此选项必须关闭以避免互操作性问题。

值得注意的是,即使”扩展帧支持“选项被关闭,不象旧路由,BACRouter仍然与支持扩展帧的设备有良好的互操作性。

(截图于2021-08-05更新,因为扩展帧是标准修订版16的强制要求,所以从固件4.13起,我们把这个功能选项移入到扩展配置模式中)

针对BACnet MSTP的帧失步攻击

如前面的文章 “BACnet MSTP 帧失步” 所指, BACnet MSTP 有一个帧失步的设计缺陷,但是是否可以利用这个缺陷,在完全遵守协议的前提下,对MSTP总线进行破坏呢?

设计这个攻击,我们先做以下几个假设:

  1. 总线上至少有3个设备,MAC地址分别为1, 8, 10。其中设备1是精心设计用来发动攻击的,设备8与10是无辜的。
  2. 设备1支持扩展帧,设备8与10不支持。
  3. 这3个设备的定时器都足够精确。

设备1的工作流程如下:

  1. 得到令牌,发送A帧
  2. 传递令牌到其它设备
  3. 再次得到令牌时,发送B帧
  4. 传递令牌到其它设备
  5. 重复步骤1.

A帧是一个合法的私有数据帧,十六进制数据如下:

55 ff 80 ff 01 00 1d a3 02 2b 72 fe 55 ff 03 08 01 00 11 a0 ff 55 ff 21 01 08 00 09 ce d4 f3 55 ff 00 01 08 00 00 bf

B帧也是一个合法的私有数据帧,十六进制数据如下:

55 ff 80 ff 01 00 1d a3 02 2b fe dc 55 ff 03 0a 01 00 11 b1 ff 55 ff 21 01 0a 00 09 fd 8a 51 55 ff 00 01 0a 00 00 8c

如果没有帧失步,一切都将正常运行。但是可能几小时,也可能几天后,设备8对设备1发出的A帧失步了,错过了A帧的帧头(设备10如对B帧失步,也是同样的效果),则设备8继续扫描A帧的数据部分,发现另一个有效帧:

55 ff 03 08 01 00 11 a0 ff 55 ff 21 01 08 00 09 ce d4 f3 55 ff 00 01 08 00 00 bf

这是发给设备8的Test-Request帧,设备8等待Tturnaround后发送Test-Response帧进行应答:

55 ff 04 01 08 00 11 ae ff 55 ff 21 01 08 00 09 ce d4 f3 55 ff 00 01 08 00 00 bf

但是此时,设备1正在传出令牌:

55 ff 00 02 01 00 00 73

令牌帧与Test_Response的前8个字节冲突了,对于设备10来说,收到了几个错误字节后,继续扫描,在Test_Response的数据部分又发现了一个帧:

55 ff 21 01 08 00 09 ce d4 f3 55 ff 00 01 08 00 00 bf

对设备10来说,这不是发给它的帧,所以他进入SKIP-DATA状态,抛弃数据,等这个帧结束,但是直到设备8发完数据,设备10还差一个字节来结束帧,他将继续等待。

对设备1来说,它发出令牌帧后,收到如下数据:

55 ff 21 01 08 00 09 ce d4 f3 55 ff 00 01 08 00 00 bf

这是一个扩展数据帧,因为它支持扩展帧,所以他按 Addendum 135-2012an规定的流程校验帧头,发现数据长度过短,中断前帧后又开始扫描,发现新帧:

55 ff 00 01 08 00 00 bf

这是一个发给设备1的令牌帧,设备1又得到令牌,经过Tturnaround后,重新发送B帧:

55 ff 80 ff 01 00 1d a3 02 2b fe dc 55 ff 03 0a 01 00 11 b1 ff 55 ff 21 01 0a 00 09 fd 8a 51 55 ff 00 01 0a 00 00 8c

在前面提到,设备10还差1个字节来结束前面一帧,因Tframe_abort>Ttrurnaround,所以解析没有中断,B帧的第一个55字节被设备10抛弃,然后开始扫描新帧,发现了:

55 ff 03 0a 01 00 11 b1 ff 55 ff 21 01 0a 00 09 fd 8a 51 55 ff 00 01 0a 00 00 8c

这是一个发给设备10的Test-Request帧,事情又开始重复。

从上面可以看出,每个设备都严格地遵守标准,但是一旦帧失步发生,整条总线就永远地瘫痪了。

更多信息见:MSTP帧失步解决方案

MSTP帧失步解决方案

于2021.7.13更新

我们曾在下面的文章中讨论过BACnet MSTP协议中有帧失步的弱点:

BACnet MSTP 帧失步

针对 BACnet MSTP 的帧失步攻击

对于BACRouter 来说,怎么来防范这个漏洞呢?让我们从标准找线索:

9.5.2 变量

SilenceTimer(翻译为静默计时器): 名义精度5ms的计时器,每当总线上有活动或每发送一个字节后清零

9.5.3 参数

Tframe_gap(翻译为字节间隔): 节点在发送一个帧时,在两个字节之间允许的最长的空闲时间: 20位时间。以我们的经验市面上几乎所有MSTP设备的字节间隔为0

Tturnaround: 节点接收到最后一个字节与开始发送之间的最小时间间隔: 40位时间

Tpostdrive: 节点发送完最后一个字节的停止位,到关闭485的驱动器之间的最长时间: 15位时间

9.5.5 发送帧流程

当SilenceTimer小于Tturnaround时, 等待 (Tturnaround – SilenceTimer)时间

9.2.3 时序

驱动器关闭: 节点应该在一个帧的最后字节的停止位起的Tpostdrive时间内关闭驱动器。标准允许但不鼓励,在帧的最后一个字节后再发送一个填充字节,如果填充字节被使用,它必须是0xFF,填充字节不被认为是帧的一部分,且应该包括在Tpostdrive时间内。

(此处并不明确Tturnaround是否包括填充字节的时间,但是在135.1的测试标准的12.1.3.4章节就描述得很清晰:Tturnaround从最后一个字节的停止位后开始计时,如果节点采用了填充字节,则应该由填充字节前一个字节的停止位后开始)

如此可见,在一个正常帧内,2个字节之间的最大空闲时间为20位时间,如果计上前一个字节拖尾的“1”位,则最长的总线空闲时间为29位时间(假设前一个字节为0xFF)。

考虑到填充字节,两帧之间的最小总线空闲时间为:Tturnaround – Tpostdrive + 9 (填充字节拖尾的”1″的位数)= 34位时间

所以BACRouter采用一个改进的接收有限状态机:

  1. 在一个MSTP帧中,字节间隔如大于20位时间,认为MSTP帧中断。
  2. 总线空闲大于等于33位时间,认为新的MSTP帧出现。
  3. 为了尽量兼容部分不遵守Tturnaround的设备,所有在有效MSTP帧后的数据认为是新的一帧。

在115200波特率下,一个数据位的时间仅8.7微秒,为了精确地测量空闲时间,BACRouter采用了5微秒精度的定时器,它有效地防止帧失步出现,并且 在115.2kbps下达到98.8%的带宽利用率 因为BACRouter发包时精确地遵守40位的Tturnaround,没有浪费多余的等待时间。

BACnet MSTP 帧失步

在MSTP领域有2个帧的概念:

  1. BACnet MSTP数据链路层的帧,它由最少8个字节组成,包括:2个前导字节为0x55, 0xff,帧类型,目标MAC地址,源MAC地址,2个字节的数据长度,crc8校验,如果数据长度不为零,还包括数据与数据较验。这里把这种帧称为MSTP帧。
  2. EIA-485帧,它由位组成,包括一个起始位,数据位,较验位,停止位。MSTP采用NRZ不归零编码,8个数据位,无较验位,一个停止位。起始位为0低电平,停止位为1高电平,数据位低位优先传输。这里把这种帧称为“字节帧”。

BACnet MSTP的接收有限状态机采用前导字节分辨MSTP帧的起始。如果在中途超过Tframe_abourt(最小60位时间,但是允许采用更大的值,最大可达100毫秒)没有收到数据或错误,则放弃帧,重新开始搜寻帧前导字节。

因为前导字节可以出现在MSTP帧的数据部分(Addendum 135-2012an 引入的扩展帧的数据及数据较验部分采用COBS编码避免出现前导字节)所以如果出现帧失步,接收状态机有可能会把前一个MSTP帧的数据部分认为是新的MSTP帧。

MSTP帧之间最小时间间隔是Tturnaround(40位时间)小于Tframe_abort,如果接收状态机对MSTP帧的解析失步,有可能会跨过帧间隔继续解析。

MSTP帧失步有几个可能原因:

  1. 发送设备与接收设备的程序漏洞,这可以通过代码审查与除错解决。
  2. 时间精度. BACnet MSTP标准仅要求1%精度的定时器,分辨率最小5毫秒。而应答方的最大延迟时间与等待方的最小超时之间的时间冗余只有5毫秒(如Tusage_delay与Tusage_timeout, Treply_delay与Treply_timeout),因此非常容易触发冲突引起失步。
  3. 总线上噪声。噪声导致的接收错误或数据校验错引起失步。

有人可以争辨说MSTP帧有crc校验保护。即使不考虑恶意设备(这里是一个例子)和随机数据碰撞, 现实中仍然有可能在帧数据中包含完整的MSTP帧。

(修订于2021.06.25)例如,市场上已经很多支持MSTP包捕捉的产品。捕获的数据也可能通过BACnet服务来传输(PrivateTransfer或AtomicReadFile?),假设当数据传输经过一个MSTP子网时,总线上出现电子噪音,会发生什么情况呢?

这些帧失步的后果不仅仅是可能导致总线拥堵,甚至设备的误动作(如果数据部分的帧是个APDU),更有甚者如果错误的帧是路由配置包的话,可能导致整个BACnet互联网络瘫痪。


字节帧失步

字节帧的失步,可能原因一般是:数据噪声,不当的终端电阻,总线未偏置引起。失步的表现有两个,一是将数据位的1解析为总线的空闲,二是将数据位的0解析为新字节的起始位。失步除了导致接收到错误的数据,如果发生在MSTP帧的最后一个字节,将可能引起对总线空闲时间的测量误差(可能过长或过短)。

更多信息见:MSTP帧失步解决方案

一次最大发包数与根据令牌占用时间

从固件版本2.0开始,BACRouter引入一个新的特性:根据令牌占用时间的一次最大发包数。

在BACnet MSTP标准中,一个主站得到令牌后,可以发送“一次最大发包数”的包后,再传递出令牌。“一次最大发包数”的默认值是1。路由器作为流量汇聚点,提高这个值可以改进网络交换带宽,但是会增加令牌占用时间。大多数路由的建议值为5到20。

MSTP作为常见的现场总线,通常由控制器、传感器、执行器互联,这些设备构成直接的控制回路,数据交换延迟通常要得到保证。我们建议设备得到令牌的时间间隔要小于1秒 。

路由器发送的NPDU的长度通常在10~50字节之间。但是最大可达到501字节(或扩展帧的1497字节)。越大的帧需要越长的时间来收发。

对于需要回应的NPDU来说,路由器需要等待目标设备应答。通常目标设备需要更长的时间来处理长帧,即路由器需要等待更长的时间。

所以同样的“一次最大发包数”,每次路由持用令牌的时间变化很大,对MSTP总线的延迟保证非常不利。

为避免这个问题,我们引进“根据令牌占用时间”特性来限制路由器持有令牌的时间。这个特性启用后。路由器不计算发包数,而是计量持有令牌的时间,当时间达到:

每字节发送时长 * 32 * “一次最大发包数”

就不再发送新帧,并传出令牌。例如“一次最大发包数”为10, 波特率为76.8kbps,每字节发送时长为0.13毫秒,则最大令牌持有时间为:

0.13 * 32 * 10 = 41.6 毫秒.

这个特性可以通过WebUI方便地启用与关闭。

MSTP包延时保证

BACnet有两种类型的服务,分为无确认与有确认。有确认服务的发送者(客户端)会等待应答直至超时。

通常情况下,无确认服务的包延时不会带来副作用。但对于有确认服务的请求包与应答包,过长的包延时将导致应答包因为超时而被抛弃,浪费了通讯带宽。

更有甚者,过迟到达的应答包可能导致应用层的逻辑错误!原因如下:

有确认服务的请求包头带有一个InvokeID,值范围0~255。应答包有同样的InvokeID。客户端通过这个InvokeID匹配请求与应答。在一个繁忙的客户端,InvokeID会快速耗尽, 此时只能回收重用已完成的服务的InvokeID。

如果一个有确认服务的应答包被过分延迟,客户端可能因为超时而结束服务,其InvokeID被回收,并被重新分配使用。此时被延迟的应答包被收到后,其InvokeID将被匹配到错误的服务。例如:

  • 客户端发出一个WriteProperty请求A,写设备X对象Y属性Z,分配的InvokeID为0。写入成功,但此请求包或者应答包延迟了。
  • 客户端等待超时而结束服务,InvokeID 0被回收。
  • 客户端发出一个WriteProperty请求B,写设备X对象U属性V,InvokeID又分配到0。写入失败。
  • 请求A的应答包先到达,由其InvokeID匹配到请求B。客户端认为请求B写入成功,造成应用层逻辑错误。

对高速的链路层如以太网或IP, 包延时通常是可忽略的,但是对于MSTP,有很多原因将造成过长的包延时:

  1. 信号噪声造成的令牌丢失或冲突。
  2. 不适当的设备配置(波特率,最大扫描站号,最大发包数)。
  3. 过高的流量。
  4. 过慢的设备。

为了避免InvokeID冲突及提高网络性能,版本2.0及以上的BACRouter实现了10秒钟 (参考BACnet的缺省APDU_Timeout,从v4.17起此延时修改为6秒钟) 的包延时保证,在收到后不能在此延时内完全转发的包将被抛弃。

虽然此策略可能造成服务无应答,但是比起错误应答,无应答是可以通过应用层的重试机制处理。

MSTP 固定/自动/强制 波特率

更新于2020-11-20(文末添加江森DDC内容)

MSTP的波特率设置一直是个现场工程师头痛的问题,如果设备的波特率设置有误,就无法加入MSTP网络中。

大部分设备采用固定的波特率,如需修改波特率,工程师必须接触到设备并调整DIP开关。有的设备支持通过BACnet服务修改波特率,但是在这之前,设备必须要能接入到BACnet网络中。

有的厂商实现了自动波特率配置,但是也带来了更多的问题,目前市场上的自动波特率有两种类型:

  • 启动时探测:设备在启动时监听总线并探测波特率,随后一直以该波特率运行。
  • 动态探测:设备不但在启动时探测波特率,在运行中如果在一段时间内持续发生通讯错误,即认为波特率改变,重新探测波特率。

不管是哪种类型,在总线运行时改变波特率都是非常困难的。仅仅改变所有固定波特率设备的设置是无法影响总线波特率的,因为其它自动波特率设备仍然以旧的波特率运中。唯一可靠的方法是在改变所有固定波特率设备的设置后,关掉所有自动波特率设备,再启动所有自动波特率设备(不能一个接一个的重新启动自动波特率设备!因为仍在运行中的自动波特率设备将维持总线波特率)

BACRouter的新版本固件(版本>=2.0)引入了新的波特率管理机制(专利申请中)。BACRouter有三种波特率模式:固定/自动/强制。

  • 固定波特率模式与传统的固定波特率一样
  • 自动波特率模式类似于前述的动态探测。重新探测的条件是10个连续的错误帧,通常只需要几秒钟。
  • 强制波特率模式类似于自动波特率模式,区别在于其在得到令牌后,将波特率改为预设的波特率。

当总线中有一个强制模式设备时,总线的波特率将会强制运行于预设值,而其它自动模式设备将自动同步波特率。固定模式但波特率设置值不同于预设值的设备将无法出现在总线中(通过检查BACRouter的运行信息中的“最近活动设备”项将很快地把这些设备找出)。对于上述的启动时探测设备,如果其探测到的波特率不同于预设值,也无法出现在总线中(同样可以通过检查BACRouter的运行信息中的“最近活动设备”项找出),但只需将其一个接一个的重新启动即可(不需全部断电,再全部上电)。

多个强制模式的设备可以共存在总线中,但这些设备中的波特率预设值必须相同。

江森自控的FEC与IOM模块即采用动态波特率,经测试,当波特率不匹配时间到150秒左右,模块开始重新检测波特率。

在BACRouter与FEC2611及IOM3731组成的测试总线中,双方完美协作,总线波特率可由BACRouter控制在9.6k~76.8k之间动态切换,FEC2611与IOM3731会延迟2.5分钟后刷新波特率。

BACRouter版本升级记录

旧固件底层OpenWRT

5.03 2024.03.20  下载

支持设置动态IP

Modbus模块从5.00起有一个bug: Modbus地址设置从点属性编辑窗口返回时不能保存。

5.01 2024.01.23

v5.00从旧版本升级时有一个bug阻止界面显示。

5.00 2024.01.05

增加自由协议模块以脚本支持各种RS485与TCP网关功能。API手册正在编写中

Modbus网关功能在v4.34引入一个bug,当写入映射于寄存器部分位的多态对象时将触发。

COV通知功能对多状态输入对象有一个竞态bug.

RS485 现在有两种无校验方式:无校验2停止位,无校验1停止位。通常无校验2停止位可以正常工作,不管对方的停止位怎么设定。但是对于某些诡异的Modbus设备,不遵守应答前静默3.5T的约定,如江*的TMS2000温控器,只有设为无校验1停止位才能工作。

4.35 2023.11.15  下载

网络层bug修复: 当缓存无法路由包时缓冲溢出。

4.34 2023.09.04

135-2016br-2: 接受写NULL到不可命令属性。

MSTP驱动立即向上层报告新包,而非以20ms的周期。

Modbus脚本: context参数携带点名与点描述。

Modbus支持2个寄存器的多状态点。

Modbus支持映射到寄存器部分位的模拟量。

Modbus支持自定义模拟量映射到多达24个寄存器。

Modbus映射输出对象时增加“容忍不匹配”选项,当回读数值与上次写入数值不匹配时,可靠性属性不变,并以“离线刷新间隔”重复输出。

Modbus驱动移除一些不必要的优化:将对同一个寄存器的多个写请求合并为一个;缓存模拟量从Modbus到BACnet的换算。

X2BACnet工程转换支持早期的X2BAC版本。

4.3201 2023.03.30

v4.23 引入的Modbus后台bug:

RTU/ASCII可能无法工作于低波特率下。

TCP从站如报告错误码将导致程序崩溃。

4.31 2023.03.23

WebUI: 在Modbus的从站设定页面,用户经常错点“编辑”与“复制”按钮,影响生产力。“编辑”按钮被删除。用户可点击点名或属性,弹出点编辑窗口。

4.3002 2023.03.20

一个长期的BACnet Bug: 当写属性的APDU中的优先级参数被忽略时,没有设置默认的优先级。

Modbus: 映射到保持寄存器的BV/BO,当选择写功能码时,应参考“单寄存器写”而不是“单线圈写“

Modbus: TCP从站地址范围由1~247扩展到0~255

Modbus bug 由v4.23导入: 离线设备可能增加在线设备的失败机率。

WebUI: Modbus“读测试”与”写测试”时将报告更详细的出错信息。

WebUI: Modbus参数编辑时的UI优化。

WebUI bug 由v4.25引入: Modbus “写测试“ 应不能在映射到只读Modbus地址,或BACnet对象类型为输入时启用。

WebUI: 当Modbus”写测试”写到多个寄存器时,提醒用户注意“单寄存器写“设定冲突。

WebUI: 在从站设定中启用拖放式移动点。

WebUI: Modbus多态点编辑时,启用拖放式移动状态定义。

4.29 2023.03.14

WebUI: 当导出到文件时,弹出窗口以便修改文件名。

4.28 2023.03.11

WebUI修正: Modbus 从站的”复原”按钮无法回滚”批量数据地址“所做的修改。

WebUI: Modbus从站增加”重排实例号”功能。

4.27 2023.03.09

所有包捕捉缓冲区总和限制从16M改到12M.

WebUI修下: Modbus从站的”批量换算”功能应跳过自定义类型。

WebUI: 导出的Modbus主站/从站配置应携带引用的脚本。当导入配置时,脚本也将被导入。

4.26 2023.03.06

BIP UDP 端口的最小值改为1024

许多脚本功能的Bug修正及改进:

当发生内存不足时,所有的脚本将被一个个地临时卸载,在卸载过程中回收的内存将被记录。回收内存最多的脚本将被视为存在内存泄露并被强制完全卸载,其余的脚本重新装入执行。

WebUI 增加脚本运行信息,以方便找到内存泄露。

脚本导入将跳转到编辑模式

创建与导入的脚本在经确认后,可以替换同名旧脚本的内容。

4.25 2023.03.02

我们经常接到用户反馈一些奇怪的Modbus设备,它们的寄存器无法线性地换算到BACnet模拟量的浮点数,所以我们引入了Lua脚本功能以处理这些映射。

用户可以在WebUI上新建、导入、编辑Lua脚本,感谢现代浏览器对WASM的支持,用户甚至可以在Modbus设备不在线的情况下,通过WebUI运行、调试Lua脚本,运行错误将由WebUI捕捉并展示给用户,Lua的print函数将输出到浏览器的终端。

负面影响是从此版本开始,我们不得不停止支持IE浏览器(但Edge仍然可以完美兼容)

目前Lua脚本的创建功能将生成一个映射Modbus BCD码的样例脚本

修正了v4.23引入的Modbus bug: AO对象持续报告可靠性问题。

4.24 2023.02.20  下载

从v4.23开始,我们对Modbus rs485驱动进行了抽象,以便在将来支持通用的rs485设备。当然这引入了Modbus网关串口功能一些bug(MSTP使用不同驱动,所以不受影响),这个固件修复了其中的一些:

离线设备引发程序重启

WebUI的串口Modbus设备的点位裸测试结果中的响应时间不精确。

4.23 2023.02.14

修复: 当Modbus模块将Ananlog_Output映射到多个寄存器上时的缓冲溢出

BIP 支持PPP接口以方便VPN连接

4.22 2022.11.22  下载

修复Modbus模块Bug:当一个TCP主站下定义了多于一个从站,且“连接保持时间”为0时可能被触发。

4.21 2022.11.13

WebUI 不再支持 IE10。

运行信息中的历史统计数据可以被重置。

MS/TP运行信息中用不同颜色的MAC地址表表示不同的状态。

4.20 2022.07.25

支持单口路由.

4.19 2022.05.20

Modbus网关导入CSV功能:

1. 修正从第2个点开始Modbus数据类型被忽略。

2. 状态未定义的多状态点不必被强制停用。

4.18 2022.02.07

从版本v3.00起,  我们加入了一个数据完整性检查: 如转发的NPDU的hop count为255,将被认为是错误并丢弃。用户可以从日志上看到相关信息:[WARN]npdu_decode_pci: hop count should not be 255 for relayed npdu.

但这个行为可能导致与其它路由器的兼容性问题。虽然此处的hop count不正确,但是因为BTL测试没有完整覆盖相关内容,市场上仍有一些经BTL认证的路由器有此错误。

相关的细节请查看:  https://hvac-talk.com/vbb/threads/2098761-BACRouter-from-China/page11, 非常感谢MaxBurn报告并协助我们定位问题。

解决方案是将hop count改为254并接受NPDU。用户可以从日志上看到:[WARN]npdu_decode_pci: hop count should not be 255 for relayed npdu, change to 254

4.17 2022.01.10

提供更多信息的日志

ReadPropertyMultiple: 构建大的回应包的可能的缓冲区溢出

当设备实例号被BACnet服务修改时可能造成冲突

当处理write-bdt bvll请求时,如BDT无变化,不触发配置保存动作,以延长flash寿命。

当VBUS的网络号被initialize-routing-table请求修改,如正在处理到虚拟设备的确认请求,当造成冲突。

MS/TP由4.10版引入的bug,在收到错误的帧头时可能引发时序错误。

4.16 2021.12.13

BBMD: 广播分布推送时遗忘了本地BBMD.

Modbus: 主站复制时WebUI bug.

4.15 2021.9.15

Modbus: 更方便的主站/从站复制功能.

Modbus: 支持批量修改从站的Modbus参数.

Modbus: 多状态对象可以映射于寄存器内的部分位(不必映射于整个寄存器).

4.14 2021.8.25

紧急升级功能存在一个bug导致旧的配置未被删除,如旧的配置有错误可能导致WebUI无法使用。如果旧版本固件因为配置问题无法使用,请用本固件紧急升级两次,第一次将升级固件,第二次就会删除旧的配置。

修复Modbus虚拟设备模式的bug,此bug在虚拟设备数量大于5时触发。

修复WebUI当导入的Modbus从站数量超过限制时的bug.

Modbus主站与从站的数量限制由100改为128.

修复WebUI停用“包捕捉映射”的bug.

为兼容更多的上位机系统及DDC编程软件,增加多个名称分隔符选项,修正内部对象名以避免与新增加的分隔符冲突。

4.13 2021.8.5

Modbus从站设定增加“批量地址”功能。

MS/TP扩展帧支持选项移到扩展配置模式中。

4.12 2021.7.23

从3.x开始的一个长期bug可能导致ms/tp端口停止工作。

4.11 2021.7.16

在4.10版本中MS/TP更新时序引入一个bug,由高等级编译优化引发。

4.10 2021.7.13

BACnet 协议版本号改为16

Polarity在Binary Value对象中是私有属性

MS/TP更新时序以兼容填充字节

Modbus 主站: 批量导入,批量实例号,批量点表

Modbus 从站: 导入点表

Modbus 主/从站: 复制与上下移动的UI.

4.09  2021.7.02

兼容新硬件变更.

BTL兼容性: max_info_frames与max_master在BACnet侧可写

4.08  2021.6.22

BTL 10.2.3.6 要求路由在发送拒绝包之前先尝试查找下游路由。

修复bug。此bug当VBUS被使能时可能被触发。

4.07  2021.6.13

修正4.05版引入的bug,此bug可能造成特定情况下无法进入配置界面。(请注意在http://IP/app/upgrade有一个后备升级固件的入口)

一些UI的小修正.

4.05  2021.6.7

Modbus对象名移除最顶层的”modbus_master”.

对象名分隔符”|” 改为可配置.

值对象允许与输出对象重叠.

一些界面修正

4.04  2021.6.1

大量的Modbus网关功能的更新:多状态对象,值对象,二进制文本,编组读取,批量换算,导入导出CSV点定义

转换BASgatewayLX的CSV格式配置文件

4.03  2021.4.23

Modbus网关

离线配置

3.23  2021.3.19

包捕捉到BACnet的映射模块的Bug被修复。此Bug可能导致包捕捉功能在BACnet侧启用时,后台程序崩溃重启。

修复Bug当扩展帧支持未被启用时,在ms/tp端口发出的请求中携带的max_apdu_length_accepted参数未正确设置。

WebUI的”系统设定“页面加入更多的信息,如全部/剩余内存,启动计时。

3.21  2021.2.22

MSTP从站代理的bug修复:当从站绑定失效时守护程序崩溃与重启问题。当在其它端口发送I-Am应答时的Hop count不正确问题.

APDU应答包及网络层拒绝包同样必须遵守目的网络的忙碌状态。

3.20  2021.1.26

取消创建网络端口的限制,现在只有总网络端口数量的限制。这将大大方便用户修改与切换端口的配置。

如果root密码还未被设置,在“系统设定”页内设置root密码的按钮将以红色字体提醒用户。

3.19  2021.1.20

在3.18上可能偶然地触发一个芯片的bug造成MS/TP无法启动

3.18  2021.1.18

MS/TP配置增加”扩展帧支持”选项.

网络层拒绝包应采用单播以遵守BTL测试标准。

外部设备的存活时间应加上30秒以遵守BTL测试标准。

发往广播地址的确认服务应在应用层被丢弃以遵守BTL测试标准

BBMD应丢弃相同UDP端口且单播的本地IP子网的转发包.

“同子网多个广播管理设备”逻辑在查找BDT表时遇到不同UDP端口判断出错的Bug被修正。

3.17  2021.1.13

WebUI 增加网络层设定页面,该页面可以显示路由表。

修复一个从设备代理的bug:当收到一个发往从设备的单播who-is时,服务所携带的设备id范围参数也必须被遵守,就如同广播的who-is。

3.15  2020.10.26

MS/TP加入了从JCI的FEC2611与IOM3731地址冲突中学习到的检测算法.

3.14  2020.10.23

MS/TP加入了地址冲突检测功能,冲突的地址会用红色显示在“最近活动的其它站点”中。因为MS/TP在冲突场景下的表现非常多样复杂,该检测并不准确,只能用于参考。

修复了由3.0版本引入MS/TP底层状态机潜在bug.

3.13  2020.10.5

基于测试及用户反馈,许多(可能是大部分)设备没有遵从BACnet标准中MS/TP接收有限状态机在遇到错误时的处理方式。我们私有的 “超时中止“特性在这种情况下并不能按预期工作,甚至造成性能下降。因此”超时中止”特性被移除。

MS/TP的运行信息页面增加更多的统计信息。

从3.08版本引入的WebUI在BIP的外部设备模式下的Bug被修复。

3.11  2020.7.14

修正mstp对错误包的占用时间计算错误。

修正3.08引入的mstp从站代理的bug

一些小的UI改进。

3.10  2020.7.1

因为从2.x升级到3.x,很多配置项改变。所以在3.00~3.09版中,升级固件时,升级脚本将安装新的配置文件。在这个版本中,升级功能增加一个“保留配置”的选项。如果配置文件错误,在打开WebUI时将有一个警告。

3.09  2020.6.30

修正3.08版本引入的读取mstp运行信息时的错误。

一些小的UI改进。

3.08  2020.6.28

修正: 单跳方式的广播分布在标准中只是可选功能。从版本3.00起,如果跨网广播支持被选中,BACRouter将强制其它广播管理设备(BBMD)使用单跳方式。这是不正确的行为,在此版本中得到修正。

广播分布表(BDT)的编辑方式得到改进。当提交时,广播分布表(BDT)中的表项将得到检查,排除可能错误配置。这种检查在收到BDT BVLL包时,同样执行。

如果同子网多个广播管理设备(BBMD)未被选中,当收到未记录在本地广播分布表(BDT)中的广播管理设备(BBMD)发来的转发包时,将记录并丢弃该转发包。此功能在绝大多数场合中将有助于识别BBMD的配置问题。上一版本的“报告多个广播管理设备”功能被本功能覆盖,所以取消。

下载配置的文件名设置为IP_版本号.json,例如:192.168.100.1_3.08.json

上传配置将先读入到WebUI中进行编辑,方可保存。如此可避免潜在的版本兼容问题。

3.06  2020.5.22

因为Ethernet端口现在已很少用到,缺省将其关闭,同时如果BIP与Ethernet同时被启用,将弹出警告,提醒用户注意可能的路由回环。

将默认的捕捉缓冲区大小增加为4M。

3.05  2020.5.15

包捕捉功能映射到BACnet。 每个链路层端口都有独立的”Capture buf_size”与”Capture command” 多状态值. “Capture buf_size”可以在”64K”到”16M”之间设置。 “Capture command”可以在”Stop&Clean”, “Start”, “Stop”之间设置。

此功能应国外用户需求开发,使用场景如下:路由默认开启包捕捉。当上位机发现某设备的通讯异常时,可以停止路由对应端口的包捕捉(使用“Stop”保留捕捉数据,而不是”Stop&Clean”),然后通过邮件提醒管理员,从WebUI读取当时的包捕捉数据进行分析。

3.04  2020.4.28

增强安全性,由WebUI可修改root密码。

3.03  2020.4.23

BACRouter以Initialize-Routing-Table包查询路由表的方式, 确认其它的路由器仍然存活。但是附录135-2012AL移除了路由器对Initialize-Routing-Table的强制支持。本版本增加通过Reject-Message-To-Network包确认路由存活的方式。

BIP BVLL对转发 (Forwarded) 的NPDU的包头要比其它的包头长6个字节,老版本在较验转发的NPDU包长时有个隐蒧的Bug,本版本已得以修正。

3.02  2020.3.26

UI的小修正

3.01  2020.3.17

系统设定增加下载配置与上传配置功能

3.00  2020.3.10

增加包捕捉功能:

所有端口均支持包捕捉。

因为Wireshark不支持MSTP扩展帧解析,扩展帧在下载时转为常规数据帧(幸运的是,Wireshark并不抱怨长度溢出)。

MSTP支持包间隔格式,可以在Wireshark中以5us精度显示包前的空闲时间,是时序与性能分析的利器。

支持持续化包捕捉,提供API接口,方便自动化流量记录。

MSTP移除自动地址探测功能。因为设备无法保证同一时间上线,无法完全避免地址冲突。如现场调试时,需要知道可用MAC地址及最大扫描地址,可以采用下述方式:开启侦听模式,从运行信息得到“当前最大扫描地址”及“最近活动站点”。

MSTP增加最大扫描地址实时分析功能,在运行信息中显示,如与配置值不符,将提示“不匹配”

MSTP增加侦听模式,可以在不干涉总线运行的前提下,检测总线运行情况。

MSTP的Web配置界面,提供简单模式与扩展模式选择。

MSTP的所有超时改为浮点数,方便精确定义。

MSTP从设备代理前版只支持广播的Who-Is查询,现版本增加支持单播的Who-Is查询

MSTP从设备代理前版应答I-Am采用网内广播,现版本采用单播

MSTP从设备代理功能修正前版中分析Who-Is查询的路由来源的漏洞。

BBMD增加选项在发现内网有多个BBMD时错误报警。

对2.17版提供功能的修正,增加“接受不匹配的目标地址”选项,如果启用,仅打印报警信息,如果未启用,打印错误信息并丢弃。

很多的WebUI小改进。

2.18  2019.4.16

提高了IP与以太网口的性能

在Unconfirmed COV通知中的进程0保留给未订阅的COV通知,当没找到进程0时不再报告错误。

2.17  2019.4.2

在前版中,当从单播地址接收到Original-broadcast BVLL包或从广播地址接收到Original-unicast BVLL包,认为是个错误而丢包。有客户报告江森的CCT用单播地址发送Original-broadcast BVLL包,所以此版中仅打印报警信息。

2.16  2019.2.25

从版本2.0.8起,  仅支持转发私有的网络层包,其它不认识的网络层包将被拒绝。此行为不利于支持标准的升级。本版本中所有不认识的网络层包均支持转发。

2.15  2017.10.19

重定向 URL “/” 到 “/?” 以支持Edge 浏览器 (否则将不停地要求认证)

修正MSTP标准状态机中的Bug: 令牌重复可能导致转发令牌给自身.

MSTP标准状态机中,当设备处于单主机模式下,其开始查询一个主站后,发送max_info_frames * Npoll 个帧。修改为更合理的行为:当结束查询所有主站后发送max_info_frames * Npoll 个帧.

2.14  2017.10.13

修复从2.0引入的Bug,当MSTP发送Expecting reply请求到255地址时,不必等待回应。

2.13  2017.9.19

当MSTP自动地址分配与波特率强制功能同时启用时,隐藏的bug可能(极其罕见的条件下)引发。

2.12  2017.7.10

优化路由表项保护功能: 来自下一跳的删除将跳过保护.

支持采用6.5.3中查找网络路由地址的方法1与4的设备。

2.11  2017.6.16

此次更新有助于在大型BACnet互联网络中快速建立路由表。

当BACRouter启动时, 广播一个无目标网络号的Who_Is_Router_To_Network以学习其它路由的信息.

当收到无目标网络号的Who_Is_Router_To_Network/Router_Busy_To_Network/Router_Available_To_Network, BACRouter回复的网络号最多可达1120个(对比前版本的112个).

2.10  2017.6.13

错误修下: ReadRange在读取property_list不应返回以下三个属性: object_identifier; object_name; object_type.

启动时延时1秒发送Network_Number_Is,因为如果路由器做为BIP的外部设备,此时注册流程尚未完成。

2.09  2017.6.10

保护路由表项从最后活动计起60秒,避免路由回环时的广播风暴。

2.08  2017.6.7

错误修正: 正确转发私有的网络层包.

转发Reject-Message-To-Network(原因4,包太长)时,使用单播地址.

修改后台的最大apdu重试为10,与WebUI一致。

2.07  2017.6.5

遵从BACnet Router与BBMD的设备描述.

如果没有收到Who_Is_Router_To_Network或Initializing_Routing_Table包的回应, 删除无效的路由. 此特性有助于从错误的网络配置中恢复.

在网络回环时(当配置错误时), 避免发送过多的I_Am_Router_To_Network.

减少复杂网络下的内存消耗.

2.06  2017.6.1

避免BBMD广播风暴.

广播发送转发的Reject-Message-To-Network包(只针对拒绝理由1,2,4).

抛弃含有错误路由信息的Reject-Message-To-Network包.

检查NPDU包头的源网络.(对Initializing-Routing-Table包特别处理)

2.05  2017.5.23

修正全局广播的initializing-routing-table请求未执行的错误.

修正WebUI BIP的模式选择未提交即生效的错误.

限制运行信息页面的路表项个数,以避免在大型互联网络中的请求失败。

2.04  2017.5.11

修正WebUI较验BDT时的错误.

当收到reinitialize-device服务请求时保存配置重启。

2.03  2017.5.7

BIP BBMD NAT模式支持端口号修改。

BIP BBMD NAT模式不监听本地广播地址及发送本地广播

BIP BBMD 外部设备模式不监听本地广播地址

2.02  2017.5.5

当收到Who-Is-Router-To查询时,假定源设备没有该路由(从路由表中删除)

当Initializing-Routing-Table修改了网络号,重新发送I-Am-Routr-To-Network以报告新网络号

修正v2.0引入的错误:保存BVLL Write-Broadcast-Distribution-Table修改的BDT表时出错

2.01  2017.5.3

增加后备的升级入口 http://ip/app/upgrade

更直觉的日志信息

改进网络层拒绝行为

修正发送I-Am-Routr-To-Network时的溢出(当报告的网络数量超过1476/2时)

以动态时间间隔发送I-Am-Routr-To-Network.

2.0  2017.4.19

提供选项启用路由内的设备对象。.

允许从BACnet端修改配置

支持What_is_Network_Number and Network_Number_Is 网络包

提供MSTP max_info_frames的by occupy time选项

实现新的MSTP自动/强制波特率机制.

MSTP包最大延迟保证(10 seconds).

WebUI界面更智能.

1.22  2016.10.26

将路由表项的数目由1024增加到65534(即没有限制).

1.21  2016.10.18

从设备代理: 如果对方是快速设备加快ReadProperty(Multiple)的发送速率.

BVLL回应NAK当收到BBMD相关的请求,但BBMD未使能. (附录135-2012ax-5)

BVLL回应NAK当收到Distribute-Broadcast-To-Network请求,但源设备未注册为外部设备. (附录135-2010ad-10)

1.20  2016.10.8

BIP提供选项接受发往255.255.255.255的广播报文

BIP外设设备模式的注册时间间隔的最小值从30秒减少到15秒。

1.19  2016.9.23

webui如果IP/掩码/网关/DHCP没有改动,采用快速重启

MSTP加入快速设备超时中止功能

MSTP快速设备最小超时改为0ms(实际是收发切换后1.5bits加上50us)

MSTP快速设备令牌传递超时最小值设为20ms

MSTP运行信息显示最近10秒活动的设备

1.18  2016.9.13

BIP BBMD 支持NAT,增加两个参数”接受BDT表写入“与”接受外部设备注册”

在“配置”页面显示以太网地址

1.17  2016.9.8

应某些OEM用户需求,登录认证的域名可以由用户定制。

1.16  2016.9.7

修正从站代理应答Who-is但查询到的设备并没有在该入口代理。

修正写远程BBMD的BDT表错误

许多的界面改进

1.15  2016.9.1

加入了从设备代理功能.

MSTP加入了无切换延时桢计数及带填充字节桢计数

一些界面改进。

修正无切换延时桢紧跟带填充字节桢时的解码错误

1.14  2016.8.24

这是一次大升级,比较多的修订:

MSTP增加令牌超时、回应超时配置项。

MSTP增加快速设备功能,允许指定设备使用小至1毫秒的令牌超时与回应超时。

MSTP增加运行诊断信息含地址冲突,发送冲突、令牌冲突、令牌丢失,令牌转发失败、无应答、包错误。

MSTP增强对不遵守40bit发送切换要求的设备的兼容性

MSTP修正发送扩展桢的编码错误

MSTP修正特定条件下应答测试桢的CRC错误

1.13  2016.8.16

底层api改动,对本软件无影响

1.12  2016.8.12

加入系列号

1.11  2016.8.10

固件文件名带版本号及校验字串。

左边树型菜单处显示版本号。

重启及升级固件后,自动刷新。

修复一些界面bug

CCN网关版本升级记录

2.9 2017.5.30

兼容一台不规范的30RQ固件。

移除2.2引入的特性,以与CCN控制网络并存。

2.8 2016.10.26

修正转换unicode字符串到utf8编码时的缓冲溢出缺陷。

2.7 2016.10.3

WebUI采用basic认证方式

修正WebUI的表格索引溢出错误(感谢Nitin的报告)

2.6 2016.9.13

WebUI 显示Ethernet地址

2.5 2016.9.13

处理字符串时忽略0-9/a-z/A-Z以外的字符

2.4 2016.8.26

可选择0.001,0.01,0.1,10,100,1000倍的映射倍数

BACnet部分合并了BACnet路由器的修订。

2.3 2016.8.16

底层API变动,为后续产品作准备

修复2.1版引入的Bug,通讯失败后持续错误

2.2 2016/8/12

某些原厂技术人员为竞争项目故意用CCN服务工具软件将一些重要的数据点强制锁定,无法写入。在初始化时检测并解锁。

2.1 2016/8/10

固件文件名带版本号及校验字串。

左边树型菜单处显示版本号。

重启及升级固件后,自动刷新。

修复一些界面bug

发表在 CCN