From 9d1660270272180cd71147d6ddd53d1382643d2e Mon Sep 17 00:00:00 2001
From: wenxiangchao <wenxiangchao@ihengxin.com.cn>
Date: 星期一, 02 十一月 2026 18:00:14 +0800
Subject: [PATCH] merge: 并入远程 Initial commit 作为历史根节点
---
Plugin.DeviceDebug/Model/DeviceDebugModel.cs | 374 +++++++++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 374 insertions(+), 0 deletions(-)
diff --git a/Plugin.DeviceDebug/Model/DeviceDebugModel.cs b/Plugin.DeviceDebug/Model/DeviceDebugModel.cs
new file mode 100644
index 0000000..12757cc
--- /dev/null
+++ b/Plugin.DeviceDebug/Model/DeviceDebugModel.cs
@@ -0,0 +1,374 @@
+using System;
+using System.Collections.Generic;
+using System.Data;
+using System.IO;
+using System.Linq;
+using HMI.Core.Util;
+using log4net;
+using Plugin.DeviceDebug.Entity;
+
+namespace Plugin.DeviceDebug.Model
+{
+ /// <summary>
+ /// 鏁版嵁璁块棶灞� - 绠$悊璋冭瘯浼氳瘽鍜屾搷浣滃璁$殑鎸佷箙鍖�
+ /// </summary>
+ public class DeviceDebugModel
+ {
+ private static readonly ILog log = LogManager.GetLogger(typeof(DeviceDebugModel));
+ private SqliteHelper? _sqliteHelper;
+ private string _dbPath = string.Empty;
+
+ /// <summary>
+ /// 鍒濆鍖栨暟鎹簱锛屽垱寤哄繀瑕佺殑琛ㄧ粨鏋�
+ /// </summary>
+ public void InitDatabase(string dbPath)
+ {
+ try
+ {
+ _dbPath = dbPath;
+
+ // 纭繚鐩綍瀛樺湪
+ string? dir = Path.GetDirectoryName(dbPath);
+ if (!string.IsNullOrEmpty(dir) && !Directory.Exists(dir))
+ {
+ Directory.CreateDirectory(dir);
+ }
+
+ // 濡傛灉鏁版嵁搴撴枃浠朵笉瀛樺湪锛屽垱寤哄畠
+ if (!File.Exists(dbPath))
+ {
+ SqliteHelper.CreateDatabase(dbPath);
+ log.Info($"鍒涘缓璋冭瘯鏁版嵁搴�: {dbPath}");
+ }
+
+ _sqliteHelper = new SqliteHelper(dbPath);
+
+ // 鍒涘缓 debug_session 琛�
+ string createSessionTable = @"
+ CREATE TABLE IF NOT EXISTS debug_session (
+ session_id TEXT PRIMARY KEY,
+ device_id TEXT NOT NULL,
+ operator_id TEXT NOT NULL,
+ operator_name TEXT,
+ effective_version TEXT,
+ state INTEGER NOT NULL DEFAULT 0,
+ reservation_ref TEXT,
+ created_at TEXT NOT NULL,
+ closed_at TEXT
+ )";
+
+ // 鍒涘缓 debug_operation 琛�
+ string createOperationTable = @"
+ CREATE TABLE IF NOT EXISTS debug_operation (
+ operation_id TEXT PRIMARY KEY,
+ session_id TEXT NOT NULL,
+ command_type TEXT NOT NULL,
+ parameters TEXT,
+ outcome TEXT NOT NULL,
+ device_readback TEXT,
+ error_code TEXT,
+ error_message TEXT,
+ timestamp TEXT NOT NULL,
+ FOREIGN KEY (session_id) REFERENCES debug_session(session_id)
+ )";
+
+ _sqliteHelper.ExecuteSql(createSessionTable);
+ _sqliteHelper.ExecuteSql(createOperationTable);
+
+ log.Info("璋冭瘯鏁版嵁搴撹〃鍒濆鍖栧畬鎴�");
+ }
+ catch (Exception ex)
+ {
+ log.Error($"鍒濆鍖栬皟璇曟暟鎹簱澶辫触: {ex.Message}", ex);
+ throw;
+ }
+ }
+
+ #region 浼氳瘽 CRUD
+
+ /// <summary>
+ /// 鍒涘缓浼氳瘽
+ /// </summary>
+ public void CreateSession(DebugSession session)
+ {
+ try
+ {
+ if (_sqliteHelper == null)
+ throw new InvalidOperationException("鏁版嵁搴撴湭鍒濆鍖栵紝璇峰厛璋冪敤 InitDatabase");
+
+ string sql = $@"
+ INSERT INTO debug_session (
+ session_id, device_id, operator_id, operator_name,
+ effective_version, state, reservation_ref, created_at, closed_at
+ ) VALUES (
+ '{EscapeSql(session.SessionId)}',
+ '{EscapeSql(session.DeviceId)}',
+ '{EscapeSql(session.OperatorId)}',
+ '{EscapeSql(session.OperatorName)}',
+ '{EscapeSql(session.EffectiveVersion)}',
+ {(int)session.State},
+ '{EscapeSql(session.ReservationRef)}',
+ '{session.CreatedAt:yyyy-MM-dd HH:mm:ss}',
+ {(session.ClosedAt.HasValue ? $"'{session.ClosedAt.Value:yyyy-MM-dd HH:mm:ss}'" : "NULL")}
+ )";
+
+ _sqliteHelper.ExecuteSql(sql);
+ log.Debug($"鍒涘缓浼氳瘽: {session.SessionId}, 璁惧: {session.DeviceId}");
+ }
+ catch (Exception ex)
+ {
+ log.Error($"鍒涘缓浼氳瘽澶辫触: {ex.Message}", ex);
+ throw;
+ }
+ }
+
+ /// <summary>
+ /// 鑾峰彇浼氳瘽
+ /// </summary>
+ public DebugSession? GetSession(string sessionId)
+ {
+ try
+ {
+ if (_sqliteHelper == null)
+ throw new InvalidOperationException("鏁版嵁搴撴湭鍒濆鍖栵紝璇峰厛璋冪敤 InitDatabase");
+
+ string sql = $"SELECT * FROM debug_session WHERE session_id = '{EscapeSql(sessionId)}'";
+ DataTable dt = _sqliteHelper.GetDataTable(sql);
+
+ if (dt.Rows.Count == 0)
+ return null;
+
+ return MapToDebugSession(dt.Rows[0]);
+ }
+ catch (Exception ex)
+ {
+ log.Error($"鑾峰彇浼氳瘽澶辫触: {ex.Message}", ex);
+ return null;
+ }
+ }
+
+ /// <summary>
+ /// 鏇存柊浼氳瘽
+ /// </summary>
+ public void UpdateSession(DebugSession session)
+ {
+ try
+ {
+ if (_sqliteHelper == null)
+ throw new InvalidOperationException("鏁版嵁搴撴湭鍒濆鍖栵紝璇峰厛璋冪敤 InitDatabase");
+
+ string sql = $@"
+ UPDATE debug_session SET
+ device_id = '{EscapeSql(session.DeviceId)}',
+ operator_id = '{EscapeSql(session.OperatorId)}',
+ operator_name = '{EscapeSql(session.OperatorName)}',
+ effective_version = '{EscapeSql(session.EffectiveVersion)}',
+ state = {(int)session.State},
+ reservation_ref = '{EscapeSql(session.ReservationRef)}',
+ closed_at = {(session.ClosedAt.HasValue ? $"'{session.ClosedAt.Value:yyyy-MM-dd HH:mm:ss}'" : "NULL")}
+ WHERE session_id = '{EscapeSql(session.SessionId)}'";
+
+ _sqliteHelper.ExecuteSql(sql);
+ log.Debug($"鏇存柊浼氳瘽: {session.SessionId}, 鐘舵��: {session.State}");
+ }
+ catch (Exception ex)
+ {
+ log.Error($"鏇存柊浼氳瘽澶辫触: {ex.Message}", ex);
+ throw;
+ }
+ }
+
+ /// <summary>
+ /// 鑾峰彇璁惧鐨勬墍鏈夋椿璺冧細璇濓紙鏈叧闂殑锛�
+ /// </summary>
+ public List<DebugSession> GetActiveSessionsByDevice(string deviceId)
+ {
+ try
+ {
+ if (_sqliteHelper == null)
+ throw new InvalidOperationException("鏁版嵁搴撴湭鍒濆鍖栵紝璇峰厛璋冪敤 InitDatabase");
+
+ string sql = $@"
+ SELECT * FROM debug_session
+ WHERE device_id = '{EscapeSql(deviceId)}'
+ AND state != {(int)DebugSessionState.Closed}
+ ORDER BY created_at DESC";
+
+ DataTable dt = _sqliteHelper.GetDataTable(sql);
+ return dt.Rows.Cast<DataRow>().Select(MapToDebugSession).ToList();
+ }
+ catch (Exception ex)
+ {
+ log.Error($"鑾峰彇璁惧娲昏穬浼氳瘽澶辫触: {ex.Message}", ex);
+ return new List<DebugSession>();
+ }
+ }
+
+ /// <summary>
+ /// 鑾峰彇鎵�鏈変細璇�
+ /// </summary>
+ public List<DebugSession> GetAllSessions()
+ {
+ try
+ {
+ if (_sqliteHelper == null)
+ throw new InvalidOperationException("鏁版嵁搴撴湭鍒濆鍖栵紝璇峰厛璋冪敤 InitDatabase");
+
+ string sql = "SELECT * FROM debug_session ORDER BY created_at DESC";
+ DataTable dt = _sqliteHelper.GetDataTable(sql);
+ return dt.Rows.Cast<DataRow>().Select(MapToDebugSession).ToList();
+ }
+ catch (Exception ex)
+ {
+ log.Error($"鑾峰彇鎵�鏈変細璇濆け璐�: {ex.Message}", ex);
+ return new List<DebugSession>();
+ }
+ }
+
+ #endregion
+
+ #region 瀹¤ CRUD
+
+ /// <summary>
+ /// 璁板綍鎿嶄綔
+ /// </summary>
+ public void RecordOperation(DebugOperation operation)
+ {
+ try
+ {
+ if (_sqliteHelper == null)
+ throw new InvalidOperationException("鏁版嵁搴撴湭鍒濆鍖栵紝璇峰厛璋冪敤 InitDatabase");
+
+ string sql = $@"
+ INSERT INTO debug_operation (
+ operation_id, session_id, command_type, parameters,
+ outcome, device_readback, error_code, error_message, timestamp
+ ) VALUES (
+ '{EscapeSql(operation.OperationId)}',
+ '{EscapeSql(operation.SessionId)}',
+ '{EscapeSql(operation.CommandType)}',
+ '{EscapeSql(operation.Parameters)}',
+ '{EscapeSql(operation.Outcome)}',
+ '{EscapeSql(operation.DeviceReadback)}',
+ '{EscapeSql(operation.ErrorCode)}',
+ '{EscapeSql(operation.ErrorMessage)}',
+ '{operation.Timestamp:yyyy-MM-dd HH:mm:ss}'
+ )";
+
+ _sqliteHelper.ExecuteSql(sql);
+ log.Debug($"璁板綍鎿嶄綔: {operation.OperationId}, 绫诲瀷: {operation.CommandType}, 缁撴灉: {operation.Outcome}");
+ }
+ catch (Exception ex)
+ {
+ log.Error($"璁板綍鎿嶄綔澶辫触: {ex.Message}", ex);
+ throw;
+ }
+ }
+
+ /// <summary>
+ /// 鑾峰彇浼氳瘽鐨勬墍鏈夋搷浣�
+ /// </summary>
+ public List<DebugOperation> GetOperationsBySession(string sessionId)
+ {
+ try
+ {
+ if (_sqliteHelper == null)
+ throw new InvalidOperationException("鏁版嵁搴撴湭鍒濆鍖栵紝璇峰厛璋冪敤 InitDatabase");
+
+ string sql = $@"
+ SELECT * FROM debug_operation
+ WHERE session_id = '{EscapeSql(sessionId)}'
+ ORDER BY timestamp DESC";
+
+ DataTable dt = _sqliteHelper.GetDataTable(sql);
+ return dt.Rows.Cast<DataRow>().Select(MapToDebugOperation).ToList();
+ }
+ catch (Exception ex)
+ {
+ log.Error($"鑾峰彇浼氳瘽鎿嶄綔澶辫触: {ex.Message}", ex);
+ return new List<DebugOperation>();
+ }
+ }
+
+ /// <summary>
+ /// 鑾峰彇璁惧鏈�杩戠殑鎿嶄綔
+ /// </summary>
+ public List<DebugOperation> GetRecentOperations(string deviceId, int count)
+ {
+ try
+ {
+ if (_sqliteHelper == null)
+ throw new InvalidOperationException("鏁版嵁搴撴湭鍒濆鍖栵紝璇峰厛璋冪敤 InitDatabase");
+
+ string sql = $@"
+ SELECT o.* FROM debug_operation o
+ INNER JOIN debug_session s ON o.session_id = s.session_id
+ WHERE s.device_id = '{EscapeSql(deviceId)}'
+ ORDER BY o.timestamp DESC
+ LIMIT {count}";
+
+ DataTable dt = _sqliteHelper.GetDataTable(sql);
+ return dt.Rows.Cast<DataRow>().Select(MapToDebugOperation).ToList();
+ }
+ catch (Exception ex)
+ {
+ log.Error($"鑾峰彇鏈�杩戞搷浣滃け璐�: {ex.Message}", ex);
+ return new List<DebugOperation>();
+ }
+ }
+
+ #endregion
+
+ #region 杈呭姪鏂规硶
+
+ /// <summary>
+ /// 灏� DataRow 鏄犲皠涓� DebugSession
+ /// </summary>
+ private DebugSession MapToDebugSession(DataRow row)
+ {
+ return new DebugSession
+ {
+ SessionId = row["session_id"].ToString() ?? string.Empty,
+ DeviceId = row["device_id"].ToString() ?? string.Empty,
+ OperatorId = row["operator_id"].ToString() ?? string.Empty,
+ OperatorName = row["operator_name"]?.ToString() ?? string.Empty,
+ EffectiveVersion = row["effective_version"]?.ToString() ?? string.Empty,
+ State = (DebugSessionState)Convert.ToInt32(row["state"]),
+ ReservationRef = row["reservation_ref"]?.ToString() ?? string.Empty,
+ CreatedAt = DateTime.Parse(row["created_at"].ToString() ?? DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")),
+ ClosedAt = row["closed_at"] != DBNull.Value && !string.IsNullOrEmpty(row["closed_at"].ToString())
+ ? DateTime.Parse(row["closed_at"].ToString()!)
+ : null
+ };
+ }
+
+ /// <summary>
+ /// 灏� DataRow 鏄犲皠涓� DebugOperation
+ /// </summary>
+ private DebugOperation MapToDebugOperation(DataRow row)
+ {
+ return new DebugOperation
+ {
+ OperationId = row["operation_id"].ToString() ?? string.Empty,
+ SessionId = row["session_id"].ToString() ?? string.Empty,
+ CommandType = row["command_type"].ToString() ?? string.Empty,
+ Parameters = row["parameters"]?.ToString() ?? string.Empty,
+ Outcome = row["outcome"].ToString() ?? string.Empty,
+ DeviceReadback = row["device_readback"]?.ToString() ?? string.Empty,
+ ErrorCode = row["error_code"]?.ToString() ?? string.Empty,
+ ErrorMessage = row["error_message"]?.ToString() ?? string.Empty,
+ Timestamp = DateTime.Parse(row["timestamp"].ToString() ?? DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"))
+ };
+ }
+
+ /// <summary>
+ /// SQL 瀛楃涓茶浆涔夛紙闃叉娉ㄥ叆锛�
+ /// </summary>
+ private string EscapeSql(string value)
+ {
+ return value.Replace("'", "''");
+ }
+
+ #endregion
+ }
+}
--
Gitblit v1.9.1