11"""
2- Prefect flow for desk lifter control.
2+ Prefect flow deployment for desk lifter control.
33
4- Provides workflow orchestration using Prefect for remote desk control .
4+ Imports the Prefect-decorated move_to_height flow from desk_controller and provides deployment utilities .
55"""
66
7- from prefect import flow , task
8- from prefect .logging import get_run_logger
9-
10- from progressive_automations_python .desk_controller import (
11- move_to_height ,
12- check_duty_cycle_status_before_execution
13- )
14- from progressive_automations_python .duty_cycle import check_movement_against_duty_cycle , load_state
15- from progressive_automations_python .config import UP_RATE , DOWN_RATE
16-
17- # Decorate core functions as tasks
18- move_to_height_task = task (move_to_height )
19- check_duty_cycle_status_task = task (check_duty_cycle_status_before_execution )
20-
21-
22- @flow
23- def simple_movement_flow (target_height : float ):
24- """Prefect flow for moving desk to a specific height with duty cycle management
25-
26- Movement will execute even if duty cycle capacity is full - it will wait as needed.
27- """
28- logger = get_run_logger ()
29- logger .info (f"=== SIMPLE MOVEMENT FLOW ===" )
30- logger .info (f"Target: { target_height } \" " )
31-
32- # Check duty cycle status
33- initial_status = check_duty_cycle_status_task ()
34- logger .info (f"Initial duty cycle: { initial_status ['current_usage' ]:.1f} s / { initial_status ['window_period' ]} s used" )
35-
36- # Get current position
37- state = load_state ()
38- current_height = state .get ("last_position" )
39-
40- if current_height is None :
41- logger .error ("❌ MOVEMENT ABORTED: No last known position" )
42- raise ValueError ("No last known position in state file" )
43-
44- # Check movement requirements
45- check_result = check_movement_against_duty_cycle (target_height , current_height , UP_RATE , DOWN_RATE )
46-
47- if not check_result ["allowed" ]:
48- # Movement not immediately possible - will wait
49- wait_time = check_result .get ("wait_time_needed" , 0 )
50- logger .warning (f"⏳ Duty cycle capacity insufficient - will wait { wait_time :.1f} s before movement" )
51-
52- # Wait for duty cycle to free up
53- import time
54- time .sleep (wait_time )
55- logger .info (f"✅ Wait complete - proceeding with movement" )
56-
57- # Execute the movement
58- result = move_to_height_task (target_height )
59-
60- # Check final duty cycle status
61- final_status = check_duty_cycle_status_task ()
62-
63- # Log usage
64- capacity_used = initial_status ["remaining_capacity" ] - final_status ["remaining_capacity" ]
65- logger .info (f"Movement completed - Duty cycle used: { capacity_used :.1f} s" )
66-
67- return {
68- ** result ,
69- "initial_duty_status" : initial_status ,
70- "final_duty_status" : final_status ,
71- "capacity_used" : capacity_used ,
72- "wait_time" : check_result .get ("wait_time_needed" , 0 ) if not check_result ["allowed" ] else 0
73- }
7+ from progressive_automations_python .desk_controller import move_to_height
748
759
7610# =============================================================================
77- # DEPLOYMENT FUNCTIONS
11+ # DEPLOYMENT FUNCTION
7812# =============================================================================
7913
80- def deploy_custom_movements_flow (deployment_name : str = "custom-movements" ):
81- """Deploy the main custom movements flow"""
82-
83- deployment = custom_movements_flow .from_source (
84- source = "." ,
85- entrypoint = "prefect_flows.py:custom_movements_flow" ,
86- ).deploy (
87- name = deployment_name ,
88- work_pool_name = "default-process-pool" ,
89- )
90-
91- print (f"✅ Deployment '{ deployment_name } ' created!" )
92- print (f"To run: prefect deployment run 'custom-movements-flow/{ deployment_name } '" )
93- return deployment_name
94-
95-
96- def deploy_duty_cycle_monitoring (deployment_name : str = "duty-cycle-monitor" , schedule_cron : str = None ):
97- """Deploy duty cycle monitoring flow with optional scheduling"""
98-
99- deploy_kwargs = {
100- "name" : deployment_name ,
101- "work_pool_name" : "default-process-pool" ,
102- }
14+ def deploy_move_desk_flow (deployment_name : str = "move-desk" ):
15+ """Deploy the move desk flow for Prefect Cloud execution.
10316
104- if schedule_cron :
105- from prefect .client .schemas .schedules import CronSchedule
106- deploy_kwargs ["schedule" ] = CronSchedule (cron = schedule_cron )
107- print (f"Deploying with cron schedule: { schedule_cron } " )
17+ Args:
18+ deployment_name: Name for the deployment in Prefect Cloud
10819
109- deployment = scheduled_duty_cycle_check .from_source (
110- source = "." ,
111- entrypoint = "prefect_flows.py:scheduled_duty_cycle_check" ,
112- ).deploy (** deploy_kwargs )
113-
114- print (f"✅ Deployment '{ deployment_name } ' created!" )
115- if schedule_cron :
116- print (f"Scheduled to run: { schedule_cron } " )
117- else :
118- print (f"To run: prefect deployment run 'scheduled-duty-cycle-check/{ deployment_name } '" )
119- return deployment_name
120-
121-
122- def deploy_test_sequence (deployment_name : str = "test-sequence" ):
123- """Deploy test sequence flow"""
20+ Returns:
21+ str: The deployment name for reference
22+ """
12423
125- deployment = test_sequence_flow .from_source (
24+ deployment = move_to_height .from_source (
12625 source = "." ,
127- entrypoint = "prefect_flows .py:test_sequence_flow " ,
26+ entrypoint = "desk_controller .py:move_to_height " ,
12827 ).deploy (
12928 name = deployment_name ,
13029 work_pool_name = "default-process-pool" ,
13130 )
13231
13332 print (f"✅ Deployment '{ deployment_name } ' created!" )
134- print (f"To run: prefect deployment run 'test-sequence-flow/{ deployment_name } '" )
135- return deployment_name
136-
137-
138- def deploy_all_flows ():
139- """Deploy all desk control flows"""
140- print ("=== DEPLOYING ALL SIMPLIFIED DESK CONTROL FLOWS ===" )
33+ print (f"To run from Prefect Cloud: Use flow 'move-to-height/{ deployment_name } '" )
34+ print (f"Parameter: target_height (float, in inches)" )
14135
142- # Deploy main flows
143- deploy_custom_movements_flow ()
144- deploy_test_sequence ()
145-
146- # Deploy monitoring flows
147- deploy_duty_cycle_monitoring ("duty-cycle-monitor-scheduled" , "*/10 * * * *" )
148- deploy_duty_cycle_monitoring ("duty-cycle-monitor-immediate" )
149-
150- print ("\n 🎉 All deployments created!" )
151- print ("\n Available flows:" )
152- print (" 1. custom-movements - Main movement execution" )
153- print (" 2. test-sequence - Automated test sequence" )
154- print (" 3. duty-cycle-monitor-scheduled - Auto monitoring (every 10min)" )
155- print (" 4. duty-cycle-monitor-immediate - On-demand monitoring" )
156-
157- return True
36+ return deployment_name
15837
15938
16039if __name__ == "__main__" :
161- import sys
162-
163- if len (sys .argv ) > 1 :
164- if sys .argv [1 ] == "test" :
165- test_sequence_flow ()
166- elif sys .argv [1 ] == "movements" :
167- custom_movements_flow ()
168- elif sys .argv [1 ] == "monitor" :
169- duty_cycle_monitoring_flow ()
170- elif sys .argv [1 ] == "deploy" :
171- deploy_all_flows ()
172- else :
173- print ("Usage: python prefect_flows.py [test|movements|monitor|deploy]" )
174- else :
175- custom_movements_flow ()
40+ # Deploy when run directly
41+ deploy_move_desk_flow ()
0 commit comments