@tx5dr/contracts 1.7.3 → 1.7.4
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.
- package/dist/index.d.ts +4 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +6 -0
- package/dist/index.js.map +1 -1
- package/dist/schema/__tests__/ability.test.d.ts +2 -0
- package/dist/schema/__tests__/ability.test.d.ts.map +1 -0
- package/dist/schema/__tests__/ability.test.js +32 -0
- package/dist/schema/__tests__/ability.test.js.map +1 -0
- package/dist/schema/__tests__/cw-decoder.schema.test.d.ts +2 -0
- package/dist/schema/__tests__/cw-decoder.schema.test.d.ts.map +1 -0
- package/dist/schema/__tests__/cw-decoder.schema.test.js +114 -0
- package/dist/schema/__tests__/cw-decoder.schema.test.js.map +1 -0
- package/dist/schema/__tests__/device-ui.schema.test.d.ts +2 -0
- package/dist/schema/__tests__/device-ui.schema.test.d.ts.map +1 -0
- package/dist/schema/__tests__/device-ui.schema.test.js +111 -0
- package/dist/schema/__tests__/device-ui.schema.test.js.map +1 -0
- package/dist/schema/__tests__/process-monitor.schema.test.js +96 -0
- package/dist/schema/__tests__/process-monitor.schema.test.js.map +1 -1
- package/dist/schema/__tests__/radio.schema.test.d.ts +2 -0
- package/dist/schema/__tests__/radio.schema.test.d.ts.map +1 -0
- package/dist/schema/__tests__/radio.schema.test.js +143 -0
- package/dist/schema/__tests__/radio.schema.test.js.map +1 -0
- package/dist/schema/ability.d.ts +3 -1
- package/dist/schema/ability.d.ts.map +1 -1
- package/dist/schema/ability.js +11 -0
- package/dist/schema/ability.js.map +1 -1
- package/dist/schema/api-response.schema.d.ts +168 -1
- package/dist/schema/api-response.schema.d.ts.map +1 -1
- package/dist/schema/api-response.schema.js +22 -0
- package/dist/schema/api-response.schema.js.map +1 -1
- package/dist/schema/cpu-profile.schema.d.ts +6 -6
- package/dist/schema/cw-decoder.schema.d.ts +2501 -0
- package/dist/schema/cw-decoder.schema.d.ts.map +1 -0
- package/dist/schema/cw-decoder.schema.js +196 -0
- package/dist/schema/cw-decoder.schema.js.map +1 -0
- package/dist/schema/cw-keyer.schema.d.ts +368 -0
- package/dist/schema/cw-keyer.schema.d.ts.map +1 -0
- package/dist/schema/cw-keyer.schema.js +143 -0
- package/dist/schema/cw-keyer.schema.js.map +1 -0
- package/dist/schema/desktop-https.schema.js +1 -1
- package/dist/schema/desktop-https.schema.js.map +1 -1
- package/dist/schema/device-ui.schema.d.ts +1782 -0
- package/dist/schema/device-ui.schema.d.ts.map +1 -0
- package/dist/schema/device-ui.schema.js +156 -0
- package/dist/schema/device-ui.schema.js.map +1 -0
- package/dist/schema/mode.schema.d.ts +1 -0
- package/dist/schema/mode.schema.d.ts.map +1 -1
- package/dist/schema/mode.schema.js +8 -0
- package/dist/schema/mode.schema.js.map +1 -1
- package/dist/schema/plugin.schema.d.ts +637 -54
- package/dist/schema/plugin.schema.d.ts.map +1 -1
- package/dist/schema/plugin.schema.js +22 -2
- package/dist/schema/plugin.schema.js.map +1 -1
- package/dist/schema/process-monitor.schema.d.ts +1948 -261
- package/dist/schema/process-monitor.schema.d.ts.map +1 -1
- package/dist/schema/process-monitor.schema.js +11 -0
- package/dist/schema/process-monitor.schema.js.map +1 -1
- package/dist/schema/radio-capability.schema.d.ts +1 -1
- package/dist/schema/radio-capability.schema.d.ts.map +1 -1
- package/dist/schema/radio-capability.schema.js +41 -0
- package/dist/schema/radio-capability.schema.js.map +1 -1
- package/dist/schema/radio-power.schema.d.ts +6 -0
- package/dist/schema/radio-power.schema.d.ts.map +1 -1
- package/dist/schema/radio-profile.schema.d.ts +86 -0
- package/dist/schema/radio-profile.schema.d.ts.map +1 -1
- package/dist/schema/radio.schema.d.ts +160 -3
- package/dist/schema/radio.schema.d.ts.map +1 -1
- package/dist/schema/radio.schema.js +82 -0
- package/dist/schema/radio.schema.js.map +1 -1
- package/dist/schema/realtime.schema.d.ts +6 -6
- package/dist/schema/voice.schema.d.ts +1 -1
- package/dist/schema/voice.schema.d.ts.map +1 -1
- package/dist/schema/voice.schema.js +1 -1
- package/dist/schema/voice.schema.js.map +1 -1
- package/dist/schema/websocket.schema.d.ts +5615 -412
- package/dist/schema/websocket.schema.d.ts.map +1 -1
- package/dist/schema/websocket.schema.js +102 -2
- package/dist/schema/websocket.schema.js.map +1 -1
- package/dist/utils/__tests__/cwTiming.test.d.ts +2 -0
- package/dist/utils/__tests__/cwTiming.test.d.ts.map +1 -0
- package/dist/utils/__tests__/cwTiming.test.js +74 -0
- package/dist/utils/__tests__/cwTiming.test.js.map +1 -0
- package/dist/utils/cwTiming.d.ts +36 -0
- package/dist/utils/cwTiming.d.ts.map +1 -0
- package/dist/utils/cwTiming.js +155 -0
- package/dist/utils/cwTiming.js.map +1 -0
- package/package.json +1 -1
- package/src/index.ts +8 -0
- package/src/schema/__tests__/ability.test.ts +40 -0
- package/src/schema/__tests__/cw-decoder.schema.test.ts +127 -0
- package/src/schema/__tests__/device-ui.schema.test.ts +122 -0
- package/src/schema/__tests__/process-monitor.schema.test.ts +99 -0
- package/src/schema/__tests__/radio.schema.test.ts +160 -0
- package/src/schema/ability.ts +13 -0
- package/src/schema/api-response.schema.ts +22 -0
- package/src/schema/cw-decoder.schema.ts +234 -0
- package/src/schema/cw-keyer.schema.ts +177 -0
- package/src/schema/desktop-https.schema.ts +1 -1
- package/src/schema/device-ui.schema.ts +182 -0
- package/src/schema/mode.schema.ts +8 -0
- package/src/schema/plugin.schema.ts +28 -2
- package/src/schema/process-monitor.schema.ts +18 -0
- package/src/schema/radio-capability.schema.ts +41 -0
- package/src/schema/radio.schema.ts +97 -0
- package/src/schema/voice.schema.ts +1 -1
- package/src/schema/websocket.schema.ts +131 -2
- package/src/utils/__tests__/cwTiming.test.ts +91 -0
- package/src/utils/cwTiming.ts +203 -0
|
@@ -0,0 +1,182 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
|
|
3
|
+
export const DEVICE_UI_JWT_TYPE = 'device-ui' as const;
|
|
4
|
+
export const DEVICE_UI_JWT_AUDIENCE = 'tx5dr-device-ui' as const;
|
|
5
|
+
|
|
6
|
+
export const DeviceUiJwtPayloadSchema = z.object({
|
|
7
|
+
typ: z.literal(DEVICE_UI_JWT_TYPE),
|
|
8
|
+
aud: z.literal(DEVICE_UI_JWT_AUDIENCE),
|
|
9
|
+
deviceId: z.string().min(1),
|
|
10
|
+
sessionId: z.string().min(1),
|
|
11
|
+
iat: z.number().int().nonnegative(),
|
|
12
|
+
exp: z.number().int().positive(),
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
export type DeviceUiJwtPayload = z.infer<typeof DeviceUiJwtPayloadSchema>;
|
|
16
|
+
|
|
17
|
+
export const DeviceUiSessionRequestSchema = z.object({
|
|
18
|
+
deviceId: z.string().trim().min(1).max(128),
|
|
19
|
+
sessionToken: z.string().min(1),
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
export type DeviceUiSessionRequest = z.infer<typeof DeviceUiSessionRequestSchema>;
|
|
23
|
+
|
|
24
|
+
export const DeviceUiSessionResponseSchema = z.object({
|
|
25
|
+
jwt: z.string().min(1),
|
|
26
|
+
deviceId: z.string().min(1),
|
|
27
|
+
sessionId: z.string().min(1),
|
|
28
|
+
expiresAt: z.number().int().positive(),
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
export type DeviceUiSessionResponse = z.infer<typeof DeviceUiSessionResponseSchema>;
|
|
32
|
+
|
|
33
|
+
export const DeviceUiAuthSessionStateSchema = z.object({
|
|
34
|
+
sessionId: z.string().min(1),
|
|
35
|
+
deviceId: z.string().min(1),
|
|
36
|
+
createdAt: z.number().int().nonnegative(),
|
|
37
|
+
expiresAt: z.number().int().positive(),
|
|
38
|
+
lastVerifiedAt: z.number().int().nonnegative().optional(),
|
|
39
|
+
revoked: z.boolean().optional(),
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
export type DeviceUiAuthSessionState = z.infer<typeof DeviceUiAuthSessionStateSchema>;
|
|
43
|
+
|
|
44
|
+
export const DeviceUiAuthStateSchema = z.object({
|
|
45
|
+
jwtSecret: z.string().min(32),
|
|
46
|
+
sessions: z.array(DeviceUiAuthSessionStateSchema).default([]),
|
|
47
|
+
updatedAt: z.number().int().nonnegative().optional(),
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
export type DeviceUiAuthState = z.infer<typeof DeviceUiAuthStateSchema>;
|
|
51
|
+
|
|
52
|
+
const NullableStringSchema = z.string().nullable();
|
|
53
|
+
const NullableNumberSchema = z.number().nullable();
|
|
54
|
+
|
|
55
|
+
export const DeviceUiFrameSnapshotSchema = z.object({
|
|
56
|
+
slotId: NullableStringSchema.optional(),
|
|
57
|
+
slotStartMs: NullableNumberSchema.optional(),
|
|
58
|
+
snr: NullableNumberSchema,
|
|
59
|
+
freq: NullableNumberSchema,
|
|
60
|
+
dt: NullableNumberSchema,
|
|
61
|
+
message: z.string(),
|
|
62
|
+
operatorId: NullableStringSchema,
|
|
63
|
+
country: NullableStringSchema.optional(),
|
|
64
|
+
countryZh: NullableStringSchema.optional(),
|
|
65
|
+
countryEn: NullableStringSchema.optional(),
|
|
66
|
+
countryCode: NullableStringSchema.optional(),
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
export const DeviceUiCurrentTxSnapshotSchema = z.object({
|
|
70
|
+
active: z.boolean(),
|
|
71
|
+
operatorIds: z.array(z.string()),
|
|
72
|
+
messages: z.array(z.string()),
|
|
73
|
+
lastMessage: NullableStringSchema,
|
|
74
|
+
slotStartMs: NullableNumberSchema,
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
export const DeviceUiOperatorSnapshotSchema = z.object({
|
|
78
|
+
id: z.string(),
|
|
79
|
+
callsign: z.string(),
|
|
80
|
+
active: z.boolean(),
|
|
81
|
+
transmitting: z.boolean(),
|
|
82
|
+
ptt: z.boolean(),
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
export const DeviceUiCwSnapshotSchema = z.object({
|
|
86
|
+
decoder: z.object({
|
|
87
|
+
enabled: z.boolean(),
|
|
88
|
+
active: z.boolean(),
|
|
89
|
+
state: z.string(),
|
|
90
|
+
muted: z.boolean(),
|
|
91
|
+
pendingText: z.string(),
|
|
92
|
+
committedText: z.string(),
|
|
93
|
+
lastDecodeAt: NullableNumberSchema,
|
|
94
|
+
updatedAt: z.number().int().nonnegative(),
|
|
95
|
+
}),
|
|
96
|
+
keyer: z.object({
|
|
97
|
+
active: z.boolean(),
|
|
98
|
+
mode: NullableStringSchema,
|
|
99
|
+
messageId: NullableStringSchema,
|
|
100
|
+
currentText: NullableStringSchema,
|
|
101
|
+
lastText: NullableStringSchema,
|
|
102
|
+
}),
|
|
103
|
+
currentTx: z.object({
|
|
104
|
+
active: z.boolean(),
|
|
105
|
+
messages: z.array(z.string()),
|
|
106
|
+
lastMessage: NullableStringSchema,
|
|
107
|
+
}),
|
|
108
|
+
});
|
|
109
|
+
|
|
110
|
+
export const DeviceUiBootstrapSnapshotSchema = z.object({
|
|
111
|
+
server: z.object({
|
|
112
|
+
status: z.literal('ok'),
|
|
113
|
+
version: z.string(),
|
|
114
|
+
webPort: NullableNumberSchema,
|
|
115
|
+
}),
|
|
116
|
+
station: z.object({
|
|
117
|
+
callsign: NullableStringSchema,
|
|
118
|
+
callsigns: z.array(z.string()).default([]),
|
|
119
|
+
}),
|
|
120
|
+
operators: z.array(DeviceUiOperatorSnapshotSchema).default([]),
|
|
121
|
+
engine: z.object({
|
|
122
|
+
running: z.boolean(),
|
|
123
|
+
mode: NullableStringSchema,
|
|
124
|
+
currentMode: z.object({
|
|
125
|
+
name: z.string(),
|
|
126
|
+
slotMs: z.number().nonnegative().optional(),
|
|
127
|
+
}).nullable(),
|
|
128
|
+
state: NullableStringSchema,
|
|
129
|
+
}),
|
|
130
|
+
radio: z.object({
|
|
131
|
+
connected: z.boolean(),
|
|
132
|
+
frequency: NullableNumberSchema,
|
|
133
|
+
radioMode: NullableStringSchema,
|
|
134
|
+
ptt: z.boolean(),
|
|
135
|
+
tx: z.boolean(),
|
|
136
|
+
}),
|
|
137
|
+
ft8: z.object({
|
|
138
|
+
slot: z.object({
|
|
139
|
+
id: z.string(),
|
|
140
|
+
startMs: z.number(),
|
|
141
|
+
phaseMs: z.number(),
|
|
142
|
+
driftMs: z.number().optional(),
|
|
143
|
+
cycleNumber: z.number(),
|
|
144
|
+
utcSeconds: z.number(),
|
|
145
|
+
mode: z.string(),
|
|
146
|
+
}).nullable(),
|
|
147
|
+
utc: NullableNumberSchema,
|
|
148
|
+
cycle: NullableNumberSchema,
|
|
149
|
+
periodMs: NullableNumberSchema,
|
|
150
|
+
recentDecodeRawMessages: z.array(z.string()),
|
|
151
|
+
lastDecodeRawMessage: NullableStringSchema,
|
|
152
|
+
recentFramesSlotId: NullableStringSchema,
|
|
153
|
+
recentFramesSlotStartMs: NullableNumberSchema,
|
|
154
|
+
recentFrames: z.array(DeviceUiFrameSnapshotSchema),
|
|
155
|
+
currentTx: DeviceUiCurrentTxSnapshotSchema,
|
|
156
|
+
}),
|
|
157
|
+
voice: z.object({
|
|
158
|
+
active: z.boolean(),
|
|
159
|
+
radioMode: NullableStringSchema,
|
|
160
|
+
pttLocked: z.boolean(),
|
|
161
|
+
pttLockedByLabel: NullableStringSchema,
|
|
162
|
+
keyerActive: z.boolean(),
|
|
163
|
+
keyerMode: NullableStringSchema,
|
|
164
|
+
keyerSlotId: NullableStringSchema,
|
|
165
|
+
}),
|
|
166
|
+
cw: DeviceUiCwSnapshotSchema,
|
|
167
|
+
access: z.object({
|
|
168
|
+
localUrl: NullableStringSchema,
|
|
169
|
+
localUrls: z.array(z.string()),
|
|
170
|
+
}),
|
|
171
|
+
updatedAt: z.number().int().nonnegative(),
|
|
172
|
+
});
|
|
173
|
+
|
|
174
|
+
export type DeviceUiBootstrapSnapshot = z.infer<typeof DeviceUiBootstrapSnapshotSchema>;
|
|
175
|
+
|
|
176
|
+
export const DeviceUiWsEventSchema = z.object({
|
|
177
|
+
type: z.literal('snapshot'),
|
|
178
|
+
payload: DeviceUiBootstrapSnapshotSchema,
|
|
179
|
+
timestamp: z.string(),
|
|
180
|
+
});
|
|
181
|
+
|
|
182
|
+
export type DeviceUiWsEvent = z.infer<typeof DeviceUiWsEventSchema>;
|
|
@@ -63,6 +63,14 @@ export const MODES = {
|
|
|
63
63
|
transmitTiming: 0,
|
|
64
64
|
encodeAdvance: 0,
|
|
65
65
|
} as ModeDescriptor,
|
|
66
|
+
CW: {
|
|
67
|
+
name: 'CW',
|
|
68
|
+
slotMs: 0, // CW 模式无时隙概念
|
|
69
|
+
toleranceMs: 0,
|
|
70
|
+
windowTiming: [], // 无解码窗口
|
|
71
|
+
transmitTiming: 0,
|
|
72
|
+
encodeAdvance: 0,
|
|
73
|
+
} as ModeDescriptor,
|
|
66
74
|
} as const;
|
|
67
75
|
|
|
68
76
|
/**
|
|
@@ -73,7 +73,7 @@ export type PluginPanelComponent = z.infer<typeof PluginPanelComponentSchema>;
|
|
|
73
73
|
* These values control both validation expectations and default frontend
|
|
74
74
|
* rendering in plugin settings UIs.
|
|
75
75
|
*/
|
|
76
|
-
export const PluginSettingTypeSchema = z.enum(['boolean', 'number', 'string', 'string[]', 'object[]', 'info']);
|
|
76
|
+
export const PluginSettingTypeSchema = z.enum(['boolean', 'number', 'string', 'string[]', 'object[]', 'keyedStringArrays', 'info']);
|
|
77
77
|
|
|
78
78
|
/**
|
|
79
79
|
* Supported generated-form field types for plugin settings.
|
|
@@ -103,6 +103,26 @@ export const PluginObjectArrayFieldSchema = z.object({
|
|
|
103
103
|
});
|
|
104
104
|
export type PluginObjectArrayField = z.infer<typeof PluginObjectArrayFieldSchema>;
|
|
105
105
|
|
|
106
|
+
export const PluginKeyedStringArrayKeySchema = z.object({
|
|
107
|
+
key: z.string(),
|
|
108
|
+
label: z.string(),
|
|
109
|
+
description: z.string().optional(),
|
|
110
|
+
});
|
|
111
|
+
export type PluginKeyedStringArrayKey = z.infer<typeof PluginKeyedStringArrayKeySchema>;
|
|
112
|
+
|
|
113
|
+
export const PluginSettingConditionSchema = z.object({
|
|
114
|
+
setting: z.string(),
|
|
115
|
+
equals: z.unknown().optional(),
|
|
116
|
+
notEquals: z.unknown().optional(),
|
|
117
|
+
});
|
|
118
|
+
export type PluginSettingCondition = z.infer<typeof PluginSettingConditionSchema>;
|
|
119
|
+
|
|
120
|
+
export const PluginSettingConditionalDescriptionSchema = z.object({
|
|
121
|
+
when: PluginSettingConditionSchema,
|
|
122
|
+
description: z.string(),
|
|
123
|
+
});
|
|
124
|
+
export type PluginSettingConditionalDescription = z.infer<typeof PluginSettingConditionalDescriptionSchema>;
|
|
125
|
+
|
|
106
126
|
/**
|
|
107
127
|
* Persistence and UI scope for a plugin setting.
|
|
108
128
|
*
|
|
@@ -134,6 +154,12 @@ export const PluginSettingDescriptorSchema = z.object({
|
|
|
134
154
|
options: z.array(PluginSettingOptionSchema).optional(),
|
|
135
155
|
/** Field schema used by generated editors for `object[]` settings. */
|
|
136
156
|
itemFields: z.array(PluginObjectArrayFieldSchema).optional(),
|
|
157
|
+
/** Fixed key list used by generated editors for `keyedStringArrays` settings. */
|
|
158
|
+
keys: z.array(PluginKeyedStringArrayKeySchema).optional(),
|
|
159
|
+
/** Conditionally show the field based on another setting in the same form. */
|
|
160
|
+
visibleWhen: PluginSettingConditionSchema.optional(),
|
|
161
|
+
/** Conditionally override the field description based on another setting. */
|
|
162
|
+
descriptionWhen: z.array(PluginSettingConditionalDescriptionSchema).optional(),
|
|
137
163
|
/** Internal settings are persisted/injected but hidden from generated UIs. */
|
|
138
164
|
hidden: z.boolean().optional(),
|
|
139
165
|
/** 设置作用域:global(所有操作员共享)或 operator(每操作员独立),默认 global */
|
|
@@ -212,7 +238,7 @@ export type PluginCapability = z.infer<typeof PluginCapabilitySchema>;
|
|
|
212
238
|
* - `voice-left-top`: shown above the voice frequency control card.
|
|
213
239
|
* - `voice-right-top`: shown in the tabbed top area of the voice right panel.
|
|
214
240
|
*/
|
|
215
|
-
export const PluginPanelSlotSchema = z.enum(['operator', 'automation', 'main-right', 'voice-left-top', 'voice-right-top']);
|
|
241
|
+
export const PluginPanelSlotSchema = z.enum(['operator', 'automation', 'main-right', 'voice-left-top', 'voice-right-top', 'cw-right-top']);
|
|
216
242
|
|
|
217
243
|
/**
|
|
218
244
|
* Rendering slot that determines where a panel appears in the UI.
|
|
@@ -74,6 +74,19 @@ export const DecodeWorkerTelemetrySnapshotSchema = z.object({
|
|
|
74
74
|
workers: z.array(DecodeWorkerTelemetryWorkerSchema),
|
|
75
75
|
});
|
|
76
76
|
|
|
77
|
+
export const WorkerPoolTelemetryWorkerSchema = DecodeWorkerTelemetryWorkerSchema;
|
|
78
|
+
export const WorkerPoolTelemetrySummarySchema = DecodeWorkerTelemetrySummarySchema;
|
|
79
|
+
|
|
80
|
+
export const WorkerPoolTelemetrySnapshotSchema = z.object({
|
|
81
|
+
id: z.string().min(1),
|
|
82
|
+
name: z.string().min(1),
|
|
83
|
+
kind: z.string().min(1),
|
|
84
|
+
summary: WorkerPoolTelemetrySummarySchema,
|
|
85
|
+
workers: z.array(WorkerPoolTelemetryWorkerSchema),
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
export const WorkerPoolTelemetryListSchema = z.array(WorkerPoolTelemetrySnapshotSchema);
|
|
89
|
+
|
|
77
90
|
export const ProcessSnapshotSchema = z.object({
|
|
78
91
|
timestamp: z.number(),
|
|
79
92
|
uptimeSeconds: z.number(),
|
|
@@ -82,6 +95,7 @@ export const ProcessSnapshotSchema = z.object({
|
|
|
82
95
|
hostCpu: HostCpuSchema.optional(),
|
|
83
96
|
eventLoop: EventLoopDelaySchema,
|
|
84
97
|
decodeWorkers: DecodeWorkerTelemetrySnapshotSchema.optional(),
|
|
98
|
+
workerPools: WorkerPoolTelemetryListSchema.optional(),
|
|
85
99
|
});
|
|
86
100
|
|
|
87
101
|
export const ProcessSnapshotHistorySchema = z.object({
|
|
@@ -98,5 +112,9 @@ export type DecodeWorkerCurrentJob = z.infer<typeof DecodeWorkerCurrentJobSchema
|
|
|
98
112
|
export type DecodeWorkerTelemetryWorker = z.infer<typeof DecodeWorkerTelemetryWorkerSchema>;
|
|
99
113
|
export type DecodeWorkerTelemetrySummary = z.infer<typeof DecodeWorkerTelemetrySummarySchema>;
|
|
100
114
|
export type DecodeWorkerTelemetrySnapshot = z.infer<typeof DecodeWorkerTelemetrySnapshotSchema>;
|
|
115
|
+
export type WorkerPoolTelemetryWorker = z.infer<typeof WorkerPoolTelemetryWorkerSchema>;
|
|
116
|
+
export type WorkerPoolTelemetrySummary = z.infer<typeof WorkerPoolTelemetrySummarySchema>;
|
|
117
|
+
export type WorkerPoolTelemetrySnapshot = z.infer<typeof WorkerPoolTelemetrySnapshotSchema>;
|
|
118
|
+
export type WorkerPoolTelemetryList = z.infer<typeof WorkerPoolTelemetryListSchema>;
|
|
101
119
|
export type ProcessSnapshot = z.infer<typeof ProcessSnapshotSchema>;
|
|
102
120
|
export type ProcessSnapshotHistory = z.infer<typeof ProcessSnapshotHistorySchema>;
|
|
@@ -247,21 +247,62 @@ export const CAPABILITY_IDS = [
|
|
|
247
247
|
'compressor',
|
|
248
248
|
'compressor_level',
|
|
249
249
|
'monitor_gain',
|
|
250
|
+
'monitor_enabled',
|
|
251
|
+
'apf_enabled',
|
|
252
|
+
'apf_level',
|
|
250
253
|
'nb',
|
|
254
|
+
'nb_level',
|
|
251
255
|
'nr',
|
|
256
|
+
'nr_level',
|
|
257
|
+
'rf_gain',
|
|
258
|
+
'if_shift',
|
|
259
|
+
'pbt_in',
|
|
260
|
+
'pbt_out',
|
|
261
|
+
'cw_pitch',
|
|
262
|
+
'key_speed',
|
|
263
|
+
'notch_raw',
|
|
264
|
+
'agc_time',
|
|
265
|
+
'balance',
|
|
266
|
+
'drive_gain',
|
|
267
|
+
'digi_sel_enabled',
|
|
268
|
+
'digi_sel_level',
|
|
252
269
|
'lock_mode',
|
|
253
270
|
'mute',
|
|
254
271
|
'vox',
|
|
272
|
+
'vox_gain',
|
|
273
|
+
'anti_vox',
|
|
274
|
+
'vox_delay',
|
|
275
|
+
'break_in_delay',
|
|
276
|
+
'auto_notch',
|
|
277
|
+
'manual_notch',
|
|
278
|
+
'rit_enabled',
|
|
279
|
+
'xit_enabled',
|
|
280
|
+
'tone_enabled',
|
|
281
|
+
'tone_squelch_enabled',
|
|
282
|
+
'beep_enabled',
|
|
283
|
+
'break_in_mode',
|
|
255
284
|
'agc_mode',
|
|
256
285
|
'preamp',
|
|
257
286
|
'attenuator',
|
|
258
287
|
'mode_bandwidth',
|
|
288
|
+
'split_enabled',
|
|
289
|
+
'vfo_select',
|
|
290
|
+
'audio_if_mode',
|
|
259
291
|
'rit_offset',
|
|
260
292
|
'xit_offset',
|
|
261
293
|
'tuning_step',
|
|
262
294
|
'repeater_shift',
|
|
263
295
|
'repeater_offset',
|
|
264
296
|
'ctcss_tone',
|
|
297
|
+
'spectrum_data_output',
|
|
298
|
+
'spectrum_hold',
|
|
299
|
+
'spectrum_speed',
|
|
300
|
+
'spectrum_ref',
|
|
301
|
+
'spectrum_average',
|
|
302
|
+
'spectrum_vbw',
|
|
303
|
+
'spectrum_rbw',
|
|
304
|
+
'spectrum_during_tx',
|
|
305
|
+
'spectrum_center_type',
|
|
265
306
|
'dcs_code',
|
|
266
307
|
] as const;
|
|
267
308
|
|
|
@@ -1,5 +1,15 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
2
|
|
|
3
|
+
/**
|
|
4
|
+
* 中继差频方向
|
|
5
|
+
*/
|
|
6
|
+
export const RepeaterShiftSchema = z.enum(['none', 'minus', 'plus']);
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* 哑音类型
|
|
10
|
+
*/
|
|
11
|
+
export const ToneSquelchModeSchema = z.enum(['none', 'ctcss', 'dcs']);
|
|
12
|
+
|
|
3
13
|
/**
|
|
4
14
|
* 预设频率Schema
|
|
5
15
|
*/
|
|
@@ -9,6 +19,85 @@ export const PresetFrequencySchema = z.object({
|
|
|
9
19
|
radioMode: z.string().optional(), // 电台调制模式,如 USB, LSB, AM, FM
|
|
10
20
|
frequency: z.number(),
|
|
11
21
|
description: z.string().optional(),
|
|
22
|
+
repeaterShift: RepeaterShiftSchema.optional(), // 中继差频方向,默认 none
|
|
23
|
+
repeaterOffsetHz: z.number().int().positive().optional(), // 中继偏移,单位 Hz
|
|
24
|
+
toneMode: ToneSquelchModeSchema.optional(), // 哑音类型,默认 none
|
|
25
|
+
ctcssToneTenthsHz: z.number().int().positive().optional(), // CTCSS,单位 0.1Hz
|
|
26
|
+
dcsCode: z.number().int().positive().optional(), // DCS 码
|
|
27
|
+
}).superRefine((preset, ctx) => {
|
|
28
|
+
const isVoiceFmPreset = preset.mode === 'VOICE' && preset.radioMode?.toUpperCase() === 'FM';
|
|
29
|
+
const hasRepeaterDuplex = preset.repeaterShift === 'minus' || preset.repeaterShift === 'plus';
|
|
30
|
+
|
|
31
|
+
if (hasRepeaterDuplex && !isVoiceFmPreset) {
|
|
32
|
+
ctx.addIssue({
|
|
33
|
+
code: z.ZodIssueCode.custom,
|
|
34
|
+
path: ['repeaterShift'],
|
|
35
|
+
message: 'repeater duplex is only supported for VOICE FM presets',
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
if (
|
|
40
|
+
hasRepeaterDuplex
|
|
41
|
+
&& preset.repeaterOffsetHz === undefined
|
|
42
|
+
) {
|
|
43
|
+
ctx.addIssue({
|
|
44
|
+
code: z.ZodIssueCode.custom,
|
|
45
|
+
path: ['repeaterOffsetHz'],
|
|
46
|
+
message: 'repeaterOffsetHz is required when repeaterShift is plus or minus',
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
if (!isVoiceFmPreset && preset.toneMode && preset.toneMode !== 'none') {
|
|
51
|
+
ctx.addIssue({
|
|
52
|
+
code: z.ZodIssueCode.custom,
|
|
53
|
+
path: ['toneMode'],
|
|
54
|
+
message: 'tone squelch is only supported for VOICE FM presets',
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
if (preset.toneMode === 'ctcss') {
|
|
59
|
+
if (preset.ctcssToneTenthsHz === undefined) {
|
|
60
|
+
ctx.addIssue({
|
|
61
|
+
code: z.ZodIssueCode.custom,
|
|
62
|
+
path: ['ctcssToneTenthsHz'],
|
|
63
|
+
message: 'ctcssToneTenthsHz is required when toneMode is ctcss',
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
if (preset.dcsCode !== undefined) {
|
|
67
|
+
ctx.addIssue({
|
|
68
|
+
code: z.ZodIssueCode.custom,
|
|
69
|
+
path: ['dcsCode'],
|
|
70
|
+
message: 'dcsCode cannot be set when toneMode is ctcss',
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
if (preset.toneMode === 'dcs') {
|
|
76
|
+
if (preset.dcsCode === undefined) {
|
|
77
|
+
ctx.addIssue({
|
|
78
|
+
code: z.ZodIssueCode.custom,
|
|
79
|
+
path: ['dcsCode'],
|
|
80
|
+
message: 'dcsCode is required when toneMode is dcs',
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
if (preset.ctcssToneTenthsHz !== undefined) {
|
|
84
|
+
ctx.addIssue({
|
|
85
|
+
code: z.ZodIssueCode.custom,
|
|
86
|
+
path: ['ctcssToneTenthsHz'],
|
|
87
|
+
message: 'ctcssToneTenthsHz cannot be set when toneMode is dcs',
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
if ((preset.toneMode === undefined || preset.toneMode === 'none')
|
|
93
|
+
&& (preset.ctcssToneTenthsHz !== undefined || preset.dcsCode !== undefined)
|
|
94
|
+
) {
|
|
95
|
+
ctx.addIssue({
|
|
96
|
+
code: z.ZodIssueCode.custom,
|
|
97
|
+
path: ['toneMode'],
|
|
98
|
+
message: 'toneMode must be ctcss or dcs when tone values are set',
|
|
99
|
+
});
|
|
100
|
+
}
|
|
12
101
|
});
|
|
13
102
|
|
|
14
103
|
/**
|
|
@@ -163,6 +252,12 @@ export const HamlibConfigSchema = z.object({
|
|
|
163
252
|
// PTT 独立串口路径(仅当 pttMethod 为 dtr/rts 时有效)
|
|
164
253
|
// 留空则复用 CAT 同一串口
|
|
165
254
|
pttPort: z.string().optional(),
|
|
255
|
+
|
|
256
|
+
// CW 键控串口路径(用于 DTR/RTS 引脚驱动电台 CW KEY 输入)
|
|
257
|
+
cwKeyPort: z.string().optional(),
|
|
258
|
+
|
|
259
|
+
// CW 键控引脚类型(dtr 或 rts)
|
|
260
|
+
cwKeyMethod: z.enum(['dtr', 'rts']).optional(),
|
|
166
261
|
});
|
|
167
262
|
|
|
168
263
|
/**
|
|
@@ -357,6 +452,8 @@ export const CustomFrequencyPresetsSchema = z.object({
|
|
|
357
452
|
// 导出类型
|
|
358
453
|
export type CustomFrequencyPresets = z.infer<typeof CustomFrequencyPresetsSchema>;
|
|
359
454
|
export type PresetFrequency = z.infer<typeof PresetFrequencySchema>;
|
|
455
|
+
export type RepeaterShift = z.infer<typeof RepeaterShiftSchema>;
|
|
456
|
+
export type ToneSquelchMode = z.infer<typeof ToneSquelchModeSchema>;
|
|
360
457
|
export type FrequencyListResponse = z.infer<typeof FrequencyListResponseSchema>;
|
|
361
458
|
export type SerialConfig = z.infer<typeof SerialConfigSchema>;
|
|
362
459
|
export type HamlibBackendConfig = z.infer<typeof HamlibBackendConfigSchema>;
|
|
@@ -24,5 +24,5 @@ export type VoicePTTLock = z.infer<typeof VoicePTTLockSchema>;
|
|
|
24
24
|
* digital: FT8/FT4 等数字模式
|
|
25
25
|
* voice: 语音通联模式(SSB/FM/AM)
|
|
26
26
|
*/
|
|
27
|
-
export const EngineModeSchema = z.enum(['digital', 'voice']);
|
|
27
|
+
export const EngineModeSchema = z.enum(['digital', 'voice', 'cw']);
|
|
28
28
|
export type EngineMode = z.infer<typeof EngineModeSchema>;
|