alielie
7 天以前 e57938fbda9bff702004038f76d009422968bff5
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
using DeviceService.Core;
using DeviceService.Service;
using System.Text.Encodings.Web;
using System.Text.Json;
using System.Text.Unicode;
 
namespace DeviceService.Device
{
    /// <summary>
    /// 服务正式启动后的设备管理:设备实例的内存集合、类型扫描与注册(Register)。
    /// 设备信息的数据库读写由 <see cref="DeviceHelper"/> 负责,本类不做任何持久化。
    /// </summary>
    public class DeviceManager
    {
 
        private readonly static object _sync = new object();
        private readonly static Dictionary<string, IDevice> _deviceCollection = new Dictionary<string, IDevice>();
 
        public static IReadOnlyList<IDevice> Devices
        {
            get
            {
                lock (_sync)
                {
                    return _deviceCollection.Values.ToList();
                }
            }
        }
 
        // ==================== 设备注册 ====================
 
        /// <summary>服务启动时注册设备(内部会调用 Init),无论初始化是否成功都会加入集合。</summary>
        public static bool Register(IDevice device, out string msg)
        {
            if (device == null) throw new ArgumentNullException(nameof(device));
 
            bool initOk = device.Init(out msg);
            if (initOk)
            {
                lock (_sync)
                {
                    _deviceCollection[device.DeviceId] = device;
                }
            }
            return initOk;
        }
 
        public static void UnRegisterAll()
        {
            lock (_sync)
            {
                _deviceCollection.Clear();
            }
        }
 
        /// <summary>
        /// 用数据库读取到的设备刷新内存集合(不调用 Init)。
        /// 已存在于内存中的实例保持不变,避免丢失已注册/已打开的运行状态;
        /// 新增记录使用传入的(从数据库还原的)实例。
        /// </summary>
        public static void Refresh(IEnumerable<IDevice> devices)
        {
            if (devices == null) throw new ArgumentNullException(nameof(devices));
 
            lock (_sync)
            {
                var refreshed = new Dictionary<string, IDevice>(StringComparer.Ordinal);
                foreach (IDevice device in devices)
                {
                    if (device == null || string.IsNullOrWhiteSpace(device.DeviceId))
                    {
                        continue;
                    }
 
                    refreshed[device.DeviceId] = _deviceCollection.TryGetValue(device.DeviceId, out IDevice? existing)
                        ? existing
                        : device;
                }
 
                _deviceCollection.Clear();
                foreach (KeyValuePair<string, IDevice> pair in refreshed)
                {
                    _deviceCollection[pair.Key] = pair.Value;
                }
            }
        }
 
        /// <summary>按 DeviceId 从内存集合移除设备(数据库记录的删除由 <see cref="DeviceHelper.RemoveDevice"/> 负责)。</summary>
        public static bool Remove(string id)
        {
            lock (_sync)
            {
                return _deviceCollection.Remove(id);
            }
        }
 
        private static readonly JsonSerializerOptions SafeOptions = new()
        {
            Encoder = JavaScriptEncoder.Create(UnicodeRanges.All)
        };
 
        public static void HandleClientMessage(RequestArg arg)
        {
            var data = arg.Data;
            string deviceId = data.DeviceId;
            if (_deviceCollection.TryGetValue(deviceId, out IDevice device))
            {
                var res = device.HandleRequest(data);
                arg.Client.Send(JsonSerializer.Serialize(res, SafeOptions), out _);
            }
            else
            {
                var res = new ResponseData
                {
                    Success = false,
                    Message = "无效的DeviceId"
                };
                arg.Client.Send(JsonSerializer.Serialize(res, SafeOptions), out _);
            }
        }
 
        public static void ReleaseClient(IClient client) { 
            
        }
    }
}