-
-
Notifications
You must be signed in to change notification settings - Fork 435
/
Copy pathmonitor-service.ts
250 lines (231 loc) · 7.12 KB
/
monitor-service.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
import { ApplicationError } from '@theia/core/lib/common/application-error';
import type { Event } from '@theia/core/lib/common/event';
import type { JsonRpcServer } from '@theia/core/lib/common/messaging/proxy-factory';
import { nls } from '@theia/core/lib/common/nls';
import type { BoardIdentifier, PortIdentifier } from './boards-service';
export type PluggableMonitorSettings = Record<string, PluggableMonitorSetting>;
export interface MonitorSettings {
pluggableMonitorSettings?: PluggableMonitorSettings;
monitorUISettings?: Partial<MonitorState>;
}
export const MonitorManagerProxyFactory = Symbol('MonitorManagerProxyFactory');
export type MonitorManagerProxyFactory = () => MonitorManagerProxy;
export const MonitorManagerProxyPath = '/services/monitor-manager-proxy';
export const MonitorManagerProxy = Symbol('MonitorManagerProxy');
export interface MonitorManagerProxy
extends JsonRpcServer<MonitorManagerProxyClient> {
startMonitor(
board: BoardIdentifier,
port: PortIdentifier,
settings?: PluggableMonitorSettings
): Promise<void>;
changeMonitorSettings(
board: BoardIdentifier,
port: PortIdentifier,
settings: MonitorSettings
): Promise<void>;
stopMonitor(board: BoardIdentifier, port: PortIdentifier): Promise<void>;
getCurrentSettings(
board: BoardIdentifier,
port: PortIdentifier
): Promise<MonitorSettings>;
}
export const MonitorManagerProxyClient = Symbol('MonitorManagerProxyClient');
export interface MonitorManagerProxyClient {
onMessagesReceived: Event<{ messages: string[] }>;
onMonitorSettingsDidChange: Event<MonitorSettings>;
onMonitorShouldReset: Event<void>;
connect(addressPort: number): Promise<void>;
disconnect(): void;
getWebSocketPort(): number | undefined;
isWSConnected(): Promise<boolean>;
startMonitor(settings?: PluggableMonitorSettings): Promise<void>;
getCurrentSettings(
board: BoardIdentifier,
port: PortIdentifier
): Promise<MonitorSettings>;
send(message: string): void;
changeSettings(settings: MonitorSettings): void;
}
export interface PluggableMonitorSetting {
// The setting identifier
readonly id: string;
// A human-readable label of the setting (to be displayed on the GUI)
readonly label: string;
// The setting type (at the moment only "enum" is available)
readonly type: string;
// The values allowed on "enum" types
readonly values: string[];
// The selected value
selectedValue: string;
}
export namespace Monitor {
// Commands sent by the clients to the web socket server
export enum ClientCommand {
SEND_MESSAGE = 'SEND_MESSAGE',
CHANGE_SETTINGS = 'CHANGE_SETTINGS',
}
// Commands sent by the backend to the clients
export enum MiddlewareCommand {
ON_SETTINGS_DID_CHANGE = 'ON_SETTINGS_DID_CHANGE',
}
export type Message = {
command: Monitor.ClientCommand | Monitor.MiddlewareCommand;
data: string | MonitorSettings;
};
}
export const MonitorErrorCodes = {
ConnectionFailed: 6001,
NotConnected: 6002,
AlreadyConnected: 6003,
MissingConfiguration: 6004,
} as const;
export const ConnectionFailedError = declareMonitorError(
MonitorErrorCodes.ConnectionFailed
);
export const NotConnectedError = declareMonitorError(
MonitorErrorCodes.NotConnected
);
export const AlreadyConnectedError = declareMonitorError(
MonitorErrorCodes.AlreadyConnected
);
export const MissingConfigurationError = declareMonitorError(
MonitorErrorCodes.MissingConfiguration
);
export function createConnectionFailedError(
port: PortIdentifier,
details?: string
): ApplicationError<number, PortDescriptor> {
const { protocol, address } = port;
let message;
if (details) {
const detailsWithPeriod = details.endsWith('.') ? details : `${details}.`;
message = nls.localize(
'arduino/monitor/connectionFailedErrorWithDetails',
'{0} Could not connect to {1} {2} port.',
detailsWithPeriod,
address,
protocol
);
} else {
message = nls.localize(
'arduino/monitor/connectionFailedError',
'Could not connect to {0} {1} port.',
address,
protocol
);
}
return ConnectionFailedError(message, { protocol, address });
}
export function createNotConnectedError(
port: PortIdentifier
): ApplicationError<number, PortDescriptor> {
const { protocol, address } = port;
return NotConnectedError(
nls.localize(
'arduino/monitor/notConnectedError',
'Not connected to {0} {1} port.',
address,
protocol
),
{ protocol, address }
);
}
export function createAlreadyConnectedError(
port: PortIdentifier
): ApplicationError<number, PortDescriptor> {
const { protocol, address } = port;
return AlreadyConnectedError(
nls.localize(
'arduino/monitor/alreadyConnectedError',
'Could not connect to {0} {1} port. Already connected.',
address,
protocol
),
{ protocol, address }
);
}
export function createMissingConfigurationError(
port: PortIdentifier
): ApplicationError<number, PortDescriptor> {
const { protocol, address } = port;
return MissingConfigurationError(
nls.localize(
'arduino/monitor/missingConfigurationError',
'Could not connect to {0} {1} port. The monitor configuration is missing.',
address,
protocol
),
{ protocol, address }
);
}
/**
* Bare minimum representation of a port. Supports neither UI labels nor properties.
*/
interface PortDescriptor {
readonly protocol: string;
readonly address: string;
}
function declareMonitorError(
code: number
): ApplicationError.Constructor<number, PortDescriptor> {
return ApplicationError.declare(
code,
(message: string, data: PortDescriptor) => ({ data, message })
);
}
export interface MonitorConnectionError {
readonly errorMessage: string;
}
export type MonitorConnectionStatus =
| 'connecting'
| 'connected'
| 'not-connected'
| MonitorConnectionError;
export function monitorConnectionStatusEquals(
left: MonitorConnectionStatus,
right: MonitorConnectionStatus
): boolean {
if (typeof left === 'object' && typeof right === 'object') {
return left.errorMessage === right.errorMessage;
}
return left === right;
}
/**
* @deprecated see `MonitorState#connected`
*/
export function isMonitorConnected(
status: MonitorConnectionStatus
): status is 'connected' {
return status === 'connected';
}
export function isMonitorConnectionError(
status: MonitorConnectionStatus
): status is MonitorConnectionError {
return typeof status === 'object';
}
export interface MonitorState {
autoscroll: boolean;
timestamp: boolean;
lineEnding: MonitorEOL;
interpolate: boolean;
darkTheme: boolean;
wsPort: number;
serialPort: string;
connectionStatus: MonitorConnectionStatus;
/**
* @deprecated This property is never get by IDE2 only set. This value is present to be backward compatible with the plotter app.
* IDE2 uses `MonitorState#connectionStatus`.
*/
connected: boolean;
}
export namespace MonitorState {
export interface Change<K extends keyof MonitorState> {
readonly property: K;
readonly value: MonitorState[K];
}
}
export type MonitorEOL = '' | '\n' | '\r' | '\r\n';
export namespace MonitorEOL {
export const DEFAULT: MonitorEOL = '\n';
}