45
45
logger = logging .getLogger (__name__ )
46
46
47
47
48
- class TC_SwitchTests (MatterBaseTest ):
49
- def __init__ (self , * args , ** kwargs ):
50
- super ().__init__ (* args , ** kwargs )
48
+ def bump_substep (step : str ) -> str :
49
+ """Given a string like "5a", bump it to "5b", or "6c" to "6d" """
50
+ if len (step ) == 0 :
51
+ raise ValueError ("Can't bump empty steps!" )
51
52
52
- def desc_TC_SWTCH_2_4 ( self ) -> str :
53
- """Returns a description of this test"""
54
- return "[TC-SWTCH-2.4] Momentary Switch Long Press Verification "
53
+ end_char = step [ - 1 ]
54
+ if not end_char . isalpha ():
55
+ return step + "a "
55
56
56
- # TODO(#34656): Fill test steps
57
- # def steps_TC_SWTCH_2_4(self) -> list[TestStep]:
58
- # steps = [
59
- # TestStep("0", "Commissioning, already done", is_commissioning=True),
60
- # # TODO: fill when test is done
61
- # ]
57
+ step_prefix = step [:- 1 ]
58
+ next_end_char = chr (ord (end_char ) + 1 )
59
+ if ord (next_end_char ) > ord ('z' ):
60
+ raise ValueError (f"Reached max substep for step '{ step } '" )
61
+ next_step = step_prefix + next_end_char
62
62
63
- # return steps
63
+ return next_step
64
+
65
+
66
+ class TC_SwitchTests (MatterBaseTest ):
67
+ def __init__ (self , * args , ** kwargs ):
68
+ super ().__init__ (* args , ** kwargs )
69
+ self ._default_pressed_position = self .user_params .get ("default_pressed_position" , 1 )
64
70
65
71
def _send_named_pipe_command (self , command_dict : dict [str , Any ]):
66
72
app_pid = self .matter_test_config .app_pid
@@ -164,14 +170,6 @@ def _ask_for_release(self):
164
170
else :
165
171
time .sleep (self .keep_pressed_delay / 1000 )
166
172
167
- def _placeholder_for_step (self , step_id : str ):
168
- # TODO(#34656): Global search an replace of `self._placeholder_for_step` with `self.step` when done.
169
- logging .info (f"Step { step_id } " )
170
- pass
171
-
172
- def _placeholder_for_skip (self , step_id : str ):
173
- logging .info (f"Skipped step { step_id } " )
174
-
175
173
def _await_sequence_of_reports (self , report_queue : queue .Queue , endpoint_id : int , attribute : TypedAttributePath , sequence : list [Any ], timeout_sec : float ):
176
174
start_time = time .time ()
177
175
elapsed = 0.0
@@ -269,93 +267,6 @@ def _expect_no_events_for_cluster(self, event_queue: queue.Queue, endpoint_id: i
269
267
270
268
logging .info (f"Successfully waited for no further events on { expected_cluster } for { elapsed :.1f} seconds" )
271
269
272
- @per_endpoint_test (has_feature (Clusters .Switch , Clusters .Switch .Bitmaps .Feature .kMomentarySwitch ))
273
- async def test_TC_SWTCH_2_4 (self ):
274
- # TODO(#34656): Make this come from PIXIT
275
- switch_pressed_position = 1
276
- post_prompt_settle_delay_seconds = 10.0
277
-
278
- # Commission DUT - already done
279
-
280
- # Read feature map to set bool markers
281
- cluster = Clusters .Objects .Switch
282
- feature_map = await self .read_single_attribute_check_success (cluster , attribute = cluster .Attributes .FeatureMap )
283
-
284
- has_ms_feature = (feature_map & cluster .Bitmaps .Feature .kMomentarySwitch ) != 0
285
- has_msr_feature = (feature_map & cluster .Bitmaps .Feature .kMomentarySwitchRelease ) != 0
286
- has_msl_feature = (feature_map & cluster .Bitmaps .Feature .kMomentarySwitchLongPress ) != 0
287
- has_as_feature = (feature_map & cluster .Bitmaps .Feature .kActionSwitch ) != 0
288
- # has_msm_feature = (feature_map & cluster.Bitmaps.Feature.kMomentarySwitchMultiPress) != 0
289
-
290
- if not has_ms_feature :
291
- logging .info ("Skipping rest of test: SWTCH.S.F01(MS) feature not present" )
292
- self .skip_all_remaining_steps ("2" )
293
-
294
- endpoint_id = self .matter_test_config .endpoint
295
-
296
- # Step 1: Set up subscription to all Switch cluster events
297
- self ._placeholder_for_step ("1" )
298
- event_listener = EventChangeCallback (cluster )
299
- attrib_listener = ClusterAttributeChangeAccumulator (cluster )
300
- await event_listener .start (self .default_controller , self .dut_node_id , endpoint = endpoint_id )
301
- await attrib_listener .start (self .default_controller , self .dut_node_id , endpoint = endpoint_id )
302
-
303
- # Step 2: Operator does not operate switch on the DUT
304
- self ._placeholder_for_step ("2" )
305
- self ._ask_for_switch_idle ()
306
-
307
- # Step 3: TH reads the CurrentPosition attribute from the DUT
308
- self ._placeholder_for_step ("3" )
309
-
310
- # Verify that the value is 0
311
- current_position = await self .read_single_attribute_check_success (cluster , attribute = cluster .Attributes .CurrentPosition )
312
- asserts .assert_equal (current_position , 0 )
313
-
314
- # Step 4a: Operator operates switch (keep pressed for long time, e.g. 5 seconds) on the DUT, the release it
315
- self ._placeholder_for_step ("4a" )
316
- self ._ask_for_long_press (endpoint_id , switch_pressed_position , feature_map )
317
-
318
- # Step 4b: TH expects report of CurrentPosition 1, followed by a report of Current Position 0.
319
- self ._placeholder_for_step ("4b" )
320
- logging .info (
321
- f"Starting to wait for { post_prompt_settle_delay_seconds :.1f} seconds for CurrentPosition to go { switch_pressed_position } , then 0." )
322
- self ._await_sequence_of_reports (report_queue = attrib_listener .attribute_queue , endpoint_id = endpoint_id , attribute = cluster .Attributes .CurrentPosition , sequence = [
323
- switch_pressed_position , 0 ], timeout_sec = post_prompt_settle_delay_seconds )
324
-
325
- # Step 4c: TH expects at least InitialPress with NewPosition = 1
326
- self ._placeholder_for_step ("4c" )
327
- logging .info (f"Starting to wait for { post_prompt_settle_delay_seconds :.1f} seconds for InitialPress event." )
328
- expected_events = [cluster .Events .InitialPress (newPosition = switch_pressed_position )]
329
- self ._await_sequence_of_events (event_queue = event_listener .event_queue , endpoint_id = endpoint_id ,
330
- sequence = expected_events , timeout_sec = post_prompt_settle_delay_seconds )
331
-
332
- # Step 4d: For MSL/AS, expect to see LongPress/LongRelease in that order
333
- if not has_msl_feature and not has_as_feature :
334
- logging .info ("Skipping Step 4d due to missing MSL and AS features" )
335
- self ._placeholder_for_skip ("4d" )
336
- else :
337
- # Steb 4d: TH expects report of LongPress, LongRelease in that order.
338
- self ._placeholder_for_step ("4d" )
339
- logging .info (f"Starting to wait for { post_prompt_settle_delay_seconds :.1f} seconds for LongPress then LongRelease." )
340
- expected_events = []
341
- expected_events .append (cluster .Events .LongPress (newPosition = switch_pressed_position ))
342
- expected_events .append (cluster .Events .LongRelease (previousPosition = switch_pressed_position ))
343
- self ._await_sequence_of_events (event_queue = event_listener .event_queue , endpoint_id = endpoint_id ,
344
- sequence = expected_events , timeout_sec = post_prompt_settle_delay_seconds )
345
-
346
- # Step 4e: For MS & (!MSL & !AS & !MSR), expect no further events for 10 seconds.
347
- if not has_msl_feature and not has_as_feature and not has_msr_feature :
348
- self ._placeholder_for_step ("4e" )
349
- self ._expect_no_events_for_cluster (event_queue = event_listener .event_queue ,
350
- endpoint_id = endpoint_id , expected_cluster = cluster , timeout_sec = 10.0 )
351
-
352
- # Step 4f: For MSR & not MSL, expect to see ShortRelease.
353
- if not has_msl_feature and has_msr_feature :
354
- self ._placeholder_for_step ("4f" )
355
- expected_events = [cluster .Events .ShortRelease (previousPosition = switch_pressed_position )]
356
- self ._await_sequence_of_events (event_queue = event_listener .event_queue , endpoint_id = endpoint_id ,
357
- sequence = expected_events , timeout_sec = post_prompt_settle_delay_seconds )
358
-
359
270
def _received_event (self , event_listener : EventChangeCallback , target_event : ClusterObjects .ClusterEvent , timeout_s : int ) -> bool :
360
271
"""
361
272
Returns true if this event was received, false otherwise
@@ -534,6 +445,104 @@ async def test_TC_SWTCH_2_3(self):
534
445
button_val = await self .read_single_attribute_check_success (cluster = cluster , attribute = cluster .Attributes .CurrentPosition )
535
446
asserts .assert_equal (button_val , 0 , "Button value is not 0" )
536
447
448
+ def desc_TC_SWTCH_2_4 (self ) -> str :
449
+ return "[TC-SWTCH-2.4] Momentary Switch Long Press Verification"
450
+
451
+ def steps_TC_SWTCH_2_4 (self ):
452
+ return [TestStep (1 , test_plan_support .commission_if_required (), "" , is_commissioning = True ),
453
+ TestStep (2 , "Set up subscription to all events of Switch cluster on the endpoint" ),
454
+ TestStep (3 , "Operator does not operate switch on the DUT" ),
455
+ TestStep (4 , "TH reads the CurrentPosition attribute from the DUT" , "Verify that the value is 0" ),
456
+ TestStep (5 , "Operator operates switch (keep pressed for long time, e.g. 5 seconds) on the DUT, the release it" ,
457
+ """
458
+ * TH expects receiving a subscription report of CurrentPosition 1, followed by a report of Current Position 0.
459
+ * TH expects receiving at InitialPress event with NewPosition = 1.
460
+ * if MSL or AS feature is supported, TH expect receiving LongPress/LongRelease in that order.
461
+ * if MS & (!MSL & !AS & !MSR) features present, TH expects receiving no further events for 10 seconds after release.
462
+ * if (MSR & !MSL) features present, TH expects receiving ShortRelease event.
463
+ """ )
464
+ ]
465
+
466
+ @per_endpoint_test (has_feature (Clusters .Switch , Clusters .Switch .Bitmaps .Feature .kMomentarySwitch ))
467
+ async def test_TC_SWTCH_2_4 (self ):
468
+ switch_pressed_position = self ._default_pressed_position
469
+ post_prompt_settle_delay_seconds = 10.0
470
+
471
+ endpoint_id = self .matter_test_config .endpoint
472
+ cluster = Clusters .Objects .Switch
473
+
474
+ # Step 1: Commission DUT - already done
475
+ self .step (1 )
476
+
477
+ # Read feature map to set bool markers
478
+ feature_map = await self .read_single_attribute_check_success (cluster , attribute = cluster .Attributes .FeatureMap )
479
+
480
+ has_ms_feature = (feature_map & cluster .Bitmaps .Feature .kMomentarySwitch ) != 0
481
+ has_msr_feature = (feature_map & cluster .Bitmaps .Feature .kMomentarySwitchRelease ) != 0
482
+ has_msl_feature = (feature_map & cluster .Bitmaps .Feature .kMomentarySwitchLongPress ) != 0
483
+ has_as_feature = (feature_map & cluster .Bitmaps .Feature .kActionSwitch ) != 0
484
+
485
+ if not has_ms_feature :
486
+ logging .info ("Skipping rest of test: SWTCH.S.F01(MS) feature not present" )
487
+ self .skip_all_remaining_steps ("2" )
488
+
489
+ # Step 2: Set up subscription to all events of Switch cluster on the endpoint
490
+ self .step (2 )
491
+ event_listener = EventChangeCallback (cluster )
492
+ attrib_listener = ClusterAttributeChangeAccumulator (cluster )
493
+ await event_listener .start (self .default_controller , self .dut_node_id , endpoint = endpoint_id )
494
+ await attrib_listener .start (self .default_controller , self .dut_node_id , endpoint = endpoint_id )
495
+
496
+ # Step 3: Operator does not operate switch on the DUT
497
+ self .step (3 )
498
+ self ._ask_for_switch_idle ()
499
+
500
+ # Step 4: TH reads the CurrentPosition attribute from the DUT
501
+ self .step (4 )
502
+
503
+ # Verify that the value is 0
504
+ current_position = await self .read_single_attribute_check_success (cluster , attribute = cluster .Attributes .CurrentPosition )
505
+ asserts .assert_equal (current_position , 0 )
506
+
507
+ # Step 5: Operator operates switch (keep pressed for long time, e.g. 5 seconds) on the DUT, the release it
508
+ self .step (5 )
509
+ self ._ask_for_long_press (endpoint_id , switch_pressed_position , feature_map )
510
+
511
+ # - TH expects report of CurrentPosition 1, followed by a report of Current Position 0.
512
+ logging .info (
513
+ f"Starting to wait for { post_prompt_settle_delay_seconds :.1f} seconds for CurrentPosition to go { switch_pressed_position } , then 0." )
514
+ self ._await_sequence_of_reports (report_queue = attrib_listener .attribute_queue , endpoint_id = endpoint_id , attribute = cluster .Attributes .CurrentPosition , sequence = [
515
+ switch_pressed_position , 0 ], timeout_sec = post_prompt_settle_delay_seconds )
516
+
517
+ # - TH expects at least InitialPress with NewPosition = 1
518
+ logging .info (f"Starting to wait for { post_prompt_settle_delay_seconds :.1f} seconds for InitialPress event." )
519
+ expected_events = [cluster .Events .InitialPress (newPosition = switch_pressed_position )]
520
+ self ._await_sequence_of_events (event_queue = event_listener .event_queue , endpoint_id = endpoint_id ,
521
+ sequence = expected_events , timeout_sec = post_prompt_settle_delay_seconds )
522
+
523
+ # - if MSL or AS feature is supported, expect to see LongPress/LongRelease in that order.
524
+ if not has_msl_feature and not has_as_feature :
525
+ logging .info ("Since MSL and AS features both unsupported, skipping check for LongPress/LongRelease" )
526
+ else :
527
+ # - TH expects report of LongPress, LongRelease in that order.
528
+ logging .info (f"Starting to wait for { post_prompt_settle_delay_seconds :.1f} seconds for LongPress then LongRelease." )
529
+ expected_events = []
530
+ expected_events .append (cluster .Events .LongPress (newPosition = switch_pressed_position ))
531
+ expected_events .append (cluster .Events .LongRelease (previousPosition = switch_pressed_position ))
532
+ self ._await_sequence_of_events (event_queue = event_listener .event_queue , endpoint_id = endpoint_id ,
533
+ sequence = expected_events , timeout_sec = post_prompt_settle_delay_seconds )
534
+
535
+ # - if MS & (!MSL & !AS & !MSR) features present, expect no further events for 10 seconds after release.
536
+ if not has_msl_feature and not has_as_feature and not has_msr_feature :
537
+ self ._expect_no_events_for_cluster (event_queue = event_listener .event_queue ,
538
+ endpoint_id = endpoint_id , expected_cluster = cluster , timeout_sec = 10.0 )
539
+
540
+ # - if (MSR & !MSL) features present, expect to see ShortRelease event.
541
+ if not has_msl_feature and has_msr_feature :
542
+ expected_events = [cluster .Events .ShortRelease (previousPosition = switch_pressed_position )]
543
+ self ._await_sequence_of_events (event_queue = event_listener .event_queue , endpoint_id = endpoint_id ,
544
+ sequence = expected_events , timeout_sec = post_prompt_settle_delay_seconds )
545
+
537
546
def steps_TC_SWTCH_2_5 (self ):
538
547
return [TestStep (1 , test_plan_support .commission_if_required (), "" , is_commissioning = True ),
539
548
TestStep (2 , "Set up a subscription to all Switch cluster events" ),
@@ -638,7 +647,7 @@ async def test_TC_SWTCH_2_5(self):
638
647
multi_press_max = await self .read_single_attribute_check_success (cluster , attribute = cluster .Attributes .MultiPressMax )
639
648
640
649
endpoint_id = self .matter_test_config .endpoint
641
- pressed_position = 1
650
+ pressed_position = self . _default_pressed_position
642
651
643
652
self .step (2 )
644
653
event_listener = EventChangeCallback (cluster )
@@ -657,35 +666,35 @@ def test_multi_press_sequence(starting_step: str, count: int, short_long: bool =
657
666
else :
658
667
self ._ask_for_multi_press (endpoint_id , number_of_presses = count , pressed_position = pressed_position ,
659
668
feature_map = feature_map , multi_press_max = multi_press_max )
660
- for i in range (count ):
669
+ for pos_idx in range (count ):
661
670
event = event_listener .wait_for_event_report (cluster .Events .InitialPress )
662
671
asserts .assert_equal (event .newPosition , pressed_position , "Unexpected NewPosition on InitialEvent" )
663
- if i > 0 :
672
+ if pos_idx > 0 :
664
673
event = event_listener .wait_for_event_report (cluster .Events .MultiPressOngoing )
665
674
asserts .assert_equal (event .newPosition , pressed_position , "Unexpected NewPosition on MultiPressOngoing" )
666
- asserts .assert_equal (event .currentNumberOfPressesCounted , i + 1 ,
675
+ asserts .assert_equal (event .currentNumberOfPressesCounted , pos_idx + 1 ,
667
676
"Unexpected CurrentNumberOfPressesCounted on MultiPressOngoing" )
668
677
event = event_listener .wait_for_event_report (cluster .Events .ShortRelease )
669
678
asserts .assert_equal (event .previousPosition , pressed_position , "Unexpected PreviousPosition on ShortRelease" )
670
679
671
- step = step [: - 1 ] + chr ( ord ( step [ - 1 ]) + 1 )
680
+ step = bump_substep ( step )
672
681
self .step (step )
673
682
self ._ask_for_switch_idle ()
674
683
event = event_listener .wait_for_event_report (cluster .Events .MultiPressComplete )
675
684
asserts .assert_equal (event .previousPosition , pressed_position , "Unexpected PreviousPosition on MultiPressComplete" )
676
685
asserts .assert_equal (event .totalNumberOfPressesCounted , count , "Unexpected count on MultiPressComplete" )
677
686
678
- test_multi_press_sequence ("4a" , 1 )
687
+ test_multi_press_sequence ("4a" , count = 1 )
679
688
680
- test_multi_press_sequence ("5a" , 2 )
689
+ test_multi_press_sequence ("5a" , count = 2 )
681
690
682
691
self .step ("6a" )
683
692
multi_press_max = await self .read_single_attribute_check_success (cluster = cluster , attribute = cluster .Attributes .MultiPressMax )
684
693
if multi_press_max == 2 :
685
694
self .skip_step ("6b" )
686
695
self .skip_step ("6c" )
687
696
else :
688
- test_multi_press_sequence ("6b" , 3 )
697
+ test_multi_press_sequence ("6b" , count = 3 )
689
698
690
699
if not has_msl_feature :
691
700
self .skip_all_remaining_steps (7 )
@@ -694,7 +703,7 @@ def test_multi_press_sequence(starting_step: str, count: int, short_long: bool =
694
703
self .step (7 )
695
704
# subscription is already set up
696
705
697
- test_multi_press_sequence ("8a" , 2 , short_long = True )
706
+ test_multi_press_sequence ("8a" , count = 2 , short_long = True )
698
707
699
708
self .step ("9a" )
700
709
self ._ask_for_multi_press_long_short (endpoint_id , pressed_position , feature_map )
@@ -813,7 +822,7 @@ async def test_TC_SWTCH_2_6(self):
813
822
multi_press_max = await self .read_single_attribute_check_success (cluster , attribute = cluster .Attributes .MultiPressMax )
814
823
815
824
endpoint_id = self .matter_test_config .endpoint
816
- pressed_position = 1
825
+ pressed_position = self . _default_pressed_position
817
826
818
827
self .step (2 )
819
828
event_listener = EventChangeCallback (cluster )
@@ -836,19 +845,19 @@ def test_multi_press_sequence(starting_step: str, count: int, short_long: bool =
836
845
event = event_listener .wait_for_event_report (cluster .Events .InitialPress )
837
846
asserts .assert_equal (event .newPosition , pressed_position , "Unexpected NewPosition on InitialEvent" )
838
847
839
- step = step [: - 1 ] + chr ( ord ( step [ - 1 ]) + 1 )
848
+ step = bump_substep ( step )
840
849
self .step (step )
841
850
self ._ask_for_switch_idle ()
842
851
event = event_listener .wait_for_event_report (cluster .Events .MultiPressComplete )
843
852
asserts .assert_equal (event .previousPosition , pressed_position , "Unexpected PreviousPosition on MultiPressComplete" )
844
853
expected_count = 0 if count > multi_press_max else count
845
854
asserts .assert_equal (event .totalNumberOfPressesCounted , expected_count , "Unexpected count on MultiPressComplete" )
846
855
847
- test_multi_press_sequence ("4a" , 1 )
856
+ test_multi_press_sequence ("4a" , count = 1 )
848
857
849
- test_multi_press_sequence ("5a" , 2 )
858
+ test_multi_press_sequence ("5a" , count = 2 )
850
859
851
- test_multi_press_sequence ("6a" , multi_press_max + 1 )
860
+ test_multi_press_sequence ("6a" , count = ( multi_press_max + 1 ) )
852
861
853
862
self .step ("7a" )
854
863
if not has_msl_feature :
@@ -857,7 +866,7 @@ def test_multi_press_sequence(starting_step: str, count: int, short_long: bool =
857
866
# subscription is already established
858
867
self .step ("7b" )
859
868
860
- test_multi_press_sequence ("8a" , 2 , short_long = True )
869
+ test_multi_press_sequence ("8a" , count = 2 , short_long = True )
861
870
862
871
self .step ("9a" )
863
872
self ._ask_for_multi_press_long_short (endpoint_id , pressed_position , feature_map )
0 commit comments