@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.
Files changed (205) hide show
  1. package/dist/web/RaftAttributeHandler.js +5 -5
  2. package/dist/web/RaftAttributeHandler.js.map +1 -1
  3. package/dist/web/RaftChannel.d.ts +2 -0
  4. package/dist/web/RaftChannelBLE.web.d.ts +2 -0
  5. package/dist/web/RaftChannelBLE.web.js +10 -0
  6. package/dist/web/RaftChannelBLE.web.js.map +1 -1
  7. package/dist/{react-native/RaftChannelWebSocket.d.ts → web/RaftChannelSimulated.d.ts} +9 -5
  8. package/dist/web/RaftChannelSimulated.js +418 -0
  9. package/dist/web/RaftChannelSimulated.js.map +1 -0
  10. package/dist/web/RaftChannelWebSerial.d.ts +2 -0
  11. package/dist/web/RaftChannelWebSerial.js +10 -0
  12. package/dist/web/RaftChannelWebSerial.js.map +1 -1
  13. package/dist/web/RaftChannelWebSocket.d.ts +2 -0
  14. package/dist/web/RaftChannelWebSocket.js +10 -0
  15. package/dist/web/RaftChannelWebSocket.js.map +1 -1
  16. package/dist/web/RaftConnector.js +5 -0
  17. package/dist/web/RaftConnector.js.map +1 -1
  18. package/dist/web/RaftDeviceInfo.d.ts +1 -1
  19. package/dist/web/RaftMsgHandler.d.ts +5 -0
  20. package/dist/web/RaftMsgHandler.js +32 -0
  21. package/dist/web/RaftMsgHandler.js.map +1 -1
  22. package/dist/web/main.d.ts +1 -0
  23. package/dist/web/main.js +3 -1
  24. package/dist/web/main.js.map +1 -1
  25. package/package.json +5 -2
  26. package/.editorconfig +0 -14
  27. package/.gitattributes +0 -11
  28. package/.nvmrc +0 -1
  29. package/TODO.md +0 -1
  30. package/dist/react-native/RaftAttributeHandler.d.ts +0 -12
  31. package/dist/react-native/RaftAttributeHandler.js +0 -249
  32. package/dist/react-native/RaftAttributeHandler.js.map +0 -1
  33. package/dist/react-native/RaftChannel.d.ts +0 -18
  34. package/dist/react-native/RaftChannel.js +0 -12
  35. package/dist/react-native/RaftChannel.js.map +0 -1
  36. package/dist/react-native/RaftChannelBLE.native.d.ts +0 -93
  37. package/dist/react-native/RaftChannelBLE.native.js +0 -472
  38. package/dist/react-native/RaftChannelBLE.native.js.map +0 -1
  39. package/dist/react-native/RaftChannelBLE.web.d.ts +0 -38
  40. package/dist/react-native/RaftChannelBLE.web.js +0 -290
  41. package/dist/react-native/RaftChannelBLE.web.js.map +0 -1
  42. package/dist/react-native/RaftChannelBLEFactory.d.ts +0 -10
  43. package/dist/react-native/RaftChannelBLEFactory.js +0 -17
  44. package/dist/react-native/RaftChannelBLEFactory.js.map +0 -1
  45. package/dist/react-native/RaftChannelBLEScanner.native.d.ts +0 -18
  46. package/dist/react-native/RaftChannelBLEScanner.native.js +0 -138
  47. package/dist/react-native/RaftChannelBLEScanner.native.js.map +0 -1
  48. package/dist/react-native/RaftChannelWebSerial.d.ts +0 -37
  49. package/dist/react-native/RaftChannelWebSerial.js +0 -319
  50. package/dist/react-native/RaftChannelWebSerial.js.map +0 -1
  51. package/dist/react-native/RaftChannelWebSocket.js +0 -197
  52. package/dist/react-native/RaftChannelWebSocket.js.map +0 -1
  53. package/dist/react-native/RaftCommsStats.d.ts +0 -39
  54. package/dist/react-native/RaftCommsStats.js +0 -128
  55. package/dist/react-native/RaftCommsStats.js.map +0 -1
  56. package/dist/react-native/RaftConnEvents.d.ts +0 -39
  57. package/dist/react-native/RaftConnEvents.js +0 -54
  58. package/dist/react-native/RaftConnEvents.js.map +0 -1
  59. package/dist/react-native/RaftConnector.d.ts +0 -245
  60. package/dist/react-native/RaftConnector.js +0 -616
  61. package/dist/react-native/RaftConnector.js.map +0 -1
  62. package/dist/react-native/RaftCustomAttrHandler.d.ts +0 -4
  63. package/dist/react-native/RaftCustomAttrHandler.js +0 -50
  64. package/dist/react-native/RaftCustomAttrHandler.js.map +0 -1
  65. package/dist/react-native/RaftDeviceInfo.d.ts +0 -63
  66. package/dist/react-native/RaftDeviceInfo.js +0 -36
  67. package/dist/react-native/RaftDeviceInfo.js.map +0 -1
  68. package/dist/react-native/RaftDeviceManager.d.ts +0 -40
  69. package/dist/react-native/RaftDeviceManager.js +0 -499
  70. package/dist/react-native/RaftDeviceManager.js.map +0 -1
  71. package/dist/react-native/RaftDeviceMgrIF.d.ts +0 -15
  72. package/dist/react-native/RaftDeviceMgrIF.js +0 -11
  73. package/dist/react-native/RaftDeviceMgrIF.js.map +0 -1
  74. package/dist/react-native/RaftDeviceMsg.d.ts +0 -9
  75. package/dist/react-native/RaftDeviceMsg.js +0 -11
  76. package/dist/react-native/RaftDeviceMsg.js.map +0 -1
  77. package/dist/react-native/RaftDeviceStates.d.ts +0 -37
  78. package/dist/react-native/RaftDeviceStates.js +0 -60
  79. package/dist/react-native/RaftDeviceStates.js.map +0 -1
  80. package/dist/react-native/RaftFileHandler.d.ts +0 -52
  81. package/dist/react-native/RaftFileHandler.js +0 -502
  82. package/dist/react-native/RaftFileHandler.js.map +0 -1
  83. package/dist/react-native/RaftLog.d.ts +0 -22
  84. package/dist/react-native/RaftLog.js +0 -63
  85. package/dist/react-native/RaftLog.js.map +0 -1
  86. package/dist/react-native/RaftMiniHDLC.d.ts +0 -18
  87. package/dist/react-native/RaftMiniHDLC.js +0 -383
  88. package/dist/react-native/RaftMiniHDLC.js.map +0 -1
  89. package/dist/react-native/RaftMsgHandler.d.ts +0 -57
  90. package/dist/react-native/RaftMsgHandler.js +0 -479
  91. package/dist/react-native/RaftMsgHandler.js.map +0 -1
  92. package/dist/react-native/RaftMsgTrackInfo.d.ts +0 -17
  93. package/dist/react-native/RaftMsgTrackInfo.js +0 -42
  94. package/dist/react-native/RaftMsgTrackInfo.js.map +0 -1
  95. package/dist/react-native/RaftProtocolDefs.d.ts +0 -30
  96. package/dist/react-native/RaftProtocolDefs.js +0 -48
  97. package/dist/react-native/RaftProtocolDefs.js.map +0 -1
  98. package/dist/react-native/RaftStreamHandler.d.ts +0 -38
  99. package/dist/react-native/RaftStreamHandler.js +0 -257
  100. package/dist/react-native/RaftStreamHandler.js.map +0 -1
  101. package/dist/react-native/RaftStruct.d.ts +0 -3
  102. package/dist/react-native/RaftStruct.js +0 -208
  103. package/dist/react-native/RaftStruct.js.map +0 -1
  104. package/dist/react-native/RaftSysTypeManager.d.ts +0 -14
  105. package/dist/react-native/RaftSysTypeManager.js +0 -53
  106. package/dist/react-native/RaftSysTypeManager.js.map +0 -1
  107. package/dist/react-native/RaftSystemType.d.ts +0 -28
  108. package/dist/react-native/RaftSystemType.js +0 -3
  109. package/dist/react-native/RaftSystemType.js.map +0 -1
  110. package/dist/react-native/RaftSystemUtils.d.ts +0 -136
  111. package/dist/react-native/RaftSystemUtils.js +0 -410
  112. package/dist/react-native/RaftSystemUtils.js.map +0 -1
  113. package/dist/react-native/RaftTypes.d.ts +0 -194
  114. package/dist/react-native/RaftTypes.js +0 -153
  115. package/dist/react-native/RaftTypes.js.map +0 -1
  116. package/dist/react-native/RaftUpdateEvents.d.ts +0 -33
  117. package/dist/react-native/RaftUpdateEvents.js +0 -46
  118. package/dist/react-native/RaftUpdateEvents.js.map +0 -1
  119. package/dist/react-native/RaftUpdateManager.d.ts +0 -61
  120. package/dist/react-native/RaftUpdateManager.js +0 -621
  121. package/dist/react-native/RaftUpdateManager.js.map +0 -1
  122. package/dist/react-native/RaftUtils.d.ts +0 -126
  123. package/dist/react-native/RaftUtils.js +0 -467
  124. package/dist/react-native/RaftUtils.js.map +0 -1
  125. package/dist/react-native/RaftWifiTypes.d.ts +0 -23
  126. package/dist/react-native/RaftWifiTypes.js +0 -43
  127. package/dist/react-native/RaftWifiTypes.js.map +0 -1
  128. package/dist/react-native/main.d.ts +0 -24
  129. package/dist/react-native/main.js +0 -49
  130. package/dist/react-native/main.js.map +0 -1
  131. package/eslint.config.mjs +0 -33
  132. package/examples/dashboard/package.json +0 -36
  133. package/examples/dashboard/src/CommandPanel.tsx +0 -147
  134. package/examples/dashboard/src/ConnManager.ts +0 -164
  135. package/examples/dashboard/src/DeviceActionsForm.tsx +0 -133
  136. package/examples/dashboard/src/DeviceAttrsForm.tsx +0 -49
  137. package/examples/dashboard/src/DeviceLineChart.tsx +0 -163
  138. package/examples/dashboard/src/DevicePanel.tsx +0 -166
  139. package/examples/dashboard/src/DevicesPanel.tsx +0 -58
  140. package/examples/dashboard/src/DispLedGrid.tsx +0 -110
  141. package/examples/dashboard/src/DispOneLed.tsx +0 -20
  142. package/examples/dashboard/src/LatencyTest.ts +0 -130
  143. package/examples/dashboard/src/LatencyTestPanel.tsx +0 -92
  144. package/examples/dashboard/src/Main.tsx +0 -234
  145. package/examples/dashboard/src/SettingsManager.ts +0 -67
  146. package/examples/dashboard/src/SettingsScreen.tsx +0 -174
  147. package/examples/dashboard/src/StatusPanel.tsx +0 -71
  148. package/examples/dashboard/src/SystemTypeCog/CogStateInfo.ts +0 -163
  149. package/examples/dashboard/src/SystemTypeCog/SystemTypeCog.ts +0 -91
  150. package/examples/dashboard/src/SystemTypeGeneric/StateInfoGeneric.ts +0 -30
  151. package/examples/dashboard/src/SystemTypeGeneric/SystemTypeGeneric.ts +0 -91
  152. package/examples/dashboard/src/SystemTypeMarty/RICAddOn.ts +0 -70
  153. package/examples/dashboard/src/SystemTypeMarty/RICAddOnBase.ts +0 -33
  154. package/examples/dashboard/src/SystemTypeMarty/RICAddOnManager.ts +0 -342
  155. package/examples/dashboard/src/SystemTypeMarty/RICCommsStats.ts +0 -170
  156. package/examples/dashboard/src/SystemTypeMarty/RICHWElem.ts +0 -123
  157. package/examples/dashboard/src/SystemTypeMarty/RICLEDPatternChecker.ts +0 -207
  158. package/examples/dashboard/src/SystemTypeMarty/RICROSSerial.ts +0 -464
  159. package/examples/dashboard/src/SystemTypeMarty/RICServoFaultDetector.ts +0 -146
  160. package/examples/dashboard/src/SystemTypeMarty/RICStateInfo.ts +0 -97
  161. package/examples/dashboard/src/SystemTypeMarty/RICSystemUtils.ts +0 -371
  162. package/examples/dashboard/src/SystemTypeMarty/RICTypes.ts +0 -20
  163. package/examples/dashboard/src/SystemTypeMarty/SystemTypeMarty.ts +0 -119
  164. package/examples/dashboard/src/index.html +0 -15
  165. package/examples/dashboard/src/index.tsx +0 -13
  166. package/examples/dashboard/src/styles.css +0 -408
  167. package/examples/dashboard/tsconfig.json +0 -18
  168. package/jest.config.js +0 -11
  169. package/src/RaftAttributeHandler.ts +0 -298
  170. package/src/RaftChannel.ts +0 -30
  171. package/src/RaftChannelBLE.native.ts +0 -604
  172. package/src/RaftChannelBLE.web.ts +0 -359
  173. package/src/RaftChannelBLEFactory.ts +0 -13
  174. package/src/RaftChannelBLEScanner.native.ts +0 -184
  175. package/src/RaftChannelWebSerial.ts +0 -408
  176. package/src/RaftChannelWebSocket.ts +0 -245
  177. package/src/RaftCommsStats.ts +0 -142
  178. package/src/RaftConnEvents.ts +0 -58
  179. package/src/RaftConnector.ts +0 -739
  180. package/src/RaftCustomAttrHandler.ts +0 -54
  181. package/src/RaftDeviceInfo.ts +0 -102
  182. package/src/RaftDeviceManager.ts +0 -607
  183. package/src/RaftDeviceMgrIF.ts +0 -33
  184. package/src/RaftDeviceMsg.ts +0 -20
  185. package/src/RaftDeviceStates.ts +0 -92
  186. package/src/RaftFileHandler.ts +0 -668
  187. package/src/RaftLog.ts +0 -70
  188. package/src/RaftMiniHDLC.ts +0 -396
  189. package/src/RaftMsgHandler.ts +0 -777
  190. package/src/RaftMsgTrackInfo.ts +0 -51
  191. package/src/RaftProtocolDefs.ts +0 -46
  192. package/src/RaftStreamHandler.ts +0 -328
  193. package/src/RaftStruct.ts +0 -209
  194. package/src/RaftSysTypeManager.ts +0 -60
  195. package/src/RaftSystemType.ts +0 -32
  196. package/src/RaftSystemUtils.ts +0 -487
  197. package/src/RaftTypes.ts +0 -278
  198. package/src/RaftUpdateEvents.ts +0 -48
  199. package/src/RaftUpdateManager.ts +0 -781
  200. package/src/RaftUtils.ts +0 -494
  201. package/src/RaftWifiTypes.ts +0 -36
  202. package/src/main.ts +0 -37
  203. package/testdata/TestDeviceTypeRecs.json +0 -492
  204. package/tsconfig.json +0 -30
  205. 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;