1use bacnet_types::enums::{ObjectType, PropertyIdentifier};
8use bacnet_types::error::Error;
9use bacnet_types::primitives::{ObjectIdentifier, PropertyValue, StatusFlags};
10use bacnet_types::MacAddr;
11use std::borrow::Cow;
12
13use crate::common::{self, read_common_properties};
14use crate::traits::BACnetObject;
15
16pub struct NetworkPortObject {
22 oid: ObjectIdentifier,
23 name: String,
24 description: String,
25 status_flags: StatusFlags,
26 out_of_service: bool,
27 reliability: u32,
28 network_type: u32,
30 network_number: u32,
32 mac_address: MacAddr,
34 max_apdu_length_accepted: u32,
36 link_speed: f32,
38 changes_pending: bool,
40 command: u32,
42 ip_address: Vec<u8>,
44 ip_default_gateway: Vec<u8>,
46 ip_subnet_mask: Vec<u8>,
48 ip_udp_port: u16,
50}
51
52impl NetworkPortObject {
53 pub fn new(instance: u32, name: impl Into<String>, network_type: u32) -> Result<Self, Error> {
57 let oid = ObjectIdentifier::new(ObjectType::NETWORK_PORT, instance)?;
58 Ok(Self {
59 oid,
60 name: name.into(),
61 description: String::new(),
62 status_flags: StatusFlags::empty(),
63 out_of_service: false,
64 reliability: 0,
65 network_type,
66 network_number: 0,
67 mac_address: MacAddr::new(),
68 max_apdu_length_accepted: 1476,
69 link_speed: 0.0,
70 changes_pending: false,
71 command: 0,
72 ip_address: vec![0, 0, 0, 0],
73 ip_default_gateway: vec![0, 0, 0, 0],
74 ip_subnet_mask: vec![255, 255, 255, 0],
75 ip_udp_port: 0xBAC0,
76 })
77 }
78
79 pub fn set_description(&mut self, desc: impl Into<String>) {
81 self.description = desc.into();
82 }
83
84 pub fn set_ip_address(&mut self, addr: Vec<u8>) {
86 self.ip_address = addr;
87 }
88
89 pub fn set_ip_default_gateway(&mut self, gw: Vec<u8>) {
91 self.ip_default_gateway = gw;
92 }
93
94 pub fn set_ip_subnet_mask(&mut self, mask: Vec<u8>) {
96 self.ip_subnet_mask = mask;
97 }
98
99 pub fn set_mac_address(&mut self, mac: MacAddr) {
101 self.mac_address = mac;
102 }
103
104 pub fn set_network_number(&mut self, num: u32) {
106 self.network_number = num;
107 }
108
109 pub fn set_link_speed(&mut self, speed: f32) {
111 self.link_speed = speed;
112 }
113
114 pub fn set_udp_port(&mut self, port: u16) {
116 self.ip_udp_port = port;
117 }
118}
119
120impl BACnetObject for NetworkPortObject {
121 fn object_identifier(&self) -> ObjectIdentifier {
122 self.oid
123 }
124
125 fn object_name(&self) -> &str {
126 &self.name
127 }
128
129 fn read_property(
130 &self,
131 property: PropertyIdentifier,
132 array_index: Option<u32>,
133 ) -> Result<PropertyValue, Error> {
134 if let Some(result) = read_common_properties!(self, property, array_index) {
135 return result;
136 }
137 match property {
138 p if p == PropertyIdentifier::OBJECT_TYPE => {
139 Ok(PropertyValue::Enumerated(ObjectType::NETWORK_PORT.to_raw()))
140 }
141 p if p == PropertyIdentifier::NETWORK_TYPE => {
142 Ok(PropertyValue::Enumerated(self.network_type))
143 }
144 p if p == PropertyIdentifier::NETWORK_NUMBER => {
145 Ok(PropertyValue::Unsigned(self.network_number as u64))
146 }
147 p if p == PropertyIdentifier::MAC_ADDRESS => {
148 Ok(PropertyValue::OctetString(self.mac_address.to_vec()))
149 }
150 p if p == PropertyIdentifier::MAX_APDU_LENGTH_ACCEPTED => Ok(PropertyValue::Unsigned(
151 self.max_apdu_length_accepted as u64,
152 )),
153 p if p == PropertyIdentifier::LINK_SPEED => Ok(PropertyValue::Real(self.link_speed)),
154 p if p == PropertyIdentifier::CHANGES_PENDING => {
155 Ok(PropertyValue::Boolean(self.changes_pending))
156 }
157 p if p == PropertyIdentifier::COMMAND_NP => Ok(PropertyValue::Enumerated(self.command)),
158 p if p == PropertyIdentifier::IP_ADDRESS => {
159 Ok(PropertyValue::OctetString(self.ip_address.clone()))
160 }
161 p if p == PropertyIdentifier::IP_DEFAULT_GATEWAY => {
162 Ok(PropertyValue::OctetString(self.ip_default_gateway.clone()))
163 }
164 p if p == PropertyIdentifier::IP_SUBNET_MASK => {
165 Ok(PropertyValue::OctetString(self.ip_subnet_mask.clone()))
166 }
167 p if p == PropertyIdentifier::BACNET_IP_UDP_PORT => {
168 Ok(PropertyValue::Unsigned(self.ip_udp_port as u64))
169 }
170 _ => Err(common::unknown_property_error()),
171 }
172 }
173
174 fn write_property(
175 &mut self,
176 property: PropertyIdentifier,
177 _array_index: Option<u32>,
178 value: PropertyValue,
179 _priority: Option<u8>,
180 ) -> Result<(), Error> {
181 if let Some(result) =
182 common::write_out_of_service(&mut self.out_of_service, property, &value)
183 {
184 return result;
185 }
186 if let Some(result) = common::write_description(&mut self.description, property, &value) {
187 return result;
188 }
189 if property == PropertyIdentifier::COMMAND_NP {
190 if let PropertyValue::Enumerated(v) = value {
191 self.command = v;
192 return Ok(());
193 }
194 return Err(common::invalid_data_type_error());
195 }
196 if property == PropertyIdentifier::IP_ADDRESS {
197 if let PropertyValue::OctetString(v) = value {
198 self.ip_address = v;
199 self.changes_pending = true;
200 return Ok(());
201 }
202 return Err(common::invalid_data_type_error());
203 }
204 if property == PropertyIdentifier::IP_DEFAULT_GATEWAY {
205 if let PropertyValue::OctetString(v) = value {
206 self.ip_default_gateway = v;
207 self.changes_pending = true;
208 return Ok(());
209 }
210 return Err(common::invalid_data_type_error());
211 }
212 if property == PropertyIdentifier::IP_SUBNET_MASK {
213 if let PropertyValue::OctetString(v) = value {
214 self.ip_subnet_mask = v;
215 self.changes_pending = true;
216 return Ok(());
217 }
218 return Err(common::invalid_data_type_error());
219 }
220 if property == PropertyIdentifier::BACNET_IP_UDP_PORT {
221 if let PropertyValue::Unsigned(v) = value {
222 if v > u16::MAX as u64 {
223 return Err(common::value_out_of_range_error());
224 }
225 self.ip_udp_port = v as u16;
226 self.changes_pending = true;
227 return Ok(());
228 }
229 return Err(common::invalid_data_type_error());
230 }
231 if property == PropertyIdentifier::NETWORK_NUMBER {
232 if let PropertyValue::Unsigned(v) = value {
233 self.network_number = common::u64_to_u32(v)?;
234 return Ok(());
235 }
236 return Err(common::invalid_data_type_error());
237 }
238 if property == PropertyIdentifier::MAC_ADDRESS {
239 if let PropertyValue::OctetString(v) = value {
240 self.mac_address = v.into();
241 return Ok(());
242 }
243 return Err(common::invalid_data_type_error());
244 }
245 Err(common::write_access_denied_error())
246 }
247
248 fn property_list(&self) -> Cow<'static, [PropertyIdentifier]> {
249 static PROPS: &[PropertyIdentifier] = &[
250 PropertyIdentifier::OBJECT_IDENTIFIER,
251 PropertyIdentifier::OBJECT_NAME,
252 PropertyIdentifier::DESCRIPTION,
253 PropertyIdentifier::OBJECT_TYPE,
254 PropertyIdentifier::STATUS_FLAGS,
255 PropertyIdentifier::OUT_OF_SERVICE,
256 PropertyIdentifier::RELIABILITY,
257 PropertyIdentifier::NETWORK_TYPE,
258 PropertyIdentifier::NETWORK_NUMBER,
259 PropertyIdentifier::MAC_ADDRESS,
260 PropertyIdentifier::MAX_APDU_LENGTH_ACCEPTED,
261 PropertyIdentifier::LINK_SPEED,
262 PropertyIdentifier::CHANGES_PENDING,
263 PropertyIdentifier::COMMAND_NP,
264 PropertyIdentifier::IP_ADDRESS,
265 PropertyIdentifier::IP_DEFAULT_GATEWAY,
266 PropertyIdentifier::IP_SUBNET_MASK,
267 PropertyIdentifier::BACNET_IP_UDP_PORT,
268 ];
269 Cow::Borrowed(PROPS)
270 }
271}
272
273#[cfg(test)]
274mod tests {
275 use super::*;
276
277 #[test]
278 fn object_type_is_network_port() {
279 let np = NetworkPortObject::new(1, "NP-1", 0).unwrap();
280 assert_eq!(
281 np.object_identifier().object_type(),
282 ObjectType::NETWORK_PORT
283 );
284 assert_eq!(np.object_identifier().instance_number(), 1);
285 }
286
287 #[test]
288 fn read_object_name() {
289 let np = NetworkPortObject::new(1, "NP-1", 0).unwrap();
290 let val = np
291 .read_property(PropertyIdentifier::OBJECT_NAME, None)
292 .unwrap();
293 assert_eq!(val, PropertyValue::CharacterString("NP-1".to_string()));
294 }
295
296 #[test]
297 fn read_object_type() {
298 let np = NetworkPortObject::new(1, "NP-1", 0).unwrap();
299 let val = np
300 .read_property(PropertyIdentifier::OBJECT_TYPE, None)
301 .unwrap();
302 assert_eq!(
303 val,
304 PropertyValue::Enumerated(ObjectType::NETWORK_PORT.to_raw())
305 );
306 }
307
308 #[test]
309 fn read_network_type() {
310 let np = NetworkPortObject::new(1, "NP-1", 0).unwrap();
311 let val = np
312 .read_property(PropertyIdentifier::NETWORK_TYPE, None)
313 .unwrap();
314 assert_eq!(val, PropertyValue::Enumerated(0)); }
316
317 #[test]
318 fn read_network_number_default() {
319 let np = NetworkPortObject::new(1, "NP-1", 0).unwrap();
320 let val = np
321 .read_property(PropertyIdentifier::NETWORK_NUMBER, None)
322 .unwrap();
323 assert_eq!(val, PropertyValue::Unsigned(0));
324 }
325
326 #[test]
327 fn read_max_apdu_length() {
328 let np = NetworkPortObject::new(1, "NP-1", 0).unwrap();
329 let val = np
330 .read_property(PropertyIdentifier::MAX_APDU_LENGTH_ACCEPTED, None)
331 .unwrap();
332 assert_eq!(val, PropertyValue::Unsigned(1476));
333 }
334
335 #[test]
336 fn read_link_speed_default() {
337 let np = NetworkPortObject::new(1, "NP-1", 0).unwrap();
338 let val = np
339 .read_property(PropertyIdentifier::LINK_SPEED, None)
340 .unwrap();
341 assert_eq!(val, PropertyValue::Real(0.0));
342 }
343
344 #[test]
345 fn read_changes_pending_default() {
346 let np = NetworkPortObject::new(1, "NP-1", 0).unwrap();
347 let val = np
348 .read_property(PropertyIdentifier::CHANGES_PENDING, None)
349 .unwrap();
350 assert_eq!(val, PropertyValue::Boolean(false));
351 }
352
353 #[test]
354 fn read_command_default() {
355 let np = NetworkPortObject::new(1, "NP-1", 0).unwrap();
356 let val = np
357 .read_property(PropertyIdentifier::COMMAND_NP, None)
358 .unwrap();
359 assert_eq!(val, PropertyValue::Enumerated(0)); }
361
362 #[test]
363 fn read_ip_address_default() {
364 let np = NetworkPortObject::new(1, "NP-1", 0).unwrap();
365 let val = np
366 .read_property(PropertyIdentifier::IP_ADDRESS, None)
367 .unwrap();
368 assert_eq!(val, PropertyValue::OctetString(vec![0, 0, 0, 0]));
369 }
370
371 #[test]
372 fn read_ip_default_gateway_default() {
373 let np = NetworkPortObject::new(1, "NP-1", 0).unwrap();
374 let val = np
375 .read_property(PropertyIdentifier::IP_DEFAULT_GATEWAY, None)
376 .unwrap();
377 assert_eq!(val, PropertyValue::OctetString(vec![0, 0, 0, 0]));
378 }
379
380 #[test]
381 fn read_ip_subnet_mask_default() {
382 let np = NetworkPortObject::new(1, "NP-1", 0).unwrap();
383 let val = np
384 .read_property(PropertyIdentifier::IP_SUBNET_MASK, None)
385 .unwrap();
386 assert_eq!(val, PropertyValue::OctetString(vec![255, 255, 255, 0]));
387 }
388
389 #[test]
390 fn read_udp_port_default() {
391 let np = NetworkPortObject::new(1, "NP-1", 0).unwrap();
392 let val = np
393 .read_property(PropertyIdentifier::BACNET_IP_UDP_PORT, None)
394 .unwrap();
395 assert_eq!(val, PropertyValue::Unsigned(0xBAC0));
396 }
397
398 #[test]
399 fn write_command() {
400 let mut np = NetworkPortObject::new(1, "NP-1", 0).unwrap();
401 np.write_property(
402 PropertyIdentifier::COMMAND_NP,
403 None,
404 PropertyValue::Enumerated(1), None,
406 )
407 .unwrap();
408 let val = np
409 .read_property(PropertyIdentifier::COMMAND_NP, None)
410 .unwrap();
411 assert_eq!(val, PropertyValue::Enumerated(1));
412 }
413
414 #[test]
415 fn write_command_wrong_type() {
416 let mut np = NetworkPortObject::new(1, "NP-1", 0).unwrap();
417 let result = np.write_property(
418 PropertyIdentifier::COMMAND_NP,
419 None,
420 PropertyValue::Unsigned(1),
421 None,
422 );
423 assert!(result.is_err());
424 }
425
426 #[test]
427 fn write_ip_address_sets_changes_pending() {
428 let mut np = NetworkPortObject::new(1, "NP-1", 0).unwrap();
429 assert_eq!(
430 np.read_property(PropertyIdentifier::CHANGES_PENDING, None)
431 .unwrap(),
432 PropertyValue::Boolean(false)
433 );
434
435 np.write_property(
436 PropertyIdentifier::IP_ADDRESS,
437 None,
438 PropertyValue::OctetString(vec![192, 168, 1, 100]),
439 None,
440 )
441 .unwrap();
442
443 assert_eq!(
444 np.read_property(PropertyIdentifier::IP_ADDRESS, None)
445 .unwrap(),
446 PropertyValue::OctetString(vec![192, 168, 1, 100])
447 );
448 assert_eq!(
449 np.read_property(PropertyIdentifier::CHANGES_PENDING, None)
450 .unwrap(),
451 PropertyValue::Boolean(true)
452 );
453 }
454
455 #[test]
456 fn write_ip_default_gateway_sets_changes_pending() {
457 let mut np = NetworkPortObject::new(1, "NP-1", 0).unwrap();
458 np.write_property(
459 PropertyIdentifier::IP_DEFAULT_GATEWAY,
460 None,
461 PropertyValue::OctetString(vec![192, 168, 1, 1]),
462 None,
463 )
464 .unwrap();
465
466 assert_eq!(
467 np.read_property(PropertyIdentifier::IP_DEFAULT_GATEWAY, None)
468 .unwrap(),
469 PropertyValue::OctetString(vec![192, 168, 1, 1])
470 );
471 assert_eq!(
472 np.read_property(PropertyIdentifier::CHANGES_PENDING, None)
473 .unwrap(),
474 PropertyValue::Boolean(true)
475 );
476 }
477
478 #[test]
479 fn write_ip_subnet_mask_sets_changes_pending() {
480 let mut np = NetworkPortObject::new(1, "NP-1", 0).unwrap();
481 np.write_property(
482 PropertyIdentifier::IP_SUBNET_MASK,
483 None,
484 PropertyValue::OctetString(vec![255, 255, 0, 0]),
485 None,
486 )
487 .unwrap();
488
489 assert_eq!(
490 np.read_property(PropertyIdentifier::IP_SUBNET_MASK, None)
491 .unwrap(),
492 PropertyValue::OctetString(vec![255, 255, 0, 0])
493 );
494 assert_eq!(
495 np.read_property(PropertyIdentifier::CHANGES_PENDING, None)
496 .unwrap(),
497 PropertyValue::Boolean(true)
498 );
499 }
500
501 #[test]
502 fn write_udp_port_sets_changes_pending() {
503 let mut np = NetworkPortObject::new(1, "NP-1", 0).unwrap();
504 np.write_property(
505 PropertyIdentifier::BACNET_IP_UDP_PORT,
506 None,
507 PropertyValue::Unsigned(47809),
508 None,
509 )
510 .unwrap();
511
512 assert_eq!(
513 np.read_property(PropertyIdentifier::BACNET_IP_UDP_PORT, None)
514 .unwrap(),
515 PropertyValue::Unsigned(47809)
516 );
517 assert_eq!(
518 np.read_property(PropertyIdentifier::CHANGES_PENDING, None)
519 .unwrap(),
520 PropertyValue::Boolean(true)
521 );
522 }
523
524 #[test]
525 fn write_udp_port_out_of_range() {
526 let mut np = NetworkPortObject::new(1, "NP-1", 0).unwrap();
527 let result = np.write_property(
528 PropertyIdentifier::BACNET_IP_UDP_PORT,
529 None,
530 PropertyValue::Unsigned(70000),
531 None,
532 );
533 assert!(result.is_err());
534 }
535
536 #[test]
537 fn write_udp_port_wrong_type() {
538 let mut np = NetworkPortObject::new(1, "NP-1", 0).unwrap();
539 let result = np.write_property(
540 PropertyIdentifier::BACNET_IP_UDP_PORT,
541 None,
542 PropertyValue::Real(47808.0),
543 None,
544 );
545 assert!(result.is_err());
546 }
547
548 #[test]
549 fn write_network_number() {
550 let mut np = NetworkPortObject::new(1, "NP-1", 0).unwrap();
551 np.write_property(
552 PropertyIdentifier::NETWORK_NUMBER,
553 None,
554 PropertyValue::Unsigned(5),
555 None,
556 )
557 .unwrap();
558 assert_eq!(
559 np.read_property(PropertyIdentifier::NETWORK_NUMBER, None)
560 .unwrap(),
561 PropertyValue::Unsigned(5)
562 );
563 }
564
565 #[test]
566 fn write_mac_address() {
567 let mut np = NetworkPortObject::new(1, "NP-1", 0).unwrap();
568 let mac = vec![0xDE, 0xAD, 0xBE, 0xEF, 0x00, 0x01];
569 np.write_property(
570 PropertyIdentifier::MAC_ADDRESS,
571 None,
572 PropertyValue::OctetString(mac.clone()),
573 None,
574 )
575 .unwrap();
576 assert_eq!(
577 np.read_property(PropertyIdentifier::MAC_ADDRESS, None)
578 .unwrap(),
579 PropertyValue::OctetString(mac)
580 );
581 }
582
583 #[test]
584 fn write_out_of_service() {
585 let mut np = NetworkPortObject::new(1, "NP-1", 0).unwrap();
586 np.write_property(
587 PropertyIdentifier::OUT_OF_SERVICE,
588 None,
589 PropertyValue::Boolean(true),
590 None,
591 )
592 .unwrap();
593 assert_eq!(
594 np.read_property(PropertyIdentifier::OUT_OF_SERVICE, None)
595 .unwrap(),
596 PropertyValue::Boolean(true)
597 );
598 }
599
600 #[test]
601 fn write_description() {
602 let mut np = NetworkPortObject::new(1, "NP-1", 0).unwrap();
603 np.write_property(
604 PropertyIdentifier::DESCRIPTION,
605 None,
606 PropertyValue::CharacterString("Main Ethernet port".to_string()),
607 None,
608 )
609 .unwrap();
610 assert_eq!(
611 np.read_property(PropertyIdentifier::DESCRIPTION, None)
612 .unwrap(),
613 PropertyValue::CharacterString("Main Ethernet port".to_string())
614 );
615 }
616
617 #[test]
618 fn write_read_only_property_denied() {
619 let mut np = NetworkPortObject::new(1, "NP-1", 0).unwrap();
620 let result = np.write_property(
622 PropertyIdentifier::LINK_SPEED,
623 None,
624 PropertyValue::Real(100_000_000.0),
625 None,
626 );
627 assert!(result.is_err());
628 }
629
630 #[test]
631 fn read_unknown_property() {
632 let np = NetworkPortObject::new(1, "NP-1", 0).unwrap();
633 let result = np.read_property(PropertyIdentifier::PRESENT_VALUE, None);
634 assert!(result.is_err());
635 }
636
637 #[test]
638 fn property_list_complete() {
639 let np = NetworkPortObject::new(1, "NP-1", 0).unwrap();
640 let props = np.property_list();
641 assert!(props.contains(&PropertyIdentifier::OBJECT_IDENTIFIER));
642 assert!(props.contains(&PropertyIdentifier::OBJECT_NAME));
643 assert!(props.contains(&PropertyIdentifier::OBJECT_TYPE));
644 assert!(props.contains(&PropertyIdentifier::NETWORK_TYPE));
645 assert!(props.contains(&PropertyIdentifier::NETWORK_NUMBER));
646 assert!(props.contains(&PropertyIdentifier::MAC_ADDRESS));
647 assert!(props.contains(&PropertyIdentifier::MAX_APDU_LENGTH_ACCEPTED));
648 assert!(props.contains(&PropertyIdentifier::LINK_SPEED));
649 assert!(props.contains(&PropertyIdentifier::CHANGES_PENDING));
650 assert!(props.contains(&PropertyIdentifier::COMMAND_NP));
651 assert!(props.contains(&PropertyIdentifier::IP_ADDRESS));
652 assert!(props.contains(&PropertyIdentifier::IP_DEFAULT_GATEWAY));
653 assert!(props.contains(&PropertyIdentifier::IP_SUBNET_MASK));
654 assert!(props.contains(&PropertyIdentifier::BACNET_IP_UDP_PORT));
655 }
656
657 #[test]
658 fn setter_methods_work() {
659 let mut np = NetworkPortObject::new(1, "NP-1", 0).unwrap();
660 np.set_ip_address(vec![10, 0, 0, 1]);
661 np.set_ip_default_gateway(vec![10, 0, 0, 254]);
662 np.set_ip_subnet_mask(vec![255, 255, 255, 0]);
663 np.set_mac_address(MacAddr::from_slice(&[0x00, 0x1A, 0x2B, 0x3C, 0x4D, 0x5E]));
664 np.set_network_number(7);
665 np.set_link_speed(100_000_000.0);
666 np.set_udp_port(47808);
667 np.set_description("Test port");
668
669 assert_eq!(
670 np.read_property(PropertyIdentifier::IP_ADDRESS, None)
671 .unwrap(),
672 PropertyValue::OctetString(vec![10, 0, 0, 1])
673 );
674 assert_eq!(
675 np.read_property(PropertyIdentifier::IP_DEFAULT_GATEWAY, None)
676 .unwrap(),
677 PropertyValue::OctetString(vec![10, 0, 0, 254])
678 );
679 assert_eq!(
680 np.read_property(PropertyIdentifier::NETWORK_NUMBER, None)
681 .unwrap(),
682 PropertyValue::Unsigned(7)
683 );
684 assert_eq!(
685 np.read_property(PropertyIdentifier::LINK_SPEED, None)
686 .unwrap(),
687 PropertyValue::Real(100_000_000.0)
688 );
689 assert_eq!(
690 np.read_property(PropertyIdentifier::BACNET_IP_UDP_PORT, None)
691 .unwrap(),
692 PropertyValue::Unsigned(47808)
693 );
694 }
695
696 #[test]
697 fn mstp_network_type() {
698 let np = NetworkPortObject::new(2, "NP-MSTP", 2).unwrap();
699 assert_eq!(
700 np.read_property(PropertyIdentifier::NETWORK_TYPE, None)
701 .unwrap(),
702 PropertyValue::Enumerated(2) );
704 }
705
706 #[test]
707 fn full_network_config_scenario() {
708 let mut np = NetworkPortObject::new(1, "Ethernet-1", 0).unwrap();
709
710 np.set_ip_address(vec![192, 168, 1, 100]);
712 np.set_ip_default_gateway(vec![192, 168, 1, 1]);
713 np.set_ip_subnet_mask(vec![255, 255, 255, 0]);
714 np.set_mac_address(MacAddr::from_slice(&[0x00, 0x50, 0x56, 0xAB, 0xCD, 0xEF]));
715 np.set_network_number(1);
716 np.set_link_speed(1_000_000_000.0); np.set_udp_port(0xBAC0);
718
719 assert_eq!(np.object_name(), "Ethernet-1");
721 assert_eq!(
722 np.read_property(PropertyIdentifier::IP_ADDRESS, None)
723 .unwrap(),
724 PropertyValue::OctetString(vec![192, 168, 1, 100])
725 );
726 assert_eq!(
727 np.read_property(PropertyIdentifier::LINK_SPEED, None)
728 .unwrap(),
729 PropertyValue::Real(1_000_000_000.0)
730 );
731 assert_eq!(
732 np.read_property(PropertyIdentifier::MAC_ADDRESS, None)
733 .unwrap(),
734 PropertyValue::OctetString(vec![0x00, 0x50, 0x56, 0xAB, 0xCD, 0xEF])
735 );
736
737 np.write_property(
739 PropertyIdentifier::IP_ADDRESS,
740 None,
741 PropertyValue::OctetString(vec![10, 0, 0, 50]),
742 None,
743 )
744 .unwrap();
745 assert_eq!(
746 np.read_property(PropertyIdentifier::CHANGES_PENDING, None)
747 .unwrap(),
748 PropertyValue::Boolean(true)
749 );
750
751 np.write_property(
753 PropertyIdentifier::COMMAND_NP,
754 None,
755 PropertyValue::Enumerated(1), None,
757 )
758 .unwrap();
759 assert_eq!(
760 np.read_property(PropertyIdentifier::COMMAND_NP, None)
761 .unwrap(),
762 PropertyValue::Enumerated(1)
763 );
764 }
765}