From 8e7484e86422e0a8105c89f0240aa7351185a44d Mon Sep 17 00:00:00 2001 From: Rune Harlyk Date: Fri, 23 Feb 2024 12:08:41 +0100 Subject: [PATCH] =?UTF-8?q?=F0=9F=8C=8D=20Split=20socket=20service=20from?= =?UTF-8?q?=20stores?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/src/components/Views/Model.svelte | 6 +- app/src/lib/models.ts | 13 ++++ app/src/lib/services/index.ts | 1 + app/src/lib/services/socket-service.ts | 102 +++++++++++-------------- app/src/lib/stores/index.ts | 1 + app/src/lib/stores/socket-store.ts | 31 ++++++++ 6 files changed, 92 insertions(+), 62 deletions(-) create mode 100644 app/src/lib/models.ts create mode 100644 app/src/lib/stores/socket-store.ts diff --git a/app/src/components/Views/Model.svelte b/app/src/components/Views/Model.svelte index fae33ed..2f4d64e 100644 --- a/app/src/components/Views/Model.svelte +++ b/app/src/components/Views/Model.svelte @@ -8,11 +8,9 @@ import { ForwardKinematics } from '$lib/kinematic'; import { location } from '$lib/utilities'; import { fileService } from '$lib/services'; + import { servoAngles, mpu } from '$lib/stores'; import SceneBuilder from '$lib/sceneBuilder'; - const angles = socketService.angles; - const mpu = socketService.mpu; - let sceneManager: SceneBuilder; let canvas: HTMLCanvasElement, streamCanvas: HTMLCanvasElement, stream: HTMLImageElement; let context: CanvasRenderingContext2D, texture: CanvasTexture; @@ -142,7 +140,7 @@ ); robot.position.y = Math.max(...points.map((coord) => coord[0] / 100)) - 2.7; robot.rotation.z = lerp(robot.rotation.z, degToRad($mpu.heading + 90), 0.1); - modelTargetAngles = $angles; + modelTargetAngles = $servoAngles; handleVideoStream(); diff --git a/app/src/lib/models.ts b/app/src/lib/models.ts new file mode 100644 index 0000000..f23f351 --- /dev/null +++ b/app/src/lib/models.ts @@ -0,0 +1,13 @@ +export type angles = number[] | Int16Array; + +type AnglesData = { + type: 'angles'; + data: angles; +}; + +type LogData = { + type: 'log'; + data: string; +}; + +export type WebSocketJsonMsg = AnglesData | LogData; diff --git a/app/src/lib/services/index.ts b/app/src/lib/services/index.ts index d3ed92d..5b10489 100644 --- a/app/src/lib/services/index.ts +++ b/app/src/lib/services/index.ts @@ -1,2 +1,3 @@ export { default as fileService } from './file-service'; export { default as socketService } from './socket-service'; +export { default as resultService } from './result-service'; diff --git a/app/src/lib/services/socket-service.ts b/app/src/lib/services/socket-service.ts index 3497098..b0f2539 100644 --- a/app/src/lib/services/socket-service.ts +++ b/app/src/lib/services/socket-service.ts @@ -1,7 +1,9 @@ +import { isConnected, socketData } from '$lib/stores'; import { Result, Ok } from '$lib/utilities'; -import { writable, type Writable } from 'svelte/store'; +import { resultService } from '$lib/services'; +import { type WebSocketJsonMsg } from '$lib/models'; -type WebsocketData = string | ArrayBufferLike | Blob | ArrayBufferView; +type WebsocketOutData = string | ArrayBufferLike | Blob | ArrayBufferView; // TODO /** @@ -13,17 +15,6 @@ type WebsocketData = string | ArrayBufferLike | Blob | ArrayBufferView; */ class SocketService { - public isConnected = writable(false); - public angles = writable(new Int16Array(12).fill(0)); - public log = writable([] as string[]); - public battery = writable({}); - public mpu = writable({ heading: 0 }); - public distances = writable({}); - public settings = writable({}); - public systemInfo = writable({} as number); - public dataBuffer = writable(new Float32Array(13)); - public servoBuffer: Writable = writable(new Int16Array(12)); - public data = writable(); private socket!: WebSocket; constructor() {} @@ -33,10 +24,12 @@ class SocketService { this.socket.binaryType = 'arraybuffer'; this.socket.onopen = () => this.handleConnected(); this.socket.onclose = () => this.handleDisconnected(); - this.socket.onmessage = (event: unknown) => this.handleMessage(event); + this.socket.onmessage = (event: MessageEvent) => + resultService.handleResult(this.handleMessage(event), 'SocketService'); + this.socket.onerror = (error: Event) => console.log(error); } - public send(data: WebsocketData): Result { + public send(data: WebsocketOutData): Result { if (this.socket.readyState === WebSocket.OPEN) { this.socket.send(data); return Ok.void(); @@ -45,56 +38,49 @@ class SocketService { } private handleConnected(): void { - this.isConnected.set(true); + isConnected.set(true); } private handleDisconnected(): void { - this.isConnected.set(false); + isConnected.set(false); } - private handleMessage(event: any): void { - if (event.data instanceof ArrayBuffer) { - let buffer = new Int8Array(event.data); - if (buffer.length === 44) { - this.dataBuffer.set(new Float32Array(buffer.buffer)); - } - } else { - let data = event.data; - try { - data = JSON.parse(event.data); - } catch (error) { - console.warn(error); - } - switch (data.type) { - case 'angles': - this.angles.set(data.angles); - break; - case 'logs': - this.log.set(data.logs); - break; - case 'log': - this.log.update((entries) => { - entries.push(data.log); - return entries; - }); - break; - case 'settings': - this.settings.set(data.settings); - case 'info': - this.systemInfo.set(data.info); - break; - case 'mpu': - this.mpu.set(data.mpu); - break; - case 'distances': - this.distances.set(data.distances); - break; - case 'battery': - this.battery.set(data.battery); - break; - } + private getJsonFromMessage(msg: string): Result { + try { + return Result.ok(JSON.parse(msg) as WebSocketJsonMsg); + } catch (error) { + return Result.err('Failed to parse socket message', error); } } + + private handleBufferMessage(buffer: ArrayBuffer): Result { + console.log(buffer); + return Ok.void(); + } + + private handleMessage(event: MessageEvent): Result { + if (event.data instanceof ArrayBuffer) { + return this.handleBufferMessage(event.data); + } + let msgRes = this.getJsonFromMessage(event.data); + if (msgRes.isErr()) { + return msgRes; + } + const msg = msgRes.inner; + + if (msg.type === 'log') { + socketData.logs.update((entries) => { + entries.push(msg.data); + return entries; + }); + return Ok.void(); + } else if (msg.data && msg.type in socketData) { + socketData[msg.type].set(msg.data); + return Ok.void(); + } + + return Result.err(`Got invalid msg: ${JSON.stringify(msg)}`); + } } export default new SocketService(); diff --git a/app/src/lib/stores/index.ts b/app/src/lib/stores/index.ts index 11b92c2..e416c99 100644 --- a/app/src/lib/stores/index.ts +++ b/app/src/lib/stores/index.ts @@ -1 +1,2 @@ +export * from './socket-store'; export * from './logging-store'; diff --git a/app/src/lib/stores/socket-store.ts b/app/src/lib/stores/socket-store.ts new file mode 100644 index 0000000..b915c22 --- /dev/null +++ b/app/src/lib/stores/socket-store.ts @@ -0,0 +1,31 @@ +import { writable, type Writable } from 'svelte/store'; +import { type angles } from '$lib/models'; + +export const isConnected = writable(false); +export const servoAngles: Writable = writable(new Int16Array(12).fill(0)); +export const logs = writable([] as string[]); +export const battery = writable({}); +export const mpu = writable({ heading: 0 }); +export const distances = writable({}); +export const settings = writable({}); +export const systemInfo = writable({} as number); + +export interface socketDataCollection { + angles: Writable; + logs: Writable; + battery: Writable; + mpu: Writable; + distances: Writable; + settings: Writable; + systemInfo: Writable; +} + +export const socketData = { + angles: servoAngles, + logs, + battery, + mpu, + distances, + settings, + systemInfo +};