reformat(message handling): centralize moduleID and move msg check out of websocket files

This commit is contained in:
kerms 2024-05-22 19:29:48 +08:00
parent 7b2c05bc57
commit 2f2982d4af
6 changed files with 135 additions and 55 deletions

View File

@ -1,6 +1,5 @@
import {type ApiJsonMsg, sendJsonMsg} from '@/api' import {type ApiJsonMsg, sendJsonMsg, WtModuleID} from '@/api'
export const WifiModuleID = 1;
export enum WifiCmd { export enum WifiCmd {
UNKNOWN = 0, UNKNOWN = 0,
WIFI_API_JSON_STA_GET_AP_INFO, WIFI_API_JSON_STA_GET_AP_INFO,
@ -17,7 +16,7 @@ interface WifiMsgOut extends ApiJsonMsg {
export function wifi_get_scan_list() { export function wifi_get_scan_list() {
const msg : WifiMsgOut = { const msg : WifiMsgOut = {
module: WifiModuleID, module: WtModuleID.WIFI,
cmd: WifiCmd.WIFI_API_JSON_GET_SCAN, cmd: WifiCmd.WIFI_API_JSON_GET_SCAN,
} }
sendJsonMsg(msg); sendJsonMsg(msg);
@ -25,7 +24,7 @@ export function wifi_get_scan_list() {
export function wifi_sta_get_ap_info() { export function wifi_sta_get_ap_info() {
const msg : WifiMsgOut = { const msg : WifiMsgOut = {
module: WifiModuleID, module: WtModuleID.WIFI,
cmd: WifiCmd.WIFI_API_JSON_STA_GET_AP_INFO, cmd: WifiCmd.WIFI_API_JSON_STA_GET_AP_INFO,
} }
sendJsonMsg(msg); sendJsonMsg(msg);
@ -33,7 +32,7 @@ export function wifi_sta_get_ap_info() {
export function wifi_ap_get_info() { export function wifi_ap_get_info() {
const msg : WifiMsgOut = { const msg : WifiMsgOut = {
module: WifiModuleID, module: WtModuleID.WIFI,
cmd: WifiCmd.WIFI_API_JSON_AP_GET_INFO, cmd: WifiCmd.WIFI_API_JSON_AP_GET_INFO,
} }
sendJsonMsg(msg); sendJsonMsg(msg);
@ -41,7 +40,7 @@ export function wifi_ap_get_info() {
export function wifi_connect_to(ssid: string, password: string) { export function wifi_connect_to(ssid: string, password: string) {
const msg: WifiMsgOut = { const msg: WifiMsgOut = {
module: WifiModuleID, module: WtModuleID.WIFI,
cmd: WifiCmd.WIFI_API_JSON_CONNECT, cmd: WifiCmd.WIFI_API_JSON_CONNECT,
ssid: ssid, ssid: ssid,
password: password, password: password,
@ -59,6 +58,6 @@ export interface WifiInfo extends ApiJsonMsg {
wifiLogo?: string; wifiLogo?: string;
} }
export interface WifiList { export interface WifiList extends ApiJsonMsg {
scan_list: Array<WifiInfo>; scan_list: Array<WifiInfo>;
} }

52
src/api/binDataDef.ts Normal file
View File

@ -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,
};
}

View File

@ -1,4 +1,5 @@
import {getWebsocketService} from "@/composables/websocket/websocketService"; import {getWebsocketService} from "@/composables/websocket/websocketService";
import type {ApiBinaryMsg} from "@/api/binDataDef";
export interface ApiJsonMsg { export interface ApiJsonMsg {
module: number; module: number;
@ -26,18 +27,34 @@ export interface ControlMsg {
export interface ServerMsg { export interface ServerMsg {
type: "json" | "binary" type: "json" | "binary"
data: ApiJsonMsg | object; data: string | ArrayBuffer;
}
export enum WtModuleID {
WIFI = 1,
DATA_FLOW = 2,
UART = 4,
} }
export function sendJsonMsg(apiJsonMsg: ApiJsonMsg) { export function sendJsonMsg(apiJsonMsg: ApiJsonMsg) {
const msg: ServerMsg = { const msg: ServerMsg = {
type: "json", type: "json",
data: apiJsonMsg, data: JSON.stringify(apiJsonMsg),
}; };
getWebsocketService().send(msg); getWebsocketService().send(msg);
// toServer.postMessage(msg);
} }
export function sendBinMsg(msg: ApiJsonMsg) { export function sendBinMsg(binMsg: ApiBinaryMsg) {
// toServer.postMessage(JSON.stringify(msg)); 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);
} }

View File

@ -58,6 +58,7 @@ class OneTimeWebsocket implements IWebsocket {
/* did not receive packet "heartBeatTimeout" times, /* did not receive packet "heartBeatTimeout" times,
* connection may be lost: close the socket */ * connection may be lost: close the socket */
if (this.socket.readyState === this.socket.OPEN) { if (this.socket.readyState === this.socket.OPEN) {
console.log("No heart beat, break connection");
this.close(); this.close();
this.clear(); this.clear();
} }
@ -80,31 +81,21 @@ class OneTimeWebsocket implements IWebsocket {
return return
const msg: ServerMsg = { const msg: ServerMsg = {
data: {}, data: ev.data,
type: "json", type: "json",
} }
if (typeof ev.data === "string") { if (typeof ev.data === "string") {
try { msg.type = "json"
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;
}
} else { } else {
msg.type = "binary"; msg.type = "binary";
msg.data = ev.data;
console.log(typeof ev.data);
} }
this.msgCallback(msg); 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.onclose = null
this.socket.onopen = null this.socket.onopen = null
this.socket.onerror = null this.socket.onerror = null
@ -150,11 +141,8 @@ class OneTimeWebsocket implements IWebsocket {
if (isDevMode()) { if (isDevMode()) {
console.log('WebSocket proxies data ', msg); console.log('WebSocket proxies data ', msg);
} }
if (msg.type === "binary") {
// this.socket.send(msg.data); this.socket.send(msg.data);
} else if (msg.type === "json") {
this.socket.send(JSON.stringify(msg.data));
}
} }
clear() { clear() {

View File

@ -1,9 +1,11 @@
import type {ApiJsonMsg, ControlMsg, ServerMsg} from "@/api"; import type {ApiJsonMsg, ControlMsg, ServerMsg} from "@/api";
import {isDevMode} from "@/composables/buildMode"; import {isDevMode} from "@/composables/buildMode";
import {type ApiBinaryMsg, decodeHeader} from "@/api/binDataDef";
export interface IModuleCallback { export interface IModuleCallback {
ctrlCallback: (msg: ControlMsg) => void; ctrlCallback: (msg: ControlMsg) => void;
serverMsgCallback: (msg: ServerMsg) => void; serverJsonMsgCallback: (msg: ApiJsonMsg) => void;
serverBinMsgCallback: (msg: ApiBinaryMsg) => void;
} }
const moduleMap = new Map<number, IModuleCallback>(); const moduleMap = new Map<number, IModuleCallback>();
@ -22,19 +24,47 @@ export function unregisterModule(moduleId: number) {
} }
export function routeModuleServerMsg(msg: ServerMsg) { export function routeModuleServerMsg(msg: ServerMsg) {
if (msg.type == "json") { if (msg.type === "json") {
const module = (msg.data as ApiJsonMsg).module; 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); const moduleHandler = moduleMap.get(module);
if (moduleHandler) { if (moduleHandler) {
moduleHandler.serverMsgCallback(msg); moduleHandler.serverJsonMsgCallback(jsonMsg);
} else { } else {
if (isDevMode()) { if (isDevMode()) {
console.log("routeModuleServerMsg module not loaded", module); console.log("routeModuleServerMsg module not loaded", module);
} }
} }
} else { } else {
if (isDevMode()) { const arr = msg.data as ArrayBuffer;
console.log("routeModuleServerMsg ignored:", msg); 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);
}
} }
} }
} }

View File

@ -198,14 +198,13 @@ import {
WifiCmd, WifiCmd,
type WifiInfo, type WifiInfo,
type WifiList, type WifiList,
WifiModuleID,
wifi_ap_get_info, wifi_connect_to wifi_ap_get_info, wifi_connect_to
} from "@/api/apiWifi"; } from "@/api/apiWifi";
import type {FormInstance} from "element-plus"; import type {FormInstance} from "element-plus";
import InlineSvg from "@/components/InlineSvg.vue"; import InlineSvg from "@/components/InlineSvg.vue";
import type {ApiJsonMsg, ControlMsg, ServerMsg} from "@/api"; 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 {registerModule, unregisterModule} from "@/router/msgRouter";
import {useWsStore} from "@/stores/websocket"; import {useWsStore} from "@/stores/websocket";
import {globalNotify, globalNotifyRightSide} from "@/composables/notification"; import {globalNotify, globalNotifyRightSide} from "@/composables/notification";
@ -250,18 +249,12 @@ const querySearch = (queryString: string, cb: any) => {
} }
} }
const onClientMsg = (msg: ServerMsg) => { const onClientMsg = (msg: ApiJsonMsg) => {
if (msg.type !== "json") { switch (msg.cmd as WifiCmd) {
return;
}
let json = msg.data as ApiJsonMsg;
switch (json.cmd as WifiCmd) {
case WifiCmd.UNKNOWN: case WifiCmd.UNKNOWN:
break; break;
case WifiCmd.WIFI_API_JSON_STA_GET_AP_INFO: { case WifiCmd.WIFI_API_JSON_STA_GET_AP_INFO: {
const info = msg.data as WifiInfo; const info = msg as WifiInfo;
if (info.rssi === 0) { if (info.rssi === 0) {
Object.assign(wifiStaApInfo, defWifiInfo); Object.assign(wifiStaApInfo, defWifiInfo);
} else { } else {
@ -276,7 +269,7 @@ const onClientMsg = (msg: ServerMsg) => {
case WifiCmd.WIFI_API_JSON_CONNECT: case WifiCmd.WIFI_API_JSON_CONNECT:
break; break;
case WifiCmd.WIFI_API_JSON_GET_SCAN: { case WifiCmd.WIFI_API_JSON_GET_SCAN: {
const list = msg.data as WifiList; const list = msg as WifiList;
scanning.value = false; scanning.value = false;
list.scan_list.forEach(value => { list.scan_list.forEach(value => {
if (value.rssi > -50) { if (value.rssi > -50) {
@ -298,7 +291,7 @@ const onClientMsg = (msg: ServerMsg) => {
case WifiCmd.WIFI_API_JSON_DISCONNECT: case WifiCmd.WIFI_API_JSON_DISCONNECT:
break; break;
case WifiCmd.WIFI_API_JSON_AP_GET_INFO: { case WifiCmd.WIFI_API_JSON_AP_GET_INFO: {
const info = msg.data as WifiInfo; const info = msg as WifiInfo;
Object.assign(wifiApInfo, info); Object.assign(wifiApInfo, info);
break; break;
} }
@ -342,16 +335,17 @@ function onConnectClick() {
} }
onMounted(() => { onMounted(() => {
registerModule(WifiModuleID, { registerModule(WtModuleID.WIFI, {
ctrlCallback: onClientCtrl, ctrlCallback: onClientCtrl,
serverMsgCallback: onClientMsg serverJsonMsgCallback: onClientMsg,
serverBinMsgCallback: () => {},
}); });
wifi_sta_get_ap_info(); wifi_sta_get_ap_info();
wifi_ap_get_info(); wifi_ap_get_info();
}); });
onUnmounted(() => { onUnmounted(() => {
unregisterModule(WifiModuleID); unregisterModule(WtModuleID.WIFI);
}); });