@tx5dr/contracts 1.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (180) hide show
  1. package/CLAUDE.md +41 -0
  2. package/dist/index.d.ts +55 -0
  3. package/dist/index.d.ts.map +1 -0
  4. package/dist/index.js +86 -0
  5. package/dist/index.js.map +1 -0
  6. package/dist/schema/__tests__/plugin-runtime-log.schema.test.d.ts +2 -0
  7. package/dist/schema/__tests__/plugin-runtime-log.schema.test.d.ts.map +1 -0
  8. package/dist/schema/__tests__/plugin-runtime-log.schema.test.js +78 -0
  9. package/dist/schema/__tests__/plugin-runtime-log.schema.test.js.map +1 -0
  10. package/dist/schema/ability.d.ts +85 -0
  11. package/dist/schema/ability.d.ts.map +1 -0
  12. package/dist/schema/ability.js +119 -0
  13. package/dist/schema/ability.js.map +1 -0
  14. package/dist/schema/api-response.schema.d.ts +1017 -0
  15. package/dist/schema/api-response.schema.d.ts.map +1 -0
  16. package/dist/schema/api-response.schema.js +137 -0
  17. package/dist/schema/api-response.schema.js.map +1 -0
  18. package/dist/schema/audio-sidecar.schema.d.ts +106 -0
  19. package/dist/schema/audio-sidecar.schema.d.ts.map +1 -0
  20. package/dist/schema/audio-sidecar.schema.js +47 -0
  21. package/dist/schema/audio-sidecar.schema.js.map +1 -0
  22. package/dist/schema/audio.schema.d.ts +227 -0
  23. package/dist/schema/audio.schema.d.ts.map +1 -0
  24. package/dist/schema/audio.schema.js +56 -0
  25. package/dist/schema/audio.schema.js.map +1 -0
  26. package/dist/schema/auth.schema.d.ts +738 -0
  27. package/dist/schema/auth.schema.d.ts.map +1 -0
  28. package/dist/schema/auth.schema.js +161 -0
  29. package/dist/schema/auth.schema.js.map +1 -0
  30. package/dist/schema/cycle.schema.d.ts +33 -0
  31. package/dist/schema/cycle.schema.d.ts.map +1 -0
  32. package/dist/schema/cycle.schema.js +23 -0
  33. package/dist/schema/cycle.schema.js.map +1 -0
  34. package/dist/schema/desktop-https.schema.d.ts +146 -0
  35. package/dist/schema/desktop-https.schema.d.ts.map +1 -0
  36. package/dist/schema/desktop-https.schema.js +31 -0
  37. package/dist/schema/desktop-https.schema.js.map +1 -0
  38. package/dist/schema/ft8.schema.d.ts +1107 -0
  39. package/dist/schema/ft8.schema.d.ts.map +1 -0
  40. package/dist/schema/ft8.schema.js +268 -0
  41. package/dist/schema/ft8.schema.js.map +1 -0
  42. package/dist/schema/hello.schema.d.ts +10 -0
  43. package/dist/schema/hello.schema.d.ts.map +1 -0
  44. package/dist/schema/hello.schema.js +5 -0
  45. package/dist/schema/hello.schema.js.map +1 -0
  46. package/dist/schema/logbook.schema.d.ts +1472 -0
  47. package/dist/schema/logbook.schema.d.ts.map +1 -0
  48. package/dist/schema/logbook.schema.js +256 -0
  49. package/dist/schema/logbook.schema.js.map +1 -0
  50. package/dist/schema/mode.schema.d.ts +130 -0
  51. package/dist/schema/mode.schema.d.ts.map +1 -0
  52. package/dist/schema/mode.schema.js +141 -0
  53. package/dist/schema/mode.schema.js.map +1 -0
  54. package/dist/schema/openwebrx.schema.d.ts +352 -0
  55. package/dist/schema/openwebrx.schema.d.ts.map +1 -0
  56. package/dist/schema/openwebrx.schema.js +139 -0
  57. package/dist/schema/openwebrx.schema.js.map +1 -0
  58. package/dist/schema/operator.schema.d.ts +883 -0
  59. package/dist/schema/operator.schema.d.ts.map +1 -0
  60. package/dist/schema/operator.schema.js +97 -0
  61. package/dist/schema/operator.schema.js.map +1 -0
  62. package/dist/schema/plugin.schema.d.ts +1579 -0
  63. package/dist/schema/plugin.schema.d.ts.map +1 -0
  64. package/dist/schema/plugin.schema.js +336 -0
  65. package/dist/schema/plugin.schema.js.map +1 -0
  66. package/dist/schema/process-monitor.schema.d.ts +282 -0
  67. package/dist/schema/process-monitor.schema.d.ts.map +1 -0
  68. package/dist/schema/process-monitor.schema.js +31 -0
  69. package/dist/schema/process-monitor.schema.js.map +1 -0
  70. package/dist/schema/pskreporter.schema.d.ts +185 -0
  71. package/dist/schema/pskreporter.schema.d.ts.map +1 -0
  72. package/dist/schema/pskreporter.schema.js +80 -0
  73. package/dist/schema/pskreporter.schema.js.map +1 -0
  74. package/dist/schema/qso.schema.d.ts +419 -0
  75. package/dist/schema/qso.schema.d.ts.map +1 -0
  76. package/dist/schema/qso.schema.js +137 -0
  77. package/dist/schema/qso.schema.js.map +1 -0
  78. package/dist/schema/radio-capability.schema.d.ts +625 -0
  79. package/dist/schema/radio-capability.schema.d.ts.map +1 -0
  80. package/dist/schema/radio-capability.schema.js +191 -0
  81. package/dist/schema/radio-capability.schema.js.map +1 -0
  82. package/dist/schema/radio-power-support.d.ts +45 -0
  83. package/dist/schema/radio-power-support.d.ts.map +1 -0
  84. package/dist/schema/radio-power-support.js +64 -0
  85. package/dist/schema/radio-power-support.js.map +1 -0
  86. package/dist/schema/radio-power.schema.d.ts +319 -0
  87. package/dist/schema/radio-power.schema.d.ts.map +1 -0
  88. package/dist/schema/radio-power.schema.js +87 -0
  89. package/dist/schema/radio-power.schema.js.map +1 -0
  90. package/dist/schema/radio-profile.schema.d.ts +2694 -0
  91. package/dist/schema/radio-profile.schema.d.ts.map +1 -0
  92. package/dist/schema/radio-profile.schema.js +71 -0
  93. package/dist/schema/radio-profile.schema.js.map +1 -0
  94. package/dist/schema/radio.schema.d.ts +1438 -0
  95. package/dist/schema/radio.schema.d.ts.map +1 -0
  96. package/dist/schema/radio.schema.js +314 -0
  97. package/dist/schema/radio.schema.js.map +1 -0
  98. package/dist/schema/realtime.schema.d.ts +1299 -0
  99. package/dist/schema/realtime.schema.d.ts.map +1 -0
  100. package/dist/schema/realtime.schema.js +184 -0
  101. package/dist/schema/realtime.schema.js.map +1 -0
  102. package/dist/schema/rigctld.schema.d.ts +151 -0
  103. package/dist/schema/rigctld.schema.d.ts.map +1 -0
  104. package/dist/schema/rigctld.schema.js +42 -0
  105. package/dist/schema/rigctld.schema.js.map +1 -0
  106. package/dist/schema/server-message-keys.d.ts +21 -0
  107. package/dist/schema/server-message-keys.d.ts.map +1 -0
  108. package/dist/schema/server-message-keys.js +22 -0
  109. package/dist/schema/server-message-keys.js.map +1 -0
  110. package/dist/schema/slot-info.schema.d.ts +696 -0
  111. package/dist/schema/slot-info.schema.d.ts.map +1 -0
  112. package/dist/schema/slot-info.schema.js +144 -0
  113. package/dist/schema/slot-info.schema.js.map +1 -0
  114. package/dist/schema/spectrum.schema.d.ts +716 -0
  115. package/dist/schema/spectrum.schema.d.ts.map +1 -0
  116. package/dist/schema/spectrum.schema.js +128 -0
  117. package/dist/schema/spectrum.schema.js.map +1 -0
  118. package/dist/schema/station-info.schema.d.ts +202 -0
  119. package/dist/schema/station-info.schema.d.ts.map +1 -0
  120. package/dist/schema/station-info.schema.js +32 -0
  121. package/dist/schema/station-info.schema.js.map +1 -0
  122. package/dist/schema/system.schema.d.ts +113 -0
  123. package/dist/schema/system.schema.d.ts.map +1 -0
  124. package/dist/schema/system.schema.js +95 -0
  125. package/dist/schema/system.schema.js.map +1 -0
  126. package/dist/schema/transmission.schema.d.ts +413 -0
  127. package/dist/schema/transmission.schema.d.ts.map +1 -0
  128. package/dist/schema/transmission.schema.js +78 -0
  129. package/dist/schema/transmission.schema.js.map +1 -0
  130. package/dist/schema/voice.schema.d.ts +38 -0
  131. package/dist/schema/voice.schema.d.ts.map +1 -0
  132. package/dist/schema/voice.schema.js +24 -0
  133. package/dist/schema/voice.schema.js.map +1 -0
  134. package/dist/schema/websocket.schema.d.ts +16916 -0
  135. package/dist/schema/websocket.schema.d.ts.map +1 -0
  136. package/dist/schema/websocket.schema.js +1050 -0
  137. package/dist/schema/websocket.schema.js.map +1 -0
  138. package/dist/utils/grid.d.ts +13 -0
  139. package/dist/utils/grid.d.ts.map +1 -0
  140. package/dist/utils/grid.js +71 -0
  141. package/dist/utils/grid.js.map +1 -0
  142. package/eslint.config.js +15 -0
  143. package/package.json +28 -0
  144. package/src/index.ts +152 -0
  145. package/src/schema/__tests__/plugin-runtime-log.schema.test.ts +90 -0
  146. package/src/schema/ability.ts +205 -0
  147. package/src/schema/api-response.schema.ts +187 -0
  148. package/src/schema/audio-sidecar.schema.ts +53 -0
  149. package/src/schema/audio.schema.ts +73 -0
  150. package/src/schema/auth.schema.ts +224 -0
  151. package/src/schema/cycle.schema.ts +25 -0
  152. package/src/schema/desktop-https.schema.ts +43 -0
  153. package/src/schema/ft8.schema.ts +362 -0
  154. package/src/schema/hello.schema.ts +7 -0
  155. package/src/schema/logbook.schema.ts +310 -0
  156. package/src/schema/mode.schema.ts +158 -0
  157. package/src/schema/openwebrx.schema.ts +160 -0
  158. package/src/schema/operator.schema.ts +112 -0
  159. package/src/schema/plugin.schema.ts +503 -0
  160. package/src/schema/process-monitor.schema.ts +41 -0
  161. package/src/schema/pskreporter.schema.ts +102 -0
  162. package/src/schema/qso.schema.ts +173 -0
  163. package/src/schema/radio-capability.schema.ts +244 -0
  164. package/src/schema/radio-power-support.ts +107 -0
  165. package/src/schema/radio-power.schema.ts +101 -0
  166. package/src/schema/radio-profile.schema.ts +91 -0
  167. package/src/schema/radio.schema.ts +385 -0
  168. package/src/schema/realtime.schema.ts +262 -0
  169. package/src/schema/rigctld.schema.ts +51 -0
  170. package/src/schema/server-message-keys.ts +26 -0
  171. package/src/schema/slot-info.schema.ts +162 -0
  172. package/src/schema/spectrum.schema.ts +166 -0
  173. package/src/schema/station-info.schema.ts +40 -0
  174. package/src/schema/system.schema.ts +121 -0
  175. package/src/schema/transmission.schema.ts +105 -0
  176. package/src/schema/voice.schema.ts +28 -0
  177. package/src/schema/websocket.schema.ts +1480 -0
  178. package/src/utils/grid.ts +94 -0
  179. package/test/mode-schema.test.ts +48 -0
  180. package/tsconfig.json +9 -0
@@ -0,0 +1,91 @@
1
+ import { z } from 'zod';
2
+ import { HamlibConfigSchema } from './radio.schema.js';
3
+ import { AudioDeviceSettingsSchema } from './audio.schema.js';
4
+
5
+ /**
6
+ * Radio Profile Schema
7
+ *
8
+ * Profile 是电台+音频配置的一等公民,取代分散的 radio/audio 配置。
9
+ * 底层系统从 activeProfile 派生运行时配置。
10
+ */
11
+ export const RadioProfileSchema = z.object({
12
+ id: z.string(),
13
+ name: z.string(), // "IC-705 WiFi", "FT-991A 串口", "纯监听"
14
+ radio: HamlibConfigSchema, // 电台连接配置
15
+ audio: AudioDeviceSettingsSchema, // 音频设备配置
16
+ audioLockedToRadio: z.boolean(), // ICOM WLAN = true,音频由电台决定
17
+ createdAt: z.number(),
18
+ updatedAt: z.number(),
19
+ description: z.string().optional(),
20
+ });
21
+
22
+ export type RadioProfile = z.infer<typeof RadioProfileSchema>;
23
+
24
+ /**
25
+ * 创建 Profile 请求
26
+ */
27
+ export const CreateProfileRequestSchema = z.object({
28
+ name: z.string().min(1, 'Profile 名称不能为空'),
29
+ radio: HamlibConfigSchema,
30
+ audio: AudioDeviceSettingsSchema.optional(),
31
+ description: z.string().optional(),
32
+ });
33
+
34
+ export type CreateProfileRequest = z.infer<typeof CreateProfileRequestSchema>;
35
+
36
+ /**
37
+ * 更新 Profile 请求
38
+ */
39
+ export const UpdateProfileRequestSchema = z.object({
40
+ name: z.string().min(1).optional(),
41
+ radio: HamlibConfigSchema.optional(),
42
+ audio: AudioDeviceSettingsSchema.optional(),
43
+ audioLockedToRadio: z.boolean().optional(),
44
+ description: z.string().optional(),
45
+ });
46
+
47
+ export type UpdateProfileRequest = z.infer<typeof UpdateProfileRequestSchema>;
48
+
49
+ /**
50
+ * Profile 列表响应
51
+ */
52
+ export const ProfileListResponseSchema = z.object({
53
+ profiles: z.array(RadioProfileSchema),
54
+ activeProfileId: z.string().nullable(),
55
+ });
56
+
57
+ export type ProfileListResponse = z.infer<typeof ProfileListResponseSchema>;
58
+
59
+ /**
60
+ * Profile 操作响应
61
+ */
62
+ export const ProfileActionResponseSchema = z.object({
63
+ success: z.boolean(),
64
+ profile: RadioProfileSchema.optional(),
65
+ message: z.string().optional(),
66
+ });
67
+
68
+ export type ProfileActionResponse = z.infer<typeof ProfileActionResponseSchema>;
69
+
70
+ /**
71
+ * Profile 激活响应
72
+ */
73
+ export const ActivateProfileResponseSchema = z.object({
74
+ success: z.boolean(),
75
+ profile: RadioProfileSchema,
76
+ wasRunning: z.boolean(),
77
+ });
78
+
79
+ export type ActivateProfileResponse = z.infer<typeof ActivateProfileResponseSchema>;
80
+
81
+ /**
82
+ * Profile 变更事件数据
83
+ */
84
+ export const ProfileChangedEventSchema = z.object({
85
+ profileId: z.string(),
86
+ profile: RadioProfileSchema,
87
+ previousProfileId: z.string().nullable(),
88
+ wasRunning: z.boolean(),
89
+ });
90
+
91
+ export type ProfileChangedEvent = z.infer<typeof ProfileChangedEventSchema>;
@@ -0,0 +1,385 @@
1
+ import { z } from 'zod';
2
+
3
+ /**
4
+ * 预设频率Schema
5
+ */
6
+ export const PresetFrequencySchema = z.object({
7
+ band: z.string(),
8
+ mode: z.string(), // 协议模式,如 FT8, FT4
9
+ radioMode: z.string().optional(), // 电台调制模式,如 USB, LSB, AM, FM
10
+ frequency: z.number(),
11
+ description: z.string().optional(),
12
+ });
13
+
14
+ /**
15
+ * 频率列表响应Schema
16
+ */
17
+ export const FrequencyListResponseSchema = z.object({
18
+ success: z.boolean(),
19
+ presets: z.array(PresetFrequencySchema),
20
+ });
21
+
22
+ /**
23
+ * 串口配置参数Schema
24
+ */
25
+ export const SerialConfigSchema = z.object({
26
+ // 基础串口设置
27
+ data_bits: z.enum(['5', '6', '7', '8']).optional(),
28
+ stop_bits: z.enum(['1', '2']).optional(),
29
+ serial_parity: z.enum(['None', 'Even', 'Odd', 'Mark', 'Space']).optional(),
30
+ serial_handshake: z.enum(['None', 'Hardware', 'Software']).optional(),
31
+
32
+ // 控制信号
33
+ rts_state: z.enum(['ON', 'OFF', 'UNSET']).optional(),
34
+ dtr_state: z.enum(['ON', 'OFF', 'UNSET']).optional(),
35
+
36
+ // 通信设置
37
+ rate: z.number().int().min(150).max(4000000).optional(), // 波特率
38
+ timeout: z.number().int().min(0).optional(), // 超时时间(ms)
39
+ retry: z.number().int().min(0).optional(), // 重试次数
40
+
41
+ // 时序控制
42
+ write_delay: z.number().int().min(0).optional(), // 字节间延迟(ms)
43
+ post_write_delay: z.number().int().min(0).optional(), // 命令间延迟(ms)
44
+ });
45
+
46
+ export const HamlibBackendConfigSchema = z.record(z.string());
47
+
48
+ export const HamlibConfigFieldTypeSchema = z.enum([
49
+ 'string',
50
+ 'combo',
51
+ 'numeric',
52
+ 'checkbutton',
53
+ 'button',
54
+ 'binary',
55
+ 'int',
56
+ 'unknown',
57
+ ]);
58
+
59
+ export const HamlibConfigFieldSchema = z.object({
60
+ token: z.number().int(),
61
+ name: z.string(),
62
+ label: z.string(),
63
+ tooltip: z.string(),
64
+ defaultValue: z.string(),
65
+ effectiveDefaultValue: z.string().optional(),
66
+ effectiveDefaultSource: z.enum(['hamlib-schema', 'rig-caps']).optional(),
67
+ type: HamlibConfigFieldTypeSchema,
68
+ numeric: z.object({
69
+ min: z.number(),
70
+ max: z.number(),
71
+ step: z.number(),
72
+ }).optional(),
73
+ options: z.array(z.string()).optional(),
74
+ });
75
+
76
+ export const RigEndpointKindSchema = z.enum([
77
+ 'serial-port',
78
+ 'network-address',
79
+ 'device-path',
80
+ ]);
81
+
82
+ /**
83
+ * 网络 RigCtld 连接配置Schema
84
+ */
85
+ export const NetworkConfigSchema = z.object({
86
+ host: z.string(),
87
+ port: z.number().int().min(1).max(65535),
88
+ });
89
+
90
+ /**
91
+ * ICOM WLAN 连接配置Schema
92
+ */
93
+ export const IcomWlanConfigSchema = z.object({
94
+ ip: z.string(),
95
+ port: z.number().int().min(1).max(65535),
96
+ userName: z.string().optional(),
97
+ password: z.string().optional(),
98
+ /**
99
+ * 数据模式(Data Mode)
100
+ * 启用时使用 USB-D 等数字模式,适用于 FT8/FT4 等数字通信
101
+ * 默认值: true
102
+ */
103
+ dataMode: z.boolean().optional().default(true),
104
+ });
105
+
106
+ /**
107
+ * 串口连接配置Schema
108
+ */
109
+ export const SerialConnectionConfigSchema = z.object({
110
+ path: z.string(),
111
+ rigModel: z.number().int(),
112
+ serialConfig: SerialConfigSchema.optional(),
113
+ backendConfig: HamlibBackendConfigSchema.optional(),
114
+ });
115
+
116
+ export const HamlibSpectrumConfigSchema = z.object({
117
+ speed: z.number().int().min(0).max(255).optional(),
118
+ });
119
+
120
+ /**
121
+ * PTT (Push-to-Talk) 方法Schema
122
+ *
123
+ * - cat: 通过 CAT 命令控制 PTT(Hamlib RIG 类型,推荐)
124
+ * - vox: 不主动控制 PTT,电台通过检测音频信号自动发射(适用于 SignaLink USB 等)
125
+ * - dtr: 通过 RS-232 DTR 引脚控制 PTT(适用于古老电台或外部功放)
126
+ * - rts: 通过 RS-232 RTS 引脚控制 PTT(适用于古老电台或外部功放)
127
+ */
128
+ export const PttMethodSchema = z.enum(['cat', 'vox', 'dtr', 'rts']);
129
+
130
+ /**
131
+ * Hamlib配置Schema - 嵌套对象结构
132
+ *
133
+ * 设计理念:
134
+ * - type: 当前使用的连接类型
135
+ * - network/icomWlan/serial: 各连接类型的独立配置对象
136
+ * - 所有配置对象共存,切换连接类型时保留历史配置
137
+ * - 根据 type 字段读取对应的配置对象
138
+ */
139
+ export const HamlibConfigSchema = z.object({
140
+ type: z.enum(['none', 'network', 'serial', 'icom-wlan']),
141
+
142
+ // 网络模式配置
143
+ network: NetworkConfigSchema.optional(),
144
+
145
+ // ICOM WLAN 模式配置
146
+ icomWlan: IcomWlanConfigSchema.optional(),
147
+
148
+ // 串口模式配置
149
+ serial: SerialConnectionConfigSchema.optional(),
150
+
151
+ // Hamlib 频谱配置(当前仅用于官方频谱流 speed)
152
+ spectrum: HamlibSpectrumConfigSchema.optional(),
153
+
154
+ // 发射时序补偿(毫秒)- 用于补偿电台和网络的处理延迟
155
+ // 正值表示提前发射,负值表示延后发射
156
+ // 范围限制:-1000~1000ms,适用于各种网络和设备延迟场景
157
+ transmitCompensationMs: z.number().int().min(-1000).max(1000).optional(),
158
+
159
+ // PTT 方法(默认 'cat',即 Hamlib RIG 类型)
160
+ // 仅对 network 和 serial 连接类型有效,icom-wlan 固定使用 CI-V PTT
161
+ pttMethod: PttMethodSchema.optional(),
162
+
163
+ // PTT 独立串口路径(仅当 pttMethod 为 dtr/rts 时有效)
164
+ // 留空则复用 CAT 同一串口
165
+ pttPort: z.string().optional(),
166
+ });
167
+
168
+ /**
169
+ * 电台配置响应Schema
170
+ */
171
+ export const RadioConfigResponseSchema = z.object({
172
+ success: z.boolean(),
173
+ config: HamlibConfigSchema,
174
+ });
175
+
176
+ /**
177
+ * 支持的电台型号Schema
178
+ */
179
+ export const SupportedRigSchema = z.object({
180
+ rigModel: z.number(),
181
+ mfgName: z.string(),
182
+ modelName: z.string(),
183
+ });
184
+
185
+ /**
186
+ * 支持的电台列表响应Schema
187
+ */
188
+ export const SupportedRigsResponseSchema = z.object({
189
+ rigs: z.array(SupportedRigSchema),
190
+ });
191
+
192
+ export const RigConfigSchemaResponseSchema = z.object({
193
+ rigModel: z.number().int(),
194
+ portType: z.string(),
195
+ endpointKind: RigEndpointKindSchema,
196
+ fields: z.array(HamlibConfigFieldSchema),
197
+ });
198
+
199
+ /**
200
+ * 电台信息Schema
201
+ * 用于描述当前连接的电台的详细信息
202
+ */
203
+ export const RadioInfoSchema = z.object({
204
+ /** 制造商名称,如 "Yaesu", "ICOM", "Network" */
205
+ manufacturer: z.string(),
206
+ /** 型号名称,如 "FT-991A", "IC-705", "RigCtrl" */
207
+ model: z.string(),
208
+ /** Hamlib 电台型号 ID (serial/network 模式使用,icom-wlan 模式可选) */
209
+ rigModel: z.number().optional(),
210
+ /** 连接类型 */
211
+ connectionType: z.enum(['serial', 'network', 'icom-wlan']),
212
+ /** 固件版本 (如果可获取) */
213
+ firmwareVersion: z.string().optional(),
214
+ /** 序列号 (如果可获取) */
215
+ serialNumber: z.string().optional(),
216
+ });
217
+
218
+ /**
219
+ * 串口信息Schema
220
+ */
221
+ export const SerialPortSchema = z.object({
222
+ path: z.string(),
223
+ manufacturer: z.string().optional(),
224
+ serialNumber: z.string().optional(),
225
+ pnpId: z.string().optional(),
226
+ locationId: z.string().optional(),
227
+ productId: z.string().optional(),
228
+ vendorId: z.string().optional(),
229
+ });
230
+
231
+ /**
232
+ * 串口列表响应Schema
233
+ */
234
+ export const SerialPortsResponseSchema = z.object({
235
+ ports: z.array(SerialPortSchema),
236
+ });
237
+
238
+ /**
239
+ * 测试响应Schema
240
+ */
241
+ export const TestResponseSchema = z.object({
242
+ success: z.boolean(),
243
+ message: z.string().optional(),
244
+ });
245
+
246
+ /**
247
+ * 天调能力Schema
248
+ * 描述电台的天线调谐器功能支持情况
249
+ */
250
+ export const TunerCapabilitiesSchema = z.object({
251
+ /** 是否支持天调功能 */
252
+ supported: z.boolean(),
253
+ /** 是否支持开关控制 */
254
+ hasSwitch: z.boolean(),
255
+ /** 是否支持手动调谐 */
256
+ hasManualTune: z.boolean(),
257
+ });
258
+
259
+ /**
260
+ * 天调状态Schema
261
+ * 描述天线调谐器的当前状态
262
+ */
263
+ export const TunerStatusSchema = z.object({
264
+ /** 天调是否已启用 */
265
+ enabled: z.boolean(),
266
+ /** 是否正在调谐中 */
267
+ active: z.boolean(),
268
+ /** 驻波比 (SWR) 值 */
269
+ swr: z.number().optional(),
270
+ /** 调谐状态 */
271
+ status: z.enum(['idle', 'tuning', 'success', 'failed']).optional(),
272
+ });
273
+
274
+ /**
275
+ * 天调能力响应Schema
276
+ */
277
+ export const TunerCapabilitiesResponseSchema = z.object({
278
+ success: z.boolean(),
279
+ capabilities: TunerCapabilitiesSchema,
280
+ });
281
+
282
+ /**
283
+ * 天调状态响应Schema
284
+ */
285
+ export const TunerStatusResponseSchema = z.object({
286
+ success: z.boolean(),
287
+ status: TunerStatusSchema,
288
+ });
289
+
290
+ /**
291
+ * 电台连接状态枚举
292
+ * 精细化的连接状态,贯穿 server → contracts → web
293
+ */
294
+ export enum RadioConnectionStatus {
295
+ /** 未配置电台 (type=none) */
296
+ NOT_CONFIGURED = 'not_configured',
297
+ /** 已断开 (type!=none, 但未连接/初始状态) */
298
+ DISCONNECTED = 'disconnected',
299
+ /** 连接中 */
300
+ CONNECTING = 'connecting',
301
+ /** 已连接 */
302
+ CONNECTED = 'connected',
303
+ /** 自动重连中(运行中断线后自动重连) */
304
+ RECONNECTING = 'reconnecting',
305
+ /** 连接丢失(重连耗尽或运行中断连后停止重连) */
306
+ CONNECTION_LOST = 'connection_lost',
307
+ }
308
+
309
+ /**
310
+ * 重连进度信息
311
+ */
312
+ export const ReconnectProgressSchema = z.object({
313
+ attempt: z.number(),
314
+ maxAttempts: z.number(),
315
+ nextRetryMs: z.number().optional(),
316
+ });
317
+ export type ReconnectProgress = z.infer<typeof ReconnectProgressSchema>;
318
+
319
+ export const RadioConnectionStatusSchema = z.nativeEnum(RadioConnectionStatus);
320
+
321
+ /**
322
+ * 核心电台能力
323
+ * 用于描述主流程是否仍可继续使用某项核心读写能力。
324
+ *
325
+ * 语义:
326
+ * - true: 当前连接仍可继续尝试该能力(已确认支持,或尚未确认不支持)
327
+ * - false: 已明确确认当前电台/连接不支持该能力,后续不再重复访问底层
328
+ */
329
+ export const CoreRadioCapabilitiesSchema = z.object({
330
+ readFrequency: z.boolean(),
331
+ writeFrequency: z.boolean(),
332
+ readRadioMode: z.boolean(),
333
+ writeRadioMode: z.boolean(),
334
+ });
335
+
336
+ export const CoreCapabilityDiagnosticSchema = z.object({
337
+ capability: z.enum(['readFrequency', 'writeFrequency', 'readRadioMode', 'writeRadioMode']),
338
+ message: z.string(),
339
+ stack: z.string(),
340
+ recordedAt: z.number(),
341
+ });
342
+
343
+ export const CoreCapabilityDiagnosticsSchema = z.object({
344
+ readFrequency: CoreCapabilityDiagnosticSchema.optional(),
345
+ writeFrequency: CoreCapabilityDiagnosticSchema.optional(),
346
+ readRadioMode: CoreCapabilityDiagnosticSchema.optional(),
347
+ writeRadioMode: CoreCapabilityDiagnosticSchema.optional(),
348
+ });
349
+
350
+ /**
351
+ * 自定义频率预设设置Schema
352
+ */
353
+ export const CustomFrequencyPresetsSchema = z.object({
354
+ presets: z.array(PresetFrequencySchema).min(1),
355
+ });
356
+
357
+ // 导出类型
358
+ export type CustomFrequencyPresets = z.infer<typeof CustomFrequencyPresetsSchema>;
359
+ export type PresetFrequency = z.infer<typeof PresetFrequencySchema>;
360
+ export type FrequencyListResponse = z.infer<typeof FrequencyListResponseSchema>;
361
+ export type SerialConfig = z.infer<typeof SerialConfigSchema>;
362
+ export type HamlibBackendConfig = z.infer<typeof HamlibBackendConfigSchema>;
363
+ export type HamlibConfigFieldType = z.infer<typeof HamlibConfigFieldTypeSchema>;
364
+ export type HamlibConfigField = z.infer<typeof HamlibConfigFieldSchema>;
365
+ export type NetworkConfig = z.infer<typeof NetworkConfigSchema>;
366
+ export type IcomWlanConfig = z.infer<typeof IcomWlanConfigSchema>;
367
+ export type SerialConnectionConfig = z.infer<typeof SerialConnectionConfigSchema>;
368
+ export type HamlibSpectrumConfig = z.infer<typeof HamlibSpectrumConfigSchema>;
369
+ export type PttMethod = z.infer<typeof PttMethodSchema>;
370
+ export type HamlibConfig = z.infer<typeof HamlibConfigSchema>;
371
+ export type RadioConfigResponse = z.infer<typeof RadioConfigResponseSchema>;
372
+ export type SupportedRig = z.infer<typeof SupportedRigSchema>;
373
+ export type SupportedRigsResponse = z.infer<typeof SupportedRigsResponseSchema>;
374
+ export type RigConfigSchemaResponse = z.infer<typeof RigConfigSchemaResponseSchema>;
375
+ export type RadioInfo = z.infer<typeof RadioInfoSchema>;
376
+ export type SerialPort = z.infer<typeof SerialPortSchema>;
377
+ export type SerialPortsResponse = z.infer<typeof SerialPortsResponseSchema>;
378
+ export type TestResponse = z.infer<typeof TestResponseSchema>;
379
+ export type TunerCapabilities = z.infer<typeof TunerCapabilitiesSchema>;
380
+ export type TunerStatus = z.infer<typeof TunerStatusSchema>;
381
+ export type TunerCapabilitiesResponse = z.infer<typeof TunerCapabilitiesResponseSchema>;
382
+ export type TunerStatusResponse = z.infer<typeof TunerStatusResponseSchema>;
383
+ export type CoreRadioCapabilities = z.infer<typeof CoreRadioCapabilitiesSchema>;
384
+ export type CoreCapabilityDiagnostic = z.infer<typeof CoreCapabilityDiagnosticSchema>;
385
+ export type CoreCapabilityDiagnostics = z.infer<typeof CoreCapabilityDiagnosticsSchema>;