Procházet zdrojové kódy

fix homing, improve error handling

Tuan Nguyen před 11 měsíci
rodič
revize
4a425ccbd6

+ 30 - 7
dune_weaver_flask/app.py

@@ -114,6 +114,10 @@ def run_theta_rho():
         return jsonify({'error': 'File not found'}), 404
 
     try:
+            
+        if not (state.conn.is_connected() if state.conn else False):
+            logger.warning("Attempted to run a pattern without a connection")
+            return jsonify({"success": False, "error": "Connection not established"}), 400
         files_to_run = [file_path]
         logger.info(f'Running theta-rho file: {file_name} with pre_execution={pre_execution}')
         pattern_manager.run_theta_rho_files(files_to_run, clear_pattern=pre_execution)
@@ -124,12 +128,18 @@ def run_theta_rho():
 
 @app.route('/stop_execution', methods=['POST'])
 def stop_execution():
+    if not (state.conn.is_connected() if state.conn else False):
+        logger.warning("Attempted to stop without a connection")
+        return jsonify({"success": False, "error": "Connection not established"}), 400
     pattern_manager.stop_actions()
     return jsonify({'success': True})
 
 @app.route('/send_home', methods=['POST'])
 def send_home():
     try:
+        if not (state.conn.is_connected() if state.conn else False):
+            logger.warning("Attempted to move to home without a connection")
+            return jsonify({"success": False, "error": "Connection not established"}), 400
         connection_manager.home()
         return jsonify({'success': True})
     except Exception as e:
@@ -141,6 +151,10 @@ def run_specific_theta_rho_file(file_name):
     file_path = os.path.join(pattern_manager.THETA_RHO_DIR, file_name)
     if not os.path.exists(file_path):
         return jsonify({'error': 'File not found'}), 404
+        
+    if not (state.conn.is_connected() if state.conn else False):
+        logger.warning("Attempted to run a pattern without a connection")
+        return jsonify({"success": False, "error": "Connection not established"}), 400
 
     pattern_manager.run_theta_rho_file(file_path)
     return jsonify({'success': True})
@@ -169,8 +183,8 @@ def delete_theta_rho_file():
 def move_to_center():
     global current_theta
     try:
-        if not state.conn.is_connected():
-            logger.warning("Attempted to move to center without connection")
+        if not (state.conn.is_connected() if state.conn else False):
+            logger.warning("Attempted to move to center without a connection")
             return jsonify({"success": False, "error": "Connection not established"}), 400
 
         logger.info("Moving device to center position")
@@ -185,8 +199,8 @@ def move_to_center():
 def move_to_perimeter():
     global current_theta
     try:
-        if not state.conn.is_connected():
-            logger.warning("Attempted to move to perimeter without connection")
+        if not (state.conn.is_connected() if state.conn else False):
+            logger.warning("Attempted to move to perimeter without a connection")
             return jsonify({"success": False, "error": "Connection not established"}), 400
         pattern_manager.reset_theta()
         pattern_manager.move_polar(0,1)
@@ -216,8 +230,8 @@ def preview_thr():
 
 @app.route('/send_coordinate', methods=['POST'])
 def send_coordinate():
-    if not state.conn.is_connected():
-        logger.warning("Attempted to send coordinate without connection")
+    if not (state.conn.is_connected() if state.conn else False):
+        logger.warning("Attempted to send coordinate without a connection")
         return jsonify({"success": False, "error": "connection not established"}), 400
 
     try:
@@ -242,7 +256,7 @@ def download_file(filename):
 
 @app.route('/serial_status', methods=['GET'])
 def serial_status():
-    connected = state.conn.is_connected()
+    connected = state.conn.is_connected() if state.conn else False
     port = state.port
     logger.debug(f"Serial status check - connected: {connected}, port: {port}")
     return jsonify({
@@ -336,6 +350,11 @@ def run_playlist():
         logger.warning("Run playlist request received without playlist name")
         return jsonify({"success": False, "error": "Missing 'playlist_name' field"}), 400
 
+        
+    if not (state.conn.is_connected() if state.conn else False):
+        logger.warning("Attempted to run a playlist without a connection")
+        return jsonify({"success": False, "error": "Connection not established"}), 400
+
     playlist_name = data["playlist_name"]
     pause_time = data.get("pause_time", 0)
     clear_pattern = data.get("clear_pattern", None)
@@ -379,6 +398,10 @@ def run_playlist():
 @app.route('/set_speed', methods=['POST'])
 def set_speed():
     try:
+        if not (state.conn.is_connected() if state.conn else False):
+            logger.warning("Attempted to change speed without a connection")
+            return jsonify({"success": False, "error": "Connection not established"}), 400
+        
         data = request.json
         new_speed = data.get('speed')
 

+ 7 - 6
dune_weaver_flask/modules/connection/connection_manager.py

@@ -6,6 +6,7 @@ import serial.tools.list_ports
 import websocket
 
 from dune_weaver_flask.modules.core.state import state
+from dune_weaver_flask.modules.core.pattern_manager import move_polar, reset_theta
 
 logger = logging.getLogger(__name__)
 
@@ -163,7 +164,7 @@ def connect_device(homing=True):
         state.conn = WebSocketConnection('ws://fluidnc.local:81')
     else:
         state.conn = SerialConnection(ports[0])
-    if state.conn.is_connected():
+    if (state.conn.is_connected() if state.conn else False):
         device_init(homing)
 
 def get_status_response() -> str:
@@ -230,7 +231,7 @@ def get_machine_steps(timeout=10):
     Send "$$" to retrieve machine settings and update state.
     Returns True if the expected configuration is received, or False if it times out.
     """
-    if not state.conn.is_connected():
+    if not (state.conn.is_connected() if state.conn else False):
         logger.error("Connection is not established.")
         return False
 
@@ -290,9 +291,9 @@ def home():
         logger.info("Sensorless homing not supported. Using crash homing")
         logger.info(f"Homing with speed {state.speed}")
         send_grbl_coordinates(0, -22, state.speed, home=True)
+        state.machine_y -= 22
+
     state.current_theta = state.current_rho = 0
-    update_machine_position()
-    state.save()
 
 def check_idle():
     """
@@ -345,7 +346,7 @@ def restart_connection(homing=False):
         True if the connection was restarted successfully, False otherwise.
     """
     try:
-        if state.conn and state.conn.is_connected():
+        if (state.conn.is_connected() if state.conn else False):
             logger.info("Closing current connection...")
             state.conn.close()
     except Exception as e:
@@ -357,7 +358,7 @@ def restart_connection(homing=False):
     logger.info("Attempting to restart connection...")
     try:
         connect_device(homing)  # This will set state.conn appropriately.
-        if state.conn and state.conn.is_connected():
+        if (state.conn.is_connected() if state.conn else False):
             logger.info("Connection restarted successfully.")
             return True
         else:

+ 1 - 2
dune_weaver_flask/modules/core/pattern_manager.py

@@ -149,7 +149,6 @@ def move_polar(theta, rho):
     x_total_steps = state.x_steps_per_mm * (100/x_scaling_factor)
     y_total_steps = state.y_steps_per_mm * (100/y_scaling_factor)
         
-    x_increment / 50 * (x_total_steps)
     offset = x_increment * (x_total_steps * x_scaling_factor / (state.gear_ratio * y_total_steps * y_scaling_factor))
     y_increment += offset
     
@@ -193,7 +192,7 @@ def run_theta_rho_file(file_path, schedule_hours=None):
     # if not connection_manager.get_status_response() and isinstance(state.conn, connection_manager.WebSocketConnection):
     #     logger.info('Cannot get status response, restarting connection')
     #     connection_manager.restart_connection(home=False)
-    # if not state.conn and not state.conn.is_connected():
+    # if (state.conn.is_connected() if state.conn else False):
     #     logger.error('Connection not established')
     #     return
     # if not file_path:

+ 1 - 1
dune_weaver_flask/modules/mqtt/handler.py

@@ -239,7 +239,7 @@ class MQTTHandler(BaseMQTTHandler):
             
     def _publish_serial_state(self):
         """Helper to publish serial state."""
-        serial_connected = state.conn.is_connected()
+        serial_connected = (state.conn.is_connected() if state.conn else False)
         serial_port = state.port if serial_connected else None
         serial_status = f"connected to {serial_port}" if serial_connected else "disconnected"
         self.client.publish(self.serial_state_topic, serial_status, retain=True)

+ 1 - 1
dune_weaver_flask/modules/mqtt/utils.py

@@ -39,7 +39,7 @@ def get_mqtt_state():
     is_running = bool(state.current_playing_file) and not state.stop_requested
     
     # Get serial status
-    serial_connected = state.conn.is_connected
+    serial_connected = (state.conn.is_connected() if state.conn else False)
     serial_port = state.port if serial_connected else None
     serial_status = f"connected to {serial_port}" if serial_connected else "disconnected"
     

+ 4 - 5
dune_weaver_flask/static/js/main.js

@@ -261,6 +261,7 @@ async function runThetaRho() {
     } else {
         logMessage(`Failed to run file: ${selectedFile}`,LOG_TYPE.ERROR);
     }
+    updateCurrentlyPlaying();
 }
 
 async function stopExecution() {
@@ -1529,13 +1530,11 @@ function formatSecondsToHMS(seconds) {
 // Function to start or stop updates based on visibility
 function handleVisibilityChange() {
     if (document.hasFocus()) {
-        // User is active, start updating
+        updateCurrentlyPlaying(); // Run immediately
         if (!updateInterval) {
-            updateCurrentlyPlaying(); // Run immediately
-            updateInterval = setInterval(updateCurrentlyPlaying, 5000); // Update every 5s
+            updateInterval = setInterval(updateCurrentlyPlaying, 3000);
         }
     } else {
-        // User is inactive, stop updating
         clearInterval(updateInterval);
         updateInterval = null;
     }
@@ -1708,7 +1707,7 @@ document.addEventListener('DOMContentLoaded', () => {
 
     // Periodically check for currently playing status
     if (document.hasFocus()) {
-        updateInterval = setInterval(updateCurrentlyPlaying, 5000);
+        updateInterval = setInterval(updateCurrentlyPlaying, 3000);
     }
     checkForUpdates();
 });