pub struct ScClientBuilder { /* private fields */ }sc-tls only.Expand description
SC-specific client builder.
Created by BACnetClient::sc_builder(). Requires the sc-tls feature.
Implementations§
Source§impl ScClientBuilder
impl ScClientBuilder
Sourcepub async fn build(
self,
) -> Result<BACnetClient<ScTransport<TlsWebSocket>>, Error>
pub async fn build( self, ) -> Result<BACnetClient<ScTransport<TlsWebSocket>>, Error>
Connect to the hub and start the client.
NPDU admission and reconnect configuration are validated before TLS lookup or dialing, and again when the transport starts. An error still consumes this builder and drops its inputs; this does not promise generic endpoint rollback.
The client’s transport() lends the hub
connection-state watch, hub-connector events and link status, accepted
Hub certificate observation and NPDU drop counts:
use bacnet_client::client::BACnetClient;
use bacnet_transport::sc::{ScConnectionState, ScEvent, ScReconnectConfig};
use bacnet_transport::sc_tls::ScNodeTlsConfig;
async fn watch_hub(tls: ScNodeTlsConfig) -> Result<(), bacnet_types::error::Error> {
let client = BACnetClient::sc_builder()
.hub_url("wss://hub.example.com/bacnet")
.failover_hub_url("wss://failover.example.com/bacnet")
.reconnect(ScReconnectConfig::default())
.tls_config(tls)
.vmac([0x02, 0, 0, 0, 0, 0x01])
.device_uuid([0x42; 16])
.build()
.await?;
// Owned receivers: they can live in their own tasks.
let mut state = client.transport().connection_state_changes();
tokio::spawn(async move {
while state.changed().await.is_ok() {
let _connected = *state.borrow_and_update() == ScConnectionState::Connected;
}
});
let mut events = client.transport().connection_events();
tokio::spawn(async move {
use tokio::sync::broadcast::error::RecvError;
loop {
match events.recv().await {
Ok(event) => {
let _failover = matches!(event, ScEvent::FailoverEngaged);
}
// Fell behind: the oldest events were dropped, not waited for.
Err(RecvError::Lagged(_)) => continue,
Err(RecvError::Closed) => break,
}
}
});
// Active hub, hub VMAC and heartbeat timing: poll when redrawing.
let _status = client.transport().connection_status();
// Owned historical TLS data, present only for an accepted active Hub.
let _peer = client.transport().hub_peer_info().await;
// A snapshot: poll it as often as needed.
let _full_queue_drops = client.transport().npdu_drop_counts().full_drops;
Ok(())
}Sourcepub async fn build_with_events(
self,
) -> Result<(BACnetClient<ScTransport<TlsWebSocket>>, Receiver<ScEvent>), Error>
pub async fn build_with_events( self, ) -> Result<(BACnetClient<ScTransport<TlsWebSocket>>, Receiver<ScEvent>), Error>
Connect to the hub and start the client, as build
does, and also return a hub-connector event receiver subscribed
before the client started.
The first ScEvent::Connected
goes out while build runs, before a caller of
transport().connection_events() can subscribe. This receiver is
already subscribed then, so it holds that event, followed by every
later one, with the same lag rules as connection_events().
use bacnet_client::client::BACnetClient;
use bacnet_transport::sc::ScEvent;
use bacnet_transport::sc_tls::ScNodeTlsConfig;
async fn first_event(tls: ScNodeTlsConfig) -> Result<(), bacnet_types::error::Error> {
let (client, mut events) = BACnetClient::sc_builder()
.hub_url("wss://hub.example.com/bacnet")
.tls_config(tls)
.vmac([0x02, 0, 0, 0, 0, 0x01])
.device_uuid([0x42; 16])
.build_with_events()
.await?;
let first = events.recv().await;
assert!(matches!(first, Ok(ScEvent::Connected { .. })));
drop(client);
Ok(())
}Sourcepub async fn build_any(self) -> Result<BACnetClient<AnyTransport>, Error>
pub async fn build_any(self) -> Result<BACnetClient<AnyTransport>, Error>
Connect to the hub and start a transport-erased BACnet/SC client.
Shares Self::build’s validation, TLS policy, identity, heartbeat and
optional reconnect configuration. Identity, NPDU admission, reconnect and client options
are checked before dialing; heartbeat timing is checked when the transport
starts. The client’s type is the default, over AnyTransport.
use bacnet_client::client::BACnetClient;
use bacnet_transport::sc::ScReconnectConfig;
use bacnet_transport::sc_tls::ScNodeTlsConfig;
async fn connect(tls: ScNodeTlsConfig) -> Result<BACnetClient, bacnet_types::error::Error> {
BACnetClient::sc_builder()
.hub_url("wss://hub.example.com/bacnet")
.tls_config(tls)
.vmac([2, 0, 0, 0, 0, 1])
.device_uuid([0x42; 16])
.reconnect(ScReconnectConfig::default())
.build_any().await
}Sourcepub async fn build_into<T>(self) -> Result<BACnetClient<T>, Error>
pub async fn build_into<T>(self) -> Result<BACnetClient<T>, Error>
Connect to the hub and start a BACnet/SC client over any transport
type an ScTransport converts
into (#2071). Self::build_any is this with AnyTransport.
Sourcepub async fn build_any_with_events(
self,
) -> Result<(BACnetClient<AnyTransport>, Receiver<ScEvent>), Error>
pub async fn build_any_with_events( self, ) -> Result<(BACnetClient<AnyTransport>, Receiver<ScEvent>), Error>
Connect to the hub and start a transport-erased BACnet/SC client, as
build_any does, and also return a hub-connector
event receiver subscribed before the client started (#1909).
As with build_with_events, the receiver
holds the first
ScEvent::Connected,
which a later connection_events() call misses.
use bacnet_client::client::BACnetClient;
use bacnet_transport::sc::ScEvent;
use bacnet_transport::sc_tls::ScNodeTlsConfig;
async fn first_event(tls: ScNodeTlsConfig) -> Result<(), bacnet_types::error::Error> {
let (client, mut events) = BACnetClient::sc_builder()
.hub_url("wss://hub.example.com/bacnet")
.tls_config(tls)
.vmac([0x02, 0, 0, 0, 0, 0x01])
.device_uuid([0x42; 16])
.build_any_with_events()
.await?;
assert!(matches!(events.recv().await, Ok(ScEvent::Connected { .. })));
drop(client);
Ok(())
}Sourcepub async fn build_into_with_events<T>(
self,
) -> Result<(BACnetClient<T>, Receiver<ScEvent>), Error>
pub async fn build_into_with_events<T>( self, ) -> Result<(BACnetClient<T>, Receiver<ScEvent>), Error>
Self::build_into, also returning the hub-connector event receiver
that Self::build_any_with_events returns (#2071).
Source§impl ScClientBuilder
impl ScClientBuilder
Sourcepub fn event_channel_capacity(self, capacity: usize) -> Self
pub fn event_channel_capacity(self, capacity: usize) -> Self
Set the independent event notification broadcast channel capacity.
Sourcepub fn apdu_retries(self, retries: u8) -> Self
pub fn apdu_retries(self, retries: u8) -> Self
Set the number of APDU retries before a confirmed request times out.
Sourcepub fn min_request_interval_ms(self, ms: u64) -> Self
pub fn min_request_interval_ms(self, ms: u64) -> Self
Set the least time, in milliseconds, from the latest confirmed
request to a destination finishing to the next being sent (default
0: no pacing; at most an hour). See
ClientConfig::min_request_interval_ms.
Sourcepub fn max_segments(self, max_segments: Option<u8>) -> Self
pub fn max_segments(self, max_segments: Option<u8>) -> Self
Set the maximum number of APDU segments this client accepts.
Values 0 and 1 fail at build time. Other finite non-rung values are conservatively rounded down in Confirmed-Request headers.
Sourcepub fn segmented_response_accepted(self, accepted: bool) -> Self
pub fn segmented_response_accepted(self, accepted: bool) -> Self
Set whether this client accepts segmented responses.
Sourcepub fn proposed_window_size(self, window_size: u8) -> Self
pub fn proposed_window_size(self, window_size: u8) -> Self
Set the proposed segmented-transfer window size.
Sourcepub fn confirmed_cov_notification_ack_policy<F>(self, policy: F) -> Self
pub fn confirmed_cov_notification_ack_policy<F>(self, policy: F) -> Self
Set the response policy for decoded ConfirmedCOVNotifications.
Source§impl ScClientBuilder
impl ScClientBuilder
Sourcepub fn hub_url(self, url: &str) -> Self
pub fn hub_url(self, url: &str) -> Self
Set the hub WebSocket URL (e.g. wss://hub.example.com/bacnet).
Sourcepub fn tls_config(self, config: ScNodeTlsConfig) -> Self
pub fn tls_config(self, config: ScNodeTlsConfig) -> Self
Set the validated local node TLS policy, shared across initial and reconnect attempts (including normal TLS resumption).
use bacnet_client::client::{BACnetClient, ScClientBuilder};
use bacnet_transport::sc_tls::ScNodeTlsConfig;
fn configured(tls: ScNodeTlsConfig) -> ScClientBuilder {
BACnetClient::sc_builder().tls_config(tls)
}use bacnet_client::client::BACnetClient;
fn raw(config: std::sync::Arc<tokio_rustls::rustls::ClientConfig>) {
let _ = BACnetClient::sc_builder().tls_config(config);
}Sourcepub fn device_uuid(self, uuid: [u8; 16]) -> Self
pub fn device_uuid(self, uuid: [u8; 16]) -> Self
Set the persistent BACnet/SC device UUID.
Sourcepub fn apdu_timeout_ms(self, ms: u64) -> Self
pub fn apdu_timeout_ms(self, ms: u64) -> Self
Set the APDU timeout in milliseconds.
Sourcepub fn cov_channel_capacity(self, capacity: usize) -> Self
pub fn cov_channel_capacity(self, capacity: usize) -> Self
Set the COV notification broadcast channel capacity.
Sourcepub fn heartbeat_interval_ms(self, ms: u64) -> Self
pub fn heartbeat_interval_ms(self, ms: u64) -> Self
Set the heartbeat interval in milliseconds (default 30 000).
Sourcepub fn heartbeat_timeout_ms(self, ms: u64) -> Self
pub fn heartbeat_timeout_ms(self, ms: u64) -> Self
Set the heartbeat timeout in milliseconds (default 60 000).
Sourcepub fn connect_timeout_ms(self, ms: u64) -> Self
pub fn connect_timeout_ms(self, ms: u64) -> Self
Set the connect timeout in milliseconds (default 10 000). It bounds
each hub dial (host lookup, TCP, TLS and WebSocket upgrade), including the ones
build() makes, and each Connect-Request handshake.
Sourcepub fn npdu_per_origin_limit(self, limit: usize) -> Self
pub fn npdu_per_origin_limit(self, limit: usize) -> Self
Set the maximum queued, unconsumed NPDUs per ingress path and source.
Defaults to 32. The accepted range is 1 through 256; checked before TLS lookup or dialing. The aggregate queue remains fixed at 256.
Sourcepub fn control_rate_limit(self, limit: ScControlRateLimit) -> Self
pub fn control_rate_limit(self, limit: ScControlRateLimit) -> Self
Set the per-source limit on inbound network-layer messages (default
ScControlRateLimit::default,
#518, #1969); see
ScTransport::with_control_rate_limit.
Checked with the NPDU quota before TLS lookup or dialing.
Sourcepub fn failover_hub_url(self, url: &str) -> Self
pub fn failover_hub_url(self, url: &str) -> Self
Set the failover hub WebSocket URL, dialled with the same TLS policy when the primary hub cannot be reached (Annex AB.5.2).
Requires reconnect: building with a failover
hub and no reconnect configuration fails before any dial. Both URLs
are checked (scheme, host) before dialling.
build starts on the failover hub when the primary
cannot be dialled, and the connector also turns to it when the primary
refuses the first Connect-Request or the reconnect attempts to the
primary are used up. While on the failover hub it keeps trying the
primary and returns to it when it can. Follow it through
connection_events() and connection_status() on
BACnetClient::transport.
Sourcepub fn reconnect(self, config: ScReconnectConfig) -> Self
pub fn reconnect(self, config: ScReconnectConfig) -> Self
Enable automatic reconnection with the given configuration.
Reconnects redial the hub that was in use, with exponential backoff
from initial_delay_ms up to max_delay_ms, for max_retries
attempts, before turning to the failover hub, if one is set. Required
by failover_hub_url.