import win32serviceutil import win32service import win32event import servicemanager import socket import time import threading from opc.client import OPCClient from API.client import APIClient from API.mix_weight_api import MixWeightAPI from services.task_service import TaskService from services.monitoring_service import MonitoringService from database.access_db import AccessDB from database.sql_server import SQLServerDB from tcp.server import TCPServer from config.settings import ( ACCESS_DB_PATH, ACCESS_DB_PASSWORD, TCP_HOST, TCP_PORT, TCP_CLIENT_HOST, TCP_CLIENT_PORT, CHECK_INTERVAL, MAX_AGE_HOURS ) from utils.helpers import cleanup_old_timestamps class InsertDataService(win32serviceutil.ServiceFramework): _svc_name_ = "InsertDataService" _svc_display_name_ = "Insert Data Service" _svc_description_ = "Service for inserting data into database" def __init__(self, args): win32serviceutil.ServiceFramework.__init__(self, args) self.hWaitStop = win32event.CreateEvent(None, 0, 0, None) self.running = True self.tcp_server = None self.data_client = None def SvcStop(self): self.ReportServiceStatus(win32service.SERVICE_STOP_PENDING) win32event.SetEvent(self.hWaitStop) self.running = False # 停止TCP服务端 if self.tcp_server: self.tcp_server.stop() # 停止TCP客户端 if self.data_client: self.data_client.stop() def SvcDoRun(self): servicemanager.LogMsg(servicemanager.EVENTLOG_INFORMATION_TYPE, servicemanager.PYS_SERVICE_STARTED, (self._svc_name_, '')) self.main() def start_api_service(self): """启动配比重量API服务""" api = MixWeightAPI() api.run(host='127.0.0.1', port=5001, debug=False, threaded=True) def main(self): try: api_thread = threading.Thread(target=self.start_api_service) api_thread.daemon = True api_thread.start() # 初始化TCP服务端 self.tcp_server = TCPServer(host=TCP_HOST, port=TCP_PORT) tcp_server_thread = threading.Thread(target=self.tcp_server.start) tcp_server_thread.daemon = True tcp_server_thread.start() # 初始化发送数据的OPC客户端 data_client = OPCClient(url=f'opc.tcp://{TCP_CLIENT_HOST}:{TCP_CLIENT_PORT}') data_client.start() # 等待服务端启动 time.sleep(1) # 初始化服务 api_client = APIClient() task_service = TaskService(self.tcp_server) monitoring_service = MonitoringService(self.tcp_server) # 步骤1:获取AppID app_id = api_client.login() task_service.api_client.app_id = app_id # 存储上次获取的所有ArtifactID last_artifact_ids = set() last_artifact_list = [] # 用于存储上一次的完整artifact_list # 启动Access数据库Flag监控线程 access_monitor_thread = threading.Thread(target=monitoring_service.monitor_access_flag_changes) access_monitor_thread.daemon = True access_monitor_thread.start() while self.running: try: # 步骤2:获取所有未浇筑信息 tasks, artifact_list, send_list, half_volume = task_service.process_not_pour_info() current_artifact_ids = {task["artifact_id"] for task in tasks} # 检查artifact_list是否发生变化 if artifact_list != last_artifact_list: servicemanager.LogInfoMsg(f"检测到artifact_list更新: {artifact_list}") # 处理新出现的任务 new_artifact_ids = current_artifact_ids - last_artifact_ids if new_artifact_ids: servicemanager.LogInfoMsg(f"检测到 {len(new_artifact_ids)} 个新任务") for task in tasks: if task["artifact_id"] in new_artifact_ids: task_info = api_client.get_task_info(task["beton_task_id"]) # 步骤4:连接Access数据库并获取最大Mark值 access_db = AccessDB(ACCESS_DB_PATH, ACCESS_DB_PASSWORD) try: max_mark = access_db.get_max_mark() finally: access_db.close() erp_id = int(max_mark) + 1 # 步骤5:连接SQL Server数据库并插入数据 sql_db = SQLServerDB() try: # 检查 block_number 是否为 "补方" if task["block_number"] == "补方": print(f"任务 {task['artifact_id']} 的 block_number 为 '补方',跳过派单") task_service.insert_into_produce_table(sql_db, task_info, task["beton_volume"], erp_id, task["artifact_id"],half_volume, 0) continue print(f"处理新任务: {task['artifact_id']}") # 获取任务单信息 task_service.insert_into_produce_table(sql_db, task_info, task["beton_volume"], erp_id, task["artifact_id"], half_volume,1) with monitoring_service.tasks_lock: monitoring_service.monitored_tasks.add(erp_id) monitoring_service.inserted_tasks[erp_id] = task["artifact_id"] servicemanager.LogInfoMsg( f"任务 {erp_id} (ArtifactID: {task['artifact_id']}) 已添加到监控列表") finally: sql_db.close() # 更新上次获取的ArtifactID集合和artifact_list last_artifact_ids = current_artifact_ids last_artifact_list = artifact_list.copy() # 每10分钟清理一次过期的时间戳记录 cleanup_old_timestamps(task_service.artifact_timestamps, current_artifact_ids, MAX_AGE_HOURS) # 每10秒检查一次 time.sleep(CHECK_INTERVAL) except Exception as e: servicemanager.LogErrorMsg(f"发生错误: {e}") # 继续循环,避免程序退出 time.sleep(2) except Exception as e: servicemanager.LogErrorMsg(f"服务异常终止: {e}") if __name__ == '__main__': win32serviceutil.HandleCommandLine(InsertDataService)