Skip to main content

纯信号 · 事件广播

独立式节点的典型模式——自行管理生命周期,不开放接口,只向外部广播事件。KnotHub 通过注册表发现它,其他程序订阅它的信号。

真实节点ClassIsland


模式

ClassIsland ──▶ [event=OnClass] ──────▶ 订阅方 A(上课提醒)
ClassIsland ──▶ [event=OnBreakingTime] ─▶ 订阅方 B(下课播报)
ClassIsland ──▶ [event=OnAfterSchool] ──▶ 订阅方 C(放学通知)

同一个 signalID 广播不同事件,verification 字段让订阅方精确匹配。


注册表

独立式节点不通过 Plugins/ 目录被发现——安装时写入注册表:

HKCU\Software\KnotLink\StandaloneNodes
└── 0x00000031 = "C:\Program Files\ClassIsland"

安装目录根目录下放置两份清单:

C:\Program Files\ClassIsland\
├── ClassIsland.exe
├── standalone_manifest.json
├── FuncList.json
└── ...

安装脚本示例:

New-Item -Path "HKCU:\Software\KnotLink\StandaloneNodes" -Force | Out-Null
Set-ItemProperty -Path "HKCU:\Software\KnotLink\StandaloneNodes" `
-Name "0x00000031" -Value "C:\Program Files\ClassIsland"

清单

standalone_manifest.json

{
"app_id": "0x00000031",
"app_name": "ClassIsland",
"author": "信",
"version": "v1.0.0",
"description": "课程信息与桌面通知服务",
"download_url": "https://github.com/hxh230802/ClassIsland/releases/latest"
}

FuncList.json — 信号为主,接口为辅:

"signal": {
"OnClass": {
"appID": "0x00000031",
"signalID": "0x00000011",
"description": "上课事件",
"returns": {
"event": {
"description": "事件名",
"verification": "OnClass"
}
}
},
"OnBreakingTime": {
"appID": "0x00000031",
"signalID": "0x00000011",
"description": "下课事件",
"returns": {
"event": {
"description": "事件名",
"verification": "OnBreakingTime"
}
}
},
"OnAfterSchool": {
"appID": "0x00000031",
"signalID": "0x00000011",
"description": "放学事件",
"returns": {
"event": { "description": "事件名", "verification": "OnAfterSchool" },
"time": { "description": "时间" }
}
}
}

signal.returns对象格式,与 openSocket.returns 的数组格式不同。


通信代码

from knotlink import SignalSender, KLKVMap
import time

APPID = "0x00000031"
SIGNAL_ID = "0x00000011"

sender = SignalSender(APPID, SIGNAL_ID)


def on_break_time():
"""下课了——广播事件"""
kv = KLKVMap()
kv["event"] = "OnBreakingTime"
sender.emitt(kv.serialize())


def on_class_start():
"""上课了"""
kv = KLKVMap()
kv["event"] = "OnClass"
sender.emitt(kv.serialize())


def on_after_school():
"""放学了"""
kv = KLKVMap()
kv["event"] = "OnAfterSchool"
kv["time"] = time.strftime("%Y-%m-%d %H:%M:%S")
sender.emitt(kv.serialize())

不设置回调、不 return 响应——纯广播,不需要 OpenSocketResponser


关键点

  • 独立式用 standalone_manifest.json — 文件名决定类型,用 app_name(不是 plugin_name
  • 注册表是发现入口HKCU\Software\KnotLink\StandaloneNodes,值名 = app_id,值 = 安装路径
  • signal.returns 是对象格式{"event": {"description": "...", "verification": "OnClass"}},跟 openSocket 的数组格式不一样
  • verification 用于信号鉴别 — 同一个 signalID 发多种事件,订阅方靠 verification 值精确匹配
  • 也可同时开放接口 — ClassIsland 还有 ClassService 供查询课程,信号和接口不互斥