From 8c45f66137b5ba3b7e93ca1f4e44bc6b42ffc17d Mon Sep 17 00:00:00 2001 From: Niklas Jensen Date: Mon, 29 Dec 2025 21:06:29 +0100 Subject: [PATCH] Idea of how typescript should decode Protobuffer --- .../{example.ts => imu_report.ts} | 130 ++++++++++-------- app/src/lib/stores/imu.ts | 30 ++-- app/src/lib/stores/socket.ts | 20 ++- app/src/routes/peripherals/imu/imu.svelte | 7 +- 4 files changed, 106 insertions(+), 81 deletions(-) rename app/src/lib/platform_shared/{example.ts => imu_report.ts} (57%) diff --git a/app/src/lib/platform_shared/example.ts b/app/src/lib/platform_shared/imu_report.ts similarity index 57% rename from app/src/lib/platform_shared/example.ts rename to app/src/lib/platform_shared/imu_report.ts index cc45c9b..de72df5 100644 --- a/app/src/lib/platform_shared/example.ts +++ b/app/src/lib/platform_shared/imu_report.ts @@ -2,68 +2,41 @@ // versions: // protoc-gen-ts_proto v2.10.1 // protoc v6.33.2 -// source: platform_shared/example.proto +// source: platform_shared/imu_report.proto /* eslint-disable */ import { BinaryReader, BinaryWriter } from "@bufbuild/protobuf/wire"; export const protobufPackage = ""; -export enum IMUType { - IMU_NONE = 0, - IMU_ACCEL = 1, - IMU_GYRO = 2, - UNRECOGNIZED = -1, -} - -export function iMUTypeFromJSON(object: any): IMUType { - switch (object) { - case 0: - case "IMU_NONE": - return IMUType.IMU_NONE; - case 1: - case "IMU_ACCEL": - return IMUType.IMU_ACCEL; - case 2: - case "IMU_GYRO": - return IMUType.IMU_GYRO; - case -1: - case "UNRECOGNIZED": - default: - return IMUType.UNRECOGNIZED; - } -} - -export function iMUTypeToJSON(object: IMUType): string { - switch (object) { - case IMUType.IMU_NONE: - return "IMU_NONE"; - case IMUType.IMU_ACCEL: - return "IMU_ACCEL"; - case IMUType.IMU_GYRO: - return "IMU_GYRO"; - case IMUType.UNRECOGNIZED: - default: - return "UNRECOGNIZED"; - } -} - export interface IMUReport { - type: IMUType; - xVal: number; + x: number; + y: number; + z: number; + temp: number; + success: boolean; } function createBaseIMUReport(): IMUReport { - return { type: 0, xVal: 0 }; + return { x: 0, y: 0, z: 0, temp: 0, success: false }; } export const IMUReport: MessageFns = { encode(message: IMUReport, writer: BinaryWriter = new BinaryWriter()): BinaryWriter { - if (message.type !== 0) { - writer.uint32(8).int32(message.type); + if (message.x !== 0) { + writer.uint32(13).float(message.x); } - if (message.xVal !== 0) { - writer.uint32(17).double(message.xVal); + if (message.y !== 0) { + writer.uint32(21).float(message.y); + } + if (message.z !== 0) { + writer.uint32(29).float(message.z); + } + if (message.temp !== 0) { + writer.uint32(37).float(message.temp); + } + if (message.success !== false) { + writer.uint32(40).bool(message.success); } return writer; }, @@ -76,19 +49,43 @@ export const IMUReport: MessageFns = { const tag = reader.uint32(); switch (tag >>> 3) { case 1: { - if (tag !== 8) { + if (tag !== 13) { break; } - message.type = reader.int32() as any; + message.x = reader.float(); continue; } case 2: { - if (tag !== 17) { + if (tag !== 21) { break; } - message.xVal = reader.double(); + message.y = reader.float(); + continue; + } + case 3: { + if (tag !== 29) { + break; + } + + message.z = reader.float(); + continue; + } + case 4: { + if (tag !== 37) { + break; + } + + message.temp = reader.float(); + continue; + } + case 5: { + if (tag !== 40) { + break; + } + + message.success = reader.bool(); continue; } } @@ -102,18 +99,30 @@ export const IMUReport: MessageFns = { fromJSON(object: any): IMUReport { return { - type: isSet(object.type) ? iMUTypeFromJSON(object.type) : 0, - xVal: isSet(object.xVal) ? globalThis.Number(object.xVal) : 0, + x: isSet(object.x) ? globalThis.Number(object.x) : 0, + y: isSet(object.y) ? globalThis.Number(object.y) : 0, + z: isSet(object.z) ? globalThis.Number(object.z) : 0, + temp: isSet(object.temp) ? globalThis.Number(object.temp) : 0, + success: isSet(object.success) ? globalThis.Boolean(object.success) : false, }; }, toJSON(message: IMUReport): unknown { const obj: any = {}; - if (message.type !== 0) { - obj.type = iMUTypeToJSON(message.type); + if (message.x !== 0) { + obj.x = message.x; } - if (message.xVal !== 0) { - obj.xVal = message.xVal; + if (message.y !== 0) { + obj.y = message.y; + } + if (message.z !== 0) { + obj.z = message.z; + } + if (message.temp !== 0) { + obj.temp = message.temp; + } + if (message.success !== false) { + obj.success = message.success; } return obj; }, @@ -123,8 +132,11 @@ export const IMUReport: MessageFns = { }, fromPartial, I>>(object: I): IMUReport { const message = createBaseIMUReport(); - message.type = object.type ?? 0; - message.xVal = object.xVal ?? 0; + message.x = object.x ?? 0; + message.y = object.y ?? 0; + message.z = object.z ?? 0; + message.temp = object.temp ?? 0; + message.success = object.success ?? false; return message; }, }; diff --git a/app/src/lib/stores/imu.ts b/app/src/lib/stores/imu.ts index 7ce44ae..c486d6f 100644 --- a/app/src/lib/stores/imu.ts +++ b/app/src/lib/stores/imu.ts @@ -1,5 +1,6 @@ import { writable } from 'svelte/store' import type { IMUMsg } from '$lib/types/models' +import type { IMUReport } from '$lib/platform_shared/imu_report' const maxIMUData = 100 @@ -14,23 +15,24 @@ export const imu = (() => { bmp_temp: [] as number[] }) - const addData = (content: IMUMsg) => { + const addData = (content: IMUReport) => { update(data => { - if (content.imu && content.imu[4]) { - data.x = [...data.x, content.imu[0]].slice(-maxIMUData) - data.y = [...data.y, content.imu[1]].slice(-maxIMUData) - data.z = [...data.z, content.imu[2]].slice(-maxIMUData) - } + if (content.success) { + data.x = [...data.x, content.x].slice(-maxIMUData) + data.y = [...data.y, content.y].slice(-maxIMUData) + data.z = [...data.z, content.z].slice(-maxIMUData) + } - if (content.mag && content.mag[4]) { - data.heading = [...data.heading, content.mag[3]].slice(-maxIMUData) - } + // TODO: Temporarily disabled + // if (content.mag && content.mag[4]) { + // data.heading = [...data.heading, content.mag[3]].slice(-maxIMUData) + // } - if (content.bmp && content.bmp[3]) { - data.pressure = [...data.pressure, content.bmp[0]].slice(-maxIMUData) - data.altitude = [...data.altitude, content.bmp[1]].slice(-maxIMUData) - data.bmp_temp = [...data.bmp_temp, content.bmp[2]].slice(-maxIMUData) - } + // if (content.bmp && content.bmp[3]) { + // data.pressure = [...data.pressure, content.bmp[0]].slice(-maxIMUData) + // data.altitude = [...data.altitude, content.bmp[1]].slice(-maxIMUData) + // data.bmp_temp = [...data.bmp_temp, content.bmp[2]].slice(-maxIMUData) + // } return data }) diff --git a/app/src/lib/stores/socket.ts b/app/src/lib/stores/socket.ts index bf976d9..2f86aba 100644 --- a/app/src/lib/stores/socket.ts +++ b/app/src/lib/stores/socket.ts @@ -4,18 +4,24 @@ import { encode, decode } from '@msgpack/msgpack' const socketEvents = ['open', 'close', 'error', 'message', 'unresponsive'] as const type SocketEvent = (typeof socketEvents)[number] -type SocketMessage = [number, string?, unknown?] +type SocketMessage = [string, ArrayBuffer] let useBinary = false -const decodeMessage = (data: string | ArrayBuffer): SocketMessage | null => { - useBinary = data instanceof ArrayBuffer + + +const decodeMessage = (data: ArrayBuffer): SocketMessage | null => { try { - if (useBinary) { - return decode(new Uint8Array(data as ArrayBuffer)) as SocketMessage + const view = new Uint8Array(data); + let comma_index: number = 0; + let tag: string = ""; + for (comma_index = 0; view[comma_index] != 0x2c; comma_index++) { // 0x2c is the ascii code for a comma! + tag += String.fromCharCode(view[comma_index]); + if (comma_index >= data.byteLength) { throw new RangeError("Comma index exceeded")} } - return JSON.parse(data as string) + + return [ tag, data.slice(comma_index+1) ] } catch (error) { console.error(`Could not decode data: ${new Uint8Array(data as ArrayBuffer)} - ${error}`) } @@ -72,7 +78,7 @@ function createWebSocket() { resetUnresponsiveCheck() const message = decodeMessage(frame.data) if (!message) return - const [, event, payload = undefined] = message + const [event, payload] = message if (event) listeners.get(event)?.forEach(listener => listener(payload)) } ws.onerror = ev => disconnect('error', ev) diff --git a/app/src/routes/peripherals/imu/imu.svelte b/app/src/routes/peripherals/imu/imu.svelte index ec65d26..8bf6d7d 100644 --- a/app/src/routes/peripherals/imu/imu.svelte +++ b/app/src/routes/peripherals/imu/imu.svelte @@ -10,6 +10,9 @@ import { useFeatureFlags } from '$lib/stores/featureFlags' import { Rotate3d } from '$lib/components/icons' + import { IMUReport } from '$lib/platform_shared/imu_report'; + import { BinaryReader, BinaryWriter } from "@bufbuild/protobuf/wire"; + Chart.register(...registerables) const features = useFeatureFlags() @@ -203,7 +206,9 @@ } onMount(() => { - socket.on(MessageTopic.imu, (data: IMUMsg) => { + socket.on(MessageTopic.imu, (buffer: ArrayBuffer) => { + // Temporary conversions here + let data = IMUReport.decode(new BinaryReader(new Uint8Array(buffer))) console.log(data) imu.addData(data) })