diff --git a/.idea/InsertData.iml b/.idea/InsertData.iml
index 34a5697..29bca85 100644
--- a/.idea/InsertData.iml
+++ b/.idea/InsertData.iml
@@ -4,7 +4,7 @@
-
+
\ No newline at end of file
diff --git a/.idea/misc.xml b/.idea/misc.xml
index df3bfff..db5199f 100644
--- a/.idea/misc.xml
+++ b/.idea/misc.xml
@@ -3,5 +3,5 @@
-
+
\ No newline at end of file
diff --git a/API/__init__.py b/API/__init__.py
new file mode 100644
index 0000000..d6f9a40
--- /dev/null
+++ b/API/__init__.py
@@ -0,0 +1,5 @@
+"""API包"""
+from .client import APIClient
+from .mix_weight_api import MixWeightAPI
+
+__all__ = ['APIClient', 'MixWeightAPI']
diff --git a/API/__pycache__/__init__.cpython-39.pyc b/API/__pycache__/__init__.cpython-39.pyc
new file mode 100644
index 0000000..28a8f9d
Binary files /dev/null and b/API/__pycache__/__init__.cpython-39.pyc differ
diff --git a/API/__pycache__/client.cpython-39.pyc b/API/__pycache__/client.cpython-39.pyc
new file mode 100644
index 0000000..a6aaaef
Binary files /dev/null and b/API/__pycache__/client.cpython-39.pyc differ
diff --git a/API/__pycache__/mix_weight_api.cpython-39.pyc b/API/__pycache__/mix_weight_api.cpython-39.pyc
new file mode 100644
index 0000000..4f25d7b
Binary files /dev/null and b/API/__pycache__/mix_weight_api.cpython-39.pyc differ
diff --git a/API/client.py b/API/client.py
new file mode 100644
index 0000000..f931a1b
--- /dev/null
+++ b/API/client.py
@@ -0,0 +1,71 @@
+"""API客户端模块"""
+import requests
+import hashlib
+from config.settings import BASE_URL, LOGIN_DATA
+
+
+class APIClient:
+ def __init__(self):
+ self.base_url = BASE_URL
+ self.login_url = f"{BASE_URL}/api/user/perlogin"
+ self.mould_info_url = f"{BASE_URL}/api/ext/mould/last_artifact?mouldCode=SHR2B1-9"
+ self.task_info_url = f"{BASE_URL}/api/ext/artifact/task"
+ self.not_pour_info_url = f"{BASE_URL}/api/ext/artifact/not_pour"
+ self.app_id = None
+
+ def hash_password(self, password):
+ """计算SHA256密码"""
+ return password
+
+ def login(self):
+ """获取AppID"""
+ login_data = LOGIN_DATA.copy()
+ login_data["password"] = self.hash_password(login_data["password"])
+
+ response = requests.post(self.login_url, json=login_data)
+ if response.status_code == 200:
+ data = response.json()
+ if data.get("Code") == 200:
+ self.app_id = data["Data"]["AppID"]
+ return self.app_id
+ raise Exception("登录失败,无法获取AppID")
+
+ def get_mould_info(self):
+ """获取模具的管片信息并提取TaskID"""
+ if not self.app_id:
+ raise Exception("请先登录获取AppID")
+
+ headers = {"AppID": self.app_id}
+ response = requests.get(self.mould_info_url, headers=headers)
+ if response.status_code == 205:
+ data = response.json()
+ if data.get("Code") == 200:
+ return data["Data"]["BetonTaskID"]
+ raise Exception("获取模具信息失败")
+
+ def get_task_info(self, task_id):
+ """获取任务单信息"""
+ if not self.app_id:
+ raise Exception("请先登录获取AppID")
+
+ headers = {"AppID": self.app_id}
+ url = f"{self.task_info_url}?TaskId={task_id}"
+ response = requests.get(url, headers=headers)
+ if response.status_code == 200:
+ data = response.json()
+ if data.get("Code") == 200:
+ return data["Data"]
+ raise Exception("获取任务单信息失败")
+
+ def get_not_pour_info(self):
+ """获取所有未浇筑信息"""
+ if not self.app_id:
+ raise Exception("请先登录获取AppID")
+
+ headers = {"AppID": self.app_id}
+ response = requests.get(self.not_pour_info_url, headers=headers)
+ if response.status_code == 200:
+ data = response.json()
+ if data.get("Code") == 200:
+ return data["Data"]
+ raise Exception("获取未浇筑信息失败")
diff --git a/API/mix_weight_api.py b/API/mix_weight_api.py
new file mode 100644
index 0000000..269e89a
--- /dev/null
+++ b/API/mix_weight_api.py
@@ -0,0 +1,62 @@
+"""配比重量API模块"""
+from flask import Flask, jsonify
+from database.sql_server_connection import SQLServerConnection
+
+class MixWeightAPI:
+ def __init__(self):
+ self.app = Flask(__name__)
+ self.db = SQLServerConnection()
+ self._register_routes()
+
+ def _register_routes(self):
+ """注册路由"""
+ self.app.add_url_rule('/API/mix_weights', 'get_mix_weights', self.get_mix_weights, methods=['GET'])
+ self.app.add_url_rule('/API/mix_weights/', 'get_mix_weight_by_code',
+ self.get_mix_weight_by_code, methods=['GET'])
+
+ def get_mix_weights(self):
+ """
+ HTTP接口:获取所有配比号及其对应每方重量
+ 返回格式:JSON数组
+ """
+ try:
+ mix_info = self.db.get_mix_weight_info()
+ return jsonify({
+ "success": True,
+ "data": mix_info,
+ "count": len(mix_info)
+ }), 200
+ except Exception as e:
+ return jsonify({
+ "success": False,
+ "error": str(e)
+ }), 500
+
+ def get_mix_weight_by_code(self, code):
+ """
+ HTTP接口:根据配比号获取其对应每方重量
+ 返回格式:JSON对象
+ """
+ try:
+ mix_info = self.db.get_mix_weight_info()
+ for item in mix_info:
+ if item["Code"] == code:
+ return jsonify({
+ "success": True,
+ "data": item
+ }), 200
+
+ return jsonify({
+ "success": False,
+ "error": f"未找到配比号 {code}"
+ }), 404
+
+ except Exception as e:
+ return jsonify({
+ "success": False,
+ "error": str(e)
+ }), 500
+
+ def run(self, host='127.0.0.1', port=5001, debug=True, threaded=True):
+ """启动Flask服务"""
+ self.app.run(host=host, port=port, debug=debug, threaded=threaded)
diff --git a/API/send_data_test.py b/API/send_data_test.py
new file mode 100644
index 0000000..4159774
--- /dev/null
+++ b/API/send_data_test.py
@@ -0,0 +1,273 @@
+
+from flask import Flask, request, jsonify
+import json
+from datetime import datetime
+from datetime import timedelta
+
+app = Flask(__name__)
+
+
+@app.route('/api/user/perlogin', methods=['POST'])
+def login():
+ """
+ 模拟登录接口 - 获取AppID
+ """
+ try:
+ # 获取请求参数
+ data = request.get_json()
+
+ # 验证必要参数
+ if not all(k in data for k in ['Program', 'SC', 'loginName', 'password']):
+ return jsonify({
+ "Code": 400,
+ "Message": "缺少必要参数",
+ "Data": None
+ }), 400
+
+ # 模拟验证逻辑
+ expected_login_name = "leduser"
+ expected_password = "bfcda35cf4eba92d4583931bbe4ff72ffdfa8b5c9c4b72611bd33f5babee069d"
+
+ if data['loginName'] != expected_login_name or data['password'] != expected_password:
+ return jsonify({
+ "Code": 401,
+ "Message": "用户名或密码错误",
+ "Data": None
+ }), 401
+
+ # 模拟生成AppID和SignToken
+ app_id = "e00412005f74144a8654d24f9d4b4e5"
+ sign_token = "79a5c0da-ebfd-4ce3-832d-36c807cc0398"
+ expire_time = (datetime.now().replace(microsecond=0) + timedelta(hours=24)).isoformat()
+
+ response_data = {
+ "Code": 200,
+ "Message": None,
+ "Data": {
+ "AppID": app_id,
+ "SignToken": sign_token,
+ "ExpireTime": expire_time,
+ "ZrJwt": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJqdGkiOiI3OQ" # 简化JWT
+ }
+ }
+
+ return jsonify(response_data), 200
+
+ except Exception as e:
+ return jsonify({
+ "Code": 500,
+ "Message": f"服务器内部错误: {str(e)}",
+ "Data": None
+ }), 500
+
+
+@app.route('/api/ext/mould/last_artifact', methods=['GET'])
+def get_mould_info():
+ """
+ 模拟获取模具管片信息接口
+ """
+ try:
+ # 获取查询参数
+ mould_code = request.args.get('mouldCode')
+
+ if not mould_code:
+ return jsonify({
+ "Code": 400,
+ "Message": "缺少mouldCode参数",
+ "Data": None
+ }), 400
+
+ # 模拟AppID验证(这里简化处理)
+ app_id = request.headers.get('AppID')
+ if not app_id:
+ return jsonify({
+ "Code": 401,
+ "Message": "缺少AppID认证",
+ "Data": None
+ }), 401
+
+ # 模拟返回数据
+ response_data = {
+ "Code": 200,
+ "Message": None,
+ "Data": {
+ "ArtifactID": "QR1B12000151AD",
+ "ArtifactActionID": 346482967298117,
+ "ArtifactIDVice1": "Q00001AD",
+ "ProduceRingNumber": 1,
+ "MouldCode": mould_code,
+ "SkeletonID": "QR1B12000046A",
+ "RingTypeCode": "R22",
+ "SizeSpecification": "6900*1500",
+ "BuriedDepth": "中埋",
+ "BlockNumber": "B1",
+ "HoleRingMarking": "否",
+ "GroutingPipeMarking": "是",
+ "PolypropyleneFiberMarking": "是",
+ "BetonVolume": 6455.0000,
+ "BetonTaskID": "20251020-01"
+ }
+ }
+
+ return jsonify(response_data), 200
+
+ except Exception as e:
+ return jsonify({
+ "Code": 500,
+ "Message": f"服务器内部错误: {str(e)}",
+ "Data": None
+ }), 500
+
+
+@app.route('/api/ext/artifact/task', methods=['GET'])
+def get_task_info():
+ """
+ 模拟获取任务单信息接口
+ """
+ try:
+ # 获取查询参数
+ task_id = request.args.get('TaskId')
+
+ if not task_id:
+ return jsonify({
+ "Code": 400,
+ "Message": "缺少TaskId参数",
+ "Data": None
+ }), 400
+
+ # 模拟AppID验证
+ app_id = request.headers.get('AppID')
+ if not app_id:
+ return jsonify({
+ "Code": 401,
+ "Message": "缺少AppID认证",
+ "Data": None
+ }), 401
+
+ # 模拟返回数据
+ response_data = {
+ "Code": 200,
+ "Message": None,
+ "Data": {
+ "TaskID": task_id,
+ "TaskStatus": 4,
+ "TaskStatusText": "已制单",
+ "TaskCount": 600,
+ "AlreadyProduceCount": 100,
+ "Progress": "100 / 600",
+ "ProjectName": "测试新增工程测试",
+ "TaskPlanDateText": "2025-07-18",
+ "BetonGrade": "C50",
+ "MixID": "P20250717001",
+ "ProduceMixID": "HNT-2025-07-17-001",
+ "PlannedVolume": 1050.00,
+ "ProducedVolume": 0.00,
+ "HoleRingMarking": "咕发环",
+ "GroutingPipeMarking": "是",
+ "PolypropyleneFiberMarking": "是",
+ "TaskDate": "1900-01-01T00:00:00",
+ "TaskDateText": "1900-01-01",
+ "PlateCount": 0,
+ "SendStatus": 0,
+ "SendStatusText": "未下发",
+ "MixSendStatus": 0,
+ "MixSendStatusText": "未下发"
+ }
+ }
+
+ return jsonify(response_data), 200
+
+ except Exception as e:
+ return jsonify({
+ "Code": 500,
+ "Message": f"服务器内部错误: {str(e)}",
+ "Data": None
+ }), 500
+
+
+@app.route('/api/ext/artifact/not_pour', methods=['GET'])
+def get_not_pour_info():
+ """
+ 模拟获取已入模绑定未浇筑的管片信息接口
+ """
+ try:
+ # 模拟AppID验证
+ app_id = request.headers.get('AppID')
+ if not app_id:
+ return jsonify({
+ "Code": 401,
+ "Message": "缺少AppID认证",
+ "Data": None
+ }), 401
+
+ # 模拟返回多个记录
+ response_data = {
+ "Code": 200,
+ "Message": None,
+ "Data": [
+ {
+ "ArtifactID": "QR1B12000151AD",
+ "ArtifactActionID": 346482967298117,
+ "ArtifactIDVice1": "Q00001AD",
+ "ProduceRingNumber": 1,
+ "MouldCode": "SHR2B1-9",
+ "SkeletonID": "QR1B12000046A",
+ "RingTypeCode": "R22",
+ "SizeSpecification": "6900*1500",
+ "BuriedDepth": "中埋",
+ "BlockNumber": "B1",
+ "HoleRingMarking": "否",
+ "GroutingPipeMarking": "否",
+ "PolypropyleneFiberMarking": "否",
+ "BetonVolume": 2.0000,
+ "BetonTaskID": "20251020-01"
+ },
+ {
+ "ArtifactID": "QR1B32000153AD",
+ "ArtifactActionID": 346482967298119,
+ "ArtifactIDVice1": "Q00001AD",
+ "ProduceRingNumber": 1,
+ "MouldCode": "SHR2B3-9",
+ "SkeletonID": "QR1B2000048A",
+ "RingTypeCode": "R22",
+ "SizeSpecification": "6900*1500",
+ "BuriedDepth": "中埋",
+ "BlockNumber": "B2",
+ "HoleRingMarking": "否",
+ "GroutingPipeMarking": "否",
+ "PolypropyleneFiberMarking": "否",
+ "BetonVolume": 2.0000,
+ "BetonTaskID": "20251020-01"
+ },
+ {
+ "ArtifactID": "QR1B12000151AD",
+ "ArtifactActionID": 346482967298120,
+ "ArtifactIDVice1": "Q00001AD",
+ "ProduceRingNumber": 1,
+ "MouldCode": "SHR2B1-9",
+ "SkeletonID": "QR1B12000046A",
+ "RingTypeCode": "R22",
+ "SizeSpecification": "6900*1500",
+ "BuriedDepth": "中埋",
+ "BlockNumber": "B3",
+ "HoleRingMarking": "否",
+ "GroutingPipeMarking": "否",
+ "PolypropyleneFiberMarking": "否",
+ "BetonVolume": 2.0000,
+ "BetonTaskID": "20251020-01"
+ },
+ ]
+ }
+
+ return jsonify(response_data), 200
+
+ except Exception as e:
+ return jsonify({
+ "Code": 500,
+ "Message": f"服务器内部错误: {str(e)}",
+ "Data": None
+ }), 500
+
+
+if __name__ == '__main__':
+ app.run(host='127.0.0.1', port=5000, debug=True)
diff --git a/Allocation.py b/Allocation.py
deleted file mode 100644
index 5522d6e..0000000
--- a/Allocation.py
+++ /dev/null
@@ -1,424 +0,0 @@
-#离线版本,根据彭的返回值更新状态,待测试
-
-import requests
-import hashlib
-import pyodbc
-from datetime import datetime
-import time
-import json
-import threading
-from TCPServer import TCPServer
-
-# 配置信息
-BASE_URL = "https://www.shnthy.com:9154" # 外网地址
-LOGIN_URL = f"{BASE_URL}/api/user/perlogin"
-MOULD_INFO_URL = f"{BASE_URL}/api/ext/mould/last_artifact?mouldCode=SHR2B1-9"
-TASK_INFO_URL = f"{BASE_URL}/api/ext/artifact/task"
-NOT_POUR_INFO_URL = f"{BASE_URL}/api/ext/artifact/not_pour" # 新增接口
-
-# 登录参数
-LOGIN_DATA = {
- "Program": 11,
- "SC": "1000000001",
- "loginName": "leduser",
- "password": "bfcda35cf4eba92d4583931bbe4ff72ffdfa8b5c9c4b72611bd33f5babee069d"
-}
-
-# 全局变量用于存储需要监控的任务ERP ID
-monitored_tasks = set() # 存储需要监控的erp_id
-inserted_tasks = {} # {erp_id: artifact_id}
-tasks_lock = threading.Lock()
-
-# TCP服务端实例
-tcp_server = TCPServer
-
-# 存储任务信息,用于在SQL Server数据删除后保存到自定义表
-task_info_storage = {} # {erp_id: task_info}
-
-
-# 计算SHA256密码
-def hash_password(password):
- return password
-
-
-LOGIN_DATA["password"] = hash_password(LOGIN_DATA["password"])
-
-
-# 获取AppID
-def get_app_id():
- response = requests.post(LOGIN_URL, json=LOGIN_DATA)
- if response.status_code == 200:
- data = response.json()
- if data.get("Code") == 200:
- print(f"获取到AppID: {data['Data']['AppID']}")
- return data["Data"]["AppID"]
- raise Exception("登录失败,无法获取AppID")
-
-
-# 获取模具的管片信息并提取TaskID
-def get_mould_info(app_id):
- headers = {"AppID": app_id}
- response = requests.get(MOULD_INFO_URL, headers=headers)
- if response.status_code == 205:
- data = response.json()
- if data.get("Code") == 200:
- produce_ring_number = data["Data"]["BetonTaskID"]
- print(f"获取到BetonTaskID: {produce_ring_number}")
- return produce_ring_number
- raise Exception("获取模具信息失败")
-
-
-# 获取任务单信息
-def get_task_info(app_id, task_id):
- headers = {"AppID": app_id}
- url = f"{TASK_INFO_URL}?TaskId={task_id}"
- response = requests.get(url, headers=headers)
- if response.status_code == 200:
- data = response.json()
- if data.get("Code") == 200:
- task_data = data["Data"]
- print(f"获取到任务单信息:")
- print(f" TaskID: {task_data['TaskID']}")
- print(f" ProduceMixID: {task_data['ProduceMixID']}")
- print(f" ProjectName: {task_data['ProjectName']}")
- print(f" BetonGrade: {task_data['BetonGrade']}")
- print(f" MixID: {task_data['MixID']}")
- print(f" PlannedVolume: {task_data['PlannedVolume']}")
- print(f" ProducedVolume: {task_data['ProducedVolume']}")
- print(f" Progress: {task_data['Progress']}")
- print(f" TaskDateText: {task_data['TaskDateText']}")
- print(f" TaskStatusText: {task_data['TaskStatusText']}")
- return task_data
- raise Exception("获取任务单信息失败")
-
-
-# 获取所有未浇筑信息
-def get_all_not_pour_info(app_id):
- headers = {"AppID": app_id}
- response = requests.get(NOT_POUR_INFO_URL, headers=headers)
- if response.status_code == 200:
- data = response.json()
- if data.get("Code") == 200:
- artifact_list = data["Data"]
- tasks = []
- for artifact in artifact_list:
- beton_task_id = artifact["BetonTaskID"]
- beton_volume = artifact["BetonVolume"]
- artifact_id = artifact["ArtifactActionID"]
- block_number = artifact.get("BlockNumber", "")
-
- # 根据BlockNumber调整方量
- if block_number == "L2":
- adjusted_volume = beton_volume + 0.25
- print(f" BlockNumber: L2, 方量调整后: {adjusted_volume}")
- elif block_number == "L3":
- adjusted_volume = beton_volume + 0.3
- print(f" BlockNumber: L3, 方量调整后: {adjusted_volume}")
- else:
- adjusted_volume = beton_volume
- print(f" BlockNumber: {block_number}, 方量未调整")
-
- tasks.append({
- "beton_task_id": beton_task_id,
- "beton_volume": adjusted_volume,
- "artifact_id": artifact_id,
- "block_number": block_number
- })
-
- return tasks
- raise Exception("获取未浇筑信息失败")
-
-
-# 连接Access数据库
-def connect_to_access_db(db_path, password):
- conn_str = (
- r'DRIVER={Microsoft Access Driver (*.mdb, *.accdb)};'
- f'DBQ={db_path};'
- f'PWD={password};'
- )
- return pyodbc.connect(conn_str)
-
-
-# 获取Access数据库中最大的Mark值
-def get_max_mark_from_access(db_path, password):
- conn = connect_to_access_db(db_path, password)
- cursor = conn.cursor()
-
- # 查询最大的Mark值
- cursor.execute("SELECT MAX(Mark) FROM Produce")
- max_mark = cursor.fetchone()[0]
-
- # 如果没有记录,返回0
- if max_mark is None:
- max_mark = 0
-
- conn.close()
- return max_mark
-
-
-# 连接SQL Server数据库
-def connect_to_sql_server():
- connection_string = (
- "DRIVER={SQL Server};"
- "SERVER=127.0.0.1;"
- "DATABASE=BS23DB;"
- "UID=sa;"
- "PWD=123;"
- )
- return pyodbc.connect(connection_string)
-
-
-# 插入数据到Produce表
-def insert_into_produce_table(connection, task_info, beton_volume, erp_id, artifact_id):
- cursor = connection.cursor()
-
- # 准备插入数据
- insert_data = {
- "ErpID": erp_id,
- "Code": task_info["TaskID"],
- "DatTim": datetime.now(),
- "Recipe": task_info["ProduceMixID"],
- "MorRec": "",
- "ProdMete": beton_volume,
- "MorMete": 0.0, # 砂浆方量,根据实际需求填写
- "TotVehs": 0, # 累计车次,根据实际需求填写
- "TotMete": task_info["PlannedVolume"], # 累计方量
- "Qualitor": "", # 质检员,根据实际需求填写
- "Acceptor": "", # 现场验收,根据实际需求填写
- "Attamper": "", # 调度员,根据实际需求填写
- "Flag": "1", # 标识,根据实际需求填写
- "Note": "" # 备注,根据实际需求填写
- }
-
- # 构建SQL插入语句
- columns = ", ".join(insert_data.keys())
- placeholders = ", ".join(["?" for _ in insert_data.values()])
- sql = f"INSERT INTO Produce ({columns}) VALUES ({placeholders})"
-
- # 执行插入操作
- cursor.execute(sql, list(insert_data.values()))
- connection.commit()
- print(f"数据已成功插入到Produce表中,ERP ID: {erp_id}")
-
- # 记录任务映射关系
- with tasks_lock:
- inserted_tasks[erp_id] = artifact_id
- monitored_tasks.add(erp_id)
- # 存储任务信息,用于后续保存到自定义表
- task_info_storage[erp_id] = {
- "task_info": task_info,
- "beton_volume": beton_volume,
- "artifact_id": artifact_id
- }
- print(f"任务 {erp_id} (ArtifactID: {artifact_id}) 已添加到监控列表")
-
- # 发送数据给TCP客户端
- try:
- task_data = {
- "erp_id": erp_id,
- "task_id": task_info["TaskID"],
- "produce_mix_id": task_info["ProduceMixID"],
- "project_name": task_info["ProjectName"],
- "beton_grade": task_info["BetonGrade"],
- "adjusted_volume": beton_volume,
- "flag": "1x",
- "timestamp": datetime.now().strftime("%Y-%m-%d %H:%M:%S")
- }
- tcp_server.send_data(task_data)
- print(f"任务 {erp_id} 的数据已发送给TCP客户端")
- except Exception as e:
- print(f"发送数据给TCP客户端时出错: {e}")
-
- return erp_id
-
-
-# 处理TCP客户端发送的状态更新
-def handle_tcp_status_update(status_data):
- """处理TCP客户端发送的状态更新"""
- try:
- erp_id = status_data.get("erp_id")
- status = status_data.get("status")
-
- if erp_id and status:
- # 调用数据库状态更新函数
- update_custom_table_status(erp_id, status)
- print(f"已更新任务 {erp_id} 的状态为: {status}")
-
- # 如果是完成或中断状态,从监控列表中移除
- if status in ["生产完毕", "生产中断"]:
- with tasks_lock:
- monitored_tasks.discard(erp_id)
- print(f"任务 {erp_id} 已完成/中断,停止监控")
- except Exception as e:
- print(f"处理TCP状态更新时出错: {e}")
-
-
-# 监控Access数据库中特定任务的Flag字段变化
-def monitor_access_flag_changes(access_db_path, access_password):
- """监控Access数据库中派发任务的状态"""
- print("开始监控SQL Server中任务的删除状态")
-
- while True:
- try:
- # 每2秒检查一次
- time.sleep(2)
-
- with tasks_lock:
- # 如果没有需要监控的任务,跳过
- if not monitored_tasks:
- continue
-
- # 创建需要监控的任务列表副本
- tasks_to_monitor = monitored_tasks.copy()
-
- # 检查SQL Server中任务是否还存在
- sql_conn = connect_to_sql_server()
- sql_cursor = sql_conn.cursor()
-
- # 检查SQL Server中是否还存在这些任务
- erp_ids = list(tasks_to_monitor)
- if not erp_ids:
- sql_conn.close()
- continue
-
- erp_ids_str = [str(erp_id) for erp_id in erp_ids]
- placeholders = ','.join('?' * len(erp_ids_str))
- check_query = f"SELECT ErpID FROM Produce WHERE ErpID IN ({placeholders})"
- sql_cursor.execute(check_query, erp_ids_str)
- sql_results = sql_cursor.fetchall()
- sql_conn.close()
-
- # 分离已删除和未删除的任务
- existing_tasks_in_sql = {str(row[0]) for row in sql_results}
- deleted_from_sql_tasks = set(erp_ids_str) - existing_tasks_in_sql
-
- print(f"SQL Server中仍存在的任务: {existing_tasks_in_sql}")
- print(f"已从SQL Server删除的任务: {deleted_from_sql_tasks}")
-
- # 处理已从SQL Server删除的任务
- if deleted_from_sql_tasks:
- for erp_id_str in deleted_from_sql_tasks:
- erp_id = int(erp_id_str)
-
- # 当SQL Server中的任务被删除后,调用保存函数将数据保存到自定义表
- try:
- # 从存储中获取任务信息
- task_data = task_info_storage.get(erp_id)
- if task_data:
- task_info = task_data["task_info"]
- beton_volume = task_data["beton_volume"]
- artifact_id = task_data["artifact_id"]
-
- # 调用同事提供的保存函数,将数据保存到自定义数据表
- save_to_custom_table(
- misid=erp_id,
- flag="1", # 初始Flag值
- task_id=task_info["TaskID"],
- produce_mix_id=task_info["ProduceMixID"],
- project_name=task_info["ProjectName"],
- beton_grade=task_info["BetonGrade"],
- adjusted_volume=beton_volume # 已经调整后的方量
- )
- print(f"任务 {erp_id} 的数据已保存到自定义数据表")
-
- # 从存储中移除已处理的任务信息
- task_info_storage.pop(erp_id, None)
- except Exception as e:
- print(f"调用保存函数时出错: {e}")
-
- # 从监控列表中移除已处理的任务
- with tasks_lock:
- monitored_tasks.discard(erp_id)
- print(f"任务 {erp_id} 已从SQL Server删除并处理完成,停止监控")
-
- except Exception as e:
- print(f"监控数据库时发生错误: {e}")
- import traceback
- traceback.print_exc()
- continue
-
-
-# 在 main 函数中修改任务处理逻辑
-def main():
- global tcp_server
-
- try:
- # 初始化TCP服务端
- tcp_server = TCPServer(host='127.0.0.1', port=8888)
- tcp_server_thread = threading.Thread(target=tcp_server.start)
- tcp_server_thread.daemon = True
- tcp_server_thread.start()
-
- # 等待服务端启动
- time.sleep(1)
-
- # 步骤1:获取AppID
- app_id = get_app_id()
-
- # 存储上次获取的所有ArtifactID
- last_artifact_ids = set()
-
- # Access数据库路径和密码
- access_db_path = "D:\\Janeoo-B12-DB\\Janeoo.2.mdb" # 替换为实际路径
- access_password = "BCS7.2_SDBS" # Access数据库密码
-
- # 启动监控线程
- access_monitor_thread = threading.Thread(target=monitor_access_flag_changes,
- args=(access_db_path, access_password))
- access_monitor_thread.daemon = True
- access_monitor_thread.start()
-
- while True:
- try:
- # 步骤2:获取所有未浇筑信息
- tasks = get_all_not_pour_info(app_id)
- current_artifact_ids = {task["artifact_id"] for task in tasks}
-
- # 检查是否有新任务
- new_artifact_ids = current_artifact_ids - last_artifact_ids
- if new_artifact_ids:
- print(f"检测到 {len(new_artifact_ids)} 个新任务")
-
- for task in tasks:
- if task["artifact_id"] in new_artifact_ids:
- # 检查 block_number 是否为 "F"
- if task["block_number"] == "F":
- print(f"任务 {task['artifact_id']} 的 block_number 为 'F',跳过派单")
- continue
-
- print(f"处理新任务: {task['artifact_id']}")
-
- # 步骤3:获取任务单信息
- task_info = get_task_info(app_id, task["beton_task_id"])
-
- # 步骤4:连接Access数据库并获取最大Mark值
- max_mark = get_max_mark_from_access(access_db_path, access_password)
- erp_id = int(max_mark) + 1
- print(f"获取到ERP ID: {erp_id}")
-
- # 步骤5:连接SQL Server数据库并插入数据
- connection = connect_to_sql_server()
- insert_into_produce_table(connection, task_info, task["beton_volume"], erp_id,
- task["artifact_id"])
- connection.close()
-
- # 更新上次获取的ArtifactID集合
- last_artifact_ids = current_artifact_ids
-
- # 每2秒检查一次
- time.sleep(2)
-
- except Exception as e:
- print(f"发生错误: {e}")
- # 继续循环,避免程序退出
- time.sleep(2)
-
- except KeyboardInterrupt:
- print("程序已停止")
- # 停止TCP服务端
- if tcp_server:
- tcp_server.stop()
-
-
-if __name__ == "__main__":
- main()
diff --git a/Allocation_api.py b/Allocation_api.py
deleted file mode 100644
index 935bc64..0000000
--- a/Allocation_api.py
+++ /dev/null
@@ -1,445 +0,0 @@
-#从api列表获取,只读第一个,还没实现
-
-import requests
-import hashlib
-import pyodbc
-from datetime import datetime
-import time
-import json
-import threading
-from TCPServer import TCPServer
-
-# 配置信息
-BASE_URL = "https://www.shnthy.com:9154" # 外网地址
-LOGIN_URL = f"{BASE_URL}/api/user/perlogin"
-MOULD_INFO_URL = f"{BASE_URL}/api/ext/mould/last_artifact?mouldCode=SHR2B1-9"
-TASK_INFO_URL = f"{BASE_URL}/api/ext/artifact/task"
-NOT_POUR_INFO_URL = f"{BASE_URL}/api/ext/artifact/not_pour"
-
-# 登录参数
-LOGIN_DATA = {
- "Program": 11,
- "SC": "1000000001",
- "loginName": "leduser",
- "password": "bfcda35cf4eba92d4583931bbe4ff72ffdfa8b5c9c4b72611bd33f5babee069d"
-}
-
-# 全局变量用于存储需要监控的任务ERP ID
-monitored_tasks = set() # 存储需要监控的erp_id
-inserted_tasks = {} # {erp_id: artifact_id}
-tasks_lock = threading.Lock()
-
-# TCP服务端实例
-tcp_server = None
-
-# 存储任务信息,用于在SQL Server数据删除后保存到自定义表
-task_info_storage = {} # {erp_id: task_info}
-
-
-# 计算SHA256密码
-def hash_password(password):
- return password
-
-
-LOGIN_DATA["password"] = hash_password(LOGIN_DATA["password"])
-
-
-# 获取AppID
-def get_app_id():
- response = requests.post(LOGIN_URL, json=LOGIN_DATA)
- if response.status_code == 200:
- data = response.json()
- if data.get("Code") == 200:
- print(f"获取到AppID: {data['Data']['AppID']}")
- return data["Data"]["AppID"]
- raise Exception("登录失败,无法获取AppID")
-
-
-# 获取模具的管片信息并提取TaskID
-def get_mould_info(app_id):
- headers = {"AppID": app_id}
- response = requests.get(MOULD_INFO_URL, headers=headers)
- if response.status_code == 205:
- data = response.json()
- if data.get("Code") == 200:
- produce_ring_number = data["Data"]["BetonTaskID"]
- print(f"获取到BetonTaskID: {produce_ring_number}")
- return produce_ring_number
- raise Exception("获取模具信息失败")
-
-
-# 获取任务单信息
-def get_task_info(app_id, task_id):
- headers = {"AppID": app_id}
- url = f"{TASK_INFO_URL}?TaskId={task_id}"
- response = requests.get(url, headers=headers)
- if response.status_code == 200:
- data = response.json()
- if data.get("Code") == 200:
- task_data = data["Data"]
- print(f"获取到任务单信息:")
- print(f" TaskID: {task_data['TaskID']}")
- print(f" ProduceMixID: {task_data['ProduceMixID']}")
- print(f" ProjectName: {task_data['ProjectName']}")
- print(f" BetonGrade: {task_data['BetonGrade']}")
- print(f" MixID: {task_data['MixID']}")
- print(f" PlannedVolume: {task_data['PlannedVolume']}")
- print(f" ProducedVolume: {task_data['ProducedVolume']}")
- print(f" Progress: {task_data['Progress']}")
- print(f" TaskDateText: {task_data['TaskDateText']}")
- print(f" TaskStatusText: {task_data['TaskStatusText']}")
- return task_data
- raise Exception("获取任务单信息失败")
-
-
-# 获取所有未浇筑信息
-# 修改 get_all_not_pour_info 函数
-def get_all_not_pour_info(app_id):
- headers = {"AppID": app_id}
- response = requests.get(NOT_POUR_INFO_URL, headers=headers)
- if response.status_code == 200:
- data = response.json()
- if data.get("Code") == 200:
- artifact_list = data["Data"]
- tasks = []
-
- # 检查列表是否为空
- if not artifact_list:
- return tasks
-
- # 获取最新的管片信息(最上面一条)
- latest_artifact = artifact_list[0] # 只处理最上面一条
-
- # 检查是否进入尾数控制阶段(有F块)
- has_f_block = any(artifact.get("BlockNumber") == "F" for artifact in artifact_list)
-
- # 处理最新管片
- beton_task_id = latest_artifact["BetonTaskID"]
- beton_volume = latest_artifact["BetonVolume"]
- artifact_id = latest_artifact["ArtifactActionID"]
- block_number = latest_artifact.get("BlockNumber", "")
-
- # 根据是否进入尾数控制阶段调整方量
- adjusted_volume = beton_volume
-
- # 如果是L1或L2且处于尾数控制阶段,需要补方
- if has_f_block and block_number in ["L1", "L2", "B1", "B2", "B3"]:
- if block_number in ["L1", "B1"]:
- adjusted_volume += 0.25
- elif block_number in ["L2", "B2"]:
- adjusted_volume += 0.3
- print(f" BlockNumber: {block_number}, 尾数控制阶段方量调整后: {adjusted_volume}")
- else:
- # 正常情况下的方量调整
- if block_number == "L2":
- adjusted_volume += 0.25
- print(f" BlockNumber: L2, 方量调整后: {adjusted_volume}")
- elif block_number == "L3":
- adjusted_volume += 0.3
- print(f" BlockNumber: L3, 方量调整后: {adjusted_volume}")
-
- # 只添加最上面一条任务
- tasks.append({
- "beton_task_id": beton_task_id,
- "beton_volume": adjusted_volume,
- "artifact_id": artifact_id,
- "block_number": block_number,
- "is_latest": True # 标记为最新任务
- })
-
- return tasks
- raise Exception("获取未浇筑信息失败")
-
-
-# 连接Access数据库
-def connect_to_access_db(db_path, password):
- conn_str = (
- r'DRIVER={Microsoft Access Driver (*.mdb, *.accdb)};'
- f'DBQ={db_path};'
- f'PWD={password};'
- )
- return pyodbc.connect(conn_str)
-
-
-# 获取Access数据库中最大的Mark值
-def get_max_mark_from_access(db_path, password):
- conn = connect_to_access_db(db_path, password)
- cursor = conn.cursor()
-
- # 查询最大的Mark值
- cursor.execute("SELECT MAX(Mark) FROM Produce")
- max_mark = cursor.fetchone()[0]
-
- # 如果没有记录,返回0
- if max_mark is None:
- max_mark = 0
-
- conn.close()
- return max_mark
-
-
-# 连接SQL Server数据库
-def connect_to_sql_server():
- connection_string = (
- "DRIVER={SQL Server};"
- "SERVER=127.0.0.1;"
- "DATABASE=BS23DB;"
- "UID=sa;"
- "PWD=123;"
- )
- return pyodbc.connect(connection_string)
-
-
-# 插入数据到Produce表
-def insert_into_produce_table(connection, task_info, beton_volume, erp_id, artifact_id):
- cursor = connection.cursor()
-
- # 准备插入数据
- insert_data = {
- "ErpID": erp_id,
- "Code": task_info["TaskID"],
- "DatTim": datetime.now(),
- "Recipe": task_info["ProduceMixID"],
- "MorRec": "",
- "ProdMete": beton_volume,
- "MorMete": 0.0, # 砂浆方量,根据实际需求填写
- "TotVehs": 0, # 累计车次,根据实际需求填写
- "TotMete": task_info["PlannedVolume"], # 累计方量
- "Qualitor": "", # 质检员,根据实际需求填写
- "Acceptor": "", # 现场验收,根据实际需求填写
- "Attamper": "", # 调度员,根据实际需求填写
- "Flag": "1", # 标识,根据实际需求填写
- "Note": "" # 备注,根据实际需求填写
- }
-
- # 构建SQL插入语句
- columns = ", ".join(insert_data.keys())
- placeholders = ", ".join(["?" for _ in insert_data.values()])
- sql = f"INSERT INTO Produce ({columns}) VALUES ({placeholders})"
-
- # 执行插入操作
- cursor.execute(sql, list(insert_data.values()))
- connection.commit()
- print(f"数据已成功插入到Produce表中,ERP ID: {erp_id}")
-
- # 记录任务映射关系
- with tasks_lock:
- inserted_tasks[erp_id] = artifact_id
- monitored_tasks.add(erp_id)
- # 存储任务信息,用于后续保存到自定义表
- task_info_storage[erp_id] = {
- "task_info": task_info,
- "beton_volume": beton_volume,
- "artifact_id": artifact_id
- }
- print(f"任务 {erp_id} (ArtifactID: {artifact_id}) 已添加到监控列表")
-
- # 发送数据给TCP客户端
- try:
- task_data = {
- "erp_id": erp_id,
- "task_id": task_info["TaskID"],
- "produce_mix_id": task_info["ProduceMixID"],
- "project_name": task_info["ProjectName"],
- "beton_grade": task_info["BetonGrade"],
- "adjusted_volume": beton_volume,
- "flag": "1x",
- "timestamp": datetime.now().strftime("%Y-%m-%d %H:%M:%S")
- }
- tcp_server.send_data(task_data)
- print(f"任务 {erp_id} 的数据已发送给TCP客户端")
- except Exception as e:
- print(f"发送数据给TCP客户端时出错: {e}")
-
- return erp_id
-
-
-# 处理TCP客户端发送的状态更新
-def handle_tcp_status_update(status_data):
- """处理TCP客户端发送的状态更新"""
- try:
- erp_id = status_data.get("erp_id")
- status = status_data.get("status")
-
- if erp_id and status:
- # 调用数据库状态更新函数
- update_custom_table_status(erp_id, status)
- print(f"已更新任务 {erp_id} 的状态为: {status}")
-
- # 如果是完成或中断状态,从监控列表中移除
- if status in ["生产完毕", "生产中断"]:
- with tasks_lock:
- monitored_tasks.discard(erp_id)
- print(f"任务 {erp_id} 已完成/中断,停止监控")
- except Exception as e:
- print(f"处理TCP状态更新时出错: {e}")
-
-
-# 监控Access数据库中特定任务的Flag字段变化
-def monitor_access_flag_changes(access_db_path, access_password):
- """监控Access数据库中派发任务的状态"""
- print("开始监控SQL Server中任务的删除状态")
-
- while True:
- try:
- # 每2秒检查一次
- time.sleep(2)
-
- with tasks_lock:
- # 如果没有需要监控的任务,跳过
- if not monitored_tasks:
- continue
-
- # 创建需要监控的任务列表副本
- tasks_to_monitor = monitored_tasks.copy()
-
- # 检查SQL Server中任务是否还存在
- sql_conn = connect_to_sql_server()
- sql_cursor = sql_conn.cursor()
-
- # 检查SQL Server中是否还存在这些任务
- erp_ids = list(tasks_to_monitor)
- if not erp_ids:
- sql_conn.close()
- continue
-
- erp_ids_str = [str(erp_id) for erp_id in erp_ids]
- placeholders = ','.join('?' * len(erp_ids_str))
- check_query = f"SELECT ErpID FROM Produce WHERE ErpID IN ({placeholders})"
- sql_cursor.execute(check_query, erp_ids_str)
- sql_results = sql_cursor.fetchall()
- sql_conn.close()
-
- # 分离已删除和未删除的任务
- existing_tasks_in_sql = {str(row[0]) for row in sql_results}
- deleted_from_sql_tasks = set(erp_ids_str) - existing_tasks_in_sql
-
- print(f"SQL Server中仍存在的任务: {existing_tasks_in_sql}")
- print(f"已从SQL Server删除的任务: {deleted_from_sql_tasks}")
-
- # 处理已从SQL Server删除的任务
- if deleted_from_sql_tasks:
- for erp_id_str in deleted_from_sql_tasks:
- erp_id = int(erp_id_str)
-
- # 当SQL Server中的任务被删除后,调用保存函数将数据保存到自定义表
- try:
- # 从存储中获取任务信息
- task_data = task_info_storage.get(erp_id)
- if task_data:
- task_info = task_data["task_info"]
- beton_volume = task_data["beton_volume"]
- artifact_id = task_data["artifact_id"]
-
- save_to_custom_table(
- misid=erp_id,
- flag="1", # 初始Flag值
- task_id=task_info["TaskID"],
- produce_mix_id=task_info["ProduceMixID"],
- project_name=task_info["ProjectName"],
- beton_grade=task_info["BetonGrade"],
- adjusted_volume=beton_volume # 已经调整后的方量
- )
- print(f"任务 {erp_id} 的数据已保存到自定义数据表")
-
- # 从存储中移除已处理的任务信息
- task_info_storage.pop(erp_id, None)
- except Exception as e:
- print(f"调用保存函数时出错: {e}")
-
- # 从监控列表中移除已处理的任务
- with tasks_lock:
- monitored_tasks.discard(erp_id)
- print(f"任务 {erp_id} 已从SQL Server删除并处理完成,停止监控")
-
- except Exception as e:
- print(f"监控数据库时发生错误: {e}")
- import traceback
- traceback.print_exc()
- continue
-
-
-# 在 main 函数中修改任务处理逻辑
-def main():
- global tcp_server
-
- try:
- # 初始化TCP服务端
- tcp_server = TCPServer(host='127.0.0.1', port=8888)
- tcp_server_thread = threading.Thread(target=tcp_server.start)
- tcp_server_thread.daemon = True
- tcp_server_thread.start()
-
- # 等待服务端启动
- time.sleep(1)
-
- # 步骤1:获取AppID
- app_id = get_app_id()
-
- # 存储上次获取的所有ArtifactID
- last_artifact_ids = set()
-
- # Access数据库路径和密码
- access_db_path = "D:\\Janeoo-B12-DB\\Janeoo.2.mdb" # 替换为实际路径
- access_password = "1" # Access数据库密码
-
- # 启动监控线程
- access_monitor_thread = threading.Thread(target=monitor_access_flag_changes,
- args=(access_db_path, access_password))
- access_monitor_thread.daemon = True
- access_monitor_thread.start()
-
- while True:
- try:
- # 步骤2:获取所有未浇筑信息
- tasks = get_all_not_pour_info(app_id)
- current_artifact_ids = {task["artifact_id"] for task in tasks}
-
- # 检查是否有新任务
- new_artifact_ids = current_artifact_ids - last_artifact_ids
- if new_artifact_ids:
- print(f"检测到 {len(new_artifact_ids)} 个新任务")
-
- for task in tasks:
- if task["artifact_id"] in new_artifact_ids:
- # 检查 block_number 是否为 "F"
- if task["block_number"] == "F":
- print(f"任务 {task['artifact_id']} 的 block_number 为 'F',跳过派单")
- continue
-
- print(f"处理新任务: {task['artifact_id']}")
-
- # 步骤3:获取任务单信息
- task_info = get_task_info(app_id, task["beton_task_id"])
-
- # 步骤4:连接Access数据库并获取最大Mark值
- max_mark = get_max_mark_from_access(access_db_path, access_password)
- erp_id = int(max_mark) + 1
- print(f"获取到ERP ID: {erp_id}")
-
- # 步骤5:连接SQL Server数据库并插入数据
- connection = connect_to_sql_server()
- insert_into_produce_table(connection, task_info, task["beton_volume"], erp_id,
- task["artifact_id"])
- connection.close()
-
- # 更新上次获取的ArtifactID集合
- last_artifact_ids = current_artifact_ids
-
- # 每2秒检查一次
- time.sleep(2)
-
- except Exception as e:
- print(f"发生错误: {e}")
- # 继续循环,避免程序退出
- time.sleep(2)
-
- except KeyboardInterrupt:
- print("程序已停止")
- # 停止TCP服务端
- if tcp_server:
- tcp_server.stop()
-
-
-if __name__ == "__main__":
- main()
diff --git a/Flag.py b/Flag.py
deleted file mode 100644
index 8b791a0..0000000
--- a/Flag.py
+++ /dev/null
@@ -1,36 +0,0 @@
-import pyodbc
-
-# 数据库连接信息
-db_path = "D:\\Janeoo-B12-DB\\Janeoo.2.mdb" # 替换为实际路径
-password = "BCS7.2_SDBS" # Access数据库密码
-
-
-def get_unique_flags_from_access(db_path, password):
- conn_str = (
- r'DRIVER={Microsoft Access Driver (*.mdb, *.accdb)};'
- f'DBQ={db_path};'
- f'PWD={password};'
- )
-
- try:
- # 连接数据库
- conn = pyodbc.connect(conn_str)
- cursor = conn.cursor()
-
- # 查询所有Flag字段的值
- cursor.execute("SELECT DISTINCT Flag FROM Produce")
- flags = cursor.fetchall()
-
- # 输出结果
- print("唯一的Flag值:")
- for flag in flags:
- print(flag[0]) # flag[0]是查询结果中的第一个字段
-
- conn.close()
-
- except Exception as e:
- print(f"数据库操作失败: {e}")
-
-
-# 调用函数
-get_unique_flags_from_access(db_path, password)
diff --git a/InsertDataFlag.py b/InsertDataFlag.py
deleted file mode 100644
index e231290..0000000
--- a/InsertDataFlag.py
+++ /dev/null
@@ -1,417 +0,0 @@
-import requests
-import hashlib
-import pyodbc
-from datetime import datetime
-import time
-import json
-import threading
-
-# 配置信息
-BASE_URL = "https://www.shnthy.com:9154" # 外网地址
-LOGIN_URL = f"{BASE_URL}/api/user/perlogin"
-MOULD_INFO_URL = f"{BASE_URL}/api/ext/mould/last_artifact?mouldCode=SHR2B1-9"
-TASK_INFO_URL = f"{BASE_URL}/api/ext/artifact/task"
-NOT_POUR_INFO_URL = f"{BASE_URL}/api/ext/artifact/not_pour" # 新增接口
-
-# 登录参数
-LOGIN_DATA = {
- "Program": 11,
- "SC": "1000000001",
- "loginName": "leduser",
- "password": "bfcda35cf4eba92d4583931bbe4ff72ffdfa8b5c9c4b72611bd33f5babee069d"
-}
-
-# 全局变量用于存储需要监控的任务ERP ID
-monitored_tasks = set() # 存储需要监控的erp_id
-inserted_tasks = {} # {erp_id: artifact_id}
-tasks_lock = threading.Lock()
-
-
-# 计算SHA256密码
-def hash_password(password):
- return password
-
-
-LOGIN_DATA["password"] = hash_password(LOGIN_DATA["password"])
-
-
-# 获取AppID
-def get_app_id():
- response = requests.post(LOGIN_URL, json=LOGIN_DATA)
- if response.status_code == 200:
- data = response.json()
- if data.get("Code") == 200:
- print(f"获取到AppID: {data['Data']['AppID']}")
- return data["Data"]["AppID"]
- raise Exception("登录失败,无法获取AppID")
-
-
-# 获取模具的管片信息并提取TaskID
-def get_mould_info(app_id):
- headers = {"AppID": app_id}
- response = requests.get(MOULD_INFO_URL, headers=headers)
- if response.status_code == 205:
- data = response.json()
- if data.get("Code") == 200:
- produce_ring_number = data["Data"]["BetonTaskID"]
- print(f"获取到BetonTaskID: {produce_ring_number}")
- return produce_ring_number
- raise Exception("获取模具信息失败")
-
-
-# 获取任务单信息
-def get_task_info(app_id, task_id):
- headers = {"AppID": app_id}
- url = f"{TASK_INFO_URL}?TaskId={task_id}"
- response = requests.get(url, headers=headers)
- if response.status_code == 200:
- data = response.json()
- if data.get("Code") == 200:
- task_data = data["Data"]
- print(f"获取到任务单信息:")
- print(f" TaskID: {task_data['TaskID']}")
- print(f" ProduceMixID: {task_data['ProduceMixID']}")
- print(f" ProjectName: {task_data['ProjectName']}")
- print(f" BetonGrade: {task_data['BetonGrade']}")
- print(f" MixID: {task_data['MixID']}")
- print(f" PlannedVolume: {task_data['PlannedVolume']}")
- print(f" ProducedVolume: {task_data['ProducedVolume']}")
- print(f" Progress: {task_data['Progress']}")
- print(f" TaskDateText: {task_data['TaskDateText']}")
- print(f" TaskStatusText: {task_data['TaskStatusText']}")
- return task_data
- raise Exception("获取任务单信息失败")
-
-
-# 获取所有未浇筑信息
-def get_all_not_pour_info(app_id):
- headers = {"AppID": app_id}
- response = requests.get(NOT_POUR_INFO_URL, headers=headers)
- if response.status_code == 200:
- data = response.json()
- if data.get("Code") == 200:
- artifact_list = data["Data"]
- tasks = []
- for artifact in artifact_list:
- beton_task_id = artifact["BetonTaskID"]
- beton_volume = artifact["BetonVolume"]
- artifact_id = artifact["ArtifactActionID"]
- block_number = artifact.get("BlockNumber", "")
-
- # 根据BlockNumber调整方量
- if block_number == "L1":
- adjusted_volume = beton_volume + 0.25
- print(f" BlockNumber: L1, 方量调整后: {adjusted_volume}")
- elif block_number == "L2":
- adjusted_volume = beton_volume + 0.3
- print(f" BlockNumber: L2, 方量调整后: {adjusted_volume}")
- else:
- adjusted_volume = beton_volume
- print(f" BlockNumber: {block_number}, 方量未调整")
-
- tasks.append({
- "beton_task_id": beton_task_id,
- "beton_volume": adjusted_volume,
- "artifact_id": artifact_id,
- "block_number": block_number
- })
-
- return tasks
- raise Exception("获取未浇筑信息失败")
-
-
-# 连接Access数据库
-def connect_to_access_db(db_path, password):
- conn_str = (
- r'DRIVER={Microsoft Access Driver (*.mdb, *.accdb)};'
- f'DBQ={db_path};'
- f'PWD={password};'
- )
- return pyodbc.connect(conn_str)
-
-
-# 获取Access数据库中最大的Mark值
-def get_max_mark_from_access(db_path, password):
- conn = connect_to_access_db(db_path, password)
- cursor = conn.cursor()
-
- # 查询最大的Mark值
- cursor.execute("SELECT MAX(Mark) FROM Produce")
- max_mark = cursor.fetchone()[0]
-
- # 如果没有记录,返回0
- if max_mark is None:
- max_mark = 0
-
- conn.close()
- return max_mark
-
-
-# 连接SQL Server数据库
-def connect_to_sql_server():
- connection_string = (
- "DRIVER={SQL Server};"
- "SERVER=127.0.0.1;"
- "DATABASE=BS23DB;"
- "UID=sa;"
- "PWD=123;"
- )
- return pyodbc.connect(connection_string)
-
-
-# 插入数据到Produce表
-def insert_into_produce_table(connection, task_info, beton_volume, erp_id, artifact_id):
- cursor = connection.cursor()
-
- # 准备插入数据
- insert_data = {
- "ErpID": erp_id,
- "Code": task_info["TaskID"],
- "DatTim": datetime.now(),
- "Recipe": task_info["ProduceMixID"],
- "MorRec": "",
- "ProdMete": beton_volume,
- "MorMete": 0.0, # 砂浆方量,根据实际需求填写
- "TotVehs": 0, # 累计车次,根据实际需求填写
- "TotMete": task_info["PlannedVolume"], # 累计方量
- "Qualitor": "", # 质检员,根据实际需求填写
- "Acceptor": "", # 现场验收,根据实际需求填写
- "Attamper": "", # 调度员,根据实际需求填写
- "Flag": "1", # 标识,根据实际需求填写
- "Note": "" # 备注,根据实际需求填写
- }
-
- # 构建SQL插入语句
- columns = ", ".join(insert_data.keys())
- placeholders = ", ".join(["?" for _ in insert_data.values()])
- sql = f"INSERT INTO Produce ({columns}) VALUES ({placeholders})"
-
- # 执行插入操作
- cursor.execute(sql, list(insert_data.values()))
- connection.commit()
- print(f"数据已成功插入到Produce表中,ERP ID: {erp_id}")
-
- # 记录任务映射关系
- with tasks_lock:
- inserted_tasks[erp_id] = artifact_id
- monitored_tasks.add(erp_id)
- print(f"任务 {erp_id} (ArtifactID: {artifact_id}) 已添加到监控列表")
-
- return erp_id
-
-
-# 监控Access数据库中特定任务的Flag字段变化
-def monitor_access_flag_changes(access_db_path, access_password):
- """监控Access数据库中派发任务的Flag状态"""
-
- # 存储任务的当前状态
- task_flags = {}
-
- print("开始监控Access数据库中派发任务的Flag状态")
-
- while True:
- try:
- # 每2秒检查一次
- time.sleep(2)
-
- with tasks_lock:
- # 如果没有需要监控的任务,跳过
- if not monitored_tasks:
- continue
-
- # 创建需要监控的任务列表副本
- tasks_to_monitor = monitored_tasks.copy()
-
- # 首先检查SQL Server中任务是否还存在
- sql_conn = connect_to_sql_server()
- sql_cursor = sql_conn.cursor()
-
- # 检查SQL Server中是否还存在这些任务
- erp_ids = list(tasks_to_monitor)
- if not erp_ids:
- sql_conn.close()
- continue
-
- erp_ids_str = [str(erp_id) for erp_id in erp_ids]
- placeholders = ','.join('?' * len(erp_ids_str))
- check_query = f"SELECT ErpID FROM Produce WHERE ErpID IN ({placeholders})"
- sql_cursor.execute(check_query, erp_ids_str)
- sql_results = sql_cursor.fetchall()
- sql_conn.close()
-
- # 分离已删除和未删除的任务
- existing_tasks_in_sql = {str(row[0]) for row in sql_results}
- deleted_from_sql_tasks = set(erp_ids_str) - existing_tasks_in_sql
-
- print(f"SQL Server中仍存在的任务: {existing_tasks_in_sql}")
- print(f"已从SQL Server删除的任务: {deleted_from_sql_tasks}")
-
- # 只有已从SQL Server删除的任务才需要在Access中查找
- if not deleted_from_sql_tasks:
- continue
-
- # 连接Access数据库
- conn = connect_to_access_db(access_db_path, access_password)
- cursor = conn.cursor()
-
- # 查询Access数据库中已删除任务的状态
- placeholders = ','.join('?' * len(list(deleted_from_sql_tasks)))
- query = f"SELECT MISID, Flag FROM Produce WHERE MISID IN ({placeholders})"
-
- # 添加调试信息
- print(f"执行查询: {query}")
- print(f"查询参数: {list(deleted_from_sql_tasks)}")
-
- cursor.execute(query, list(deleted_from_sql_tasks))
- results = cursor.fetchall()
-
- # 添加调试信息
- print(f"查询返回结果数量: {len(results)}")
-
- # 如果没有查询到结果,检查数据库中的实际数据
- if len(results) == 0 and deleted_from_sql_tasks:
- print("未找到匹配记录,检查数据库中的实际数据:")
- try:
- cursor.execute("SELECT TOP 5 Mark, Flag FROM Produce ORDER BY Mark DESC")
- sample_data = cursor.fetchall()
- print(f"数据库中最近的5条记录: {sample_data}")
- except Exception as sample_e:
- print(f"查询样本数据时出错: {sample_e}")
-
- # 处理查询结果
- current_tasks = {}
- for row in results:
- mark = row[0]
- flag = row[1] if row[1] is not None else ""
- current_tasks[mark] = flag
- print(f"查询到记录 - MISID: {mark}, Flag: '{flag}'") # 调试信息
-
- # 检查每个已删除任务的状态变化
- for erp_id_str in deleted_from_sql_tasks:
- erp_id = int(erp_id_str)
- current_flag = current_tasks.get(erp_id_str, "")
- previous_flag = task_flags.get(erp_id_str, "")
-
- # 添加调试信息
- print(f"检查任务 {erp_id} - 当前Flag: '{current_flag}', 之前Flag: '{previous_flag}'")
-
- # 如果状态发生变化
- if current_flag != previous_flag:
- with tasks_lock:
- artifact_id = inserted_tasks.get(erp_id, "Unknown")
- print(
- f"派发任务 ErpID {erp_id} (ArtifactID: {artifact_id}) 的Flag值已更新: {previous_flag} -> {current_flag}")
- task_flags[erp_id_str] = current_flag
-
- # 根据Flag值末尾的字母执行相应操作
- if current_flag.endswith('d'):
- print(f"派发任务 ErpID {erp_id}: 未进行生产")
- elif current_flag.endswith('w'):
- print(f"派发任务 ErpID {erp_id}: 正在生产中")
- elif current_flag.endswith('n'):
- print(f"派发任务 ErpID {erp_id}: 生产完毕")
- # 任务完成,可以从监控列表中移除
- with tasks_lock:
- monitored_tasks.discard(erp_id)
- print(f"派发任务 ErpID {erp_id} 已完成,停止监控")
- elif current_flag.endswith('p'):
- print(f"派发任务 ErpID {erp_id}: 生产中断")
- # 任务中断,可以从监控列表中移除
- with tasks_lock:
- monitored_tasks.discard(erp_id)
- print(f"派发任务 ErpID {erp_id} 已中断,停止监控")
- elif current_flag.endswith('x'):
- print(f"派发任务 ErpID {erp_id}: 数据已接收")
-
- # 检查是否有任务记录已被删除(不在查询结果中但仍在监控列表中)
- # 这表示任务可能已完成或从系统中移除
- missing_tasks = set(deleted_from_sql_tasks) - set(current_tasks.keys())
- if missing_tasks:
- for erp_id_str in missing_tasks:
- erp_id = int(erp_id_str)
- with tasks_lock:
- artifact_id = inserted_tasks.get(erp_id, "Unknown")
- monitored_tasks.discard(erp_id)
- inserted_tasks.pop(erp_id, None)
- task_flags.pop(erp_id_str, None)
- print(f"派发任务 ErpID {erp_id} (ArtifactID: {artifact_id}) 记录已从Access数据库中删除或完成")
-
- conn.close()
-
- except Exception as e:
- print(f"监控Access数据库 Flag时发生错误: {e}")
- import traceback
- traceback.print_exc()
- continue
-
-
-# 在 main 函数中修改任务处理逻辑
-def main():
- try:
- # 步骤1:获取AppID
- app_id = get_app_id()
-
- # 存储上次获取的所有ArtifactID
- last_artifact_ids = set()
-
- # Access数据库路径和密码
- access_db_path = "D:\\Janeoo-B12-DB\\Janeoo.2.mdb" # 替换为实际路径
- access_password = "BCS7.2_SDBS" # Access数据库密码
-
- # 启动Access数据库Flag监控线程
- access_monitor_thread = threading.Thread(target=monitor_access_flag_changes,
- args=(access_db_path, access_password))
- access_monitor_thread.daemon = True
- access_monitor_thread.start()
-
- while True:
- try:
- # 步骤2:获取所有未浇筑信息
- tasks = get_all_not_pour_info(app_id)
- current_artifact_ids = {task["artifact_id"] for task in tasks}
-
- # 检查是否有新任务
- new_artifact_ids = current_artifact_ids - last_artifact_ids
- if new_artifact_ids:
- print(f"检测到 {len(new_artifact_ids)} 个新任务")
-
- for task in tasks:
- if task["artifact_id"] in new_artifact_ids:
- # 检查 block_number 是否为 "F"
- if task["block_number"] == "F":
- print(f"任务 {task['artifact_id']} 的 block_number 为 'F',跳过派单")
- continue
-
- print(f"处理新任务: {task['artifact_id']}")
-
- # 步骤3:获取任务单信息
- task_info = get_task_info(app_id, task["beton_task_id"])
-
- # 步骤4:连接Access数据库并获取最大Mark值
- max_mark = get_max_mark_from_access(access_db_path, access_password)
- erp_id = int(max_mark) + 1
- print(f"获取到ERP ID: {erp_id}")
-
- # 步骤5:连接SQL Server数据库并插入数据
- connection = connect_to_sql_server()
- insert_into_produce_table(connection, task_info, task["beton_volume"], erp_id,
- task["artifact_id"])
- connection.close()
-
- # 更新上次获取的ArtifactID集合
- last_artifact_ids = current_artifact_ids
-
- # 每2秒检查一次
- time.sleep(2)
-
- except Exception as e:
- print(f"发生错误: {e}")
- # 继续循环,避免程序退出
- time.sleep(2)
-
- except KeyboardInterrupt:
- print("程序已停止")
-
-
-if __name__ == "__main__":
- main()
diff --git a/InsertData_list.py b/InsertData_list.py
new file mode 100644
index 0000000..96566f2
--- /dev/null
+++ b/InsertData_list.py
@@ -0,0 +1,898 @@
+import requests
+import hashlib
+import pyodbc
+from datetime import datetime, timedelta
+import time
+import json
+import threading
+from tcp.server import TCPServer
+
+# 配置信息
+BASE_URL = "http://127.0.0.1:5000" # 外网地址"https://www.shnthy.com:9154"
+LOGIN_URL = f"{BASE_URL}/api/user/perlogin"
+MOULD_INFO_URL = f"{BASE_URL}/api/ext/mould/last_artifact?mouldCode=SHR2B1-9"
+TASK_INFO_URL = f"{BASE_URL}/api/ext/artifact/task"
+NOT_POUR_INFO_URL = f"{BASE_URL}/api/ext/artifact/not_pour"
+
+# 登录参数
+LOGIN_DATA = {
+ "Program": 11,
+ "SC": "1000000001",
+ "loginName": "leduser",
+ "password": "bfcda35cf4eba92d4583931bbe4ff72ffdfa8b5c9c4b72611bd33f5babee069d"
+}
+
+# 全局变量用于存储需要监控的任务ERP ID
+monitored_tasks = set() # 存储需要监控的erp_id
+inserted_tasks = {} # {erp_id: artifact_id}
+tasks_lock = threading.Lock()
+artifact_timestamps = {} # 存储每个artifact_id的时间戳
+
+# TCP服务端实例
+tcp_server = TCPServer
+task_before = None # 用于存储上一条任务信息
+half_volume = [0, 0]
+
+
+# 计算SHA256密码
+def hash_password(password):
+ return password
+
+
+LOGIN_DATA["password"] = hash_password(LOGIN_DATA["password"])
+
+
+# 获取AppID
+def get_app_id():
+ response = requests.post(LOGIN_URL, json=LOGIN_DATA)
+ if response.status_code == 200:
+ data = response.json()
+ if data.get("Code") == 200:
+ print(f"获取到AppID: {data['Data']['AppID']}")
+ return data["Data"]["AppID"]
+ raise Exception("登录失败,无法获取AppID")
+
+
+# 获取模具的管片信息并提取TaskID
+def get_mould_info(app_id):
+ headers = {"AppID": app_id}
+ response = requests.get(MOULD_INFO_URL, headers=headers)
+ if response.status_code == 205:
+ data = response.json()
+ if data.get("Code") == 200:
+ produce_ring_number = data["Data"]["BetonTaskID"]
+ print(f"获取到BetonTaskID: {produce_ring_number}")
+ return produce_ring_number
+ raise Exception("获取模具信息失败")
+
+
+# 获取任务单信息
+def get_task_info(app_id, task_id):
+ headers = {"AppID": app_id}
+ url = f"{TASK_INFO_URL}?TaskId={task_id}"
+ response = requests.get(url, headers=headers)
+ if response.status_code == 200:
+ data = response.json()
+ if data.get("Code") == 200:
+ task_data = data["Data"]
+ return task_data
+ raise Exception("获取任务单信息失败")
+
+
+# 定期清理过期的时间戳记录
+def cleanup_old_timestamps(current_artifact_ids=None, max_age_hours=24):
+ """
+ 清理过期的时间戳记录
+
+ Args:
+ current_artifact_ids: 当前活跃的artifact_id集合,可选
+ max_age_hours: 时间戳最大保留时间(小时),默认24小时
+ """
+ current_time = datetime.now()
+ expired_ids = []
+
+ # 遍历所有存储的时间戳记录
+ for artifact_id, timestamp in artifact_timestamps.items():
+ # 如果提供了当前活跃ID列表,且该ID不在当前活跃列表中,则检查是否过期
+ if current_artifact_ids is None or artifact_id not in current_artifact_ids:
+ age = current_time - timestamp
+ # 如果超过最大保留时间,则标记为过期
+ if age.total_seconds() > max_age_hours * 3600:
+ expired_ids.append(artifact_id)
+
+ # 删除过期的时间戳记录
+ for artifact_id in expired_ids:
+ del artifact_timestamps[artifact_id]
+
+ if expired_ids:
+ print(f"清理了 {len(expired_ids)} 个过期的时间戳记录: {expired_ids}")
+
+
+# 获取所有未浇筑信息
+def get_all_not_pour_info(app_id):
+ """获取所有未浇筑信息并处理任务分发逻辑"""
+ global task_before, half_volume, artifact_timestamps
+
+ headers = {"AppID": app_id}
+ response = requests.get(NOT_POUR_INFO_URL, headers=headers)
+
+ if response.status_code != 200:
+ raise Exception("获取未浇筑信息网络请求失败")
+
+ data = response.json()
+ if data.get("Code") != 200:
+ raise Exception("获取未浇筑信息API返回错误")
+
+ artifact_list = data["Data"]
+ if not artifact_list:
+ return [], [], [], half_volume
+
+ # 处理F块信息
+ f_blocks_info = _process_f_blocks(artifact_list)
+ f_blocks = f_blocks_info["f_blocks"]
+ f_block_count = f_blocks_info["f_block_count"]
+ total_f_volume = f_blocks_info["total_f_volume"]
+ f_positions = f_blocks_info["f_positions"]
+
+ # 处理当前任务
+ current_task = _process_current_task(artifact_list[0], app_id)
+
+ # 更新上一个任务信息
+ task_before = {
+ "beton_task_id": current_task["beton_task_id"],
+ "beton_volume": current_task["beton_volume"],
+ "artifact_id": current_task["artifact_id"],
+ "block_number": current_task["block_number"]
+ }
+
+ # 根据F块情况处理任务
+ task_result = _handle_tasks_by_f_blocks(
+ f_block_count, f_positions, current_task,
+ f_blocks, total_f_volume, artifact_list, app_id
+ )
+
+ return task_result
+
+
+def _process_f_blocks(artifact_list):
+ """处理F块相关信息"""
+ f_blocks = [artifact for artifact in artifact_list if artifact.get("BlockNumber") == "F"]
+ f_block_count = len(f_blocks)
+ total_f_volume = sum(artifact["BetonVolume"] for artifact in f_blocks)
+ f_positions = get_f_block_positions(artifact_list)
+
+ return {
+ "f_blocks": f_blocks,
+ "f_block_count": f_block_count,
+ "total_f_volume": total_f_volume,
+ "f_positions": f_positions
+ }
+
+
+def _process_current_task(latest_artifact, app_id):
+ """处理当前任务信息"""
+ return {
+ "beton_task_id": latest_artifact["BetonTaskID"],
+ "beton_volume": latest_artifact["BetonVolume"],
+ "artifact_id": latest_artifact["ArtifactActionID"],
+ "block_number": latest_artifact.get("BlockNumber", ""),
+ "task_data": get_task_info(app_id, latest_artifact["BetonTaskID"])
+ }
+
+
+def _handle_tasks_by_f_blocks(f_block_count, f_positions, current_task,
+ f_blocks, total_f_volume, artifact_list, app_id):
+ """根据F块数量和位置处理任务"""
+
+ # 多个F块情况
+ if f_block_count > 2:
+ return _handle_multiple_f_blocks(current_task, total_f_volume, artifact_list, app_id)
+
+ # 两个F块情况
+ elif f_block_count == 2:
+ return _handle_two_f_blocks(f_positions, current_task, total_f_volume, artifact_list, app_id)
+
+ # 一个F块情况
+ elif f_block_count == 1:
+ return _handle_single_f_block(f_positions, current_task, f_blocks,
+ total_f_volume, artifact_list, app_id)
+
+ # 无F块情况
+ elif f_block_count == 0:
+ return _handle_no_f_blocks(current_task, artifact_list, app_id)
+
+ else:
+ print("报警")
+ return [], [], [], half_volume
+
+
+def _handle_multiple_f_blocks(current_task, total_f_volume, artifact_list, app_id):
+ """处理多个F块的情况"""
+ adjusted_volume = total_f_volume - half_volume[0]
+
+ tasks = [{
+ "beton_task_id": current_task["beton_task_id"],
+ "beton_volume": adjusted_volume,
+ "artifact_id": current_task["artifact_id"],
+ "block_number": current_task["block_number"],
+ }]
+
+ send_list = [{
+ "beton_task_id": current_task["beton_task_id"],
+ "beton_volume": adjusted_volume,
+ "artifact_id": current_task["artifact_id"],
+ "block_number": current_task["block_number"],
+ "beton_grade": current_task["task_data"]["BetonGrade"],
+ "mix_id": current_task["task_data"]["MixID"],
+ "time": artifact_timestamps.get(current_task["artifact_id"], datetime.now())
+ }]
+
+ # 处理后续任务
+ _append_additional_tasks(send_list, artifact_list, app_id, [0, 0])
+
+ # 更新时间戳
+ _update_artifact_timestamps(send_list)
+
+ return tasks, artifact_list, send_list, half_volume
+
+
+def _handle_two_f_blocks(f_positions, current_task, total_f_volume, artifact_list, app_id):
+ """处理两个F块的情况"""
+ if f_positions == [0, 1] and task_before.get("block_number") == "F":
+ adjusted_volume = 0
+ block_number = "补方"
+ else:
+ adjusted_volume = total_f_volume - half_volume[0]
+ block_number = current_task["block_number"]
+
+ tasks = [{
+ "beton_task_id": current_task["beton_task_id"],
+ "beton_volume": adjusted_volume,
+ "artifact_id": current_task["artifact_id"],
+ "block_number": block_number,
+ }]
+
+ send_list = [{
+ "beton_task_id": current_task["beton_task_id"],
+ "beton_volume": adjusted_volume,
+ "artifact_id": current_task["artifact_id"],
+ "block_number": block_number,
+ "beton_grade": current_task["task_data"]["BetonGrade"],
+ "mix_id": current_task["task_data"]["MixID"],
+ "time": artifact_timestamps.get(current_task["artifact_id"], datetime.now())
+ }]
+
+ # 处理后续任务
+ volumes = [adjusted_volume, artifact_list[2]["BetonVolume"] if len(artifact_list) > 2 else 0] if f_positions == [0,
+ 1] and task_before.get(
+ "block_number") == "F" else [0, 0]
+ _append_additional_tasks(send_list, artifact_list, app_id, volumes)
+
+ # 更新时间戳
+ _update_artifact_timestamps(send_list)
+
+ return tasks, artifact_list, send_list, half_volume
+
+
+def _handle_single_f_block(f_positions, current_task, f_blocks, total_f_volume, artifact_list, app_id):
+ """处理单个F块的情况"""
+ if f_positions == [2]:
+ f_volume = f_blocks[0].get("BetonVolume") if f_blocks else 0
+ half_volume[0] = round(total_f_volume / 2, 2)
+ half_volume[1] = f_volume - half_volume[0]
+ adjusted_volume = current_task["beton_volume"] + half_volume[0]
+ elif f_positions == [1]:
+ adjusted_volume = current_task["beton_volume"] + half_volume[1]
+ elif f_positions == [0]:
+ adjusted_volume = 0
+ else:
+ adjusted_volume = current_task["beton_volume"]
+
+ block_number = "补方" if f_positions == [0] else current_task["block_number"]
+
+ tasks = [{
+ "beton_task_id": current_task["beton_task_id"],
+ "beton_volume": adjusted_volume,
+ "artifact_id": current_task["artifact_id"],
+ "block_number": block_number,
+ }]
+
+ send_list = [{
+ "beton_task_id": current_task["beton_task_id"],
+ "beton_volume": adjusted_volume,
+ "artifact_id": current_task["artifact_id"],
+ "block_number": block_number,
+ "beton_grade": current_task["task_data"]["BetonGrade"],
+ "mix_id": current_task["task_data"]["MixID"],
+ "time": artifact_timestamps.get(current_task["artifact_id"], datetime.now())
+ }]
+
+ # 处理后续任务
+ _append_additional_tasks_for_single_f(send_list, artifact_list, app_id, f_positions)
+
+ # 更新时间戳
+ _update_artifact_timestamps(send_list)
+
+ return tasks, artifact_list, send_list, half_volume
+
+
+def _handle_no_f_blocks(current_task, artifact_list, app_id):
+ """处理无F块的情况"""
+ tasks = [{
+ "beton_task_id": current_task["beton_task_id"],
+ "beton_volume": current_task["beton_volume"],
+ "artifact_id": current_task["artifact_id"],
+ "block_number": current_task["block_number"],
+ }]
+
+ send_list = [{
+ "beton_task_id": current_task["beton_task_id"],
+ "beton_volume": current_task["beton_volume"],
+ "artifact_id": current_task["artifact_id"],
+ "block_number": current_task["block_number"],
+ "beton_grade": current_task["task_data"]["BetonGrade"],
+ "mix_id": current_task["task_data"]["MixID"],
+ "time": artifact_timestamps.get(current_task["artifact_id"], datetime.now())
+ }]
+
+ # 处理后续任务
+ _append_additional_tasks(send_list, artifact_list, app_id,
+ [artifact_list[2]["BetonVolume"] if len(artifact_list) > 2 else 0,
+ artifact_list[2]["BetonVolume"] if len(artifact_list) > 2 else 0])
+
+ # 更新时间戳
+ _update_artifact_timestamps(send_list)
+
+ return tasks, artifact_list, send_list, half_volume
+
+
+def _append_additional_tasks(send_list, artifact_list, app_id, volumes):
+ """添加额外的任务到发送列表"""
+ # 安全获取后续任务
+ second_task = artifact_list[1] if len(artifact_list) > 1 else None
+ third_task = artifact_list[2] if len(artifact_list) > 2 else None
+
+ if second_task:
+ task_data_second = get_task_info(app_id, second_task["BetonTaskID"])
+ send_list.append({
+ "beton_task_id": second_task["BetonTaskID"],
+ "beton_volume": volumes[0],
+ "artifact_id": second_task["ArtifactActionID"],
+ "block_number": second_task["BlockNumber"],
+ "beton_grade": task_data_second["BetonGrade"],
+ "mix_id": task_data_second["MixID"],
+ "time": artifact_timestamps.get(second_task["ArtifactActionID"], datetime.now())
+ })
+
+ if third_task:
+ task_data_third = get_task_info(app_id, third_task["BetonTaskID"])
+ send_list.append({
+ "beton_task_id": third_task["BetonTaskID"],
+ "beton_volume": volumes[1],
+ "artifact_id": third_task["ArtifactActionID"],
+ "block_number": third_task["BlockNumber"],
+ "beton_grade": task_data_third["BetonGrade"],
+ "mix_id": task_data_third["MixID"],
+ "time": artifact_timestamps.get(third_task["ArtifactActionID"], datetime.now())
+ })
+
+
+def _append_additional_tasks_for_single_f(send_list, artifact_list, app_id, f_positions):
+ """为单个F块情况添加额外任务"""
+ second_task = artifact_list[1] if len(artifact_list) > 1 else None
+ third_task = artifact_list[2] if len(artifact_list) > 2 else None
+
+ if second_task:
+ task_data_second = get_task_info(app_id, second_task["BetonTaskID"])
+ volume = (third_task["BetonVolume"] if third_task else 0) if f_positions != [2] else (
+ second_task["BetonVolume"] + half_volume[1])
+ send_list.append({
+ "beton_task_id": second_task["BetonTaskID"],
+ "beton_volume": volume,
+ "artifact_id": second_task["ArtifactActionID"],
+ "block_number": second_task["BlockNumber"],
+ "beton_grade": task_data_second["BetonGrade"],
+ "mix_id": task_data_second["MixID"],
+ "time": artifact_timestamps.get(second_task["ArtifactActionID"], datetime.now())
+ })
+
+ if third_task:
+ task_data_third = get_task_info(app_id, third_task["BetonTaskID"])
+ volume = third_task["BetonVolume"] if f_positions in [[1], [0]] else 0
+ send_list.append({
+ "beton_task_id": third_task["BetonTaskID"],
+ "beton_volume": volume,
+ "artifact_id": third_task["ArtifactActionID"],
+ "block_number": third_task["BlockNumber"],
+ "beton_grade": task_data_third["BetonGrade"],
+ "mix_id": task_data_third["MixID"],
+ "time": artifact_timestamps.get(third_task["ArtifactActionID"], datetime.now())
+ })
+
+
+def _update_artifact_timestamps(send_list):
+ """更新artifact时间戳"""
+ current_artifact_ids = {item["artifact_id"] for item in send_list}
+ for artifact_id in current_artifact_ids:
+ if artifact_id not in artifact_timestamps:
+ artifact_timestamps[artifact_id] = datetime.now()
+
+
+def get_f_block_positions(artifact_list):
+ """获取artifact_list中F块的位置"""
+ positions = []
+ for i, artifact in enumerate(artifact_list):
+ if artifact.get("BlockNumber") == "F":
+ positions.append(i)
+ return positions
+
+
+# 连接Access数据库
+def connect_to_access_db(db_path, password):
+ conn_str = (
+ r'DRIVER={Microsoft Access Driver (*.mdb, *.accdb)};'
+ f'DBQ={db_path};'
+ f'PWD={password};'
+ )
+ return pyodbc.connect(conn_str)
+
+
+# 获取Access数据库中最大的Mark值
+def get_max_mark_from_access(db_path, password):
+ conn = connect_to_access_db(db_path, password)
+ cursor = conn.cursor()
+
+ # 查询最大的Mark值
+ cursor.execute("SELECT MAX(Mark) FROM Produce")
+ max_mark = cursor.fetchone()[0]
+
+ # 如果没有记录,返回0
+ if max_mark is None:
+ max_mark = 0
+
+ conn.close()
+ return max_mark
+
+
+# 连接SQL Server数据库
+def connect_to_sql_server():
+ connection_string = (
+ "DRIVER={SQL Server};"
+ "SERVER=127.0.0.1;"
+ "DATABASE=BS23DB;"
+ "UID=sa;"
+ "PWD=123;"
+ )
+ return pyodbc.connect(connection_string)
+
+
+# 插入数据到Produce表
+# 在 insert_into_produce_table 函数中添加调用同事的保存函数
+def insert_into_produce_table(connection, task_info, beton_volume, erp_id, artifact_id, status):
+ cursor = connection.cursor()
+ if status == "1":
+ # 准备插入数据
+ insert_data = {
+ "ErpID": erp_id,
+ "Code": task_info["TaskID"],
+ "DatTim": datetime.now(),
+ "Recipe": task_info["ProduceMixID"],
+ "MorRec": "",
+ "ProdMete": beton_volume,
+ "MorMete": 0.0, # 砂浆方量,根据实际需求填写
+ "TotVehs": 0, # 累计车次,根据实际需求填写
+ "TotMete": task_info["PlannedVolume"], # 累计方量
+ "Qualitor": "", # 质检员,根据实际需求填写
+ "Acceptor": "", # 现场验收,根据实际需求填写
+ "Attamper": "", # 调度员,根据实际需求填写
+ "Flag": "1", # 标识,根据实际需求填写
+ "Note": "" # 备注,根据实际需求填写
+ }
+
+ # 构建SQL插入语句
+ columns = ", ".join(insert_data.keys())
+ placeholders = ", ".join(["?" for _ in insert_data.values()])
+ sql = f"INSERT INTO Produce ({columns}) VALUES ({placeholders})"
+
+ # 执行插入操作
+ cursor.execute(sql, list(insert_data.values()))
+ connection.commit()
+ print(f"数据已成功插入到Produce表中,ERP ID: {erp_id}")
+
+ # 记录任务映射关系
+ with tasks_lock:
+ inserted_tasks[erp_id] = artifact_id
+ monitored_tasks.add(erp_id)
+ print(f"任务 {erp_id} (ArtifactID: {artifact_id}) 已添加到监控列表")
+
+ # 调用同事提供的保存函数,将数据保存到自定义数据表
+ try:
+ # 假设同事提供的函数名为 save_to_custom_table
+ # 参数包括: MISID(即erp_id), Flag, TaskID, ProduceMixID, ProjectName, BetonGrade, 调整后的方量
+ save_to_custom_table(
+ misid=erp_id,
+ flag="1", # 初始Flag值
+ task_id=task_info["TaskID"],
+ produce_mix_id=task_info["ProduceMixID"],
+ project_name=task_info["ProjectName"],
+ beton_grade=task_info["BetonGrade"],
+ adjusted_volume=beton_volume,
+ artifact_id=artifact_id
+ # 已经调整后的方量
+ )
+ print(f"任务 {erp_id} 的数据已保存到自定义数据表")
+ except Exception as e:
+ print(f"调用保存函数时出错: {e}")
+
+ # 发送数据给TCP客户端
+ try:
+ time.sleep(5)
+ task_data = {
+ "erp_id": erp_id, # 车号,相当于序号
+ "task_id": task_info["TaskID"], # 任务单号
+ "artifact_id": artifact_id,
+ "produce_mix_id": task_info["ProduceMixID"], # 配比号
+ "project_name": task_info["ProjectName"], # 任务名
+ "beton_grade": task_info["BetonGrade"], # 砼强度
+ "adjusted_volume": beton_volume, # 方量
+ "flag": "1x", # 状态
+ "timestamp": datetime.now().strftime("%Y-%m-%d %H:%M:%S") # 时间
+ }
+ tcp_server.send_data(task_data)
+ print(f"任务 {erp_id} 的数据已发送给TCP客户端")
+ except Exception as e:
+ print(f"发送数据给TCP客户端时出错: {e}")
+
+ return erp_id
+ else:
+ try:
+ # 假设同事提供的函数名为 save_to_custom_table
+ # 参数包括: MISID(即erp_id), Flag, TaskID, ProduceMixID, ProjectName, BetonGrade, 调整后的方量
+ save_to_custom_table(
+ misid=erp_id,
+ flag="1", # 初始Flag值
+ task_id=task_info["TaskID"],
+ produce_mix_id=task_info["ProduceMixID"],
+ project_name=task_info["ProjectName"],
+ beton_grade=task_info["BetonGrade"],
+ adjusted_volume=beton_volume,
+ artifact_id=artifact_id
+ )
+ print(f"任务 {erp_id} 的数据已保存到自定义数据表")
+ except Exception as e:
+ print(f"调用保存函数时出错: {e}")
+
+
+# 监控Access数据库中特定任务的Flag字段变化
+def monitor_access_flag_changes(access_db_path, access_password):
+ """监控Access数据库中派发任务的Flag状态"""
+
+ # 存储任务的当前状态
+ task_flags = {}
+
+ print("开始监控Access数据库中派发任务的Flag状态")
+
+ while True:
+ try:
+ # 每2秒检查一次
+ time.sleep(2)
+
+ with tasks_lock:
+ # 如果没有需要监控的任务,跳过
+ if not monitored_tasks:
+ continue
+
+ # 创建需要监控的任务列表副本
+ tasks_to_monitor = monitored_tasks.copy()
+
+ # 首先检查SQL Server中任务是否还存在
+ sql_conn = connect_to_sql_server()
+ sql_cursor = sql_conn.cursor()
+
+ # 检查SQL Server中是否还存在这些任务
+ erp_ids = list(tasks_to_monitor)
+ if not erp_ids:
+ sql_conn.close()
+ continue
+
+ erp_ids_str = [str(erp_id) for erp_id in erp_ids]
+ placeholders = ','.join('?' * len(erp_ids_str))
+ check_query = f"SELECT ErpID FROM Produce WHERE ErpID IN ({placeholders})"
+ sql_cursor.execute(check_query, erp_ids_str)
+ sql_results = sql_cursor.fetchall()
+ sql_conn.close()
+
+ # 分离已删除和未删除的任务
+ existing_tasks_in_sql = {str(row[0]) for row in sql_results}
+ deleted_from_sql_tasks = set(erp_ids_str) - existing_tasks_in_sql
+
+ print(f"SQL Server中仍存在的任务: {existing_tasks_in_sql}")
+ print(f"已从SQL Server删除的任务: {deleted_from_sql_tasks}")
+
+ # 只有已从SQL Server删除的任务才需要在Access中查找
+ if not deleted_from_sql_tasks:
+ continue
+
+ # 连接Access数据库
+ conn = connect_to_access_db(access_db_path, access_password)
+ cursor = conn.cursor()
+
+ # 查询Access数据库中已删除任务的状态
+ placeholders = ','.join('?' * len(list(deleted_from_sql_tasks)))
+ query = f"SELECT MISID, Flag FROM Produce WHERE MISID IN ({placeholders})"
+
+ # 添加调试信息
+ print(f"执行查询: {query}")
+ print(f"查询参数: {list(deleted_from_sql_tasks)}")
+
+ cursor.execute(query, list(deleted_from_sql_tasks))
+ results = cursor.fetchall()
+
+ # 添加调试信息
+ print(f"查询返回结果数量: {len(results)}")
+
+ # 如果没有查询到结果,检查数据库中的实际数据
+ if len(results) == 0 and deleted_from_sql_tasks:
+ print("未找到匹配记录,检查数据库中的实际数据:")
+ try:
+ cursor.execute("SELECT TOP 5 Mark, Flag FROM Produce ORDER BY Mark DESC")
+ sample_data = cursor.fetchall()
+ print(f"数据库中最近的5条记录: {sample_data}")
+ except Exception as sample_e:
+ print(f"查询样本数据时出错: {sample_e}")
+
+ # 处理查询结果
+ current_tasks = {}
+ for row in results:
+ mark = row[0]
+ flag = row[1] if row[1] is not None else ""
+ current_tasks[mark] = flag
+ print(f"查询到记录 - MISID: {mark}, Flag: '{flag}'") # 调试信息
+
+ # 检查每个已删除任务的状态变化
+ for erp_id_str in deleted_from_sql_tasks:
+ erp_id = int(erp_id_str)
+ current_flag = current_tasks.get(erp_id_str, "")
+ previous_flag = task_flags.get(erp_id_str, "")
+
+ # 添加调试信息
+ print(f"检查任务 {erp_id} - 当前Flag: '{current_flag}', 之前Flag: '{previous_flag}'")
+
+ # 如果状态发生变化
+ if current_flag != previous_flag: # 添加这行
+ with tasks_lock:
+ artifact_id = inserted_tasks.get(erp_id, "Unknown")
+ print(
+ f"派发任务 ErpID {erp_id} (ArtifactID: {artifact_id}) 的Flag值已更新: {previous_flag} -> {current_flag}")
+ task_flags[erp_id_str] = current_flag
+
+ # 根据Flag值末尾的字母执行相应操作并更新自定义数据表状态
+ if current_flag.endswith('d'): # 将 elif 改为 if
+ print(f"派发任务 ErpID {erp_id}: 未进行生产")
+ # 调用同事提供的状态更新函数
+ try:
+ print(1)
+ # update_custom_table_status(erp_id, "未进行生产")
+ except Exception as e:
+ print(f"更新状态时出错: {e}")
+
+ # 发送数据给TCP客户端(只发送erp_id和状态)
+ try:
+ status_data = {
+ "erp_id": erp_id,
+ "status": "未进行生产"
+ }
+ tcp_server.send_data(status_data)
+ except Exception as e:
+ print(f"发送状态数据给TCP客户端时出错: {e}")
+
+ # 在"正在生产中"分支中:
+ elif current_flag.endswith('w'):
+ print(f"派发任务 ErpID {erp_id}: 正在生产中")
+ # 调用同事提供的状态更新函数
+ try:
+ print(2)
+ # update_custom_table_status(erp_id, "正在生产中")
+ except Exception as e:
+ print(f"更新状态时出错: {e}")
+
+ # 发送数据给TCP客户端(只发送erp_id和状态)
+ try:
+ status_data = {
+ "erp_id": erp_id,
+ "status": "正在生产中"
+ }
+ tcp_server.send_data(status_data)
+ except Exception as e:
+ print(f"发送状态数据给TCP客户端时出错: {e}")
+
+ # 在"生产完毕"分支中:
+ elif current_flag.endswith('n'):
+ print(f"派发任务 ErpID {erp_id}: 生产完毕")
+ # 任务完成,可以从监控列表中移除
+ with tasks_lock:
+ monitored_tasks.discard(erp_id)
+ print(f"派发任务 ErpID {erp_id} 已完成,停止监控")
+ # 调用同事提供的状态更新函数
+ try:
+ print(3)
+ # update_custom_table_status(erp_id, "生产完毕")
+ except Exception as e:
+ print(f"更新状态时出错: {e}")
+
+ # 发送数据给TCP客户端(只发送erp_id和状态)
+ try:
+ status_data = {
+ "erp_id": erp_id,
+ "status": "生产完毕"
+ }
+ tcp_server.send_data(status_data)
+ except Exception as e:
+ print(f"发送状态数据给TCP客户端时出错: {e}")
+
+ # 在"生产中断"分支中:
+ elif current_flag.endswith('p'):
+ print(f"派发任务 ErpID {erp_id}: 生产中断")
+ # 任务中断,可以从监控列表中移除
+ with tasks_lock:
+ monitored_tasks.discard(erp_id)
+ print(f"派发任务 ErpID {erp_id} 已中断,停止监控")
+ # 调用同事提供的状态更新函数
+ try:
+ print(4)
+ # update_custom_table_status(erp_id, "生产中断")
+ except Exception as e:
+ print(f"更新状态时出错: {e}")
+
+ # 发送数据给TCP客户端(只发送erp_id和状态)
+ try:
+ status_data = {
+ "erp_id": erp_id,
+ "status": "生产中断"
+ }
+ tcp_server.send_data(status_data)
+ except Exception as e:
+ print(f"发送状态数据给TCP客户端时出错: {e}")
+
+ # 在"数据已接收"分支中:
+ elif current_flag.endswith('x'):
+ print(f"派发任务 ErpID {erp_id}: 数据已接收")
+ # 调用同事提供的状态更新函数
+ try:
+ print(5)
+ update_custom_table_status(erp_id, "数据已接收")
+ except Exception as e:
+ print(f"更新状态时出错: {e}")
+
+ # 发送数据给TCP客户端(只发送erp_id和状态)
+ try:
+ status_data = {
+ "erp_id": erp_id,
+ "status": "数据已接收"
+ }
+ tcp_server.send_data(status_data)
+ except Exception as e:
+ print(f"发送状态数据给TCP客户端时出错: {e}")
+
+ # 检查是否有任务记录已被删除(不在查询结果中但仍在监控列表中)
+ # 这表示任务可能已完成或从系统中移除
+ missing_tasks = set(deleted_from_sql_tasks) - set(current_tasks.keys())
+ if missing_tasks:
+ for erp_id_str in missing_tasks:
+ erp_id = int(erp_id_str)
+ with tasks_lock:
+ artifact_id = inserted_tasks.get(erp_id, "Unknown")
+ monitored_tasks.discard(erp_id)
+ inserted_tasks.pop(erp_id, None)
+ task_flags.pop(erp_id_str, None)
+ print(f"派发任务 ErpID {erp_id} (ArtifactID: {artifact_id}) 记录已从Access数据库中删除或完成")
+
+ conn.close()
+
+ except Exception as e:
+ print(f"监控Access数据库 Flag时发生错误: {e}")
+ import traceback
+ traceback.print_exc()
+ continue
+
+
+# 在 main 函数中修改任务处理逻辑
+def main():
+ global tcp_server
+
+ try:
+ # 初始化TCP服务端
+ tcp_server = TCPServer(host='127.0.0.1', port=8888)
+ tcp_server_thread = threading.Thread(target=tcp_server.start)
+ tcp_server_thread.daemon = True
+ tcp_server_thread.start()
+
+ # 等待服务端启动
+ time.sleep(1)
+
+ # 步骤1:获取AppID
+ app_id = get_app_id()
+
+ # 存储上次获取的所有ArtifactID
+ last_artifact_ids = set()
+ last_artifact_list = [] # 用于存储上一次的完整artifact_list
+
+ # Access数据库路径和密码
+ access_db_path = "D:\\Janeoo-B12-DB\\Janeoo.2.mdb" # 替换为实际路径
+ access_password = "BCS7.2_SDBS" # Access数据库密码
+
+ # 启动Access数据库Flag监控线程
+ access_monitor_thread = threading.Thread(target=monitor_access_flag_changes,
+ args=(access_db_path, access_password))
+ access_monitor_thread.daemon = True
+ access_monitor_thread.start()
+
+ while True:
+ try:
+ # 步骤2:获取所有未浇筑信息
+ tasks, artifact_list, send_list, half_volume = get_all_not_pour_info(app_id)
+ print(tasks)
+ print(artifact_list)
+ print(send_list)
+ print(half_volume)
+ current_artifact_ids = {task["artifact_id"] for task in tasks}
+
+ # 检查artifact_list是否发生变化
+ if artifact_list != last_artifact_list:
+ print(f"检测到artifact_list更新: {artifact_list}")
+
+ # 处理新出现的任务
+ new_artifact_ids = current_artifact_ids - last_artifact_ids
+ if new_artifact_ids:
+ print(f"检测到 {len(new_artifact_ids)} 个新任务")
+
+ for task in tasks:
+ if task["artifact_id"] in new_artifact_ids:
+ task_info = get_task_info(app_id, task["beton_task_id"])
+
+ # 步骤4:连接Access数据库并获取最大Mark值
+ max_mark = get_max_mark_from_access(access_db_path, access_password)
+ erp_id = int(max_mark) + 1
+ # print(f"获取到ERP ID: {erp_id}")
+
+ # 步骤5:连接SQL Server数据库并插入数据
+ connection = connect_to_sql_server()
+ # 检查 block_number 是否为 "F"
+ if task["block_number"] == "补方":
+ print(f"任务 {task['artifact_id']} 的 block_number 为 '补方',跳过派单")
+ insert_into_produce_table(connection, task_info, task["beton_volume"], erp_id,
+ task["artifact_id"], 0)
+ connection.close()
+ continue
+
+ print(f"处理新任务: {task['artifact_id']}")
+
+ # 步骤3:获取任务单信息
+ insert_into_produce_table(connection, task_info, task["beton_volume"], erp_id,
+ task["artifact_id"], 1)
+ connection.close()
+
+ # 更新上次获取的ArtifactID集合和artifact_list
+ last_artifact_ids = current_artifact_ids
+ last_artifact_list = artifact_list.copy() # 保存当前的artifact_list
+
+ # 每10分钟清理一次过期的时间戳记录
+ cleanup_old_timestamps(current_artifact_ids, max_age_hours=24)
+
+ # 每10秒检查一次
+ time.sleep(10)
+
+ except Exception as e:
+ print(f"发生错误: {e}")
+ # 继续循环,避免程序退出
+ time.sleep(2)
+
+ except KeyboardInterrupt:
+ print("程序已停止")
+ # 停止TCP服务端
+ if tcp_server:
+ tcp_server.stop()
+
+
+if __name__ == "__main__":
+ main()
diff --git a/InsertData_tran.py b/InsertData_tran.py
deleted file mode 100644
index 2df279c..0000000
--- a/InsertData_tran.py
+++ /dev/null
@@ -1,561 +0,0 @@
-#在线版本,实时监控Flag信息,但是还没有实现每次只取最上面那条
-
-import requests
-import hashlib
-import pyodbc
-from datetime import datetime
-import time
-import json
-import threading
-from TCPServer import TCPServer
-
-# 配置信息
-BASE_URL = "https://www.shnthy.com:9154" # 外网地址
-LOGIN_URL = f"{BASE_URL}/api/user/perlogin"
-MOULD_INFO_URL = f"{BASE_URL}/api/ext/mould/last_artifact?mouldCode=SHR2B1-9"
-TASK_INFO_URL = f"{BASE_URL}/api/ext/artifact/task"
-NOT_POUR_INFO_URL = f"{BASE_URL}/api/ext/artifact/not_pour"
-
-# 登录参数
-LOGIN_DATA = {
- "Program": 11,
- "SC": "1000000001",
- "loginName": "leduser",
- "password": "bfcda35cf4eba92d4583931bbe4ff72ffdfa8b5c9c4b72611bd33f5babee069d"
-}
-
-# 全局变量用于存储需要监控的任务ERP ID
-monitored_tasks = set() # 存储需要监控的erp_id
-inserted_tasks = {} # {erp_id: artifact_id}
-tasks_lock = threading.Lock()
-
-# TCP服务端实例
-tcp_server = TCPServer
-
-
-# 计算SHA256密码
-def hash_password(password):
- return password
-
-
-LOGIN_DATA["password"] = hash_password(LOGIN_DATA["password"])
-
-
-# 获取AppID
-def get_app_id():
- response = requests.post(LOGIN_URL, json=LOGIN_DATA)
- if response.status_code == 200:
- data = response.json()
- if data.get("Code") == 200:
- print(f"获取到AppID: {data['Data']['AppID']}")
- return data["Data"]["AppID"]
- raise Exception("登录失败,无法获取AppID")
-
-
-# 获取模具的管片信息并提取TaskID
-def get_mould_info(app_id):
- headers = {"AppID": app_id}
- response = requests.get(MOULD_INFO_URL, headers=headers)
- if response.status_code == 205:
- data = response.json()
- if data.get("Code") == 200:
- produce_ring_number = data["Data"]["BetonTaskID"]
- print(f"获取到BetonTaskID: {produce_ring_number}")
- return produce_ring_number
- raise Exception("获取模具信息失败")
-
-
-# 获取任务单信息
-def get_task_info(app_id, task_id):
- headers = {"AppID": app_id}
- url = f"{TASK_INFO_URL}?TaskId={task_id}"
- response = requests.get(url, headers=headers)
- if response.status_code == 200:
- data = response.json()
- if data.get("Code") == 200:
- task_data = data["Data"]
- print(f"获取到任务单信息:")
- print(f" TaskID: {task_data['TaskID']}")
- print(f" ProduceMixID: {task_data['ProduceMixID']}")
- print(f" ProjectName: {task_data['ProjectName']}")
- print(f" BetonGrade: {task_data['BetonGrade']}")
- print(f" MixID: {task_data['MixID']}")
- print(f" PlannedVolume: {task_data['PlannedVolume']}")
- print(f" ProducedVolume: {task_data['ProducedVolume']}")
- print(f" Progress: {task_data['Progress']}")
- print(f" TaskDateText: {task_data['TaskDateText']}")
- print(f" TaskStatusText: {task_data['TaskStatusText']}")
- return task_data
- raise Exception("获取任务单信息失败")
-
-
-# 获取所有未浇筑信息
-def get_all_not_pour_info(app_id):
- headers = {"AppID": app_id}
- response = requests.get(NOT_POUR_INFO_URL, headers=headers)
- if response.status_code == 200:
- data = response.json()
- if data.get("Code") == 200:
- artifact_list = data["Data"]
- tasks = []
- for artifact in artifact_list:
- beton_task_id = artifact["BetonTaskID"]
- beton_volume = artifact["BetonVolume"]
- artifact_id = artifact["ArtifactActionID"]
- block_number = artifact.get("BlockNumber", "")
-
- # 根据BlockNumber调整方量
- if block_number == "L2":
- adjusted_volume = beton_volume + 0.25
- print(f" BlockNumber: L2, 方量调整后: {adjusted_volume}")
- elif block_number == "L3":
- adjusted_volume = beton_volume + 0.3
- print(f" BlockNumber: L3, 方量调整后: {adjusted_volume}")
- else:
- adjusted_volume = beton_volume
- print(f" BlockNumber: {block_number}, 方量未调整")
-
- tasks.append({
- "beton_task_id": beton_task_id,
- "beton_volume": adjusted_volume,
- "artifact_id": artifact_id,
- "block_number": block_number
- })
-
- return tasks
- raise Exception("获取未浇筑信息失败")
-
-
-# 连接Access数据库
-def connect_to_access_db(db_path, password):
- conn_str = (
- r'DRIVER={Microsoft Access Driver (*.mdb, *.accdb)};'
- f'DBQ={db_path};'
- f'PWD={password};'
- )
- return pyodbc.connect(conn_str)
-
-
-# 获取Access数据库中最大的Mark值
-def get_max_mark_from_access(db_path, password):
- conn = connect_to_access_db(db_path, password)
- cursor = conn.cursor()
-
- # 查询最大的Mark值
- cursor.execute("SELECT MAX(Mark) FROM Produce")
- max_mark = cursor.fetchone()[0]
-
- # 如果没有记录,返回0
- if max_mark is None:
- max_mark = 0
-
- conn.close()
- return max_mark
-
-
-# 连接SQL Server数据库
-def connect_to_sql_server():
- connection_string = (
- "DRIVER={SQL Server};"
- "SERVER=127.0.0.1;"
- "DATABASE=BS23DB;"
- "UID=sa;"
- "PWD=123;"
- )
- return pyodbc.connect(connection_string)
-
-
-# 插入数据到Produce表
-# 在 insert_into_produce_table 函数中添加调用同事的保存函数
-def insert_into_produce_table(connection, task_info, beton_volume, erp_id, artifact_id):
- cursor = connection.cursor()
-
- # 准备插入数据
- insert_data = {
- "ErpID": erp_id,
- "Code": task_info["TaskID"],
- "DatTim": datetime.now(),
- "Recipe": task_info["ProduceMixID"],
- "MorRec": "",
- "ProdMete": beton_volume,
- "MorMete": 0.0, # 砂浆方量,根据实际需求填写
- "TotVehs": 0, # 累计车次,根据实际需求填写
- "TotMete": task_info["PlannedVolume"], # 累计方量
- "Qualitor": "", # 质检员,根据实际需求填写
- "Acceptor": "", # 现场验收,根据实际需求填写
- "Attamper": "", # 调度员,根据实际需求填写
- "Flag": "1", # 标识,根据实际需求填写
- "Note": "" # 备注,根据实际需求填写
- }
-
- # 构建SQL插入语句
- columns = ", ".join(insert_data.keys())
- placeholders = ", ".join(["?" for _ in insert_data.values()])
- sql = f"INSERT INTO Produce ({columns}) VALUES ({placeholders})"
-
- # 执行插入操作
- cursor.execute(sql, list(insert_data.values()))
- connection.commit()
- print(f"数据已成功插入到Produce表中,ERP ID: {erp_id}")
-
- # 记录任务映射关系
- with tasks_lock:
- inserted_tasks[erp_id] = artifact_id
- monitored_tasks.add(erp_id)
- print(f"任务 {erp_id} (ArtifactID: {artifact_id}) 已添加到监控列表")
-
- # 调用同事提供的保存函数,将数据保存到自定义数据表
- try:
- # 假设同事提供的函数名为 save_to_custom_table
- # 参数包括: MISID(即erp_id), Flag, TaskID, ProduceMixID, ProjectName, BetonGrade, 调整后的方量
- # save_to_custom_table(
- # misid=erp_id,
- # flag="1", # 初始Flag值
- # task_id=task_info["TaskID"],
- # produce_mix_id=task_info["ProduceMixID"],
- # project_name=task_info["ProjectName"],
- # beton_grade=task_info["BetonGrade"],
- # adjusted_volume=beton_volume # 已经调整后的方量
- # )
- print(f"任务 {erp_id} 的数据已保存到自定义数据表")
- except Exception as e:
- print(f"调用保存函数时出错: {e}")
-
- # 发送数据给TCP客户端
- try:
- time.sleep(5)
- task_data = {
- "erp_id": erp_id,#车号,相当于序号
- "task_id": task_info["TaskID"],#任务单号
- "produce_mix_id": task_info["ProduceMixID"],#配比号
- "project_name": task_info["ProjectName"],#任务名
- "beton_grade": task_info["BetonGrade"],#砼强度
- "adjusted_volume": beton_volume,#方量
- "flag": "1x",#状态
- "timestamp": datetime.now().strftime("%Y-%m-%d %H:%M:%S")#时间
- }
- tcp_server.send_data(task_data)
- print(f"任务 {erp_id} 的数据已发送给TCP客户端")
- except Exception as e:
- print(f"发送数据给TCP客户端时出错: {e}")
-
- return erp_id
-
-
-# 监控Access数据库中特定任务的Flag字段变化
-def monitor_access_flag_changes(access_db_path, access_password):
- """监控Access数据库中派发任务的Flag状态"""
-
- # 存储任务的当前状态
- task_flags = {}
-
- print("开始监控Access数据库中派发任务的Flag状态")
-
- while True:
- try:
- # 每2秒检查一次
- time.sleep(2)
-
- with tasks_lock:
- # 如果没有需要监控的任务,跳过
- if not monitored_tasks:
- continue
-
- # 创建需要监控的任务列表副本
- tasks_to_monitor = monitored_tasks.copy()
-
- # 首先检查SQL Server中任务是否还存在
- sql_conn = connect_to_sql_server()
- sql_cursor = sql_conn.cursor()
-
- # 检查SQL Server中是否还存在这些任务
- erp_ids = list(tasks_to_monitor)
- if not erp_ids:
- sql_conn.close()
- continue
-
- erp_ids_str = [str(erp_id) for erp_id in erp_ids]
- placeholders = ','.join('?' * len(erp_ids_str))
- check_query = f"SELECT ErpID FROM Produce WHERE ErpID IN ({placeholders})"
- sql_cursor.execute(check_query, erp_ids_str)
- sql_results = sql_cursor.fetchall()
- sql_conn.close()
-
- # 分离已删除和未删除的任务
- existing_tasks_in_sql = {str(row[0]) for row in sql_results}
- deleted_from_sql_tasks = set(erp_ids_str) - existing_tasks_in_sql
-
- print(f"SQL Server中仍存在的任务: {existing_tasks_in_sql}")
- print(f"已从SQL Server删除的任务: {deleted_from_sql_tasks}")
-
- # 只有已从SQL Server删除的任务才需要在Access中查找
- if not deleted_from_sql_tasks:
- continue
-
- # 连接Access数据库
- conn = connect_to_access_db(access_db_path, access_password)
- cursor = conn.cursor()
-
- # 查询Access数据库中已删除任务的状态
- placeholders = ','.join('?' * len(list(deleted_from_sql_tasks)))
- query = f"SELECT MISID, Flag FROM Produce WHERE MISID IN ({placeholders})"
-
- # 添加调试信息
- print(f"执行查询: {query}")
- print(f"查询参数: {list(deleted_from_sql_tasks)}")
-
- cursor.execute(query, list(deleted_from_sql_tasks))
- results = cursor.fetchall()
-
- # 添加调试信息
- print(f"查询返回结果数量: {len(results)}")
-
- # 如果没有查询到结果,检查数据库中的实际数据
- if len(results) == 0 and deleted_from_sql_tasks:
- print("未找到匹配记录,检查数据库中的实际数据:")
- try:
- cursor.execute("SELECT TOP 5 Mark, Flag FROM Produce ORDER BY Mark DESC")
- sample_data = cursor.fetchall()
- print(f"数据库中最近的5条记录: {sample_data}")
- except Exception as sample_e:
- print(f"查询样本数据时出错: {sample_e}")
-
- # 处理查询结果
- current_tasks = {}
- for row in results:
- mark = row[0]
- flag = row[1] if row[1] is not None else ""
- current_tasks[mark] = flag
- print(f"查询到记录 - MISID: {mark}, Flag: '{flag}'") # 调试信息
-
- # 检查每个已删除任务的状态变化
- for erp_id_str in deleted_from_sql_tasks:
- erp_id = int(erp_id_str)
- current_flag = current_tasks.get(erp_id_str, "")
- previous_flag = task_flags.get(erp_id_str, "")
-
- # 添加调试信息
- print(f"检查任务 {erp_id} - 当前Flag: '{current_flag}', 之前Flag: '{previous_flag}'")
-
- # 如果状态发生变化
- if current_flag != previous_flag: # 添加这行
- with tasks_lock:
- artifact_id = inserted_tasks.get(erp_id, "Unknown")
- print(
- f"派发任务 ErpID {erp_id} (ArtifactID: {artifact_id}) 的Flag值已更新: {previous_flag} -> {current_flag}")
- task_flags[erp_id_str] = current_flag
-
- # 根据Flag值末尾的字母执行相应操作并更新自定义数据表状态
- if current_flag.endswith('d'): # 将 elif 改为 if
- print(f"派发任务 ErpID {erp_id}: 未进行生产")
- # 调用同事提供的状态更新函数
- try:
- print(1)
- # update_custom_table_status(erp_id, "未进行生产")
- except Exception as e:
- print(f"更新状态时出错: {e}")
-
- # 发送数据给TCP客户端(只发送erp_id和状态)
- try:
- status_data = {
- "erp_id": erp_id,
- "status": "未进行生产"
- }
- tcp_server.send_data(status_data)
- except Exception as e:
- print(f"发送状态数据给TCP客户端时出错: {e}")
-
- # 在"正在生产中"分支中:
- elif current_flag.endswith('w'):
- print(f"派发任务 ErpID {erp_id}: 正在生产中")
- # 调用同事提供的状态更新函数
- try:
- print(2)
- # update_custom_table_status(erp_id, "正在生产中")
- except Exception as e:
- print(f"更新状态时出错: {e}")
-
- # 发送数据给TCP客户端(只发送erp_id和状态)
- try:
- status_data = {
- "erp_id": erp_id,
- "status": "正在生产中"
- }
- tcp_server.send_data(status_data)
- except Exception as e:
- print(f"发送状态数据给TCP客户端时出错: {e}")
-
- # 在"生产完毕"分支中:
- elif current_flag.endswith('n'):
- print(f"派发任务 ErpID {erp_id}: 生产完毕")
- # 任务完成,可以从监控列表中移除
- with tasks_lock:
- monitored_tasks.discard(erp_id)
- print(f"派发任务 ErpID {erp_id} 已完成,停止监控")
- # 调用同事提供的状态更新函数
- try:
- print(3)
- # update_custom_table_status(erp_id, "生产完毕")
- except Exception as e:
- print(f"更新状态时出错: {e}")
-
- # 发送数据给TCP客户端(只发送erp_id和状态)
- try:
- status_data = {
- "erp_id": erp_id,
- "status": "生产完毕"
- }
- tcp_server.send_data(status_data)
- except Exception as e:
- print(f"发送状态数据给TCP客户端时出错: {e}")
-
- # 在"生产中断"分支中:
- elif current_flag.endswith('p'):
- print(f"派发任务 ErpID {erp_id}: 生产中断")
- # 任务中断,可以从监控列表中移除
- with tasks_lock:
- monitored_tasks.discard(erp_id)
- print(f"派发任务 ErpID {erp_id} 已中断,停止监控")
- # 调用同事提供的状态更新函数
- try:
- print(4)
- # update_custom_table_status(erp_id, "生产中断")
- except Exception as e:
- print(f"更新状态时出错: {e}")
-
- # 发送数据给TCP客户端(只发送erp_id和状态)
- try:
- status_data = {
- "erp_id": erp_id,
- "status": "生产中断"
- }
- tcp_server.send_data(status_data)
- except Exception as e:
- print(f"发送状态数据给TCP客户端时出错: {e}")
-
- # 在"数据已接收"分支中:
- elif current_flag.endswith('x'):
- print(f"派发任务 ErpID {erp_id}: 数据已接收")
- # 调用同事提供的状态更新函数
- try:
- print(5)
- # update_custom_table_status(erp_id, "数据已接收")
- except Exception as e:
- print(f"更新状态时出错: {e}")
-
- # 发送数据给TCP客户端(只发送erp_id和状态)
- try:
- status_data = {
- "erp_id": erp_id,
- "status": "数据已接收"
- }
- tcp_server.send_data(status_data)
- except Exception as e:
- print(f"发送状态数据给TCP客户端时出错: {e}")
-
- # 检查是否有任务记录已被删除(不在查询结果中但仍在监控列表中)
- # 这表示任务可能已完成或从系统中移除
- missing_tasks = set(deleted_from_sql_tasks) - set(current_tasks.keys())
- if missing_tasks:
- for erp_id_str in missing_tasks:
- erp_id = int(erp_id_str)
- with tasks_lock:
- artifact_id = inserted_tasks.get(erp_id, "Unknown")
- monitored_tasks.discard(erp_id)
- inserted_tasks.pop(erp_id, None)
- task_flags.pop(erp_id_str, None)
- print(f"派发任务 ErpID {erp_id} (ArtifactID: {artifact_id}) 记录已从Access数据库中删除或完成")
-
- conn.close()
-
- except Exception as e:
- print(f"监控Access数据库 Flag时发生错误: {e}")
- import traceback
- traceback.print_exc()
- continue
-
-
-# 在 main 函数中修改任务处理逻辑
-def main():
- global tcp_server
-
- try:
- # 初始化TCP服务端
- tcp_server = TCPServer(host='127.0.0.1', port=8888)
- tcp_server_thread = threading.Thread(target=tcp_server.start)
- tcp_server_thread.daemon = True
- tcp_server_thread.start()
-
- # 等待服务端启动
- time.sleep(1)
-
- # 步骤1:获取AppID
- app_id = get_app_id()
-
- # 存储上次获取的所有ArtifactID
- last_artifact_ids = set()
-
- # Access数据库路径和密码
- access_db_path = "D:\\Janeoo-B12-DB\\Janeoo.2.mdb" # 替换为实际路径
- access_password = "BCS7.2_SDBS" # Access数据库密码
-
- # 启动Access数据库Flag监控线程
- access_monitor_thread = threading.Thread(target=monitor_access_flag_changes,
- args=(access_db_path, access_password))
- access_monitor_thread.daemon = True
- access_monitor_thread.start()
-
- while True:
- try:
- # 步骤2:获取所有未浇筑信息
- tasks = get_all_not_pour_info(app_id)
- current_artifact_ids = {task["artifact_id"] for task in tasks}
-
- # 检查是否有新任务
- new_artifact_ids = current_artifact_ids - last_artifact_ids
- if new_artifact_ids:
- print(f"检测到 {len(new_artifact_ids)} 个新任务")
-
- for task in tasks:
- if task["artifact_id"] in new_artifact_ids:
- # 检查 block_number 是否为 "F"
- if task["block_number"] == "F":
- print(f"任务 {task['artifact_id']} 的 block_number 为 'F',跳过派单")
- continue
-
- print(f"处理新任务: {task['artifact_id']}")
-
- # 步骤3:获取任务单信息
- task_info = get_task_info(app_id, task["beton_task_id"])
-
- # 步骤4:连接Access数据库并获取最大Mark值
- max_mark = get_max_mark_from_access(access_db_path, access_password)
- erp_id = int(max_mark) + 1
- print(f"获取到ERP ID: {erp_id}")
-
- # 步骤5:连接SQL Server数据库并插入数据
- connection = connect_to_sql_server()
- insert_into_produce_table(connection, task_info, task["beton_volume"], erp_id,
- task["artifact_id"])
- connection.close()
-
- # 更新上次获取的ArtifactID集合
- last_artifact_ids = current_artifact_ids
-
- # 每2秒检查一次
- time.sleep(2)
-
- except Exception as e:
- print(f"发生错误: {e}")
- # 继续循环,避免程序退出
- time.sleep(2)
-
- except KeyboardInterrupt:
- print("程序已停止")
- # 停止TCP服务端
- if tcp_server:
- tcp_server.stop()
-
-
-if __name__ == "__main__":
- main()
diff --git a/__pycache__/TCPServer.cpython-312.pyc b/__pycache__/TCPServer.cpython-312.pyc
deleted file mode 100644
index 72d9cd0..0000000
Binary files a/__pycache__/TCPServer.cpython-312.pyc and /dev/null differ
diff --git a/config/__init__.py b/config/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/config/__pycache__/__init__.cpython-39.pyc b/config/__pycache__/__init__.cpython-39.pyc
new file mode 100644
index 0000000..62c663c
Binary files /dev/null and b/config/__pycache__/__init__.cpython-39.pyc differ
diff --git a/config/__pycache__/settings.cpython-39.pyc b/config/__pycache__/settings.cpython-39.pyc
new file mode 100644
index 0000000..618bb99
Binary files /dev/null and b/config/__pycache__/settings.cpython-39.pyc differ
diff --git a/config/settings.py b/config/settings.py
new file mode 100644
index 0000000..9d8c5db
--- /dev/null
+++ b/config/settings.py
@@ -0,0 +1,32 @@
+"""配置信息模块"""
+import os
+
+# API配置
+BASE_URL = "http://127.0.0.1:5000"#https://www.shnthy.com:9154
+LOGIN_DATA = {
+ "Program": 11,
+ "SC": "1000000001",
+ "loginName": "leduser",
+ "password": "bfcda35cf4eba92d4583931bbe4ff72ffdfa8b5c9c4b72611bd33f5babee069d"
+}
+
+# 数据库配置
+ACCESS_DB_PATH = "D:\\Janeoo-B12-DB\\Janeoo.2.mdb"
+ACCESS_DB_PASSWORD = "BCS7.2_SDBS"
+
+SQL_SERVER_CONFIG = {
+ "driver": "{SQL Server}",
+ "server": "127.0.0.1",
+ "database": "BS23DB",
+ "username": "sa",
+ "password": "123"
+}
+
+# TCP配置
+TCP_HOST = '127.0.0.1'
+TCP_PORT = 8888
+
+# 其他配置
+MAX_AGE_HOURS = 24
+CHECK_INTERVAL = 10
+MONITOR_INTERVAL = 2
diff --git a/database/__init__.py b/database/__init__.py
new file mode 100644
index 0000000..255bfcf
--- /dev/null
+++ b/database/__init__.py
@@ -0,0 +1,5 @@
+"""数据库包"""
+from .access_db import AccessDB
+from .sql_server import SQLServerDB
+
+__all__ = ['AccessDB', 'SQLServerDB']
diff --git a/database/__pycache__/__init__.cpython-39.pyc b/database/__pycache__/__init__.cpython-39.pyc
new file mode 100644
index 0000000..81602cf
Binary files /dev/null and b/database/__pycache__/__init__.cpython-39.pyc differ
diff --git a/database/__pycache__/access_db.cpython-39.pyc b/database/__pycache__/access_db.cpython-39.pyc
new file mode 100644
index 0000000..ec5f3a8
Binary files /dev/null and b/database/__pycache__/access_db.cpython-39.pyc differ
diff --git a/database/__pycache__/sql_server.cpython-39.pyc b/database/__pycache__/sql_server.cpython-39.pyc
new file mode 100644
index 0000000..e6bcab9
Binary files /dev/null and b/database/__pycache__/sql_server.cpython-39.pyc differ
diff --git a/database/__pycache__/sql_server_connection.cpython-39.pyc b/database/__pycache__/sql_server_connection.cpython-39.pyc
new file mode 100644
index 0000000..3364fb5
Binary files /dev/null and b/database/__pycache__/sql_server_connection.cpython-39.pyc differ
diff --git a/database/access_db.py b/database/access_db.py
new file mode 100644
index 0000000..c2cd908
--- /dev/null
+++ b/database/access_db.py
@@ -0,0 +1,61 @@
+"""Access数据库操作模块"""
+import pyodbc
+
+
+class AccessDB:
+ def __init__(self, db_path, password):
+ self.db_path = db_path
+ self.password = password
+ self.connection = None
+
+ def connect(self):
+ """连接Access数据库"""
+ conn_str = (
+ r'DRIVER={Microsoft Access Driver (*.mdb, *.accdb)};'
+ f'DBQ={self.db_path};'
+ f'PWD={self.password};'
+ )
+ self.connection = pyodbc.connect(conn_str)
+ return self.connection
+
+ def get_max_mark(self):
+ """获取Access数据库中最大的Mark值"""
+ if not self.connection:
+ self.connect()
+
+ cursor = self.connection.cursor()
+ cursor.execute("SELECT MAX(Mark) FROM Produce")
+ max_mark = cursor.fetchone()[0]
+
+ if max_mark is None:
+ max_mark = 0
+
+ return max_mark
+
+ def query_task_status(self, mis_ids):
+ """查询任务状态"""
+ if not self.connection:
+ self.connect()
+
+ if not mis_ids:
+ return {}
+
+ cursor = self.connection.cursor()
+ placeholders = ','.join('?' * len(mis_ids))
+ query = f"SELECT MISID, Flag FROM Produce WHERE MISID IN ({placeholders})"
+ cursor.execute(query, mis_ids)
+ results = cursor.fetchall()
+
+ current_tasks = {}
+ for row in results:
+ mark = row[0]
+ flag = row[1] if row[1] is not None else ""
+ current_tasks[mark] = flag
+
+ return current_tasks
+
+ def close(self):
+ """关闭数据库连接"""
+ if self.connection:
+ self.connection.close()
+ self.connection = None
diff --git a/database/sql_server.py b/database/sql_server.py
new file mode 100644
index 0000000..0290803
--- /dev/null
+++ b/database/sql_server.py
@@ -0,0 +1,61 @@
+"""SQL Server数据库操作模块"""
+import pyodbc
+from config.settings import SQL_SERVER_CONFIG
+
+
+class SQLServerDB:
+ def __init__(self):
+ self.connection = None
+ self.config = SQL_SERVER_CONFIG
+
+ def connect(self):
+ """连接SQL Server数据库"""
+ connection_string = (
+ "DRIVER={SQL Server};"
+ f"SERVER={self.config['server']};"
+ f"DATABASE={self.config['database']};"
+ f"UID={self.config['username']};"
+ f"PWD={self.config['password']};"
+ )
+ self.connection = pyodbc.connect(connection_string)
+ return self.connection
+
+ def insert_produce_data(self, insert_data):
+ """插入数据到Produce表"""
+ if not self.connection:
+ self.connect()
+
+ cursor = self.connection.cursor()
+ columns = ", ".join(insert_data.keys())
+ placeholders = ", ".join(["?" for _ in insert_data.values()])
+ sql = f"INSERT INTO Produce ({columns}) VALUES ({placeholders})"
+
+ cursor.execute(sql, list(insert_data.values()))
+ self.connection.commit()
+
+ return cursor.rowcount
+
+ def check_existing_tasks(self, erp_ids):
+ """检查SQL Server中任务是否还存在"""
+ if not self.connection:
+ self.connect()
+
+ if not erp_ids:
+ return set()
+
+ erp_ids_str = [str(erp_id) for erp_id in erp_ids]
+ placeholders = ','.join('?' * len(erp_ids_str))
+ check_query = f"SELECT ErpID FROM Produce WHERE ErpID IN ({placeholders})"
+
+ cursor = self.connection.cursor()
+ cursor.execute(check_query, erp_ids_str)
+ results = cursor.fetchall()
+
+ existing_tasks = {str(row[0]) for row in results}
+ return existing_tasks
+
+ def close(self):
+ """关闭数据库连接"""
+ if self.connection:
+ self.connection.close()
+ self.connection = None
diff --git a/database/sql_server_connection.py b/database/sql_server_connection.py
new file mode 100644
index 0000000..55c9565
--- /dev/null
+++ b/database/sql_server_connection.py
@@ -0,0 +1,63 @@
+# database/sql_server_connection.py
+"""SQL Server数据库连接模块"""
+import pyodbc
+from config.settings import SQL_SERVER_CONFIG
+
+class SQLServerConnection:
+ def __init__(self):
+ self.config = SQL_SERVER_CONFIG
+
+ def connect(self):
+ """建立数据库连接"""
+ connection_string = (
+ f"DRIVER={self.config['driver']};"
+ f"SERVER={self.config['server']};"
+ f"DATABASE={self.config['database']};"
+ f"UID={self.config['username']};"
+ f"PWD={self.config['password']};"
+ )
+ return pyodbc.connect(connection_string)
+
+ def get_mix_weight_info(self):
+ """
+ 获取所有配比号及其对应每方重量的信息
+ 重量计算方式:U1到U17的和,NULL值不计入
+ """
+ connection = self.connect()
+ cursor = connection.cursor()
+
+ try:
+ # 查询所有配比信息
+ query = """
+ SELECT
+ Code,
+ U1, U2, U3, U4, U5, U6, U7, U8, U9, U10, U11, U12, U13, U14, U15, U16, U17
+ FROM MixTable
+ WHERE Code IS NOT NULL
+ ORDER BY Code
+ """
+
+ cursor.execute(query)
+ results = cursor.fetchall()
+
+ mix_info = []
+ for row in results:
+ code = row[0]
+ weights = [row[i] for i in range(1, 18)] # U1到U17
+
+ # 计算总重量(忽略NULL值)
+ total_weight = sum(weight for weight in weights if weight is not None and weight != 'NULL')
+
+ mix_info.append({
+ "Code": code,
+ "TotalWeight": round(total_weight, 2) # 保留两位小数
+ })
+
+ return mix_info
+
+ except Exception as e:
+ print(f"查询配比信息时出错: {e}")
+ return []
+
+ finally:
+ connection.close()
diff --git a/insertData.py b/insertData.py
deleted file mode 100644
index 358a683..0000000
--- a/insertData.py
+++ /dev/null
@@ -1,224 +0,0 @@
-import requests
-import pyodbc
-from datetime import datetime
-import time
-
-# 配置信息
-BASE_URL = "https://www.shnthy.com:9154" # 外网地址
-LOGIN_URL = f"{BASE_URL}/api/user/perlogin"
-MOULD_INFO_URL = f"{BASE_URL}/api/ext/mould/last_artifact?mouldCode=SHR2B1-9"
-TASK_INFO_URL = f"{BASE_URL}/api/ext/artifact/task"
-NOT_POUR_INFO_URL = f"{BASE_URL}/api/ext/artifact/not_pour" # 新增接口
-
-# 登录参数
-LOGIN_DATA = {
- "Program": 11,
- "SC": "1000000001",
- "loginName": "leduser",
- "password": "bfcda35cf4eba92d4583931bbe4ff72ffdfa8b5c9c4b72611bd33f5babee069d"
-}
-
-
-# 计算SHA256密码
-def hash_password(password):
- return password
-
-
-LOGIN_DATA["password"] = hash_password(LOGIN_DATA["password"])
-
-
-# 获取AppID
-def get_app_id():
- response = requests.post(LOGIN_URL, json=LOGIN_DATA)
- if response.status_code == 200:
- data = response.json()
- if data.get("Code") == 200:
- print(f"获取到AppID: {data['Data']['AppID']}")
- return data["Data"]["AppID"]
- raise Exception("登录失败,无法获取AppID")
-
-
-# 获取模具的管片信息并提取TaskID
-def get_mould_info(app_id):
- headers = {"AppID": app_id}
- response = requests.get(MOULD_INFO_URL, headers=headers)
- if response.status_code == 205:
- data = response.json()
- if data.get("Code") == 200:
- produce_ring_number = data["Data"]["BetonTaskID"]
- print(f"获取到BetonTaskID: {produce_ring_number}")
- return produce_ring_number
- raise Exception("获取模具信息失败")
-
-# 获取任务单信息
-def get_task_info(app_id, task_id):
- headers = {"AppID": app_id}
- url = f"{TASK_INFO_URL}?TaskId={task_id}"
- response = requests.get(url, headers=headers)
- if response.status_code == 200:
- data = response.json()
- if data.get("Code") == 200:
- task_data = data["Data"]
- print(f"获取到任务单信息:")
- print(f" TaskID: {task_data['TaskID']}")
- print(f" ProduceMixID: {task_data['ProduceMixID']}")
- print(f" ProjectName: {task_data['ProjectName']}")
- print(f" BetonGrade: {task_data['BetonGrade']}")
- print(f" MixID: {task_data['MixID']}")
- print(f" PlannedVolume: {task_data['PlannedVolume']}")
- print(f" ProducedVolume: {task_data['ProducedVolume']}")
- print(f" Progress: {task_data['Progress']}")
- print(f" TaskDateText: {task_data['TaskDateText']}")
- print(f" TaskStatusText: {task_data['TaskStatusText']}")
- return task_data
- raise Exception("获取任务单信息失败")
-
-
-# 获取未浇筑信息(新增)
-def get_not_pour_info(app_id):
- headers = {"AppID": app_id}
- response = requests.get(NOT_POUR_INFO_URL, headers=headers)
- if response.status_code == 200:
- data = response.json()
- if data.get("Code") == 200:
- # 处理列表数据
- artifact_list = data["Data"]
- if len(artifact_list) > 0:
- first_artifact = artifact_list[0] # 获取第一个元素
- beton_task_id = first_artifact["BetonTaskID"]
- beton_volume = first_artifact["BetonVolume"]
- artifact_id = first_artifact["ArtifactActionID"] # 获取ArtifactID
- print(f"获取到BetonTaskID: {beton_task_id}")
- print(f"获取到BetonVolume: {beton_volume}")
- print(f"获取到ArtifactActionID: {artifact_id}")
- return beton_task_id, beton_volume, artifact_id
- else:
- raise Exception("未找到未浇筑信息")
- raise Exception("获取未浇筑信息失败")
-
-
-# 连接Access数据库
-def connect_to_access_db(db_path, password):
- conn_str = (
- r'DRIVER={Microsoft Access Driver (*.mdb, *.accdb)};'
- f'DBQ={db_path};'
- f'PWD={password};'
- )
- return pyodbc.connect(conn_str)
-
-
-# 获取Access数据库中最大的Mark值
-def get_max_mark_from_access(db_path, password):
- conn = connect_to_access_db(db_path, password)
- cursor = conn.cursor()
-
- # 查询最大的Mark值
- cursor.execute("SELECT MAX(Mark) FROM Produce")
- max_mark = cursor.fetchone()[0]
-
- # 如果没有记录,返回0
- if max_mark is None:
- max_mark = 0
-
- conn.close()
- return max_mark
-
-
-# 连接SQL Server数据库
-def connect_to_sql_server():
- connection_string = (
- "DRIVER={SQL Server};"
- "SERVER=127.0.0.1;"
- "DATABASE=BS23DB;"
- "UID=sa;"
- "PWD=123;"
- )
- return pyodbc.connect(connection_string)
-
-
-# 插入数据到Produce表
-def insert_into_produce_table(connection, task_info, beton_volume, erp_id):
- cursor = connection.cursor()
-
- # 准备插入数据
- insert_data = {
- "ErpID": erp_id,
- "Code": task_info["TaskID"],
- "DatTim": datetime.now(),
- "Recipe": task_info["ProduceMixID"],
- "MorRec": "",
- "ProdMete": beton_volume,
- "MorMete": 0.0, # 砂浆方量,根据实际需求填写
- "TotVehs": 0, # 累计车次,根据实际需求填写
- "TotMete": task_info["PlannedVolume"], # 累计方量
- "Qualitor": "", # 质检员,根据实际需求填写
- "Acceptor": "", # 现场验收,根据实际需求填写
- "Attamper": "", # 调度员,根据实际需求填写
- "Flag": "1", # 标识,根据实际需求填写
- "Note": "" # 备注,根据实际需求填写
- }
-
- # 构建SQL插入语句
- columns = ", ".join(insert_data.keys())
- placeholders = ", ".join(["?" for _ in insert_data.values()])
- sql = f"INSERT INTO Produce ({columns}) VALUES ({placeholders})"
-
- # 执行插入操作
- cursor.execute(sql, list(insert_data.values()))
- connection.commit()
- print(f"数据已成功插入到Produce表中")
-
-
-# 主函数
-def main():
- try:
- # 步骤1:获取AppID
- app_id = get_app_id()
-
- # 上次获取的ArtifactID,用于检测变化
- last_artifact_id = None
-
- # Access数据库路径和密码
- access_db_path = "D:\\Janeoo-B12-DB\\Janeoo.2.mdb" # 替换为实际路径
- access_password = "BCS7.2_SDBS" # Access数据库密码
-
- while True:
- try:
- # 步骤2:获取未浇筑信息中的BetonTaskID、BetonVolume和ArtifactID
- beton_task_id, beton_volume, artifact_id = get_not_pour_info(app_id)
- # beton_task_id = "20251016-01"
-
- # 检查ArtifactID是否发生变化
- if artifact_id != last_artifact_id:
- print(f"检测到新任务: {artifact_id}")
-
- # 步骤3:使用BetonTaskID获取任务单信息
- task_info = get_task_info(app_id, beton_task_id)
-
- # 步骤4:连接Access数据库并获取最大Mark值
- max_mark = get_max_mark_from_access(access_db_path, access_password)
- erp_id = int(max_mark) + 1 # 在最大Mark值基础上加1
- print(f"获取到ERP ID: {erp_id}")
-
- # 步骤5:连接SQL Server数据库并插入数据
- connection = connect_to_sql_server()
- insert_into_produce_table(connection, task_info, beton_volume, erp_id)
- connection.close()
-
- # 更新上次获取的ArtifactID
- last_artifact_id = artifact_id
-
- # 每2秒检查一次
- time.sleep(2)
-
- except Exception as e:
- print(f"发生错误: {e}")
- # 继续循环,避免程序退出
- time.sleep(2)
-
- except KeyboardInterrupt:
- print("程序已停止")
-
-
-if __name__ == "__main__":
- main()
diff --git a/main.py b/main.py
new file mode 100644
index 0000000..f07040f
--- /dev/null
+++ b/main.py
@@ -0,0 +1,132 @@
+"""主程序入口"""
+import time
+import threading
+from datetime import datetime
+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, CHECK_INTERVAL, MAX_AGE_HOURS
+)
+from utils.helpers import cleanup_old_timestamps
+
+def start_api_service():
+ """启动配比重量API服务"""
+ api = MixWeightAPI()
+ api.run(host='127.0.0.1', port=5001, debug=False, threaded=True)
+
+def main():
+ api_thread = threading.Thread(target=start_api_service)
+ api_thread.daemon = True
+ api_thread.start()
+ try:
+ # 初始化TCP服务端
+ tcp_server = TCPServer(host=TCP_HOST, port=TCP_PORT)
+ tcp_server_thread = threading.Thread(target=tcp_server.start)
+ tcp_server_thread.daemon = True
+ tcp_server_thread.start()
+
+ # 等待服务端启动
+ time.sleep(1)
+
+ # 初始化服务
+ api_client = APIClient()
+ task_service = TaskService()
+ monitoring_service = MonitoringService(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 True:
+ 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:
+ print(f"检测到artifact_list更新: {artifact_list}")
+
+ # 处理新出现的任务
+ new_artifact_ids = current_artifact_ids - last_artifact_ids
+ if new_artifact_ids:
+ print(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:
+ # 准备插入数据
+ insert_data = {
+ "ErpID": erp_id,
+ "Code": task_info["TaskID"],
+ "DatTim": datetime.now(),
+ "Recipe": task_info["ProduceMixID"],
+ "MorRec": "",
+ "ProdMete": task["beton_volume"],
+ "MorMete": 0.0,
+ "TotVehs": 0,
+ "TotMete": task_info["PlannedVolume"],
+ "Qualitor": "",
+ "Acceptor": "",
+ "Attamper": "",
+ "Flag": "1",
+ "Note": ""
+ }
+
+ sql_db.insert_produce_data(insert_data)
+ print(f"数据已成功插入到Produce表中,ERP ID: {erp_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:
+ print(f"发生错误: {e}")
+ # 继续循环,避免程序退出
+ time.sleep(2)
+
+ except KeyboardInterrupt:
+ print("程序已停止")
+ # 停止TCP服务端
+ if 'tcp_server' in locals():
+ tcp_server.stop()
+
+
+if __name__ == "__main__":
+ main()
diff --git a/models/__init__.py b/models/__init__.py
new file mode 100644
index 0000000..36fc1f9
--- /dev/null
+++ b/models/__init__.py
@@ -0,0 +1,4 @@
+"""模型包"""
+from .task import Task, SendTask
+
+__all__ = ['Task', 'SendTask']
diff --git a/models/task.py b/models/task.py
new file mode 100644
index 0000000..bb33d89
--- /dev/null
+++ b/models/task.py
@@ -0,0 +1,20 @@
+"""任务相关数据模型"""
+from datetime import datetime
+
+class Task:
+ def __init__(self, beton_task_id, beton_volume, artifact_id, block_number):
+ self.beton_task_id = beton_task_id
+ self.beton_volume = beton_volume
+ self.artifact_id = artifact_id
+ self.block_number = block_number
+
+class SendTask:
+ def __init__(self, beton_task_id, beton_volume, artifact_id, block_number,
+ beton_grade, mix_id, timestamp=None):
+ self.beton_task_id = beton_task_id
+ self.beton_volume = beton_volume
+ self.artifact_id = artifact_id
+ self.block_number = block_number
+ self.beton_grade = beton_grade
+ self.mix_id = mix_id
+ self.timestamp = timestamp or datetime.now()
diff --git a/services/__init__.py b/services/__init__.py
new file mode 100644
index 0000000..dc69dbb
--- /dev/null
+++ b/services/__init__.py
@@ -0,0 +1,5 @@
+"""服务包"""
+from .task_service import TaskService
+from .monitoring_service import MonitoringService
+
+__all__ = ['TaskService', 'MonitoringService']
diff --git a/services/__pycache__/__init__.cpython-39.pyc b/services/__pycache__/__init__.cpython-39.pyc
new file mode 100644
index 0000000..603d984
Binary files /dev/null and b/services/__pycache__/__init__.cpython-39.pyc differ
diff --git a/services/__pycache__/monitoring_service.cpython-39.pyc b/services/__pycache__/monitoring_service.cpython-39.pyc
new file mode 100644
index 0000000..ad7892c
Binary files /dev/null and b/services/__pycache__/monitoring_service.cpython-39.pyc differ
diff --git a/services/__pycache__/task_service.cpython-39.pyc b/services/__pycache__/task_service.cpython-39.pyc
new file mode 100644
index 0000000..e5188da
Binary files /dev/null and b/services/__pycache__/task_service.cpython-39.pyc differ
diff --git a/services/monitoring_service.py b/services/monitoring_service.py
new file mode 100644
index 0000000..248838a
--- /dev/null
+++ b/services/monitoring_service.py
@@ -0,0 +1,228 @@
+
+"""监控服务"""
+import time
+import threading
+from datetime import datetime
+from database.access_db import AccessDB
+from database.sql_server import SQLServerDB
+from config.settings import ACCESS_DB_PATH, ACCESS_DB_PASSWORD, MONITOR_INTERVAL
+from tcp.server import TCPServer
+
+class MonitoringService:
+ def __init__(self, tcp_server):
+ self.tcp_server = tcp_server
+ self.task_flags = {}
+ self.monitored_tasks = set()
+ self.inserted_tasks = {}
+ self.tasks_lock = threading.Lock()
+
+ def monitor_access_flag_changes(self):
+ """监控Access数据库中派发任务的Flag状态"""
+ print("开始监控Access数据库中派发任务的Flag状态")
+
+ while True:
+ try:
+ # 每2秒检查一次
+ time.sleep(MONITOR_INTERVAL)
+
+ with self.tasks_lock:
+ # 如果没有需要监控的任务,跳过
+ if not self.monitored_tasks:
+ continue
+
+ # 创建需要监控的任务列表副本
+ tasks_to_monitor = self.monitored_tasks.copy()
+
+ # 检查SQL Server中任务是否还存在
+ sql_db = SQLServerDB()
+ try:
+ existing_tasks_in_sql = sql_db.check_existing_tasks(list(tasks_to_monitor))
+ finally:
+ sql_db.close()
+
+ # 分离已删除和未删除的任务
+ erp_ids_str = [str(erp_id) for erp_id in tasks_to_monitor]
+ deleted_from_sql_tasks = set(erp_ids_str) - existing_tasks_in_sql
+
+ print(f"SQL Server中仍存在的任务: {existing_tasks_in_sql}")
+ print(f"已从SQL Server删除的任务: {deleted_from_sql_tasks}")
+
+ # 只有已从SQL Server删除的任务才需要在Access中查找
+ if not deleted_from_sql_tasks:
+ continue
+
+ # 查询Access数据库中已删除任务的状态
+ access_db = AccessDB(ACCESS_DB_PATH, ACCESS_DB_PASSWORD)
+ try:
+ current_tasks = access_db.query_task_status(list(deleted_from_sql_tasks))
+ finally:
+ access_db.close()
+
+ # 处理任务状态变化
+ self._process_task_status_changes(deleted_from_sql_tasks, current_tasks)
+
+ except Exception as e:
+ print(f"监控Access数据库 Flag时发生错误: {e}")
+ import traceback
+ traceback.print_exc()
+ continue
+
+ def _process_task_status_changes(self, deleted_from_sql_tasks, current_tasks):
+ """处理任务状态变化"""
+ # 检查每个已删除任务的状态变化
+ for erp_id_str in deleted_from_sql_tasks:
+ erp_id = int(erp_id_str)
+ current_flag = current_tasks.get(erp_id_str, "")
+ previous_flag = self.task_flags.get(erp_id_str, "")
+
+ # 添加调试信息
+ print(f"检查任务 {erp_id} - 当前Flag: '{current_flag}', 之前Flag: '{previous_flag}'")
+
+ # 如果状态发生变化
+ if current_flag != previous_flag:
+ with self.tasks_lock:
+ artifact_id = self.inserted_tasks.get(erp_id, "Unknown")
+ print(
+ f"派发任务 ErpID {erp_id} (ArtifactID: {artifact_id}) 的Flag值已更新: {previous_flag} -> {current_flag}")
+ self.task_flags[erp_id_str] = current_flag
+
+ # 根据Flag值末尾的字母执行相应操作并更新自定义数据表状态
+ self._handle_flag_status_change(erp_id, current_flag, artifact_id)
+
+ # 检查是否有任务记录已被删除(不在查询结果中但仍在监控列表中)
+ # 这表示任务可能已完成或从系统中移除
+ missing_tasks = set(deleted_from_sql_tasks) - set(current_tasks.keys())
+ if missing_tasks:
+ self._handle_missing_tasks(missing_tasks)
+
+ def _handle_flag_status_change(self, erp_id, current_flag, artifact_id):
+ """处理标志状态变化"""
+ if current_flag.endswith('d'):
+ self._handle_status_d(erp_id, artifact_id)
+ elif current_flag.endswith('w'):
+ self._handle_status_w(erp_id, artifact_id)
+ elif current_flag.endswith('n'):
+ self._handle_status_n(erp_id, artifact_id)
+ elif current_flag.endswith('p'):
+ self._handle_status_p(erp_id, artifact_id)
+ elif current_flag.endswith('x'):
+ self._handle_status_x(erp_id, artifact_id)
+
+ def _handle_status_d(self, erp_id, artifact_id):
+ """处理状态'd' - 未进行生产"""
+ print(f"派发任务 ErpID {erp_id}: 未进行生产")
+ # 调用同事提供的状态更新函数
+ try:
+ print(1)
+ # update_custom_table_status(erp_id, "未进行生产")
+ except Exception as e:
+ print(f"更新状态时出错: {e}")
+
+ # 发送数据给TCP客户端(只发送erp_id和状态)
+ try:
+ status_data = {
+ "erp_id": erp_id,
+ "status": "未进行生产"
+ }
+ self.tcp_server.send_data(status_data)
+ except Exception as e:
+ print(f"发送状态数据给TCP客户端时出错: {e}")
+
+ def _handle_status_w(self, erp_id, artifact_id):
+ """处理状态'w' - 正在生产中"""
+ print(f"派发任务 ErpID {erp_id}: 正在生产中")
+ # 调用同事提供的状态更新函数
+ try:
+ print(2)
+ # update_custom_table_status(erp_id, "正在生产中")
+ except Exception as e:
+ print(f"更新状态时出错: {e}")
+
+ # 发送数据给TCP客户端(只发送erp_id和状态)
+ try:
+ status_data = {
+ "erp_id": erp_id,
+ "status": "正在生产中"
+ }
+ self.tcp_server.send_data(status_data)
+ except Exception as e:
+ print(f"发送状态数据给TCP客户端时出错: {e}")
+
+ def _handle_status_n(self, erp_id, artifact_id):
+ """处理状态'n' - 生产完毕"""
+ print(f"派发任务 ErpID {erp_id}: 生产完毕")
+ # 任务完成,可以从监控列表中移除
+ with self.tasks_lock:
+ self.monitored_tasks.discard(erp_id)
+ print(f"派发任务 ErpID {erp_id} 已完成,停止监控")
+ # 调用同事提供的状态更新函数
+ try:
+ print(3)
+ # update_custom_table_status(erp_id, "生产完毕")
+ except Exception as e:
+ print(f"更新状态时出错: {e}")
+
+ # 发送数据给TCP客户端(只发送erp_id和状态)
+ try:
+ status_data = {
+ "erp_id": erp_id,
+ "status": "生产完毕"
+ }
+ self.tcp_server.send_data(status_data)
+ except Exception as e:
+ print(f"发送状态数据给TCP客户端时出错: {e}")
+
+ def _handle_status_p(self, erp_id, artifact_id):
+ """处理状态'p' - 生产中断"""
+ print(f"派发任务 ErpID {erp_id}: 生产中断")
+ # 任务中断,可以从监控列表中移除
+ with self.tasks_lock:
+ self.monitored_tasks.discard(erp_id)
+ print(f"派发任务 ErpID {erp_id} 已中断,停止监控")
+ # 调用同事提供的状态更新函数
+ try:
+ print(4)
+ # update_custom_table_status(erp_id, "生产中断")
+ except Exception as e:
+ print(f"更新状态时出错: {e}")
+
+ # 发送数据给TCP客户端(只发送erp_id和状态)
+ try:
+ status_data = {
+ "erp_id": erp_id,
+ "status": "生产中断"
+ }
+ self.tcp_server.send_data(status_data)
+ except Exception as e:
+ print(f"发送状态数据给TCP客户端时出错: {e}")
+
+ def _handle_status_x(self, erp_id, artifact_id):
+ """处理状态'x' - 数据已接收"""
+ print(f"派发任务 ErpID {erp_id}: 数据已接收")
+ # 调用同事提供的状态更新函数
+ try:
+ print(5)
+ # update_custom_table_status(erp_id, "数据已接收")
+ except Exception as e:
+ print(f"更新状态时出错: {e}")
+
+ # 发送数据给TCP客户端(只发送erp_id和状态)
+ try:
+ status_data = {
+ "erp_id": erp_id,
+ "status": "数据已接收"
+ }
+ self.tcp_server.send_data(status_data)
+ except Exception as e:
+ print(f"发送状态数据给TCP客户端时出错: {e}")
+
+ def _handle_missing_tasks(self, missing_tasks):
+ """处理缺失的任务"""
+ for erp_id_str in missing_tasks:
+ erp_id = int(erp_id_str)
+ with self.tasks_lock:
+ artifact_id = self.inserted_tasks.get(erp_id, "Unknown")
+ self.monitored_tasks.discard(erp_id)
+ self.inserted_tasks.pop(erp_id, None)
+ self.task_flags.pop(erp_id_str, None)
+ print(f"派发任务 ErpID {erp_id} (ArtifactID: {artifact_id}) 记录已从Access数据库中删除或完成")
diff --git a/services/task_service.py b/services/task_service.py
new file mode 100644
index 0000000..4e8770b
--- /dev/null
+++ b/services/task_service.py
@@ -0,0 +1,303 @@
+"""任务处理服务"""
+from datetime import datetime
+from API.client import APIClient
+from database.access_db import AccessDB
+from database.sql_server import SQLServerDB
+from config.settings import ACCESS_DB_PATH, ACCESS_DB_PASSWORD
+from utils.helpers import get_f_block_positions
+
+
+class TaskService:
+ def __init__(self):
+ self.api_client = APIClient()
+ self.half_volume = [0, 0]
+ self.task_before = None
+ self.artifact_timestamps = {}
+
+ def process_not_pour_info(self):
+ """处理未浇筑信息"""
+ artifact_list = self.api_client.get_not_pour_info()
+
+ if not artifact_list:
+ return [], [], [], self.half_volume
+
+ # 处理F块信息
+ f_blocks_info = self._process_f_blocks(artifact_list)
+ f_blocks = f_blocks_info["f_blocks"]
+ f_block_count = f_blocks_info["f_block_count"]
+ total_f_volume = f_blocks_info["total_f_volume"]
+ f_positions = f_blocks_info["f_positions"]
+
+ # 处理当前任务
+ current_task = self._process_current_task(artifact_list[0])
+
+ # 更新上一个任务信息
+ self.task_before = {
+ "beton_task_id": current_task["beton_task_id"],
+ "beton_volume": current_task["beton_volume"],
+ "artifact_id": current_task["artifact_id"],
+ "block_number": current_task["block_number"]
+ }
+
+ # 根据F块情况处理任务
+ task_result = self._handle_tasks_by_f_blocks(
+ f_block_count, f_positions, current_task,
+ f_blocks, total_f_volume, artifact_list
+ )
+
+ return task_result
+
+ def _process_f_blocks(self, artifact_list):
+ """处理F块相关信息"""
+ f_blocks = [artifact for artifact in artifact_list if artifact.get("BlockNumber") == "F"]
+ f_block_count = len(f_blocks)
+ total_f_volume = sum(artifact["BetonVolume"] for artifact in f_blocks)
+ f_positions = get_f_block_positions(artifact_list)
+
+ return {
+ "f_blocks": f_blocks,
+ "f_block_count": f_block_count,
+ "total_f_volume": total_f_volume,
+ "f_positions": f_positions
+ }
+
+ def _process_current_task(self, latest_artifact):
+ """处理当前任务信息"""
+ task_data = self.api_client.get_task_info(latest_artifact["BetonTaskID"])
+ return {
+ "beton_task_id": latest_artifact["BetonTaskID"],
+ "beton_volume": latest_artifact["BetonVolume"],
+ "artifact_id": latest_artifact["ArtifactActionID"],
+ "block_number": latest_artifact.get("BlockNumber", ""),
+ "task_data": task_data
+ }
+
+ def _handle_tasks_by_f_blocks(self, f_block_count, f_positions, current_task,
+ f_blocks, total_f_volume, artifact_list):
+ """根据F块数量和位置处理任务"""
+ # 多个F块情况
+ if f_block_count > 2:
+ return self._handle_multiple_f_blocks(current_task, total_f_volume, artifact_list)
+
+ # 两个F块情况
+ elif f_block_count == 2:
+ return self._handle_two_f_blocks(f_positions, current_task, total_f_volume, artifact_list)
+
+ # 一个F块情况
+ elif f_block_count == 1:
+ return self._handle_single_f_block(f_positions, current_task, f_blocks,
+ total_f_volume, artifact_list)
+
+ # 无F块情况
+ elif f_block_count == 0:
+ return self._handle_no_f_blocks(current_task, artifact_list)
+
+ else:
+ print("报警")
+ return [], [], [], self.half_volume
+
+ def _handle_multiple_f_blocks(self, current_task, total_f_volume, artifact_list):
+ """处理多个F块的情况"""
+ adjusted_volume = total_f_volume - self.half_volume[0]
+
+ tasks = [{
+ "beton_task_id": current_task["beton_task_id"],
+ "beton_volume": adjusted_volume,
+ "artifact_id": current_task["artifact_id"],
+ "block_number": current_task["block_number"],
+ }]
+
+ send_list = [{
+ "beton_task_id": current_task["beton_task_id"],
+ "beton_volume": adjusted_volume,
+ "artifact_id": current_task["artifact_id"],
+ "block_number": current_task["block_number"],
+ "beton_grade": current_task["task_data"]["BetonGrade"],
+ "mix_id": current_task["task_data"]["MixID"],
+ "time": self.artifact_timestamps.get(current_task["artifact_id"], datetime.now())
+ }]
+
+ # 处理后续任务
+ self._append_additional_tasks(send_list, artifact_list, [0, 0])
+
+ # 更新时间戳
+ self._update_artifact_timestamps(send_list)
+
+ return tasks, artifact_list, send_list, self.half_volume
+
+ def _handle_two_f_blocks(self, f_positions, current_task, total_f_volume, artifact_list):
+ """处理两个F块的情况"""
+ if f_positions == [0, 1] and self.task_before.get("block_number") == "F":
+ adjusted_volume = 0
+ block_number = "补方"
+ else:
+ adjusted_volume = total_f_volume - self.half_volume[0]
+ block_number = current_task["block_number"]
+
+ tasks = [{
+ "beton_task_id": current_task["beton_task_id"],
+ "beton_volume": adjusted_volume,
+ "artifact_id": current_task["artifact_id"],
+ "block_number": block_number,
+ }]
+
+ send_list = [{
+ "beton_task_id": current_task["beton_task_id"],
+ "beton_volume": adjusted_volume,
+ "artifact_id": current_task["artifact_id"],
+ "block_number": block_number,
+ "beton_grade": current_task["task_data"]["BetonGrade"],
+ "mix_id": current_task["task_data"]["MixID"],
+ "time": self.artifact_timestamps.get(current_task["artifact_id"], datetime.now())
+ }]
+
+ # 处理后续任务
+ volumes = [adjusted_volume,
+ artifact_list[2]["BetonVolume"] if len(artifact_list) > 2 else 0] if f_positions == [0,
+ 1] and self.task_before.get(
+ "block_number") == "F" else [0, 0]
+ self._append_additional_tasks(send_list, artifact_list, volumes)
+
+ # 更新时间戳
+ self._update_artifact_timestamps(send_list)
+
+ return tasks, artifact_list, send_list, self.half_volume
+
+ def _handle_single_f_block(self, f_positions, current_task, f_blocks, total_f_volume, artifact_list):
+ """处理单个F块的情况"""
+ if f_positions == [2]:
+ f_volume = f_blocks[0].get("BetonVolume") if f_blocks else 0
+ self.half_volume[0] = round(total_f_volume / 2, 2)
+ self.half_volume[1] = f_volume - self.half_volume[0]
+ adjusted_volume = current_task["beton_volume"] + self.half_volume[0]
+ elif f_positions == [1]:
+ adjusted_volume = current_task["beton_volume"] + self.half_volume[1]
+ elif f_positions == [0]:
+ adjusted_volume = 0
+ else:
+ adjusted_volume = current_task["beton_volume"]
+
+ block_number = "补方" if f_positions == [0] else current_task["block_number"]
+
+ tasks = [{
+ "beton_task_id": current_task["beton_task_id"],
+ "beton_volume": adjusted_volume,
+ "artifact_id": current_task["artifact_id"],
+ "block_number": block_number,
+ }]
+
+ send_list = [{
+ "beton_task_id": current_task["beton_task_id"],
+ "beton_volume": adjusted_volume,
+ "artifact_id": current_task["artifact_id"],
+ "block_number": block_number,
+ "beton_grade": current_task["task_data"]["BetonGrade"],
+ "mix_id": current_task["task_data"]["MixID"],
+ "time": self.artifact_timestamps.get(current_task["artifact_id"], datetime.now())
+ }]
+
+ # 处理后续任务
+ self._append_additional_tasks_for_single_f(send_list, artifact_list, f_positions)
+
+ # 更新时间戳
+ self._update_artifact_timestamps(send_list)
+
+ return tasks, artifact_list, send_list, self.half_volume
+
+ def _handle_no_f_blocks(self, current_task, artifact_list):
+ """处理无F块的情况"""
+ tasks = [{
+ "beton_task_id": current_task["beton_task_id"],
+ "beton_volume": current_task["beton_volume"],
+ "artifact_id": current_task["artifact_id"],
+ "block_number": current_task["block_number"],
+ }]
+
+ send_list = [{
+ "beton_task_id": current_task["beton_task_id"],
+ "beton_volume": current_task["beton_volume"],
+ "artifact_id": current_task["artifact_id"],
+ "block_number": current_task["block_number"],
+ "beton_grade": current_task["task_data"]["BetonGrade"],
+ "mix_id": current_task["task_data"]["MixID"],
+ "time": self.artifact_timestamps.get(current_task["artifact_id"], datetime.now())
+ }]
+
+ # 处理后续任务
+ self._append_additional_tasks(send_list, artifact_list,
+ [artifact_list[2]["BetonVolume"] if len(artifact_list) > 2 else 0,
+ artifact_list[2]["BetonVolume"] if len(artifact_list) > 2 else 0])
+
+ # 更新时间戳
+ self._update_artifact_timestamps(send_list)
+
+ return tasks, artifact_list, send_list, self.half_volume
+
+ def _append_additional_tasks(self, send_list, artifact_list, volumes):
+ """添加额外的任务到发送列表"""
+ # 安全获取后续任务
+ second_task = artifact_list[1] if len(artifact_list) > 1 else None
+ third_task = artifact_list[2] if len(artifact_list) > 2 else None
+
+ if second_task:
+ task_data_second = self.api_client.get_task_info(second_task["BetonTaskID"])
+ send_list.append({
+ "beton_task_id": second_task["BetonTaskID"],
+ "beton_volume": volumes[0],
+ "artifact_id": second_task["ArtifactActionID"],
+ "block_number": second_task["BlockNumber"],
+ "beton_grade": task_data_second["BetonGrade"],
+ "mix_id": task_data_second["MixID"],
+ "time": self.artifact_timestamps.get(second_task["ArtifactActionID"], datetime.now())
+ })
+
+ if third_task:
+ task_data_third = self.api_client.get_task_info(third_task["BetonTaskID"])
+ send_list.append({
+ "beton_task_id": third_task["BetonTaskID"],
+ "beton_volume": volumes[1],
+ "artifact_id": third_task["ArtifactActionID"],
+ "block_number": third_task["BlockNumber"],
+ "beton_grade": task_data_third["BetonGrade"],
+ "mix_id": task_data_third["MixID"],
+ "time": self.artifact_timestamps.get(third_task["ArtifactActionID"], datetime.now())
+ })
+
+ def _append_additional_tasks_for_single_f(self, send_list, artifact_list, f_positions):
+ """为单个F块情况添加额外任务"""
+ second_task = artifact_list[1] if len(artifact_list) > 1 else None
+ third_task = artifact_list[2] if len(artifact_list) > 2 else None
+
+ if second_task:
+ task_data_second = self.api_client.get_task_info(second_task["BetonTaskID"])
+ volume = (third_task["BetonVolume"] if third_task else 0) if f_positions != [2] else (
+ second_task["BetonVolume"] + self.half_volume[1])
+ send_list.append({
+ "beton_task_id": second_task["BetonTaskID"],
+ "beton_volume": volume,
+ "artifact_id": second_task["ArtifactActionID"],
+ "block_number": second_task["BlockNumber"],
+ "beton_grade": task_data_second["BetonGrade"],
+ "mix_id": task_data_second["MixID"],
+ "time": self.artifact_timestamps.get(second_task["ArtifactActionID"], datetime.now())
+ })
+
+ if third_task:
+ task_data_third = self.api_client.get_task_info(third_task["BetonTaskID"])
+ volume = third_task["BetonVolume"] if f_positions in [[1], [0]] else 0
+ send_list.append({
+ "beton_task_id": third_task["BetonTaskID"],
+ "beton_volume": volume,
+ "artifact_id": third_task["ArtifactActionID"],
+ "block_number": third_task["BlockNumber"],
+ "beton_grade": task_data_third["BetonGrade"],
+ "mix_id": task_data_third["MixID"],
+ "time": self.artifact_timestamps.get(third_task["ArtifactActionID"], datetime.now())
+ })
+
+ def _update_artifact_timestamps(self, send_list):
+ """更新artifact时间戳"""
+ current_artifact_ids = {item["artifact_id"] for item in send_list}
+ for artifact_id in current_artifact_ids:
+ if artifact_id not in self.artifact_timestamps:
+ self.artifact_timestamps[artifact_id] = datetime.now()
diff --git a/tcp/__init__.py b/tcp/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/tcp/__pycache__/__init__.cpython-39.pyc b/tcp/__pycache__/__init__.cpython-39.pyc
new file mode 100644
index 0000000..0163450
Binary files /dev/null and b/tcp/__pycache__/__init__.cpython-39.pyc differ
diff --git a/tcp/__pycache__/server.cpython-39.pyc b/tcp/__pycache__/server.cpython-39.pyc
new file mode 100644
index 0000000..a6e0632
Binary files /dev/null and b/tcp/__pycache__/server.cpython-39.pyc differ
diff --git a/TCPServer.py b/tcp/server.py
similarity index 95%
rename from TCPServer.py
rename to tcp/server.py
index cd3ac9d..91643ff 100644
--- a/TCPServer.py
+++ b/tcp/server.py
@@ -2,8 +2,7 @@ import socket
import json
import threading
import time
-from datetime import datetime
-import os
+
class TCPServer:
@@ -109,16 +108,16 @@ class TCPServer:
print(f"收到异常生产通知 - 时间: {timestamp}, ERP ID: {erp_id}")
# 调用update_custom_table_status更新数据库状态
try:
- # update_custom_table_status(erp_id, "异常生产")
+ update_custom_table_status(erp_id, "异常生产")
print(f"数据库状态已更新为: 异常生产 (ERP ID: {erp_id})")
except Exception as e:
print(f"更新数据库状态时出错: {e}")
- elif cmd == "interrupt_error":
+ elif cmd == "cancel_feed":
print(f"收到中断生产通知 - 时间: {timestamp}, ERP ID: {erp_id}")
# 调用update_custom_table_status更新数据库状态
try:
- # update_custom_table_status(erp_id, "中断生产")
- print(f"数据库状态已更新为: 中断生产 (ERP ID: {erp_id})")
+ update_custom_table_status(erp_id, "取消生产")
+ print(f"数据库状态已更新为: 取消生产 (ERP ID: {erp_id})")
except Exception as e:
print(f"更新数据库状态时出错: {e}")
else:
diff --git a/temp.py b/temp.py
new file mode 100644
index 0000000..2214966
--- /dev/null
+++ b/temp.py
@@ -0,0 +1,432 @@
+def get_all_not_pour_info(app_id): # 添加这一行声明
+ global task_before, half_volume, artifact_timestamps
+ headers = {"AppID": app_id}
+ response = requests.get(NOT_POUR_INFO_URL, headers=headers)
+ if response.status_code == 200:
+ data = response.json()
+ if data.get("Code") == 200:
+ artifact_list = data["Data"]
+ send_list = []
+ tasks = []
+
+ if not artifact_list:
+ return tasks
+ if task_before is not None:
+ # 这里可以处理上一条任务的逻辑
+ print(f"上一条任务: {task_before}")
+ # 记录F块位置
+ f_positions = get_f_block_positions(artifact_list)
+ # 统计F块数量和总方量
+ f_blocks = [artifact for artifact in artifact_list if artifact.get("BlockNumber") == "F"]
+ f_block_count = len(f_blocks)
+ total_f_volume = sum(artifact["BetonVolume"] for artifact in f_blocks)
+
+ # 处理最上面一条
+ latest_artifact = artifact_list[0]
+ beton_task_id = latest_artifact["BetonTaskID"]
+ beton_volume = latest_artifact["BetonVolume"]
+ artifact_id = latest_artifact["ArtifactActionID"]
+ block_number = latest_artifact.get("BlockNumber", "")
+
+ task_before = {
+ "beton_task_id": latest_artifact["BetonTaskID"],
+ "beton_volume": latest_artifact["BetonVolume"],
+ "artifact_id": latest_artifact["ArtifactActionID"],
+ "block_number": latest_artifact.get("BlockNumber", "")
+ }
+ task_data = get_task_info(app_id, beton_task_id)
+ if f_block_count == 1 and f_positions == [2]:
+ f_volume = f_blocks.get("BetonVolume")
+ half_volume[0] = round(total_f_volume / 2, 2)
+ half_volume[1] = f_volume - half_volume[0]
+ # 如果有多个F块,先派当前任务,再创建补方任务
+ if f_block_count > 2:
+ adjusted_volume = total_f_volume - half_volume[0]
+ tasks.append({
+ "beton_task_id": beton_task_id,
+ "beton_volume": adjusted_volume,
+ "artifact_id": artifact_id,
+ "block_number": block_number,
+ })
+ send_list.append({
+ "beton_task_id": beton_task_id,
+ "beton_volume": adjusted_volume,
+ "artifact_id": artifact_id,
+ "block_number": block_number,
+ "beton_grade": task_data["BetonGrade"],
+ "mix_id": task_data["MixID"],
+ "time": artifact_timestamps.get(artifact_id, datetime.now())
+ })
+ dispatch_list_second = artifact_list[1]
+ task_data_second = get_task_info(app_id, dispatch_list_second["BetonTaskID"])
+ dispatch_list_third = artifact_list[2]
+ task_data_third = get_task_info(app_id, dispatch_list_third["BetonTaskID"])
+ send_list.append({
+ "beton_task_id": dispatch_list_second["BetonTaskID"],
+ "beton_volume": 0,
+ "artifact_id": dispatch_list_second["ArtifactActionID"],
+ "block_number": dispatch_list_second["BlockNumber"],
+ "beton_grade": task_data_second["BetonGrade"],
+ "mix_id": task_data_second["MixID"],
+ "time": artifact_timestamps.get(dispatch_list_second["ArtifactActionID"], datetime.now())
+ })
+ send_list.append({
+ "beton_task_id": dispatch_list_third["BetonTaskID"],
+ "beton_volume": 0,
+ "artifact_id": dispatch_list_third["ArtifactActionID"],
+ "block_number": dispatch_list_third["BlockNumber"],
+ "beton_grade": task_data_third["BetonGrade"],
+ "mix_id": task_data_third["MixID"],
+ "time": artifact_timestamps.get(dispatch_list_third["ArtifactActionID"], datetime.now())
+ })
+ # 更新新出现的 artifact_id 的时间戳
+ current_artifact_ids = {item["artifact_id"] for item in send_list}
+ for artifact_id in current_artifact_ids:
+ if artifact_id not in artifact_timestamps:
+ artifact_timestamps[artifact_id] = datetime.now()
+ return tasks, artifact_list, send_list, half_volume
+
+ elif f_block_count == 2 and f_positions == [0, 1] and task_before.block_number == "F":
+ adjusted_volume = 0
+ tasks.append({
+ "beton_task_id": beton_task_id,
+ "beton_volume": adjusted_volume,
+ "artifact_id": artifact_id,
+ "block_number": "补方",
+ })
+ send_list.append({
+ "beton_task_id": beton_task_id,
+ "beton_volume": adjusted_volume,
+ "artifact_id": artifact_id,
+ "block_number": block_number,
+ "beton_grade": task_data["BetonGrade"],
+ "mix_id": task_data["MixID"],
+ "time": artifact_timestamps.get(artifact_id, datetime.now())
+ })
+ dispatch_list_second = artifact_list[1]
+ task_data_second = get_task_info(app_id, dispatch_list_second["BetonTaskID"])
+ dispatch_list_third = artifact_list[2]
+ task_data_third = get_task_info(app_id, dispatch_list_third["BetonTaskID"])
+ send_list.append({
+ "beton_task_id": dispatch_list_second["BetonTaskID"],
+ "beton_volume": adjusted_volume,
+ "artifact_id": dispatch_list_second["ArtifactActionID"],
+ "block_number": dispatch_list_second["BlockNumber"],
+ "beton_grade": task_data_second["BetonGrade"],
+ "mix_id": task_data_second["MixID"],
+ "time": artifact_timestamps.get(dispatch_list_second["ArtifactActionID"], datetime.now())
+ })
+ send_list.append({
+ "beton_task_id": dispatch_list_third["BetonTaskID"],
+ "beton_volume": dispatch_list_third["BetonVolume"],
+ "artifact_id": dispatch_list_third["ArtifactActionID"],
+ "block_number": dispatch_list_third["BlockNumber"],
+ "beton_grade": task_data_third["BetonGrade"],
+ "mix_id": task_data_third["MixID"],
+ "time": artifact_timestamps.get(dispatch_list_third["ArtifactActionID"], datetime.now())
+ })
+ # 更新新出现的 artifact_id 的时间戳
+ current_artifact_ids = {item["artifact_id"] for item in send_list}
+ for artifact_id in current_artifact_ids:
+ if artifact_id not in artifact_timestamps:
+ artifact_timestamps[artifact_id] = datetime.now()
+ return tasks, artifact_list, send_list, half_volume
+
+ elif f_block_count == 2 and f_positions == [1, 2]:
+ adjusted_volume = total_f_volume - half_volume[0]
+ tasks.append({
+ "beton_task_id": beton_task_id,
+ "beton_volume": beton_volume,
+ "artifact_id": artifact_id,
+ "block_number": block_number,
+ })
+ send_list.append({
+ "beton_task_id": beton_task_id,
+ "beton_volume": beton_volume,
+ "artifact_id": artifact_id,
+ "block_number": block_number,
+ "beton_grade": task_data["BetonGrade"],
+ "mix_id": task_data["MixID"],
+ "time": artifact_timestamps.get(artifact_id, datetime.now())
+ })
+ dispatch_list_second = artifact_list[1]
+ task_data_second = get_task_info(app_id, dispatch_list_second["BetonTaskID"])
+ dispatch_list_third = artifact_list[2]
+ task_data_third = get_task_info(app_id, dispatch_list_third["BetonTaskID"])
+ send_list.append({
+ "beton_task_id": dispatch_list_second["BetonTaskID"],
+ "beton_volume": adjusted_volume,
+ "artifact_id": dispatch_list_second["ArtifactActionID"],
+ "block_number": dispatch_list_second["BlockNumber"],
+ "beton_grade": task_data_second["BetonGrade"],
+ "mix_id": task_data_second["MixID"],
+ "time": artifact_timestamps.get(dispatch_list_second["ArtifactActionID"], datetime.now())
+ })
+ send_list.append({
+ "beton_task_id": dispatch_list_third["BetonTaskID"],
+ "beton_volume": 0,
+ "artifact_id": dispatch_list_third["ArtifactActionID"],
+ "block_number": dispatch_list_third["BlockNumber"],
+ "beton_grade": task_data_third["BetonGrade"],
+ "mix_id": task_data_third["MixID"],
+ "time": artifact_timestamps.get(dispatch_list_third["ArtifactActionID"], datetime.now())
+ })
+ # 更新新出现的 artifact_id 的时间戳
+ current_artifact_ids = {item["artifact_id"] for item in send_list}
+ for artifact_id in current_artifact_ids:
+ if artifact_id not in artifact_timestamps:
+ artifact_timestamps[artifact_id] = datetime.now()
+ return tasks, artifact_list, send_list, half_volume
+
+ elif f_block_count == 2 and f_positions == [0, 1] and task_before.block_number != "F":
+ adjusted_volume = total_f_volume - half_volume[0]
+ tasks.append({
+ "beton_task_id": beton_task_id,
+ "beton_volume": adjusted_volume,
+ "artifact_id": artifact_id,
+ "block_number": block_number,
+ })
+ send_list.append({
+ "beton_task_id": beton_task_id,
+ "beton_volume": adjusted_volume,
+ "artifact_id": artifact_id,
+ "block_number": block_number,
+ "beton_grade": task_data["BetonGrade"],
+ "mix_id": task_data["MixID"],
+ "time": artifact_timestamps.get(artifact_id, datetime.now())
+ })
+ dispatch_list_second = artifact_list[1]
+ task_data_second = get_task_info(app_id, dispatch_list_second["BetonTaskID"])
+ dispatch_list_third = artifact_list[2]
+ task_data_third = get_task_info(app_id, dispatch_list_third["BetonTaskID"])
+ send_list.append({
+ "beton_task_id": dispatch_list_second["BetonTaskID"],
+ "beton_volume": 0,
+ "artifact_id": dispatch_list_second["ArtifactActionID"],
+ "block_number": dispatch_list_second["BlockNumber"],
+ "beton_grade": task_data_second["BetonGrade"],
+ "mix_id": task_data_second["MixID"],
+ "time": artifact_timestamps.get(dispatch_list_second["ArtifactActionID"], datetime.now())
+ })
+ send_list.append({
+ "beton_task_id": dispatch_list_third["BetonTaskID"],
+ "beton_volume": dispatch_list_third["BetonVolume"],
+ "artifact_id": dispatch_list_third["ArtifactActionID"],
+ "block_number": dispatch_list_third["BlockNumber"],
+ "beton_grade": task_data_third["BetonGrade"],
+ "mix_id": task_data_third["MixID"],
+ "time": artifact_timestamps.get(dispatch_list_third["ArtifactActionID"], datetime.now())
+ })
+ # 更新新出现的 artifact_id 的时间戳
+ current_artifact_ids = {item["artifact_id"] for item in send_list}
+ for artifact_id in current_artifact_ids:
+ if artifact_id not in artifact_timestamps:
+ artifact_timestamps[artifact_id] = datetime.now()
+ return tasks, artifact_list, send_list, half_volume
+
+ elif f_block_count == 1 and f_positions == [2]:
+ adjusted_volume = beton_volume + half_volume[0]
+ tasks.append({
+ "beton_task_id": beton_task_id,
+ "beton_volume": adjusted_volume,
+ "artifact_id": artifact_id,
+ "block_number": block_number,
+ })
+ send_list.append({
+ "beton_task_id": beton_task_id,
+ "beton_volume": adjusted_volume,
+ "artifact_id": artifact_id,
+ "block_number": block_number,
+ "beton_grade": task_data["BetonGrade"],
+ "mix_id": task_data["MixID"],
+ "time": artifact_timestamps.get(artifact_id, datetime.now())
+ })
+ dispatch_list_second = artifact_list[1]
+ task_data_second = get_task_info(app_id, dispatch_list_second["BetonTaskID"])
+ dispatch_list_third = artifact_list[2]
+ task_data_third = get_task_info(app_id, dispatch_list_third["BetonTaskID"])
+ send_list.append({
+ "beton_task_id": dispatch_list_second["BetonTaskID"],
+ "beton_volume": beton_volume + half_volume[1],
+ "artifact_id": dispatch_list_second["ArtifactActionID"],
+ "block_number": dispatch_list_second["BlockNumber"],
+ "beton_grade": task_data_second["BetonGrade"],
+ "mix_id": task_data_second["MixID"],
+ "time": artifact_timestamps.get(dispatch_list_second["ArtifactActionID"], datetime.now())
+ })
+ send_list.append({
+ "beton_task_id": dispatch_list_third["BetonTaskID"],
+ "beton_volume": dispatch_list_third["BetonVolume"],
+ "artifact_id": dispatch_list_third["ArtifactActionID"],
+ "block_number": dispatch_list_third["BlockNumber"],
+ "beton_grade": task_data_third["BetonGrade"],
+ "mix_id": task_data_third["MixID"],
+ "time": artifact_timestamps.get(dispatch_list_third["ArtifactActionID"], datetime.now())
+ })
+ # 更新新出现的 artifact_id 的时间戳
+ current_artifact_ids = {item["artifact_id"] for item in send_list}
+ for artifact_id in current_artifact_ids:
+ if artifact_id not in artifact_timestamps:
+ artifact_timestamps[artifact_id] = datetime.now()
+ return tasks, artifact_list, send_list, half_volume
+
+ elif f_block_count == 1 and f_positions == [1]:
+ adjusted_volume = beton_volume + half_volume[1]
+ tasks.append({
+ "beton_task_id": beton_task_id,
+ "beton_volume": adjusted_volume,
+ "artifact_id": artifact_id,
+ "block_number": block_number,
+ })
+ send_list.append({
+ "beton_task_id": beton_task_id,
+ "beton_volume": adjusted_volume,
+ "artifact_id": artifact_id,
+ "block_number": block_number,
+ "beton_grade": task_data["BetonGrade"],
+ "mix_id": task_data["MixID"],
+ "time": artifact_timestamps.get(artifact_id, datetime.now())
+ })
+ dispatch_list_second = artifact_list[1]
+ task_data_second = get_task_info(app_id, dispatch_list_second["BetonTaskID"])
+ dispatch_list_third = artifact_list[2]
+ task_data_third = get_task_info(app_id, dispatch_list_third["BetonTaskID"])
+ send_list.append({
+ "beton_task_id": dispatch_list_second["BetonTaskID"],
+ "beton_volume": dispatch_list_third["BetonVolume"],
+ "artifact_id": dispatch_list_second["ArtifactActionID"],
+ "block_number": dispatch_list_second["BlockNumber"],
+ "beton_grade": task_data_second["BetonGrade"],
+ "mix_id": task_data_second["MixID"],
+ "time": artifact_timestamps.get(dispatch_list_second["ArtifactActionID"], datetime.now())
+ })
+ send_list.append({
+ "beton_task_id": dispatch_list_third["BetonTaskID"],
+ "beton_volume": dispatch_list_third["BetonVolume"],
+ "artifact_id": dispatch_list_third["ArtifactActionID"],
+ "block_number": dispatch_list_third["BlockNumber"],
+ "beton_grade": task_data_third["BetonGrade"],
+ "mix_id": task_data_third["MixID"],
+ "time": artifact_timestamps.get(dispatch_list_third["ArtifactActionID"], datetime.now())
+ })
+ # 更新新出现的 artifact_id 的时间戳
+ current_artifact_ids = {item["artifact_id"] for item in send_list}
+ for artifact_id in current_artifact_ids:
+ if artifact_id not in artifact_timestamps:
+ artifact_timestamps[artifact_id] = datetime.now()
+ return tasks, artifact_list, send_list, half_volume
+
+ elif f_block_count == 1 and f_positions == [0]:
+ adjusted_volume = 0
+ tasks.append({
+ "beton_task_id": beton_task_id,
+ "beton_volume": adjusted_volume,
+ "artifact_id": artifact_id,
+ "block_number": "补方",
+ })
+ send_list.append({
+ "beton_task_id": beton_task_id,
+ "beton_volume": adjusted_volume,
+ "artifact_id": artifact_id,
+ "block_number": block_number,
+ "beton_grade": task_data["BetonGrade"],
+ "mix_id": task_data["MixID"],
+ "time": artifact_timestamps.get(artifact_id, datetime.now())
+ })
+ dispatch_list_second = artifact_list[1]
+ task_data_second = get_task_info(app_id, dispatch_list_second["BetonTaskID"])
+ dispatch_list_third = artifact_list[2]
+ task_data_third = get_task_info(app_id, dispatch_list_third["BetonTaskID"])
+ send_list.append({
+ "beton_task_id": dispatch_list_second["BetonTaskID"],
+ "beton_volume": dispatch_list_third["BetonVolume"],
+ "artifact_id": dispatch_list_second["ArtifactActionID"],
+ "block_number": dispatch_list_second["BlockNumber"],
+ "beton_grade": task_data_second["BetonGrade"],
+ "mix_id": task_data_second["MixID"],
+ "time": artifact_timestamps.get(dispatch_list_second["ArtifactActionID"], datetime.now())
+ })
+ send_list.append({
+ "beton_task_id": dispatch_list_third["BetonTaskID"],
+ "beton_volume": dispatch_list_third["BetonVolume"],
+ "artifact_id": dispatch_list_third["ArtifactActionID"],
+ "block_number": dispatch_list_third["BlockNumber"],
+ "beton_grade": task_data_third["BetonGrade"],
+ "mix_id": task_data_third["MixID"],
+ "time": artifact_timestamps.get(dispatch_list_third["ArtifactActionID"], datetime.now())
+ })
+ # 更新新出现的 artifact_id 的时间戳
+ current_artifact_ids = {item["artifact_id"] for item in send_list}
+ for artifact_id in current_artifact_ids:
+ if artifact_id not in artifact_timestamps:
+ artifact_timestamps[artifact_id] = datetime.now()
+ return tasks, artifact_list, send_list, half_volume
+ elif f_block_count == 0:
+ adjusted_volume = beton_volume
+ tasks.append({
+ "beton_task_id": beton_task_id,
+ "beton_volume": adjusted_volume,
+ "artifact_id": artifact_id,
+ "block_number": block_number,
+ })
+ send_list.append({
+ "beton_task_id": beton_task_id,
+ "beton_volume": adjusted_volume,
+ "artifact_id": artifact_id,
+ "block_number": block_number,
+ "beton_grade": task_data["BetonGrade"],
+ "mix_id": task_data["MixID"],
+ "time": artifact_timestamps.get(artifact_id, datetime.now())
+ })
+ dispatch_list_second = artifact_list[1]
+ task_data_second = get_task_info(app_id, dispatch_list_second["BetonTaskID"])
+ dispatch_list_third = artifact_list[2]
+ task_data_third = get_task_info(app_id, dispatch_list_third["BetonTaskID"])
+ send_list.append({
+ "beton_task_id": dispatch_list_second["BetonTaskID"],
+ "beton_volume": dispatch_list_third["BetonVolume"],
+ "artifact_id": dispatch_list_second["ArtifactActionID"],
+ "block_number": dispatch_list_second["BlockNumber"],
+ "beton_grade": task_data_second["BetonGrade"],
+ "mix_id": task_data_second["MixID"],
+ "time": artifact_timestamps.get(dispatch_list_second["ArtifactActionID"], datetime.now())
+ })
+ send_list.append({
+ "beton_task_id": dispatch_list_third["BetonTaskID"],
+ "beton_volume": dispatch_list_third["BetonVolume"],
+ "artifact_id": dispatch_list_third["ArtifactActionID"],
+ "block_number": dispatch_list_third["BlockNumber"],
+ "beton_grade": task_data_third["BetonGrade"],
+ "mix_id": task_data_third["MixID"],
+ "time": artifact_timestamps.get(dispatch_list_third["ArtifactActionID"], datetime.now())
+ })
+ # 更新新出现的 artifact_id 的时间戳
+ current_artifact_ids = {item["artifact_id"] for item in send_list}
+ for artifact_id in current_artifact_ids:
+ if artifact_id not in artifact_timestamps:
+ artifact_timestamps[artifact_id] = datetime.now()
+ return tasks, artifact_list, send_list, half_volume
+
+ else:
+ print("报警")
+
+ raise Exception("获取未浇筑信息失败")
+
+
+{
+ "ArtifactID": "QR1B32000153AD",
+ "ArtifactActionID": 346482967298128,
+ "ArtifactIDVice1": "Q00001AD",
+ "ProduceRingNumber": 1,
+ "MouldCode": "SHR2B3-9",
+ "SkeletonID": "QR1B2000048A",
+ "RingTypeCode": "R22",
+ "SizeSpecification": "6900*1500",
+ "BuriedDepth": "中埋",
+ "BlockNumber": "F",
+ "HoleRingMarking": "否",
+ "GroutingPipeMarking": "否",
+ "PolypropyleneFiberMarking": "否",
+ "BetonVolume": 0.55,
+ "BetonTaskID": "20251020-01"
+},
\ No newline at end of file
diff --git a/test.py b/test.py
deleted file mode 100644
index 3861ab0..0000000
--- a/test.py
+++ /dev/null
@@ -1,5 +0,0 @@
-import pyodbc
-print("系统中可用的ODBC驱动程序:")
-for driver in pyodbc.drivers():
- if "Access" in driver or "Excel" in driver:
- print(f" {driver}")
diff --git a/utils/__init__.py b/utils/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/utils/__pycache__/__init__.cpython-39.pyc b/utils/__pycache__/__init__.cpython-39.pyc
new file mode 100644
index 0000000..a0ca318
Binary files /dev/null and b/utils/__pycache__/__init__.cpython-39.pyc differ
diff --git a/utils/__pycache__/helpers.cpython-39.pyc b/utils/__pycache__/helpers.cpython-39.pyc
new file mode 100644
index 0000000..dc045d5
Binary files /dev/null and b/utils/__pycache__/helpers.cpython-39.pyc differ
diff --git a/utils/helpers.py b/utils/helpers.py
new file mode 100644
index 0000000..6cba2f8
--- /dev/null
+++ b/utils/helpers.py
@@ -0,0 +1,43 @@
+"""工具函数模块"""
+
+
+def get_f_block_positions(artifact_list):
+ """获取artifact_list中F块的位置"""
+ positions = []
+ for i, artifact in enumerate(artifact_list):
+ if artifact.get("BlockNumber") == "F":
+ positions.append(i)
+ return positions
+
+
+def cleanup_old_timestamps(artifact_timestamps, current_artifact_ids=None, max_age_hours=24):
+ """
+ 清理过期的时间戳记录
+
+ Args:
+ artifact_timestamps: 时间戳字典
+ current_artifact_ids: 当前活跃的artifact_id集合,可选
+ max_age_hours: 时间戳最大保留时间(小时),默认24小时
+ """
+ from datetime import datetime
+
+ current_time = datetime.now()
+ expired_ids = []
+
+ # 遍历所有存储的时间戳记录
+ for artifact_id, timestamp in artifact_timestamps.items():
+ # 如果提供了当前活跃ID列表,且该ID不在当前活跃列表中,则检查是否过期
+ if current_artifact_ids is None or artifact_id not in current_artifact_ids:
+ age = current_time - timestamp
+ # 如果超过最大保留时间,则标记为过期
+ if age.total_seconds() > max_age_hours * 3600:
+ expired_ids.append(artifact_id)
+
+ # 删除过期的时间戳记录
+ for artifact_id in expired_ids:
+ del artifact_timestamps[artifact_id]
+
+ if expired_ids:
+ print(f"清理了 {len(expired_ids)} 个过期的时间戳记录: {expired_ids}")
+
+ return len(expired_ids)
diff --git a/zjsh_ui_sysytem b/zjsh_ui_sysytem
index 30d00b8..fe751e8 160000
--- a/zjsh_ui_sysytem
+++ b/zjsh_ui_sysytem
@@ -1 +1 @@
-Subproject commit 30d00b8aef550efa6a06e69a64c24ab6b021e5c2
+Subproject commit fe751e8dd209b7a4bb8ac88b27a7291d347e20b9