moonbacnet

    Typed BACnet/IP object property services and bounded device application core

    bacnet
    building-automation
    property-services
    Download zip
    Version
    0.1.0
    License
    Apache-2.0
    Last updated
    9 hours ago
    Downloads
    4

    #MoonBACnet

    MoonBit 原生的 BACnet 对象与属性服务核心:将建筑设备状态、命令优先级、批量属性查询和变化通知交给可复用的类型化 API。协议核心不依赖 Python、JavaScript 或外部 BACnet 运行时,能在 wasm、wasm-gc、js、native 后端使用。

    模块:erzhuzi259/moonbacnet@0.1.0;GitHub · Mooncakes。许可证为 Apache-2.0。

    #用途与生态定位

    • 楼宇控制与操作员覆盖:温度、照明或设备设定值同时受到自动策略与人工命令影响。用16级 priority array 保留各方意图,Null 释放当前槽,恢复较低优先级或 relinquish default,避免把“释放”误写成零。
    • 能源与设备管理网关:通过 Who-Is/I-Am 发现设备,枚举 Object_List,以 ReadPropertyMultiple 读取多个测点、单位和名称;单个未知对象/属性返回独立错误,不丢弃其余成功数据。
    • 运行状态监测:按累计变化阈值观察模拟量,以及二进制故障状态/Status_Flags;接收初始快照、变化通知和有限期订阅,减少无变化轮询。这里使用 COV,不包含完整的事件告警确认服务。

    上述三类场景均有可运行的本地例子。现有 MoonBit IEC104、Modbus 包和本地 MoonAMQP1 分别处理其他标准的点命令或消息传输;BACnet 增补对象标识、属性数组、命令优先级、发现和 COV 的不同语义。本轮 bacnet/BACnet/bvlc/npdu/bacpypes 检索未发现同核心成熟 Mooncakes 包;这是有范围的查重结果,不是对整个生态绝无相关实现的保证。

    #安装与运行

    已验证 moonc v0.10.16、Moon0.1.20261016;CI 固定 compiler/core 0.10.16+b1a0e846e。原生目标需要 C 编译器,JS 示例需要 Node.js。本库可只用 MoonBit 构建;Python3.11 和 BACpypes3 仅用于独立互操作测试。

    取得源码目录后运行:

    moon check --target all --deny-warn moon build --target all --deny-warn moon test --target all --deny-warn moon run examples/hvac --target native --deny-warn moon run examples/energy --target native --deny-warn moon run examples/monitoring --target js --deny-warn moon run examples/scale --target native --deny-warn

    Windows 已提供当前官方编译器的路径适配入口。若工具链无法处理扩展路径 \\?\,把命令中的 moon 换成 & .\tools\windows\moon.ps1,例如:

    & .\tools\windows\moon.ps1 test --target all --deny-warn & .\tools\windows\moon.ps1 run examples/hvac --target native --deny-warn

    脚本只在本进程为官方 moonc/moonfmt/mooninfo 子进程规范化参数路径,不改变全局环境。依赖 moonbitlang/async@0.22.5 只被原生 CLI 的文件、stdio 及回环 UDP 宿主导入,类型、服务和设备核心均不依赖它。

    #最小使用样例

    在已有 MoonBit 工程中安装:

    moon add erzhuzi259/moonbacnet@0.1.0

    使用方 moon.pkg 配置导入:

    import { "erzhuzi259/moonbacnet" @bac, }
    pkgtype(kind: "executable")

    以下过程对应可运行的 examples/hvac:

    fn main raise {
    let device = @bac.Device::new(42, "room-controller", 999U)
    let id = @bac.ObjectId::new(2, 1) // analog-value
    device.add_point(id, "setpoint", Analog, Real(19.0F), commandable=true)
    let server = @bac.Server::new(device)
    let client = @bac.Client::new()
    let body = @bac.encode_write_property({
    reference: { object: id, property: 85U, index: None },
    value: [Application(Real(23.0F))], priority: Some(8),
    })
    let tx = client.start("device", 15, body, 0UL)
    let reply = server.datagram(tx.bytes, "client", 0UL).unwrap()
    assert_true(client.receive("device", @bac.decode_datagram(reply), 0UL)
    is Some(Completed(SimpleAck(_, 15))))
    assert_eq(device.active_priority(id), Some(8))
    }

    宿主负责把 tx.bytes 经可靠的对端映射交给 UDP 等传输,把响应和单调递增的秒数送回核心;例子在内存中传递完整 BACnet/IP datagram。peer 是对端身份键,不提供认证。真实集成必须提供访问控制、可信网络和稳定地址映射,核心不会把 priority 当作权限系统。

    #API 与功能边界

    层次已实现首版边界
    应用值null/bool/uint32/int32/REAL/DOUBLE/octet/string/bits/enum/date/time/object-id,精确位模式,嵌套context字符串仅encoding0 UTF-8;日期使用1900年偏移和协议通配字节,不提供日历运算
    标签扩展tag、8/16/32位长度、opening/closing、严格截断/计数/深度检查未知application tag明确拒绝;编码规范化整数宽度,不保留原输入的非最短形式
    网络报文IPv4 BVLC 原始单播/广播、forwarded、distribute、result、foreign-register;NPDU路由字段只编解码相关包;没有BBMD表、外来设备注册管理、路由器、MS/TP、IPv6或BACnet/SC
    APDU未分段confirmed/unconfirmed、simple/complex ACK、error/reject/abort分段及SegmentACK明确拒绝;设备宿主最多1476字节APDU,按请求方最大长度返回有界abort
    服务Who-Is/I-Am、ReadProperty、WriteProperty、ReadPropertyMultiple、SubscribeCOV、unconfirmed COV notificationRPM支持all(8)展开,required/optional宏未实现;不支持WritePropertyMultiple等其他服务
    属性库对象ID/名称唯一、Object_List/Property_List、数组索引、标量及只读自定义数组、类型与预算检查索引0为数组长度,None为整体;远端数组及compound写入未实现;对象集合不经网络创建
    测点analog/binary/multi-state input/output/value,类型域、Status_Flags、Out_Of_Service为明确子集对象模型,未实现标准对象的所有必备属性/行为;不是完整可认证设备profile
    控制16级在途命令槽、默认priority16、Null释放、relinquish default、域检查priority6保留,网络写入拒绝;未实现输出最小开/关时间及优先级6内部计时;默认值由宿主API设置
    COV初始快照、累计模拟量阈值、二进制/状态变化、续期/取消/过期、原子poll只接受unconfirmed通知订阅;0 lifetime代表不定期,取消为两个可选字段均缺失;无通知持久重发
    事务按peer关联invoke/service/reference、轮转ID、超时/定次重试/取消无网络socket;重复写入的业务幂等性仍由宿主决定;RPM客户端校验结构与service,不实现完整请求结果集合证明

    通用 Tag/服务codec能表示设备profile之外的数据。Device.add_point 检查标准测点kind与值域;输出对象必须启用命令优先级,输入对象不得设为commandable。网络权限由注册时的 writable 及 commandable 属性决定。Device.update 是可信宿主入口,维护四位状态标志与 Out_Of_Service 一致性;不实现输入点脱机模式下的网络写入扩展。

    ReadPropertyACK、RPM及COV的constructed value可为空,以表示真实空数组;这与必需字段缺失不同。存储与返回值均建立快照,调用者修改数组不会改写已保存的属性或COV基线。

    #时钟、重传与宿主责任

    Client.start/receive/poll、Server.handle/datagram/notifications 和 CovManager 使用宿主提供的单调秒数;时间倒退和截止溢出明确报错。Client.poll 返回 Retry 或 TimedOut,重复调用不会重复发同一到期事件;宿主负责发送返回的字节。客户端ID轮转且不覆盖同peer在途ID。

    Server缓存同peer/invoke的已完成响应30秒,相同请求逐字节重传复用响应,避免再次写入或续期。相同invoke但请求内容变化被视为新事务;缓存数量/字节均受限,会淘汰最旧条目。因此缓存不是持久exactly-once保证,宿主应避免在缓存期内复用相同invoke发送不同业务含义的相同报文。广播confirmed请求被忽略;设备宿主不接受forwarded或routed数据,也不提供BBMD信任判断。

    notifications(now) 返回通知后推进基线,由宿主决定实际发送和接收策略。无时钟线程、自动重连或后台队列;对象只支持串行驱动,不保证并发修改安全。

    #预算与复杂度

    默认 Limits:65535逻辑字节、8192 tag节点、32层嵌套、256对象、每对象256属性(包括计算属性)、128订阅、128在途事务/响应缓存条目。可调整,嵌套上限128。存储属性聚合wire字节、待发事务字节、单批通知和RPM结果各自有预算;缓存预算为2×max_bytes+256,额外peer地址限256 UTF-8字节。这些不是整个进程RSS的精确上限。

    设N为wire字节、V为tag节点、D为嵌套深度,标签编解码O(N+V),递归栈O(D);Writer直接写同一输出缓冲,不反复拼接父容器。文本body和规范化快照另有线性副本。属性查找O(O+P+X),O为对象数、P为对象属性数、X为返回的属性数据规模;每次命令选择扫描固定16槽。RPM按实际展开属性数处理,不按数值ID跨度循环。COV轮询最坏O(S·(O+P)+B),S为订阅数、B为产生的编码字节。事务匹配/取消与缓存查找O(T),invoke分配最多O(256·T),批量数组删除/缓存淘汰最坏O(T²),T默认限128;当前有界规模下优先保留直接可验证的数据结构,尚未做速度基准证明需要更复杂索引。

    examples/scale 验证64测点、32订阅、4096次写入及4096次读取、2048次变化通知;写入/回复流量143360字节。它是有界正确性负载,不是速度或内存基准。

    #独立验证与 CLI

    moon build --target native --deny-warn python -m pip install --target _local/oracle -r scripts/requirements-interop.txt python scripts/interop.py moon run cmd/main --target native -- tags INPUT.bin NEW_OUTPUT.bin moon run cmd/main --target native -- rp INPUT.bin NEW_OUTPUT.bin

    CLI支持 tags、apdu、bvlc、npdu、rp、rp-ack、wp、rpm、rpm-ack、cov-sub、cov、whois、iam;输入最多65535字节,输出路径必须尚不存在。peer 输入逐行十六进制BACnet/IP datagram,输出对应回复或-;保持一个示例设备,固定逻辑时刻0。它用于互操作验证,不是有真实时钟或UDP接入的设备服务。

    固定BACpypes3 0.0.110,已验证23组类型和13组服务/报文向量双向编码,以及11次真实Python实现对持续MoonBit宿主的请求:发现、优先级写入/读取/释放、RPM、错误、订阅/取消。以上向量与持续宿主对照使用stdio;十一月另增加 scripts/udp_interop.py,通过真实回环UDP验证发现、优先级、错误、畸形报文恢复和COV通知/取消。未连接外部厂商设备,不构成BTL认证、完整标准符合性或厂商兼容认证。

    本地严格检查、构建、四后端各54个测试、格式和接口快照已通过。Linux/Windows CI 覆盖上述流程、五个示例、独立stdio/UDP oracle、打包与历史/ZIP内容检查;工程检查不等于正式赛事验收。申报书及审查/AI/汇总材料可放在项目本地文件夹,经忽略及历史/包检查排除,不进入 Git 或发行包。来源与AI辅助范围见 THIRD_PARTY.md,主要公共API快照见 pkg.generated.mbti。

    #十一月新增功能

    设备发现与冲突目录(DiscoveryDirectory);命令仲裁可解释快照(Device::command_snapshot);Native UDP 接入与独立网络验证(cmd/udp + scripts/udp_interop.py)。详见功能、用途和边界,运行 moon run examples/november --target native --deny-warn。功能包含于0.1.0,安装方式见上文。

    BacnetError

    pub suberror BacnetError {
    Invalid(String, Int)
    Unsupported(String)
    Limit(String)
    State(String)
    Property(UInt, UInt)
    } derive(
    Debug
    )

    Apdu

    pub(all) enum Apdu {
    Confirmed(Request)
    Unconfirmed(Int, Bytes)
    SimpleAck(Int, Int)
    ComplexAck(Int, Int, Bytes)
    ErrorPdu(Int, Int, Bytes)
    Reject(Int, Int)
    Abort(Int, Bool, Int)
    } derive(
    Debug
    )

    Apdu::to_repr

    Bvlc

    pub(all) enum Bvlc {
    ResultCode(Int)
    RegisterForeign(Int)
    OriginalUnicast(Bytes)
    OriginalBroadcast(Bytes)
    Forwarded(Bytes, Bytes)
    DistributeBroadcast(Bytes)
    } derive(
    Debug
    )

    Bvlc::to_repr

    Client

    pub struct Client {
    // private fields
    }

    Client::cancel

    fn Client::cancel(self : Client, peer : String, invoke : Int) -> Bool raise BacnetError

    Client::new

    fn Client::new(timeout? : UInt64, retries? : Int, limits? : Limits) -> Client raise BacnetError

    Client::pending_count

    fn Client::pending_count(self : Client) -> Int

    Client::poll

    fn Client::poll(self : Client, now : UInt64) -> Array[ClientEvent] raise BacnetError

    Client::receive

    fn Client::receive(self : Client, peer : String, response : Apdu, now : UInt64) -> Completion? raise BacnetError

    Client::start

    fn Client::start(self : Client, peer : String, service : Int, body : Bytes, now : UInt64, max_apdu? : Int) -> Transmission raise BacnetError

    ClientEvent

    pub(all) enum ClientEvent {
    Retry(Transmission)
    TimedOut(String, Int)
    } derive(
    Debug
    )

    CommandDomain

    pub(all) enum CommandDomain {
    Analog
    Binary
    MultiState(UInt)
    } derive(
    Debug
    )

    CommandSnapshot

    pub(all) struct CommandSnapshot {
    object : ObjectId
    effective : Value
    relinquish_default : Value
    active_priority : Int?
    occupied : Array[(Int, Value)]
    }

    Completion

    pub(all) enum Completion {
    Completed(Apdu)
    ServiceError(UInt, UInt)
    Rejected(Int)
    Aborted(Bool, Int)
    } derive(
    Debug
    )

    CovEnvelope

    pub(all) struct CovEnvelope {
    peer : String
    notification : CovNotification
    } derive(
    Debug
    )

    CovManager

    pub struct CovManager {
    // private fields
    }

    CovManager::count

    fn CovManager::count(self : CovManager, now : UInt64) -> Int raise BacnetError

    CovManager::new

    fn CovManager::new(device : Device) -> CovManager

    CovManager::poll

    fn CovManager::poll(self : CovManager, now : UInt64) -> Array[CovEnvelope] raise BacnetError

    CovManager::subscribe

    fn CovManager::subscribe(self : CovManager, peer : String, request : SubscribeCov, now : UInt64) -> Unit raise BacnetError

    CovNotification

    pub(all) struct CovNotification {
    process : UInt
    device : ObjectId
    object : ObjectId
    remaining : UInt
    values : Array[CovProperty]
    } derive(
    Debug
    )

    CovProperty

    pub(all) struct CovProperty {
    property : UInt
    index : UInt?
    value : Array[Tag]
    priority : Int?
    } derive(
    Debug
    )

    Date

    pub(all) struct Date {
    year : Int
    month : Int
    day : Int
    weekday : Int
    } derive(Eq,
    Debug
    )

    Date::equal

    fn Date::equal(Date, Date) -> Bool

    Date::not_equal

    fn Date::not_equal(x : Date, y : Date) -> Bool

    Date::to_repr

    Device

    pub struct Device {
    // private fields
    }

    Device::active_priority

    fn Device::active_priority(self : Device, id : ObjectId) -> Int? raise BacnetError

    Device::add_object

    fn Device::add_object(self : Device, id : ObjectId, name : String) -> Unit raise BacnetError

    Device::add_point

    fn Device::add_point(self : Device, id : ObjectId, name : String, domain : CommandDomain, initial : Value, commandable? : Bool, units? : UInt) -> Unit raise BacnetError

    Device::all_property_ids

    fn Device::all_property_ids(self : Device, id : ObjectId) -> Array[UInt] raise BacnetError

    Device::announcement

    fn Device::announcement(self : Device) -> IAm

    Device::command_snapshot

    fn Device::command_snapshot(self : Device, id : ObjectId) -> CommandSnapshot raise BacnetError

    Detached explanation of all active command intents, including overridden slots. Command priority represents arbitration, not access authorization.

    Device::define_property

    fn Device::define_property(self : Device, id : ObjectId, property : UInt, value : Array[Tag], writable? : Bool, array? : Bool) -> Unit raise BacnetError

    Device::identifier

    fn Device::identifier(self : Device) -> ObjectId

    Device::new

    fn Device::new(instance : Int, name : String, vendor : UInt, limits? : Limits) -> Device raise BacnetError

    Device::property_ids

    fn Device::property_ids(self : Device, id : ObjectId) -> Array[UInt] raise BacnetError

    Device::read

    fn Device::read(self : Device, reference : PropertyRef) -> Array[Tag] raise BacnetError

    Device::resource_limits

    fn Device::resource_limits(self : Device) -> Limits

    Device::set_relinquish_default

    fn Device::set_relinquish_default(self : Device, id : ObjectId, value : Value) -> Unit raise BacnetError

    Device::update

    fn Device::update(self : Device, id : ObjectId, property : UInt, value : Value) -> Unit raise BacnetError

    Device::write

    fn Device::write(self : Device, request : WriteProperty) -> Unit raise BacnetError

    DiscoveredDevice

    pub(all) struct DiscoveredDevice {
    peer : String
    announcement : IAm
    first_seen : UInt64
    last_seen : UInt64
    }

    DiscoveryDirectory

    pub struct DiscoveryDirectory {
    // private fields
    }

    DiscoveryDirectory::devices

    DiscoveryDirectory::expire

    fn DiscoveryDirectory::expire(self : DiscoveryDirectory, now : UInt64, max_age : UInt64) -> Array[DiscoveredDevice] raise BacnetError

    DiscoveryDirectory::forget

    fn DiscoveryDirectory::forget(self : DiscoveryDirectory, device : ObjectId) -> Bool

    DiscoveryDirectory::new

    fn DiscoveryDirectory::new(maximum? : Int) -> DiscoveryDirectory raise BacnetError

    DiscoveryDirectory::observe

    fn DiscoveryDirectory::observe(self : DiscoveryDirectory, peer : String, announcement : IAm, now : UInt64) -> Bool raise BacnetError

    Observe an already-decoded I-Am. Duplicate device IDs at different peers are conflicts, never silently reassigned. Caller chooses peer/address identity.

    IAm

    pub(all) struct IAm {
    device : ObjectId
    max_apdu : UInt
    segmentation : UInt
    vendor : UInt
    } derive(
    Debug
    )

    IAm::to_repr

    Limits

    pub(all) struct Limits {
    max_bytes : Int
    max_nodes : Int
    max_depth : Int
    max_objects : Int
    max_properties : Int
    max_subscriptions : Int
    max_pending : Int
    } derive(Eq,
    Debug
    )

    Limits::default

    fn Limits::default() -> Limits

    Limits::equal

    fn Limits::equal(Limits, Limits) -> Bool

    Limits::not_equal

    fn Limits::not_equal(x : Limits, y : Limits) -> Bool

    Limits::to_repr

    Limits::validate

    fn Limits::validate(self : Limits) -> Unit raise BacnetError

    Npdu

    pub(all) struct Npdu {
    destination : Route?
    source : Route?
    hop_count : Int
    expecting_reply : Bool
    priority : Int
    payload : Bytes
    } derive(
    Debug
    )

    Npdu::for_local

    fn Npdu::for_local(payload : Bytes, expecting_reply? : Bool) -> Npdu

    Npdu::to_repr

    ObjectId

    pub struct ObjectId {
    kind : Int
    instance : Int
    } derive(Compare, Eq, Hash,
    Debug
    )

    ObjectId::compare

    fn ObjectId::compare(ObjectId, ObjectId) -> Int

    ObjectId::equal

    fn ObjectId::equal(ObjectId, ObjectId) -> Bool

    ObjectId::from_number

    fn ObjectId::from_number(value : UInt) -> ObjectId

    ObjectId::hash

    fn ObjectId::hash(self : ObjectId) -> Int

    ObjectId::hash_combine

    fn ObjectId::hash_combine(ObjectId, Hasher) -> Unit

    ObjectId::new

    fn ObjectId::new(kind : Int, instance : Int) -> ObjectId raise BacnetError

    ObjectId::not_equal

    fn ObjectId::not_equal(x : ObjectId, y : ObjectId) -> Bool

    ObjectId::number

    fn ObjectId::number(self : ObjectId) -> UInt

    ObjectId::op_ge

    fn ObjectId::op_ge(x : ObjectId, y : ObjectId) -> Bool

    ObjectId::op_gt

    fn ObjectId::op_gt(x : ObjectId, y : ObjectId) -> Bool

    ObjectId::op_le

    fn ObjectId::op_le(x : ObjectId, y : ObjectId) -> Bool

    ObjectId::op_lt

    fn ObjectId::op_lt(x : ObjectId, y : ObjectId) -> Bool

    ObjectId::to_repr

    PriorityArray

    pub struct PriorityArray {
    // private fields
    }

    PriorityArray::active_priority

    fn PriorityArray::active_priority(self : PriorityArray) -> Int?

    PriorityArray::default_value

    fn PriorityArray::default_value(self : PriorityArray) -> Value

    PriorityArray::effective

    fn PriorityArray::effective(self : PriorityArray) -> Value

    PriorityArray::new

    fn PriorityArray::new(domain : CommandDomain, fallback : Value) -> PriorityArray raise BacnetError

    PriorityArray::set_default

    fn PriorityArray::set_default(self : PriorityArray, value : Value) -> Unit raise BacnetError

    PriorityArray::values

    fn PriorityArray::values(self : PriorityArray) -> Array[Tag]

    PriorityArray::write

    fn PriorityArray::write(self : PriorityArray, priority : Int, value : Value) -> Unit raise BacnetError

    PropertyRef

    pub(all) struct PropertyRef {
    object : ObjectId
    property : UInt
    index : UInt?
    } derive(Eq,
    Debug
    )

    PropertyRef::equal

    fn PropertyRef::equal(PropertyRef, PropertyRef) -> Bool

    PropertyRef::not_equal

    fn PropertyRef::not_equal(x : PropertyRef, y : PropertyRef) -> Bool

    PropertyValue

    pub(all) struct PropertyValue {
    reference : PropertyRef
    value : Array[Tag]
    } derive(
    Debug
    )

    ReadAccess

    pub(all) struct ReadAccess {
    object : ObjectId
    properties : Array[(UInt, UInt?)]
    } derive(
    Debug
    )

    ReadAccessResult

    pub(all) struct ReadAccessResult {
    object : ObjectId
    results : Array[ReadResult]
    } derive(
    Debug
    )

    ReadResult

    pub(all) enum ReadResult {
    PropertyData(PropertyRef, Array[Tag])
    PropertyFailure(PropertyRef, UInt, UInt)
    } derive(
    Debug
    )

    Request

    pub(all) struct Request {
    invoke : Int
    service : Int
    max_apdu : Int
    max_segments : Int
    segmented_response_accepted : Bool
    body : Bytes
    } derive(
    Debug
    )

    Request::new

    fn Request::new(invoke : Int, service : Int, body : Bytes, max_apdu? : Int) -> Request raise BacnetError

    Request::to_repr

    Route

    pub(all) struct Route {
    network : Int
    address : Bytes
    } derive(
    Debug
    )

    Route::to_repr

    Server

    pub struct Server {
    // private fields
    }

    Server::datagram

    fn Server::datagram(self : Server, bytes : Bytes, peer : String, now : UInt64) -> Bytes? raise BacnetError

    Server::device

    fn Server::device(self : Server) -> Device

    Server::handle

    fn Server::handle(self : Server, apdu : Apdu, peer : String, now : UInt64) -> Apdu? raise BacnetError

    Server::new

    fn Server::new(device : Device) -> Server

    Server::notifications

    fn Server::notifications(self : Server, now : UInt64) -> Array[CovEnvelope] raise BacnetError

    SubscribeCov

    pub(all) struct SubscribeCov {
    process : UInt
    object : ObjectId
    confirmed : Bool?
    lifetime : UInt?
    } derive(
    Debug
    )

    Tag

    pub(all) enum Tag {
    Application(Value)
    Context(Int, Bytes)
    Constructed(Int, Array[Tag])
    } derive(
    Debug
    )

    Tag::to_repr

    Time

    pub(all) struct Time {
    hour : Int
    minute : Int
    second : Int
    hundredth : Int
    } derive(Eq,
    Debug
    )

    Time::equal

    fn Time::equal(Time, Time) -> Bool

    Time::not_equal

    fn Time::not_equal(x : Time, y : Time) -> Bool

    Time::to_repr

    Transmission

    pub(all) struct Transmission {
    peer : String
    invoke : Int
    bytes : Bytes
    } derive(
    Debug
    )

    Value

    pub(all) enum Value {
    Null
    Boolean(Bool)
    Unsigned(UInt)
    Signed(Int)
    Real(Float)
    DoubleValue(Double)
    Octets(Bytes)
    Text(String)
    Bits(Int, Bytes)
    Enumerated(UInt)
    DateValue(Date)
    TimeValue(Time)
    Object(ObjectId)
    } derive(
    Debug
    )

    Value::to_repr

    WhoIs

    pub(all) struct WhoIs {
    low : Int?
    high : Int?
    } derive(
    Debug
    )

    WhoIs::to_repr

    WriteProperty

    pub(all) struct WriteProperty {
    reference : PropertyRef
    value : Array[Tag]
    priority : Int?
    } derive(
    Debug
    )

    decode_apdu

    fn decode_apdu(data : Bytes, limits? : Limits) -> Apdu raise BacnetError

    decode_bvlc

    fn decode_bvlc(data : Bytes, limits? : Limits) -> Bvlc raise BacnetError

    decode_cov

    fn decode_cov(bytes : Bytes, limits? : Limits) -> CovNotification raise BacnetError

    decode_datagram

    fn decode_datagram(bytes : Bytes, limits? : Limits) -> Apdu raise BacnetError

    decode_error

    fn decode_error(bytes : Bytes) -> (UInt, UInt) raise BacnetError

    decode_i_am

    fn decode_i_am(bytes : Bytes, limits? : Limits) -> IAm raise BacnetError

    decode_multiple_ack

    fn decode_multiple_ack(bytes : Bytes, limits? : Limits) -> Array[ReadAccessResult] raise BacnetError

    decode_npdu

    fn decode_npdu(data : Bytes, limits? : Limits) -> Npdu raise BacnetError

    decode_property_ack

    fn decode_property_ack(bytes : Bytes, limits? : Limits) -> PropertyValue raise BacnetError

    decode_read_multiple

    fn decode_read_multiple(bytes : Bytes, limits? : Limits) -> Array[ReadAccess] raise BacnetError

    decode_read_property

    fn decode_read_property(bytes : Bytes, limits? : Limits) -> PropertyRef raise BacnetError

    decode_subscribe_cov

    fn decode_subscribe_cov(bytes : Bytes, limits? : Limits) -> SubscribeCov raise BacnetError

    decode_tags

    fn decode_tags(data : Bytes, limits? : Limits) -> Array[Tag] raise BacnetError

    decode_who_is

    fn decode_who_is(bytes : Bytes, limits? : Limits) -> WhoIs raise BacnetError

    decode_write_property

    fn decode_write_property(bytes : Bytes, limits? : Limits) -> WriteProperty raise BacnetError

    encode_apdu

    fn encode_apdu(apdu : Apdu, limits? : Limits) -> Bytes raise BacnetError

    encode_bvlc

    fn encode_bvlc(frame : Bvlc, limits? : Limits) -> Bytes raise BacnetError

    encode_cov

    fn encode_cov(notification : CovNotification, limits? : Limits) -> Bytes raise BacnetError

    encode_datagram

    fn encode_datagram(apdu : Apdu, broadcast? : Bool, limits? : Limits) -> Bytes raise BacnetError

    encode_error

    fn encode_error(class : UInt, code : UInt) -> Bytes raise BacnetError

    encode_i_am

    fn encode_i_am(value : IAm, limits? : Limits) -> Bytes raise BacnetError

    encode_multiple_ack

    fn encode_multiple_ack(access : Array[ReadAccessResult], limits? : Limits) -> Bytes raise BacnetError

    encode_npdu

    fn encode_npdu(npdu : Npdu, limits? : Limits) -> Bytes raise BacnetError

    encode_property_ack

    fn encode_property_ack(ack : PropertyValue, limits? : Limits) -> Bytes raise BacnetError

    encode_read_multiple

    fn encode_read_multiple(access : Array[ReadAccess], limits? : Limits) -> Bytes raise BacnetError

    encode_read_property

    fn encode_read_property(reference : PropertyRef, limits? : Limits) -> Bytes raise BacnetError

    encode_subscribe_cov

    fn encode_subscribe_cov(s : SubscribeCov, limits? : Limits) -> Bytes raise BacnetError

    encode_tags

    fn encode_tags(tags : Array[Tag], limits? : Limits) -> Bytes raise BacnetError

    encode_who_is

    fn encode_who_is(query : WhoIs, limits? : Limits) -> Bytes raise BacnetError

    encode_write_property

    fn encode_write_property(request : WriteProperty, limits? : Limits) -> Bytes raise BacnetError

    hex_decode

    fn hex_decode(text : String, limits? : Limits) -> Bytes raise BacnetError

    hex_encode

    fn hex_encode(bytes : Bytes) -> String

    max_apdu_size

    fn max_apdu_size(code : Int) -> Int raise BacnetError

    Powered by MoonBit

    Site sourceReport issueModulesSkillsBuild queueStatistics

    © 2026 mooncakes.io