Skip to content

Commit 916bf7b

Browse files
User Preferences (#77)
* Initial implementation * Flashbar * Latency added * Change tresholds * Threshold adjust + fix * Refactoring * Resolution approach * Clean-up, un-used values * Enable user preferences for new features * Tweak menu label * Change icons * bump * update readme --------- Co-authored-by: MarkRoss-Eviden <[email protected]> Co-authored-by: Mark Ross <[email protected]>
1 parent 7c7ff29 commit 916bf7b

File tree

7 files changed

+255
-141
lines changed

7 files changed

+255
-141
lines changed

README.md

+9-16
Original file line numberDiff line numberDiff line change
@@ -18,32 +18,25 @@ Whether you're a casual racer or a DeepRacer developer, this custom console prov
1818

1919
## How to install on your car
2020

21-
### Option 1 - Using Debian Package
21+
### Using Debian Package
2222

2323
- Find the latest release - https://github.com/aws-deepracer-community/deepracer-custom-console/releases
2424
- SSH to your car
25-
- Run `curl -L -o deepracer-console-new.deb https://github.com/aws-deepracer-community/deepracer-custom-console/releases/download/v2.2.2/aws-deepracer-community-device-console_2.2.2.0_all.deb`
25+
- Run `curl -L -o deepracer-console-new.deb https://github.com/aws-deepracer-community/deepracer-custom-console/releases/download/v2.2.9/aws-deepracer-community-device-console_2.2.9.0_all.deb`
2626
- Run `sudo dpkg -i deepracer-console-new.deb`
27+
- Run `sudo systemctl restart deepracer-core.service` to restart the DeepRacer service
2728
- Open your browser and navigate to the IP address of the car and login using your password
2829

2930
If you should need to restore the original UI run:
3031
- `sudo apt remove aws-deepracer-community-device-console`
3132
- `sudo apt install aws-deepracer-device-console`
3233

33-
### Option 2 - Using scripts within this repo
34-
35-
- Find the latest release - https://github.com/aws-deepracer-community/deepracer-custom-console/releases
36-
- SSH to your car
37-
- Run `git clone https://github.com/aws-deepracer-community/deepracer-custom-console`
38-
- Run `cd deepracer-custom-console`
39-
- Run `curl -L -o deepracer-console-new.zip https://github.com/aws-deepracer-community/deepracer-custom-console/releases/download/v2.2.2/aws-deepracer-community-device-console-v2.2.2.zip` (or the latest tagged version you want to install) to download the zip package
40-
- Run `sudo ./deepracer-backup-console.sh` to take a backup of the original UI
41-
- Run `sudo ./deepracer-deploy-console.sh` to install the new Cloudscape UI
42-
- Run `sudo systemctl restart deepracer-core.service` to restart the DeepRacer service
43-
- Run `sudo systemctl restart nginx` to restart nginx
44-
- Open your browser and navigate to the IP address of the car and login using your password
45-
46-
If you should need to restore the original UI run `sudo ./deepracer-restore-console.sh`
34+
Note - some features also require the deepracer-custom-car code - https://github.com/aws-deepracer-community/deepracer-custom-car
35+
- Follow the instructions in that repo to install
36+
- If some features require the 'experimental' custom-car-code then update your car with the following config
37+
- Run `sudo vi /etc/apt/sources.list.d/aws_deepracer-community.list` and then comment out the first line and uncomment the third line
38+
- Run `sudo apt update && sudo apt upgrade`
39+
- Run `sudo systemctl restart deepracer-core.service` to restart the DeepRacer service
4740

4841
## Development Guide
4942

website/src/common/helpers/storage-helper.ts

+22
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ import { NavigationPanelState } from "../types";
44
const PREFIX = "deepracer";
55
const THEME_STORAGE_NAME = `${PREFIX}-theme`;
66
const NAVIGATION_PANEL_STATE_STORAGE_NAME = `${PREFIX}-navigation-panel-state`;
7+
const SPEED_ADJUSTMENT_KEY = `${PREFIX}-speed-adjustment`;
8+
const DEVICE_STATUS_KEY = `${PREFIX}-device-status`;
79

810
export abstract class StorageHelper {
911
static getTheme() {
@@ -50,4 +52,24 @@ export abstract class StorageHelper {
5052

5153
return newState;
5254
}
55+
56+
// Speed adjustment methods
57+
static getEnableSpeedAdjustment(): boolean {
58+
const savedValue = localStorage.getItem(SPEED_ADJUSTMENT_KEY);
59+
return savedValue ? JSON.parse(savedValue) : false;
60+
}
61+
62+
static setEnableSpeedAdjustment(value: boolean): void {
63+
localStorage.setItem(SPEED_ADJUSTMENT_KEY, JSON.stringify(value));
64+
}
65+
66+
// Device status methods
67+
static getEnableDeviceStatus(): boolean {
68+
const savedValue = localStorage.getItem(DEVICE_STATUS_KEY);
69+
return savedValue ? JSON.parse(savedValue) : false;
70+
}
71+
72+
static setEnableDeviceStatus(value: boolean): void {
73+
localStorage.setItem(DEVICE_STATUS_KEY, JSON.stringify(value));
74+
}
5375
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
import { createContext, useContext, useState, useCallback } from "react";
2+
import { StorageHelper } from "../helpers/storage-helper";
3+
4+
export interface Settings {
5+
enableSpeedAdjustment: boolean;
6+
enableDeviceStatus: boolean;
7+
}
8+
9+
interface PreferencesContextType {
10+
settings: Settings;
11+
setEnableSpeedAdjustment: (value: boolean) => void;
12+
setEnableDeviceStatus: (value: boolean) => void;
13+
}
14+
15+
export const PreferencesContext = createContext<PreferencesContextType | null>(null);
16+
17+
export const usePreferencesProvider = () => {
18+
const [settings, setSettings] = useState<Settings>({
19+
enableSpeedAdjustment: StorageHelper.getEnableSpeedAdjustment(),
20+
enableDeviceStatus: StorageHelper.getEnableDeviceStatus(),
21+
});
22+
23+
const setEnableSpeedAdjustment = useCallback((value: boolean) => {
24+
StorageHelper.setEnableSpeedAdjustment(value);
25+
setSettings((prev) => ({ ...prev, enableSpeedAdjustment: value }));
26+
}, []);
27+
28+
const setEnableDeviceStatus = useCallback((value: boolean) => {
29+
StorageHelper.setEnableDeviceStatus(value);
30+
setSettings((prev) => ({ ...prev, enableDeviceStatus: value }));
31+
}, []);
32+
33+
return {
34+
settings,
35+
setEnableSpeedAdjustment,
36+
setEnableDeviceStatus,
37+
};
38+
};
39+
40+
export const usePreferences = (): PreferencesContextType => {
41+
const context = useContext(PreferencesContext);
42+
if (!context) {
43+
throw new Error("usePreferences must be used within a PreferencesProvider");
44+
}
45+
return context;
46+
};

website/src/components/context-provider.tsx

+11-7
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import { NetworkContext, useNetworkProvider } from "../common/hooks/use-network"
44
import { SupportedApisContext, useSupportedApisProvider } from "../common/hooks/use-supported-apis";
55
import { ModelsContext, useModelsProvider } from "../common/hooks/use-models";
66
import { AuthContext, useAuthProvider } from "../common/hooks/use-authentication";
7+
import { PreferencesContext, usePreferencesProvider } from "../common/hooks/use-preferences";
78

89
// Main Context Provider Component
910
export const ContextProvider: React.FC<{
@@ -13,15 +14,18 @@ export const ContextProvider: React.FC<{
1314
const networkContextValue = useNetworkProvider();
1415
const supportedApisContextValue = useSupportedApisProvider();
1516
const modelsContextValue = useModelsProvider();
17+
const preferencesContextValue = usePreferencesProvider();
1618

1719
return (
18-
<BatteryContext.Provider value={batteryContextValue}>
19-
<NetworkContext.Provider value={networkContextValue}>
20-
<SupportedApisContext.Provider value={supportedApisContextValue}>
21-
<ModelsContext.Provider value={modelsContextValue}>{children}</ModelsContext.Provider>
22-
</SupportedApisContext.Provider>
23-
</NetworkContext.Provider>
24-
</BatteryContext.Provider>
20+
<SupportedApisContext.Provider value={supportedApisContextValue}>
21+
<PreferencesContext.Provider value={preferencesContextValue}>
22+
<BatteryContext.Provider value={batteryContextValue}>
23+
<NetworkContext.Provider value={networkContextValue}>
24+
<ModelsContext.Provider value={modelsContextValue}>{children}</ModelsContext.Provider>
25+
</NetworkContext.Provider>
26+
</BatteryContext.Provider>
27+
</PreferencesContext.Provider>
28+
</SupportedApisContext.Provider>
2529
);
2630
};
2731

website/src/components/global-header.tsx

+41
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,18 @@ import { TopNavigation } from "@cloudscape-design/components";
33
import { Mode } from "@cloudscape-design/global-styles";
44
import { StorageHelper } from "../common/helpers/storage-helper";
55
import { APP_NAME } from "../common/constants";
6+
import { useSupportedApis } from "../common/hooks/use-supported-apis";
7+
import { usePreferences } from "../common/hooks/use-preferences";
68

79
export default function GlobalHeader() {
810
const [theme, setTheme] = useState<Mode>(StorageHelper.getTheme());
911

12+
// Get API support information
13+
const { isDeviceStatusSupported } = useSupportedApis();
14+
15+
// Use settings context instead of local state
16+
const { settings, setEnableSpeedAdjustment, setEnableDeviceStatus } = usePreferences();
17+
1018
const onChangeThemeClick = () => {
1119
if (theme === Mode.Dark) {
1220
setTheme(StorageHelper.applyTheme(Mode.Light));
@@ -15,13 +23,24 @@ export default function GlobalHeader() {
1523
}
1624
};
1725

26+
// Helper function to toggle settings
27+
const toggleSetting = (id: string) => {
28+
if (id === "speed-adjustment") {
29+
setEnableSpeedAdjustment(!settings.enableSpeedAdjustment);
30+
} else if (id === "device-status" && isDeviceStatusSupported) {
31+
// Only allow toggle if supported
32+
setEnableDeviceStatus(!settings.enableDeviceStatus);
33+
}
34+
};
35+
1836
return (
1937
<div
2038
style={{ zIndex: 1002, top: 0, left: 0, right: 0, position: "fixed" }}
2139
id="awsui-top-navigation"
2240
>
2341
<TopNavigation
2442
identity={{
43+
title: "AWS DeepRacer",
2544
href: "/",
2645
logo: { src: "/static/images/deepracer.png", alt: `${APP_NAME} Logo` },
2746
}}
@@ -31,6 +50,28 @@ export default function GlobalHeader() {
3150
text: theme === Mode.Dark ? "Light Mode" : "Dark Mode",
3251
onClick: onChangeThemeClick,
3352
},
53+
{
54+
type: "menu-dropdown",
55+
iconName: "settings",
56+
items: [
57+
{
58+
id: "speed-adjustment",
59+
text:
60+
(settings.enableSpeedAdjustment ? "Disable " : "Enable ") + "5x Speed Adjustment",
61+
iconName: "angle-right-double",
62+
},
63+
{
64+
id: "device-status",
65+
text: (settings.enableDeviceStatus ? "Disable " : "Enable ") + "Car Health Monitoring",
66+
iconName: "heart",
67+
disabled: !isDeviceStatusSupported,
68+
description: !isDeviceStatusSupported ? "Not supported on this device" : undefined,
69+
},
70+
],
71+
onItemClick: (event) => {
72+
toggleSetting(event.detail.id);
73+
},
74+
},
3475
]}
3576
/>
3677
</div>

0 commit comments

Comments
 (0)