From 2f2982d4aff7c5711c836d87cdd4da5c5d9db381 Mon Sep 17 00:00:00 2001 From: kerms Date: Wed, 22 May 2024 19:29:48 +0800 Subject: [PATCH] reformat(message handling): centralize moduleID and move msg check out of websocket files --- src/api/apiWifi.ts | 13 +++-- src/api/binDataDef.ts | 52 +++++++++++++++++++ src/api/index.ts | 27 ++++++++-- src/composables/websocket/websocketWrapper.ts | 30 ++++------- src/router/msgRouter.ts | 42 ++++++++++++--- src/views/Wifi.vue | 26 ++++------ 6 files changed, 135 insertions(+), 55 deletions(-) create mode 100644 src/api/binDataDef.ts diff --git a/src/api/apiWifi.ts b/src/api/apiWifi.ts index a07ebf5..3866841 100644 --- a/src/api/apiWifi.ts +++ b/src/api/apiWifi.ts @@ -1,6 +1,5 @@ -import {type ApiJsonMsg, sendJsonMsg} from '@/api' +import {type ApiJsonMsg, sendJsonMsg, WtModuleID} from '@/api' -export const WifiModuleID = 1; export enum WifiCmd { UNKNOWN = 0, WIFI_API_JSON_STA_GET_AP_INFO, @@ -17,7 +16,7 @@ interface WifiMsgOut extends ApiJsonMsg { export function wifi_get_scan_list() { const msg : WifiMsgOut = { - module: WifiModuleID, + module: WtModuleID.WIFI, cmd: WifiCmd.WIFI_API_JSON_GET_SCAN, } sendJsonMsg(msg); @@ -25,7 +24,7 @@ export function wifi_get_scan_list() { export function wifi_sta_get_ap_info() { const msg : WifiMsgOut = { - module: WifiModuleID, + module: WtModuleID.WIFI, cmd: WifiCmd.WIFI_API_JSON_STA_GET_AP_INFO, } sendJsonMsg(msg); @@ -33,7 +32,7 @@ export function wifi_sta_get_ap_info() { export function wifi_ap_get_info() { const msg : WifiMsgOut = { - module: WifiModuleID, + module: WtModuleID.WIFI, cmd: WifiCmd.WIFI_API_JSON_AP_GET_INFO, } sendJsonMsg(msg); @@ -41,7 +40,7 @@ export function wifi_ap_get_info() { export function wifi_connect_to(ssid: string, password: string) { const msg: WifiMsgOut = { - module: WifiModuleID, + module: WtModuleID.WIFI, cmd: WifiCmd.WIFI_API_JSON_CONNECT, ssid: ssid, password: password, @@ -59,6 +58,6 @@ export interface WifiInfo extends ApiJsonMsg { wifiLogo?: string; } -export interface WifiList { +export interface WifiList extends ApiJsonMsg { scan_list: Array; } diff --git a/src/api/binDataDef.ts b/src/api/binDataDef.ts new file mode 100644 index 0000000..6755469 --- /dev/null +++ b/src/api/binDataDef.ts @@ -0,0 +1,52 @@ +import type {WtModuleID} from "@/api/index"; + +export enum WtDataType { + RESERVED = 0x00, + /* primitive type */ + EVENT = 0x02, + ROUTE_HDR = 0x03, + RAW_BROADCAST = 0x04, + + /* broadcast data */ + CMD_BROADCAST = 0x11, + + /* targeted data */ + RAW = 0x20, + CMD = 0x21, + RESPONSE = 0x22, + + /* standard protocols */ + PROTOBUF = 0x40, + JSON = 0x41, + MQTT = 0x42, +} + + +export interface ApiBinaryMsg { + data_type: WtDataType, + module: WtModuleID, + sub_mod: number, + payload: Uint8Array; +} + +export function decodeHeader(arrayBuffer: ArrayBuffer) : ApiBinaryMsg { + // Create a DataView to access the data in the ArrayBuffer + const dataView = new DataView(arrayBuffer); + + // Extract the data_type from the first byte + const data_type = dataView.getUint8(0) as WtDataType; + + // Extract the module_id and sub_id from the next bytes + const module = dataView.getUint8(1); + const sub_mod = dataView.getUint8(2); + + const payload = new Uint8Array(arrayBuffer.slice(4)); + + // Constructing the header object + return { + data_type, + module, + sub_mod, + payload, + }; +} \ No newline at end of file diff --git a/src/api/index.ts b/src/api/index.ts index faf7ad1..be2fa89 100644 --- a/src/api/index.ts +++ b/src/api/index.ts @@ -1,4 +1,5 @@ import {getWebsocketService} from "@/composables/websocket/websocketService"; +import type {ApiBinaryMsg} from "@/api/binDataDef"; export interface ApiJsonMsg { module: number; @@ -26,18 +27,34 @@ export interface ControlMsg { export interface ServerMsg { type: "json" | "binary" - data: ApiJsonMsg | object; + data: string | ArrayBuffer; +} + +export enum WtModuleID { + WIFI = 1, + DATA_FLOW = 2, + UART = 4, } export function sendJsonMsg(apiJsonMsg: ApiJsonMsg) { const msg: ServerMsg = { type: "json", - data: apiJsonMsg, + data: JSON.stringify(apiJsonMsg), }; getWebsocketService().send(msg); - // toServer.postMessage(msg); } -export function sendBinMsg(msg: ApiJsonMsg) { - // toServer.postMessage(JSON.stringify(msg)); +export function sendBinMsg(binMsg: ApiBinaryMsg) { + const buffer = new Uint8Array(4 + binMsg.payload.length); + buffer[0] = binMsg.data_type; + buffer[1] = binMsg.module; + buffer[2] = binMsg.sub_mod; + buffer[3] = 0; // Reserved byte + buffer.set(binMsg.payload, 4); // Append payload after header + + const msg: ServerMsg = { + type: "binary", + data: buffer, + }; + getWebsocketService().send(msg); } \ No newline at end of file diff --git a/src/composables/websocket/websocketWrapper.ts b/src/composables/websocket/websocketWrapper.ts index ee74427..8efede7 100644 --- a/src/composables/websocket/websocketWrapper.ts +++ b/src/composables/websocket/websocketWrapper.ts @@ -58,6 +58,7 @@ class OneTimeWebsocket implements IWebsocket { /* did not receive packet "heartBeatTimeout" times, * connection may be lost: close the socket */ if (this.socket.readyState === this.socket.OPEN) { + console.log("No heart beat, break connection"); this.close(); this.clear(); } @@ -80,31 +81,21 @@ class OneTimeWebsocket implements IWebsocket { return const msg: ServerMsg = { - data: {}, + data: ev.data, type: "json", } if (typeof ev.data === "string") { - try { - msg.data = JSON.parse(ev.data) as ApiJsonMsg; - if ((msg.data as ApiJsonMsg).cmd === undefined || - (msg.data as ApiJsonMsg).module === undefined - ){ - console.log("Server msg has no cmd or module"); - return; - } - } catch (e) { - console.log(e); - return; - } + msg.type = "json" } else { msg.type = "binary"; - msg.data = ev.data; - console.log(typeof ev.data); } this.msgCallback(msg); } - this.socket.onclose = () => { + this.socket.onclose = (ev) => { + if (isDevMode()) { + console.log("ws closed", ev.reason, ev.code); + } this.socket.onclose = null this.socket.onopen = null this.socket.onerror = null @@ -150,11 +141,8 @@ class OneTimeWebsocket implements IWebsocket { if (isDevMode()) { console.log('WebSocket proxies data ', msg); } - if (msg.type === "binary") { - // this.socket.send(msg.data); - } else if (msg.type === "json") { - this.socket.send(JSON.stringify(msg.data)); - } + + this.socket.send(msg.data); } clear() { diff --git a/src/router/msgRouter.ts b/src/router/msgRouter.ts index 1ff9c7d..368df05 100644 --- a/src/router/msgRouter.ts +++ b/src/router/msgRouter.ts @@ -1,9 +1,11 @@ import type {ApiJsonMsg, ControlMsg, ServerMsg} from "@/api"; import {isDevMode} from "@/composables/buildMode"; +import {type ApiBinaryMsg, decodeHeader} from "@/api/binDataDef"; export interface IModuleCallback { ctrlCallback: (msg: ControlMsg) => void; - serverMsgCallback: (msg: ServerMsg) => void; + serverJsonMsgCallback: (msg: ApiJsonMsg) => void; + serverBinMsgCallback: (msg: ApiBinaryMsg) => void; } const moduleMap = new Map(); @@ -22,19 +24,47 @@ export function unregisterModule(moduleId: number) { } export function routeModuleServerMsg(msg: ServerMsg) { - if (msg.type == "json") { - const module = (msg.data as ApiJsonMsg).module; + if (msg.type === "json") { + let jsonMsg: ApiJsonMsg; + try { + jsonMsg = JSON.parse(msg.data as string) as ApiJsonMsg; + if (jsonMsg.cmd === undefined || + jsonMsg.module === undefined + ){ + console.log("Server msg has no cmd or module", msg.data); + return; + } + } catch (e) { + console.log(e); + return; + } + + const module = jsonMsg.module; const moduleHandler = moduleMap.get(module); if (moduleHandler) { - moduleHandler.serverMsgCallback(msg); + moduleHandler.serverJsonMsgCallback(jsonMsg); } else { if (isDevMode()) { console.log("routeModuleServerMsg module not loaded", module); } } } else { - if (isDevMode()) { - console.log("routeModuleServerMsg ignored:", msg); + const arr = msg.data as ArrayBuffer; + if (arr.byteLength < 4) { + if (isDevMode()) { + console.log("binary message too short"); + } + return; + } + + const binaryMsg = decodeHeader(msg.data as ArrayBuffer); + const moduleHandler = moduleMap.get(binaryMsg.module); + if (moduleHandler) { + moduleHandler.serverBinMsgCallback(binaryMsg); + } else { + if (isDevMode()) { + console.log("routeModuleServerMsg ignored:", msg, binaryMsg); + } } } } diff --git a/src/views/Wifi.vue b/src/views/Wifi.vue index 58951e0..2a53dbc 100644 --- a/src/views/Wifi.vue +++ b/src/views/Wifi.vue @@ -198,14 +198,13 @@ import { WifiCmd, type WifiInfo, type WifiList, - WifiModuleID, wifi_ap_get_info, wifi_connect_to } from "@/api/apiWifi"; import type {FormInstance} from "element-plus"; import InlineSvg from "@/components/InlineSvg.vue"; import type {ApiJsonMsg, ControlMsg, ServerMsg} from "@/api"; -import {ControlEvent, ControlMsgType} from "@/api"; +import {ControlEvent, ControlMsgType, WtModuleID} from "@/api"; import {registerModule, unregisterModule} from "@/router/msgRouter"; import {useWsStore} from "@/stores/websocket"; import {globalNotify, globalNotifyRightSide} from "@/composables/notification"; @@ -250,18 +249,12 @@ const querySearch = (queryString: string, cb: any) => { } } -const onClientMsg = (msg: ServerMsg) => { - if (msg.type !== "json") { - return; - } - - let json = msg.data as ApiJsonMsg; - - switch (json.cmd as WifiCmd) { +const onClientMsg = (msg: ApiJsonMsg) => { + switch (msg.cmd as WifiCmd) { case WifiCmd.UNKNOWN: break; case WifiCmd.WIFI_API_JSON_STA_GET_AP_INFO: { - const info = msg.data as WifiInfo; + const info = msg as WifiInfo; if (info.rssi === 0) { Object.assign(wifiStaApInfo, defWifiInfo); } else { @@ -276,7 +269,7 @@ const onClientMsg = (msg: ServerMsg) => { case WifiCmd.WIFI_API_JSON_CONNECT: break; case WifiCmd.WIFI_API_JSON_GET_SCAN: { - const list = msg.data as WifiList; + const list = msg as WifiList; scanning.value = false; list.scan_list.forEach(value => { if (value.rssi > -50) { @@ -298,7 +291,7 @@ const onClientMsg = (msg: ServerMsg) => { case WifiCmd.WIFI_API_JSON_DISCONNECT: break; case WifiCmd.WIFI_API_JSON_AP_GET_INFO: { - const info = msg.data as WifiInfo; + const info = msg as WifiInfo; Object.assign(wifiApInfo, info); break; } @@ -342,16 +335,17 @@ function onConnectClick() { } onMounted(() => { - registerModule(WifiModuleID, { + registerModule(WtModuleID.WIFI, { ctrlCallback: onClientCtrl, - serverMsgCallback: onClientMsg + serverJsonMsgCallback: onClientMsg, + serverBinMsgCallback: () => {}, }); wifi_sta_get_ap_info(); wifi_ap_get_info(); }); onUnmounted(() => { - unregisterModule(WifiModuleID); + unregisterModule(WtModuleID.WIFI); });