<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="zh-Hans-CN">
	<id>https://wiki2.lessokaji.com/index.php?action=history&amp;feed=atom&amp;title=IOObject%E5%B1%9E%E6%80%A7%E5%8F%82%E8%80%83</id>
	<title>IOObject属性参考 - 版本历史</title>
	<link rel="self" type="application/atom+xml" href="https://wiki2.lessokaji.com/index.php?action=history&amp;feed=atom&amp;title=IOObject%E5%B1%9E%E6%80%A7%E5%8F%82%E8%80%83"/>
	<link rel="alternate" type="text/html" href="https://wiki2.lessokaji.com/index.php?title=IOObject%E5%B1%9E%E6%80%A7%E5%8F%82%E8%80%83&amp;action=history"/>
	<updated>2026-05-16T16:52:08Z</updated>
	<subtitle>本wiki上该页面的版本历史</subtitle>
	<generator>MediaWiki 1.40.0</generator>
	<entry>
		<id>https://wiki2.lessokaji.com/index.php?title=IOObject%E5%B1%9E%E6%80%A7%E5%8F%82%E8%80%83&amp;diff=1037&amp;oldid=prev</id>
		<title>Artheru：​Initial bilingual draft (auto-published)</title>
		<link rel="alternate" type="text/html" href="https://wiki2.lessokaji.com/index.php?title=IOObject%E5%B1%9E%E6%80%A7%E5%8F%82%E8%80%83&amp;diff=1037&amp;oldid=prev"/>
		<updated>2026-05-16T14:00:13Z</updated>

		<summary type="html">&lt;p&gt;Initial bilingual draft (auto-published)&lt;/p&gt;
&lt;p&gt;&lt;b&gt;新页面&lt;/b&gt;&lt;/p&gt;&lt;div&gt;&amp;lt;languages/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== 概述 / Overview ==&lt;br /&gt;
本页是 Medulla `IOObject` 基类与其上 ''全部装饰属性''的速查表。属性定义在 `D:\src\M2\MedullaCore\Types\IO.cs:9-70`。&lt;br /&gt;
&lt;br /&gt;
This page is the cheat sheet for the Medulla `IOObject` base class and ''all its decorating attributes''. Attribute definitions at `D:\src\M2\MedullaCore\Types\IO.cs:9-70`.&lt;br /&gt;
&lt;br /&gt;
== IOObject 基类 / IOObject base ==&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! 成员 / Member !! 类型 / Type !! 含义 / Meaning&lt;br /&gt;
|-&lt;br /&gt;
| `Name` || `string` || 实例名（由 startup.iocmd 加载时设置）/ instance name set by the script engine on load&lt;br /&gt;
|-&lt;br /&gt;
| `TimeoutThreshold` || `float = 500` || 预期更新间隔（ms）；框架不强制，插件自己用 / expected update interval, plugin-enforced&lt;br /&gt;
|-&lt;br /&gt;
| `Methods` || `string[]` || 反射回填的公共方法名 / reflection-backed; for UI auto-binding&lt;br /&gt;
|-&lt;br /&gt;
| `OpenUI(Terminal)` || virtual || 打开 UI 面板的钩子 / UI panel creation hook&lt;br /&gt;
|-&lt;br /&gt;
| `CloseUI()` || virtual || 关闭 UI / UI teardown&lt;br /&gt;
|-&lt;br /&gt;
| `SwitchTerminal(Terminal)` || virtual || 把 UI 迁移到新 Terminal / migrate UI to a new Terminal&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
`MainIOObject` 类名是 Medulla 反射查找的硬约束（`MedullaIO.cs:299`）。&lt;br /&gt;
The class name `MainIOObject` is a hard-coded reflection lookup in `MedullaIO.cs:299`.&lt;br /&gt;
&lt;br /&gt;
== 装饰属性 / Decorating attributes ==&lt;br /&gt;
=== [IOObjectMonitor] ===&lt;br /&gt;
'''目标''' / Target: 字段 / field&lt;br /&gt;
&lt;br /&gt;
'''效果''' / Effect: 字段值导出到 CycleGUI 的属性栅格；如果 `VerboseLog = true`，每次变化记到 DLog。&lt;br /&gt;
Exports the field to CycleGUI's property grid; logs to DLog if `VerboseLog = true`.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;csharp&amp;quot;&amp;gt;&lt;br /&gt;
[IOObjectMonitor]&lt;br /&gt;
public float currentVelocity;&lt;br /&gt;
&lt;br /&gt;
[IOObjectMonitor(desc = &amp;quot;电池剩余百分比 / Battery percentage&amp;quot;)]&lt;br /&gt;
public int batteryPercent;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== [IOObjectUtility] ===&lt;br /&gt;
'''目标''' / Target: 方法（仅 ''零参数''）/ method (zero-arg only)&lt;br /&gt;
&lt;br /&gt;
'''效果''' / Effect: 在 UI 的 &amp;quot;Actions&amp;quot; 组中显示为按钮。&lt;br /&gt;
Renders as a button in the UI's &amp;quot;Actions&amp;quot; group.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;csharp&amp;quot;&amp;gt;&lt;br /&gt;
[IOObjectUtility]&lt;br /&gt;
public void StartScan() { /* trigger device start */ }&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== [IOObjectWebUtility] ===&lt;br /&gt;
'''目标''' / Target: 方法 / method&lt;br /&gt;
&lt;br /&gt;
'''效果''' / Effect: 自动注册 HTTP 端点 `/&amp;lt;IOName&amp;gt;/&amp;lt;MethodName&amp;gt;`。&lt;br /&gt;
Auto-registers an HTTP endpoint `/&amp;lt;IOName&amp;gt;/&amp;lt;MethodName&amp;gt;`.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;csharp&amp;quot;&amp;gt;&lt;br /&gt;
[IOObjectWebUtility(type = WebUtilityType.API)]&lt;br /&gt;
public byte[] GetCurrentFrame() { /* return JSON or binary */ }&lt;br /&gt;
&lt;br /&gt;
[IOObjectWebUtility(type = WebUtilityType.WebPage)]&lt;br /&gt;
public byte[] StatusPage() { /* return HTML */ }&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
子类型 / Subtypes (`type` enum):&lt;br /&gt;
* `WebPage` — 返回 `byte[]`，作为完整页面 / returns `byte[]` as a full page&lt;br /&gt;
* `API` — JSON API&lt;br /&gt;
* `Utility` — 普通工具方法&lt;br /&gt;
* `DataChunk` — 大块二进制数据（流式 / chunked）&lt;br /&gt;
&lt;br /&gt;
=== [IOObjectWatch] ===&lt;br /&gt;
'''目标''' / Target: 字段 / field&lt;br /&gt;
&lt;br /&gt;
'''效果''' / Effect: 看门狗。当 JS 表达式 `jsWatcher` 在字段上为 true → 触发告警模板 `jsAlertTemplate`。&lt;br /&gt;
Watchdog. When the JS predicate `jsWatcher` on the field evaluates true → fires the alert template `jsAlertTemplate`.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;csharp&amp;quot;&amp;gt;&lt;br /&gt;
[IOObjectWatch(&lt;br /&gt;
    watchVal = &amp;quot;value&amp;quot;,&lt;br /&gt;
    jsWatcher = &amp;quot;value &amp;lt; 10&amp;quot;,&lt;br /&gt;
    jsAlertTemplate = &amp;quot;Battery critically low: ${value}%&amp;quot;,&lt;br /&gt;
    jsAlertColorTemplate = &amp;quot;red&amp;quot;,&lt;br /&gt;
    holdIfAlert = true)]&lt;br /&gt;
public int batteryPercent;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== [IOObjectSerialize] ===&lt;br /&gt;
'''目标''' / Target: 类 / class&lt;br /&gt;
&lt;br /&gt;
'''效果''' / Effect: 自定义序列化器。当前 build 未使用 / unused in current build.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;csharp&amp;quot;&amp;gt;&lt;br /&gt;
[IOObjectSerialize(Serializer = typeof(MyCustomSerializer))]&lt;br /&gt;
public class MyIO : IOObject { ... }&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== 与 CartDefinition 属性的区别 / vs CartDefinition attributes ==&lt;br /&gt;
注意 `[AsUpperIO] / [AsLowerIO] / [AsInitParam] / [UseLadderLogic]` 不是 `IOObject` 的属性 —— 它们属于 `CartDefinition`（位于 `CartActivator` 插件）。详见 [[Special:MyLanguage/CartDefinition属性参考|CartDefinition属性参考]]。&lt;br /&gt;
&lt;br /&gt;
The `[AsUpperIO]` / `[AsLowerIO]` / `[AsInitParam]` / `[UseLadderLogic]` attributes are NOT on `IOObject` — they live in the `CartActivator` plugin's `CartDefinition` family. See [[Special:MyLanguage/CartDefinition属性参考|CartDefinition属性参考]].&lt;br /&gt;
&lt;br /&gt;
== Web 端点路由 / Web endpoint routing ==&lt;br /&gt;
Medulla 启动 HTTP server（`Startup.cs:204-256`）后：&lt;br /&gt;
After Medulla starts its HTTP server:&lt;br /&gt;
&lt;br /&gt;
* `GET /getIOs` — 列出所有加载的 IOObject + 它们的字段 + 方法 + 端点&lt;br /&gt;
* `GET/POST /&amp;lt;IOName&amp;gt;/&amp;lt;MethodName&amp;gt;` — 调用 `[IOObjectWebUtility]` 方法&lt;br /&gt;
* `GET /&amp;lt;IOName&amp;gt;/&amp;lt;FieldName&amp;gt;` — 读 `[IOObjectMonitor]` 字段（如果配置开放）&lt;br /&gt;
&lt;br /&gt;
端口由 `MedullaIO.CPort` 控制（默认 8081 / `MedullaIO.cs:34`）。&lt;br /&gt;
&lt;br /&gt;
Port controlled by `MedullaIO.CPort` (default 8081).&lt;br /&gt;
&lt;br /&gt;
== 调试技巧 / Debug tips ==&lt;br /&gt;
* '''字段不出现在 dashboard''' → 检查 `[IOObjectMonitor]` 是否标在 ''public 字段''上。&lt;br /&gt;
* '''按钮不出现''' → `[IOObjectUtility]` 标在 ''public 零参数方法''上吗？&lt;br /&gt;
* '''Web 端点 404''' → IO 名是否正确？看 `/getIOs` 列表确认。&lt;br /&gt;
* '''告警不触发''' → `jsWatcher` 表达式语法错误是常见原因；用 `console.log(value)` 调试。&lt;br /&gt;
&lt;br /&gt;
== 相关页面 / See also ==&lt;br /&gt;
* [[Special:MyLanguage/CartDefinition属性参考|CartDefinition属性参考]]&lt;br /&gt;
* [[Special:MyLanguage/插件契约与打包约定|插件契约与打包约定]]&lt;br /&gt;
* [[Special:MyLanguage/Medulla软件架构|Medulla软件架构]]&lt;br /&gt;
* [[Special:MyLanguage/Medulla|Medulla]] / [[Special:MyLanguage/Medulla-API|Medulla-API]]&lt;br /&gt;
&lt;br /&gt;
[[Category:二次开发相关说明]]&lt;br /&gt;
[[Category:开发手册]]&lt;/div&gt;</summary>
		<author><name>Artheru</name></author>
	</entry>
</feed>