csv logging added
This commit is contained in:
parent
87f0a7cc8c
commit
2e2792c913
@ -59,6 +59,8 @@ class RSICommandLineInterface:
|
||||
self.adjust_speed(parts[1], parts[2])
|
||||
elif cmd == "override" and len(parts) == 2:
|
||||
self.override_safety(parts[1])
|
||||
elif cmd == "log" and len(parts) >= 2:
|
||||
self.handle_logging_command(parts)
|
||||
elif cmd == "exit":
|
||||
self.stop_rsi()
|
||||
self.running = False
|
||||
@ -161,6 +163,22 @@ class RSICommandLineInterface:
|
||||
"""Override safety limits."""
|
||||
print(f"⚠️ Overriding safety limit: {limit}")
|
||||
|
||||
def handle_logging_command(self, parts):
|
||||
"""Handles logging-related commands."""
|
||||
subcmd = parts[1]
|
||||
if subcmd == "start" and len(parts) == 3:
|
||||
filename = parts[2]
|
||||
self.client.start_logging(filename)
|
||||
print(f"✅ Logging started: {filename}")
|
||||
elif subcmd == "stop":
|
||||
self.client.stop_logging()
|
||||
print("🛑 Logging stopped.")
|
||||
elif subcmd == "status":
|
||||
status = "ON" if self.client.is_logging_active() else "OFF"
|
||||
print(f"📊 Logging Status: {status}")
|
||||
else:
|
||||
print("❌ Invalid log command. Use 'log start <file>.csv', 'log stop', or 'log status'.")
|
||||
|
||||
def show_help(self):
|
||||
"""Displays the list of available commands."""
|
||||
print("""
|
||||
@ -170,6 +188,7 @@ Available Commands:
|
||||
toggle <DiO/DiL> <0/1>, move_external <axis> <value>
|
||||
correct <RKorr/AKorr> <X/Y/Z/A/B/C> <value>, speed <Tech.TX> <value>
|
||||
override <limit>
|
||||
log start <file>.csv, log stop, log status
|
||||
""")
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
||||
@ -1,25 +1,15 @@
|
||||
|
||||
import multiprocessing
|
||||
import socket
|
||||
import time
|
||||
import csv
|
||||
import logging
|
||||
from config_parser import ConfigParser
|
||||
import sys
|
||||
import os
|
||||
import socket
|
||||
import xml.etree.ElementTree as ET
|
||||
import multiprocessing
|
||||
from xml_handler import XMLGenerator # ✅ Import XML generator module
|
||||
from config_parser import ConfigParser # ✅ Import the updated config parser
|
||||
|
||||
|
||||
import multiprocessing
|
||||
import socket
|
||||
import logging
|
||||
import xml.etree.ElementTree as ET # ✅ FIX: Import ElementTree
|
||||
from config_parser import ConfigParser
|
||||
from xml_handler import XMLGenerator
|
||||
|
||||
class NetworkProcess(multiprocessing.Process):
|
||||
"""Handles UDP communication in a separate process."""
|
||||
"""Handles UDP communication and optional CSV logging in a separate process."""
|
||||
|
||||
def __init__(self, ip, port, send_variables, receive_variables, stop_event, config_parser):
|
||||
super().__init__()
|
||||
@ -29,14 +19,17 @@ class NetworkProcess(multiprocessing.Process):
|
||||
self.config_parser = config_parser
|
||||
self.udp_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
|
||||
|
||||
# ✅ Fallback IP handling
|
||||
self.client_address = (ip, port)
|
||||
|
||||
if not self.is_valid_ip(ip):
|
||||
logging.warning(f"Invalid IP address '{ip}' detected. Falling back to '0.0.0.0'.")
|
||||
print(f"⚠️ Invalid IP '{ip}', falling back to '0.0.0.0'.")
|
||||
self.client_address = ('0.0.0.0', port)
|
||||
else:
|
||||
self.client_address = (ip, port)
|
||||
self.logging_active = multiprocessing.Value('b', False) # Shared flag for logging
|
||||
self.log_filename = multiprocessing.Array('c', 256) # Shared memory for filename
|
||||
self.csv_process = None
|
||||
|
||||
try:
|
||||
self.udp_socket.bind(self.client_address)
|
||||
@ -63,44 +56,74 @@ class NetworkProcess(multiprocessing.Process):
|
||||
print("[DEBUG] Network process started.")
|
||||
while not self.stop_event.is_set():
|
||||
try:
|
||||
print("[DEBUG] Waiting for incoming message...")
|
||||
self.udp_socket.settimeout(5)
|
||||
data_received, self.controller_ip_and_port = self.udp_socket.recvfrom(1024)
|
||||
message = data_received.decode()
|
||||
|
||||
print(f"[DEBUG] Received message: {message}")
|
||||
self.process_received_data(message)
|
||||
|
||||
# ✅ Generate the send XML using the updated XMLGenerator
|
||||
send_xml = XMLGenerator.generate_send_xml(self.send_variables, self.config_parser.network_settings)
|
||||
print(f"[DEBUG] Sending response: {send_xml}")
|
||||
|
||||
self.udp_socket.sendto(send_xml.encode(), self.controller_ip_and_port)
|
||||
|
||||
# ✅ If logging is active, write data to CSV
|
||||
if self.logging_active.value:
|
||||
self.log_to_csv()
|
||||
|
||||
except socket.timeout:
|
||||
print("[WARNING] No message received within timeout period.")
|
||||
except Exception as e:
|
||||
print(f"[ERROR] Network process error: {e}")
|
||||
|
||||
|
||||
def stop_network(self):
|
||||
"""Safely stop the network process."""
|
||||
if self.udp_socket:
|
||||
self.udp_socket.close()
|
||||
print("✅ Network socket closed.")
|
||||
|
||||
def process_received_data(self, xml_string):
|
||||
"""Parse incoming XML and update shared variables."""
|
||||
try:
|
||||
root = ET.fromstring(xml_string)
|
||||
for element in root:
|
||||
if element.tag in self.receive_variables:
|
||||
if len(element.attrib) > 0: # ✅ Handle structured data (dictionaries)
|
||||
if len(element.attrib) > 0:
|
||||
self.receive_variables[element.tag] = {k: float(v) for k, v in element.attrib.items()}
|
||||
else:
|
||||
self.receive_variables[element.tag] = element.text
|
||||
|
||||
print(f"[DEBUG] Updated received variables: {self.receive_variables}")
|
||||
except Exception as e:
|
||||
print(f"[ERROR] Error parsing received message: {e}")
|
||||
|
||||
def log_to_csv(self):
|
||||
"""Write send/receive variables to the CSV log."""
|
||||
filename = self.log_filename.value.decode().strip()
|
||||
if not filename:
|
||||
return
|
||||
|
||||
try:
|
||||
with open(filename, mode="a", newline="") as file:
|
||||
writer = csv.writer(file)
|
||||
|
||||
# Write header if the file is new
|
||||
if file.tell() == 0:
|
||||
headers = ["Timestamp", "IPOC"]
|
||||
headers += [f"Send.{k}" for k in self.send_variables.keys()]
|
||||
headers += [f"Receive.{k}" for k in self.receive_variables.keys()]
|
||||
writer.writerow(headers)
|
||||
|
||||
# Write current data
|
||||
timestamp = time.strftime("%d-%m-%Y %H:%M:%S")
|
||||
ipoc = self.receive_variables.get("IPOC", 0)
|
||||
send_data = [self.send_variables.get(k, "") for k in self.send_variables.keys()]
|
||||
receive_data = [self.receive_variables.get(k, "") for k in self.receive_variables.keys()]
|
||||
writer.writerow([timestamp, ipoc] + send_data + receive_data)
|
||||
|
||||
except Exception as e:
|
||||
print(f"[ERROR] Failed to log data to CSV: {e}")
|
||||
|
||||
def start_logging(self, filename):
|
||||
"""Start logging RSI data to CSV."""
|
||||
self.logging_active.value = True
|
||||
self.log_filename.value = filename.encode()
|
||||
print(f"✅ CSV Logging started: {filename}")
|
||||
|
||||
def stop_logging(self):
|
||||
"""Stop logging RSI data."""
|
||||
self.logging_active.value = False
|
||||
print("🛑 CSV Logging stopped.")
|
||||
|
||||
def is_logging_active(self):
|
||||
"""Return logging status."""
|
||||
return self.logging_active.value
|
||||
|
||||
@ -77,3 +77,17 @@ class RSIAPI:
|
||||
"send_variables": dict(self.client.send_variables),
|
||||
"receive_variables": dict(self.client.receive_variables)
|
||||
}
|
||||
|
||||
def start_logging(self, filename):
|
||||
"""Start logging RSI data to CSV."""
|
||||
self.client.start_logging(filename)
|
||||
return f"✅ CSV Logging started: {filename}"
|
||||
|
||||
def stop_logging(self):
|
||||
"""Stop logging RSI data."""
|
||||
self.client.stop_logging()
|
||||
return "🛑 CSV Logging stopped."
|
||||
|
||||
def is_logging_active(self):
|
||||
"""Return logging status."""
|
||||
return self.client.is_logging_active()
|
||||
Loading…
Reference in New Issue
Block a user