VOCsReminder 1.0.4

dotnet add package VOCsReminder --version 1.0.4
                    
NuGet\Install-Package VOCsReminder -Version 1.0.4
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="VOCsReminder" Version="1.0.4" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="VOCsReminder" Version="1.0.4" />
                    
Directory.Packages.props
<PackageReference Include="VOCsReminder" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add VOCsReminder --version 1.0.4
                    
#r "nuget: VOCsReminder, 1.0.4"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package VOCsReminder@1.0.4
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=VOCsReminder&version=1.0.4
                    
Install as a Cake Addin
#tool nuget:?package=VOCsReminder&version=1.0.4
                    
Install as a Cake Tool

VOCsReminder

VOCsReminder 是面向 VOCs 色谱设备应用的本地提醒库,用于统一处理磁盘容量不足提醒和设备模块维护到期提醒。库负责配置保存、到期计算、磁盘检测、提醒去重、状态持久化和处理闭环;应用层负责触发检测、展示提醒,并在用户完成处理后通知库。

  • 当前版本:1.0.0
  • 目标框架:.NET Framework 4.8、.NET Standard 2.0、.NET 8.0、.NET 10.0
  • 数据存储:SQLite
  • 调度方式:由应用层调用,库不包含定时器

解决目标

  • 定期检查指定目录所在磁盘的可用容量;
  • 可用容量小于或等于阈值时产生提醒;
  • 按小时、天或月维护设备模块的到期时间;
  • 维护时间到期后产生提醒;
  • 同一模块存在未处理提醒时,不重复创建或推送新提醒;
  • 使用 SQLite 保存配置、维护时间和提醒历史;
  • 应用重启后恢复显示尚未处理的提醒;
  • 应用处理维护提醒后,从处理时间开始计算下一次到期时间;
  • 通过接口把提醒展示交给应用层,不依赖具体 UI 框架。

工作原理

磁盘容量检测

应用调用 StorageCapacityDetectProcess.Execute() 后,库按以下顺序执行:

  1. 查询 EquipmentModuleToken.STORAGE_CAPACITY 对应的模块配置;
  2. 配置不存在或未启用时结束;
  3. 已存在该模块的未处理提醒时结束;
  4. 读取磁盘容量配置;
  5. 获取配置目录所在磁盘分区的可用空间;
  6. 可用空间大于阈值时结束;
  7. 可用空间小于或等于阈值时,先写入未处理提醒,再调用 IMessageReminder 通知应用层。

每调用一次流程,就执行一次容量检测。检测周期由应用层决定。

设备模块维护检测

应用调用 DeviceModuleMaintainRemindProcess.Execute() 后,库遍历除磁盘容量以外的模块配置:

  1. 跳过未启用的模块;
  2. 跳过已经存在未处理提醒的模块;
  3. 读取模块维护数据;
  4. 到期时间未到时跳过;
  5. 到期后先写入未处理提醒,再调用 IMessageReminder 通知应用层。

统一检测入口

ReminderProcess.Execute() 是推荐入口,一次调用依次执行:

  1. 磁盘容量检测;
  2. 设备模块维护检测。

应用层也可以按需单独调用任一检测流程。

提醒处理闭环

应用展示提醒后,在用户确认处理完成时调用 IMessageHandler.Handling(...):

  • 磁盘容量提醒:标记为已处理并记录处理时间;
  • 设备维护提醒:标记为已处理、记录处理时间,并从处理时间开始计算下一次到期时间。

已处理提醒不会删除,可以继续作为历史记录查询。

库分层

层次 主要类型 职责
应用接入层 VOCsRemindManager、IMessageReminder 提供统一入口,接收应用层提醒实现,暴露读取、设置和处理能力
流程层 ReminderProcess、StorageCapacityDetectProcess、DeviceModuleMaintainRemindProcess 执行检测、判断触发条件、创建并推送提醒
提醒服务层 RemindGetter、RemindSetter、RemindHandler 实现配置查询、配置保存、提醒处理和周期续期
领域模型层 ReminderNotice、DeviceModuleMaintainInfo、DeviceModuleMaintainData、StorageCapacityInfo 表达提醒、模块配置、维护状态和容量配置
持久化层 ReminderSQLite、SQLiteBase 创建 SQLite 数据库及数据表,完成数据查询和写入;不向应用层公开

应用层通常只需要使用:

  • VOCsRemindManager.GetInstance()
  • VOCsRemindManager.Getter
  • VOCsRemindManager.Setter
  • VOCsRemindManager.Handler
  • ReminderProcess.GetInstance().Execute()
  • IMessageReminder

快速开始

1. 实现应用层提醒接口

IMessageReminder 由应用层实现。库产生提醒后,会把 ReminderNotice 传给该接口。

using System;
using System.Threading.Tasks;
using VOCsReminder;

public sealed class AppMessageReminder : IMessageReminder
{
    public Task Reminder(ReminderNotice notice)
    {
        if (notice == null)
        {
            return Task.CompletedTask;
        }

        // 替换为应用自己的消息框或消息中心。
        Console.WriteLine($"[{notice.ReminderType}] {notice.Message}");
        return Task.CompletedTask;
    }
}

如果检测流程从后台线程调用,WinForms 或 WPF 应用应在接口实现中自行切换到 UI 线程。

2. 获取管理器并注册提醒实现

VOCsRemindManager manager = VOCsRemindManager
    .GetInstance()
    .SetReminder(new AppMessageReminder());

SetPusher(IDataPusher) 是预留能力。当前版本的 IDataPusher 为空接口,提醒流程尚未使用,普通应用无需设置。

3. 恢复未处理提醒

应用启动时,在注册 IMessageReminder 后调用一次:

await manager.GetCurrentRemind();

该方法查询数据库中的所有未处理提醒,并重新调用 IMessageReminder。它只恢复已有提醒,不执行新的容量检测或维护到期检测。

推荐初始化顺序:

获取 VOCsRemindManager
        ↓
注册 IMessageReminder
        ↓
调用 GetCurrentRemind
        ↓
启动应用层定时检测

配置磁盘容量提醒

磁盘容量提醒需要同时配置容量信息和模块启用状态。

设置检测目录和容量阈值

bool capacitySaved = await manager.Setter.SetStorageCapacity(
    @"D:\VOCsData",
    20d);
  • folder:要监控的目录;实际检测的是该目录所在磁盘分区;
  • minCapacity:最小可用容量,单位为 GB,必须大于 0,且不能为 NaN 或无穷大。

检测时目录必须存在,对应磁盘必须处于可用状态,否则本次检测会跳过。

启用磁盘容量模块

bool reminderSaved = await manager.Setter.SetModuleMaintainInfo(
    new DeviceModuleMaintainInfo
    {
        ModuleToken = EquipmentModuleToken.STORAGE_CAPACITY,
        IsEnabled = true,
        ReminderValue = 1,
        ReminderTimeType = ReminderTimeType.DAY,
        Message = "数据盘可用空间不足,请及时清理。"
    });

磁盘容量检测不使用 ReminderValue 和 ReminderTimeType 控制检测周期,检测周期完全由应用层调用频率决定。但由于启用配置复用 DeviceModuleMaintainInfo,启用时 ReminderValue 仍须大于 0。

容量判断规则:

可用容量 > MinCapacity   不提醒
可用容量 <= MinCapacity  产生提醒

配置设备模块维护提醒

bool saved = await manager.Setter.SetModuleMaintainInfo(
    new DeviceModuleMaintainInfo
    {
        ModuleToken = EquipmentModuleToken.HYDROGEN_GENERATOR,
        IsEnabled = true,
        ReminderValue = 30,
        ReminderTimeType = ReminderTimeType.DAY,
        Message = "氢气发生器已到维护周期。"
    });

首次新增并启用配置时,库以当前本地时间为起点计算到期时间。以下情况会重新从当前时间计算到期时间:

  • 模块由停用变为启用;
  • ReminderValue 发生变化;
  • ReminderTimeType 发生变化;
  • 模块维护数据不存在。

仅修改 Message 不会重置到期时间。停用模块不会删除配置、维护数据或提醒历史,只会停止该模块的到期检测。

批量设置

bool saved = await manager.Setter.SetModuleMaintainInfo(
    new System.Collections.Generic.List<DeviceModuleMaintainInfo>
    {
        new DeviceModuleMaintainInfo
        {
            ModuleToken = EquipmentModuleToken.PROBE_FILTER,
            IsEnabled = true,
            ReminderValue = 1,
            ReminderTimeType = ReminderTimeType.MONTH,
            Message = "请更换探头过滤器。"
        },
        new DeviceModuleMaintainInfo
        {
            ModuleToken = EquipmentModuleToken.AIR_COMPRESSOR,
            IsEnabled = true,
            ReminderValue = 500,
            ReminderTimeType = ReminderTimeType.HOUR,
            Message = "请维护空气压缩机。"
        }
    });

批量设置按列表顺序逐条执行,遇到失败立即返回 false。此前已经成功保存的数据不会回滚。

执行检测

库不包含定时器,应用层应根据业务要求周期性调用:

await ReminderProcess.GetInstance().Execute();

例如应用层每小时调用一次,提醒时间精度也约为一小时。也可以单独执行某个流程:

await StorageCapacityDetectProcess.GetInstance().Execute();

await DeviceModuleMaintainRemindProcess.GetInstance().Execute();

应用层应等待本次 Execute() 完成后再开始下一次调用,避免检测流程重叠执行。

处理提醒

用户完成处理后,应用层使用模块标识通知库:

bool handled = await manager.Handler.Handling(
    EquipmentModuleToken.HYDROGEN_GENERATOR,
    ProcessStatus.PROCESSED);

调用要求:

  • token 不能为空;
  • status 必须为 ProcessStatus.PROCESSED;
  • 对应模块必须存在未处理提醒;
  • 对应模块配置必须存在并保持启用状态。

设备维护提醒处理成功后,下一次到期时间以本次处理时间为起点重新计算。磁盘容量提醒处理成功后,如果磁盘空间仍小于或等于阈值,下一次检测会再次产生提醒。

查询配置、状态和历史

StorageCapacityInfo capacity =
    await manager.Getter.GetStorageCapacity();

System.Collections.Generic.List<DeviceModuleMaintainInfo> infos =
    await manager.Getter.GetModuleMaintainInfo();

System.Collections.Generic.List<DeviceModuleMaintainData> allData =
    await manager.Getter.GetModuleMaintainData();

DeviceModuleMaintainData oneData =
    await manager.Getter.GetModuleMaintainDataByToken(
        EquipmentModuleToken.HYDROGEN_GENERATOR);

System.Collections.Generic.List<ReminderNotice> allNotices =
    await manager.Getter.GetRemindStatus();

System.Collections.Generic.List<ReminderNotice> unprocessed =
    await manager.Getter.GetRemindStatus(
        status: ProcessStatus.UNPROCESSED);

System.Collections.Generic.List<ReminderNotice> history =
    await manager.Getter.GetRemindStatus(
        start: new DateTime(2026, 1, 1),
        end: new DateTime(2027, 1, 1),
        type: ReminderType.MODULE_MAINTAIN_EXPIRE,
        token: EquipmentModuleToken.HYDROGEN_GENERATOR,
        status: ProcessStatus.PROCESSED);

条件查询的时间范围为左闭右开区间:

Time >= start && Time < end

条件查询结果按提醒时间倒序排列。如果同时传入 start 和 end,且 start >= end,方法返回 null。

公开数据模型

类型 关键属性 用途
DeviceModuleMaintainInfo ModuleToken、IsEnabled、ReminderValue、ReminderTimeType、Message 模块维护配置
DeviceModuleMaintainData ModuleToken、ExpireTime、UpdateTime 库维护的模块运行状态
StorageCapacityInfo Folder、MinCapacity 磁盘容量配置,阈值单位为 GB
ReminderNotice Time、ReminderType、ModuleToken、ProcessingStatus、ProcessingTime、Message 应用收到的提醒及历史记录

模块标识与枚举

EquipmentModuleToken

常量 含义
STORAGE_CAPACITY 存储容量,磁盘检测保留标识
HYDROGEN_GENERATOR 氢气发生器
ZERO_GAS_GENERATOR 零气发生器
AIR_COMPRESSOR 空气压缩机
PROBE_FILTER 探头过滤器
SECONDARY_FILTER 二级过滤器
DEOXYGENATION_UNIT 除氧单元

ModuleToken 用于关联配置、维护状态和提醒。同一个模块应始终使用相同且唯一的标识。STORAGE_CAPACITY 具有特殊含义,不应分配给其他设备模块。

枚举

枚举 值 含义
ReminderTimeType HOUR / DAY / MONTH 按小时、天或日历月计算周期
ReminderType STORAGE_CAPACITY_NOT_ENOUGH 磁盘容量不足
ReminderType MODULE_MAINTAIN_EXPIRE 设备模块维护到期
ProcessStatus UNPROCESSED / PROCESSED 未处理 / 已处理

SQLite 数据存储

数据库在第一次访问相关功能时自动创建,实际路径为:

{AppContext.BaseDirectory}\File\VOCsReminder\DB\VOCsReminder.db

宿主程序需要对该目录具有读写权限。数据库包含四张表:

表名 用途
RemindStatus 保存未处理提醒和已处理历史
DeviceModuleMaintainInfo 保存模块启用状态、提醒周期和文案
DeviceModuleMaintainData 保存模块到期时间和更新时间
StorageCapacityInfo 保存检测目录和最小容量阈值

时间写入 SQLite 前统一格式化为:

yyyy-MM-dd HH:mm:ss.fff

应用层不应直接修改数据库文件,应通过 Getter、Setter 和 Handler 操作数据。

参数、返回值与失败处理

  • SetStorageCapacity:目录不能为空;阈值必须大于 0,且不能为 NaN 或无穷大;
  • SetModuleMaintainInfo:模块标识和提醒内容不能为空;时间类型必须有效;启用时周期值必须大于 0;
  • 设置和处理方法返回 true 表示成功,返回 false 表示失败;
  • 查询无数据或底层操作失败时可能返回 null,应用层应做好空值判断;
  • 检测流程只有在提醒成功写入数据库后才调用 IMessageReminder;
  • 未注册 IMessageReminder 时,检测流程不会生成新的提醒;
  • IMessageReminder.Reminder(...) 返回的 Task 会被库等待,实现中不应长时间阻塞。

使用注意事项

  • VOCsRemindManager 和三个检测流程均为进程内单例;
  • 库使用宿主进程的本地时间 DateTime.Now,不进行时区转换;
  • 库不创建定时器,检测频率和生命周期由应用层管理;
  • 同一模块已有未处理提醒时,不会再次创建或推送提醒;
  • 应用启动后应先调用 SetReminder(...),再调用一次 GetCurrentRemind();
  • 用户完成设备维护后必须调用 Handler.Handling(...),否则该模块不会进入下一个维护周期;
  • 容量不足状态未解除时,磁盘提醒处理后会在下一次检测中再次出现;
  • 设置为停用只停止检测,不会删除配置、维护状态和提醒历史;
  • 批量设置不是整体事务,调用方应检查返回值;
  • 应用层应避免重叠执行总流程和单独流程。

最小完整示例

using System;
using System.Threading.Tasks;
using VOCsReminder;

public sealed class ConsoleReminder : IMessageReminder
{
    public Task Reminder(ReminderNotice notice)
    {
        Console.WriteLine(
            $"{notice.Time:yyyy-MM-dd HH:mm:ss} {notice.Message}");

        return Task.CompletedTask;
    }
}

public static class ReminderBootstrap
{
    public static async Task ConfigureAndCheck()
    {
        VOCsRemindManager manager = VOCsRemindManager
            .GetInstance()
            .SetReminder(new ConsoleReminder());

        // 应用启动时恢复未处理提醒。
        await manager.GetCurrentRemind();

        await manager.Setter.SetStorageCapacity(@"D:\VOCsData", 20d);

        await manager.Setter.SetModuleMaintainInfo(
            new DeviceModuleMaintainInfo
            {
                ModuleToken = EquipmentModuleToken.STORAGE_CAPACITY,
                IsEnabled = true,
                ReminderValue = 1,
                ReminderTimeType = ReminderTimeType.DAY,
                Message = "数据盘可用空间不足。"
            });

        await manager.Setter.SetModuleMaintainInfo(
            new DeviceModuleMaintainInfo
            {
                ModuleToken = EquipmentModuleToken.ZERO_GAS_GENERATOR,
                IsEnabled = true,
                ReminderValue = 1,
                ReminderTimeType = ReminderTimeType.MONTH,
                Message = "零气发生器需要维护。"
            });

        // 实际应用中由应用层定时调用。
        await ReminderProcess.GetInstance().Execute();

        // 用户确认完成维护后调用:
        // await manager.Handler.Handling(
        //     EquipmentModuleToken.ZERO_GAS_GENERATOR,
        //     ProcessStatus.PROCESSED);
    }
}
Product Compatible and additional computed target framework versions.
.NET net5.0 was computed.  net5.0-windows was computed.  net6.0 was computed.  net6.0-android was computed.  net6.0-ios was computed.  net6.0-maccatalyst was computed.  net6.0-macos was computed.  net6.0-tvos was computed.  net6.0-windows was computed.  net7.0 was computed.  net7.0-android was computed.  net7.0-ios was computed.  net7.0-maccatalyst was computed.  net7.0-macos was computed.  net7.0-tvos was computed.  net7.0-windows was computed.  net8.0 is compatible.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed.  net9.0 was computed.  net9.0-android was computed.  net9.0-browser was computed.  net9.0-ios was computed.  net9.0-maccatalyst was computed.  net9.0-macos was computed.  net9.0-tvos was computed.  net9.0-windows was computed.  net10.0 is compatible.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
.NET Core netcoreapp2.0 was computed.  netcoreapp2.1 was computed.  netcoreapp2.2 was computed.  netcoreapp3.0 was computed.  netcoreapp3.1 was computed. 
.NET Standard netstandard2.0 is compatible.  netstandard2.1 was computed. 
.NET Framework net461 was computed.  net462 was computed.  net463 was computed.  net47 was computed.  net471 was computed.  net472 was computed.  net48 is compatible.  net481 was computed. 
MonoAndroid monoandroid was computed. 
MonoMac monomac was computed. 
MonoTouch monotouch was computed. 
Tizen tizen40 was computed.  tizen60 was computed. 
Xamarin.iOS xamarinios was computed. 
Xamarin.Mac xamarinmac was computed. 
Xamarin.TVOS xamarintvos was computed. 
Xamarin.WatchOS xamarinwatchos was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
1.0.4 0 11/2/2026
1.0.3 97 10/23/2026
1.0.2 89 10/23/2026
1.0.1 102 10/22/2026
1.0.0 95 10/21/2026

本次更新内容:
1.修复已处理后再次检测会重新报警的问题。
2.修复忽略后依然触发提醒的问题。