@@ -11,6 +11,7 @@ use bacnet_transport::bip::BipTransport;
1111use bacnet_types:: error:: Error ;
1212
1313use crate :: config:: GatewayConfig ;
14+ use crate :: parse:: { construct_object, parse_object_type} ;
1415use crate :: state:: GatewayState ;
1516
1617/// Builder for constructing a fully wired Gateway.
@@ -39,6 +40,27 @@ impl GatewayBuilder {
3940 } ) ?;
4041 db. add ( Box :: new ( device) ) ?;
4142
43+ // Pre-populate local objects from config.
44+ for obj_cfg in & self . config . objects {
45+ let obj_type = parse_object_type ( & obj_cfg. object_type )
46+ . map_err ( |e| Error :: Encoding ( format ! ( "object config: {e}" ) ) ) ?;
47+ let obj = construct_object (
48+ obj_type,
49+ obj_cfg. instance ,
50+ & obj_cfg. name ,
51+ obj_cfg. number_of_states ,
52+ )
53+ . map_err ( |e| Error :: Encoding ( format ! ( "object config: {e}" ) ) ) ?;
54+ db. add ( obj)
55+ . map_err ( |e| Error :: Encoding ( format ! ( "object config: {e}" ) ) ) ?;
56+ tracing:: info!(
57+ "Pre-populated object {}:{} ({})" ,
58+ obj_cfg. object_type,
59+ obj_cfg. instance,
60+ obj_cfg. name
61+ ) ;
62+ }
63+
4264 // Determine BIP settings (required for now).
4365 let bip = self . config . transports . bip . as_ref ( ) . ok_or_else ( || {
4466 Error :: Encoding ( "[transports.bip] is required for the gateway" . to_string ( ) )
@@ -53,23 +75,69 @@ impl GatewayBuilder {
5375 . parse ( )
5476 . map_err ( |e| Error :: Encoding ( format ! ( "invalid BIP broadcast: {e}" ) ) ) ?;
5577
56- // Start server on the configured BIP port.
57- let server = BACnetServer :: bip_builder ( )
58- . interface ( interface)
59- . port ( bip. port )
60- . broadcast_address ( broadcast)
78+ // Parse foreign device config once (used for both server and client transports).
79+ let fd_config = if let Some ( fd) = & self . config . foreign_device {
80+ let addr: std:: net:: SocketAddrV4 = fd. bbmd . parse ( ) . map_err ( |e| {
81+ Error :: Encoding ( format ! ( "invalid foreign_device.bbmd '{}': {e}" , fd. bbmd) )
82+ } ) ?;
83+ Some ( bacnet_transport:: bip:: ForeignDeviceConfig {
84+ bbmd_ip : * addr. ip ( ) ,
85+ bbmd_port : addr. port ( ) ,
86+ ttl : fd. ttl ,
87+ } )
88+ } else {
89+ None
90+ } ;
91+
92+ // Create and configure BIP transport for the server.
93+ let mut server_transport = BipTransport :: new ( interface, bip. port , broadcast) ;
94+
95+ if let Some ( ref fdc) = fd_config {
96+ server_transport. register_as_foreign_device ( fdc. clone ( ) ) ;
97+ tracing:: info!(
98+ "Registered as foreign device with BBMD {}:{}" ,
99+ fdc. bbmd_ip,
100+ fdc. bbmd_port
101+ ) ;
102+ }
103+
104+ if let Some ( bbmd_cfg) = & self . config . bbmd {
105+ if bbmd_cfg. enabled {
106+ let mut bdt_entries = Vec :: new ( ) ;
107+ for entry_str in & bbmd_cfg. bdt {
108+ let addr: std:: net:: SocketAddrV4 = entry_str. parse ( ) . map_err ( |e| {
109+ Error :: Encoding ( format ! ( "invalid BDT entry '{entry_str}': {e}" ) )
110+ } ) ?;
111+ bdt_entries. push ( bacnet_transport:: bbmd:: BdtEntry {
112+ ip : addr. ip ( ) . octets ( ) ,
113+ port : addr. port ( ) ,
114+ broadcast_mask : [ 0xff , 0xff , 0xff , 0xff ] ,
115+ } ) ;
116+ }
117+ server_transport. enable_bbmd ( bdt_entries) ;
118+ tracing:: info!( "BBMD enabled with {} BDT entries" , bbmd_cfg. bdt. len( ) ) ;
119+ }
120+ }
121+
122+ // Start server with the pre-configured transport.
123+ let server = BACnetServer :: generic_builder ( )
124+ . transport ( server_transport)
61125 . database ( db)
126+ . vendor_id ( self . config . device . vendor_id )
62127 . build ( )
63128 . await ?;
64129
65130 let server_mac = server. local_mac ( ) . to_vec ( ) ;
66131 let db = server. database ( ) . clone ( ) ;
67132
68- // Start client on an ephemeral port.
69- let client = BACnetClient :: bip_builder ( )
70- . interface ( interface)
71- . port ( 0 )
72- . broadcast_address ( broadcast)
133+ // Create client transport (also needs foreign device config for broadcast routing).
134+ let mut client_transport = BipTransport :: new ( interface, 0 , broadcast) ;
135+ if let Some ( ref fdc) = fd_config {
136+ client_transport. register_as_foreign_device ( fdc. clone ( ) ) ;
137+ }
138+
139+ let client = BACnetClient :: generic_builder ( )
140+ . transport ( client_transport)
73141 . apdu_timeout_ms ( 6000 )
74142 . build ( )
75143 . await ?;
0 commit comments