Adjusted parts of routes layout to work with protobufs

This commit is contained in:
Niklas Jensen
2026-01-01 20:10:13 +01:00
committed by nikguin04
parent a53bf806ac
commit a8abaaaf61
7 changed files with 284 additions and 66 deletions
@@ -104,6 +104,16 @@ export interface RSSIData {
rssi: number; rssi: number;
} }
export interface DownloadOTAData {
status: string;
progress: number;
error: string;
}
export interface SonarData {
dummyField: string;
}
export interface SubscribeNotification { export interface SubscribeNotification {
tag: number; tag: number;
} }
@@ -1604,6 +1614,156 @@ export const RSSIData: MessageFns<RSSIData> = {
}, },
}; };
function createBaseDownloadOTAData(): DownloadOTAData {
return { status: "", progress: 0, error: "" };
}
export const DownloadOTAData: MessageFns<DownloadOTAData> = {
encode(message: DownloadOTAData, writer: BinaryWriter = new BinaryWriter()): BinaryWriter {
if (message.status !== "") {
writer.uint32(10).string(message.status);
}
if (message.progress !== 0) {
writer.uint32(16).int32(message.progress);
}
if (message.error !== "") {
writer.uint32(26).string(message.error);
}
return writer;
},
decode(input: BinaryReader | Uint8Array, length?: number): DownloadOTAData {
const reader = input instanceof BinaryReader ? input : new BinaryReader(input);
const end = length === undefined ? reader.len : reader.pos + length;
const message = createBaseDownloadOTAData();
while (reader.pos < end) {
const tag = reader.uint32();
switch (tag >>> 3) {
case 1: {
if (tag !== 10) {
break;
}
message.status = reader.string();
continue;
}
case 2: {
if (tag !== 16) {
break;
}
message.progress = reader.int32();
continue;
}
case 3: {
if (tag !== 26) {
break;
}
message.error = reader.string();
continue;
}
}
if ((tag & 7) === 4 || tag === 0) {
break;
}
reader.skip(tag & 7);
}
return message;
},
fromJSON(object: any): DownloadOTAData {
return {
status: isSet(object.status) ? globalThis.String(object.status) : "",
progress: isSet(object.progress) ? globalThis.Number(object.progress) : 0,
error: isSet(object.error) ? globalThis.String(object.error) : "",
};
},
toJSON(message: DownloadOTAData): unknown {
const obj: any = {};
if (message.status !== "") {
obj.status = message.status;
}
if (message.progress !== 0) {
obj.progress = Math.round(message.progress);
}
if (message.error !== "") {
obj.error = message.error;
}
return obj;
},
create<I extends Exact<DeepPartial<DownloadOTAData>, I>>(base?: I): DownloadOTAData {
return DownloadOTAData.fromPartial(base ?? ({} as any));
},
fromPartial<I extends Exact<DeepPartial<DownloadOTAData>, I>>(object: I): DownloadOTAData {
const message = createBaseDownloadOTAData();
message.status = object.status ?? "";
message.progress = object.progress ?? 0;
message.error = object.error ?? "";
return message;
},
};
function createBaseSonarData(): SonarData {
return { dummyField: "" };
}
export const SonarData: MessageFns<SonarData> = {
encode(message: SonarData, writer: BinaryWriter = new BinaryWriter()): BinaryWriter {
if (message.dummyField !== "") {
writer.uint32(10).string(message.dummyField);
}
return writer;
},
decode(input: BinaryReader | Uint8Array, length?: number): SonarData {
const reader = input instanceof BinaryReader ? input : new BinaryReader(input);
const end = length === undefined ? reader.len : reader.pos + length;
const message = createBaseSonarData();
while (reader.pos < end) {
const tag = reader.uint32();
switch (tag >>> 3) {
case 1: {
if (tag !== 10) {
break;
}
message.dummyField = reader.string();
continue;
}
}
if ((tag & 7) === 4 || tag === 0) {
break;
}
reader.skip(tag & 7);
}
return message;
},
fromJSON(object: any): SonarData {
return { dummyField: isSet(object.dummyField) ? globalThis.String(object.dummyField) : "" };
},
toJSON(message: SonarData): unknown {
const obj: any = {};
if (message.dummyField !== "") {
obj.dummyField = message.dummyField;
}
return obj;
},
create<I extends Exact<DeepPartial<SonarData>, I>>(base?: I): SonarData {
return SonarData.fromPartial(base ?? ({} as any));
},
fromPartial<I extends Exact<DeepPartial<SonarData>, I>>(object: I): SonarData {
const message = createBaseSonarData();
message.dummyField = object.dummyField ?? "";
return message;
},
};
function createBaseSubscribeNotification(): SubscribeNotification { function createBaseSubscribeNotification(): SubscribeNotification {
return { tag: 0 }; return { tag: 0 };
} }
@@ -2928,6 +3088,78 @@ export const protoMetadata: ProtoMetadata = {
"reservedRange": [], "reservedRange": [],
"reservedName": [], "reservedName": [],
"visibility": 0, "visibility": 0,
}, {
"name": "DownloadOTAData",
"field": [{
"name": "status",
"number": 1,
"label": 1,
"type": 9,
"typeName": "",
"extendee": "",
"defaultValue": "",
"oneofIndex": 0,
"jsonName": "status",
"options": undefined,
"proto3Optional": false,
}, {
"name": "progress",
"number": 2,
"label": 1,
"type": 5,
"typeName": "",
"extendee": "",
"defaultValue": "",
"oneofIndex": 0,
"jsonName": "progress",
"options": undefined,
"proto3Optional": false,
}, {
"name": "error",
"number": 3,
"label": 1,
"type": 9,
"typeName": "",
"extendee": "",
"defaultValue": "",
"oneofIndex": 0,
"jsonName": "error",
"options": undefined,
"proto3Optional": false,
}],
"extension": [],
"nestedType": [],
"enumType": [],
"extensionRange": [],
"oneofDecl": [],
"options": undefined,
"reservedRange": [],
"reservedName": [],
"visibility": 0,
}, {
"name": "SonarData",
"field": [{
"name": "dummy_field",
"number": 1,
"label": 1,
"type": 9,
"typeName": "",
"extendee": "",
"defaultValue": "",
"oneofIndex": 0,
"jsonName": "dummyField",
"options": undefined,
"proto3Optional": false,
}],
"extension": [],
"nestedType": [],
"enumType": [],
"extensionRange": [],
"oneofDecl": [],
"options": undefined,
"reservedRange": [],
"reservedName": [],
"visibility": 0,
}, { }, {
"name": "SubscribeNotification", "name": "SubscribeNotification",
"field": [{ "field": [{
@@ -3193,8 +3425,8 @@ export const protoMetadata: ProtoMetadata = {
"trailingComments": "", "trailingComments": "",
"leadingDetachedComments": [], "leadingDetachedComments": [],
}, { }, {
"path": [4, 18], "path": [4, 20],
"span": [54, 0, 71, 1], "span": [56, 0, 73, 1],
"leadingComments": " WebSocket message wrapper\n Only ONE field will be set at a time (oneof ensures this)\n", "leadingComments": " WebSocket message wrapper\n Only ONE field will be set at a time (oneof ensures this)\n",
"trailingComments": "", "trailingComments": "",
"leadingDetachedComments": [], "leadingDetachedComments": [],
@@ -3218,6 +3450,8 @@ export const protoMetadata: ProtoMetadata = {
".PeripheralSettingsData": PeripheralSettingsData, ".PeripheralSettingsData": PeripheralSettingsData,
".WifiSettingsData": WifiSettingsData, ".WifiSettingsData": WifiSettingsData,
".RSSIData": RSSIData, ".RSSIData": RSSIData,
".DownloadOTAData": DownloadOTAData,
".SonarData": SonarData,
".SubscribeNotification": SubscribeNotification, ".SubscribeNotification": SubscribeNotification,
".UnsubscribeNotification": UnsubscribeNotification, ".UnsubscribeNotification": UnsubscribeNotification,
".PingMsg": PingMsg, ".PingMsg": PingMsg,
+19 -8
View File
@@ -142,19 +142,27 @@ function createWebSocket() {
ws.onclose = ev => disconnect('close', ev) ws.onclose = ev => disconnect('close', ev)
} }
function unsubscribe(event_type: MessageFns<any>, listener: (data: unknown) => void) { function unsubscribe<MT>(event_type: MessageFns<MT>, listener: (data: MT) => void) {
const tag = get_tag_from_messagetype(event_type) const tag = get_tag_from_messagetype(event_type)
const message_listeners_totag = message_listeners.get(tag) const message_listeners_totag = message_listeners.get(tag)
if (!message_listeners_totag) return if (!message_listeners_totag) return
// TODO: This looks like it deletes an individual listener, but unsubscribe unsubscribes for everyone. Not sure what it is supposed to do right now // TODO: This looks like it deletes an individual listener, but unsubscribe unsubscribes for everyone. Not sure what it is supposed to do right now
message_listeners_totag?.delete(listener) message_listeners_totag?.delete(listener as (data?: unknown) => void)
if (message_listeners_totag.size == 0) { // No more listeners, so we can unsubscribe if (message_listeners_totag.size == 0) { // No more listeners, so we can unsubscribe
unsubscribeToEvent(event_type) unsubscribeToMessageFromServer(event_type)
} }
} }
function unsubscribe_event(event_type: SocketEvent, listener: (data: unknown) => void) {
const message_listeners_totag = event_listeners.get(event_type)
if (!message_listeners_totag) return
message_listeners_totag?.delete(listener)
}
function resetUnresponsiveCheck() { function resetUnresponsiveCheck() {
clearTimeout(unresponsiveTimeoutId) clearTimeout(unresponsiveTimeoutId)
unresponsiveTimeoutId = setTimeout(() => disconnect('unresponsive'), reconnectTimeoutTime) unresponsiveTimeoutId = setTimeout(() => disconnect('unresponsive'), reconnectTimeoutTime)
@@ -169,7 +177,7 @@ function createWebSocket() {
send(wsm) send(wsm)
} }
function unsubscribeToEvent<T>(event_type: MessageFns<T>) { function unsubscribeToMessageFromServer<T>(event_type: MessageFns<T>) {
if (!ws || ws.readyState !== WebSocket.OPEN) return if (!ws || ws.readyState !== WebSocket.OPEN) return
const event = get_name_from_messagetype(event_type); const event = get_name_from_messagetype(event_type);
const unsub_msg = WebsocketMessages.UnsubscribeNotification.create( const unsub_msg = WebsocketMessages.UnsubscribeNotification.create(
@@ -201,7 +209,7 @@ function createWebSocket() {
subscribe, subscribe,
sendEvent, sendEvent,
init, init,
on: <MT, T>(event_type: MessageFns<MT>, listener: (data: T) => void): (() => void) => { on: <MT>(event_type: MessageFns<MT>, listener: (data: MT) => void): (() => void) => {
const tag = get_tag_from_messagetype(event_type); const tag = get_tag_from_messagetype(event_type);
let message_listeners_totag = message_listeners.get(tag) let message_listeners_totag = message_listeners.get(tag)
@@ -213,11 +221,14 @@ function createWebSocket() {
message_listeners_totag.add(listener as (data: unknown) => void) message_listeners_totag.add(listener as (data: unknown) => void)
return () => { return () => {
unsubscribe(event_type, listener as (data: unknown) => void) unsubscribe(event_type, listener)
} }
}, },
off: <MT, T>(event_type: MessageFns<MT>, listener: (data: T) => void) => { onEvent: (event_type: SocketEvent, listener: (data: unknown) => void): (() => void) => {
unsubscribe(event_type, listener as (data: unknown) => void)
return () => {
unsubscribe_event(event_type, listener)
}
} }
} }
} }
+9 -19
View File
@@ -1,33 +1,23 @@
import type { DownloadOTA } from '$lib/types/models' import { DownloadOTAData, RSSIData } from '$lib/platform_shared/websocket_message'
import { DownloadOTA } from '$lib/types/models'
import { writable } from 'svelte/store' import { writable } from 'svelte/store'
const telemetry_data = { type telemetry_data_type = {
rssi: { rssi: RSSIData;
rssi: 0 download_ota: DownloadOTAData;
},
download_ota: {
status: 'none',
progress: 0,
error: ''
}
} }
const telemetry_data: telemetry_data_type = { rssi: RSSIData.create(), download_ota: DownloadOTAData.create() }; // Note: perhaps init these as null instead of an undefined create()
function createTelemetry() { function createTelemetry() {
const { subscribe, update } = writable(telemetry_data) const { subscribe, update } = writable(telemetry_data)
return { return {
subscribe, subscribe,
setRSSI: (data: number) => { setRSSI: (data: RSSIData) => {
update(telemetry_data => ({ update(telemetry_data => { telemetry_data.rssi = data; return telemetry_data })
...telemetry_data,
rssi: { rssi: data }
}))
}, },
setDownloadOTA: (data: DownloadOTA) => { setDownloadOTA: (data: DownloadOTA) => {
update(telemetry_data => ({ update(telemetry_data => { telemetry_data.download_ota = data; return telemetry_data })
...telemetry_data,
download_ota: { status: data.status, progress: data.progress, error: data.error }
}))
} }
} }
} }
-5
View File
@@ -59,11 +59,6 @@ export type ApSettings = {
subnet_mask: string subnet_mask: string
} }
export type DownloadOTA = {
status: string
progress: number
error: string
}
export type Rssi = { export type Rssi = {
rssi: number rssi: number
+17 -31
View File
@@ -22,15 +22,8 @@
useFeatureFlags, useFeatureFlags,
walkGait walkGait
} from '$lib/stores' } from '$lib/stores'
import { type Analytics, type DownloadOTA } from '$lib/types/models' import { AnalyticsData, AnglesData, DownloadOTAData, ModeData, RSSIData, SonarData } from '$lib/platform_shared/websocket_message'
import { Throttler } from '$lib/utilities' import { Throttler } from '$lib/utilities'
import {
AnglesData,
GaitData,
InputData,
ModeData,
PositionData
} from '$lib/platform_shared/websocket_message'
interface Props { interface Props {
children?: import('svelte').Snippet children?: import('svelte').Snippet
@@ -58,28 +51,27 @@
removeEventListeners() removeEventListeners()
}) })
const eventListeners: (() => void)[] = [];
const addEventListeners = () => { const addEventListeners = () => {
socket.on('open', handleOpen) eventListeners.push(...[
socket.on('close', handleClose) socket.onEvent('open', handleOpen),
socket.on('error', handleError) socket.onEvent('close', handleClose),
socket.on(MessageTopic.rssi, handleNetworkStatus) socket.onEvent('error', handleError),
socket.on(MessageTopic.mode, (data: ModesEnum) => mode.set(data)) socket.on(RSSIData, (data) => telemetry.setRSSI(data)),
socket.on(MessageTopic.analytics, handleAnalytics) socket.on(ModeData, (data) => mode.set(data.mode)),
socket.on(MessageTopic.angles, (angles: number[]) => { socket.on(AnalyticsData, (data) => {analytics.addData(data)}),
if (angles.length) servoAngles.set(angles) socket.on(AnglesData, (data) => {servoAngles.set(data.angles)})
}) ])
features.subscribe(data => { features.subscribe(data => {
if (data?.download_firmware) socket.on(MessageTopic.otastatus, handleOAT) if (data?.download_firmware) eventListeners.push( socket.on(DownloadOTAData, (data) => telemetry.setDownloadOTA(data)) )
if (data?.sonar) socket.on(MessageTopic.sonar, data => console.log(data)) if (data?.sonar) eventListeners.push( socket.on(SonarData, (data) => console.log(data)) )
}) })
} }
const removeEventListeners = () => { const removeEventListeners = () => {
socket.off(MessageTopic.analytics, handleAnalytics) for (let offFunction of eventListeners) {
socket.off('open', handleOpen) offFunction();
socket.off('close', handleClose) }
socket.off(MessageTopic.rssi, handleNetworkStatus)
socket.off(MessageTopic.otastatus, handleOAT)
} }
const handleOpen = () => { const handleOpen = () => {
@@ -88,17 +80,11 @@
const handleClose = () => { const handleClose = () => {
notifications.error('Connection to device lost', 5000) notifications.error('Connection to device lost', 5000)
telemetry.setRSSI(0) telemetry.setRSSI( RSSIData.create({rssi: 0}) )
} }
const handleError = (data: unknown) => console.error(data) const handleError = (data: unknown) => console.error(data)
const handleAnalytics = (data: Analytics) => analytics.addData(data)
const handleNetworkStatus = (data: number) => telemetry.setRSSI(data)
const handleOAT = (data: DownloadOTA) => telemetry.setDownloadOTA(data)
let menuOpen = $state(false) let menuOpen = $state(false)
</script> </script>
+1 -1
View File
@@ -3,7 +3,7 @@ This file is temporary, just to show how ot compile the proto files
Make sure to actually create the output directories before executing the commands Make sure to actually create the output directories before executing the commands
TS: TS:
rotoc --plugin="protoc-gen-ts_proto=$(Resolve-Path app\node_modules\.bin\protoc-gen-ts_proto.CMD)" --ts_proto_out="./app/src/lib" --ts_proto_opt=outputSchema=true ".\platform_shared\websocket_message.proto" protoc --plugin="protoc-gen-ts_proto=$(Resolve-Path app\node_modules\.bin\protoc-gen-ts_proto.CMD)" --ts_proto_out="./app/src/lib" --ts_proto_opt=outputSchema=true ".\platform_shared\websocket_message.proto"
NEW TS (USING PROTOBUFJS): NEW TS (USING PROTOBUFJS):
cd app cd app
+2
View File
@@ -42,6 +42,8 @@ message I2CScanData { repeated I2CDevice devices = 1; }
message PeripheralSettingsData { int32 sda = 1; int32 scl = 2; int32 frequency = 3; repeated PinConfig pins = 4; } message PeripheralSettingsData { int32 sda = 1; int32 scl = 2; int32 frequency = 3; repeated PinConfig pins = 4; }
message WifiSettingsData { string hostname = 1; bool priority_rssi = 2; repeated KnownNetworkItem wifi_networks = 3; } message WifiSettingsData { string hostname = 1; bool priority_rssi = 2; repeated KnownNetworkItem wifi_networks = 3; }
message RSSIData { int32 rssi = 1; } message RSSIData { int32 rssi = 1; }
message DownloadOTAData { string status = 1; int32 progress = 2; string error = 3; }
message SonarData { string dummy_field = 1; }
message SubscribeNotification { int32 tag = 1; } message SubscribeNotification { int32 tag = 1; }
message UnsubscribeNotification {int32 tag = 1; } message UnsubscribeNotification {int32 tag = 1; }