battery/andon_flask_client.py

197 lines
6.2 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import time
from concurrent.futures import ThreadPoolExecutor
import requests
from enum import Enum
from typing import Optional, Dict, Any
class DeviceStatus(Enum):
"""设备状态枚举"""
NORMAL = 0
ABNORMAL = 1
class ErrorCode(Enum):
"""错误代码枚举"""
EMERGENCY_STOP = 1
EQUIPMENT_ERROR = 2
class AndonEndpoint(Enum):
"""API端点枚举"""
HEARTBEAT = "/heartbeat"
JOB_START = "/job_start"
JOB_END = "/job_end"
JOB_ERROR = "/job_error"
CALL = "/call"
class SimpleAndonSender:
"""简化版 Andon 发送器"""
def __init__(self, server_ip: str = "192.168.2.1", port: int = 5100, timeout: int = 5):
self.base_url = f"http://{server_ip}:{port}"
self.timeout = timeout
# 状态记录
self.last_start: Optional[int] = None
self.last_end: Optional[int] = None
self.error_status = True
self.stop_status = True
self.call_status = True
# 消息队列
self.thread_pool = ThreadPoolExecutor(max_workers=5, thread_name_prefix="AndonSender")
# 会话对象,支持连接池
self.session = requests.Session()
def send_mes_thread(self, m_values, device_id=1):
self.thread_pool.submit(self.send_all_status, device_id, m_values)
def send_all_status(self, device_id: int, m_values: list) -> None:
"""发送所有状态"""
print("发送心跳")
self._post(AndonEndpoint.HEARTBEAT, {"id": device_id, "status": 1})
# 解析状态值
status = self._parse_status_values(m_values)
print(status)
# 处理作业状态
self._handle_job_status(device_id, status)
# 处理信号状态(按优先级)
self._handle_signal_status(device_id, status)
def _parse_status_values(self, m_values: list) -> Dict[str, int]:
"""解析状态值"""
return {
'start': int(m_values[1]), # 开始工作状态位
'end': int(m_values[12]), # 结束工作状态位
'stop': int(m_values[11]), # 急停状态位
'call': int(m_values[10]), # 呼叫状态位
'error': int(m_values[2]) # 异常状态位
}
def _handle_job_status(self, device_id: int, status: Dict[str, int]) -> None:
"""处理作业状态"""
# 开始工作检测
if status['start'] == 1 and self.last_start != 1:
print("发送作业开始")
self._post(AndonEndpoint.JOB_START, {"id": device_id, "elapsed_time": 0})
self.last_start = 1
# 结束工作检测
if status['end'] == 1:
print("发送作业结束")
self._post(AndonEndpoint.JOB_END, {"id": device_id})
self.last_start = 0
self.last_end = 0
def _handle_signal_status(self, device_id: int, status: Dict[str, int]) -> None:
"""处理信号状态(按优先级:呼叫 > 异常 > 急停)"""
call_handled = self._handle_call_status(device_id, status['call'])
if not call_handled:
error_handled = self._handle_error_status(device_id, status['error'])
if not error_handled:
self._handle_stop_status(device_id, status['stop'])
def _handle_call_status(self, device_id: int, call_value: int) -> bool:
"""处理呼叫状态"""
if call_value == 1:
print("发送呼叫")
self._post(AndonEndpoint.CALL, {"id": device_id, "call_status": 1})
self.call_status = True
return True
elif call_value == 0 and self.call_status:
print("发送呼叫复位")
self._post(AndonEndpoint.CALL, {"id": device_id, "call_status": 0})
self.call_status = False
return False
def _handle_error_status(self, device_id: int, error_value: int) -> bool:
"""处理异常状态"""
if error_value == 1:
print("发送异常")
self._post(AndonEndpoint.JOB_ERROR, {
"id": device_id,
"error_type": 1,
"error_code": ErrorCode.EQUIPMENT_ERROR.value
})
self.error_status = True
return True
elif error_value == 0 and self.error_status:
print("发送异常复位")
self._post(AndonEndpoint.JOB_ERROR, {
"id": device_id,
"error_type": 0,
"error_code": ErrorCode.EQUIPMENT_ERROR.value
})
self.error_status = False
return False
def _handle_stop_status(self, device_id: int, stop_value: int) -> bool:
"""处理急停状态"""
if stop_value == 1:
print("紧急停止")
self._post(AndonEndpoint.JOB_ERROR, {
"id": device_id,
"error_type": 1,
"error_code": ErrorCode.EMERGENCY_STOP.value
})
self.stop_status = True
return True
elif stop_value == 0 and self.stop_status:
print("紧急停止复位")
self._post(AndonEndpoint.JOB_ERROR, {
"id": device_id,
"error_type": 0,
"error_code": ErrorCode.EMERGENCY_STOP.value
})
self.stop_status = False
return False
def _post(self, endpoint: AndonEndpoint, data: Dict[str, Any]) -> Optional[Dict[str, Any]]:
"""发送POST请求"""
url = f"{self.base_url}{endpoint.value}"
try:
response = self.session.post(url, json=data, timeout=self.timeout)
response.raise_for_status() # 如果状态码不是200,抛出异常
return response.json()
except Exception as e:
print(f"发送失败到 {url}: {e}")
return None
if __name__ == '__main__':
"""主函数 - 监听键盘输入并调用自定义方法"""
andon_sender = SimpleAndonSender(server_ip='127.0.0.1', port=5100)
# device_id = 1 # 默认设备ID
"""
0000000000000
# stop
0000000000010
# error
0010000000000
#
0000000000001
0100000000000
"""
# while True:
# cmd = input("> ").strip()
# print(cmd)
# andon_sender.send_mes_thread(cmd)
# time.sleep(1)