✨ Adds promise based request reponse system
This commit is contained in:
+1
-1
@@ -15,7 +15,7 @@
|
|||||||
"format": "prettier --write .",
|
"format": "prettier --write .",
|
||||||
"test:integration": "playwright test",
|
"test:integration": "playwright test",
|
||||||
"test:unit": "vitest",
|
"test:unit": "vitest",
|
||||||
"proto": "protoc --plugin=protoc-gen-ts_proto=.\\node_modules\\.bin\\protoc-gen-ts_proto.cmd --ts_proto_out=./src/lib/platform_shared --ts_proto_opt=outputTypeAnnotations=true,useExactTypes=false,outputExtensions=true,outputTypeRegistry=true -I ../platform_shared ../platform_shared/websocket_message.proto ../platform_shared/rest_message.proto"
|
"proto": "protoc --plugin=protoc-gen-ts_proto=.\\node_modules\\.bin\\protoc-gen-ts_proto.cmd --ts_proto_out=./src/lib/platform_shared --ts_proto_opt=outputTypeAnnotations=true,useExactTypes=false,outputExtensions=true,outputTypeRegistry=true,outputSchema=true -I ../platform_shared ../platform_shared/websocket_message.proto ../platform_shared/rest_message.proto"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@eslint/js": "^9.39.2",
|
"@eslint/js": "^9.39.2",
|
||||||
|
|||||||
@@ -6,13 +6,12 @@
|
|||||||
|
|
||||||
/* eslint-disable */
|
/* eslint-disable */
|
||||||
import { BinaryReader, BinaryWriter } from "@bufbuild/protobuf/wire";
|
import { BinaryReader, BinaryWriter } from "@bufbuild/protobuf/wire";
|
||||||
import { messageTypeRegistry } from "./typeRegistry";
|
import type { FileDescriptorProto } from "ts-proto-descriptors";
|
||||||
import { KnownNetworkItem } from "./websocket_message";
|
import { KnownNetworkItem, protoMetadata as protoMetadata1 } from "./websocket_message";
|
||||||
|
|
||||||
export const protobufPackage = "rest_message";
|
export const protobufPackage = "rest_message";
|
||||||
|
|
||||||
export interface WifiStatus {
|
export interface WifiStatus {
|
||||||
$type: "rest_message.WifiStatus";
|
|
||||||
status: number;
|
status: number;
|
||||||
localIp: string;
|
localIp: string;
|
||||||
macAddress: string;
|
macAddress: string;
|
||||||
@@ -27,7 +26,6 @@ export interface WifiStatus {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export interface WifiSettings {
|
export interface WifiSettings {
|
||||||
$type: "rest_message.WifiSettings";
|
|
||||||
hostname: string;
|
hostname: string;
|
||||||
priorityRssi: boolean;
|
priorityRssi: boolean;
|
||||||
wifiNetworks: KnownNetworkItem[];
|
wifiNetworks: KnownNetworkItem[];
|
||||||
@@ -35,7 +33,6 @@ export interface WifiSettings {
|
|||||||
|
|
||||||
function createBaseWifiStatus(): WifiStatus {
|
function createBaseWifiStatus(): WifiStatus {
|
||||||
return {
|
return {
|
||||||
$type: "rest_message.WifiStatus",
|
|
||||||
status: 0,
|
status: 0,
|
||||||
localIp: "",
|
localIp: "",
|
||||||
macAddress: "",
|
macAddress: "",
|
||||||
@@ -50,9 +47,7 @@ function createBaseWifiStatus(): WifiStatus {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export const WifiStatus: MessageFns<WifiStatus, "rest_message.WifiStatus"> = {
|
export const WifiStatus: MessageFns<WifiStatus> = {
|
||||||
$type: "rest_message.WifiStatus" as const,
|
|
||||||
|
|
||||||
encode(message: WifiStatus, writer: BinaryWriter = new BinaryWriter()): BinaryWriter {
|
encode(message: WifiStatus, writer: BinaryWriter = new BinaryWriter()): BinaryWriter {
|
||||||
if (message.status !== 0) {
|
if (message.status !== 0) {
|
||||||
writer.uint32(8).int32(message.status);
|
writer.uint32(8).int32(message.status);
|
||||||
@@ -196,7 +191,6 @@ export const WifiStatus: MessageFns<WifiStatus, "rest_message.WifiStatus"> = {
|
|||||||
|
|
||||||
fromJSON(object: any): WifiStatus {
|
fromJSON(object: any): WifiStatus {
|
||||||
return {
|
return {
|
||||||
$type: WifiStatus.$type,
|
|
||||||
status: isSet(object.status) ? globalThis.Number(object.status) : 0,
|
status: isSet(object.status) ? globalThis.Number(object.status) : 0,
|
||||||
localIp: isSet(object.localIp) ? globalThis.String(object.localIp) : "",
|
localIp: isSet(object.localIp) ? globalThis.String(object.localIp) : "",
|
||||||
macAddress: isSet(object.macAddress) ? globalThis.String(object.macAddress) : "",
|
macAddress: isSet(object.macAddress) ? globalThis.String(object.macAddress) : "",
|
||||||
@@ -249,10 +243,10 @@ export const WifiStatus: MessageFns<WifiStatus, "rest_message.WifiStatus"> = {
|
|||||||
return obj;
|
return obj;
|
||||||
},
|
},
|
||||||
|
|
||||||
create(base?: DeepPartial<WifiStatus>): WifiStatus {
|
create<I extends Exact<DeepPartial<WifiStatus>, I>>(base?: I): WifiStatus {
|
||||||
return WifiStatus.fromPartial(base ?? {});
|
return WifiStatus.fromPartial(base ?? ({} as any));
|
||||||
},
|
},
|
||||||
fromPartial(object: DeepPartial<WifiStatus>): WifiStatus {
|
fromPartial<I extends Exact<DeepPartial<WifiStatus>, I>>(object: I): WifiStatus {
|
||||||
const message = createBaseWifiStatus();
|
const message = createBaseWifiStatus();
|
||||||
message.status = object.status ?? 0;
|
message.status = object.status ?? 0;
|
||||||
message.localIp = object.localIp ?? "";
|
message.localIp = object.localIp ?? "";
|
||||||
@@ -269,15 +263,11 @@ export const WifiStatus: MessageFns<WifiStatus, "rest_message.WifiStatus"> = {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
messageTypeRegistry.set(WifiStatus.$type, WifiStatus);
|
|
||||||
|
|
||||||
function createBaseWifiSettings(): WifiSettings {
|
function createBaseWifiSettings(): WifiSettings {
|
||||||
return { $type: "rest_message.WifiSettings", hostname: "", priorityRssi: false, wifiNetworks: [] };
|
return { hostname: "", priorityRssi: false, wifiNetworks: [] };
|
||||||
}
|
}
|
||||||
|
|
||||||
export const WifiSettings: MessageFns<WifiSettings, "rest_message.WifiSettings"> = {
|
export const WifiSettings: MessageFns<WifiSettings> = {
|
||||||
$type: "rest_message.WifiSettings" as const,
|
|
||||||
|
|
||||||
encode(message: WifiSettings, writer: BinaryWriter = new BinaryWriter()): BinaryWriter {
|
encode(message: WifiSettings, writer: BinaryWriter = new BinaryWriter()): BinaryWriter {
|
||||||
if (message.hostname !== "") {
|
if (message.hostname !== "") {
|
||||||
writer.uint32(10).string(message.hostname);
|
writer.uint32(10).string(message.hostname);
|
||||||
@@ -333,7 +323,6 @@ export const WifiSettings: MessageFns<WifiSettings, "rest_message.WifiSettings">
|
|||||||
|
|
||||||
fromJSON(object: any): WifiSettings {
|
fromJSON(object: any): WifiSettings {
|
||||||
return {
|
return {
|
||||||
$type: WifiSettings.$type,
|
|
||||||
hostname: isSet(object.hostname) ? globalThis.String(object.hostname) : "",
|
hostname: isSet(object.hostname) ? globalThis.String(object.hostname) : "",
|
||||||
priorityRssi: isSet(object.priorityRssi) ? globalThis.Boolean(object.priorityRssi) : false,
|
priorityRssi: isSet(object.priorityRssi) ? globalThis.Boolean(object.priorityRssi) : false,
|
||||||
wifiNetworks: globalThis.Array.isArray(object?.wifiNetworks)
|
wifiNetworks: globalThis.Array.isArray(object?.wifiNetworks)
|
||||||
@@ -356,10 +345,10 @@ export const WifiSettings: MessageFns<WifiSettings, "rest_message.WifiSettings">
|
|||||||
return obj;
|
return obj;
|
||||||
},
|
},
|
||||||
|
|
||||||
create(base?: DeepPartial<WifiSettings>): WifiSettings {
|
create<I extends Exact<DeepPartial<WifiSettings>, I>>(base?: I): WifiSettings {
|
||||||
return WifiSettings.fromPartial(base ?? {});
|
return WifiSettings.fromPartial(base ?? ({} as any));
|
||||||
},
|
},
|
||||||
fromPartial(object: DeepPartial<WifiSettings>): WifiSettings {
|
fromPartial<I extends Exact<DeepPartial<WifiSettings>, I>>(object: I): WifiSettings {
|
||||||
const message = createBaseWifiSettings();
|
const message = createBaseWifiSettings();
|
||||||
message.hostname = object.hostname ?? "";
|
message.hostname = object.hostname ?? "";
|
||||||
message.priorityRssi = object.priorityRssi ?? false;
|
message.priorityRssi = object.priorityRssi ?? false;
|
||||||
@@ -368,26 +357,270 @@ export const WifiSettings: MessageFns<WifiSettings, "rest_message.WifiSettings">
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
messageTypeRegistry.set(WifiSettings.$type, WifiSettings);
|
type ProtoMetaMessageOptions = {
|
||||||
|
options?: { [key: string]: any };
|
||||||
|
fields?: { [key: string]: { [key: string]: any } };
|
||||||
|
oneof?: { [key: string]: { [key: string]: any } };
|
||||||
|
nested?: { [key: string]: ProtoMetaMessageOptions };
|
||||||
|
};
|
||||||
|
|
||||||
|
export interface ProtoMetadata {
|
||||||
|
fileDescriptor: FileDescriptorProto;
|
||||||
|
references: { [key: string]: any };
|
||||||
|
dependencies?: ProtoMetadata[];
|
||||||
|
options?: {
|
||||||
|
options?: { [key: string]: any };
|
||||||
|
services?: {
|
||||||
|
[key: string]: { options?: { [key: string]: any }; methods?: { [key: string]: { [key: string]: any } } };
|
||||||
|
};
|
||||||
|
messages?: { [key: string]: ProtoMetaMessageOptions };
|
||||||
|
enums?: { [key: string]: { options?: { [key: string]: any }; values?: { [key: string]: { [key: string]: any } } } };
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export const protoMetadata: ProtoMetadata = {
|
||||||
|
fileDescriptor: {
|
||||||
|
"name": "rest_message.proto",
|
||||||
|
"package": "rest_message",
|
||||||
|
"dependency": ["websocket_message.proto"],
|
||||||
|
"publicDependency": [],
|
||||||
|
"weakDependency": [],
|
||||||
|
"optionDependency": [],
|
||||||
|
"messageType": [{
|
||||||
|
"name": "WifiStatus",
|
||||||
|
"field": [{
|
||||||
|
"name": "status",
|
||||||
|
"number": 1,
|
||||||
|
"label": 1,
|
||||||
|
"type": 5,
|
||||||
|
"typeName": "",
|
||||||
|
"extendee": "",
|
||||||
|
"defaultValue": "",
|
||||||
|
"oneofIndex": 0,
|
||||||
|
"jsonName": "status",
|
||||||
|
"options": undefined,
|
||||||
|
"proto3Optional": false,
|
||||||
|
}, {
|
||||||
|
"name": "local_ip",
|
||||||
|
"number": 2,
|
||||||
|
"label": 1,
|
||||||
|
"type": 9,
|
||||||
|
"typeName": "",
|
||||||
|
"extendee": "",
|
||||||
|
"defaultValue": "",
|
||||||
|
"oneofIndex": 0,
|
||||||
|
"jsonName": "localIp",
|
||||||
|
"options": undefined,
|
||||||
|
"proto3Optional": false,
|
||||||
|
}, {
|
||||||
|
"name": "mac_address",
|
||||||
|
"number": 3,
|
||||||
|
"label": 1,
|
||||||
|
"type": 9,
|
||||||
|
"typeName": "",
|
||||||
|
"extendee": "",
|
||||||
|
"defaultValue": "",
|
||||||
|
"oneofIndex": 0,
|
||||||
|
"jsonName": "macAddress",
|
||||||
|
"options": undefined,
|
||||||
|
"proto3Optional": false,
|
||||||
|
}, {
|
||||||
|
"name": "rssi",
|
||||||
|
"number": 4,
|
||||||
|
"label": 1,
|
||||||
|
"type": 2,
|
||||||
|
"typeName": "",
|
||||||
|
"extendee": "",
|
||||||
|
"defaultValue": "",
|
||||||
|
"oneofIndex": 0,
|
||||||
|
"jsonName": "rssi",
|
||||||
|
"options": undefined,
|
||||||
|
"proto3Optional": false,
|
||||||
|
}, {
|
||||||
|
"name": "ssid",
|
||||||
|
"number": 5,
|
||||||
|
"label": 1,
|
||||||
|
"type": 9,
|
||||||
|
"typeName": "",
|
||||||
|
"extendee": "",
|
||||||
|
"defaultValue": "",
|
||||||
|
"oneofIndex": 0,
|
||||||
|
"jsonName": "ssid",
|
||||||
|
"options": undefined,
|
||||||
|
"proto3Optional": false,
|
||||||
|
}, {
|
||||||
|
"name": "bssid",
|
||||||
|
"number": 6,
|
||||||
|
"label": 1,
|
||||||
|
"type": 9,
|
||||||
|
"typeName": "",
|
||||||
|
"extendee": "",
|
||||||
|
"defaultValue": "",
|
||||||
|
"oneofIndex": 0,
|
||||||
|
"jsonName": "bssid",
|
||||||
|
"options": undefined,
|
||||||
|
"proto3Optional": false,
|
||||||
|
}, {
|
||||||
|
"name": "channel",
|
||||||
|
"number": 7,
|
||||||
|
"label": 1,
|
||||||
|
"type": 13,
|
||||||
|
"typeName": "",
|
||||||
|
"extendee": "",
|
||||||
|
"defaultValue": "",
|
||||||
|
"oneofIndex": 0,
|
||||||
|
"jsonName": "channel",
|
||||||
|
"options": undefined,
|
||||||
|
"proto3Optional": false,
|
||||||
|
}, {
|
||||||
|
"name": "subnet_mask",
|
||||||
|
"number": 8,
|
||||||
|
"label": 1,
|
||||||
|
"type": 9,
|
||||||
|
"typeName": "",
|
||||||
|
"extendee": "",
|
||||||
|
"defaultValue": "",
|
||||||
|
"oneofIndex": 0,
|
||||||
|
"jsonName": "subnetMask",
|
||||||
|
"options": undefined,
|
||||||
|
"proto3Optional": false,
|
||||||
|
}, {
|
||||||
|
"name": "gateway_ip",
|
||||||
|
"number": 9,
|
||||||
|
"label": 1,
|
||||||
|
"type": 9,
|
||||||
|
"typeName": "",
|
||||||
|
"extendee": "",
|
||||||
|
"defaultValue": "",
|
||||||
|
"oneofIndex": 0,
|
||||||
|
"jsonName": "gatewayIp",
|
||||||
|
"options": undefined,
|
||||||
|
"proto3Optional": false,
|
||||||
|
}, {
|
||||||
|
"name": "dns_ip_1",
|
||||||
|
"number": 10,
|
||||||
|
"label": 1,
|
||||||
|
"type": 9,
|
||||||
|
"typeName": "",
|
||||||
|
"extendee": "",
|
||||||
|
"defaultValue": "",
|
||||||
|
"oneofIndex": 0,
|
||||||
|
"jsonName": "dnsIp1",
|
||||||
|
"options": undefined,
|
||||||
|
"proto3Optional": false,
|
||||||
|
}, {
|
||||||
|
"name": "dns_ip_2",
|
||||||
|
"number": 11,
|
||||||
|
"label": 1,
|
||||||
|
"type": 9,
|
||||||
|
"typeName": "",
|
||||||
|
"extendee": "",
|
||||||
|
"defaultValue": "",
|
||||||
|
"oneofIndex": 0,
|
||||||
|
"jsonName": "dnsIp2",
|
||||||
|
"options": undefined,
|
||||||
|
"proto3Optional": true,
|
||||||
|
}],
|
||||||
|
"extension": [],
|
||||||
|
"nestedType": [],
|
||||||
|
"enumType": [],
|
||||||
|
"extensionRange": [],
|
||||||
|
"oneofDecl": [{ "name": "_dns_ip_2", "options": undefined }],
|
||||||
|
"options": undefined,
|
||||||
|
"reservedRange": [],
|
||||||
|
"reservedName": [],
|
||||||
|
"visibility": 0,
|
||||||
|
}, {
|
||||||
|
"name": "WifiSettings",
|
||||||
|
"field": [{
|
||||||
|
"name": "hostname",
|
||||||
|
"number": 1,
|
||||||
|
"label": 1,
|
||||||
|
"type": 9,
|
||||||
|
"typeName": "",
|
||||||
|
"extendee": "",
|
||||||
|
"defaultValue": "",
|
||||||
|
"oneofIndex": 0,
|
||||||
|
"jsonName": "hostname",
|
||||||
|
"options": undefined,
|
||||||
|
"proto3Optional": false,
|
||||||
|
}, {
|
||||||
|
"name": "priority_rssi",
|
||||||
|
"number": 2,
|
||||||
|
"label": 1,
|
||||||
|
"type": 8,
|
||||||
|
"typeName": "",
|
||||||
|
"extendee": "",
|
||||||
|
"defaultValue": "",
|
||||||
|
"oneofIndex": 0,
|
||||||
|
"jsonName": "priorityRssi",
|
||||||
|
"options": undefined,
|
||||||
|
"proto3Optional": false,
|
||||||
|
}, {
|
||||||
|
"name": "wifi_networks",
|
||||||
|
"number": 3,
|
||||||
|
"label": 3,
|
||||||
|
"type": 11,
|
||||||
|
"typeName": ".socket_message.KnownNetworkItem",
|
||||||
|
"extendee": "",
|
||||||
|
"defaultValue": "",
|
||||||
|
"oneofIndex": 0,
|
||||||
|
"jsonName": "wifiNetworks",
|
||||||
|
"options": undefined,
|
||||||
|
"proto3Optional": false,
|
||||||
|
}],
|
||||||
|
"extension": [],
|
||||||
|
"nestedType": [],
|
||||||
|
"enumType": [],
|
||||||
|
"extensionRange": [],
|
||||||
|
"oneofDecl": [],
|
||||||
|
"options": undefined,
|
||||||
|
"reservedRange": [],
|
||||||
|
"reservedName": [],
|
||||||
|
"visibility": 0,
|
||||||
|
}],
|
||||||
|
"enumType": [],
|
||||||
|
"service": [],
|
||||||
|
"extension": [],
|
||||||
|
"options": undefined,
|
||||||
|
"sourceCodeInfo": {
|
||||||
|
"location": [{
|
||||||
|
"path": [2],
|
||||||
|
"span": [5, 0, 21],
|
||||||
|
"leadingComments":
|
||||||
|
' Note: This is most likely a "temporary" proto that will be redone, as these endpoints are static for the esp32, which means we are forced to use WiFi for communication\n',
|
||||||
|
"trailingComments": "",
|
||||||
|
"leadingDetachedComments": [],
|
||||||
|
}],
|
||||||
|
},
|
||||||
|
"syntax": "proto3",
|
||||||
|
"edition": 0,
|
||||||
|
},
|
||||||
|
references: { ".rest_message.WifiStatus": WifiStatus, ".rest_message.WifiSettings": WifiSettings },
|
||||||
|
dependencies: [protoMetadata1],
|
||||||
|
};
|
||||||
|
|
||||||
type Builtin = Date | Function | Uint8Array | string | number | boolean | undefined;
|
type Builtin = Date | Function | Uint8Array | string | number | boolean | undefined;
|
||||||
|
|
||||||
export type DeepPartial<T> = T extends Builtin ? T
|
export type DeepPartial<T> = T extends Builtin ? T
|
||||||
: T extends globalThis.Array<infer U> ? globalThis.Array<DeepPartial<U>>
|
: T extends globalThis.Array<infer U> ? globalThis.Array<DeepPartial<U>>
|
||||||
: T extends ReadonlyArray<infer U> ? ReadonlyArray<DeepPartial<U>>
|
: T extends ReadonlyArray<infer U> ? ReadonlyArray<DeepPartial<U>>
|
||||||
: T extends {} ? { [K in Exclude<keyof T, "$type">]?: DeepPartial<T[K]> }
|
: T extends {} ? { [K in keyof T]?: DeepPartial<T[K]> }
|
||||||
: Partial<T>;
|
: Partial<T>;
|
||||||
|
|
||||||
|
type KeysOfUnion<T> = T extends T ? keyof T : never;
|
||||||
|
export type Exact<P, I extends P> = P extends Builtin ? P
|
||||||
|
: P & { [K in keyof P]: Exact<P[K], I[K]> } & { [K in Exclude<keyof I, KeysOfUnion<P>>]: never };
|
||||||
|
|
||||||
function isSet(value: any): boolean {
|
function isSet(value: any): boolean {
|
||||||
return value !== null && value !== undefined;
|
return value !== null && value !== undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface MessageFns<T, V extends string> {
|
export interface MessageFns<T> {
|
||||||
readonly $type: V;
|
|
||||||
encode(message: T, writer?: BinaryWriter): BinaryWriter;
|
encode(message: T, writer?: BinaryWriter): BinaryWriter;
|
||||||
decode(input: BinaryReader | Uint8Array, length?: number): T;
|
decode(input: BinaryReader | Uint8Array, length?: number): T;
|
||||||
fromJSON(object: any): T;
|
fromJSON(object: any): T;
|
||||||
toJSON(message: T): unknown;
|
toJSON(message: T): unknown;
|
||||||
create(base?: DeepPartial<T>): T;
|
create<I extends Exact<DeepPartial<T>, I>>(base?: I): T;
|
||||||
fromPartial(object: DeepPartial<T>): T;
|
fromPartial<I extends Exact<DeepPartial<T>, I>>(object: I): T;
|
||||||
}
|
}
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -1,8 +1,10 @@
|
|||||||
import { writable } from 'svelte/store'
|
import { writable } from 'svelte/store'
|
||||||
import {
|
import {
|
||||||
WebsocketMessage,
|
WebsocketMessage,
|
||||||
type MessageFns,
|
CorrelationRequest,
|
||||||
protoMetadata as websocket_md
|
CorrelationResponse,
|
||||||
|
protoMetadata as websocket_md,
|
||||||
|
type MessageFns
|
||||||
} from '$lib/platform_shared/websocket_message'
|
} from '$lib/platform_shared/websocket_message'
|
||||||
import * as WebsocketMessages from '$lib/platform_shared/websocket_message'
|
import * as WebsocketMessages from '$lib/platform_shared/websocket_message'
|
||||||
|
|
||||||
@@ -11,6 +13,13 @@ export const MESSAGE_TYPE_TO_TAG = new Map<MessageFns<unknown>, number>()
|
|||||||
export const MESSAGE_KEY_TO_TAG = new Map<string, number>()
|
export const MESSAGE_KEY_TO_TAG = new Map<string, number>()
|
||||||
export const MESSAGE_TAG_TO_KEY = new Map<number, string>()
|
export const MESSAGE_TAG_TO_KEY = new Map<number, string>()
|
||||||
|
|
||||||
|
type CorrelationRequestData = Omit<CorrelationRequest, 'correlationId'>
|
||||||
|
type PendingRequest = {
|
||||||
|
resolve: (response: CorrelationResponse) => void
|
||||||
|
reject: (error: Error) => void
|
||||||
|
timeoutId: ReturnType<typeof setTimeout>
|
||||||
|
}
|
||||||
|
|
||||||
const websocketMessageType = websocket_md.fileDescriptor.messageType?.find(
|
const websocketMessageType = websocket_md.fileDescriptor.messageType?.find(
|
||||||
(msg: { name: string }) => msg.name === 'WebsocketMessage'
|
(msg: { name: string }) => msg.name === 'WebsocketMessage'
|
||||||
)
|
)
|
||||||
@@ -75,8 +84,11 @@ export const encodeMessage = (data: WebsocketMessage): Uint8Array<ArrayBuffer> =
|
|||||||
function createWebSocket() {
|
function createWebSocket() {
|
||||||
const message_listeners = new Map<number, Set<(data?: unknown) => void>>()
|
const message_listeners = new Map<number, Set<(data?: unknown) => void>>()
|
||||||
const event_listeners = new Map<string, Set<(data?: unknown) => void>>()
|
const event_listeners = new Map<string, Set<(data?: unknown) => void>>()
|
||||||
|
const pending_requests = new Map<number, PendingRequest>()
|
||||||
const { subscribe, set } = writable(false)
|
const { subscribe, set } = writable(false)
|
||||||
const reconnectTimeoutTime = 500000
|
const reconnectTimeoutTime = 500000
|
||||||
|
const requestTimeoutTime = 10000
|
||||||
|
let correlationIdCounter = 0
|
||||||
let unresponsiveTimeoutId: ReturnType<typeof setTimeout>
|
let unresponsiveTimeoutId: ReturnType<typeof setTimeout>
|
||||||
let reconnectTimeoutId: ReturnType<typeof setTimeout>
|
let reconnectTimeoutId: ReturnType<typeof setTimeout>
|
||||||
let ws: WebSocket
|
let ws: WebSocket
|
||||||
@@ -109,9 +121,20 @@ function createWebSocket() {
|
|||||||
ws.onmessage = frame => {
|
ws.onmessage = frame => {
|
||||||
resetUnresponsiveCheck()
|
resetUnresponsiveCheck()
|
||||||
const { tag, msg } = decodeMessage(frame.data)
|
const { tag, msg } = decodeMessage(frame.data)
|
||||||
|
if (msg.correlationResponse) {
|
||||||
|
const pending = pending_requests.get(msg.correlationResponse.correlationId)
|
||||||
|
if (pending) {
|
||||||
|
clearTimeout(pending.timeoutId)
|
||||||
|
pending_requests.delete(msg.correlationResponse.correlationId)
|
||||||
|
pending.resolve(msg.correlationResponse)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
if (tag) {
|
if (tag) {
|
||||||
const key = MESSAGE_TAG_TO_KEY.get(tag)!
|
const key = MESSAGE_TAG_TO_KEY.get(tag)!
|
||||||
message_listeners.get(tag)?.forEach(listener => listener(msg[key as keyof typeof msg]))
|
message_listeners
|
||||||
|
.get(tag)
|
||||||
|
?.forEach(listener => listener(msg[key as keyof typeof msg]))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ws.onerror = ev => disconnect('error', ev)
|
ws.onerror = ev => disconnect('error', ev)
|
||||||
@@ -211,6 +234,25 @@ function createWebSocket() {
|
|||||||
return () => {
|
return () => {
|
||||||
unsubscribe_event(event_type, listener)
|
unsubscribe_event(event_type, listener)
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
request: (data: CorrelationRequestData): Promise<CorrelationResponse> => {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
if (!ws || ws.readyState !== WebSocket.OPEN) {
|
||||||
|
reject(new Error('WebSocket not connected'))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
const correlationId = ++correlationIdCounter
|
||||||
|
const timeoutId = setTimeout(() => {
|
||||||
|
pending_requests.delete(correlationId)
|
||||||
|
reject(new Error(`Request timeout (id: ${correlationId})`))
|
||||||
|
}, requestTimeoutTime)
|
||||||
|
|
||||||
|
pending_requests.set(correlationId, { resolve, reject, timeoutId })
|
||||||
|
|
||||||
|
const request = CorrelationRequest.create({ correlationId, ...data })
|
||||||
|
send(WebsocketMessage.create({ correlationRequest: request }))
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,45 +4,23 @@
|
|||||||
import { socket } from '$lib/stores'
|
import { socket } from '$lib/stores'
|
||||||
import { Connection } from '$lib/components/icons'
|
import { Connection } from '$lib/components/icons'
|
||||||
import I2CSetting from './i2cSetting.svelte'
|
import I2CSetting from './i2cSetting.svelte'
|
||||||
import {
|
import type { I2CDevice } from '$lib/platform_shared/websocket_message'
|
||||||
I2CDevice,
|
|
||||||
I2CScanData,
|
|
||||||
I2CScanDataRequest
|
|
||||||
} from '$lib/platform_shared/websocket_message'
|
|
||||||
|
|
||||||
// TODO: Delete this completely, this should be done on esp side, as it decides what addresses are actually valid, as for example ICM20948 and MPU6050 can have same address
|
|
||||||
// const i2cDevices = [
|
|
||||||
// { address: 30, part_number: 'HMC5883', name: '3-Axis Digital Compass/Magnetometer IC' },
|
|
||||||
// { address: 41, part_number: 'BNO055', name: '9-Axis Absolute Orientation Sensor' },
|
|
||||||
// { address: 64, part_number: 'PCA9685', name: '16-channel PWM driver default address' },
|
|
||||||
// { address: 72, part_number: 'ADS1115', name: '4-channel 16-bit ADC' },
|
|
||||||
// {
|
|
||||||
// address: 104,
|
|
||||||
// part_number: 'MPU6050',
|
|
||||||
// name: 'Six-Axis (Gyro + Accelerometer) MEMS MotionTracking™ Devices'
|
|
||||||
// },
|
|
||||||
// { address: 115, part_number: 'PAJ7620U2', name: 'Gesture sensor' },
|
|
||||||
// { address: 119, part_number: 'BMP085', name: 'Temp/Barometric' }
|
|
||||||
// ]
|
|
||||||
|
|
||||||
let active_devices: I2CDevice[] = $state([])
|
let active_devices: I2CDevice[] = $state([])
|
||||||
|
|
||||||
let isLoading = $state(false)
|
let isLoading = $state(false)
|
||||||
|
|
||||||
onMount(() => {
|
onMount(() => {
|
||||||
const unsub = socket.on(I2CScanData, handleScan)
|
|
||||||
triggerScan()
|
triggerScan()
|
||||||
return () => unsub
|
|
||||||
})
|
})
|
||||||
|
|
||||||
const handleScan = (data: I2CScanData) => {
|
const triggerScan = async () => {
|
||||||
active_devices = data.devices
|
|
||||||
isLoading = false
|
|
||||||
}
|
|
||||||
|
|
||||||
const triggerScan = () => {
|
|
||||||
isLoading = true
|
isLoading = true
|
||||||
socket.sendEvent(I2CScanDataRequest, {})
|
try {
|
||||||
|
const response = await socket.request({ i2cScanDataRequest: {} })
|
||||||
|
active_devices = response.i2cScanData?.devices ?? []
|
||||||
|
} finally {
|
||||||
|
isLoading = false
|
||||||
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|||||||
+31
-33
@@ -3,6 +3,7 @@
|
|||||||
#include <ESPmDNS.h>
|
#include <ESPmDNS.h>
|
||||||
#include <WiFi.h>
|
#include <WiFi.h>
|
||||||
#include <Wire.h>
|
#include <Wire.h>
|
||||||
|
#include <map>
|
||||||
|
|
||||||
#include <filesystem.h>
|
#include <filesystem.h>
|
||||||
#include <peripherals/peripherals.h>
|
#include <peripherals/peripherals.h>
|
||||||
@@ -150,18 +151,6 @@ void setupEventSocket() {
|
|||||||
socket.on<socket_message_AnglesData>(
|
socket.on<socket_message_AnglesData>(
|
||||||
[&](const socket_message_AnglesData &data, int clientId) { motionService.handleAngles(data); });
|
[&](const socket_message_AnglesData &data, int clientId) { motionService.handleAngles(data); });
|
||||||
|
|
||||||
socket.on<socket_message_I2CScanDataRequest>([&](const socket_message_I2CScanDataRequest &data, int clientId) {
|
|
||||||
peripherals.scanI2C();
|
|
||||||
socket_message_I2CScanData result = socket_message_I2CScanData_init_zero;
|
|
||||||
peripherals.getI2CScanProto(result);
|
|
||||||
socket.emit(result, clientId);
|
|
||||||
});
|
|
||||||
|
|
||||||
socket.on<socket_message_IMUCalibrateExecute>([&](const socket_message_IMUCalibrateExecute &data, int clientId) {
|
|
||||||
socket_message_IMUCalibrateData result = {.success = peripherals.calibrateIMU()};
|
|
||||||
socket.emit(result, clientId);
|
|
||||||
});
|
|
||||||
|
|
||||||
socket.on<socket_message_ServoPWMData>([&](const socket_message_ServoPWMData &data, int clientId) {
|
socket.on<socket_message_ServoPWMData>([&](const socket_message_ServoPWMData &data, int clientId) {
|
||||||
servoController.setServoPWM(data.servo_id, data.servo_pwm);
|
servoController.setServoPWM(data.servo_id, data.servo_pwm);
|
||||||
});
|
});
|
||||||
@@ -170,29 +159,38 @@ void setupEventSocket() {
|
|||||||
data.active ? servoController.activate() : servoController.deactivate();
|
data.active ? servoController.activate() : servoController.deactivate();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
using CorrelationHandler =
|
||||||
|
std::function<void(const socket_message_CorrelationRequest &, socket_message_CorrelationResponse &)>;
|
||||||
|
static std::map<pb_size_t, CorrelationHandler> correlationHandlers = {
|
||||||
|
{socket_message_CorrelationRequest_features_data_request_tag,
|
||||||
|
[](const auto &req, auto &res) {
|
||||||
|
res.which_response = socket_message_CorrelationResponse_features_data_response_tag;
|
||||||
|
feature_service::features_request(req.request.features_data_request, res.response.features_data_response);
|
||||||
|
}},
|
||||||
|
{socket_message_CorrelationRequest_i2c_scan_data_request_tag,
|
||||||
|
[](const auto &req, auto &res) {
|
||||||
|
res.which_response = socket_message_CorrelationResponse_i2c_scan_data_tag;
|
||||||
|
peripherals.scanI2C();
|
||||||
|
peripherals.getI2CScanProto(res.response.i2c_scan_data);
|
||||||
|
}},
|
||||||
|
{socket_message_CorrelationRequest_imu_calibrate_execute_tag,
|
||||||
|
[](const auto &req, auto &res) {
|
||||||
|
res.which_response = socket_message_CorrelationResponse_imu_calibrate_data_tag;
|
||||||
|
res.response.imu_calibrate_data.success = peripherals.calibrateIMU();
|
||||||
|
}},
|
||||||
|
};
|
||||||
|
|
||||||
socket.on<socket_message_CorrelationRequest>([&](const socket_message_CorrelationRequest &data, int clientId) {
|
socket.on<socket_message_CorrelationRequest>([&](const socket_message_CorrelationRequest &data, int clientId) {
|
||||||
printf("Received correlation request: %d\n", data.correlation_id);
|
socket_message_CorrelationResponse res = socket_message_CorrelationResponse_init_default;
|
||||||
// Temporarily hardcoded
|
res.correlation_id = data.correlation_id;
|
||||||
switch (data.which_request) {
|
res.status_code = 200;
|
||||||
case socket_message_CorrelationRequest_features_data_request_tag: {
|
|
||||||
socket_message_CorrelationResponse res = socket_message_CorrelationResponse_init_default;
|
|
||||||
res.correlation_id = data.correlation_id;
|
|
||||||
res.stauts_code = 200;
|
|
||||||
res.which_response = socket_message_CorrelationResponse_features_data_response_tag;
|
|
||||||
|
|
||||||
feature_service::features_request(
|
auto it = correlationHandlers.find(data.which_request);
|
||||||
data.request.features_data_request,
|
if (it != correlationHandlers.end()) {
|
||||||
res.response.features_data_response
|
it->second(data, res);
|
||||||
);
|
socket.emit(res, clientId);
|
||||||
|
} else {
|
||||||
socket.emit(res, clientId);
|
printf("WARNING: no handler for correlation request: %d\n", data.which_request);
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default: {
|
|
||||||
printf("WARNING: no tag found for correlation request: %d", data.which_request);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,111 +8,70 @@
|
|||||||
|
|
||||||
PB_BIND(socket_message_Vector, socket_message_Vector, AUTO)
|
PB_BIND(socket_message_Vector, socket_message_Vector, AUTO)
|
||||||
|
|
||||||
|
|
||||||
PB_BIND(socket_message_I2CDevice, socket_message_I2CDevice, AUTO)
|
PB_BIND(socket_message_I2CDevice, socket_message_I2CDevice, AUTO)
|
||||||
|
|
||||||
|
|
||||||
PB_BIND(socket_message_PinConfig, socket_message_PinConfig, AUTO)
|
PB_BIND(socket_message_PinConfig, socket_message_PinConfig, AUTO)
|
||||||
|
|
||||||
|
|
||||||
PB_BIND(socket_message_KnownNetworkItem, socket_message_KnownNetworkItem, AUTO)
|
PB_BIND(socket_message_KnownNetworkItem, socket_message_KnownNetworkItem, AUTO)
|
||||||
|
|
||||||
|
|
||||||
PB_BIND(socket_message_IMUData, socket_message_IMUData, AUTO)
|
PB_BIND(socket_message_IMUData, socket_message_IMUData, AUTO)
|
||||||
|
|
||||||
|
|
||||||
PB_BIND(socket_message_FeaturesDataResponse, socket_message_FeaturesDataResponse, 2)
|
PB_BIND(socket_message_FeaturesDataResponse, socket_message_FeaturesDataResponse, 2)
|
||||||
|
|
||||||
|
|
||||||
PB_BIND(socket_message_FeaturesDataRequest, socket_message_FeaturesDataRequest, AUTO)
|
PB_BIND(socket_message_FeaturesDataRequest, socket_message_FeaturesDataRequest, AUTO)
|
||||||
|
|
||||||
|
|
||||||
PB_BIND(socket_message_CorrelationRequest, socket_message_CorrelationRequest, AUTO)
|
PB_BIND(socket_message_CorrelationRequest, socket_message_CorrelationRequest, AUTO)
|
||||||
|
|
||||||
|
PB_BIND(socket_message_CorrelationResponse, socket_message_CorrelationResponse, 2)
|
||||||
PB_BIND(socket_message_CorrelationResponse, socket_message_CorrelationResponse, AUTO)
|
|
||||||
|
|
||||||
|
|
||||||
PB_BIND(socket_message_StaticSystemInformation, socket_message_StaticSystemInformation, AUTO)
|
PB_BIND(socket_message_StaticSystemInformation, socket_message_StaticSystemInformation, AUTO)
|
||||||
|
|
||||||
|
|
||||||
PB_BIND(socket_message_IMUCalibrateData, socket_message_IMUCalibrateData, AUTO)
|
PB_BIND(socket_message_IMUCalibrateData, socket_message_IMUCalibrateData, AUTO)
|
||||||
|
|
||||||
|
|
||||||
PB_BIND(socket_message_IMUCalibrateExecute, socket_message_IMUCalibrateExecute, AUTO)
|
PB_BIND(socket_message_IMUCalibrateExecute, socket_message_IMUCalibrateExecute, AUTO)
|
||||||
|
|
||||||
|
|
||||||
PB_BIND(socket_message_ModeData, socket_message_ModeData, AUTO)
|
PB_BIND(socket_message_ModeData, socket_message_ModeData, AUTO)
|
||||||
|
|
||||||
|
|
||||||
PB_BIND(socket_message_ControllerInputData, socket_message_ControllerInputData, AUTO)
|
PB_BIND(socket_message_ControllerInputData, socket_message_ControllerInputData, AUTO)
|
||||||
|
|
||||||
|
|
||||||
PB_BIND(socket_message_AnalyticsData, socket_message_AnalyticsData, AUTO)
|
PB_BIND(socket_message_AnalyticsData, socket_message_AnalyticsData, AUTO)
|
||||||
|
|
||||||
|
|
||||||
PB_BIND(socket_message_ServoPWMData, socket_message_ServoPWMData, AUTO)
|
PB_BIND(socket_message_ServoPWMData, socket_message_ServoPWMData, AUTO)
|
||||||
|
|
||||||
|
|
||||||
PB_BIND(socket_message_ServoStateData, socket_message_ServoStateData, AUTO)
|
PB_BIND(socket_message_ServoStateData, socket_message_ServoStateData, AUTO)
|
||||||
|
|
||||||
|
|
||||||
PB_BIND(socket_message_AnglesData, socket_message_AnglesData, AUTO)
|
PB_BIND(socket_message_AnglesData, socket_message_AnglesData, AUTO)
|
||||||
|
|
||||||
|
|
||||||
PB_BIND(socket_message_I2CScanData, socket_message_I2CScanData, 2)
|
PB_BIND(socket_message_I2CScanData, socket_message_I2CScanData, 2)
|
||||||
|
|
||||||
|
|
||||||
PB_BIND(socket_message_I2CScanDataRequest, socket_message_I2CScanDataRequest, AUTO)
|
PB_BIND(socket_message_I2CScanDataRequest, socket_message_I2CScanDataRequest, AUTO)
|
||||||
|
|
||||||
|
|
||||||
PB_BIND(socket_message_PeripheralSettingsData, socket_message_PeripheralSettingsData, 2)
|
PB_BIND(socket_message_PeripheralSettingsData, socket_message_PeripheralSettingsData, 2)
|
||||||
|
|
||||||
|
|
||||||
PB_BIND(socket_message_PeripheralSettingsDataRequest, socket_message_PeripheralSettingsDataRequest, AUTO)
|
PB_BIND(socket_message_PeripheralSettingsDataRequest, socket_message_PeripheralSettingsDataRequest, AUTO)
|
||||||
|
|
||||||
|
|
||||||
PB_BIND(socket_message_WifiSettingsData, socket_message_WifiSettingsData, 2)
|
PB_BIND(socket_message_WifiSettingsData, socket_message_WifiSettingsData, 2)
|
||||||
|
|
||||||
|
|
||||||
PB_BIND(socket_message_RSSIData, socket_message_RSSIData, AUTO)
|
PB_BIND(socket_message_RSSIData, socket_message_RSSIData, AUTO)
|
||||||
|
|
||||||
|
|
||||||
PB_BIND(socket_message_DownloadOTAData, socket_message_DownloadOTAData, AUTO)
|
PB_BIND(socket_message_DownloadOTAData, socket_message_DownloadOTAData, AUTO)
|
||||||
|
|
||||||
|
|
||||||
PB_BIND(socket_message_SonarData, socket_message_SonarData, AUTO)
|
PB_BIND(socket_message_SonarData, socket_message_SonarData, AUTO)
|
||||||
|
|
||||||
|
|
||||||
PB_BIND(socket_message_HumanInputData, socket_message_HumanInputData, AUTO)
|
PB_BIND(socket_message_HumanInputData, socket_message_HumanInputData, AUTO)
|
||||||
|
|
||||||
|
|
||||||
PB_BIND(socket_message_SystemInformation, socket_message_SystemInformation, 2)
|
PB_BIND(socket_message_SystemInformation, socket_message_SystemInformation, 2)
|
||||||
|
|
||||||
|
|
||||||
PB_BIND(socket_message_WalkGaitData, socket_message_WalkGaitData, AUTO)
|
PB_BIND(socket_message_WalkGaitData, socket_message_WalkGaitData, AUTO)
|
||||||
|
|
||||||
|
|
||||||
PB_BIND(socket_message_KinematicData, socket_message_KinematicData, AUTO)
|
PB_BIND(socket_message_KinematicData, socket_message_KinematicData, AUTO)
|
||||||
|
|
||||||
|
|
||||||
PB_BIND(socket_message_SubscribeNotification, socket_message_SubscribeNotification, AUTO)
|
PB_BIND(socket_message_SubscribeNotification, socket_message_SubscribeNotification, AUTO)
|
||||||
|
|
||||||
|
|
||||||
PB_BIND(socket_message_UnsubscribeNotification, socket_message_UnsubscribeNotification, AUTO)
|
PB_BIND(socket_message_UnsubscribeNotification, socket_message_UnsubscribeNotification, AUTO)
|
||||||
|
|
||||||
|
|
||||||
PB_BIND(socket_message_PingMsg, socket_message_PingMsg, AUTO)
|
PB_BIND(socket_message_PingMsg, socket_message_PingMsg, AUTO)
|
||||||
|
|
||||||
|
|
||||||
PB_BIND(socket_message_PongMsg, socket_message_PongMsg, AUTO)
|
PB_BIND(socket_message_PongMsg, socket_message_PongMsg, AUTO)
|
||||||
|
|
||||||
|
|
||||||
PB_BIND(socket_message_WebsocketMessage, socket_message_WebsocketMessage, 2)
|
PB_BIND(socket_message_WebsocketMessage, socket_message_WebsocketMessage, 2)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -42,19 +42,20 @@ message FeaturesDataRequest { bool sonar_test = 1; }
|
|||||||
|
|
||||||
|
|
||||||
message CorrelationRequest {
|
message CorrelationRequest {
|
||||||
uint32 correlation_id = 1; // Used for request-response correlation
|
uint32 correlation_id = 1;
|
||||||
oneof request {
|
oneof request {
|
||||||
// NOTE: requests must have same tag id as correlating to the response type (currently not enforced in C, but will be, and tests will fail)
|
|
||||||
FeaturesDataRequest features_data_request = 10;
|
FeaturesDataRequest features_data_request = 10;
|
||||||
|
I2CScanDataRequest i2c_scan_data_request = 20;
|
||||||
|
IMUCalibrateExecute imu_calibrate_execute = 30;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
message CorrelationResponse {
|
message CorrelationResponse {
|
||||||
uint32 correlation_id = 1; // Used for request-response correlation'
|
uint32 correlation_id = 1;
|
||||||
uint32 stauts_code = 2;
|
uint32 status_code = 2;
|
||||||
oneof response {
|
oneof response {
|
||||||
// NOTE: responses must have same tag id as correlating to the request type (currently not enforced in C, but will be, and tests will fail)
|
|
||||||
FeaturesDataResponse features_data_response = 10;
|
FeaturesDataResponse features_data_response = 10;
|
||||||
|
I2CScanData i2c_scan_data = 20;
|
||||||
|
IMUCalibrateData imu_calibrate_data = 30;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user