4545logger = logging .getLogger (__name__ )
4646
4747
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!" )
5152
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 "
5556
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
6262
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 )
6470
6571 def _send_named_pipe_command (self , command_dict : dict [str , Any ]):
6672 app_pid = self .matter_test_config .app_pid
@@ -164,14 +170,6 @@ def _ask_for_release(self):
164170 else :
165171 time .sleep (self .keep_pressed_delay / 1000 )
166172
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-
175173 def _await_sequence_of_reports (self , report_queue : queue .Queue , endpoint_id : int , attribute : TypedAttributePath , sequence : list [Any ], timeout_sec : float ):
176174 start_time = time .time ()
177175 elapsed = 0.0
@@ -269,93 +267,6 @@ def _expect_no_events_for_cluster(self, event_queue: queue.Queue, endpoint_id: i
269267
270268 logging .info (f"Successfully waited for no further events on { expected_cluster } for { elapsed :.1f} seconds" )
271269
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-
359270 def _received_event (self , event_listener : EventChangeCallback , target_event : ClusterObjects .ClusterEvent , timeout_s : int ) -> bool :
360271 """
361272 Returns true if this event was received, false otherwise
@@ -534,6 +445,104 @@ async def test_TC_SWTCH_2_3(self):
534445 button_val = await self .read_single_attribute_check_success (cluster = cluster , attribute = cluster .Attributes .CurrentPosition )
535446 asserts .assert_equal (button_val , 0 , "Button value is not 0" )
536447
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+
537546 def steps_TC_SWTCH_2_5 (self ):
538547 return [TestStep (1 , test_plan_support .commission_if_required (), "" , is_commissioning = True ),
539548 TestStep (2 , "Set up a subscription to all Switch cluster events" ),
@@ -638,7 +647,7 @@ async def test_TC_SWTCH_2_5(self):
638647 multi_press_max = await self .read_single_attribute_check_success (cluster , attribute = cluster .Attributes .MultiPressMax )
639648
640649 endpoint_id = self .matter_test_config .endpoint
641- pressed_position = 1
650+ pressed_position = self . _default_pressed_position
642651
643652 self .step (2 )
644653 event_listener = EventChangeCallback (cluster )
@@ -657,35 +666,35 @@ def test_multi_press_sequence(starting_step: str, count: int, short_long: bool =
657666 else :
658667 self ._ask_for_multi_press (endpoint_id , number_of_presses = count , pressed_position = pressed_position ,
659668 feature_map = feature_map , multi_press_max = multi_press_max )
660- for i in range (count ):
669+ for pos_idx in range (count ):
661670 event = event_listener .wait_for_event_report (cluster .Events .InitialPress )
662671 asserts .assert_equal (event .newPosition , pressed_position , "Unexpected NewPosition on InitialEvent" )
663- if i > 0 :
672+ if pos_idx > 0 :
664673 event = event_listener .wait_for_event_report (cluster .Events .MultiPressOngoing )
665674 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 ,
667676 "Unexpected CurrentNumberOfPressesCounted on MultiPressOngoing" )
668677 event = event_listener .wait_for_event_report (cluster .Events .ShortRelease )
669678 asserts .assert_equal (event .previousPosition , pressed_position , "Unexpected PreviousPosition on ShortRelease" )
670679
671- step = step [: - 1 ] + chr ( ord ( step [ - 1 ]) + 1 )
680+ step = bump_substep ( step )
672681 self .step (step )
673682 self ._ask_for_switch_idle ()
674683 event = event_listener .wait_for_event_report (cluster .Events .MultiPressComplete )
675684 asserts .assert_equal (event .previousPosition , pressed_position , "Unexpected PreviousPosition on MultiPressComplete" )
676685 asserts .assert_equal (event .totalNumberOfPressesCounted , count , "Unexpected count on MultiPressComplete" )
677686
678- test_multi_press_sequence ("4a" , 1 )
687+ test_multi_press_sequence ("4a" , count = 1 )
679688
680- test_multi_press_sequence ("5a" , 2 )
689+ test_multi_press_sequence ("5a" , count = 2 )
681690
682691 self .step ("6a" )
683692 multi_press_max = await self .read_single_attribute_check_success (cluster = cluster , attribute = cluster .Attributes .MultiPressMax )
684693 if multi_press_max == 2 :
685694 self .skip_step ("6b" )
686695 self .skip_step ("6c" )
687696 else :
688- test_multi_press_sequence ("6b" , 3 )
697+ test_multi_press_sequence ("6b" , count = 3 )
689698
690699 if not has_msl_feature :
691700 self .skip_all_remaining_steps (7 )
@@ -694,7 +703,7 @@ def test_multi_press_sequence(starting_step: str, count: int, short_long: bool =
694703 self .step (7 )
695704 # subscription is already set up
696705
697- test_multi_press_sequence ("8a" , 2 , short_long = True )
706+ test_multi_press_sequence ("8a" , count = 2 , short_long = True )
698707
699708 self .step ("9a" )
700709 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):
813822 multi_press_max = await self .read_single_attribute_check_success (cluster , attribute = cluster .Attributes .MultiPressMax )
814823
815824 endpoint_id = self .matter_test_config .endpoint
816- pressed_position = 1
825+ pressed_position = self . _default_pressed_position
817826
818827 self .step (2 )
819828 event_listener = EventChangeCallback (cluster )
@@ -836,19 +845,19 @@ def test_multi_press_sequence(starting_step: str, count: int, short_long: bool =
836845 event = event_listener .wait_for_event_report (cluster .Events .InitialPress )
837846 asserts .assert_equal (event .newPosition , pressed_position , "Unexpected NewPosition on InitialEvent" )
838847
839- step = step [: - 1 ] + chr ( ord ( step [ - 1 ]) + 1 )
848+ step = bump_substep ( step )
840849 self .step (step )
841850 self ._ask_for_switch_idle ()
842851 event = event_listener .wait_for_event_report (cluster .Events .MultiPressComplete )
843852 asserts .assert_equal (event .previousPosition , pressed_position , "Unexpected PreviousPosition on MultiPressComplete" )
844853 expected_count = 0 if count > multi_press_max else count
845854 asserts .assert_equal (event .totalNumberOfPressesCounted , expected_count , "Unexpected count on MultiPressComplete" )
846855
847- test_multi_press_sequence ("4a" , 1 )
856+ test_multi_press_sequence ("4a" , count = 1 )
848857
849- test_multi_press_sequence ("5a" , 2 )
858+ test_multi_press_sequence ("5a" , count = 2 )
850859
851- test_multi_press_sequence ("6a" , multi_press_max + 1 )
860+ test_multi_press_sequence ("6a" , count = ( multi_press_max + 1 ) )
852861
853862 self .step ("7a" )
854863 if not has_msl_feature :
@@ -857,7 +866,7 @@ def test_multi_press_sequence(starting_step: str, count: int, short_long: bool =
857866 # subscription is already established
858867 self .step ("7b" )
859868
860- test_multi_press_sequence ("8a" , 2 , short_long = True )
869+ test_multi_press_sequence ("8a" , count = 2 , short_long = True )
861870
862871 self .step ("9a" )
863872 self ._ask_for_multi_press_long_short (endpoint_id , pressed_position , feature_map )
0 commit comments