运行流程
仪表盘启动流程
这个流程中的各种 管理器
, 服务
, 源代码均在 KitX Dashboard/Services/
下
- 初始化事件总线 (
EventHandlers
) - 处理启动参数 (即命令行参数)
- 单进程检查 (防止多个实例同时运行)
- 启动时检查
- 读取配置文件, 初始化配置信息 (存在则读取, 不存在则初始化默认配置)
- 初始化日志系统, 开始记录日志
- 初始化全局异常捕获
- 初始化相关环境 (存在则读取, 不存在则重新创建)
- Common.Algorithm
- 初始化数据库 (存在则读取, 不存在则重新创建)
- 初始化任务管理器 (
TasksManager
) - 初始化网络管理器 (
WebManager
) - 初始化数据记录管理器 (
StatisticsManager
) - 初始化有关事件 (
EventHandlers
) - 初始化文件监控管理器 (
FileWatcherManager
)
- 进入应用生命周期, 启动图形化界面
网络初始化过程
- 在
仪表盘启动流程
的 4.7 步中, 实际执行的代码是:这个任务将在#region 初始化 WebManager Program.TasksManager.SignalRun(nameof(SignalsNames.MainWindowInitSignal), () => { new Thread(() => { Thread.Sleep(Program.Config.Web.DelayStartSeconds * 1000); Program.WebManager = new WebManager().Start(); }).Start(); }); #endregion
MainWindow.xaml.cs
中InitWindow()
函数执行完毕时Raise
并且休眠Program.Config.Web.DelayStartSeconds
秒数后再开始启动网络相关服务 WebManager.Start()
方法将分别初始化DevicesManager
,DevicesServer
,PluginsManager
和PluginsServer
DevicesServer
在调用Start()
方法后开始向局域网多播本机的设备信息 udp 包, 表现形式为DeviceInfoStruct
的 json 序列化字符串 (该结构定义于KitX.Web.Rules
中)
同时也会监听来自局域网组播的 udp 包, 并将其解析为DeviceInfoStruct
结构, 并通过DevicesManager.Update(DeviceInfoStruct)
方法将其添加到界面中PluginsServer
在调用Start()
方法后开始监听网络连接请求并同请求的插件建立 tcp 连接, 接收到以"PluginStruct: "
打头的报文之后将剩余部分作为 json 字符串反序列化为PluginStruct
结构, 并通过PluginsManager.Execute(string, IPEndPoint)
方法将其添加到界面中
自组网流程
基于局域网中不断发送的 udp 设备报文, KitX Dashboard 可以很轻松地判断出局域网中运行着 KitX Dashboard 的设备
在 udp 设备报文中增加 tcp 服务器相关字段, 即可依据 udp 设备报文自动建立连接, 组成网络
具体流程: (以某个设备的视角观察)
当然, 观察的过程不会在连接主控或是建立主控后结束
这个观察的过程会持续进行, 以免发生网络内多台设备同时建立主控的情况
如果观察到有其它的主控的 udp 设备报文中的 DeviceServerBuildTime
字段早于自己的主控服务建立时间, 则主动关闭服务器, 并重新开始观察流程
插件启动流程
- 启动仪表盘
- 用户选择启动插件A
- 仪表盘根据插件A的 PluginStruct.json 中的 RootStartupFileName 字段以及 LoaderStruct.json 中的 LoaderName 字段拼凑启动命令
根据 Config.json 中 Loaders.InstallPath 得到加载器安装路径, LoaderName 拼凑可执行文件名称来启动 Loader
传入参数格式为:--load {file} --connect {address}:{port}
其中,{file}
为插件根启动文件的绝对路径{address}
为当前仪表盘与插件连接的地址 (目前为内网 IPv4 地址){port}
为当前仪表盘通讯服务器的服务端口
- Loader 启动后与仪表盘建立 Socket 连接, 通过 --connect 参数后指定的地址与端口
启动后 Loader 向仪表盘发送一个文本, 格式为:PluginStruct: {ps}
, 其中{ps}
为 json 序列化的 PluginStruct 对象