Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions src/lib/device/http_system_time_config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { HTTPConfig } from "@device-ui/lib/device/http_config";
import { Formatter } from "@device-ui/lib/fmt/formatter";

// UNIX time configuration over HTTP.
export class HTTPSystemTimeConfig extends HTTPConfig {
// Initialize.
constructor(formatter: Formatter, url: string) {
super(formatter, url);
}

// Non-operational reset.
override async reset(): Promise<Error | null> {
return null;
}
}
43 changes: 43 additions & 0 deletions src/lib/fmt/field_formatter.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import { describe, test, expect } from "vitest";

import { FieldFormatter } from "@device-ui/lib/fmt/field_formatter";

describe("Field Formatter", () => {
test("Format empty data", () => {
const data = new TextEncoder().encode("");
const f = new FieldFormatter("timestamp");

const result = f.format(data);
expect(result.data).not.toBeNull();
expect(result.data).toEqual({ timestamp: "" });
expect(result.error).toBeNull();
});

test("Format text data", () => {
const data = new TextEncoder().encode("1733233869");
const f = new FieldFormatter("timestamp");

const result = f.format(data);
expect(result.data).not.toBeNull();
expect(result.data).toEqual({ timestamp: "1733233869" });
expect(result.error).toBeNull();
});

test("Format with different key name", () => {
const data = new TextEncoder().encode("OK");
const f = new FieldFormatter("status");

const result = f.format(data);
expect(result.data).toEqual({ status: "OK" });
expect(result.error).toBeNull();
});

test("Format binary data", () => {
const data = new Uint8Array([72, 101, 108, 108, 111]);
const f = new FieldFormatter("message");

const result = f.format(data);
expect(result.data).toEqual({ message: "Hello" });
expect(result.error).toBeNull();
});
});
24 changes: 24 additions & 0 deletions src/lib/fmt/field_formatter.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import { Formatter } from "@device-ui/lib/fmt/formatter";

// Format a single key-value pair.
export class FieldFormatter implements Formatter {
// Initialize.
constructor(private readonly key: string) {}

format(data: Uint8Array): {
data: Record<string, any> | null;
error: Error | null;
} {
let ret: Record<string, any> | null = null;
let err: Error | null = null;

try {
const text = new TextDecoder().decode(data);
ret = { [this.key]: text };
} catch (error) {
err = error instanceof Error ? error : new Error(String(error));
}

return { data: ret, error: err };
}
}
74 changes: 74 additions & 0 deletions src/ui/preact/system_status_component.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,10 @@ import { DataStore } from "@device-ui/lib/device/data_store";
import { TimeOps } from "@device-ui/lib/algo/time_ops";
import { ConnectionHandler } from "@device-ui/lib/device/connection_handler";
import { FanoutConnectionHandler } from "@device-ui/lib/device/fanout_connection_handler";
import { Notificator } from "@device-ui/lib/system/notificator";
import { Config } from "@device-ui/lib/device/config";

import { FormConfigComponent } from "@device-ui/ui/preact/form_config_component";

import "@device-ui/ui/preact/system_status_component.css";

Expand All @@ -17,6 +21,15 @@ export type SystemStatusComponentProps = {

// Connection handler to receive the device connection status.
connectionHandler: FanoutConnectionHandler;

// Notificator to send various notifications.
notificator: Notificator;

// Config to configure the mDNS.
mDNSConfig: Config;

// Config to configure the UNIX time.
systemTimeConfig: Config;
};

class TelemetryData {
Expand Down Expand Up @@ -45,6 +58,8 @@ class RegistrationData {
type SystemStatusComponentState = {
expanded: boolean;
connected: boolean;
enableConfiguration: boolean;
config: Config | null;
telemetry: TelemetryData | null;
registration: RegistrationData | null;
showCopied: boolean;
Expand Down Expand Up @@ -79,6 +94,8 @@ export class SystemStatusComponent
this.state = {
expanded: false,
connected: false,
enableConfiguration: false,
config: null,
telemetry: null,
registration: null,
showCopied: false,
Expand Down Expand Up @@ -137,6 +154,8 @@ export class SystemStatusComponent
this.setState({
expanded: false,
connected: false,
enableConfiguration: false,
config: null,
telemetry: null,
registration: null,
showCopied: false,
Expand Down Expand Up @@ -268,8 +287,38 @@ export class SystemStatusComponent
</>
)}
</div>
{/* Configuration mode */}
{this.state.enableConfiguration && (
<FormConfigComponent
config={this.state.config!}
onClose={this.handleConfigEnd}
notificator={this.props.notificator}
/>
)}
</div>
)}

{this.state.expanded && !this.state.enableConfiguration && (
<>
<div className="config-button-container">
<button
onClick={this.handleConfigBeginMdns}
className="config-button"
>
Configure mDNS
</button>
</div>

<div className="config-button-container">
<button
onClick={this.handleConfigBeginSystemTime}
className="config-button"
>
Configure System Time
</button>
</div>
</>
)}
</div>
);
}
Expand Down Expand Up @@ -313,6 +362,31 @@ export class SystemStatusComponent
});
};

private handleConfigBeginMdns = () => {
this.setState({
...this.state,
enableConfiguration: true,
config: this.props.mDNSConfig,
});
};

private handleConfigBeginSystemTime = () => {
this.setState({
...this.state,
enableConfiguration: true,
config: this.props.systemTimeConfig,
});
};

private handleConfigEnd = () => {
this.setState({
...this.state,
expanded: false,
enableConfiguration: false,
config: null,
});
};

private copyDeviceId = async (e: Event) => {
e.stopPropagation(); // Prevent card expansion/collapse

Expand Down
2 changes: 2 additions & 0 deletions vite.config.base.js
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,10 @@ export function createBaseConfig(deviceIP = "", projectConfig = {}) {
"/api/v1/config/sensor/analog": createProxyConfig(deviceIP),
"/api/v1/system/reboot": createProxyConfig(deviceIP),
"/api/v1/system/locate": createProxyConfig(deviceIP),
"/api/v1/system/time": createProxyConfig(deviceIP),
"/api/v1/config/wifi/sta": createProxyConfig(deviceIP),
"/api/v1/config/wifi/ap": createProxyConfig(deviceIP),
"/api/v1/config/mdns": createProxyConfig(deviceIP),
},
},
build: {
Expand Down