@robdobsn/raftjs 1.7.1 → 1.7.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/web/RaftAttributeHandler.js +5 -5
- package/dist/web/RaftAttributeHandler.js.map +1 -1
- package/dist/web/RaftChannel.d.ts +2 -0
- package/dist/web/RaftChannelBLE.web.d.ts +2 -0
- package/dist/web/RaftChannelBLE.web.js +10 -0
- package/dist/web/RaftChannelBLE.web.js.map +1 -1
- package/dist/{react-native/RaftChannelWebSocket.d.ts → web/RaftChannelSimulated.d.ts} +9 -5
- package/dist/web/RaftChannelSimulated.js +418 -0
- package/dist/web/RaftChannelSimulated.js.map +1 -0
- package/dist/web/RaftChannelWebSerial.d.ts +2 -0
- package/dist/web/RaftChannelWebSerial.js +10 -0
- package/dist/web/RaftChannelWebSerial.js.map +1 -1
- package/dist/web/RaftChannelWebSocket.d.ts +2 -0
- package/dist/web/RaftChannelWebSocket.js +10 -0
- package/dist/web/RaftChannelWebSocket.js.map +1 -1
- package/dist/web/RaftConnector.js +5 -0
- package/dist/web/RaftConnector.js.map +1 -1
- package/dist/web/RaftDeviceInfo.d.ts +1 -1
- package/dist/web/RaftMsgHandler.d.ts +5 -0
- package/dist/web/RaftMsgHandler.js +32 -0
- package/dist/web/RaftMsgHandler.js.map +1 -1
- package/dist/web/main.d.ts +1 -0
- package/dist/web/main.js +3 -1
- package/dist/web/main.js.map +1 -1
- package/package.json +5 -2
- package/.editorconfig +0 -14
- package/.gitattributes +0 -11
- package/.nvmrc +0 -1
- package/TODO.md +0 -1
- package/dist/react-native/RaftAttributeHandler.d.ts +0 -12
- package/dist/react-native/RaftAttributeHandler.js +0 -249
- package/dist/react-native/RaftAttributeHandler.js.map +0 -1
- package/dist/react-native/RaftChannel.d.ts +0 -18
- package/dist/react-native/RaftChannel.js +0 -12
- package/dist/react-native/RaftChannel.js.map +0 -1
- package/dist/react-native/RaftChannelBLE.native.d.ts +0 -93
- package/dist/react-native/RaftChannelBLE.native.js +0 -472
- package/dist/react-native/RaftChannelBLE.native.js.map +0 -1
- package/dist/react-native/RaftChannelBLE.web.d.ts +0 -38
- package/dist/react-native/RaftChannelBLE.web.js +0 -290
- package/dist/react-native/RaftChannelBLE.web.js.map +0 -1
- package/dist/react-native/RaftChannelBLEFactory.d.ts +0 -10
- package/dist/react-native/RaftChannelBLEFactory.js +0 -17
- package/dist/react-native/RaftChannelBLEFactory.js.map +0 -1
- package/dist/react-native/RaftChannelBLEScanner.native.d.ts +0 -18
- package/dist/react-native/RaftChannelBLEScanner.native.js +0 -138
- package/dist/react-native/RaftChannelBLEScanner.native.js.map +0 -1
- package/dist/react-native/RaftChannelWebSerial.d.ts +0 -37
- package/dist/react-native/RaftChannelWebSerial.js +0 -319
- package/dist/react-native/RaftChannelWebSerial.js.map +0 -1
- package/dist/react-native/RaftChannelWebSocket.js +0 -197
- package/dist/react-native/RaftChannelWebSocket.js.map +0 -1
- package/dist/react-native/RaftCommsStats.d.ts +0 -39
- package/dist/react-native/RaftCommsStats.js +0 -128
- package/dist/react-native/RaftCommsStats.js.map +0 -1
- package/dist/react-native/RaftConnEvents.d.ts +0 -39
- package/dist/react-native/RaftConnEvents.js +0 -54
- package/dist/react-native/RaftConnEvents.js.map +0 -1
- package/dist/react-native/RaftConnector.d.ts +0 -245
- package/dist/react-native/RaftConnector.js +0 -616
- package/dist/react-native/RaftConnector.js.map +0 -1
- package/dist/react-native/RaftCustomAttrHandler.d.ts +0 -4
- package/dist/react-native/RaftCustomAttrHandler.js +0 -50
- package/dist/react-native/RaftCustomAttrHandler.js.map +0 -1
- package/dist/react-native/RaftDeviceInfo.d.ts +0 -63
- package/dist/react-native/RaftDeviceInfo.js +0 -36
- package/dist/react-native/RaftDeviceInfo.js.map +0 -1
- package/dist/react-native/RaftDeviceManager.d.ts +0 -40
- package/dist/react-native/RaftDeviceManager.js +0 -499
- package/dist/react-native/RaftDeviceManager.js.map +0 -1
- package/dist/react-native/RaftDeviceMgrIF.d.ts +0 -15
- package/dist/react-native/RaftDeviceMgrIF.js +0 -11
- package/dist/react-native/RaftDeviceMgrIF.js.map +0 -1
- package/dist/react-native/RaftDeviceMsg.d.ts +0 -9
- package/dist/react-native/RaftDeviceMsg.js +0 -11
- package/dist/react-native/RaftDeviceMsg.js.map +0 -1
- package/dist/react-native/RaftDeviceStates.d.ts +0 -37
- package/dist/react-native/RaftDeviceStates.js +0 -60
- package/dist/react-native/RaftDeviceStates.js.map +0 -1
- package/dist/react-native/RaftFileHandler.d.ts +0 -52
- package/dist/react-native/RaftFileHandler.js +0 -502
- package/dist/react-native/RaftFileHandler.js.map +0 -1
- package/dist/react-native/RaftLog.d.ts +0 -22
- package/dist/react-native/RaftLog.js +0 -63
- package/dist/react-native/RaftLog.js.map +0 -1
- package/dist/react-native/RaftMiniHDLC.d.ts +0 -18
- package/dist/react-native/RaftMiniHDLC.js +0 -383
- package/dist/react-native/RaftMiniHDLC.js.map +0 -1
- package/dist/react-native/RaftMsgHandler.d.ts +0 -57
- package/dist/react-native/RaftMsgHandler.js +0 -479
- package/dist/react-native/RaftMsgHandler.js.map +0 -1
- package/dist/react-native/RaftMsgTrackInfo.d.ts +0 -17
- package/dist/react-native/RaftMsgTrackInfo.js +0 -42
- package/dist/react-native/RaftMsgTrackInfo.js.map +0 -1
- package/dist/react-native/RaftProtocolDefs.d.ts +0 -30
- package/dist/react-native/RaftProtocolDefs.js +0 -48
- package/dist/react-native/RaftProtocolDefs.js.map +0 -1
- package/dist/react-native/RaftStreamHandler.d.ts +0 -38
- package/dist/react-native/RaftStreamHandler.js +0 -257
- package/dist/react-native/RaftStreamHandler.js.map +0 -1
- package/dist/react-native/RaftStruct.d.ts +0 -3
- package/dist/react-native/RaftStruct.js +0 -208
- package/dist/react-native/RaftStruct.js.map +0 -1
- package/dist/react-native/RaftSysTypeManager.d.ts +0 -14
- package/dist/react-native/RaftSysTypeManager.js +0 -53
- package/dist/react-native/RaftSysTypeManager.js.map +0 -1
- package/dist/react-native/RaftSystemType.d.ts +0 -28
- package/dist/react-native/RaftSystemType.js +0 -3
- package/dist/react-native/RaftSystemType.js.map +0 -1
- package/dist/react-native/RaftSystemUtils.d.ts +0 -136
- package/dist/react-native/RaftSystemUtils.js +0 -410
- package/dist/react-native/RaftSystemUtils.js.map +0 -1
- package/dist/react-native/RaftTypes.d.ts +0 -194
- package/dist/react-native/RaftTypes.js +0 -153
- package/dist/react-native/RaftTypes.js.map +0 -1
- package/dist/react-native/RaftUpdateEvents.d.ts +0 -33
- package/dist/react-native/RaftUpdateEvents.js +0 -46
- package/dist/react-native/RaftUpdateEvents.js.map +0 -1
- package/dist/react-native/RaftUpdateManager.d.ts +0 -61
- package/dist/react-native/RaftUpdateManager.js +0 -621
- package/dist/react-native/RaftUpdateManager.js.map +0 -1
- package/dist/react-native/RaftUtils.d.ts +0 -126
- package/dist/react-native/RaftUtils.js +0 -467
- package/dist/react-native/RaftUtils.js.map +0 -1
- package/dist/react-native/RaftWifiTypes.d.ts +0 -23
- package/dist/react-native/RaftWifiTypes.js +0 -43
- package/dist/react-native/RaftWifiTypes.js.map +0 -1
- package/dist/react-native/main.d.ts +0 -24
- package/dist/react-native/main.js +0 -49
- package/dist/react-native/main.js.map +0 -1
- package/eslint.config.mjs +0 -33
- package/examples/dashboard/package.json +0 -36
- package/examples/dashboard/src/CommandPanel.tsx +0 -147
- package/examples/dashboard/src/ConnManager.ts +0 -164
- package/examples/dashboard/src/DeviceActionsForm.tsx +0 -133
- package/examples/dashboard/src/DeviceAttrsForm.tsx +0 -49
- package/examples/dashboard/src/DeviceLineChart.tsx +0 -163
- package/examples/dashboard/src/DevicePanel.tsx +0 -166
- package/examples/dashboard/src/DevicesPanel.tsx +0 -58
- package/examples/dashboard/src/DispLedGrid.tsx +0 -110
- package/examples/dashboard/src/DispOneLed.tsx +0 -20
- package/examples/dashboard/src/LatencyTest.ts +0 -130
- package/examples/dashboard/src/LatencyTestPanel.tsx +0 -92
- package/examples/dashboard/src/Main.tsx +0 -234
- package/examples/dashboard/src/SettingsManager.ts +0 -67
- package/examples/dashboard/src/SettingsScreen.tsx +0 -174
- package/examples/dashboard/src/StatusPanel.tsx +0 -71
- package/examples/dashboard/src/SystemTypeCog/CogStateInfo.ts +0 -163
- package/examples/dashboard/src/SystemTypeCog/SystemTypeCog.ts +0 -91
- package/examples/dashboard/src/SystemTypeGeneric/StateInfoGeneric.ts +0 -30
- package/examples/dashboard/src/SystemTypeGeneric/SystemTypeGeneric.ts +0 -91
- package/examples/dashboard/src/SystemTypeMarty/RICAddOn.ts +0 -70
- package/examples/dashboard/src/SystemTypeMarty/RICAddOnBase.ts +0 -33
- package/examples/dashboard/src/SystemTypeMarty/RICAddOnManager.ts +0 -342
- package/examples/dashboard/src/SystemTypeMarty/RICCommsStats.ts +0 -170
- package/examples/dashboard/src/SystemTypeMarty/RICHWElem.ts +0 -123
- package/examples/dashboard/src/SystemTypeMarty/RICLEDPatternChecker.ts +0 -207
- package/examples/dashboard/src/SystemTypeMarty/RICROSSerial.ts +0 -464
- package/examples/dashboard/src/SystemTypeMarty/RICServoFaultDetector.ts +0 -146
- package/examples/dashboard/src/SystemTypeMarty/RICStateInfo.ts +0 -97
- package/examples/dashboard/src/SystemTypeMarty/RICSystemUtils.ts +0 -371
- package/examples/dashboard/src/SystemTypeMarty/RICTypes.ts +0 -20
- package/examples/dashboard/src/SystemTypeMarty/SystemTypeMarty.ts +0 -119
- package/examples/dashboard/src/index.html +0 -15
- package/examples/dashboard/src/index.tsx +0 -13
- package/examples/dashboard/src/styles.css +0 -408
- package/examples/dashboard/tsconfig.json +0 -18
- package/jest.config.js +0 -11
- package/src/RaftAttributeHandler.ts +0 -298
- package/src/RaftChannel.ts +0 -30
- package/src/RaftChannelBLE.native.ts +0 -604
- package/src/RaftChannelBLE.web.ts +0 -359
- package/src/RaftChannelBLEFactory.ts +0 -13
- package/src/RaftChannelBLEScanner.native.ts +0 -184
- package/src/RaftChannelWebSerial.ts +0 -408
- package/src/RaftChannelWebSocket.ts +0 -245
- package/src/RaftCommsStats.ts +0 -142
- package/src/RaftConnEvents.ts +0 -58
- package/src/RaftConnector.ts +0 -739
- package/src/RaftCustomAttrHandler.ts +0 -54
- package/src/RaftDeviceInfo.ts +0 -102
- package/src/RaftDeviceManager.ts +0 -607
- package/src/RaftDeviceMgrIF.ts +0 -33
- package/src/RaftDeviceMsg.ts +0 -20
- package/src/RaftDeviceStates.ts +0 -92
- package/src/RaftFileHandler.ts +0 -668
- package/src/RaftLog.ts +0 -70
- package/src/RaftMiniHDLC.ts +0 -396
- package/src/RaftMsgHandler.ts +0 -777
- package/src/RaftMsgTrackInfo.ts +0 -51
- package/src/RaftProtocolDefs.ts +0 -46
- package/src/RaftStreamHandler.ts +0 -328
- package/src/RaftStruct.ts +0 -209
- package/src/RaftSysTypeManager.ts +0 -60
- package/src/RaftSystemType.ts +0 -32
- package/src/RaftSystemUtils.ts +0 -487
- package/src/RaftTypes.ts +0 -278
- package/src/RaftUpdateEvents.ts +0 -48
- package/src/RaftUpdateManager.ts +0 -781
- package/src/RaftUtils.ts +0 -494
- package/src/RaftWifiTypes.ts +0 -36
- package/src/main.ts +0 -37
- package/testdata/TestDeviceTypeRecs.json +0 -492
- package/tsconfig.json +0 -30
- package/tsconfig.react-native.json +0 -29
|
@@ -1,163 +0,0 @@
|
|
|
1
|
-
import React, { useEffect, useState, memo, useRef } from "react";
|
|
2
|
-
import { Chart as ChartJS, CategoryScale, LinearScale, PointElement, LineElement, ArcElement, Tooltip, Legend } from 'chart.js';
|
|
3
|
-
import { Line } from "react-chartjs-2";
|
|
4
|
-
import ConnManager from "./ConnManager";
|
|
5
|
-
import { DeviceState } from "../../../src/RaftDeviceStates";
|
|
6
|
-
import SettingsManager from "./SettingsManager";
|
|
7
|
-
|
|
8
|
-
const connManager = ConnManager.getInstance();
|
|
9
|
-
|
|
10
|
-
ChartJS.register(
|
|
11
|
-
CategoryScale,
|
|
12
|
-
LinearScale,
|
|
13
|
-
PointElement,
|
|
14
|
-
LineElement,
|
|
15
|
-
ArcElement,
|
|
16
|
-
Tooltip,
|
|
17
|
-
Legend
|
|
18
|
-
);
|
|
19
|
-
|
|
20
|
-
export interface DeviceLineChartProps {
|
|
21
|
-
deviceKey: string;
|
|
22
|
-
lastUpdated: number;
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
interface ChartJSData {
|
|
26
|
-
labels: string[];
|
|
27
|
-
datasets: {
|
|
28
|
-
label: string;
|
|
29
|
-
data: number[];
|
|
30
|
-
fill: boolean;
|
|
31
|
-
borderColor: string;
|
|
32
|
-
backgroundColor: string;
|
|
33
|
-
yAxisID: string;
|
|
34
|
-
}[];
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
const DeviceLineChart: React.FC<DeviceLineChartProps> = memo(({ deviceKey, lastUpdated }) => {
|
|
38
|
-
|
|
39
|
-
const settingsManager = SettingsManager.getInstance();
|
|
40
|
-
const maxChartDataPoints = settingsManager.getSetting('maxChartDataPoints');
|
|
41
|
-
|
|
42
|
-
const deviceManager = connManager.getConnector().getSystemType()?.deviceMgrIF;
|
|
43
|
-
const deviceState: DeviceState | undefined = deviceManager?.getDeviceState(deviceKey);
|
|
44
|
-
// const { deviceAttributes, deviceTimeline } = deviceState;
|
|
45
|
-
const [chartData, setChartData] = useState<ChartJSData>({
|
|
46
|
-
labels: [],
|
|
47
|
-
datasets: []
|
|
48
|
-
});
|
|
49
|
-
|
|
50
|
-
const options = {
|
|
51
|
-
responsive: true,
|
|
52
|
-
maintainAspectRatio: false,
|
|
53
|
-
animation: {
|
|
54
|
-
duration: 1, // default is 1000ms
|
|
55
|
-
},
|
|
56
|
-
scales: {}
|
|
57
|
-
};
|
|
58
|
-
|
|
59
|
-
const colourMapRef = useRef<{ [key: string]: string }>({
|
|
60
|
-
prox: "hsl(60, 70%, 60%)",
|
|
61
|
-
als: "hsl(0, 70%, 60%)",
|
|
62
|
-
white: "hsl(120, 70%, 60%)",
|
|
63
|
-
x: "hsl(240, 70%, 60%)",
|
|
64
|
-
y: "hsl(300, 70%, 60%)",
|
|
65
|
-
z: "hsl(0, 70%, 60%)",
|
|
66
|
-
ax: "hsl(230, 70%, 60%)",
|
|
67
|
-
ay: "hsl(323, 69.60%, 60.00%)",
|
|
68
|
-
az: "hsl(64, 69.60%, 60.00%)",
|
|
69
|
-
gx: "hsl(275, 70%, 60%)",
|
|
70
|
-
gy: "hsl(352, 69.60%, 60.00%)",
|
|
71
|
-
gz: "hsl(88, 69.60%, 60.00%)",
|
|
72
|
-
dist: "hsl(60, 70%, 60%)",
|
|
73
|
-
temperature: "hsl(360, 70%, 60%)",
|
|
74
|
-
humidity: "hsl(200, 70%, 60%)",
|
|
75
|
-
Red: "hsl(0, 70%, 60%)",
|
|
76
|
-
Green: "hsl(120, 70%, 60%)",
|
|
77
|
-
Blue: "hsl(240, 70%, 60%)",
|
|
78
|
-
ir0: "hsl(300, 70%, 60%)",
|
|
79
|
-
ir1: "hsl(278, 69.60%, 60.00%)",
|
|
80
|
-
ir2: "hsl(7, 69.60%, 60.00%)",
|
|
81
|
-
amb0: "hsl(231, 25.50%, 90.00%)",
|
|
82
|
-
battV: "hsl(194, 69.60%, 60.00%)",
|
|
83
|
-
powerBtn: "hsl(256, 69.60%, 60.00%)",
|
|
84
|
-
USB: "hsl(71, 69.60%, 60.00%)",
|
|
85
|
-
powerMan: "hsl(0, 69.60%, 60.00%)",
|
|
86
|
-
powerBtnLvl: "hsl(120, 69.60%, 60.00%)",
|
|
87
|
-
angle: "hsl(240, 69.60%, 60.00%)",
|
|
88
|
-
current: "hsl(300, 69.60%, 60.00%)",
|
|
89
|
-
state: "hsl(60, 69.60%, 60.00%)",
|
|
90
|
-
velocity: "hsl(120, 69.60%, 60.00%)",
|
|
91
|
-
});
|
|
92
|
-
|
|
93
|
-
useEffect(() => {
|
|
94
|
-
if (!deviceState) return;
|
|
95
|
-
|
|
96
|
-
const labels = deviceState.deviceTimeline.timestampsUs.slice(-maxChartDataPoints).map(time => {
|
|
97
|
-
const seconds = time / 1e6; // Convert microseconds to seconds
|
|
98
|
-
return seconds.toFixed(3); // Format decimal places
|
|
99
|
-
});
|
|
100
|
-
|
|
101
|
-
const uniqueAxes = new Map<string, { range: [number, number], units: string }>();
|
|
102
|
-
const datasets = Object.entries(deviceState.deviceAttributes)
|
|
103
|
-
.filter(([attributeName, attributeDetails]) => attributeDetails.visibleSeries !== false)
|
|
104
|
-
.map(([attributeName, attributeDetails]) => {
|
|
105
|
-
const data = attributeDetails.values.slice(-maxChartDataPoints);
|
|
106
|
-
let colour = colourMapRef.current[attributeName];
|
|
107
|
-
if (!colour) {
|
|
108
|
-
colour = `hsl(${Math.random() * 360}, 70%, 60%)`;
|
|
109
|
-
colourMapRef.current[attributeName] = colour;
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
// Ensure range has a minimum width if all values are the same
|
|
113
|
-
const minVal = Math.min(...attributeDetails.range);
|
|
114
|
-
const maxVal = Math.max(...attributeDetails.range);
|
|
115
|
-
const rangeEnds: [number, number] = minVal === maxVal
|
|
116
|
-
? [minVal - 1, maxVal + 1]
|
|
117
|
-
: [minVal, maxVal];
|
|
118
|
-
|
|
119
|
-
const axisKey = `${rangeEnds[0]}-${rangeEnds[1]}-${attributeDetails.units}`;
|
|
120
|
-
if (!uniqueAxes.has(axisKey)) {
|
|
121
|
-
uniqueAxes.set(axisKey, { range: rangeEnds, units: attributeDetails.units });
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
return {
|
|
125
|
-
label: attributeName,
|
|
126
|
-
data: data,
|
|
127
|
-
fill: false,
|
|
128
|
-
borderColor: colour,
|
|
129
|
-
backgroundColor: colour,
|
|
130
|
-
yAxisID: axisKey
|
|
131
|
-
};
|
|
132
|
-
});
|
|
133
|
-
|
|
134
|
-
const scales: { [key: string]: any } = {};
|
|
135
|
-
uniqueAxes.forEach((axis, key) => {
|
|
136
|
-
scales[key] = {
|
|
137
|
-
type: 'linear',
|
|
138
|
-
display: true,
|
|
139
|
-
position: 'left',
|
|
140
|
-
ticks: {
|
|
141
|
-
min: axis.range[0],
|
|
142
|
-
max: axis.range[1],
|
|
143
|
-
},
|
|
144
|
-
};
|
|
145
|
-
});
|
|
146
|
-
|
|
147
|
-
// Update options and chart data
|
|
148
|
-
options.scales = scales;
|
|
149
|
-
setChartData({ labels: labels.length ? labels : ['0.000'], datasets });
|
|
150
|
-
}, [lastUpdated]);
|
|
151
|
-
|
|
152
|
-
if (!deviceState || Object.keys(deviceState.deviceAttributes).length === 0) {
|
|
153
|
-
return <></>;
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
return (
|
|
157
|
-
<div className="device-line-chart">
|
|
158
|
-
<Line data={chartData} options={options} />
|
|
159
|
-
</div>
|
|
160
|
-
);
|
|
161
|
-
});
|
|
162
|
-
|
|
163
|
-
export default DeviceLineChart;
|
|
@@ -1,166 +0,0 @@
|
|
|
1
|
-
import React, { useEffect, useRef, useState } from 'react';
|
|
2
|
-
import './styles.css';
|
|
3
|
-
import { DeviceState } from '../../../src/RaftDeviceStates';
|
|
4
|
-
import DeviceAttrsForm from './DeviceAttrsForm';
|
|
5
|
-
import DeviceActionsForm from './DeviceActionsForm';
|
|
6
|
-
import DeviceLineChart from './DeviceLineChart';
|
|
7
|
-
import ConnManager from './ConnManager';
|
|
8
|
-
import SettingsManager from './SettingsManager';
|
|
9
|
-
|
|
10
|
-
const connManager = ConnManager.getInstance();
|
|
11
|
-
|
|
12
|
-
export interface DevicePanelProps {
|
|
13
|
-
deviceKey: string;
|
|
14
|
-
lastUpdated: number;
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
const DevicePanel = ({ deviceKey, lastUpdated }: DevicePanelProps) => {
|
|
18
|
-
const deviceManager = connManager.getConnector().getSystemType()?.deviceMgrIF;
|
|
19
|
-
const deviceState: DeviceState | undefined = deviceManager?.getDeviceState(deviceKey);
|
|
20
|
-
|
|
21
|
-
// Gray out the device panel if the device is offline
|
|
22
|
-
const offlineClass = deviceState?.isOnline ? '' : 'offline';
|
|
23
|
-
|
|
24
|
-
const [timedChartUpdate, setTimedChartUpdate] = useState<number>(0);
|
|
25
|
-
const [menuOpen, setMenuOpen] = useState<boolean>(false);
|
|
26
|
-
const menuRef = useRef<HTMLDivElement>(null);
|
|
27
|
-
|
|
28
|
-
const settingsManager = SettingsManager.getInstance();
|
|
29
|
-
const [showCharts, setShowCharts] = useState(
|
|
30
|
-
settingsManager.getSetting('showCharts')
|
|
31
|
-
);
|
|
32
|
-
|
|
33
|
-
useEffect(() => {
|
|
34
|
-
const startTime = Date.now();
|
|
35
|
-
const updateChart = () => {
|
|
36
|
-
setTimedChartUpdate(Date.now());
|
|
37
|
-
};
|
|
38
|
-
const updateTimer = setInterval(updateChart, 500);
|
|
39
|
-
return () => clearInterval(updateTimer);
|
|
40
|
-
}, []);
|
|
41
|
-
|
|
42
|
-
useEffect(() => {
|
|
43
|
-
const handleClickOutside = (event: MouseEvent) => {
|
|
44
|
-
if (menuRef.current && !menuRef.current.contains(event.target as Node)) {
|
|
45
|
-
setMenuOpen(false);
|
|
46
|
-
}
|
|
47
|
-
};
|
|
48
|
-
document.addEventListener("mousedown", handleClickOutside);
|
|
49
|
-
return () => {
|
|
50
|
-
document.removeEventListener("mousedown", handleClickOutside);
|
|
51
|
-
};
|
|
52
|
-
}, []);
|
|
53
|
-
|
|
54
|
-
const handleCopyToClipboard = () => {
|
|
55
|
-
if (!deviceState) {
|
|
56
|
-
return;
|
|
57
|
-
}
|
|
58
|
-
const headers = ["Time (s)"];
|
|
59
|
-
const rows: string[][] = [];
|
|
60
|
-
|
|
61
|
-
const timestampsUs = deviceState.deviceTimeline.timestampsUs;
|
|
62
|
-
const attributes = deviceState.deviceAttributes;
|
|
63
|
-
|
|
64
|
-
// Collect headers and initialize rows with timestamps
|
|
65
|
-
Object.keys(attributes).forEach(attrName => {
|
|
66
|
-
headers.push(attrName);
|
|
67
|
-
});
|
|
68
|
-
|
|
69
|
-
timestampsUs.forEach((timestampUs, index) => {
|
|
70
|
-
const row: string[] = [(timestampUs / 1000000.0).toString()];
|
|
71
|
-
Object.keys(attributes).forEach(attrName => {
|
|
72
|
-
const values = attributes[attrName].values;
|
|
73
|
-
row.push(values[index]?.toString() || "");
|
|
74
|
-
});
|
|
75
|
-
rows.push(row);
|
|
76
|
-
});
|
|
77
|
-
|
|
78
|
-
// Create a tab-separated string
|
|
79
|
-
const csvContent = [headers.join("\t"), ...rows.map(row => row.join("\t"))].join("\n");
|
|
80
|
-
|
|
81
|
-
// Try using navigator.clipboard.writeText, with a fallback to document.execCommand
|
|
82
|
-
if (navigator.clipboard) {
|
|
83
|
-
navigator.clipboard.writeText(csvContent).then(() => {
|
|
84
|
-
console.log("Device values copied to clipboard");
|
|
85
|
-
}).catch(err => {
|
|
86
|
-
console.error('Failed to copy: ', err);
|
|
87
|
-
fallbackCopyTextToClipboard(csvContent);
|
|
88
|
-
});
|
|
89
|
-
} else {
|
|
90
|
-
fallbackCopyTextToClipboard(csvContent);
|
|
91
|
-
}
|
|
92
|
-
setMenuOpen(false);
|
|
93
|
-
};
|
|
94
|
-
|
|
95
|
-
const fallbackCopyTextToClipboard = (text: string) => {
|
|
96
|
-
const textArea = document.createElement("textarea");
|
|
97
|
-
textArea.value = text;
|
|
98
|
-
|
|
99
|
-
// Avoid scrolling to bottom
|
|
100
|
-
textArea.style.top = "0";
|
|
101
|
-
textArea.style.left = "0";
|
|
102
|
-
textArea.style.position = "fixed";
|
|
103
|
-
|
|
104
|
-
document.body.appendChild(textArea);
|
|
105
|
-
textArea.focus();
|
|
106
|
-
textArea.select();
|
|
107
|
-
|
|
108
|
-
try {
|
|
109
|
-
document.execCommand("copy");
|
|
110
|
-
// alert("Device values copied to clipboard!");
|
|
111
|
-
} catch (err) {
|
|
112
|
-
console.error('Fallback: Oops, unable to copy', err);
|
|
113
|
-
alert("Failed to copy device values to clipboard");
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
document.body.removeChild(textArea);
|
|
117
|
-
};
|
|
118
|
-
|
|
119
|
-
let headerText = `Device ${deviceState?.deviceTypeInfo?.name}`;
|
|
120
|
-
if ((deviceState?.deviceAddress !== undefined) && (deviceState?.deviceAddress !== "") && (deviceState?.deviceAddress !== "0")) {
|
|
121
|
-
// See if we can identify I2C addresses - should start with two bytes of 0s and then have a byte which is slot and a byte which is address
|
|
122
|
-
const addrInt = parseInt(deviceState?.deviceAddress, 10);
|
|
123
|
-
if (addrInt < 65536) {
|
|
124
|
-
const slot = addrInt >> 8;
|
|
125
|
-
const address = ("00" + (addrInt & 0xFF).toString(16)).slice(-2);
|
|
126
|
-
headerText += ` I2C Address 0x${address}`;
|
|
127
|
-
if (slot === 0)
|
|
128
|
-
headerText += ` (Main Bus)`;
|
|
129
|
-
else
|
|
130
|
-
headerText += ` (Slot ${slot})`;
|
|
131
|
-
} else {
|
|
132
|
-
headerText += ` Address ${deviceState?.deviceAddress}`;
|
|
133
|
-
}
|
|
134
|
-
}
|
|
135
|
-
if ((deviceState?.busName !== undefined) && (deviceState?.busName !== "") && (deviceState?.busName !== "0")) {
|
|
136
|
-
headerText += ` Bus ${deviceState?.busName}`;
|
|
137
|
-
}
|
|
138
|
-
if (!deviceState?.isOnline) {
|
|
139
|
-
headerText += " (Offline)";
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
return (
|
|
143
|
-
<div className={`device-panel ${offlineClass}`}>
|
|
144
|
-
<div className="device-block-heading">
|
|
145
|
-
<div className="device-block-heading-text">{headerText}</div>
|
|
146
|
-
<div className="menu-icon always-enabled" onClick={() => setMenuOpen(!menuOpen)}>☰</div>
|
|
147
|
-
{menuOpen && (
|
|
148
|
-
<div className="dropdown-menu" ref={menuRef}>
|
|
149
|
-
<div className="menu-item always-enabled" onClick={handleCopyToClipboard}>Copy Values to Clipboard</div>
|
|
150
|
-
</div>
|
|
151
|
-
)}
|
|
152
|
-
</div>
|
|
153
|
-
<div className={`device-block-data`}>
|
|
154
|
-
<div className="device-attrs-and-actions">
|
|
155
|
-
<DeviceAttrsForm deviceKey={deviceKey} lastUpdated={lastUpdated} />
|
|
156
|
-
<DeviceActionsForm deviceKey={deviceKey} />
|
|
157
|
-
</div>
|
|
158
|
-
{showCharts &&
|
|
159
|
-
<DeviceLineChart deviceKey={deviceKey} lastUpdated={timedChartUpdate} />
|
|
160
|
-
}
|
|
161
|
-
</div>
|
|
162
|
-
</div>
|
|
163
|
-
);
|
|
164
|
-
};
|
|
165
|
-
|
|
166
|
-
export default DevicePanel;
|
|
@@ -1,58 +0,0 @@
|
|
|
1
|
-
// Component which uses the DeviceList component to display the list of devices
|
|
2
|
-
|
|
3
|
-
import React, { useEffect, useState } from 'react';
|
|
4
|
-
// import { DeviceAttributeState, DevicesState, DeviceState } from "../../../src/main";
|
|
5
|
-
// import { DeviceManager } from './DeviceManager';
|
|
6
|
-
// import DeviceScreen from './DeviceScreen';
|
|
7
|
-
import './styles.css';
|
|
8
|
-
import ConnManager from "./ConnManager";
|
|
9
|
-
import { DeviceAttributeState, DevicesState, DeviceState } from '../../../src/RaftDeviceStates';
|
|
10
|
-
import DevicePanel from './DevicePanel';
|
|
11
|
-
|
|
12
|
-
const connManager = ConnManager.getInstance();
|
|
13
|
-
|
|
14
|
-
export class DevicesPanelProps {
|
|
15
|
-
constructor(
|
|
16
|
-
) { }
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
export default function DevicesPanel(props: DevicesPanelProps) {
|
|
20
|
-
const [lastUpdated, setLastUpdated] = useState<number>(0);
|
|
21
|
-
|
|
22
|
-
useEffect(() => {
|
|
23
|
-
const deviceManager = connManager.getConnector().getSystemType()?.deviceMgrIF;
|
|
24
|
-
if (!deviceManager) {
|
|
25
|
-
return;
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
const onNewDevice = (deviceKey: string, newDeviceState: DeviceState) => {
|
|
29
|
-
setLastUpdated(Date.now());
|
|
30
|
-
};
|
|
31
|
-
deviceManager.addNewDeviceCallback(onNewDevice);
|
|
32
|
-
|
|
33
|
-
const onNewAttribute = (deviceKey: string, attribute: DeviceAttributeState) => {
|
|
34
|
-
setLastUpdated(Date.now());
|
|
35
|
-
}
|
|
36
|
-
deviceManager.addNewAttributeCallback(onNewAttribute);
|
|
37
|
-
|
|
38
|
-
const onNewAttributeData = (deviceKey: string, attribute: DeviceAttributeState) => {
|
|
39
|
-
setLastUpdated(Date.now());
|
|
40
|
-
// console.log(`New attribute data: ${deviceKey} ${attribute.name} ${attribute.values.length}`);
|
|
41
|
-
}
|
|
42
|
-
deviceManager.addAttributeDataCallback(onNewAttributeData);
|
|
43
|
-
|
|
44
|
-
}, []);
|
|
45
|
-
|
|
46
|
-
const deviceManager = connManager.getConnector().getSystemType()?.deviceMgrIF;
|
|
47
|
-
let devicesState: DevicesState = {};
|
|
48
|
-
if (deviceManager)
|
|
49
|
-
devicesState = deviceManager.getDevicesState();
|
|
50
|
-
|
|
51
|
-
return (
|
|
52
|
-
<div className="devices-container">
|
|
53
|
-
{Object.entries(devicesState).filter(([key, _]) => key !== 'getDeviceKey').map(([deviceKey, data]) => (
|
|
54
|
-
<DevicePanel key={deviceKey} deviceKey={deviceKey} lastUpdated={lastUpdated} />
|
|
55
|
-
))}
|
|
56
|
-
</div>
|
|
57
|
-
);
|
|
58
|
-
}
|
|
@@ -1,110 +0,0 @@
|
|
|
1
|
-
import React, { useState } from 'react';
|
|
2
|
-
import DispOneLED from './DispOneLed';
|
|
3
|
-
import ConnManager from './ConnManager';
|
|
4
|
-
import { DeviceTypeAction } from '../../../src/RaftDeviceInfo';
|
|
5
|
-
import { CirclePicker } from 'react-color';
|
|
6
|
-
|
|
7
|
-
const connManager = ConnManager.getInstance();
|
|
8
|
-
|
|
9
|
-
interface LEDGridProps {
|
|
10
|
-
rows: number;
|
|
11
|
-
cols: number;
|
|
12
|
-
deviceKey: string;
|
|
13
|
-
deviceAction: DeviceTypeAction;
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
const customColors = [
|
|
17
|
-
'#000000', // black
|
|
18
|
-
'#FFFFFF', // white
|
|
19
|
-
'#FF0000', // red
|
|
20
|
-
'#00FF00', // green
|
|
21
|
-
'#0000FF', // blue
|
|
22
|
-
'#FFFF00', // yellow
|
|
23
|
-
'#FF00FF', // pink
|
|
24
|
-
'#00FFFF', // cyan
|
|
25
|
-
'#FFA500', // orange
|
|
26
|
-
'#800080', // purple
|
|
27
|
-
'#808080', // gray
|
|
28
|
-
'#A52A2A', // brown
|
|
29
|
-
'#008000', // dark green
|
|
30
|
-
'#800000', // maroon
|
|
31
|
-
'#008080', // teal
|
|
32
|
-
'#000080', // navy
|
|
33
|
-
'#FFD700', // gold
|
|
34
|
-
'#FF4500', // orange red
|
|
35
|
-
'#FF6347', // tomato
|
|
36
|
-
// Add more custom colors as needed
|
|
37
|
-
];
|
|
38
|
-
|
|
39
|
-
const DispLEDGrid: React.FC<LEDGridProps> = ({ rows, cols, deviceKey, deviceAction }) => {
|
|
40
|
-
// Initialize the grid with all LEDs turned off (black)
|
|
41
|
-
const [colors, setColors] = useState<string[][]>(
|
|
42
|
-
Array.from({ length: rows }, () => Array.from({ length: cols }, () => '#000000'))
|
|
43
|
-
);
|
|
44
|
-
const [activeLED, setActiveLED] = useState<{row: number, col: number} | null>(null);
|
|
45
|
-
|
|
46
|
-
const handleLEDClick = (row: number, col: number) => {
|
|
47
|
-
setActiveLED({ row, col });
|
|
48
|
-
};
|
|
49
|
-
|
|
50
|
-
const hexToRgb = (hex: string): number[] => {
|
|
51
|
-
const r = parseInt(hex.slice(1, 3), 16);
|
|
52
|
-
const g = parseInt(hex.slice(3, 5), 16);
|
|
53
|
-
const b = parseInt(hex.slice(5, 7), 16);
|
|
54
|
-
return [r, g, b];
|
|
55
|
-
};
|
|
56
|
-
|
|
57
|
-
const handleChangeComplete = (color: any) => {
|
|
58
|
-
if (activeLED) {
|
|
59
|
-
const { row, col } = activeLED;
|
|
60
|
-
const newColors = colors.map((rowColors, rowIndex) =>
|
|
61
|
-
rowColors.map((colColor, colIndex) =>
|
|
62
|
-
rowIndex === row && colIndex === col ? color.hex : colColor
|
|
63
|
-
)
|
|
64
|
-
);
|
|
65
|
-
setColors(newColors);
|
|
66
|
-
setActiveLED(null); // Optionally close the picker automatically
|
|
67
|
-
|
|
68
|
-
// Convert into a list of RGB values
|
|
69
|
-
let colourList = [];
|
|
70
|
-
for (let i = 0; i < rows; i++) {
|
|
71
|
-
for (let j = 0; j < cols; j++) {
|
|
72
|
-
colourList.push(hexToRgb(newColors[i][j]));
|
|
73
|
-
}
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
// Send result
|
|
77
|
-
const deviceManager = connManager.getConnector().getSystemType()?.deviceMgrIF;
|
|
78
|
-
if (deviceManager) {
|
|
79
|
-
deviceManager.sendCompoundAction(deviceKey, deviceAction, colourList);
|
|
80
|
-
}
|
|
81
|
-
}
|
|
82
|
-
};
|
|
83
|
-
|
|
84
|
-
return (
|
|
85
|
-
<div>
|
|
86
|
-
<div style={{
|
|
87
|
-
display: 'grid',
|
|
88
|
-
gridTemplateColumns: `repeat(${cols}, 24px)`,
|
|
89
|
-
gridTemplateRows: `${rows === 1 ? '1fr' : `repeat(${rows}, 24px)`}`,
|
|
90
|
-
justifyContent: 'center',
|
|
91
|
-
width: `${cols * 24}px`
|
|
92
|
-
}}>
|
|
93
|
-
{colors.map((row, rowIndex) =>
|
|
94
|
-
row.map((color, colIndex) => (
|
|
95
|
-
<DispOneLED key={`${rowIndex}-${colIndex}`} color={color} onClick={() => handleLEDClick(rowIndex, colIndex)} />
|
|
96
|
-
))
|
|
97
|
-
)}
|
|
98
|
-
</div>
|
|
99
|
-
{activeLED && (
|
|
100
|
-
<CirclePicker
|
|
101
|
-
color={colors[activeLED.row][activeLED.col]}
|
|
102
|
-
colors={customColors}
|
|
103
|
-
onChangeComplete={handleChangeComplete}
|
|
104
|
-
/>
|
|
105
|
-
)}
|
|
106
|
-
</div>
|
|
107
|
-
);
|
|
108
|
-
};
|
|
109
|
-
|
|
110
|
-
export default DispLEDGrid;
|
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
import React from 'react';
|
|
2
|
-
|
|
3
|
-
interface LEDProps {
|
|
4
|
-
color: string;
|
|
5
|
-
onClick: () => void;
|
|
6
|
-
}
|
|
7
|
-
|
|
8
|
-
const DispOneLED: React.FC<LEDProps> = ({ color, onClick }) => {
|
|
9
|
-
return (
|
|
10
|
-
<div style={{
|
|
11
|
-
width: '20px',
|
|
12
|
-
height: '20px',
|
|
13
|
-
backgroundColor: color,
|
|
14
|
-
margin: '2px',
|
|
15
|
-
cursor: 'pointer'
|
|
16
|
-
}} onClick={onClick} />
|
|
17
|
-
);
|
|
18
|
-
};
|
|
19
|
-
|
|
20
|
-
export default DispOneLED;
|
|
@@ -1,130 +0,0 @@
|
|
|
1
|
-
import { mean, standardDeviation } from 'simple-statistics';
|
|
2
|
-
import { DeviceAttributeState } from '../../../src/RaftDeviceStates';
|
|
3
|
-
import SettingsManager from './SettingsManager';
|
|
4
|
-
|
|
5
|
-
class LatencyTest {
|
|
6
|
-
private static instance: LatencyTest;
|
|
7
|
-
|
|
8
|
-
private lastWhiteTime: number | null = null;
|
|
9
|
-
private lastBlackTime: number | null = null;
|
|
10
|
-
private lastAttrValue: number | null = null;
|
|
11
|
-
|
|
12
|
-
private latencyRecords: { type: 'white' | 'black'; latency: number }[] = [];
|
|
13
|
-
private latencyWindowSize: number = 10;
|
|
14
|
-
private sampleCounter: number = 0;
|
|
15
|
-
|
|
16
|
-
// Singleton access
|
|
17
|
-
static getInstance(): LatencyTest {
|
|
18
|
-
if (!LatencyTest.instance) {
|
|
19
|
-
LatencyTest.instance = new LatencyTest();
|
|
20
|
-
}
|
|
21
|
-
return LatencyTest.instance;
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
// Get abruptChangeThreshold
|
|
25
|
-
private get abruptChangeThreshold(): number {
|
|
26
|
-
const settingsManager = SettingsManager.getInstance();
|
|
27
|
-
return settingsManager.getSetting('latencyChangeThreshold') || 50;
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
// Record color change time
|
|
31
|
-
recordColorChange(color: 'white' | 'black', timestamp: number): void {
|
|
32
|
-
if (color === 'white') {
|
|
33
|
-
this.lastWhiteTime = timestamp;
|
|
34
|
-
this.lastBlackTime = null;
|
|
35
|
-
} else if (color === 'black') {
|
|
36
|
-
this.lastBlackTime = timestamp;
|
|
37
|
-
this.lastWhiteTime = null;
|
|
38
|
-
}
|
|
39
|
-
// console.log(`Color change recorded: ${color} at ${timestamp}`);
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
// Process values
|
|
43
|
-
processAttrValues(attribute: DeviceAttributeState, timestamp: number): void {
|
|
44
|
-
for (let i = 0; i < attribute.numNewValues; i++) {
|
|
45
|
-
const newValue = attribute.values[attribute.values.length - attribute.numNewValues + i];
|
|
46
|
-
// console.log(`New value: ${newValue} prev value: ${this.lastAttrValue}`);
|
|
47
|
-
if (this.lastAttrValue === null) {
|
|
48
|
-
this.lastAttrValue = newValue;
|
|
49
|
-
return;
|
|
50
|
-
}
|
|
51
|
-
this.sampleCounter++;
|
|
52
|
-
|
|
53
|
-
// Calculate change and update last value
|
|
54
|
-
const change = newValue - this.lastAttrValue;
|
|
55
|
-
this.lastAttrValue = newValue;
|
|
56
|
-
|
|
57
|
-
// Check size of change - needs to be above threshold
|
|
58
|
-
if (Math.abs(change) < this.abruptChangeThreshold) {
|
|
59
|
-
continue;
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
// console.log(`[${new Date().toISOString()}] new ${newValue} chg ${Math.abs(change)} >thresh ${Math.abs(change) >= this.abruptChangeThreshold} ${this.sampleCounter}`);
|
|
63
|
-
|
|
64
|
-
// Skip invalid changes (in the wrong direction) - also skips repeated values
|
|
65
|
-
// since lastWhiteTime and lastBlackTime are cleared after a change
|
|
66
|
-
if ((change >= 0 && this.lastWhiteTime === null) || (change < 0 && this.lastBlackTime === null)) {
|
|
67
|
-
// console.log(`Invalid change detected: ${change} lastWhite ${this.lastWhiteTime} lastBlack ${this.lastBlackTime}`);
|
|
68
|
-
continue;
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
// console.log(
|
|
72
|
-
// `[${new Date().toISOString()}] ${newValue} ${this.lastAttrValue} ${change} ${Math.abs(change)} ${this.abruptChangeThreshold} ${Math.abs(change) >= this.abruptChangeThreshold} ${this.sampleCounter} ${this.lastTriggerIndex}`
|
|
73
|
-
// );
|
|
74
|
-
|
|
75
|
-
// console.log(`Sample counter = ${this.sampleCounter} Last trigger index = ${this.lastTriggerIndex} Diff = ${this.sampleCounter - this.lastTriggerIndex}`);
|
|
76
|
-
|
|
77
|
-
// Detect abrupt change with threshold
|
|
78
|
-
if (Math.abs(change) >= this.abruptChangeThreshold) {
|
|
79
|
-
const eventType = change > 0 ? 'white' : 'black';
|
|
80
|
-
const relatedTime =
|
|
81
|
-
eventType === 'white' ? this.lastWhiteTime : this.lastBlackTime;
|
|
82
|
-
|
|
83
|
-
if (relatedTime !== null) {
|
|
84
|
-
const latency = timestamp - relatedTime;
|
|
85
|
-
this.latencyRecords.push({ type: eventType, latency });
|
|
86
|
-
if (this.latencyRecords.length > this.latencyWindowSize) {
|
|
87
|
-
this.latencyRecords.shift();
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
// console.log(
|
|
91
|
-
// `[${new Date().toISOString()}] Triggered: ${eventType} change ${change} detected. Last white time = ${this.lastWhiteTime} Last black time = ${this.lastBlackTime} Latency = ${latency} ms`
|
|
92
|
-
// );
|
|
93
|
-
}
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
// Clear timers of change
|
|
97
|
-
this.lastWhiteTime = null;
|
|
98
|
-
this.lastBlackTime = null;
|
|
99
|
-
}
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
// Get latency stats
|
|
103
|
-
getLatencyStats(): {
|
|
104
|
-
meanLatency: number | null;
|
|
105
|
-
stdDevLatency: number | null;
|
|
106
|
-
records: { type: 'white' | 'black'; latency: number }[];
|
|
107
|
-
} {
|
|
108
|
-
if (this.latencyRecords.length === 0) {
|
|
109
|
-
return {
|
|
110
|
-
meanLatency: null,
|
|
111
|
-
stdDevLatency: null,
|
|
112
|
-
records: [],
|
|
113
|
-
};
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
const latencies = this.latencyRecords.map((record) => record.latency);
|
|
117
|
-
const meanLatency = mean(latencies);
|
|
118
|
-
const stdDevLatency = standardDeviation(latencies);
|
|
119
|
-
|
|
120
|
-
// console.log(`Mean latency: ${meanLatency} ms, Std Dev: ${stdDevLatency} ms Num records: ${this.latencyRecords.length}`);
|
|
121
|
-
|
|
122
|
-
return {
|
|
123
|
-
meanLatency,
|
|
124
|
-
stdDevLatency,
|
|
125
|
-
records: this.latencyRecords,
|
|
126
|
-
};
|
|
127
|
-
}
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
export default LatencyTest;
|