将读写功能修改为read_genetic,write_genetic并且添加.exe文件
This commit is contained in:
@ -8,11 +8,11 @@ import logging
|
||||
|
||||
class APIServer:
|
||||
"""REST API服务器,提供PLC数据访问和配置管理功能"""
|
||||
|
||||
def __init__(self, cache_manager, config_path="config/config.json"):
|
||||
|
||||
def __init__(self, cache_manager, config_path="./config/config.json"):
|
||||
"""
|
||||
初始化API服务器
|
||||
|
||||
|
||||
Args:
|
||||
cache_manager: 缓存管理器实例
|
||||
config_path: 配置文件路径
|
||||
@ -25,10 +25,10 @@ class APIServer:
|
||||
self.username = "admin"
|
||||
self.password = "admin123" # 实际应用中应从安全存储获取
|
||||
self.start_time = time.strftime("%Y-%m-%d %H:%M:%S")
|
||||
|
||||
|
||||
# 在初始化方法中调用 setup_routes
|
||||
self.setup_routes()
|
||||
|
||||
|
||||
def check_auth(self, username, password):
|
||||
"""验证用户名和密码"""
|
||||
return username == self.username and password == self.password
|
||||
@ -36,8 +36,8 @@ class APIServer:
|
||||
def authenticate(self):
|
||||
"""发送401响应要求认证"""
|
||||
return Response(
|
||||
"Unauthorized",
|
||||
401,
|
||||
"Unauthorized",
|
||||
401,
|
||||
{"WWW-Authenticate": 'Basic realm="PLC Gateway Configuration"'}
|
||||
)
|
||||
|
||||
@ -47,7 +47,7 @@ class APIServer:
|
||||
def decorated(*args, **kwargs):
|
||||
if not self.auth_enabled:
|
||||
return f(*args, **kwargs)
|
||||
|
||||
|
||||
auth = request.authorization
|
||||
if not auth or not self.check_auth(auth.username, auth.password):
|
||||
return self.authenticate()
|
||||
@ -62,7 +62,7 @@ class APIServer:
|
||||
for area_name, area in areas.items():
|
||||
last_update = self.cache_manager.last_update[plc_name][area_name]
|
||||
plc_status = self.cache_manager.plc_connection_status.get(plc_name, "unknown")
|
||||
|
||||
|
||||
summary[plc_name][area_name] = {
|
||||
"status": area["status"],
|
||||
"plc_connection_status": plc_status,
|
||||
@ -74,7 +74,7 @@ class APIServer:
|
||||
|
||||
def setup_routes(self):
|
||||
"""设置所有API路由"""
|
||||
|
||||
|
||||
# ===========================
|
||||
# 主页面 - 状态摘要
|
||||
# ===========================
|
||||
@ -108,7 +108,7 @@ class APIServer:
|
||||
<h1>PLC Gateway Status</h1>
|
||||
<p>Gateway running since: {{ start_time }}</p>
|
||||
"""
|
||||
|
||||
|
||||
for plc_name, areas in summary.items():
|
||||
plc_status = self.cache_manager.plc_connection_status.get(plc_name, "unknown")
|
||||
plc_class = ""
|
||||
@ -118,7 +118,7 @@ class APIServer:
|
||||
plc_class = "plc-disconnected"
|
||||
else:
|
||||
plc_class = "plc-never-connected"
|
||||
|
||||
|
||||
html += f'<h2 class="{plc_class}">PLC: {plc_name} (Status: {plc_status})</h2>'
|
||||
html += """
|
||||
<table>
|
||||
@ -131,11 +131,11 @@ class APIServer:
|
||||
<th>Last Update</th>
|
||||
</tr>
|
||||
"""
|
||||
|
||||
|
||||
for area_name, area in areas.items():
|
||||
status_class = ""
|
||||
status_text = area["status"]
|
||||
|
||||
|
||||
if area["status"] == "connected":
|
||||
status_class = "status-connected"
|
||||
elif area["status"] == "never_connected":
|
||||
@ -146,7 +146,7 @@ class APIServer:
|
||||
status_text = "Disconnected"
|
||||
else:
|
||||
status_class = "status-disconnected"
|
||||
|
||||
|
||||
html += f"""
|
||||
<tr>
|
||||
<td>{area_name}</td>
|
||||
@ -157,9 +157,9 @@ class APIServer:
|
||||
<td>{area['last_update']}</td>
|
||||
</tr>
|
||||
"""
|
||||
|
||||
|
||||
html += "</table>"
|
||||
|
||||
|
||||
# 添加API文档部分
|
||||
html += """
|
||||
<div class="api-section">
|
||||
@ -219,7 +219,7 @@ class APIServer:
|
||||
<p>PLC Gateway v1.0 | <a href="/api/status">System Status</a></p>
|
||||
</div>
|
||||
"""
|
||||
|
||||
|
||||
html += """
|
||||
</body>
|
||||
</html>
|
||||
@ -236,10 +236,10 @@ class APIServer:
|
||||
for plc_name in self.cache_manager.plc_connection_status:
|
||||
plc_statuses[plc_name] = {
|
||||
"status": self.cache_manager.plc_connection_status[plc_name],
|
||||
"last_connected": time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(self.cache_manager.plc_last_connected[plc_name]))
|
||||
"last_connected": time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(self.cache_manager.plc_last_connected[plc_name]))
|
||||
if self.cache_manager.plc_last_connected[plc_name] > 0 else "Never"
|
||||
}
|
||||
|
||||
|
||||
return jsonify({
|
||||
"status": "running",
|
||||
"start_time": self.start_time,
|
||||
@ -257,7 +257,7 @@ class APIServer:
|
||||
"""配置编辑页面"""
|
||||
config = self.config_manager.get_config()
|
||||
config_json = json.dumps(config, indent=2)
|
||||
|
||||
|
||||
html = """
|
||||
<html>
|
||||
<head>
|
||||
@ -469,7 +469,7 @@ class APIServer:
|
||||
</html>
|
||||
"""
|
||||
return render_template_string(
|
||||
html,
|
||||
html,
|
||||
config_json=config_json,
|
||||
username=self.username,
|
||||
password=self.password
|
||||
@ -505,7 +505,7 @@ class APIServer:
|
||||
try:
|
||||
config = request.json
|
||||
reload = request.args.get('reload', 'false').lower() == 'true'
|
||||
|
||||
|
||||
success, message = self.config_manager.save_config(config)
|
||||
if success:
|
||||
if reload:
|
||||
@ -1277,13 +1277,13 @@ class APIServer:
|
||||
if not data:
|
||||
# 如果没有提供数据,返回错误
|
||||
return jsonify({
|
||||
"status": "error",
|
||||
"status": "error",
|
||||
"message": "No data provided",
|
||||
"plc_connection_status": self.cache_manager.plc_connection_status.get(plc_name, "unknown"),
|
||||
"last_update": 0,
|
||||
"last_update_formatted": "N/A"
|
||||
}), 400
|
||||
|
||||
|
||||
success, error, plc_status, update_time = self.cache_manager.write_area(plc_name, area_name, offset, data)
|
||||
if error:
|
||||
return jsonify({
|
||||
@ -1397,7 +1397,7 @@ class APIServer:
|
||||
"last_update": 0,
|
||||
"last_update_formatted": "N/A"
|
||||
}), 400
|
||||
|
||||
|
||||
requests = request.json
|
||||
if not isinstance(requests, list):
|
||||
return jsonify({
|
||||
@ -1407,9 +1407,9 @@ class APIServer:
|
||||
"last_update": 0,
|
||||
"last_update_formatted": "N/A"
|
||||
}), 400
|
||||
|
||||
|
||||
self.logger.info(f"Received batch write request: {json.dumps(requests)}")
|
||||
|
||||
|
||||
results = self.cache_manager.batch_write(requests)
|
||||
return jsonify(results)
|
||||
except Exception as e:
|
||||
@ -1422,6 +1422,119 @@ class APIServer:
|
||||
"last_update_formatted": "N/A"
|
||||
}), 500
|
||||
|
||||
# 通用读取接口
|
||||
@self.app.route("/api/read_generic/<plc_name>/<area_name>/<int:offset>/<data_type>", methods=["GET"],
|
||||
endpoint="read_generic")
|
||||
def read_generic(plc_name, area_name, offset, data_type):
|
||||
"""通用读取接口"""
|
||||
print("Enter Read generic")
|
||||
# 检查请求参数
|
||||
count = request.args.get('count', 1, type=int)
|
||||
if count < 1:
|
||||
return jsonify({
|
||||
"status": "error",
|
||||
"message": "Count must be at least 1",
|
||||
"plc_name": plc_name,
|
||||
"area_name": area_name
|
||||
}), 400
|
||||
|
||||
# 执行读取
|
||||
result, error, plc_status, update_time = self.cache_manager.read_generic(
|
||||
plc_name,
|
||||
area_name,
|
||||
offset,
|
||||
data_type,
|
||||
count
|
||||
)
|
||||
|
||||
if error:
|
||||
return jsonify({
|
||||
"status": "error",
|
||||
"plc_name": plc_name,
|
||||
"area_name": area_name,
|
||||
"message": error,
|
||||
"plc_connection_status": plc_status,
|
||||
"last_update": update_time,
|
||||
"last_update_formatted": time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(
|
||||
update_time)) if update_time > 0 else "Never"
|
||||
}), 400
|
||||
|
||||
return jsonify({
|
||||
"status": "success",
|
||||
"plc_name": plc_name,
|
||||
"area_name": area_name,
|
||||
"offset": offset,
|
||||
"data_type": data_type,
|
||||
"count": count,
|
||||
"data": result,
|
||||
"plc_connection_status": plc_status,
|
||||
"last_update": update_time,
|
||||
"last_update_formatted": time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(update_time))
|
||||
})
|
||||
|
||||
# 通用写入接口
|
||||
@self.app.route("/api/write_generic/<plc_name>/<area_name>/<int:offset>/<data_type>", methods=["POST"],
|
||||
endpoint="write_generic")
|
||||
def write_generic(plc_name, area_name, offset, data_type):
|
||||
"""通用写入接口"""
|
||||
# 检查请求数据
|
||||
if not request.is_json:
|
||||
return jsonify({
|
||||
"status": "error",
|
||||
"message": "Request must be JSON (Content-Type: application/json)",
|
||||
"plc_name": plc_name,
|
||||
"area_name": area_name
|
||||
}), 400
|
||||
json_data = request.get_json()
|
||||
if "value" not in json_data and "values" not in json_data:
|
||||
return jsonify({
|
||||
"status": "error",
|
||||
"message": "Missing 'value' or 'values' field",
|
||||
"plc_name": plc_name,
|
||||
"area_name": area_name
|
||||
}), 400
|
||||
|
||||
# 确定要写入的值
|
||||
value = json_data.get("value", json_data.get("values"))
|
||||
|
||||
# 执行写入
|
||||
success, error, plc_status, update_time = self.cache_manager.write_generic(
|
||||
plc_name,
|
||||
area_name,
|
||||
offset,
|
||||
data_type,
|
||||
value
|
||||
)
|
||||
|
||||
if error:
|
||||
return jsonify({
|
||||
"status": "error",
|
||||
"plc_name": plc_name,
|
||||
"area_name": area_name,
|
||||
"message": error,
|
||||
"plc_connection_status": plc_status,
|
||||
"last_update": update_time,
|
||||
"last_update_formatted": time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(
|
||||
update_time)) if update_time > 0 else "Never"
|
||||
}), 400
|
||||
|
||||
# 确定写入数量
|
||||
count = 1
|
||||
if isinstance(value, list):
|
||||
count = len(value)
|
||||
|
||||
return jsonify({
|
||||
"status": "success",
|
||||
"plc_name": plc_name,
|
||||
"area_name": area_name,
|
||||
"offset": offset,
|
||||
"data_type": data_type,
|
||||
"count": count,
|
||||
"plc_connection_status": plc_status,
|
||||
"last_update": update_time,
|
||||
"last_update_formatted": time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(update_time))
|
||||
})
|
||||
|
||||
@self.app.route("/api/batch_write_bool", methods=["POST"], endpoint="batch_write_bool")
|
||||
def batch_write_bool():
|
||||
"""批量写入多个区域的数据"""
|
||||
@ -1475,10 +1588,10 @@ class APIServer:
|
||||
def start(self):
|
||||
"""启动API服务器"""
|
||||
self.server_thread = threading.Thread(
|
||||
target=self.app.run,
|
||||
target=self.app.run,
|
||||
kwargs={
|
||||
"host": "0.0.0.0",
|
||||
"port": 5000,
|
||||
"host": "0.0.0.0",
|
||||
"port": 5000,
|
||||
"threaded": True,
|
||||
"use_reloader": False # 避免在生产环境中使用重载器
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user