@@ -542,7 +542,9 @@ async def test_capability_custom_toggle(hass: HomeAssistant, entry_data: MockCon
542
542
assert cap .new_with_value (v3 ).get_value () is False
543
543
544
544
545
- async def test_capability_custom_range_random_access (hass : HomeAssistant , entry_data : MockConfigEntryData ) -> None :
545
+ async def test_capability_custom_range_random_access_with_range (
546
+ hass : HomeAssistant , entry_data : MockConfigEntryData
547
+ ) -> None :
546
548
state = State ("switch.test" , "30" , {})
547
549
hass .states .async_set (state .entity_id , state .state )
548
550
cap = cast (
@@ -566,14 +568,19 @@ async def test_capability_custom_range_random_access(hass: HomeAssistant, entry_
566
568
),
567
569
},
568
570
CapabilityType .RANGE ,
569
- RangeCapabilityInstance .OPEN ,
571
+ RangeCapabilityInstance .VOLUME ,
570
572
"foo" ,
571
573
),
572
574
)
573
575
assert cap .supported is True
574
576
assert cap .retrievable is True
575
577
assert cap .reportable is True
576
578
assert cap .support_random_access is True
579
+ assert cap .parameters .as_dict () == {
580
+ "instance" : "volume" ,
581
+ "random_access" : True ,
582
+ "range" : {"min" : 10 , "max" : 50 , "precision" : 3 },
583
+ }
577
584
assert cap .get_value () == 30
578
585
579
586
for v in ["55" , "5" ]:
@@ -586,7 +593,7 @@ async def test_capability_custom_range_random_access(hass: HomeAssistant, entry_
586
593
for value , relative in ((40 , False ), (100 , False ), (10 , True ), (- 3 , True ), (- 50 , True )):
587
594
await cap .set_instance_state (
588
595
Context (),
589
- RangeCapabilityInstanceActionState (instance = RangeCapabilityInstance .OPEN , value = value , relative = relative ),
596
+ RangeCapabilityInstanceActionState (instance = RangeCapabilityInstance .VOLUME , value = value , relative = relative ),
590
597
)
591
598
592
599
assert len (calls ) == 5
@@ -606,7 +613,7 @@ async def test_capability_custom_range_random_access(hass: HomeAssistant, entry_
606
613
with pytest .raises (APIError ) as e :
607
614
await cap .set_instance_state (
608
615
Context (),
609
- RangeCapabilityInstanceActionState (instance = RangeCapabilityInstance .OPEN , value = 10 , relative = True ),
616
+ RangeCapabilityInstanceActionState (instance = RangeCapabilityInstance .VOLUME , value = 10 , relative = True ),
610
617
)
611
618
assert e .value .code == ResponseCode .DEVICE_OFF
612
619
assert e .value .message == "Device switch.test probably turned off"
@@ -615,21 +622,81 @@ async def test_capability_custom_range_random_access(hass: HomeAssistant, entry_
615
622
with pytest .raises (APIError ) as e :
616
623
await cap .set_instance_state (
617
624
Context (),
618
- RangeCapabilityInstanceActionState (instance = RangeCapabilityInstance .OPEN , value = 10 , relative = True ),
625
+ RangeCapabilityInstanceActionState (instance = RangeCapabilityInstance .VOLUME , value = 10 , relative = True ),
619
626
)
620
627
assert e .value .code == ResponseCode .NOT_SUPPORTED_IN_CURRENT_MODE
621
- assert e .value .message == "Missing current value for instance open of range capability of foo"
628
+ assert e .value .message == "Missing current value for instance volume of range capability of foo"
622
629
623
630
hass .states .async_remove (state .entity_id )
624
631
with pytest .raises (APIError ) as e :
625
632
await cap .set_instance_state (
626
633
Context (),
627
- RangeCapabilityInstanceActionState (instance = RangeCapabilityInstance .OPEN , value = 10 , relative = True ),
634
+ RangeCapabilityInstanceActionState (instance = RangeCapabilityInstance .VOLUME , value = 10 , relative = True ),
628
635
)
629
636
assert e .value .code == ResponseCode .DEVICE_OFF
630
637
assert e .value .message == "Entity switch.test not found"
631
638
632
639
640
+ async def test_capability_custom_range_random_access_no_range (
641
+ hass : HomeAssistant , entry_data : MockConfigEntryData
642
+ ) -> None :
643
+ state = State ("switch.test" , "30" , {})
644
+ hass .states .async_set (state .entity_id , state .state )
645
+ cap = cast (
646
+ CustomRangeCapability ,
647
+ get_custom_capability (
648
+ hass ,
649
+ entry_data ,
650
+ {
651
+ CONF_ENTITY_CUSTOM_CAPABILITY_STATE_ENTITY_ID : state .entity_id ,
652
+ CONF_ENTITY_CUSTOM_RANGE_SET_VALUE : SERVICE_SCHEMA (
653
+ {
654
+ CONF_SERVICE : "test.set_value" ,
655
+ ATTR_ENTITY_ID : "input_number.test" ,
656
+ CONF_SERVICE_DATA : {"value" : dynamic_template ("value: {{ value|int }}" )},
657
+ }
658
+ ),
659
+ },
660
+ CapabilityType .RANGE ,
661
+ RangeCapabilityInstance .VOLUME ,
662
+ "foo" ,
663
+ ),
664
+ )
665
+ assert cap .supported is True
666
+ assert cap .retrievable is True
667
+ assert cap .reportable is True
668
+ assert cap .support_random_access is True
669
+ assert cap .parameters .as_dict () == {
670
+ "instance" : "volume" ,
671
+ "random_access" : True ,
672
+ }
673
+ assert cap .get_value () == 30
674
+
675
+ for v in [55 , 5 ]:
676
+ hass .states .async_set (state .entity_id , str (v ))
677
+ assert cap .get_value () == v
678
+
679
+ hass .states .async_set (state .entity_id , "30" )
680
+
681
+ calls = async_mock_service (hass , "test" , "set_value" )
682
+ for value , relative in ((40 , False ), (100 , False ), (10 , True ), (- 3 , True ), (- 50 , True ), (100 , True )):
683
+ await cap .set_instance_state (
684
+ Context (),
685
+ RangeCapabilityInstanceActionState (instance = RangeCapabilityInstance .VOLUME , value = value , relative = relative ),
686
+ )
687
+
688
+ assert len (calls ) == 6
689
+ for i in range (0 , len (calls )):
690
+ assert calls [i ].data [ATTR_ENTITY_ID ] == ["input_number.test" ]
691
+
692
+ assert calls [0 ].data ["value" ] == "value: 40"
693
+ assert calls [1 ].data ["value" ] == "value: 100"
694
+ assert calls [2 ].data ["value" ] == "value: 40"
695
+ assert calls [3 ].data ["value" ] == "value: 27"
696
+ assert calls [4 ].data ["value" ] == "value: -20"
697
+ assert calls [5 ].data ["value" ] == "value: 130"
698
+
699
+
633
700
async def test_capability_custom_range_random_access_no_state (
634
701
hass : HomeAssistant , entry_data : MockConfigEntryData
635
702
) -> None :
@@ -664,6 +731,12 @@ async def test_capability_custom_range_random_access_no_state(
664
731
assert cap .retrievable is False
665
732
assert cap .reportable is False
666
733
assert cap .support_random_access is True
734
+ assert cap .parameters .as_dict () == {
735
+ "instance" : "open" ,
736
+ "random_access" : True ,
737
+ "range" : {"min" : 10 , "max" : 50 , "precision" : 3 },
738
+ "unit" : "unit.percent" ,
739
+ }
667
740
assert cap .get_value () is None
668
741
669
742
calls = async_mock_service (hass , "test" , "set_value" )
@@ -865,7 +938,7 @@ async def test_capability_custom_range_no_service(hass: HomeAssistant, entry_dat
865
938
[RangeCapabilityInstance .OPEN , (- 10 , 150 ), (0 , 100 )],
866
939
],
867
940
)
868
- async def test_capability_custom_range_parameters_range (
941
+ async def test_capability_custom_range_limits (
869
942
hass : HomeAssistant ,
870
943
entry_data : MockConfigEntryData ,
871
944
instance : RangeCapabilityInstance ,
@@ -892,3 +965,38 @@ async def test_capability_custom_range_parameters_range(
892
965
assert cap .supported is True
893
966
assert cap .parameters .range
894
967
assert (cap .parameters .range .min , cap .parameters .range .max ) == expected_range
968
+
969
+
970
+ @pytest .mark .parametrize (
971
+ "instance,range_expected" ,
972
+ [
973
+ (RangeCapabilityInstance .BRIGHTNESS , True ),
974
+ (RangeCapabilityInstance .CHANNEL , False ),
975
+ (RangeCapabilityInstance .HUMIDITY , True ),
976
+ (RangeCapabilityInstance .OPEN , True ),
977
+ (RangeCapabilityInstance .TEMPERATURE , True ),
978
+ (RangeCapabilityInstance .VOLUME , False ),
979
+ ],
980
+ )
981
+ async def test_capability_custom_range_requirement (
982
+ hass : HomeAssistant ,
983
+ entry_data : MockConfigEntryData ,
984
+ instance : RangeCapabilityInstance ,
985
+ range_expected : bool ,
986
+ ) -> None :
987
+ cap = cast (
988
+ CustomRangeCapability ,
989
+ get_custom_capability (
990
+ hass ,
991
+ entry_data ,
992
+ {},
993
+ CapabilityType .RANGE ,
994
+ instance ,
995
+ "foo" ,
996
+ ),
997
+ )
998
+ assert cap .supported is True
999
+ if range_expected :
1000
+ assert cap .parameters .range is not None
1001
+ else :
1002
+ assert cap .parameters .range is None
0 commit comments