Browse Source

调整接口

master
zhangjiming 5 months ago
parent
commit
1f658cb316
  1. 16
      src/index.ts
  2. 52
      src/routes/auth.ts
  3. 92
      src/routes/debug.ts
  4. 362
      src/routes/measure.ts
  5. 24
      src/routes/measureAnalysis.ts
  6. 4
      src/routes/measureData.ts
  7. 91
      src/types/wsTypes.ts

16
src/index.ts

@ -2,13 +2,14 @@ import express from "express";
import { Server } from "ws";
import http from "http";
import bodyParser from "body-parser";
import morgan from 'morgan';
import morgan from "morgan";
import cmdRouter from "./routes/cmd";
import debugRouter from "./routes/debug";
import authRouter from "./routes/auth";
import measureRouter from "./routes/measure";
import measureDataRouter from "./routes/measureData"
import measureAnalysisRouter from "./routes/measureAnalysis";
import measureDataRouter from "./routes/measureData";
// import { defaultStatus, StatusDatagram } from "./types/wsTypes";
import { wsSend } from "./utils/wss";
@ -18,7 +19,7 @@ const app = express();
app.use(express.static("public"));
app.use(bodyParser.urlencoded());
app.use(bodyParser.json());
app.use(morgan('combined'));
app.use(morgan("dev"));
const server = http.createServer(app);
// 在HTTP服务器上初始化WebSocket服务器
@ -66,9 +67,10 @@ app.locals["measure"] = defaultMeasureState;
// });
app.use("/api/debug", debugRouter);
app.use("/api/cmd", cmdRouter);
app.use("/auth", authRouter);
app.use("/measurement-task", measureRouter);
app.use("/measurement-data", measureDataRouter);
app.use("/api/auth", authRouter);
app.use("/api/measurement-analysis", measureAnalysisRouter);
app.use("/api/measurement-task", measureRouter);
app.use("/api/measurement-data", measureDataRouter);
//@ts-ignore
app.use((err, req, res, next) => {
console.error(err.stack);
@ -76,7 +78,7 @@ app.use((err, req, res, next) => {
});
// 监听端口
const PORT = process.env.PORT || 3005;
const PORT = process.env.PORT || 8080;
server.listen(PORT, () => {
console.log(`Server is listening on port ${PORT}`);
});

52
src/routes/auth.ts

@ -5,25 +5,25 @@ import { delay } from "../utils/helper";
router.post("/login", async (req, res) => {
console.log("/login:", req.body);
req.app.locals["context"] = {
loginFlag: true,
loginUser: {
id: 0,
account: "admin",
nickname: "admin",
password: "",
userRole: "Admin",
isBuiltInUser: true,
},
};
// req.app.locals["context"] = {
// loginFlag: true,
// loginUser: {
// id: 0,
// account: "admin",
// nickname: "admin",
// password: "",
// userRole: "Admin",
// isBuiltInUser: true,
// },
// };
wsSend(req.app.locals["wss"], {
messageType: "DeviceContext",
data: req.app.locals["context"],
path: "/deviceContext",
});
// wsSend(req.app.locals["wss"], {
// messageType: "DeviceContext",
// data: req.app.locals["context"],
// path: "/deviceContext",
// });
await delay(200);
// await delay(200);
res.json({
status: 0,
@ -42,15 +42,15 @@ router.post("/login", async (req, res) => {
});
router.post("/logout", (req, res) => {
req.app.locals["context"] = {
loginFlag: false,
loginUser: {},
};
wsSend(req.app.locals["wss"], {
messageType: "DeviceContext",
data: req.app.locals["context"],
path: "/deviceContext",
});
// req.app.locals["context"] = {
// loginFlag: false,
// loginUser: {},
// };
// wsSend(req.app.locals["wss"], {
// messageType: "DeviceContext",
// data: req.app.locals["context"],
// path: "/deviceContext",
// });
res.json({
status: 0,

92
src/routes/debug.ts

@ -7,52 +7,52 @@ import points from "../utils/measure.json";
let ptIndex = 0;
let intervalId: ReturnType<typeof setInterval>;
// console.log(points)
router.post("/record-sig/:action", async (req, res) => {
// await delay(200);
if (req.params["action"] === "start") {
ptIndex = 0;
setTimeout(() => {
wsSend(req.app.locals["wss"], {
messageType: "EVENT",
data: {
event: "START_RECORD_SIG",
},
path: "/measurement-task/get-task-state",
});
}, 1000);
} else if (req.params["action"] === "stop") {
ptIndex = 0;
setTimeout(() => {
wsSend(req.app.locals["wss"], {
messageType: "EVENT",
data: {
event: "END_RECORD_SIG",
},
path: "/measurement-task/get-task-state",
});
}, 1000);
} else if (req.params["action"] === "upload") {
intervalId = setInterval(() => {
if (ptIndex >= points.length) {
clearInterval(intervalId);
// ptIndex = 0;
return;
}
wsSend(req.app.locals["wss"], {
messageType: "EVENT",
data: {
x: points[ptIndex].x,
y: points[ptIndex].y,
},
path: "/measurement-task/profile-record-ctrl-sig",
});
ptIndex = ptIndex + 2;
}, 10);
}
// const curr: StatusDatagram["data"] = req.app.locals["status"];
// // console.log(points)
// router.post("/record-sig/:action", async (req, res) => {
// // await delay(200);
// if (req.params["action"] === "start") {
// ptIndex = 0;
// setTimeout(() => {
// wsSend(req.app.locals["wss"], {
// messageType: "EVENT",
// data: {
// event: "START_RECORD_SIG",
// },
// path: "/measurement-task/get-task-state",
// });
// }, 1000);
// } else if (req.params["action"] === "stop") {
// ptIndex = 0;
// setTimeout(() => {
// wsSend(req.app.locals["wss"], {
// messageType: "EVENT",
// data: {
// event: "END_RECORD_SIG",
// },
// path: "/measurement-task/get-task-state",
// });
// }, 1000);
// } else if (req.params["action"] === "upload") {
// intervalId = setInterval(() => {
// if (ptIndex >= points.length) {
// clearInterval(intervalId);
// // ptIndex = 0;
// return;
// }
// wsSend(req.app.locals["wss"], {
// messageType: "EVENT",
// data: {
// x: points[ptIndex].x,
// y: points[ptIndex].y,
// },
// path: "/measurement-task/profile-record-ctrl-sig",
// });
// ptIndex = ptIndex + 2;
// }, 10);
// }
// // const curr: StatusDatagram["data"] = req.app.locals["status"];
res.json({ code: "00000", msg: "执行成功" });
});
// res.json({ code: "00000", msg: "执行成功" });
// });
export default router;

362
src/routes/measure.ts

@ -6,7 +6,8 @@ const router = express.Router();
import points from "../utils/measure.json";
import { MeasureState } from "../types/wsTypes";
let ptIndex = 0;
let intervalId: ReturnType<typeof setInterval>;
let intervalId1: ReturnType<typeof setInterval>;
let intervalId2: ReturnType<typeof setInterval>;
router.post("/cache-measurement", async (req, res) => {
await delay(100);
@ -20,13 +21,13 @@ router.post("/cache-measurement", async (req, res) => {
// });
// }, 2000);
const measure: MeasureState["data"] = req.app.locals["measure"];
measure.taskStatus = "IDLE";
wsSend(req.app.locals["wss"], {
messageType: "STATE",
data: req.app.locals["measure"],
path: "/measurement-task/get-task-state",
});
// const measure: MeasureState["data"] = req.app.locals["measure"];
// measure.taskStatus = "IDLE";
// wsSend(req.app.locals["wss"], {
// messageType: "STATE",
// data: req.app.locals["measure"],
// path: "/measurement-task/get-task-state",
// });
res.json({ status: 0 });
});
@ -36,41 +37,55 @@ router.post("/start-measurement", (req, res) => {
ptIndex = 0;
wsSend(req.app.locals["wss"], {
messageType: "EVENT",
data: {
event: "START_RECORD_SIG",
},
path: "/measurement-task/get-task-state",
data: "START_RECORD_LEFT",
path: "/api/measurement-task/event",
});
const measure: MeasureState["data"] = req.app.locals["measure"];
measure.taskStatus = "MEASURING";
});
intervalId1 = setInterval(() => {
if (ptIndex >= points.length / 2) {
clearInterval(intervalId1);
wsSend(req.app.locals["wss"], {
messageType: "STATE",
data: req.app.locals["measure"],
path: "/measurement-task/get-task-state",
messageType: "EVENT",
data: "FINISH_RECORD_LEFT",
path: "/api/measurement-task/event",
});
setTimeout(() => {
wsSend(req.app.locals["wss"], {
messageType: "EVENT",
data: "START_RECORD_RIGHT",
path: "/api/measurement-task/event",
});
intervalId = setInterval(() => {
intervalId2 = setInterval(() => {
if (ptIndex >= points.length) {
clearInterval(intervalId);
// ptIndex = 0;
const measure: MeasureState["data"] = req.app.locals["measure"];
measure.taskStatus = "FINISHED";
clearInterval(intervalId2);
ptIndex = 0;
wsSend(req.app.locals["wss"], {
messageType: "EVENT",
data: "FINISH_RECORD_RIGHT",
path: "/api/measurement-task/event",
});
return;
}
wsSend(req.app.locals["wss"], {
messageType: "STATE",
data: req.app.locals["measure"],
path: "/measurement-task/get-task-state",
data: {
x: points[ptIndex].x,
y: points[ptIndex].y + 1,
},
path: "/api/measurement-task/point-report",
});
ptIndex = ptIndex + 2;
}, 10);
}, 2000);
return;
}
wsSend(req.app.locals["wss"], {
messageType: "EVENT",
messageType: "STATE",
data: {
x: points[ptIndex].x,
y: points[ptIndex].y,
y: points[ptIndex].y + 1,
},
path: "/measurement-task/profile-record-ctrl-sig",
path: "/api/measurement-task/point-report",
});
ptIndex = ptIndex + 2;
}, 10);
@ -79,62 +94,267 @@ router.post("/start-measurement", (req, res) => {
});
router.post("/stop-measurement", async (req, res) => {
ptIndex = 0;
clearInterval(intervalId);
wsSend(req.app.locals["wss"], {
messageType: "EVENT",
data: {
event: "END_RECORD_SIG",
},
path: "/measurement-task/get-task-state",
});
const measure: MeasureState["data"] = req.app.locals["measure"];
measure.taskStatus = "IDLE";
wsSend(req.app.locals["wss"], {
messageType: "STATE",
data: req.app.locals["measure"],
path: "/measurement-task/get-task-state",
});
clearInterval(intervalId1);
clearInterval(intervalId2);
res.json({ status: 0 });
});
router.post("/analyze-measurement", async (req, res) => {
router.post("/save-analysis-report/6001", async (req, res) => {
await delay(100);
// setTimeout(() => {
// wsSend(req.app.locals["wss"], {
// type: "cmd",
// data: {
// commandId: req.body.commandId,
// status: "D0000",
// },
// });
// }, 2000);
res.json({
status: 0,
data: {
angles: [
{ x: 9.949007022412, y: -0.1650166186941, degree: 80, describe: "80°" },
{ x: 25.35, y: -2.184814802617, degree: 60, describe: "60°" },
{ x: -9.949007022412, y: -0.1650166186941, degree: 100, describe: "100°" },
{ x: -25.35, y: -2.184814802617, degree: 120, describe: "120°" },
railHeadWidth: 0,
w1: 0,
angleAnalysisList: [
{
base: {
x: "-31.20880",
y: "5.46060",
},
measure: {
x: "-18.33515",
y: "18.33426",
},
pointA: {
x: "-32.62301",
y: "4.04639",
},
pointB: {
x: "-29.79458",
y: "6.87482",
},
distance: "18.206",
describe: "-45.0°",
},
{
base: {
x: "-28.51641",
y: "3.39466",
},
measure: {
x: "-22.92048",
y: "13.08709",
},
pointA: {
x: "-29.51641",
y: "1.66261",
},
pointB: {
x: "-27.51641",
y: "5.12671",
},
distance: "11.192",
describe: "-30.0°",
},
{
base: {
x: "-25.38106",
y: "2.09596",
},
measure: {
x: "-24.26901",
y: "6.24616",
},
pointA: {
x: "-25.89870",
y: "0.16410",
},
pointB: {
x: "-24.86342",
y: "4.02781",
},
distance: "4.297",
describe: "-15.0°",
},
{
base: {
x: "-21.01959",
y: "1.19347",
},
measure: {
x: "-20.63937",
y: "3.34981",
},
pointA: {
x: "-21.36689",
y: "-0.77615",
},
pointB: {
x: "-20.67230",
y: "3.16308",
},
distance: "2.190",
describe: "-10.0°",
},
{
base: {
x: "-14.10020",
y: "0.28251",
},
measure: {
x: "-14.04551",
y: "0.90758",
},
pointA: {
x: "-14.27451",
y: "-1.70988",
},
pointB: {
x: "-13.92589",
y: "2.27490",
},
distance: "0.627",
describe: "-5.0°",
},
{
base: {
x: "0.00000",
y: "0.00000",
},
measure: {
x: "0.00000",
y: "0.00000",
},
pointA: {
x: "0.03000",
y: "-1.99977",
},
pointB: {
x: "-0.03000",
y: "1.99977",
},
distance: "0.000",
describe: "0.0°",
},
{
base: {
x: "9.91970",
y: "0.02682",
},
measure: {
x: "9.91964",
y: "0.02864",
},
pointA: {
x: "9.98950",
y: "-1.97196",
},
pointB: {
x: "9.84990",
y: "2.02560",
},
distance: "0.002",
describe: "2.0°",
},
{
base: {
x: "14.10020",
y: "0.28251",
},
measure: {
x: "14.05095",
y: "0.84548",
},
pointA: {
x: "14.27451",
y: "-1.70988",
},
pointB: {
x: "13.92589",
y: "2.27490",
},
distance: "0.565",
describe: "5.0°",
},
{
base: {
x: "21.01959",
y: "1.19347",
},
measure: {
x: "20.66094",
y: "3.22749",
},
pointA: {
x: "21.36689",
y: "-0.77615",
},
pointB: {
x: "20.67230",
y: "3.16308",
},
distance: "2.065",
describe: "10.0°",
},
{
base: {
x: "25.38106",
y: "2.09596",
},
measure: {
x: "24.31693",
y: "6.06734",
},
pointA: {
x: "25.89870",
y: "0.16410",
},
pointB: {
x: "24.86342",
y: "4.02781",
},
distance: "4.111",
describe: "15.0°",
},
{
base: {
x: "28.51641",
y: "3.39466",
},
measure: {
x: "23.09930",
y: "12.77737",
},
pointA: {
x: "29.51641",
y: "1.66261",
},
pointB: {
x: "27.51641",
y: "5.12671",
},
distance: "10.834",
describe: "30.0°",
},
{
base: {
x: "31.20880",
y: "5.46060",
},
measure: {
x: "18.68979",
y: "17.97962",
},
pointA: {
x: "32.62301",
y: "4.04639",
},
pointB: {
x: "29.79458",
y: "6.87482",
},
distance: "17.705",
describe: "45.0°",
},
],
},
timestamp: 1741697350184,
});
});
router.post("/save-report", async (req, res) => {
await delay(100);
// setTimeout(() => {
// wsSend(req.app.locals["wss"], {
// type: "cmd",
// data: {
// commandId: req.body.commandId,
// status: "D0000",
// },
// });
// }, 2000);
res.json({ status: 0 });
});
export default router;

24
src/routes/measureAnalysis.ts

@ -0,0 +1,24 @@
import express from "express";
import { delay } from "../utils/helper";
import { wsSend } from "../utils/wss";
const router = express.Router();
import points from "../utils/measure.json";
router.post("/base-point/6001", async (req, res) => {
res.json(
{
status: 0,
data: {
id: 1,
createTime: "2025-03-03 12:31:25",
updateTime: "2025-03-03 12:31:25",
name: "60型标准轨",
code: "6001",
points: "[{\"type\":\"arc\",\"start\": {\"x\": 0,\"y\": 0},\"end\": {\"x\": -9.949,\"y\": 0.165},\"radius\": 300,\"color\":\"#000000\",\"side\":\"right\"},{\"type\":\"arc\",\"start\": {\"x\": -9.949,\"y\": 0.165},\"end\": {\"x\": -25.35,\"y\": 2.185},\"radius\": 80,\"color\":\"#000000\",\"side\":\"right\"},{\"type\":\"arc\",\"start\": {\"x\": -25.35,\"y\": 2.185},\"end\": {\"x\": -35.4,\"y\": 14.2},\"radius\": 13,\"color\":\"#000000\",\"side\":\"right\"},{\"type\":\"line\",\"start\": {\"x\": -35.4,\"y\": 14.2},\"end\": {\"x\": -36.317,\"y\": 32.539},\"color\":\"#000000\"},{\"type\":\"arc\",\"start\": {\"x\": -36.317,\"y\": 32.539},\"end\": {\"x\": -32.904,\"y\": 37.532},\"radius\": 5,\"color\":\"#000000\",\"side\":\"right\"},{\"type\":\"line\",\"start\": {\"x\": -32.904,\"y\": 37.532},\"end\": {\"x\": -20,\"y\": 41.833},\"color\":\"#000000\"},{\"type\":\"arc\",\"start\": {\"x\": 0,\"y\": 0},\"end\": {\"x\": 9.949,\"y\": 0.165},\"radius\": 300,\"color\":\"#000000\",\"side\":\"right\"},{\"type\":\"arc\",\"start\": {\"x\": 9.949,\"y\": 0.165},\"end\": {\"x\": 25.35,\"y\": 2.185},\"radius\": 80,\"color\":\"#000000\",\"side\":\"left\"},{\"type\":\"arc\",\"start\": {\"x\": 25.35,\"y\": 2.185},\"end\": {\"x\": 35.4,\"y\": 14.2},\"radius\": 13,\"color\":\"#000000\",\"side\":\"left\"},{\"type\":\"line\",\"start\": {\"x\": 35.4,\"y\": 14.2},\"end\": {\"x\": 36.317,\"y\": 32.539},\"color\":\"#000000\"},{\"type\":\"arc\",\"start\": {\"x\": 36.317,\"y\": 32.539},\"end\": {\"x\": 32.904,\"y\": 37.532},\"radius\": 5,\"color\":\"#000000\",\"side\":\"left\"},{\"type\":\"line\",\"start\": {\"x\": 32.904,\"y\": 37.532},\"end\": {\"x\": 20,\"y\": 41.833},\"color\":\"#000000\"}]",
calPoints: "[{\"type\":\"arc\",\"start\": {\"x\": 0,\"y\": 0},\"end\": {\"x\": -9.949,\"y\": 0.165},\"radius\": 300,\"color\":\"#339900\",\"side\":\"right\"},{\"type\":\"arc\",\"start\": {\"x\": -9.949,\"y\": 0.165},\"end\": {\"x\": -25.35,\"y\": 2.185},\"radius\": 80,\"color\":\"#336699\",\"side\":\"right\"},{\"type\":\"arc\",\"start\": {\"x\": -25.35,\"y\": 2.185},\"end\": {\"x\": -35.4,\"y\": 14.2},\"radius\": 13,\"color\":\"#660000\",\"side\":\"right\"},{\"type\":\"arc\",\"start\": {\"x\": 0,\"y\": 0},\"end\": {\"x\": 9.949,\"y\": 0.165},\"radius\": 300,\"color\":\"#99CCCC\",\"side\":\"left\"},{\"type\":\"arc\",\"start\": {\"x\": 9.949,\"y\": 0.165},\"end\": {\"x\": 25.35,\"y\": 2.185},\"radius\": 80,\"color\":\"#CC0033\",\"side\":\"left\"},{\"type\":\"arc\",\"start\": {\"x\": 25.35,\"y\": 2.185},\"end\": {\"x\": 35.4,\"y\": 14.2},\"radius\": 13,\"color\":\"#CC6600\",\"side\":\"left\"}]"
},
timestamp: 1741695858099
}
);
});
export default router;

4
src/routes/measureData.ts

@ -10,10 +10,10 @@ router.post("/list", async (req, res) => {
data: {
isConnect: true,
"connectPort": "COM4",//串口名
"sn": "",//连接的设备ID
"sn": "xyz-abc",//连接的设备ID
"descriptivePortName": "COM4 serial ch340" //用于详细系
},
path: "/subdevice/uartchanel/get-channel-state",
path: "/api/subdevice/uartchanel/get-channel-state",
});
res.json({

91
src/types/wsTypes.ts

@ -1,20 +1,32 @@
// 开始、停止绘制
export type TaskState = {
messageType: "EVENT";
data: {
event: "START_RECORD_SIG" | "END_RECORD_SIG";
};
path: "/measurement-task/get-task-state";
data:
| "START_RECORD_SIG"
| "END_RECORD_SIG"
| "FINISHED"
| "START_RECORD_LEFT"
| "FINISH_RECORD_RIGHT"
| "FINISH_RECORD"
| "FINISH_RECORD_LEFT"
| "END_RECORD_SIG"
| "END_RECORD"
| "START_RECORD_RIGHT"
| "WRONG_SIDE";
// data: {
// event: "START_RECORD_SIG" | "END_RECORD_SIG" | "FINISHED" | "START_RECORD_LEFT" | "FINISH_RECORD_RIGHT" | "FINISH_RECORD" | "FINISH_RECORD_LEFT" | "END_RECORD_SIG" | "END_RECORD" | "START_RECORD_RIGHT";
// };
path: "/api/measurement-task/event";
};
// 连续上报坐标点
export type TrackRecordSig = {
messageType: "EVENT";
messageType: "STATE";
data: {
x: number;
y: number;
};
path: "/measurement-task/profile-record-ctrl-sig";
path: "/api/measurement-task/point-report";
};
export const defaultContext: ContextMessage["data"] = {
@ -42,39 +54,55 @@ export type ContextMessage = {
isBuiltInUser: boolean;
}>;
};
path: "/deviceContext";
path: "/api/deviceContext";
};
export type ChannelMessage = {
messageType: "STATE";
data: {
isConnect: boolean;
connectPort: string;
sn: string;
descriptivePortName:string;
};
path: "/subdevice/uartchanel/get-channel-state";
};
export type loginUser = Partial<{
id: 3; //数据主键id
account: "test001"; //用户账户
nickname: "测试账户001"; //用户昵称
userRole: "User"; //用户角色,可用值:User,Admin,Dev
isBuiltInUser: false; //是否内置用户(内置用户不可删除)
}>;
export const taskStatusDescMap: { [k in MeasureState["data"]["taskStatus"]]: string } = {
IDLE: "空闲",
MEASURING: "测量中",
WAITING_FOR_MEASURING: "等待测量",
FINISHED: "测量完成",
START_RECORD_LEFT: "",
FINISH_RECORD_RIGHT: "",
FINISH_RECORD: "",
FINISH_RECORD_LEFT: "",
END_RECORD_SIG: "",
END_RECORD: "",
START_RECORD_RIGHT: "",
};
// 测量任务状态
export type MeasureState = {
messageType: "STATE";
data: {
taskStatus: "IDLE" | "MEASURING" | "WAITING_FOR_MEASURING" | "FINISHED";
taskStatus:
| "IDLE"
| "MEASURING"
| "WAITING_FOR_MEASURING"
| "FINISHED"
| "START_RECORD_LEFT"
| "FINISH_RECORD_RIGHT"
| "FINISH_RECORD"
| "FINISH_RECORD_LEFT"
| "END_RECORD_SIG"
| "END_RECORD"
| "START_RECORD_RIGHT";
measureSideCnt: 0 | 1 | 2; //已测量数量,0,1,2 最多两边(左边和右边)
isMeasuringLeftEnd: boolean; //测量左侧完成
isMeasuringRightEnd: boolean; //测量右侧完成
motionlessSigFlag: boolean; //滑轮质心是否静止
inStartMeasuringPos: boolean; //是否在允许开始测量的位置
isWrongSide: boolean; //测量方向是错误的
// profileRecordDescription: null; //用户填写的新测量信息
};
path: "/measurement-task/get-task-state";
path: "/api/measurement-task/get-task-state";
};
export const defaultMeasureState = {
@ -86,4 +114,27 @@ export const defaultMeasureState = {
inStartMeasuringPos: true, //是否在允许开始测量的位置
};
export type Datagram = TrackRecordSig | TaskState | ContextMessage | MeasureState | ChannelMessage;
export type ChannelMessage = {
messageType: "STATE";
data: {
isConnect: boolean;
connectPort: string;
sn: string;
descriptivePortName: string;
};
path: "/api/subdevice/uartchanel/get-channel-state";
};
export type DeviceStatus = {
messageType: "STATE";
data: {
isConnected: boolean; //是否链接
power: number; //电量
inclinatorX: number; //x轴倾斜
inclinatorY: number; //y轴倾斜
temperature: number; //温度
};
path: "/api/profiler-state/get-state";
};
export type Datagram = TrackRecordSig | TaskState | ContextMessage | MeasureState | ChannelMessage | DeviceStatus;
Loading…
Cancel
Save