A portable Modbus RTU, ASCII, and TCP protocol stack with device simulation and gateway primitives for MoonBit.
moon update
moon check --target all --deny-warn
moon test --target all --deny-warn
moon run cmd/main///|
let request = @moonbit-modbus.read_holding(1, 0, 4)
///|
let rtu_bytes = @moonbit-modbus.encode_rtu(request)
///|
let parsed = @moonbit-modbus.decode_rtu(rtu_bytes)///|
let parser = @moonbit-modbus.IncrementalParser::new(@moonbit-modbus.rtu_mode())
///|
let frames = parser.feed(rtu_bytes)# 展示请求编码、虚拟设备处理和响应格式化
moon run --target native cmd/main
# 运行 1000 次 CRC、RTU、TCP 和设备读工作负载
moon run --target native cmd/benchmoon fmt --check
moon info
moon check --target all --deny-warn
moon test --target all --deny-warnfn AccessPolicy::allows(self : AccessPolicy, role : AccessRole, operation : AccessOperation, frame : Frame) -> Boolfn AccessPolicy::decision(self : AccessPolicy, role : AccessRole, operation : AccessOperation, frame : Frame) -> Result[Unit, ModbusError]pub(all) struct AccessRule {
name : String
role : AccessRole
operation : AccessOperation
unit_start : Byte
unit_end : Byte
functions : Array[Byte]
enabled : Bool
}fn AccessRule::matches(self : AccessRule, role : AccessRole, operation : AccessOperation, frame : Frame) -> Boolfn AccessRule::new(name : String, role : AccessRole, operation : AccessOperation, unit_start : Byte, unit_end : Byte, functions : Array[Byte]) -> Result[AccessRule, ModbusError]fn AddressAllocator::allocate(self : AddressAllocator, length : Int) -> Result[AddressRange, ModbusError]fn AddressAllocator::release(self : AddressAllocator, range : AddressRange) -> Result[Unit, ModbusError]pub(all) struct AddressRange {
start : UInt16
length : Int
}fn AddressRange::slice(self : AddressRange, offset : Int, length : Int) -> Result[AddressRange, ModbusError]fn AddressRange::split(self : AddressRange, segment_length : Int) -> Result[Array[AddressRange], ModbusError]pub(all) struct AlarmEngine {
instances : Array[AlarmInstance]
events : Array[AlarmEvent]
max_events : Int
next_sequence : Int
}fn AlarmEngine::acknowledge(self : AlarmEngine, rule_id : String, operator : String, timestamp : Int) -> Result[AlarmEvent, ModbusError]fn AlarmEngine::evaluate(self : AlarmEngine, point_id : String, value : Int, timestamp : Int) -> Result[Array[AlarmEvent], ModbusError]fn AlarmEngine::shelve(self : AlarmEngine, rule_id : String, timestamp : Int) -> Result[AlarmEvent, ModbusError]fn AlarmEngine::unshelve(self : AlarmEngine, rule_id : String, timestamp : Int) -> Result[AlarmEvent, ModbusError]pub(all) struct AlarmEvent {
sequence : Int
rule_id : String
point_id : String
state : AlarmState
value : Int
timestamp : Int
severity : AlarmSeverity
message : String
} derive(Debug)pub(all) struct AlarmInstance {
rule : AlarmRule
state : AlarmState
pending_since : Int?
clearing_since : Int?
last_value : Int
last_timestamp : Int
transitions : Int
acknowledger : String?
}fn AlarmInstance::evaluate(self : AlarmInstance, value : Int, timestamp : Int, sequence : Int) -> AlarmTransitionpub(all) struct AlarmMonitor {
threshold : Threshold
state : ThresholdState
transitions : Int
last_value : Int?
}pub(all) struct AlarmRule {
id : String
point_id : String
condition : AlarmCondition
low : Int
high : Int
severity : AlarmSeverity
activation_delay : Int
clear_delay : Int
hysteresis : Int
enabled : Bool
}fn AlarmRule::new(id : String, point_id : String, condition : AlarmCondition, low : Int, high : Int, severity : AlarmSeverity, activation_delay? : Int, clear_delay? : Int, hysteresis? : Int) -> Result[AlarmRule, ModbusError]pub(all) struct AnalyticsReport {
direction : TrendDirection
average : Int
minimum : Int
maximum : Int
slope : Int
anomalies : Int
p95 : Int
}pub(all) struct AnalyticsRule {
id : String
lower : Int?
upper : Int?
spike_delta : Int
flatline_delta : Int
flatline_count : Int
}fn AnalyticsRule::new(id : String, lower? : Int, upper? : Int, spike_delta? : Int, flatline_delta? : Int, flatline_count? : Int) -> Result[AnalyticsRule, ModbusError]fn AnalyticsSample::new(timestamp : Int, value : Int, quality? : ReadingQuality) -> Result[AnalyticsSample, ModbusError]pub(all) struct AnalyticsWindow {
id : String
capacity : Int
samples : Array[AnalyticsSample]
dropped : Int
}fn AnalyticsWindow::append(self : AnalyticsWindow, sample : AnalyticsSample) -> Result[Unit, ModbusError]fn AnalyticsWindow::direction(self : AnalyticsWindow, threshold : Int) -> Result[TrendDirection, ModbusError]pub(all) struct AuditEntry {
sequence : Int
direction : String
mode : Mode
transaction_id : UInt16
summary : FrameSummary
outcome : String
}pub(all) struct BenchmarkResult {
name : String
iterations : Int
successful : Int
failed : Int
bytes : Int
}fn BitVector::pack_range(self : BitVector, start : Int, quantity : Int) -> Result[Array[Byte], ModbusError]fn BitVector::unpack_into(self : BitVector, start : Int, quantity : Int, bytes : Array[Byte]) -> Result[Unit, ModbusError]pub(all) struct BridgeDecision {
rule_id : String?
action : BridgeAction
frame : Frame?
reason : String
matched : Bool
}fn BridgeDecision::matched(rule : ServiceBridgeRule, action : BridgeAction, frame : Frame?, reason : String) -> BridgeDecisionpub(all) struct CalibrationCurve {
samples : Array[CalibrationSample]
max_samples : Int
clamp : Bool
}fn CalibrationCurve::add(self : CalibrationCurve, sample : CalibrationSample) -> Result[Unit, ModbusError]fn CalibrationCurve::convert_many(self : CalibrationCurve, values : Array[Int]) -> Result[Array[Int], ModbusError]fn CalibrationCurve::new(max_samples? : Int, clamp? : Bool) -> Result[CalibrationCurve, ModbusError]fn CalibrationCurve::sample(self : CalibrationCurve, index : Int) -> Result[CalibrationSample, ModbusError]pub(all) struct CalibrationSample {
raw : Int
engineering : Int
}pub(all) struct CapacityLedger {
limits : Array[CapacityLimit]
reservations : Array[CapacityReservation]
max_reservations : Int
sequence : Int
}fn CapacityLedger::add_limit(self : CapacityLedger, limit : CapacityLimit) -> Result[Unit, ModbusError]fn CapacityLedger::release(self : CapacityLedger, reservation_id : String) -> Result[Unit, ModbusError]fn CapacityLedger::reserve(self : CapacityLedger, resource : CapacityResource, amount : Int, now : Int) -> Result[CapacityReservation, ModbusError]pub(all) struct CapacityLimit {
resource : CapacityResource
name : String
soft_limit : Int
hard_limit : Int
used : Int
}fn CapacityLimit::new(resource : CapacityResource, name : String, soft_limit : Int, hard_limit : Int) -> Result[CapacityLimit, ModbusError]pub(all) struct CapacityReservation {
id : String
resource : CapacityResource
amount : Int
created_at : Int
released : Bool
}fn CapacityReservation::new(id : String, resource : CapacityResource, amount : Int, created_at : Int) -> Result[CapacityReservation, ModbusError]pub(all) struct CaptureFilter {
mode : Mode?
unit_id : Byte?
function : Byte?
direction : CaptureDirection?
status : CaptureStatus?
start_time : Int?
end_time : Int?
}fn CaptureFilter::between(self : CaptureFilter, start : Int, end : Int) -> Result[CaptureFilter, ModbusError]fn CaptureFilter::with_direction(self : CaptureFilter, direction : CaptureDirection) -> CaptureFilterpub(all) struct CaptureRecord {
id : Int
timestamp : Int
mode : Mode
transaction_id : UInt16
direction : CaptureDirection
bytes : Array[Byte]
frame : Frame?
status : CaptureStatus
note : String
}fn CaptureRecord::from_frame(id : Int, timestamp : Int, mode : Mode, transaction_id : UInt16, direction : CaptureDirection, frame : Frame, note? : String) -> Result[CaptureRecord, ModbusError]fn CaptureRecord::new(id : Int, timestamp : Int, mode : Mode, transaction_id : UInt16, direction : CaptureDirection, bytes : Array[Byte], note? : String) -> Result[CaptureRecord, ModbusError]pub(all) struct CaptureRing {
records : Array[CaptureRecord]
max_records : Int
next_id : Int
lost : Int
}fn CaptureRing::push(self : CaptureRing, timestamp : Int, mode : Mode, transaction_id : UInt16, direction : CaptureDirection, bytes : Array[Byte], note? : String) -> Result[CaptureRecord, ModbusError]fn CaptureRing::push_frame(self : CaptureRing, timestamp : Int, mode : Mode, transaction_id : UInt16, direction : CaptureDirection, frame : Frame, note? : String) -> Result[CaptureRecord, ModbusError]pub(all) struct CircuitGuard {
name : String
failure_threshold : Int
recovery_after : Int
probe_limit : Int
state : CircuitGuardState
consecutive_failures : Int
opened_at : Int?
probes : Int
}fn CircuitGuard::new(name : String, failure_threshold : Int, recovery_after : Int, probe_limit? : Int) -> Result[CircuitGuard, ModbusError]pub struct Client {
mode : Mode
config : ClientConfig
next_transaction : UInt16
pending : Array[PendingExchange]
}fn Client::accept(self : Client, request : ClientRequest, bytes : Array[Byte]) -> Result[Frame, ModbusError]fn Client::accept_frame(self : Client, request : ClientRequest, transaction_id : UInt16, response : Frame) -> Result[Frame, ModbusError]pub(all) struct ClientConfig {
timeout_ticks : Int
retries : Int
max_pending : Int
strict_unit : Bool
}fn CoilBank::read(self : CoilBank, address : UInt16, quantity : Int) -> Result[Array[Bool], ModbusError]fn CoilBank::write(self : CoilBank, address : UInt16, values : Array[Bool]) -> Result[Unit, ModbusError]pub(all) struct CommandArgument {
key : String
value : String
}pub(all) struct CommandAuditEntry {
sequence : Int
command_id : String
principal : String
device_id : String
operation : String
state : DeviceCommandState
timestamp : Int
detail : String
}fn CommandAuditEntry::new(sequence : Int, command : DeviceCommand, state : DeviceCommandState, timestamp : Int, detail? : String) -> Result[CommandAuditEntry, ModbusError]pub(all) struct CommandCenter {
queue : Array[DeviceCommand]
completed : Array[CommandExecution]
audit : Array[CommandAuditEntry]
max_queue : Int
max_audit : Int
sequence : Int
}fn CommandCenter::cancel(self : CommandCenter, command_id : String, timestamp : Int) -> Result[Unit, ModbusError]fn CommandCenter::finish(self : CommandCenter, command : DeviceCommand, execution : CommandExecution) -> Result[Unit, ModbusError]fn CommandCenter::recent(self : CommandCenter, limit : Int) -> Result[Array[CommandAuditEntry], ModbusError]fn CommandCenter::submit(self : CommandCenter, command : DeviceCommand, timestamp : Int) -> Result[Unit, ModbusError]pub(all) struct CommandExecution {
command_id : String
state : DeviceCommandState
started_at : Int
finished_at : Int
response : Frame?
error : ModbusError?
message : String
}fn CommandExecution::new(command_id : String, state : DeviceCommandState, started_at : Int, finished_at : Int, response? : Frame, error? : ModbusError, message? : String) -> Result[CommandExecution, ModbusError]fn ConfigEntry::new(key : String, value : ConfigValue, source? : String, revision? : Int) -> Result[ConfigEntry, ModbusError]fn ConfigSchema::validate_values(self : ConfigSchema, values : Array[ConfigEntry]) -> Result[Unit, ModbusError]pub(all) struct ConfigSpec {
key : String
kind : ConfigKind
required : Bool
default_value : ConfigValue?
min_integer : Int?
max_integer : Int?
min_length : Int
max_length : Int
secret : Bool
description : String
}fn ConfigSpec::new(key : String, kind : ConfigKind, required? : Bool, default_value? : ConfigValue, min_integer? : Int, max_integer? : Int, min_length? : Int, max_length? : Int, secret? : Bool, description? : String) -> Result[ConfigSpec, ModbusError]pub(all) struct ConformanceResult {
name : String
passed : Bool
detail : String
}pub(all) struct ConformanceVector {
name : String
mode : Mode
bytes : Array[Byte]
expected_function : Byte?
expected_error : ModbusError?
}fn ConformanceVector::invalid(name : String, mode : Mode, bytes : Array[Byte], expected_error : ModbusError) -> ConformanceVectorfn ConformanceVector::valid(name : String, mode : Mode, bytes : Array[Byte], expected_function : Byte) -> ConformanceVectorpub(all) struct Counter {
name : String
value : Int
}pub(all) struct Crc16State {
value : UInt16
}pub struct Device {
unit_id : Byte
memory : DeviceMemory
file_store : FileRecordStore
server_id : Array[Byte]
event_count : UInt16
busy : Bool
exception_count : Int
}fn Device::new(unit_id : Byte, coil_capacity? : Int, register_capacity? : Int) -> Result[Device, ModbusError]pub(all) struct DeviceCommand {
id : String
device_id : String
unit_id : Byte
kind : DeviceCommandKind
function : Byte
address : UInt16
quantity : Int
arguments : Array[CommandArgument]
principal : String
reason : String
timeout : Int
state : DeviceCommandState
created_at : Int
}fn DeviceCommand::add_argument(self : DeviceCommand, argument : CommandArgument) -> Result[Unit, ModbusError]fn DeviceCommand::new(id : String, device_id : String, unit_id : Byte, kind : DeviceCommandKind, function : Byte, address : UInt16, quantity : Int, principal : String, reason : String, created_at : Int, timeout? : Int) -> Result[DeviceCommand, ModbusError]fn DeviceCommand::set_state(self : DeviceCommand, state : DeviceCommandState) -> Result[Unit, ModbusError]pub(all) struct DeviceHealth {
unit_id : Byte
event_count : UInt16
exception_count : Int
busy : Bool
}pub(all) struct DeviceIdObject {
object_id : Byte
value : String
}pub(all) struct DeviceIdentification {
category : DeviceIdCategory
conformity : Byte
more_follows : Bool
next_object_id : Byte
objects : Array[DeviceIdObject]
}pub struct DeviceIdentityCatalog {
category : DeviceIdCategory
objects : Array[DeviceIdObject]
conformity : Byte
}fn DeviceIdentityCatalog::add(self : DeviceIdentityCatalog, object : DeviceIdObject) -> Result[Unit, ModbusError]fn DeviceIdentityCatalog::response(self : DeviceIdentityCatalog, request : Frame) -> Result[Frame, ModbusError]pub(all) struct DeviceInventory {
devices : Array[InventoryDevice]
max_devices : Int
revision : Int
}fn DeviceInventory::add(self : DeviceInventory, device : InventoryDevice) -> Result[Unit, ModbusError]fn DeviceInventory::mark_stale(self : DeviceInventory, now : Int, timeout : Int) -> Result[Int, ModbusError]fn DeviceInventory::remove(self : DeviceInventory, id : String) -> Result[InventoryDevice, ModbusError]pub(all) struct DeviceMemory {
coils : CoilBank
discrete_inputs : CoilBank
input_registers : RegisterBank
holding_registers : RegisterBank
}fn DeviceMemory::load_discrete(self : DeviceMemory, address : UInt16, values : Array[Bool]) -> Result[Unit, ModbusError]fn DeviceMemory::load_holding(self : DeviceMemory, address : UInt16, values : Array[UInt16]) -> Result[Unit, ModbusError]fn DeviceMemory::load_input(self : DeviceMemory, address : UInt16, values : Array[UInt16]) -> Result[Unit, ModbusError]fn DeviceMemory::new(coil_capacity? : Int, register_capacity? : Int) -> Result[DeviceMemory, ModbusError]pub(all) struct DeviceProfile {
name : String
model : String
unit_id : Byte
revision : String
points : Array[ProfilePoint]
max_points : Int
}fn DeviceProfile::add_point(self : DeviceProfile, point : ProfilePoint) -> Result[Unit, ModbusError]fn DeviceProfile::new(name : String, model : String, unit_id : Byte, revision? : String, max_points? : Int) -> Result[DeviceProfile, ModbusError]fn DeviceProfile::remove_point(self : DeviceProfile, id : String) -> Result[ProfilePoint, ModbusError]pub(all) struct DeviceReliability {
device_id : String
window : ReliabilityWindow
circuit : CircuitGuard
last_seen : Int?
total_requests : Int
total_successes : Int
}fn DeviceReliability::allow_request(self : DeviceReliability, now : Int) -> Result[Bool, ModbusError]fn DeviceReliability::new(device_id : String, window_width : Int, failure_threshold : Int, recovery_after : Int) -> Result[DeviceReliability, ModbusError]fn DeviceReliability::record(self : DeviceReliability, sample : ReliabilitySample) -> Result[Unit, ModbusError]pub(all) struct DeviceService {
id : String
device_id : String
kind : DeviceServiceKind
endpoint : String
state : DeviceServiceState
started_at : Int?
stopped_at : Int?
restart_count : Int
tags : Array[String]
}fn DeviceService::new(id : String, device_id : String, kind : DeviceServiceKind, endpoint : String) -> Result[DeviceService, ModbusError]pub(all) struct DeviceServiceRegistry {
services : Array[DeviceService]
snapshots : Array[DeviceSnapshot]
max_services : Int
max_snapshots : Int
}fn DeviceServiceRegistry::for_device(self : DeviceServiceRegistry, device_id : String) -> Array[DeviceService]fn DeviceServiceRegistry::new(max_services? : Int, max_snapshots? : Int) -> Result[DeviceServiceRegistry, ModbusError]fn DeviceServiceRegistry::put_snapshot(self : DeviceServiceRegistry, snapshot : DeviceSnapshot) -> Result[Unit, ModbusError]fn DeviceServiceRegistry::register(self : DeviceServiceRegistry, service : DeviceService) -> Result[Unit, ModbusError]fn DeviceServiceRegistry::snapshot(self : DeviceServiceRegistry, device_id : String) -> DeviceSnapshot?pub(all) struct DeviceSnapshot {
device_id : String
captured_at : Int
values : Array[SnapshotValue]
sequence : Int
complete : Bool
}fn DeviceSnapshot::new(device_id : String, captured_at : Int, sequence : Int) -> Result[DeviceSnapshot, ModbusError]pub(all) struct DiagnosticIssue {
code : String
category : DiagnosticCategory
severity : DiagnosticSeverity
message : String
context : String
suggestion : String
}fn DiagnosticIssue::new(code : String, category : DiagnosticCategory, severity : DiagnosticSeverity, message : String, context? : String, suggestion? : String) -> Result[DiagnosticIssue, ModbusError]pub(all) struct DiagnosticReport {
name : String
issues : Array[DiagnosticIssue]
max_issues : Int
inspected : Int
}fn DiagnosticReport::add(self : DiagnosticReport, issue : DiagnosticIssue) -> Result[Unit, ModbusError]fn DiagnosticReport::inspect_one(self : DiagnosticReport, frame : Frame) -> Result[Unit, ModbusError]fn DiagnosticReport::inspect_wire(self : DiagnosticReport, mode : Mode, bytes : Array[Byte]) -> Unitfn DiagnosticReport::new(name? : String, max_issues? : Int) -> Result[DiagnosticReport, ModbusError]fn EncodedAdu::new(mode : Mode, transaction_id : UInt16, frame : Frame) -> Result[EncodedAdu, ModbusError]pub(all) struct EndpointHealth {
unit_id : Byte
ready : Bool
event_count : UInt16
exceptions : Int
requests : Int
responses : Int
errors : Int
}pub(all) struct EndpointRuntime {
config : EndpointConfig
state : EndpointState
opened_at : Int
last_error : ModbusError?
reconnects : Int
frames_in : Int
frames_out : Int
}pub(all) struct EventSubscription {
id : String
source : String?
kind : ServiceEventKind?
enabled : Bool
}fn EventSubscription::new(id : String, source? : String, kind? : ServiceEventKind) -> Result[EventSubscription, ModbusError]fn ExchangeEnvelope::new(source : String, destination : String, adu : EncodedAdu) -> ExchangeEnvelopepub(all) struct FileRecordReference {
reference_type : Byte
file_number : UInt16
record_number : UInt16
record_length : UInt16
}fn FileRecordReference::new(file_number : UInt16, record_number : UInt16, record_length : UInt16, reference_type? : Byte) -> Result[FileRecordReference, ModbusError]fn FileRecordStore::get(self : FileRecordStore, reference : FileRecordReference) -> Result[Array[UInt16], ModbusError]fn FileRecordStore::put(self : FileRecordStore, record : FileRecordWrite) -> Result[Unit, ModbusError]fn FileRecordWrite::new(reference : FileRecordReference, values : Array[UInt16]) -> Result[FileRecordWrite, ModbusError]pub(all) struct FirmwareConstraint {
vendor : String
model : String
minimum : String
recommended : String
}fn FirmwareConstraint::new(vendor : String, model : String, minimum : String, recommended : String) -> Result[FirmwareConstraint, ModbusError]pub(all) struct FleetHealthRollup {
contributions : Array[HealthContribution]
score : Int
state : FleetHealthState
timestamp : Int
}fn FleetHealthRollup::add(self : FleetHealthRollup, contribution : HealthContribution) -> Result[Unit, ModbusError]fn FleetHealthRollup::contribution(self : FleetHealthRollup, source : String) -> HealthContribution?fn FleetHealthRollup::remove(self : FleetHealthRollup, source : String) -> Result[HealthContribution, ModbusError]pub(all) struct FrameContract {
id : String
function : Byte
request_min : Int
request_max : Int
response_min : Int
response_max : Int
require_echo : Bool
}fn FrameContract::new(id : String, function : Byte, request_min : Int, request_max : Int, response_min : Int, response_max : Int, require_echo? : Bool) -> Result[FrameContract, ModbusError]fn FrameContractCatalog::add(self : FrameContractCatalog, contract : FrameContract) -> Result[Unit, ModbusError]fn FrameContractCatalog::check(self : FrameContractCatalog, request : Frame, response : Frame) -> Result[ContractResult, ModbusError]fn FrameContractCatalog::check_all(self : FrameContractCatalog, pairs : Array[(Frame, Frame)]) -> Array[ContractResult]pub(all) struct FrameFingerprint {
unit_id : Byte
function : Byte
data_length : Int
checksum : Int
}fn FrameSequence::validate(self : FrameSequence, allow_broadcast : Bool) -> Result[Unit, ModbusError]pub struct FrameStream {
mode : Mode
parser : IncrementalParser
queue : ByteQueue
chunks : Int
frames : Int
}fn FrameStream::new(mode : Mode, role? : ParserRole, max_buffer? : Int, max_frame? : Int) -> Result[FrameStream, ModbusError]pub(all) struct FrameSummary {
unit_id : Byte
function : Byte
data_length : Int
exception : Bool
}fn FrameTextLog::record_wire(self : FrameTextLog, direction : String, mode : Mode, transaction_id : UInt16, frame : Frame) -> Unitpub(all) enum FunctionCode {
ReadCoils
ReadDiscreteInputs
ReadHoldingRegisters
ReadInputRegisters
WriteSingleCoil
WriteSingleRegister
ReadExceptionStatus
Diagnostics
GetCommEventCounter
GetCommEventLog
ReportServerId
WriteMultipleCoils
WriteMultipleRegisters
ReportServerIdExtended
ReadFileRecord
WriteFileRecord
MaskWriteRegister
ReadWriteMultipleRegisters
ReadFifoQueue
EncapsulatedInterface
Unknown(Byte)
} derive(Eq, Debug)pub(all) struct FunctionDescriptor {
function : Byte
name : String
request_min : Int
request_max : Int
response_variable : Bool
writable : Bool
description : String
}fn GatewayPolicyTable::add(self : GatewayPolicyTable, policy : ServiceGatewayPolicy) -> Result[Unit, ModbusError]fn GatewayPolicyTable::evaluate(self : GatewayPolicyTable, source : String, destination : String, frame : Frame) -> Result[BridgeDecision, ModbusError]fn GatewayPolicyTable::find(self : GatewayPolicyTable, source : String, destination : String) -> ServiceGatewayPolicy?pub(all) struct GatewayRule {
source_unit : Byte
target_unit : Byte
function : Byte
source_start : UInt16
target_start : UInt16
span : Int
enabled : Bool
}fn GatewayRule::new(source_unit : Byte, target_unit : Byte, function : Byte, source_start : UInt16, target_start : UInt16, span : Int) -> Result[GatewayRule, ModbusError]pub(all) struct GuardEvent {
sequence : Int
timestamp : Int
peer : String
decision : GuardDecision
reason : GuardReason
unit_id : Byte
function : Byte
frame_bytes : Int
fingerprint : FrameFingerprint
}fn GuardEvent::new(sequence : Int, timestamp : Int, peer : String, decision : GuardDecision, reason : GuardReason, frame : Frame) -> Result[GuardEvent, ModbusError]pub(all) struct HealthContribution {
source : String
score : Int
weight : Int
detail : String
}fn HealthContribution::new(source : String, score : Int, weight : Int, detail : String) -> Result[HealthContribution, ModbusError]fn Historian::aggregate(self : Historian, point_id : String, start : Int, end : Int, aggregation : Aggregation) -> Result[Int, ModbusError]fn Historian::query(self : Historian, point_id : String, start : Int, end : Int) -> Result[Array[TagSample], ModbusError]pub(all) struct HistoryBucket {
start : Int
end : Int
count : Int
minimum : Int
maximum : Int
sum : Int
}pub struct IncrementalParser {
mode : Mode
role : ParserRole
buffer : Array[Byte]
max_frame : Int
frames_seen : Int
errors_seen : Int
}fn IncrementalParser::feed(self : IncrementalParser, input : Array[Byte]) -> Result[Array[Frame], ModbusError]fn IncrementalParser::feed_byte(self : IncrementalParser, byte : Byte) -> Result[Array[Frame], ModbusError]fn IncrementalParser::set_max_frame(self : IncrementalParser, max_frame : Int) -> Result[Unit, ModbusError]pub(all) struct InventoryDevice {
id : String
label : String
vendor : String
model : String
serial : String
firmware : String
unit_id : Byte
transport : String
state : InventoryState
last_seen : Int?
tags : Array[String]
}fn InventoryDevice::new(id : String, label : String, vendor : String, model : String, serial : String, firmware : String, unit_id : Byte, transport : String) -> Result[InventoryDevice, ModbusError]fn InventoryDevice::stale(self : InventoryDevice, now : Int, timeout : Int) -> Result[Bool, ModbusError]pub(all) struct JobScheduler {
jobs : Array[ScheduledJob]
max_jobs : Int
now : Int
dispatched : Int
completed : Int
failed : Int
cancelled : Int
}fn JobScheduler::fail(self : JobScheduler, id : String, error : ModbusError, now : Int) -> Result[Bool, ModbusError]fn JobScheduler::reschedule(self : JobScheduler, id : String, due_at : Int) -> Result[Unit, ModbusError]pub(all) struct LeaseManager {
leases : Array[ResourceLease]
max_leases : Int
default_duration : Int
sequence : Int
}fn LeaseManager::acquire(self : LeaseManager, resource : String, owner : String, now : Int, priority? : Int) -> Result[ResourceLease, ModbusError]fn LeaseManager::active_resources(self : LeaseManager, now : Int) -> Result[Array[String], ModbusError]fn LeaseManager::new(max_leases? : Int, default_duration? : Int) -> Result[LeaseManager, ModbusError]fn LeaseManager::owned_by(self : LeaseManager, owner : String, now : Int) -> Result[Array[String], ModbusError]fn LeaseManager::release(self : LeaseManager, lease_id : String, owner : String) -> Result[Unit, ModbusError]fn LeaseManager::renew(self : LeaseManager, lease_id : String, owner : String, now : Int, duration? : Int) -> Result[Unit, ModbusError]pub(all) struct MaintenancePlanner {
plans : Array[ServicePlan]
records : Array[ServiceRecord]
work_orders : Array[MaintenanceWorkOrder]
max_records : Int
max_orders : Int
}fn MaintenancePlanner::add_plan(self : MaintenancePlanner, plan : ServicePlan) -> Result[Unit, ModbusError]fn MaintenancePlanner::add_record(self : MaintenancePlanner, record : ServiceRecord) -> Result[Unit, ModbusError]fn MaintenancePlanner::add_work_order(self : MaintenancePlanner, order : MaintenanceWorkOrder) -> Result[Unit, ModbusError]fn MaintenancePlanner::complete_order(self : MaintenancePlanner, order_id : String, timestamp : Int, note? : String) -> Result[Unit, ModbusError]fn MaintenancePlanner::due_plans(self : MaintenancePlanner, now : Int) -> Result[Array[String], ModbusError]fn MaintenancePlanner::generate_due(self : MaintenancePlanner, now : Int) -> Result[Int, ModbusError]fn MaintenancePlanner::history_count(self : MaintenancePlanner, asset_id : String, start : Int, end : Int) -> Result[Int, ModbusError]fn MaintenancePlanner::new(max_records? : Int, max_orders? : Int) -> Result[MaintenancePlanner, ModbusError]fn MaintenancePlanner::open_orders(self : MaintenancePlanner, now : Int, overdue_only? : Bool) -> Result[Array[String], ModbusError]fn MaintenancePlanner::summary(self : MaintenancePlanner, now : Int) -> Result[MaintenanceSummary, ModbusError]pub(all) struct MaintenanceSummary {
plans : Int
due : Int
overdue : Int
completed : Int
open : Int
records : Int
}pub(all) struct MaintenanceWorkOrder {
id : String
asset_id : String
plan_id : String?
title : String
priority : MaintenancePriority
state : WorkOrderState
created_at : Int
due_at : Int
assigned_to : String?
started_at : Int?
finished_at : Int?
note : String
}fn MaintenanceWorkOrder::assign(self : MaintenanceWorkOrder, technician : String) -> Result[Unit, ModbusError]fn MaintenanceWorkOrder::block(self : MaintenanceWorkOrder, note : String) -> Result[Unit, ModbusError]fn MaintenanceWorkOrder::cancel(self : MaintenanceWorkOrder, reason : String) -> Result[Unit, ModbusError]fn MaintenanceWorkOrder::complete(self : MaintenanceWorkOrder, timestamp : Int, note? : String) -> Result[Unit, ModbusError]fn MaintenanceWorkOrder::new(id : String, asset_id : String, title : String, priority : MaintenancePriority, created_at : Int, due_at : Int, plan_id? : String) -> Result[MaintenanceWorkOrder, ModbusError]fn MaintenanceWorkOrder::start(self : MaintenanceWorkOrder, timestamp : Int) -> Result[Unit, ModbusError]fn MetricRegistry::new(max_series? : Int, max_samples? : Int) -> Result[MetricRegistry, ModbusError]fn MetricRegistry::range(self : MetricRegistry, start : Int, end : Int) -> Result[Array[ServiceMetric], ModbusError]fn MetricRegistry::record(self : MetricRegistry, metric : ServiceMetric) -> Result[Unit, ModbusError]fn MetricRegistry::register(self : MetricRegistry, name : String, kind : MetricKind) -> Result[Unit, ModbusError]pub(all) struct MetricSeries {
name : String
kind : MetricKind
capacity : Int
samples : Array[ServiceMetric]
dropped : Int
}fn MetricSeries::between(self : MetricSeries, start : Int, end : Int) -> Result[Array[ServiceMetric], ModbusError]fn MetricSeries::new(name : String, kind : MetricKind, capacity? : Int) -> Result[MetricSeries, ModbusError]pub(all) struct MigrationPlan {
id : String
from_version : Int
to_version : Int
steps : Array[MigrationStep]
max_steps : Int
state : MigrationState
}fn MigrationPlan::apply(self : MigrationPlan, snapshot : MigrationSnapshot) -> Result[MigrationSnapshot, ModbusError]fn MigrationPlan::new(id : String, from_version : Int, to_version : Int, max_steps? : Int) -> Result[MigrationPlan, ModbusError]fn MigrationPlan::rollback(self : MigrationPlan, snapshot : MigrationSnapshot) -> Result[MigrationSnapshot, ModbusError]pub(all) struct MigrationSnapshot {
version : Int
entries : Array[(String, String)]
timestamp : Int
}fn MigrationSnapshot::put(self : MigrationSnapshot, key : String, value : String) -> Result[Unit, ModbusError]pub(all) struct MigrationStep {
id : String
operation : MigrationOperation
key : String
value : String
rollback_value : String?
order : Int
applied : Bool
}fn MigrationStep::new(id : String, operation : MigrationOperation, key : String, value : String, order : Int, rollback_value? : String) -> Result[MigrationStep, ModbusError]pub(all) struct ModbusScenario {
id : String
description : String
steps : Array[ScenarioStep]
max_steps : Int
revision : Int
}fn ModbusScenario::new(id : String, description : String, max_steps? : Int) -> Result[ModbusScenario, ModbusError]pub(all) struct ModbusTransaction {
id : String
unit_id : Byte
items : Array[TransactionItem]
outcomes : Array[TransactionOutcome]
max_items : Int
state : TransactionState
next_order : Int
}fn ModbusTransaction::acknowledge(self : ModbusTransaction, item_id : String, response : Frame, timestamp : Int) -> Result[Unit, ModbusError]fn ModbusTransaction::add(self : ModbusTransaction, request : Frame, compensation? : Frame) -> Result[String, ModbusError]fn ModbusTransaction::fail(self : ModbusTransaction, item_id : String, error : ModbusError, timestamp : Int) -> Result[Unit, ModbusError]fn ModbusTransaction::new(id : String, unit_id : Byte, max_items? : Int) -> Result[ModbusTransaction, ModbusError]fn ModbusTransaction::rollback(self : ModbusTransaction, timestamp : Int) -> Result[Array[Frame], ModbusError]pub(all) struct NetworkTopology {
nodes : Array[TopologyNode]
links : Array[TopologyLink]
max_nodes : Int
max_links : Int
}fn NetworkTopology::add_link(self : NetworkTopology, link : TopologyLink) -> Result[Unit, ModbusError]fn NetworkTopology::add_node(self : NetworkTopology, node : TopologyNode) -> Result[Unit, ModbusError]fn NetworkTopology::busy_links(self : NetworkTopology, threshold : Int) -> Result[Array[String], ModbusError]fn NetworkTopology::remove_node(self : NetworkTopology, id : String) -> Result[TopologyNode, ModbusError]fn NetworkTopology::route(self : NetworkTopology, source : String, destination : String) -> Result[TopologyRoute, ModbusError]fn NetworkTopology::set_link_utilization(self : NetworkTopology, id : String, utilization : Int) -> Result[Unit, ModbusError]fn NetworkTopology::set_node_health(self : NetworkTopology, id : String, health : TopologyHealth) -> Result[Unit, ModbusError]pub(all) struct ObservabilityDigest {
metric_series : Int
samples : Int
counters : Int
gauges : Int
latest_timestamp : Int
}pub(all) struct PeerGuardState {
peer : String
timestamps : Array[Int]
fingerprints : Array[(FrameFingerprint, Int)]
accepted : Int
rejected : Int
}fn PeerGuardState::duplicate(self : PeerGuardState, fingerprint : FrameFingerprint, now : Int, policy : ProtocolGuardPolicy) -> Boolfn PeerGuardState::prune(self : PeerGuardState, now : Int, policy : ProtocolGuardPolicy) -> Result[Unit, ModbusError]fn PeerGuardState::record(self : PeerGuardState, fingerprint : FrameFingerprint, now : Int, accepted : Bool) -> Unitpub(all) struct PendingExchange {
transaction_id : UInt16
frame : Frame
attempts : Int
created_at : Int
last_sent_at : Int
state : ExchangeState
}pub(all) struct PlanSummary {
requests : Int
total_registers : Int
total_coils : Int
total_bytes : Int
}pub(all) struct PollBudget {
max_requests : Int
max_registers : Int
requests : Int
registers : Int
rejected : Int
}pub(all) struct PollGroupPlan {
points : Array[PollPoint]
groups : Array[PollRequestGroup]
max_groups : Int
merge_gap : Int
revision : Int
}fn PollGroupPlan::due_groups(self : PollGroupPlan, now : Int, last_run : Array[(String, Int)]) -> Result[Array[String], ModbusError]fn PollGroupPlan::request_for(self : PollGroupPlan, group_id : String) -> Result[Frame, ModbusError]fn PollJob::new(id : Int, name : String, request : Frame, interval? : Int, timeout? : Int, retries? : Int) -> Result[PollJob, ModbusError]fn PollPlan::mark_success(self : PollPlan, id : Int, now : Int, response : Frame) -> Result[Unit, ModbusError]pub(all) struct PollPlanStats {
points : Int
enabled_points : Int
groups : Int
merged_points : Int
estimated_registers : Int
highest_priority : Int
}pub(all) struct PollPoint {
id : String
device_id : String
unit_id : Byte
area : PollArea
address : UInt16
quantity : Int
period : Int
priority : Int
enabled : Bool
}fn PollPoint::new(id : String, device_id : String, unit_id : Byte, area : PollArea, address : UInt16, quantity : Int, period : Int, priority? : Int) -> Result[PollPoint, ModbusError]pub(all) struct ProfilePoint {
id : String
label : String
area : ProfileArea
address : UInt16
quantity : Int
encoding : ProfileEncoding
writable : Bool
scale_numerator : Int
scale_denominator : Int
offset : Int
}fn ProfilePoint::new(id : String, label : String, area : ProfileArea, address : UInt16, quantity : Int, encoding : ProfileEncoding, writable? : Bool, scale_numerator? : Int, scale_denominator? : Int, offset? : Int) -> Result[ProfilePoint, ModbusError]fn ProfilePoint::write_request(self : ProfilePoint, unit_id : Byte, value : Int) -> Result[Frame, ModbusError]fn ProfileRegistry::add(self : ProfileRegistry, profile : DeviceProfile) -> Result[Unit, ModbusError]fn ProfileRegistry::remove_by_name(self : ProfileRegistry, name : String) -> Result[DeviceProfile, ModbusError]fn ProfileRegistry::replace(self : ProfileRegistry, profile : DeviceProfile) -> Result[Unit, ModbusError]pub(all) struct ProtocolGuard {
policy : ProtocolGuardPolicy
peers : Array[PeerGuardState]
events : Array[GuardEvent]
max_peers : Int
max_events : Int
sequence : Int
}fn ProtocolGuard::admit(self : ProtocolGuard, peer_name : String, frame : Frame, now : Int) -> Result[GuardDecision, ModbusError]fn ProtocolGuard::new(policy : ProtocolGuardPolicy, max_peers? : Int, max_events? : Int) -> Result[ProtocolGuard, ModbusError]fn ProtocolGuard::peer_stats(self : ProtocolGuard, name : String) -> Result[(Int, Int), ModbusError]fn ProtocolGuard::recent_events(self : ProtocolGuard, limit : Int) -> Result[Array[GuardEvent], ModbusError]pub(all) struct ProtocolGuardPolicy {
max_frame_bytes : Int
max_frames : Int
window : Int
duplicate_window : Int
allow_broadcast : Bool
functions : Array[Byte]
}fn ProtocolGuardPolicy::add_function(self : ProtocolGuardPolicy, function : Byte) -> Result[Unit, ModbusError]fn ProtocolGuardPolicy::new(max_frame_bytes? : Int, max_frames? : Int, window? : Int, duplicate_window? : Int, allow_broadcast? : Bool) -> Result[ProtocolGuardPolicy, ModbusError]pub(all) struct ProtocolLimits {
max_adu : Int
max_pdu : Int
max_registers : Int
max_coils : Int
max_buffer : Int
}pub(all) struct ProtocolMetrics {
requests : Int
responses : Int
exceptions : Int
errors : Int
bytes_in : Int
bytes_out : Int
active : Int
latency : LatencyHistogram
}fn ProtocolMetrics::record_request(self : ProtocolMetrics, bytes : Int) -> Result[Unit, ModbusError]fn ProtocolMetrics::record_response(self : ProtocolMetrics, bytes : Int, latency : Int, exception : Bool) -> Result[Unit, ModbusError]pub(all) struct QualityFinding {
rule_id : String
point_id : String
check_kind : QualityTest
decision : QualityDecision
value : Int
timestamp : Int
message : String
}fn QualityFinding::new(rule : QualityRule, decision : QualityDecision, value : Int, timestamp : Int, message : String) -> Result[QualityFinding, ModbusError]pub(all) struct QualityPipeline {
rules : Array[QualityRule]
findings : Array[QualityFinding]
max_findings : Int
}fn QualityPipeline::add_rule(self : QualityPipeline, rule : QualityRule) -> Result[Unit, ModbusError]fn QualityPipeline::evaluate(self : QualityPipeline, point_id : String, value : Int, timestamp : Int, previous? : Int?, previous_timestamp? : Int?) -> Result[QualityDecision, ModbusError]fn QualityPipeline::findings_for(self : QualityPipeline, point_id : String) -> Array[QualityFinding]pub(all) struct QualityRule {
id : String
point_id : String
check_kind : QualityTest
lower : Int?
upper : Int?
limit : Int
allowed : Array[Int]
enabled : Bool
}fn QualityRule::evaluate(self : QualityRule, value : Int, timestamp : Int, previous : Int?, previous_timestamp : Int?) -> Result[QualityFinding, ModbusError]fn QualityRule::new(id : String, point_id : String, check_kind : QualityTest, lower? : Int, upper? : Int, limit? : Int) -> Result[QualityRule, ModbusError]pub(all) struct QualitySummary {
accepted : Int
substituted : Int
rejected : Int
deferred : Int
}pub(all) struct RateLimiter {
max_delta : Int
previous : Int?
}pub(all) struct ReconciliationDiff {
point_id : String
kind : ReconciliationKind
expected : Int?
observed : Int?
detail : String
}fn ReconciliationDiff::new(point_id : String, kind : ReconciliationKind, expected? : Int, observed? : Int, detail? : String) -> Result[ReconciliationDiff, ModbusError]pub(all) struct ReconciliationReport {
device_id : String
compared : Int
differences : Int
missing : Int
added : Int
changed : Int
equivalent : Bool
}fn RegisterBank::new(start : UInt16, length : Int, writable? : Bool) -> Result[RegisterBank, ModbusError]fn RegisterBank::read(self : RegisterBank, address : UInt16, quantity : Int) -> Result[Array[UInt16], ModbusError]fn RegisterBank::set(self : RegisterBank, address : UInt16, value : UInt16) -> Result[Unit, ModbusError]fn RegisterBank::write(self : RegisterBank, address : UInt16, values : Array[UInt16]) -> Result[Unit, ModbusError]fn RegisterBank::write_mask(self : RegisterBank, address : UInt16, and_mask : UInt16, or_mask : UInt16) -> Result[UInt16, ModbusError]fn RegisterCursor::read_f32(self : RegisterCursor, order : RegisterWordOrder) -> Result[Float, ModbusError]fn RegisterCursor::read_i32(self : RegisterCursor, order : RegisterWordOrder) -> Result[Int, ModbusError]fn RegisterCursor::read_u32(self : RegisterCursor, order : RegisterWordOrder) -> Result[UInt, ModbusError]fn RegisterCursor::read_u64(self : RegisterCursor, order : RegisterWordOrder) -> Result[UInt64, ModbusError]pub(all) struct RegisterField {
name : String
address : UInt16
kind : RegisterFieldKind
writable : Bool
scale : Float
}fn RegisterField::new(name : String, address : UInt16, kind : RegisterFieldKind, writable? : Bool, scale? : Float) -> Result[RegisterField, ModbusError]fn RegisterSchema::read(self : RegisterSchema, name : String, bank : RegisterBank) -> Result[RegisterValue, ModbusError]fn RegisterSchema::read_all(self : RegisterSchema, bank : RegisterBank) -> Result[Array[(String, RegisterValue)], ModbusError]fn RegisterSchema::validate_against(self : RegisterSchema, bank : RegisterBank) -> Result[Unit, ModbusError]fn RegisterSchema::write(self : RegisterSchema, name : String, value : RegisterValue, bank : RegisterBank) -> Result[Unit, ModbusError]pub(all) enum RegisterValue {
U16(UInt16)
I16(Int)
U32(UInt)
I32(Int)
F32(Float)
U64(UInt64)
Bits(Array[Bool])
}fn RegisterWriter::push_f32(self : RegisterWriter, value : Float, order : RegisterWordOrder) -> Result[Unit, ModbusError]fn RegisterWriter::push_u32(self : RegisterWriter, value : UInt, order : RegisterWordOrder) -> Result[Unit, ModbusError]fn RegisterWriter::push_u64(self : RegisterWriter, value : UInt64, order : RegisterWordOrder) -> Result[Unit, ModbusError]pub(all) struct ReliabilityFleetSummary {
devices : Int
healthy : Int
degraded : Int
open_circuits : Int
average_success_rate : Int
average_latency : Int
}pub(all) struct ReliabilitySample {
timestamp : Int
latency : Int
success : Bool
failure : ReliabilityFailure?
operation : String
}fn ReliabilitySample::new(timestamp : Int, latency : Int, success : Bool, operation : String, failure? : ReliabilityFailure) -> Result[ReliabilitySample, ModbusError]pub(all) struct ReliabilityWindow {
width : Int
max_samples : Int
samples : Array[ReliabilitySample]
evicted : Int
}fn ReliabilityWindow::append(self : ReliabilityWindow, sample : ReliabilitySample) -> Result[Unit, ModbusError]fn ReliabilityWindow::new(width : Int, max_samples? : Int) -> Result[ReliabilityWindow, ModbusError]pub(all) struct ReplayItem {
record_id : Int
due_at : Int
bytes : Array[Byte]
attempts : Int
sent : Bool
}fn ReplayPlan::add(self : ReplayPlan, record : CaptureRecord, delay : Int) -> Result[Unit, ModbusError]pub(all) struct ResourceLease {
id : String
resource : String
owner : String
acquired_at : Int
expires_at : Int
state : LeaseState
renewals : Int
priority : Int
}fn ResourceLease::new(id : String, resource : String, owner : String, acquired_at : Int, duration : Int, priority? : Int) -> Result[ResourceLease, ModbusError]fn ResourceLease::renew(self : ResourceLease, now : Int, duration : Int) -> Result[Unit, ModbusError]pub(all) struct RetryPolicy {
max_attempts : Int
initial_backoff : Int
max_backoff : Int
multiplier : Int
}fn RetryPolicy::new(max_attempts : Int, initial_backoff : Int, max_backoff : Int, multiplier? : Int) -> Result[RetryPolicy, ModbusError]fn RuntimeConfig::apply(self : RuntimeConfig, operations : Array[ConfigOperation], source? : String) -> Result[Int, ModbusError]fn RuntimeConfig::set(self : RuntimeConfig, key : String, value : ConfigValue, source? : String) -> Result[Unit, ModbusError]pub(all) struct ScaleTransform {
raw_min : Int
raw_max : Int
engineering_min : Int
engineering_max : Int
unit : EngineeringUnit
deadband : Int
clamp : Bool
precision : Int
}fn ScaleTransform::engineering_to_raw(self : ScaleTransform, value : Int) -> Result[Int, ModbusError]fn ScaleTransform::new(raw_min : Int, raw_max : Int, engineering_min : Int, engineering_max : Int, unit? : EngineeringUnit, deadband? : Int, clamp? : Bool, precision? : Int) -> Result[ScaleTransform, ModbusError]pub(all) struct ScaledReading {
point_id : String
raw : Int
value : Int
unit : EngineeringUnit
quality : ReadingQuality
timestamp : Int
}fn ScaledReading::new(point_id : String, raw : Int, transform : ScaleTransform, timestamp : Int) -> Result[ScaledReading, ModbusError]pub(all) struct ScenarioResult {
step_id : String
outcome : ScenarioOutcome
started_at : Int
finished_at : Int
response : Frame?
error : ModbusError?
detail : String
}fn ScenarioResult::new(step_id : String, outcome : ScenarioOutcome, started_at : Int, finished_at : Int, response? : Frame, error? : ModbusError, detail? : String) -> Result[ScenarioResult, ModbusError]pub(all) struct ScenarioRunner {
scenario : ModbusScenario
results : Array[ScenarioResult]
cursor : Int
now : Int
}fn ScenarioRunner::new(scenario : ModbusScenario, start_at? : Int) -> Result[ScenarioRunner, ModbusError]pub(all) struct ScenarioStep {
id : String
timestamp : Int
request : Frame
expected_function : Byte
expected_outcome : ScenarioOutcome
fault : ScenarioFault
note : String
}fn ScenarioStep::new(id : String, timestamp : Int, request : Frame, expected_outcome : ScenarioOutcome, note? : String) -> Result[ScenarioStep, ModbusError]pub(all) struct ScheduledJob {
id : String
request : Frame
priority : JobPriority
period : Int
deadline : Int
policy : RetryPolicy
due_at : Int
attempts : Int
state : JobState
last_error : ModbusError?
last_started : Int?
last_finished : Int?
tag : String
}fn ScheduledJob::fail(self : ScheduledJob, error : ModbusError, now : Int) -> Result[Bool, ModbusError]fn ScheduledJob::new(id : String, request : Frame, due_at : Int, period? : Int, priority? : JobPriority, deadline? : Int, policy? : RetryPolicy, tag? : String) -> Result[ScheduledJob, ModbusError]pub(all) struct SchedulerSnapshot {
total : Int
ready : Int
in_flight : Int
waiting : Int
completed : Int
failed : Int
cancelled : Int
}pub(all) struct SecurityAudit {
sequence : Int
timestamp : Int
principal : String
role : AccessRole
operation : AccessOperation
unit_id : Byte
function : Byte
allowed : Bool
reason : String
}fn SecurityAudit::new(sequence : Int, timestamp : Int, principal : String, role : AccessRole, operation : AccessOperation, frame : Frame, allowed : Bool, reason : String) -> Result[SecurityAudit, ModbusError]pub(all) struct SerialConfig {
path : String
baud : Int
data_bits : Int
stop_bits : Int
parity : Byte
mode : Mode
}fn SerialConfig::new(path : String, baud : Int, mode : Mode, data_bits? : Int, stop_bits? : Int, parity? : Byte) -> Result[SerialConfig, ModbusError]pub struct Server {
config : ServerConfig
devices : Array[Device]
parser : IncrementalParser
metrics : ProtocolMetrics
audit : AuditLog
}pub(all) struct ServerConfig {
mode : Mode
max_devices : Int
max_frame : Int
allow_broadcast : Bool
max_pending_bytes : Int
}pub(all) struct ServiceBridgeRule {
id : String
source_unit : Byte
target_unit : Byte
function : Byte
source_start : UInt16
span : Int
target_start : UInt16
action : BridgeAction
priority : Int
enabled : Bool
tag : String
}fn ServiceBridgeRule::new(id : String, source_unit : Byte, target_unit : Byte, function : Byte, source_start : UInt16, span : Int, target_start : UInt16, action : BridgeAction, priority? : Int, tag? : String) -> Result[ServiceBridgeRule, ModbusError]fn ServiceBridgeRule::rewrite(self : ServiceBridgeRule, frame : Frame) -> Result[Frame, ModbusError]pub(all) struct ServiceEvent {
id : String
kind : ServiceEventKind
source : String
timestamp : Int
payload : Array[Byte]
delivery : EventDelivery
attempts : Int
}fn ServiceEvent::mark_failed(self : ServiceEvent, dead_letter_after : Int) -> Result[Unit, ModbusError]fn ServiceEvent::new(id : String, kind : ServiceEventKind, source : String, timestamp : Int, payload : Array[Byte]) -> Result[ServiceEvent, ModbusError]pub(all) struct ServiceEventBus {
queue : Array[ServiceEvent]
dead_letters : Array[ServiceEvent]
subscriptions : Array[EventSubscription]
max_queue : Int
max_dead_letters : Int
max_subscriptions : Int
}fn ServiceEventBus::ack(self : ServiceEventBus, event : ServiceEvent, success : Bool, dead_letter_after? : Int) -> Result[Unit, ModbusError]fn ServiceEventBus::claim(self : ServiceEventBus, subscription_id : String) -> Result[ServiceEvent, ModbusError]fn ServiceEventBus::new(max_queue? : Int, max_dead_letters? : Int, max_subscriptions? : Int) -> Result[ServiceEventBus, ModbusError]fn ServiceEventBus::peek_kind(self : ServiceEventBus, kind : ServiceEventKind) -> Array[ServiceEvent]fn ServiceEventBus::publish(self : ServiceEventBus, event : ServiceEvent) -> Result[Unit, ModbusError]fn ServiceEventBus::subscribe(self : ServiceEventBus, subscription : EventSubscription) -> Result[Unit, ModbusError]fn ServiceEventBus::unsubscribe(self : ServiceEventBus, id : String) -> Result[EventSubscription, ModbusError]pub(all) struct ServiceGatewayPolicy {
id : String
source : String
destination : String
rules : Array[ServiceBridgeRule]
default_action : BridgeAction
max_rules : Int
revision : Int
}fn ServiceGatewayPolicy::add_rule(self : ServiceGatewayPolicy, rule : ServiceBridgeRule) -> Result[Unit, ModbusError]fn ServiceGatewayPolicy::evaluate(self : ServiceGatewayPolicy, frame : Frame) -> Result[BridgeDecision, ModbusError]fn ServiceGatewayPolicy::new(id : String, source : String, destination : String, default_action? : BridgeAction, max_rules? : Int) -> Result[ServiceGatewayPolicy, ModbusError]fn ServiceGatewayPolicy::remove_rule(self : ServiceGatewayPolicy, id : String) -> Result[ServiceBridgeRule, ModbusError]pub(all) struct ServiceMetric {
name : String
kind : MetricKind
value : Int
timestamp : Int
labels : Array[(String, String)]
}fn ServiceMetric::new(name : String, kind : MetricKind, value : Int, timestamp : Int) -> Result[ServiceMetric, ModbusError]fn ServiceMetric::with_label(self : ServiceMetric, key : String, value : String) -> Result[Unit, ModbusError]pub(all) struct ServicePlan {
id : String
asset_id : String
title : String
kind : MaintenanceKind
interval : Int
grace : Int
estimated_minutes : Int
enabled : Bool
last_completed : Int?
owner : String
}fn ServicePlan::new(id : String, asset_id : String, title : String, kind : MaintenanceKind, interval : Int, grace? : Int, estimated_minutes? : Int, owner? : String) -> Result[ServicePlan, ModbusError]fn ServiceRecord::new(id : String, plan_id : String, asset_id : String, started_at : Int, finished_at : Int, technician : String, result : String) -> Result[ServiceRecord, ModbusError]pub struct Simulation {
device : Device
mode : Mode
fault : FaultMode
clock : Int
metrics : ProtocolMetrics
audit : AuditLog
}fn Simulation::request(self : Simulation, transaction_id : UInt16, request : Frame) -> SimulationResultpub(all) struct SnapshotValue {
point_id : String
value : Int
quality : ReadingQuality
timestamp : Int
}fn SnapshotValue::new(point_id : String, value : Int, timestamp : Int, quality? : ReadingQuality) -> Result[SnapshotValue, ModbusError]fn TagSample::new(point_id : String, timestamp : Int, value : Int, quality? : ReadingQuality) -> Result[TagSample, ModbusError]fn TagSeries::aggregate(self : TagSeries, start : Int, end : Int, aggregation : Aggregation) -> Result[Int, ModbusError]fn TagSeries::between(self : TagSeries, start : Int, end : Int) -> Result[Array[TagSample], ModbusError]pub(all) struct TcpConfig {
host : String
port : Int
connect_timeout : Int
keep_alive : Bool
}pub(all) struct Threshold {
low : Int
high : Int
}pub(all) struct TokenBucket {
capacity : Int
refill_interval : Int
tokens : Int
last_refill : Int
}fn TokenBucket::new(capacity : Int, refill_interval : Int, now : Int) -> Result[TokenBucket, ModbusError]pub(all) struct TopologyHealthReport {
node_count : Int
link_count : Int
healthy : Int
degraded : Int
unavailable : Int
average_load : Int
invalid_edges : Int
}pub(all) struct TopologyLink {
id : String
from : String
to : String
latency : Int
capacity : Int
utilization : Int
bidirectional : Bool
transport : String
}fn TopologyLink::new(id : String, from : String, to : String, latency : Int, capacity : Int, bidirectional? : Bool, transport? : String) -> Result[TopologyLink, ModbusError]pub(all) struct TopologyNode {
id : String
label : String
kind : TopologyNodeKind
unit_id : Byte?
health : TopologyHealth
load : Int
zone : String
tags : Array[String]
}fn TopologyNode::new(id : String, label : String, kind : TopologyNodeKind, unit_id? : Byte, zone? : String) -> Result[TopologyNode, ModbusError]fn TopologyRoute::new(source : String, destination : String, nodes : Array[String], links : Array[String], cost : Int) -> TopologyRoutefn TransactionBatch::add(self : TransactionBatch, transaction : ModbusTransaction) -> Result[Unit, ModbusError]pub(all) struct TransactionItem {
id : String
request : Frame
compensation : Frame?
state : TransactionState
order : Int
}fn TransactionItem::new(id : String, request : Frame, order : Int, compensation? : Frame) -> Result[TransactionItem, ModbusError]pub(all) struct TransactionOutcome {
item_id : String
state : TransactionState
response : Frame?
error : ModbusError?
timestamp : Int
}fn TransactionOutcome::new(item_id : String, state : TransactionState, timestamp : Int, response? : Frame, error? : ModbusError) -> Result[TransactionOutcome, ModbusError]pub(all) struct TransportCapabilities {
mode : Mode
max_adu : Int
supports_broadcast : Bool
preserves_transaction_id : Bool
}pub(all) struct TransportMetricWindow {
transport : MetricsTransport
window : Int
requests : Int
successes : Int
failures : Int
bytes_sent : Int
bytes_received : Int
latency_total : Int
latency_max : Int
last_timestamp : Int
}fn TransportMetricWindow::new(transport : MetricsTransport, window : Int) -> Result[TransportMetricWindow, ModbusError]fn TransportMetricWindow::record(self : TransportMetricWindow, timestamp : Int, success : Bool, latency : Int, sent : Int, received : Int) -> Result[Unit, ModbusError]pub(all) struct TransportMetricsRegistry {
windows : Array[TransportMetricWindow]
max_windows : Int
}fn TransportMetricsRegistry::new(max_windows? : Int, window? : Int) -> Result[TransportMetricsRegistry, ModbusError]fn TransportMetricsRegistry::record(self : TransportMetricsRegistry, transport : MetricsTransport, timestamp : Int, success : Bool, latency : Int, sent : Int, received : Int) -> Result[Unit, ModbusError]fn TransportMetricsRegistry::window(self : TransportMetricsRegistry, transport : MetricsTransport) -> TransportMetricWindow?pub(all) struct ValueAnomaly {
rule_id : String
timestamp : Int
value : Int
kind : AnomalyKind
severity : Int
detail : String
}fn ValueAnomaly::new(rule_id : String, timestamp : Int, value : Int, kind : AnomalyKind, severity : Int, detail : String) -> Result[ValueAnomaly, ModbusError]pub(all) struct ValueHistogram {
lower : Int
upper : Int
width : Int
bins : Array[Int]
outside : Int
}fn ValueHistogram::new(lower : Int, upper : Int, bin_count : Int) -> Result[ValueHistogram, ModbusError]fn VirtualLink::round_trip(self : VirtualLink, device : Device, transaction_id : UInt16, request : Frame) -> Result[DeviceResponse, ModbusError]fn VirtualLink::send_request(self : VirtualLink, transaction_id : UInt16, frame : Frame) -> Result[Unit, ModbusError]fn VirtualLink::send_response(self : VirtualLink, transaction_id : UInt16, frame : Frame) -> Result[Unit, ModbusError]fn analytics_report(window : AnalyticsWindow, rule : AnalyticsRule, histogram : ValueHistogram) -> Result[AnalyticsReport, ModbusError]fn bucket_samples(samples : Array[TagSample], start : Int, width : Int) -> Result[Array[HistoryBucket], ModbusError]fn bytes_to_register(bytes : Array[Byte], offset : Int, order : RegisterByteOrder) -> Result[UInt16, ModbusError]fn bytes_to_registers(bytes : Array[Byte], order : RegisterByteOrder) -> Result[Array[UInt16], ModbusError]fn crc16_update(crc : UInt16, byte : Byte) -> UInt16fn decode_comm_event_counter(request : Frame, response : Frame) -> Result[(UInt16, UInt16), ModbusError]fn decode_device_identification(request : Frame, response : Frame) -> Result[DeviceIdentification, ModbusError]fn decode_diagnostics(request : Frame, response : Frame) -> Result[(UInt16, Array[Byte]), ModbusError]fn decode_file_record_response(request : Frame, response : Frame) -> Result[Array[Array[UInt16]], ModbusError]fn decode_file_record_write_response(request : Frame, response : Frame) -> Result[Unit, ModbusError]fn decode_multiple_write(request : Frame, response : Frame) -> Result[(UInt16, UInt16), ModbusError]fn decode_read_write_response(request : Frame, response : Frame) -> Result[Array[UInt16], ModbusError]fn decode_register_response(request : Frame, response : Frame) -> Result[Array[UInt16], ModbusError]fn diagnose_capability_gap(capabilities : CapabilitySet, expected_functions : Array[Byte]) -> DiagnosticReportfn diagnostics(unit_id : Byte, subfunction : UInt16, data : Array[Byte]) -> Result[Frame, ModbusError]fn encapsulated_interface(unit_id : Byte, mei_type : Byte, payload : Array[Byte]) -> Result[Frame, ModbusError]fn encode_device_identification(unit_id : Byte, category : DeviceIdCategory, conformity : Byte, more_follows : Bool, next_object_id : Byte, objects : Array[DeviceIdObject]) -> Result[Frame, ModbusError]fn evaluate_access(policy : AccessPolicy, role : AccessRole, operation : AccessOperation, principal : String, frame : Frame, timestamp : Int, sequence : Int) -> Result[SecurityAudit, ModbusError]fn fleet_health_from_inventory(rollup : FleetHealthRollup, inventory : DeviceInventory, now : Int, timeout : Int) -> Result[Unit, ModbusError]fn fleet_health_from_reliability(timestamp : Int, summary : ReliabilityFleetSummary) -> Result[FleetHealthRollup, ModbusError]fn fleet_health_from_services(rollup : FleetHealthRollup, registry : DeviceServiceRegistry) -> Result[Unit, ModbusError]fn float_words(high : UInt16, low : UInt16) -> UInt64fn function_name(function : Byte) -> Stringfn gateway_function_supported(function : Byte) -> Boolfn is_broadcast(unit_id : Byte) -> Boolfn is_valid_unit_id(unit_id : Byte, broadcast? : Bool) -> Boolfn lrc_from_sum(sum : Byte) -> Bytefn mask_write_register(unit_id : Byte, address : UInt16, and_mask : UInt16, or_mask : UInt16) -> Result[Frame, ModbusError]fn ordinary_function(function : Byte) -> Bytefn plan_read_coils(unit_id : Byte, address : UInt16, quantity : Int, discrete? : Bool) -> Result[Array[PlannedRequest], ModbusError]fn plan_read_registers(unit_id : Byte, address : UInt16, quantity : Int, function? : Byte) -> Result[Array[PlannedRequest], ModbusError]fn plan_write_registers(unit_id : Byte, address : UInt16, values : Array[UInt16]) -> Result[Array[PlannedRequest], ModbusError]fn profile_contiguous_points(points : Array[ProfilePoint], area : ProfileArea) -> Array[ProfilePoint]fn profile_point_value_from_registers(point : ProfilePoint, registers : Array[UInt16]) -> Result[ProfileValue, ModbusError]fn read_device_identification(unit_id : Byte, category : DeviceIdCategory, object_id : Byte) -> Result[Frame, ModbusError]fn read_discrete_inputs(unit_id : Byte, address : UInt16, quantity : UInt16) -> Result[Frame, ModbusError]fn read_file_record(unit_id : Byte, references : Array[FileRecordReference]) -> Result[Frame, ModbusError]fn read_holding_checked(unit_id : Byte, address : UInt16, quantity : UInt16) -> Result[Frame, ModbusError]fn read_holding_registers(unit_id : Byte, address : UInt16, quantity : UInt16) -> Result[Frame, ModbusError]fn read_input_registers(unit_id : Byte, address : UInt16, quantity : UInt16) -> Result[Frame, ModbusError]fn read_quantity_limit(function : Byte) -> Intfn read_write_multiple_registers(unit_id : Byte, read_address : UInt16, read_quantity : UInt16, write_address : UInt16, write_values : Array[UInt16]) -> Result[Frame, ModbusError]fn reconcile_snapshots(expected : DeviceSnapshot, observed : DeviceSnapshot) -> Result[Array[ReconciliationDiff], ModbusError]fn reconciliation_report(device_id : String, diffs : Array[ReconciliationDiff], compared : Int) -> Result[ReconciliationReport, ModbusError]fn registers_to_f32(values : Array[UInt16], word_order : RegisterWordOrder) -> Result[Float, ModbusError]fn registers_to_i32(values : Array[UInt16], word_order : RegisterWordOrder) -> Result[Int, ModbusError]fn registers_to_u32(values : Array[UInt16], word_order : RegisterWordOrder) -> Result[UInt, ModbusError]fn registers_to_u64(values : Array[UInt16], word_order : RegisterWordOrder) -> Result[UInt64, ModbusError]fn signed_register(value : UInt16) -> Intfn supported_function(function : Byte) -> Boolfn try_encode_mode(mode : Mode, transaction_id : UInt16, frame : Frame) -> Result[Array[Byte], ModbusError]fn valid_address_range(address : UInt16, quantity : Int) -> Boolfn write_file_record(unit_id : Byte, records : Array[FileRecordWrite]) -> Result[Frame, ModbusError]fn write_multiple_coils(unit_id : Byte, address : UInt16, values : Array[Bool]) -> Result[Frame, ModbusError]fn write_multiple_registers(unit_id : Byte, address : UInt16, values : Array[UInt16]) -> Result[Frame, ModbusError]fn write_quantity_limit(function : Byte) -> Intfn write_single_register_checked(unit_id : Byte, address : UInt16, value : UInt16) -> Result[Frame, ModbusError]Install
Download zipA portable Modbus RTU, ASCII, and TCP protocol stack with device simulation and gateway primitives for MoonBit.