OpenRobot.Litegraph.RuleEngine 1.0.0

dotnet add package OpenRobot.Litegraph.RuleEngine --version 1.0.0
                    
NuGet\Install-Package OpenRobot.Litegraph.RuleEngine -Version 1.0.0
                    
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="OpenRobot.Litegraph.RuleEngine" Version="1.0.0" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="OpenRobot.Litegraph.RuleEngine" Version="1.0.0" />
                    
Directory.Packages.props
<PackageReference Include="OpenRobot.Litegraph.RuleEngine" />
                    
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 OpenRobot.Litegraph.RuleEngine --version 1.0.0
                    
#r "nuget: OpenRobot.Litegraph.RuleEngine, 1.0.0"
                    
#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 OpenRobot.Litegraph.RuleEngine@1.0.0
                    
#: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=OpenRobot.Litegraph.RuleEngine&version=1.0.0
                    
Install as a Cake Addin
#tool nuget:?package=OpenRobot.Litegraph.RuleEngine&version=1.0.0
                    
Install as a Cake Tool

OpenRobot.Litegraph.RuleEngine

MMID 规则引擎的模型层(net8.0):规则模型 + 语义校验 + MMID 选择器求值。 回答「什么时候、让谁参与、满足什么条件、做什么」,不含执行器,也不含画布编译器。

  • 动作里没有 topic:动作只写能力名(biz.enable / decision.feedRate / report.bizResult …), 共 11 个白名单枚举。能力名到 MQTT topic / identifier 的映射写在宿主代码里 —— 规则可以下发、可以现场改,但永远改不到跨仓库契约。
  • 逐帧规则不许做 IO:hook = segment.frame 是每个采集帧触发;挂 decision.* / alarm.raise / report.* / log.* 一律是 Error,规则集拒绝加载。
  • 不认识业务名,也不认识参数名:业务是否注册、参数键是否存在、值域是否合法,全部通过宿主注入的 IBizRuleCatalog 判定;字段名走 IMmidFieldCatalog。开源包里不出现任何一个专有业务。
  • 有 Error 即拒绝加载:BizRuleValidator 在加载前就把「配了但永远不生效」的形态挡下来 —— 这一点与画布引擎「有 Error 也照常执行」不同,规则静默失效的代价现场承受不起。

安装

<PackageReference Include="OpenRobot.Litegraph.RuleEngine" Version="1.0.0" />

包由本仓库产出:

dotnet pack Litegraph/OpenRobot.Litegraph.RuleEngine/OpenRobot.Litegraph.RuleEngine.csproj -c Release

依赖:

  • OpenRobot.Litegraph.MmidSyntax 1.0.0(选择器文本 ⇄ AST)

不依赖 OpenRobot.Litegraph.Core:本包只提供模型、校验与求值,调度与执行属于宿主。


快速开始

写一条规则并校验

using OpenRobot.Litegraph.RuleEngine;

var rule = new BizRule
{
    RuleId = "O1026-T3-rough-ips",
    Version = 3,
    Priority = 100,
    Hook = BizRuleHook.SegmentStart,
    Matcher = new BizRuleMatcher { Product = "O1026", SegmentKey = "O1026-T3-rough#*" },
    When = BizRuleCondition.All(
        BizRuleCondition.Predicate("$BUS.Cut", BizConditionOperator.Eq, "1")),
    Once = BizRuleOnce.Edge,
    Actions = [new BizRuleAction { Type = BizRuleActionType.BizEnable, Name = "Ips" }],
};

var ruleSet = new BizRuleSet { RuleSetVersion = 7, Rules = [rule] };
var result = BizRuleValidator.Validate(ruleSet, catalog);   // catalog = 宿主的 IBizRuleCatalog

if (!result.CanLoad)
{
    foreach (var issue in result.Errors)
        Console.WriteLine(issue);     // [Error] FRAME_HOOK_IO_ACTION (O1026-T3-rough-ips): …
}

// 或者一步到位:有 Error 直接抛
BizRuleValidator.ValidateOrThrow(ruleSet, catalog);

求值 MMID 选择器

选择器来自 OpenRobot.Litegraph.MmidSyntax,求值要宿主提供两样东西:当前帧和段历史。

using OpenRobot.Litegraph.MmidSyntax;

var selectors = MmidSelectorParser.Parse("T3.S8000:cut");

var context = new MmidEvaluationContext
{
    Frame = new Dictionary<string, string?>
    {
        ["$BUS.Tool.Tcode"] = "3",
        ["$BUS.Scommand"] = "8000",
        ["$BUS.Cut"] = "1",
    },
    StableMs = 320,                 // :stable(300ms) 用它
    Occurrence = 1,                 // :nth(n) 用它(本规则第几次命中)
    Published = publishedSegments,  // 本件内已发布的段,正序;最后一个 = 紧邻前驱
    LastMatched = lastMatched,      // 本规则最近一次命中的段;:lastMatch 用它
};

var evaluator = new MmidSelectorEvaluator();
var hit = evaluator.MatchesAny(selectors, context);

MmidSelectorEvaluator.Validate(selectors, catalog) 是加载期的结构性检查(类型名、类前缀、字段名能不能解释), 它和上面的命中判定是两件事 —— 前者不做这一步的后果是「规则配了但永远不命中,日志里什么都没有」。

:prev 与 :lastMatch

T3.S8000:cut:stable(300ms):lastMatch($BUS.Tool.Tcode = @previousTool)
伪类 语义
:prev(...) 紧邻的上一段满足条件(中间不许夹段)
:lastMatch(...) 本件内最近一次被本规则命中的段满足条件(允许夹着背刀、MDI、伪段)

「上一把刀」刻意不进 MMID 字面量、也不进 SegmentKey —— 否则条目会按「工序位置 × 前一把刀」膨胀, 且规则一改历史条目全作废。

求值条件

条件求值要宿主把字段名映射成实际值(本包不认识 $BUS.*,也不持有信号快照):

public sealed class SignalSource : IBizRuleConditionEvaluator
{
    public bool TryGetFieldValue(string field, bool previous, out string? value)
    {
        // previous=true 时取上一帧的值(CHANGED / RISE / FALL 需要)
        // 取不到就返回 false —— 缺失字段一律按「不命中」处理
        return _snapshot.TryGet(field, previous, out value);
    }
}

var ok = BizConditionEvaluator.Evaluate(rule.When!, new SignalSource());

API 速查

规则模型

类型 说明
BizRule RuleId / Version / Enabled / Priority / Hook / Matcher / When / Once / Actions / VersionTag
BizRuleSet RuleSetVersion / Rules
BizRuleHook 7 个时机:ProductStart / ProductEnd / EngineState / SegmentStart / SegmentEnd / SegmentToolChange / SegmentFrame
BizRuleHooks ToText / TryParse(字面量如 segment.start,大小写敏感)
BizRuleOnce Edge(由假变真执行一次)/ Level(成立期间每帧执行)
BizRuleMatcher 静态身份:DeviceId / Product / SegmentKey(* 或空 = 任意)
BizRuleAction Type / Name / Key / Value;没有 topic 字段
BizRuleActionType 11 个能力:BizEnable / BizDisable / BizParam / PropertySet / DecisionFeedRate / DecisionStop / AlarmRaise / ReportBizResult / LogInfo / LogWarn / LogError
BizRuleActionTypes ToText / TryParse / IsIo(有副作用 / IO 的动作)

条件

类型 说明
BizRuleCondition 四形态 AST:All / Any / Not / 谓词;All(...) / Any(...) / Not(...) / Predicate(...)
BizConditionKind All / Any / Not / Predicate
BizConditionOperator 13 个算子:Eq / NotEq / Gt / Gte / Lt / Lte / Between / In / NotIn / Changed / Rise / Fall / ChangedTo
BizConditionOperators ToText(EQ 全大写)/ ToJson(eq 小写)/ TryParse / RequiresList / IsEdgeOperator
BizConditionEvaluator Evaluate(condition, source) / AreEqual / TryCompare / IsTruthy
IBizRuleConditionEvaluator TryGetFieldValue(field, previous, out value):宿主实现字段 → 值的映射

选择器求值

类型 说明
MmidSelectorEvaluator(options?) Matches / MatchesAny / FirstMatchingIndex(没命中返回 -1)/ Validate
MmidEvaluationContext Frame / Computed / StableMs / Occurrence / Published / LastMatched
MmidSegmentView 一段已发布段的快照:SegmentKey / Mmid / Fields / Computed / StartedAtMs / EndedAtMs
MmidEvaluatorOptions 字段口径:CutField / ToolField / SpeedField / ClassMappings / FieldAliases
MmidClassMapping 类前缀 → 字段(.S8000 读作「$BUS.Scommand 等于 8000」)

段键与校验

类型 说明
SegmentKeyPattern Parse / TryParse / Build / TrySplit / Matches;RuleId#序号,#* 通配,Any
BizRuleValidator Validate(ruleSet, catalog?) / Validate(rule, catalog?) / ValidateOrThrow(...);FrameLeafBudget = 16
BizRuleValidationResult Issues / Errors / Warnings / IsValid / HasError / CanLoad
BizRuleIssue Code / Severity / RuleId / Message
IBizRuleCatalog IsBusinessRegistered(name) / TryValidateParameter(name, key, value, out error)

已知限制

  1. 不含执行器:本包不调度、不订阅、不调业务。规则什么时候求值、动作怎么落地,全在宿主。
  2. 不含规则集 JSON 读写:规则集的报文形状与下发命令还在定稿,包里不固化。确认之后才补序列化 —— 在此之前请宿主自己映射,避免把未定的形状变成事实。
  3. 不注入 IBizRuleCatalog 就查不到业务语义:业务名是否存在、参数值域是否合理这两类校验会直接跳过, 只剩结构校验。生产宿主必须注入。
  4. 求值不持有历史::prev / :lastMatch 靠 MmidEvaluationContext.Published / LastMatched, CHANGED / RISE / FALL 靠 IBizRuleConditionEvaluator 的 previous 值。宿主没给,就是不命中 —— 本包不替你缓存任何历史。
  5. 取不到值 = 整条不命中:不做「空串 != x 所以命中」这类假阳性。缺字段拼出假命中的问题不在规则层重演。
  6. :nth(n) 不是段键里的 #n:前者是「本规则第几次命中」(Occurrence),后者是段键内的出现序号, 两者刻意分开。
  7. FrameLeafBudget 只是 Warning:逐帧钩子叶子条件超过 16 个不阻断加载,但 100 Hz 下要自己掂量。

版本历史

1.0.0(首次发布)

  • 规则模型:7 个 hook、edge / level、静态 matcher(设备 / 产品 / 段键)、11 个动作白名单
  • 条件 AST(All / Any / Not / 谓词)与 13 个算子,含 4 个边沿算子与 holdMs 去抖窗口
  • BizRuleValidator:语义校验,有 Error 即拒绝加载
  • MmidSelectorEvaluator:组合子 >、:cut / :stable / :nth / :not / :prev / :lastMatch
  • SegmentKeyPattern:段键解析、构建与通配匹配
  • 业务与字段的「已知事实」全部由宿主注入(IBizRuleCatalog / IMmidFieldCatalog)
Product Compatible and additional computed target framework versions.
.NET 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 was computed.  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. 
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.0 5 10/28/2026