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