Skip to content

Commit 17708f7

Browse files
[Simulator] Initial data logging (#922)
Similar in approach to radio. Co-authored-by: Robert Knight <[email protected]>
1 parent 76745b2 commit 17708f7

18 files changed

+671
-48
lines changed

.circleci/config.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ _default_workflow: &default_workflow
88
- "CircleCI API"
99
- "AWS Web"
1010
_defaults: &defaults
11+
resource_class: large
1112
working_directory: ~/repo
1213
_docker_defaults: &docker_defaults
1314
image: cimg/node:16.14

lang/ui.en.json

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -799,6 +799,26 @@
799799
"defaultMessage": "Collapse {title} module",
800800
"description": "Aria label for collapse simulator module button"
801801
},
802+
"simulator-data-logging-empty": {
803+
"defaultMessage": "No log entries.",
804+
"description": "Shown in the simulator Data logging table when there are no rows"
805+
},
806+
"simulator-data-logging-full": {
807+
"defaultMessage": "Log full",
808+
"description": "Shown below the Data logging table to warn that the log is full"
809+
},
810+
"simulator-data-logging-rows": {
811+
"defaultMessage": "{count, plural, =0 {No rows logged} 1 {# row logged} other {# rows logged}}",
812+
"description": "Indicator of the number of rows logged"
813+
},
814+
"simulator-data-logging-save-log": {
815+
"defaultMessage": "Save log",
816+
"description": "Action label to save the data log as a file from the Data logging simulator panel"
817+
},
818+
"simulator-data-logging-truncated": {
819+
"defaultMessage": "Older rows not shown",
820+
"description": "Text shown in the Data logging table to indicate that old rows have been omitted"
821+
},
802822
"simulator-expand": {
803823
"defaultMessage": "Expand simulator",
804824
"description": "Aria label for the expand simulator button"
@@ -831,6 +851,10 @@
831851
"defaultMessage": "Light level",
832852
"description": "Light level title"
833853
},
854+
"simulator-log": {
855+
"defaultMessage": "Data log",
856+
"description": "Data log title"
857+
},
834858
"simulator-loud": {
835859
"defaultMessage": "Loud",
836860
"description": "Sound level high threshold marker hover text"

lang/ui.fr.json

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -798,6 +798,26 @@
798798
"defaultMessage": "Collapse {title} module",
799799
"description": "Aria label for collapse simulator module button"
800800
},
801+
"simulator-data-logging-empty": {
802+
"defaultMessage": "No log entries.",
803+
"description": "Shown in the simulator Data logging table when there are no rows"
804+
},
805+
"simulator-data-logging-full": {
806+
"defaultMessage": "Log full",
807+
"description": "Shown below the Data logging table to warn that the log is full"
808+
},
809+
"simulator-data-logging-rows": {
810+
"defaultMessage": "{count, plural, =0 {No rows} 1 {# row} other {# rows}}",
811+
"description": "Indicator of the number of rows logged"
812+
},
813+
"simulator-data-logging-save-log": {
814+
"defaultMessage": "Save log",
815+
"description": "Action label to save the data log as a file from the Data logging simulator panel"
816+
},
817+
"simulator-data-logging-truncated": {
818+
"defaultMessage": "Older rows not shown",
819+
"description": "Text shown in the Data logging table to indicate that old rows have been omitted"
820+
},
801821
"simulator-expand": {
802822
"defaultMessage": "Expand simulator",
803823
"description": "Aria label for the expand simulator button"
@@ -830,6 +850,10 @@
830850
"defaultMessage": "Light level",
831851
"description": "Light level title"
832852
},
853+
"simulator-log": {
854+
"defaultMessage": "Data log",
855+
"description": "Data log title"
856+
},
833857
"simulator-loud": {
834858
"defaultMessage": "Loud",
835859
"description": "Sound level high threshold marker hover text"

lang/ui.lol.json

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -798,6 +798,26 @@
798798
"defaultMessage": "Collapse {title} module",
799799
"description": "Aria label for collapse simulator module button"
800800
},
801+
"simulator-data-logging-empty": {
802+
"defaultMessage": "No log entries.",
803+
"description": "Shown in the simulator Data logging table when there are no rows"
804+
},
805+
"simulator-data-logging-full": {
806+
"defaultMessage": "Log full",
807+
"description": "Shown below the Data logging table to warn that the log is full"
808+
},
809+
"simulator-data-logging-rows": {
810+
"defaultMessage": "{count, plural, =0 {No rows} 1 {# row} other {# rows}}",
811+
"description": "Indicator of the number of rows logged"
812+
},
813+
"simulator-data-logging-save-log": {
814+
"defaultMessage": "Save log",
815+
"description": "Action label to save the data log as a file from the Data logging simulator panel"
816+
},
817+
"simulator-data-logging-truncated": {
818+
"defaultMessage": "Older rows not shown",
819+
"description": "Text shown in the Data logging table to indicate that old rows have been omitted"
820+
},
801821
"simulator-expand": {
802822
"defaultMessage": "Expand simulator",
803823
"description": "Aria label for the expand simulator button"
@@ -830,6 +850,10 @@
830850
"defaultMessage": "Light level",
831851
"description": "Light level title"
832852
},
853+
"simulator-log": {
854+
"defaultMessage": "Data log",
855+
"description": "Data log title"
856+
},
833857
"simulator-loud": {
834858
"defaultMessage": "Loud",
835859
"description": "Sound level high threshold marker hover text"

src/common/use-raf-state.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@ import useIsUnmounted from "./use-is-unmounted";
88

99
/**
1010
* State that rate limits changes with request animation frame.
11+
*
12+
* Note that if you rely on the previous state value you'll get a stale one.
1113
*/
1214
const useRafState = <S>(
1315
initialState: S | (() => S)

src/device/simulator.ts

Lines changed: 45 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import {
1515
} from "./device";
1616

1717
// Simulator-only events.
18+
export const EVENT_LOG_DATA = "log_data";
1819
export const EVENT_RADIO_DATA = "radio_data";
1920
export const EVENT_RADIO_GROUP = "radio_group";
2021
export const EVENT_RADIO_RESET = "radio_reset";
@@ -54,6 +55,11 @@ export interface EnumSensor {
5455

5556
export type Sensor = RangeSensor | EnumSensor;
5657

58+
export interface LogEntry {
59+
headings?: string[];
60+
data?: string[];
61+
}
62+
5763
export interface SimulatorState {
5864
radio: RadioState;
5965

@@ -96,6 +102,21 @@ export type SensorStateKey = Extract<
96102
| "buttonB"
97103
>;
98104

105+
export interface DataLog {
106+
headings: string[];
107+
data: DataLogRow[];
108+
}
109+
110+
export interface DataLogRow {
111+
isHeading?: boolean;
112+
data: string[];
113+
}
114+
115+
const initialDataLog = (): DataLog => ({
116+
headings: [],
117+
data: [],
118+
});
119+
99120
/**
100121
* A simulated device.
101122
*
@@ -108,13 +129,14 @@ export class SimulatorDeviceConnection
108129
status: ConnectionStatus = ConnectionStatus.NO_AUTHORIZED_DEVICE;
109130
state: SimulatorState | undefined;
110131

132+
log: DataLog = initialDataLog();
133+
111134
private messageListener = (event: MessageEvent) => {
112135
const iframe = this.iframe();
113136
if (!iframe || event.source !== iframe.contentWindow || !event.data.kind) {
114137
// Not an event for us.
115138
return;
116139
}
117-
118140
switch (event.data.kind) {
119141
case "ready": {
120142
this.state = event.data.state;
@@ -150,6 +172,28 @@ export class SimulatorDeviceConnection
150172
}
151173
break;
152174
}
175+
case "log_output": {
176+
const entry: LogEntry = event.data;
177+
const result: DataLog = {
178+
headings: entry.headings ?? this.log.headings,
179+
data: this.log.data,
180+
};
181+
// The first row is all-time headings row so don't show the initial set.
182+
if (entry.headings && this.log.data.length > 0) {
183+
result.data.push({ isHeading: true, data: entry.headings });
184+
}
185+
if (entry.data) {
186+
result.data.push({ data: entry.data });
187+
}
188+
this.log = result;
189+
this.emit(EVENT_LOG_DATA, this.log);
190+
break;
191+
}
192+
case "log_delete": {
193+
this.log = initialDataLog();
194+
this.emit(EVENT_LOG_DATA, this.log);
195+
break;
196+
}
153197
case "serial_output": {
154198
const text = event.data.data;
155199
if (typeof text === "string") {

src/messages/ui.en.json

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1811,6 +1811,70 @@
18111811
"value": " module"
18121812
}
18131813
],
1814+
"simulator-data-logging-empty": [
1815+
{
1816+
"type": 0,
1817+
"value": "No log entries."
1818+
}
1819+
],
1820+
"simulator-data-logging-full": [
1821+
{
1822+
"type": 0,
1823+
"value": "Log full"
1824+
}
1825+
],
1826+
"simulator-data-logging-rows": [
1827+
{
1828+
"offset": 0,
1829+
"options": {
1830+
"1": {
1831+
"value": [
1832+
{
1833+
"type": 7
1834+
},
1835+
{
1836+
"type": 0,
1837+
"value": " row logged"
1838+
}
1839+
]
1840+
},
1841+
"=0": {
1842+
"value": [
1843+
{
1844+
"type": 0,
1845+
"value": "No rows logged"
1846+
}
1847+
]
1848+
},
1849+
"other": {
1850+
"value": [
1851+
{
1852+
"type": 7
1853+
},
1854+
{
1855+
"type": 0,
1856+
"value": " rows logged"
1857+
}
1858+
]
1859+
}
1860+
},
1861+
"pluralType": "cardinal",
1862+
"type": 6,
1863+
"value": "count"
1864+
}
1865+
],
1866+
"simulator-data-logging-save-log": [
1867+
{
1868+
"type": 0,
1869+
"value": "Save log"
1870+
}
1871+
],
1872+
"simulator-data-logging-truncated": [
1873+
{
1874+
"type": 0,
1875+
"value": "Older rows not shown"
1876+
}
1877+
],
18141878
"simulator-expand": [
18151879
{
18161880
"type": 0,
@@ -1867,6 +1931,12 @@
18671931
"value": "Light level"
18681932
}
18691933
],
1934+
"simulator-log": [
1935+
{
1936+
"type": 0,
1937+
"value": "Data log"
1938+
}
1939+
],
18701940
"simulator-loud": [
18711941
{
18721942
"type": 0,

src/messages/ui.fr.json

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1811,6 +1811,70 @@
18111811
"value": " module"
18121812
}
18131813
],
1814+
"simulator-data-logging-empty": [
1815+
{
1816+
"type": 0,
1817+
"value": "No log entries."
1818+
}
1819+
],
1820+
"simulator-data-logging-full": [
1821+
{
1822+
"type": 0,
1823+
"value": "Log full"
1824+
}
1825+
],
1826+
"simulator-data-logging-rows": [
1827+
{
1828+
"offset": 0,
1829+
"options": {
1830+
"1": {
1831+
"value": [
1832+
{
1833+
"type": 7
1834+
},
1835+
{
1836+
"type": 0,
1837+
"value": " row"
1838+
}
1839+
]
1840+
},
1841+
"=0": {
1842+
"value": [
1843+
{
1844+
"type": 0,
1845+
"value": "No rows"
1846+
}
1847+
]
1848+
},
1849+
"other": {
1850+
"value": [
1851+
{
1852+
"type": 7
1853+
},
1854+
{
1855+
"type": 0,
1856+
"value": " rows"
1857+
}
1858+
]
1859+
}
1860+
},
1861+
"pluralType": "cardinal",
1862+
"type": 6,
1863+
"value": "count"
1864+
}
1865+
],
1866+
"simulator-data-logging-save-log": [
1867+
{
1868+
"type": 0,
1869+
"value": "Save log"
1870+
}
1871+
],
1872+
"simulator-data-logging-truncated": [
1873+
{
1874+
"type": 0,
1875+
"value": "Older rows not shown"
1876+
}
1877+
],
18141878
"simulator-expand": [
18151879
{
18161880
"type": 0,
@@ -1867,6 +1931,12 @@
18671931
"value": "Light level"
18681932
}
18691933
],
1934+
"simulator-log": [
1935+
{
1936+
"type": 0,
1937+
"value": "Data log"
1938+
}
1939+
],
18701940
"simulator-loud": [
18711941
{
18721942
"type": 0,

0 commit comments

Comments
 (0)