@@ -105,7 +105,7 @@ def test_saving_session(my_predbat):
105105 # Example format Sat 25/01
106106 date_today_service = datetime .now ().strftime ("%a %d/%m" )
107107 expected_service = [
108- ["octopus_energy/join_octoplus_saving_session_event " , {"event_code" : 987654 , "entity_id" : "event.octopus_energy_a_12345678_octoplus_saving_session_event" }],
108+ ["octopus_energy/join_octoplus_power_down_session_event " , {"event_code" : 987654 , "entity_id" : "event.octopus_energy_a_12345678_octoplus_saving_session_event" }],
109109 ["notify/notify" , {"message" : "Predbat: Joined Octopus saving event {} 18:30-19:30, 50.0 p/kWh" .format (date_today_service )}],
110110 ]
111111
@@ -494,6 +494,111 @@ def setup_items():
494494 return failed
495495
496496
497+ def test_saving_session_join_service_fallback (my_predbat ):
498+ """
499+ Test that auto-join tries the current Bottle Cap Dave join service
500+ (join_octoplus_power_down_session_event) first, falling back to the deprecated
501+ join_octoplus_saving_session_event only when the current one is unavailable (e.g. an
502+ integration version that predates the Power Down rename). Covers GitHub issue #4548 point 3.
503+ """
504+ print ("Test saving session join service fallback (issue #4548 point 3)" )
505+ ha = my_predbat .ha_interface
506+ failed = False
507+ date_today = datetime .now ().strftime ("%Y-%m-%d" )
508+ tz_offset = int (my_predbat .midnight_utc .tzinfo .utcoffset (my_predbat .midnight_utc ).total_seconds () / 3600 )
509+ tz_offset = f"{ tz_offset :02d} "
510+
511+ session_binary = """
512+ state: off
513+ current_joined_event_start: null
514+ current_joined_event_end: null
515+ current_joined_event_duration_in_minutes: null
516+ next_joined_event_start: null
517+ next_joined_event_end: null
518+ next_joined_event_duration_in_minutes: null
519+ icon: mdi:leaf
520+ friendly_name: Octoplus Saving Session
521+ """
522+
523+ session_sensor = f"""
524+ state: '2025-01-23T12:10:11.108+{ tz_offset } :00'
525+ event_types: octopus_energy_all_octoplus_saving_sessions
526+ event_type: octopus_energy_all_octoplus_saving_sessions
527+ account_id: A-4DD6C5EE
528+ available_events:
529+ - id: 9999
530+ start: '{ date_today } T18:30:00+{ tz_offset } :00'
531+ end: '{ date_today } T19:30:00+{ tz_offset } :00'
532+ duration_in_minutes: 60
533+ rewarded_octopoints: null
534+ octopoints_per_kwh: 500
535+ code: TEST123
536+ joined_events: []
537+ friendly_name: Octoplus Saving Session Events
538+ """
539+
540+ def setup_items ():
541+ ha .dummy_items .clear ()
542+ ha .dummy_items ["binary_sensor.octopus_energy_test_octoplus_saving_sessions" ] = yaml .safe_load (session_binary )
543+ ha .dummy_items ["event.octopus_energy_test_octoplus_saving_session_event" ] = yaml .safe_load (session_sensor )
544+ ha .dummy_items ["sensor.octopus_free_session" ] = {}
545+ my_predbat .args ["octopus_saving_session" ] = "event.octopus_energy_test_octoplus_saving_session_event"
546+ my_predbat .args ["octopus_free_session" ] = "sensor.octopus_free_session"
547+ if "octopus_free_url" in my_predbat .args :
548+ del my_predbat .args ["octopus_free_url" ]
549+ my_predbat .args ["octopus_saving_session_octopoints_per_penny" ] = 10
550+ # No octopus_saving_session_join configured, so this exercises the Bottle Cap Dave service
551+ # branch, not the select-entity branch (Octopus Energy Direct or similar)
552+ if "octopus_saving_session_join" in my_predbat .args :
553+ del my_predbat .args ["octopus_saving_session_join" ]
554+ my_predbat .octopus_last_joined_try = None
555+
556+ # Test 1: current service available -> used directly, no fallback
557+ print (" Test 1: Current service used when available" )
558+ setup_items ()
559+ ha .service_store_fail = set ()
560+ ha .service_store_enable = True
561+ ha .service_store = []
562+ my_predbat .fetch_octopus_sessions ()
563+ service_result = ha .get_service_store ()
564+ ha .service_store_enable = False
565+
566+ services_called = [svc [0 ] for svc in service_result ]
567+ if "octopus_energy/join_octoplus_power_down_session_event" not in services_called :
568+ print (f"ERROR: Expected the current service to be called, got { services_called } " )
569+ failed = True
570+ elif "octopus_energy/join_octoplus_saving_session_event" in services_called :
571+ print (f"ERROR: Deprecated service should not be called when the current one succeeds, got { services_called } " )
572+ failed = True
573+ else :
574+ print (" PASS: Current service called, no fallback" )
575+
576+ # Test 2: current service unavailable (older integration) -> falls back to the deprecated one
577+ print (" Test 2: Falls back to deprecated service when the current one is unavailable" )
578+ setup_items ()
579+ ha .service_store_fail = {"octopus_energy/join_octoplus_power_down_session_event" }
580+ ha .service_store_enable = True
581+ ha .service_store = []
582+ my_predbat .fetch_octopus_sessions ()
583+ service_result = ha .get_service_store ()
584+ ha .service_store_enable = False
585+ ha .service_store_fail = set ()
586+
587+ services_called = [svc [0 ] for svc in service_result ]
588+ if "octopus_energy/join_octoplus_saving_session_event" not in services_called :
589+ print (f"ERROR: Expected fallback to the deprecated service, got { services_called } " )
590+ failed = True
591+ else :
592+ print (" PASS: Fell back to the deprecated service" )
593+
594+ if not failed :
595+ print ("PASS: All join service fallback tests passed" )
596+
597+ my_predbat .octopus_last_joined_try = None
598+
599+ return failed
600+
601+
497602def test_saving_session_auto_join_toggle (my_predbat ):
498603 """
499604 Test that the octopus_saving_auto_join switch controls whether available saving sessions are auto-joined
0 commit comments