Portable IEC 60870-5-104 protocol core for SCADA, gateways, and deterministic simulation.
moon update
moon fmt
moon check --deny-warn --target all
moon build --target wasm-gc
moon test --deny-warn --target wasm-gcmoon run cmd/main
moon run cmd/main -- --help
moon run cmd/main -- --benchmark
moon run cmd/main -- --application-benchmark///|
let payload = @hhxhhx78/moonbit-iec104.normalized_value_asdu(3, 1, 2300, 0)
///|
let apdu = @hhxhhx78/moonbit-iec104.encode_frame(
@hhxhhx78/moonbit-iec104.information_frame(0, 0, payload),
)| 层次 | 主要文件 | 职责 |
|---|---|---|
| 链路与帧 | frame_types.mbt, codec.mbt, validation.mbt, state_machine.mbt | APCI、ASDU 基础模型、校验和链路状态 |
| 应用数据 | protocol_domain.mbt, quality.mbt, time_tags.mbt, application_objects.mbt, extended_asdu.mbt | Type ID、地址、质量、时标和信息对象 |
| 服务与状态 | transport_layer.mbt, station_database.mbt, telemetry_pipeline.mbt, command_scheduler.mbt, point_store.mbt | 传输会话、站点数据库、遥测、命令和点表 |
| 运行时能力 | file_transfer.mbt, historical_archive.mbt, redundancy_manager.mbt, service_registry.mbt, runtime_facade.mbt | 文件、归档、冗余、依赖编排和统一运行时 |
| 工具与可靠性 | wire_tools.mbt, security_limits.mbt, diagnostics_metrics.mbt, health_report.mbt | 字节工具、资源保护、指标和诊断 |
| 仿真与契约 | simulation.mbt, conformance_catalog.mbt, protocol_profiles.mbt, benchmark_api.mbt | 确定性仿真、类型目录、能力协商和基准接口 |
| 示例 | cmd/main | 可运行的最小 CLI |
1..5 | ForEach-Object { Measure-Command { moon run cmd/main -- --benchmark } }moon check --deny-warn --target all
moon test --deny-warn --target wasm-gc
moon test --deny-warn --target nativepub struct AlarmEvent {
station : CommonAddress
address : InformationAddress
name : String
severity : AlarmSeverity
active : Bool
value : Float
timestamp : Int
message : String
} derive(Eq, Debug)pub struct AlarmJournal {
active : Map[String, AlarmRecord]
events : Array[AlarmJournalEvent]
event_limit : Int
next_sequence : Int
metrics : AlarmJournalMetrics
} derive(Debug)fn AlarmJournal::acknowledge(self : AlarmJournal, key : String, operator : String, timestamp : Int) -> Result[AlarmRecord, String]fn AlarmJournal::escalate(self : AlarmJournal, key : String, operator : String, timestamp : Int) -> Result[AlarmRecord, String]fn AlarmJournal::shelve(self : AlarmJournal, key : String, operator : String, until : Int, timestamp : Int) -> Result[AlarmRecord, String]pub struct AlarmJournalEvent {
sequence : Int
timestamp : Int
key : String
action : AlarmJournalAction
operator : String
detail : String
} derive(Eq, Debug)pub struct AlarmRecord {
key : String
station : CommonAddress
address : InformationAddress
name : String
severity : AlarmSeverity
lifecycle : AlarmLifecycle
first_seen : Int
last_seen : Int
occurrences : Int
acknowledged_by : String?
acknowledged_at : Int?
shelf_until : Int?
last_value : Float
message : String
} derive(Debug)pub struct AlarmRule {
low : Float?
high : Float?
severity : AlarmSeverity
hysteresis : Float
name : String
} derive(Eq, Debug)fn AlarmRule::new(name : String, severity : AlarmSeverity, low? : Float, high? : Float, hysteresis? : Float) -> Result[AlarmRule, String]pub struct ApplicationObject {
address : InformationAddress
type_id : ApplicationType
value : ApplicationValue
time_tag : TimeTag?
} derive(Eq, Debug)fn ApplicationObject::new(address : InformationAddress, value : ApplicationValue, time_tag? : TimeTag) -> Result[ApplicationObject, String]pub enum ApplicationType {
MSpNa
MSpTa
MDpNa
MDpTa
MStNa
MStTa
MBoNa
MBoTa
MMeNa
MMeTa
MMeNb
MMeTb
MMeNc
MMeTc
MItNa
MItTa
MEpTa
MEpTb
MEpTc
MPsNa
MMeNd
MSpTb
MDpTb
MStTb
MBoTb
MMeTd
MMeTe
MMeTf
MItTb
MEpTd
MEpTe
MEpTf
MEiNa
CScNa
CDcNa
CRcNa
CSeNa
CSeNb
CSeNc
CBoNa
CIcNa
CCiNa
CRdNa
CCsNa
CTsNa
CRpNa
UnknownType(Int)
} derive(Eq, Debug)pub enum ApplicationValue {
SinglePointValue(SinglePointValue)
DoublePointValue(DoublePointValue)
StepPositionValue(StepPositionValue)
BitStringValue(UInt)
NormalizedMeasurement(NormalizedValue)
ScaledMeasurement(ScaledValue)
ShortFloatMeasurement(ShortFloatValue)
BinaryCounterMeasurement(BinaryCounterValue)
SingleCommand(Bool, Int)
DoubleCommand(Int, Int)
RegulatingStepCommand(Int, Int)
NormalizedSetPoint(Int, Int)
ScaledSetPoint(Int, Int)
ShortFloatSetPoint(Float, Int)
BitStringCommand(UInt)
InterrogationCommand(Int)
CounterInterrogationCommand(Int)
ReadCommand
ClockSyncCommand(Cp56Time)
TestCommand(Int)
ResetCommand(Int)
DelayCommand(Int)
EndOfInitialization(Int)
RawValue(Bytes)
} derive(Eq, Debug)pub struct ArchiveBucket {
station : CommonAddress
address : InformationAddress
start : Int
end : Int
count : Int
minimum : Float
maximum : Float
sum : Float
invalid : Int
} derive(Eq, Debug)fn ArchivePolicy::new(maximum_samples? : Int, maximum_age? : Int, bucket_width? : Int, reject_invalid? : Bool) -> Result[ArchivePolicy, String]pub struct ArchiveQuery {
station : CommonAddress?
first_address : InformationAddress?
last_address : InformationAddress?
start : Int?
end : Int?
source : String?
include_invalid : Bool
} derive(Eq, Debug)fn ArchiveQuery::address_range(self : ArchiveQuery, first : InformationAddress, last : InformationAddress) -> ArchiveQuerypub struct ArchiveStore {
samples : Array[ArchivedSample]
policy : ArchivePolicy
next_sequence : Int
evicted : Int
} derive(Debug)fn ArchiveStore::latest(self : ArchiveStore, station : CommonAddress, address : InformationAddress) -> ArchivedSample?pub struct ArchivedSample {
station : CommonAddress
address : InformationAddress
type_id : ApplicationType
value : Float
quality : QualityDescriptor
timestamp : Int
sequence : Int
source : String
} derive(Debug)pub struct AsduEnvelope {
type_id : ApplicationType
sequence : Bool
cause : CauseOfTransmission
common_address : CommonAddress
objects : Array[ApplicationObject]
} derive(Eq, Debug)fn AsduEnvelope::new(type_id : ApplicationType, sequence : Bool, cause : CauseOfTransmission, common_address : CommonAddress, objects : Array[ApplicationObject]) -> Result[AsduEnvelope, Diagnostic]fn BenchmarkCase::new(name : String, rounds : Int, payload_size : Int, target : String) -> Result[BenchmarkCase, String]pub struct BenchmarkResult {
case : BenchmarkCase
encoded_frames : Int
encoded_bytes : Int
checksum : UInt
elapsed_micros : Int
} derive(Eq, Debug)fn BenchmarkResult::new(case : BenchmarkCase, workload : BenchmarkWorkload, elapsed_micros : Int) -> Result[BenchmarkResult, String]fn BenchmarkSuite::run(self : BenchmarkSuite, elapsed_micros : Array[Int]) -> Result[Array[BenchmarkResult], String]fn BinaryCounterValue::new(value : UInt, sequence? : Int, carry? : Bool, adjusted? : Bool, invalid? : Bool) -> Result[BinaryCounterValue, String]pub struct CauseOfTransmission {
category : CauseCategory
number : Int
positive : Bool
test_flag : Bool
originator : Int
qualifier : Int
} derive(Eq, Debug)fn CauseOfTransmission::from_number(number : Int, positive? : Bool, test_flag? : Bool, originator? : Int, qualifier? : Int) -> Result[CauseOfTransmission, String]fn CauseOfTransmission::new(category : CauseCategory, positive? : Bool, test_flag? : Bool, originator? : Int, qualifier? : Int) -> Result[CauseOfTransmission, String]pub struct ClockSyncTransaction {
request : ServiceRequest
status : ServiceStatus
received : Cp56Time?
applied_at : Int?
} derive(Debug)fn ClockSyncTransaction::apply(self : ClockSyncTransaction, timestamp : Cp56Time, applied_at : Int) -> Result[Int, String]pub struct CommandAudit {
ticket : Int
timestamp : Int
from : CommandLifecycle
to : CommandLifecycle
attempt : Int
message : String
} derive(Eq, Debug)fn CommandAudit::new(ticket : Int, timestamp : Int, from : CommandLifecycle, to : CommandLifecycle, attempt : Int, message : String) -> CommandAuditpub struct CommandDispatch {
ticket : Int
station : CommonAddress
object : ApplicationObject
attempt : Int
expires_at : Int
} derive(Debug)pub struct CommandOutcome {
accepted : Bool
status : ServiceStatus
object : ApplicationObject?
message : String
} derive(Debug)pub struct CommandQueue {
pending : Array[ApplicationObject]
completed : Array[CommandOutcome]
limit : Int
} derive(Debug)pub struct CommandRequest {
ticket : Int
station : CommonAddress
object : ApplicationObject
priority : CommandPriority
submitted_at : Int
deadline : Int
idempotency_key : String
source : String
policy : RetryPolicy
attempts : Int
lifecycle : CommandLifecycle
next_attempt_at : Int
last_error : String
} derive(Debug)fn CommandRequest::new(ticket : Int, station : CommonAddress, object : ApplicationObject, priority : CommandPriority, submitted_at : Int, deadline : Int, idempotency_key : String, source : String, policy : RetryPolicy) -> Result[CommandRequest, Diagnostic]pub struct CommandScheduler {
pending : Array[CommandRequest]
audits : Array[CommandAudit]
audit_limit : Int
idempotency : Map[String, Int]
next_ticket : Int
metrics : SchedulerMetrics
} derive(Debug)fn CommandScheduler::cancel(self : CommandScheduler, ticket : Int, now : Int, reason? : String) -> Result[CommandRequest, Diagnostic]fn CommandScheduler::confirm(self : CommandScheduler, ticket : Int, now : Int, accepted : Bool, message? : String) -> Result[CommandRequest, Diagnostic]fn CommandScheduler::dispatch(self : CommandScheduler, policy : CommandPolicy, now : Int) -> Result[CommandDispatch?, Diagnostic]fn CommandScheduler::submit(self : CommandScheduler, station : CommonAddress, object : ApplicationObject, priority : CommandPriority, now : Int, deadline : Int, idempotency_key : String, source? : String, policy? : RetryPolicy) -> Result[CommandRequest, Diagnostic]pub struct ConfigChange {
key : String
kind : ConfigChangeKind
from : ConfigValue?
to : ConfigValue?
revision : Int
timestamp : Int
operator : String
message : String
} derive(Eq, Debug)pub struct ConfigDefinition {
key : String
description : String
default_value : ConfigValue
required : Bool
minimum : Int?
maximum : Int?
secret : Bool
restart_required : Bool
} derive(Eq, Debug)fn ConfigDefinition::new(key : String, description : String, default_value : ConfigValue, required? : Bool, minimum? : Int, maximum? : Int, secret? : Bool, restart_required? : Bool) -> Result[ConfigDefinition, String]pub struct ConfigEntry {
definition : ConfigDefinition
value : ConfigValue
revision : Int
updated_at : Int
updated_by : String
} derive(Eq, Debug)pub struct ConfigTransaction {
base_revision : Int
operator : String
timestamp : Int
updates : Array[(String, ConfigValue)]
resets : Array[String]
closed : Bool
} derive(Debug)fn ConfigTransaction::new(base_revision : Int, operator : String, timestamp : Int) -> ConfigTransactionfn ConfigTransaction::set(self : ConfigTransaction, key : String, value : ConfigValue) -> Result[Unit, String]pub enum ConfigValue {
ConfigInt(Int)
ConfigBool(Bool)
ConfigText(String)
ConfigDuration(Int)
ConfigAddress(CommonAddress)
ConfigAddressList(Array[CommonAddress])
} derive(Eq, Debug)pub struct ConfigurationRegistry {
definitions : Map[String, ConfigDefinition]
values : Map[String, ConfigEntry]
history : Array[ConfigChange]
history_limit : Int
revision : Int
} derive(Debug)fn ConfigurationRegistry::commit(self : ConfigurationRegistry, transaction : ConfigTransaction) -> Result[Array[ConfigChange], String]fn ConfigurationRegistry::definition(self : ConfigurationRegistry, key : String) -> ConfigDefinition?fn ConfigurationRegistry::register_definition(self : ConfigurationRegistry, definition : ConfigDefinition, timestamp : Int, operator : String) -> Result[Unit, String]fn ConfigurationRegistry::reset(self : ConfigurationRegistry, key : String, timestamp : Int, operator : String) -> Result[ConfigEntry, String]fn ConfigurationRegistry::set(self : ConfigurationRegistry, key : String, value : ConfigValue, timestamp : Int, operator : String) -> Result[ConfigEntry, String]pub struct ConformanceReport {
valid : Bool
type_id : ApplicationType
object_count : Int
expected_width : Int
actual_width : Int
issues : Array[String]
} derive(Eq, Debug)pub struct ConformanceVector {
name : String
category : VectorCategory
input : Bytes
expectation : VectorExpectation
expected_kind : FrameKind?
expected_send : Int?
expected_receive : Int?
expected_payload : Bytes?
} derive(Debug)fn ConformanceVector::new(name : String, category : VectorCategory, input : Bytes, expectation : VectorExpectation, expected_kind? : FrameKind, expected_send? : Int, expected_receive? : Int, expected_payload? : Bytes) -> Result[ConformanceVector, String]fn ConnectionParameters::new(k : Int, w : Int, t0_seconds : Int, t1_seconds : Int, t2_seconds : Int, t3_seconds : Int) -> Result[ConnectionParameters, String]pub struct CounterInterrogationRequest {
common_address : CommonAddress
qualifier : Int
created_at : Int
} derive(Eq, Debug)fn CounterInterrogationRequest::new(common_address : CommonAddress, qualifier : Int, created_at : Int) -> Result[CounterInterrogationRequest, String]pub struct DatabaseEvent {
sequence : Int
timestamp : Int
kind : DatabaseEventKind
common_address : CommonAddress?
point_address : InformationAddress?
message : String
} derive(Eq, Debug)fn DatabaseEvent::new(sequence : Int, timestamp : Int, kind : DatabaseEventKind, common_address? : CommonAddress, point_address? : InformationAddress, message? : String) -> DatabaseEventpub struct DatabaseSnapshot {
revision : Int
timestamp : Int
stations : Array[StationSummary]
events : Array[DatabaseEvent]
} derive(Debug)pub struct DatabaseTransaction {
base_revision : Int
timestamp : Int
additions : Array[StationConfig]
removals : Array[CommonAddress]
states : Array[(CommonAddress, StationStatus, StationStateReason, String)]
points : Array[(CommonAddress, ApplicationObject, String)]
closed : Bool
} derive(Debug)fn DatabaseTransaction::add_station(self : DatabaseTransaction, config : StationConfig) -> Result[Unit, String]fn DatabaseTransaction::remove_station(self : DatabaseTransaction, common_address : CommonAddress) -> Result[Unit, String]fn DatabaseTransaction::set_state(self : DatabaseTransaction, common_address : CommonAddress, status : StationStatus, reason : StationStateReason, message? : String) -> Result[Unit, String]fn DatabaseTransaction::write_point(self : DatabaseTransaction, common_address : CommonAddress, object : ApplicationObject, source? : String) -> Result[Unit, Diagnostic]fn DeadbandRule::changed(self : DeadbandRule, previous : TelemetrySample, current : TelemetrySample) -> Boolfn DeadbandRule::new(absolute? : Float, relative_percent? : Float, minimum_interval? : Int) -> Result[DeadbandRule, String]pub struct DiagnosticCatalog {
records : Map[String, DiagnosticRecord]
history : Array[DiagnosticRecord]
history_limit : Int
metrics : DiagnosticCatalogMetrics
} derive(Debug)fn DiagnosticCatalog::acknowledge(self : DiagnosticCatalog, key : String, operator : String) -> Result[DiagnosticRecord, String]fn DiagnosticCatalog::record_diagnostic(self : DiagnosticCatalog, diagnostic : Diagnostic, severity : DiagnosticSeverity, station : CommonAddress?, timestamp : Int) -> DiagnosticRecordfn DiagnosticCatalog::resolve(self : DiagnosticCatalog, key : String, timestamp : Int) -> Result[DiagnosticRecord, String]pub struct DiagnosticRecord {
key : String
kind : DiagnosticKind
severity : DiagnosticSeverity
message : String
station : CommonAddress?
first_seen : Int
last_seen : Int
occurrences : Int
active : Bool
acknowledged : Bool
acknowledged_by : String?
} derive(Eq, Debug)pub struct FailoverEvent {
station : CommonAddress
from_peer : Int?
to_peer : Int?
reason : FailoverReason
timestamp : Int
fencing_token : Int
message : String
} derive(Eq, Debug)fn FileIdentity::new(station : CommonAddress, name : String, file_id : Int) -> Result[FileIdentity, String]pub struct FileInventoryEntry {
identity : FileIdentity
size : Int
revision : Int
checksum : UInt
updated_at : Int
} derive(Eq, Debug)fn FileSegment::new(file_id : Int, section : Int, offset : Int, data : Bytes, last : Bool) -> Result[FileSegment, String]pub struct FileStore {
files : Map[String, StoredFile]
capacity : Int
maximum_size : Int
} derive(Debug)fn FileStore::put(self : FileStore, identity : FileIdentity, data : Bytes, timestamp : Int) -> Result[StoredFile, String]pub struct FileTransferManager {
store : FileStore
sessions : Map[Int, FileTransferSession]
history : Array[FileTransferSession]
history_limit : Int
next_ticket : Int
metrics : FileTransferMetrics
} derive(Debug)fn FileTransferManager::ack(self : FileTransferManager, ticket : Int, timestamp : Int) -> Result[Unit, String]fn FileTransferManager::activate(self : FileTransferManager, ticket : Int, timestamp : Int) -> Result[Unit, String]fn FileTransferManager::append(self : FileTransferManager, ticket : Int, segment : FileSegment, timestamp : Int) -> Result[FileTransferState, String]fn FileTransferManager::begin_download(self : FileTransferManager, identity : FileIdentity, segment_size? : Int, timestamp? : Int) -> Result[Array[FileSegment], String]fn FileTransferManager::begin_upload(self : FileTransferManager, identity : FileIdentity, expected_size : Int, expected_checksum? : UInt, segment_size? : Int, timestamp? : Int) -> Result[FileTransferSession, String]fn FileTransferManager::cancel(self : FileTransferManager, ticket : Int, timestamp : Int) -> Result[Unit, String]fn FileTransferManager::finish(self : FileTransferManager, ticket : Int, timestamp : Int) -> Result[StoredFile, String]fn FileTransferManager::new(store : FileStore, history_limit? : Int) -> Result[FileTransferManager, String]pub struct FileTransferSession {
ticket : Int
identity : FileIdentity
direction : FileTransferDirection
expected_size : Int
segment_size : Int
expected_checksum : UInt?
buffer : Array[Byte]
next_offset : Int
next_section : Int
state : FileTransferState
attempts : Int
last_activity : Int
error : String
} derive(Debug)fn FileTransferSession::activate(self : FileTransferSession, timestamp : Int) -> Result[Unit, String]fn FileTransferSession::append(self : FileTransferSession, segment : FileSegment, timestamp : Int) -> Result[Unit, String]fn FileTransferSession::new(ticket : Int, identity : FileIdentity, direction : FileTransferDirection, expected_size : Int, segment_size : Int, expected_checksum : UInt?, timestamp : Int) -> Result[FileTransferSession, String]pub struct GatewayAdmissionPolicy {
max_objects : Int
allow_monitoring : Bool
allow_control : Bool
allowed_types : Array[ApplicationType]
denied_types : Array[ApplicationType]
} derive(Eq, Debug)fn GatewayAdmissionPolicy::allow_type(self : GatewayAdmissionPolicy, type_id : ApplicationType) -> Unitfn GatewayAdmissionPolicy::deny_type(self : GatewayAdmissionPolicy, type_id : ApplicationType) -> Unitfn GatewayAdmissionPolicy::evaluate(self : GatewayAdmissionPolicy, envelope : AsduEnvelope) -> Result[Unit, String]fn GatewayAdmissionPolicy::new(max_objects : Int, allow_monitoring? : Bool, allow_control? : Bool) -> Result[GatewayAdmissionPolicy, String]pub enum GatewayDispatch {
Forwarded(GatewayEnvelope, GatewayRoute)
Dropped(GatewayEnvelope, String)
} derive(Debug)pub struct GatewayEnvelope {
ingress : Int
egress : Int
common_address : CommonAddress
asdu : AsduEnvelope
received_at : Int
trace_id : String
} derive(Debug)fn GatewayEnvelope::new(ingress : Int, egress : Int, asdu : AsduEnvelope, received_at : Int, trace_id? : String) -> Result[GatewayEnvelope, String]pub struct GatewayRoute {
id : Int
source : Int
destination : Int
common_address : CommonAddress?
type_ids : Array[ApplicationType]
enabled : Bool
priority : Int
} derive(Eq, Debug)fn GatewayRoute::new(id : Int, source : Int, destination : Int, common_address? : CommonAddress, type_ids? : Array[ApplicationType], priority? : Int) -> Result[GatewayRoute, String]fn GatewayRouteTable::select(self : GatewayRouteTable, source : Int, common_address : CommonAddress, type_id : ApplicationType) -> GatewayRoute?pub struct GatewayRuntime {
mode : GatewayMode
routes : GatewayRouteTable
policy : GatewayAdmissionPolicy
inbound : Array[GatewayEnvelope]
outbound : Array[GatewayEnvelope]
dead_letters : Array[GatewayEnvelope]
stores : Array[GatewayStoreBinding]
counters : GatewayCounters
max_queue : Int
last_error : String?
} derive(Debug)fn GatewayRuntime::attach_store(self : GatewayRuntime, binding : GatewayStoreBinding) -> Result[Unit, String]fn GatewayRuntime::enqueue(self : GatewayRuntime, envelope : GatewayEnvelope) -> Result[Unit, String]fn GatewayRuntime::ingest_to_store(self : GatewayRuntime, envelope : GatewayEnvelope) -> Result[Int, String]fn GatewayRuntime::new(max_queue : Int, route_capacity? : Int, policy? : GatewayAdmissionPolicy) -> Result[GatewayRuntime, String]pub struct GatewaySnapshot {
mode : GatewayMode
routes : Int
queue : Int
outbound : Int
dead_letters : Int
counters : GatewayCounters
last_error : String?
} derive(Eq, Debug)pub struct GatewayStoreBinding {
common_address : CommonAddress
store : PointStore
accepted : Int
rejected : Int
} derive(Debug)fn GatewayStoreBinding::ingest(self : GatewayStoreBinding, envelope : GatewayEnvelope) -> Result[Int, String]fn GatewayStoreBinding::new(common_address : CommonAddress, history_limit? : Int) -> Result[GatewayStoreBinding, String]pub struct HealthReport {
state : HealthState
score : Int
checks : Array[String]
warnings : Array[String]
} derive(Eq, Debug)fn HealthReport::new(state : HealthState, score : Int, checks : Array[String], warnings : Array[String]) -> HealthReportpub struct Iec104Runtime {
database : StationDatabase
telemetry : TelemetryPipeline
schedulers : Map[Int, CommandScheduler]
redundancy : Map[Int, RedundancyManager]
policy : OperationalPolicy
redundancy_policy : RedundancyPolicy
files : FileTransferManager
clock : VirtualClock
events : Array[RuntimeEvent]
event_limit : Int
next_event : Int
metrics : RuntimeMetrics
} derive(Debug)fn Iec104Runtime::confirm_command(self : Iec104Runtime, station : CommonAddress, ticket : Int, accepted : Bool, message? : String) -> Result[CommandRequest, Diagnostic]fn Iec104Runtime::dispatch_command(self : Iec104Runtime, station : CommonAddress, policy : CommandPolicy) -> Result[CommandDispatch?, Diagnostic]fn Iec104Runtime::heartbeat(self : Iec104Runtime, station : CommonAddress, peer_id : Int) -> Result[Unit, String]fn Iec104Runtime::ingest(self : Iec104Runtime, station : CommonAddress, object : ApplicationObject, source? : String) -> Result[PipelineResult, Diagnostic]fn Iec104Runtime::register_station(self : Iec104Runtime, config : StationConfig) -> Result[StationSummary, String]fn Iec104Runtime::submit_command(self : Iec104Runtime, operator_id : String, station : CommonAddress, object : ApplicationObject, priority : CommandPriority, deadline : Int, idempotency_key : String) -> Result[CommandRequest, Diagnostic]fn InformationAddress::from_octets(low : Int, middle : Int, high : Int) -> Result[InformationAddress, String]pub struct Interrogation {
request : InterrogationRequest
phase : InterrogationPhase
objects_sent : Int
}pub struct InterrogationPlan {
request : InterrogationRequest
objects : Array[ApplicationObject]
batch_size : Int
cursor : Int
status : ServiceStatus
} derive(Debug)fn InterrogationPlan::new(request : InterrogationRequest, objects : Array[ApplicationObject], batch_size? : Int) -> Result[InterrogationPlan, String]fn InterrogationPlan::next_batch(self : InterrogationPlan) -> Result[Array[ApplicationObject], String]pub struct MaintenanceWindow {
id : Int
station : CommonAddress?
start : Int
end : Int
reason : String
blocks_commands : Bool
blocks_file_writes : Bool
enabled : Bool
} derive(Eq, Debug)fn MaintenanceWindow::contains(self : MaintenanceWindow, station : CommonAddress, timestamp : Int) -> Boolfn MaintenanceWindow::new(id : Int, start : Int, end : Int, reason : String, station? : CommonAddress, blocks_commands? : Bool, blocks_file_writes? : Bool) -> Result[MaintenanceWindow, String]fn NormalizedValue::new(value : Int, quality? : QualityDescriptor) -> Result[NormalizedValue, String]pub struct OperationalPolicy {
rules : Array[PolicyRule]
windows : Array[MaintenanceWindow]
identities : Map[String, OperatorIdentity]
journal : PolicyAuditJournal
revision : Int
} derive(Debug)fn OperationalPolicy::add_identity(self : OperationalPolicy, identity : OperatorIdentity) -> Result[Unit, String]fn OperationalPolicy::add_window(self : OperationalPolicy, window : MaintenanceWindow) -> Result[Unit, String]fn OperationalPolicy::authorize(self : OperationalPolicy, operator_id : String, permission : OperationalPermission, station : CommonAddress, type_id : ApplicationType?, timestamp : Int) -> PolicyDecisionfn OperationalPolicy::remove_identity(self : OperationalPolicy, id : String) -> Result[Unit, String]pub struct OperatorIdentity {
id : String
display_name : String
role : OperatorRole
stations : Array[CommonAddress]
active : Bool
} derive(Eq, Debug)fn OperatorIdentity::new(id : String, display_name : String, role : OperatorRole, stations? : Array[CommonAddress], active? : Bool) -> Result[OperatorIdentity, String]pub struct PipelineResult {
sample : TelemetrySample
accepted : Bool
changed : Bool
rate_valid : Bool
alarms : Array[AlarmEvent]
subscribers : Array[Int]
message : String
} derive(Debug)pub struct PointChange {
kind : PointChangeKind
address : InformationAddress
revision : Int
timestamp : Int
message : String
} derive(Eq, Debug)fn PointChange::new(kind : PointChangeKind, address : InformationAddress, revision : Int, timestamp : Int, message : String) -> PointChangepub struct PointFilter {
direction : PointDirection?
type_id : ApplicationType?
first_address : InformationAddress?
last_address : InformationAddress?
only_valid : Bool
source : String?
} derive(Eq, Debug)fn PointFilter::with_range(self : PointFilter, first : InformationAddress, last : InformationAddress) -> PointFilterpub struct PointRecord {
address : InformationAddress
type_id : ApplicationType
value : ApplicationValue
time_tag : TimeTag?
revision : Int
updated_at : Int
source : String
} derive(Eq, Debug)fn PointRecord::new(object : ApplicationObject, updated_at : Int, revision? : Int, source? : String) -> PointRecordpub struct PointStore {
common_address : CommonAddress
points : Map[Int, PointRecord]
history : Array[PointChange]
history_limit : Int
} derive(Debug)fn PointStore::new(common_address : CommonAddress, history_limit? : Int) -> Result[PointStore, String]fn PointStore::remove(self : PointStore, address : InformationAddress, timestamp : Int) -> Result[PointChange, Diagnostic]fn PointStore::upsert(self : PointStore, object : ApplicationObject, timestamp : Int, source? : String) -> Result[PointChange, Diagnostic]pub struct PolicyAudit {
sequence : Int
timestamp : Int
action : AuditAction
operator : String
station : CommonAddress?
object : InformationAddress?
allowed : Bool
detail : String
} derive(Eq, Debug)pub struct PolicyAuditJournal {
entries : Array[PolicyAudit]
limit : Int
next_sequence : Int
} derive(Debug)fn PolicyAuditJournal::append(self : PolicyAuditJournal, timestamp : Int, action : AuditAction, operator : String, station : CommonAddress?, object : InformationAddress?, allowed : Bool, detail : String) -> PolicyAuditpub struct PolicyDecision {
allowed : Bool
permission : OperationalPermission
operator : String
station : CommonAddress
rule_id : Int?
reason : String
} derive(Eq, Debug)pub struct PolicyRule {
id : Int
permission : OperationalPermission
station : CommonAddress?
type_ids : Array[ApplicationType]
roles : Array[OperatorRole]
enabled : Bool
reason : String
} derive(Eq, Debug)fn PolicyRule::new(id : Int, permission : OperationalPermission, reason : String, station? : CommonAddress, type_ids? : Array[ApplicationType], roles? : Array[OperatorRole]) -> Result[PolicyRule, String]pub struct ProtocolRouter {
rules : Array[RoutingRule]
queues : Map[Int, Array[RoutedObject]]
queue_capacity : Int
metrics : RouterMetrics
sequence : Int
} derive(Debug)fn ProtocolRouter::drain(self : ProtocolRouter, destination : Int, limit : Int) -> Array[RoutedObject]fn ProtocolRouter::evaluate(self : ProtocolRouter, source : Int, destination : Int, object : ApplicationObject) -> RouteDecisionfn ProtocolRouter::route(self : ProtocolRouter, source : Int, destination : Int, object : ApplicationObject, timestamp : Int) -> Result[RouteDecision, Diagnostic]pub struct ProtocolTimers {
t0 : TimerState
t1 : TimerState
t2 : TimerState
t3 : TimerState
} derive(Eq, Debug)pub struct QualityEvaluation {
station : CommonAddress?
address : InformationAddress?
disposition : QualityDisposition
score : Int
age : Int
evaluated_at : Int
rule_id : Int
findings : Array[QualityFinding]
message : String
} derive(Eq, Debug)pub struct QualityGateRule {
id : Int
name : String
max_age : Int
future_skew : Int
require_source : Bool
reject_invalid : Bool
reject_stale : Bool
reject_future : Bool
reject_control : Bool
invalid_penalty : Int
stale_penalty : Int
future_penalty : Int
missing_source_penalty : Int
enabled : Bool
} derive(Eq, Debug)fn QualityGateRule::new(id : Int, name : String, max_age? : Int, future_skew? : Int, require_source? : Bool, reject_invalid? : Bool, reject_stale? : Bool, reject_future? : Bool, reject_control? : Bool, invalid_penalty? : Int, stale_penalty? : Int, future_penalty? : Int, missing_source_penalty? : Int, enabled? : Bool) -> Result[QualityGateRule, String]pub struct QualityPolicyEngine {
rules : Map[Int, QualityGateRule]
station_rules : Map[Int, Int]
history : Array[QualityEvaluation]
history_limit : Int
metrics : QualityPolicyMetrics
} derive(Debug)fn QualityPolicyEngine::accepts_point(self : QualityPolicyEngine, station : CommonAddress, record : PointRecord, now : Int) -> Boolfn QualityPolicyEngine::accepts_sample(self : QualityPolicyEngine, sample : TelemetrySample, now : Int) -> Boolfn QualityPolicyEngine::assign(self : QualityPolicyEngine, station : CommonAddress, rule_id : Int) -> Result[Unit, String]fn QualityPolicyEngine::evaluate_object(self : QualityPolicyEngine, station : CommonAddress, object : ApplicationObject, source : String, timestamp : Int, now : Int) -> QualityEvaluationfn QualityPolicyEngine::evaluate_point(self : QualityPolicyEngine, station : CommonAddress, record : PointRecord, now : Int) -> QualityEvaluationfn QualityPolicyEngine::evaluate_records(self : QualityPolicyEngine, station : CommonAddress, records : Array[PointRecord], now : Int) -> QualityPolicyReportfn QualityPolicyEngine::evaluate_sample(self : QualityPolicyEngine, sample : TelemetrySample, now : Int) -> QualityEvaluationfn QualityPolicyEngine::evaluate_store(self : QualityPolicyEngine, store : PointStore, now : Int) -> QualityPolicyReportfn QualityPolicyEngine::filter_accepted(_self : QualityPolicyEngine, evaluations : Array[QualityEvaluation]) -> Array[QualityEvaluation]fn QualityPolicyEngine::filter_rejected(_self : QualityPolicyEngine, evaluations : Array[QualityEvaluation]) -> Array[QualityEvaluation]fn QualityPolicyEngine::finding_counts(_self : QualityPolicyEngine, evaluations : Array[QualityEvaluation]) -> Map[String, Int]fn QualityPolicyEngine::history_since(self : QualityPolicyEngine, evaluated_at : Int) -> Array[QualityEvaluation]fn QualityPolicyEngine::register_rule(self : QualityPolicyEngine, rule : QualityGateRule) -> Result[Unit, String]fn QualityPolicyEngine::remove_assignment(self : QualityPolicyEngine, station : CommonAddress) -> Boolfn QualityPolicyEngine::replace_rule(self : QualityPolicyEngine, rule : QualityGateRule) -> Result[Unit, String]fn QualityPolicyEngine::station_rule(self : QualityPolicyEngine, station : CommonAddress) -> QualityGateRulefn QualityPolicyEngine::stations_for_rule(self : QualityPolicyEngine, rule_id : Int) -> Array[CommonAddress]pub struct QualityPolicyReport {
total : Int
accepted : Int
degraded : Int
rejected : Int
evaluations : Array[QualityEvaluation]
} derive(Debug)pub struct QualityPolicySnapshot {
rule_count : Int
assignment_count : Int
history_count : Int
metrics : QualityPolicyMetrics
configuration_issues : Array[String]
} derive(Debug)fn ReadTransaction::complete(self : ReadTransaction, object : ApplicationObject) -> Result[ServiceResponse, String]pub struct RedundancyManager {
station : CommonAddress
peers : Map[Int, RedundantPeer]
events : Array[FailoverEvent]
event_limit : Int
policy : RedundancyPolicy
owner : Int?
last_takeover : Int
fencing_token : Int
metrics : RedundancyMetrics
} derive(Debug)fn RedundancyManager::add_peer(self : RedundancyManager, peer : RedundantPeer) -> Result[Unit, String]fn RedundancyManager::heartbeat(self : RedundancyManager, id : Int, now : Int) -> Result[LinkHealth, String]fn RedundancyManager::manual_takeover(self : RedundancyManager, id : Int, now : Int) -> Result[FailoverEvent, String]