mirror of
https://github.com/Hypfer/Valetudo.git
synced 2025-10-26 11:27:27 +00:00
parent
dceea16f5a
commit
bd5fa9c1d1
@ -23,24 +23,48 @@ class NetworkAdvertisementManager {
|
||||
this.networkStateCheckTimeout = undefined;
|
||||
this.ipAddresses = "";
|
||||
|
||||
this.config.onUpdate((key) => {
|
||||
if (key === "networkAdvertisement") {
|
||||
this.restart().catch((err) => {
|
||||
Logger.warn("Error while restarting NetworkAdvertisementManager due to config change", err);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
this.setUp();
|
||||
}
|
||||
|
||||
/**
|
||||
* @public
|
||||
* @return {{port: number, zeroconfHostname: string}}
|
||||
*/
|
||||
getProperties() {
|
||||
return {
|
||||
port: this.webserverPort,
|
||||
zeroconfHostname: Tools.GET_ZEROCONF_HOSTNAME()
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
setUp() {
|
||||
const networkAdvertisementConfig = this.config.get("networkAdvertisement");
|
||||
|
||||
if (networkAdvertisementConfig.enabled === true && this.config.get("embedded") === true) {
|
||||
this.setUpSSDP();
|
||||
this.setUpBonjour();
|
||||
if (this.config.get("embedded") === true) {
|
||||
if (networkAdvertisementConfig.enabled === true) {
|
||||
this.setUpSSDP();
|
||||
this.setUpBonjour();
|
||||
|
||||
this.ipAddresses = Tools.GET_CURRENT_HOST_IP_ADDRESSES().sort().join();
|
||||
this.networkStateCheckTimeout = setTimeout(() => {
|
||||
this.checkNetworkStateAndReschedule();
|
||||
}, NETWORK_STATE_CHECK_INTERVAL);
|
||||
this.ipAddresses = Tools.GET_CURRENT_HOST_IP_ADDRESSES().sort().join();
|
||||
this.networkStateCheckTimeout = setTimeout(() => {
|
||||
this.checkNetworkStateAndReschedule();
|
||||
}, NETWORK_STATE_CHECK_INTERVAL);
|
||||
}
|
||||
} else {
|
||||
Logger.info("Not starting NetworkAdvertisementManager because we're not in embedded mode");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@ -73,10 +73,16 @@ class Valetudo {
|
||||
robot: this.robot
|
||||
});
|
||||
|
||||
this.networkAdvertisementManager = new NetworkAdvertisementManager({
|
||||
config: this.config,
|
||||
robot: this.robot
|
||||
});
|
||||
|
||||
this.webserver = new Webserver({
|
||||
config: this.config,
|
||||
robot: this.robot,
|
||||
mqttController: this.mqttController,
|
||||
networkAdvertisementManager: this.networkAdvertisementManager,
|
||||
ntpClient: this.ntpClient,
|
||||
updater: this.updater,
|
||||
valetudoEventStore: this.valetudoEventStore
|
||||
@ -89,10 +95,6 @@ class Valetudo {
|
||||
ntpClient: this.ntpClient
|
||||
});
|
||||
|
||||
this.networkAdvertisementManager = new NetworkAdvertisementManager({
|
||||
config: this.config,
|
||||
robot: this.robot
|
||||
});
|
||||
|
||||
this.setupDebuggingFeatures();
|
||||
this.setupMemoryManagement();
|
||||
|
||||
@ -31,7 +31,7 @@ class NTPClientRouter {
|
||||
this.router.put("/config", this.validator, (req, res) => {
|
||||
this.config.set("ntpClient", req.body);
|
||||
|
||||
res.sendStatus(202);
|
||||
res.sendStatus(200);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
52
backend/lib/webserver/NetworkAdvertisementManagerRouter.js
Normal file
52
backend/lib/webserver/NetworkAdvertisementManagerRouter.js
Normal file
@ -0,0 +1,52 @@
|
||||
const express = require("express");
|
||||
|
||||
|
||||
class NetworkAdvertisementManagerRouter {
|
||||
/**
|
||||
*
|
||||
* @param {object} options
|
||||
* @param {import("../NetworkAdvertisementManager")} options.networkAdvertisementManager
|
||||
* @param {import("../Configuration")} options.config
|
||||
* @param {*} options.validator
|
||||
*/
|
||||
constructor(options) {
|
||||
this.router = express.Router({mergeParams: true});
|
||||
this.networkAdvertisementManager = options.networkAdvertisementManager;
|
||||
this.config = options.config;
|
||||
this.validator = options.validator;
|
||||
|
||||
this.initRoutes();
|
||||
}
|
||||
|
||||
|
||||
initRoutes() {
|
||||
this.router.get("/config", (req, res) => {
|
||||
res.json(this.config.get("networkAdvertisement"));
|
||||
});
|
||||
|
||||
this.router.put("/config", (req, res) => {
|
||||
if (
|
||||
req.body && typeof req.body === "object" &&
|
||||
typeof req.body.enabled === "boolean"
|
||||
) {
|
||||
const conf = this.config.get("networkAdvertisement");
|
||||
this.config.set("networkAdvertisement", Object.assign({}, conf, {enabled: req.body.enabled}));
|
||||
|
||||
res.sendStatus(200);
|
||||
} else {
|
||||
res.status(400).send("bad request body");
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
this.router.get("/properties", (req, res) => {
|
||||
res.json(this.networkAdvertisementManager.getProperties());
|
||||
});
|
||||
}
|
||||
|
||||
getRouter() {
|
||||
return this.router;
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = NetworkAdvertisementManagerRouter;
|
||||
@ -83,7 +83,7 @@ class TimerRouter {
|
||||
storedTimers[newTimer.id] = newTimer;
|
||||
|
||||
this.config.set("timers", storedTimers);
|
||||
res.sendStatus(201);
|
||||
res.sendStatus(200);
|
||||
} else {
|
||||
res.sendStatus(400);
|
||||
}
|
||||
|
||||
@ -62,7 +62,7 @@ class ValetudoRouter {
|
||||
if (req.body && req.body.level && typeof req.body.level === "string") {
|
||||
Logger.setLogLevel(req.body.level);
|
||||
|
||||
res.sendStatus(202);
|
||||
res.sendStatus(200);
|
||||
} else {
|
||||
res.sendStatus(400);
|
||||
}
|
||||
@ -94,7 +94,7 @@ class ValetudoRouter {
|
||||
|
||||
this.config.set("mqtt", mqttConfig);
|
||||
|
||||
res.sendStatus(202);
|
||||
res.sendStatus(200);
|
||||
});
|
||||
|
||||
this.router.get("/config/interfaces/http/auth/basic", (req, res) => {
|
||||
@ -123,7 +123,7 @@ class ValetudoRouter {
|
||||
webserverConfig.basicAuth = options;
|
||||
|
||||
this.config.set("webserver", webserverConfig);
|
||||
res.sendStatus(201);
|
||||
res.sendStatus(200);
|
||||
}
|
||||
} else {
|
||||
res.status(400).send("bad request body");
|
||||
|
||||
@ -22,6 +22,7 @@ const ValetudoRouter = require("./ValetudoRouter");
|
||||
const fs = require("fs");
|
||||
const MiioValetudoRobot = require("../robots/MiioValetudoRobot");
|
||||
const MQTTRouter = require("./MQTTRouter");
|
||||
const NetworkAdvertisementManagerRouter = require("./NetworkAdvertisementManagerRouter");
|
||||
const NTPClientRouter = require("./NTPClientRouter");
|
||||
const SSDPRouter = require("./SSDPRouter");
|
||||
const SystemRouter = require("./SystemRouter");
|
||||
@ -35,6 +36,7 @@ class WebServer {
|
||||
* @param {object} options
|
||||
* @param {import("../core/ValetudoRobot")} options.robot
|
||||
* @param {import("../mqtt/MqttController")} options.mqttController
|
||||
* @param {import("../NetworkAdvertisementManager")} options.networkAdvertisementManager
|
||||
* @param {import("../NTPClient")} options.ntpClient
|
||||
* @param {import("../updater/Updater")} options.updater
|
||||
* @param {import("../ValetudoEventStore")} options.valetudoEventStore
|
||||
@ -116,6 +118,8 @@ class WebServer {
|
||||
|
||||
this.app.use("/api/v2/mqtt/", new MQTTRouter({config: this.config, mqttController: options.mqttController, validator: this.validator}).getRouter());
|
||||
|
||||
this.app.use("/api/v2/networkadvertisement/", new NetworkAdvertisementManagerRouter({config: this.config, networkAdvertisementManager: options.networkAdvertisementManager, validator: this.validator}).getRouter());
|
||||
|
||||
this.app.use("/api/v2/ntpclient/", new NTPClientRouter({config: this.config, ntpClient: options.ntpClient, validator: this.validator}).getRouter());
|
||||
|
||||
this.app.use("/api/v2/timers/", new TimerRouter({config: this.config, robot: this.robot, validator: this.validator}).getRouter());
|
||||
|
||||
@ -92,7 +92,7 @@ class GoToLocationCapabilityRouter extends CapabilityRouter {
|
||||
goToLocationPresets[newPreset.id] = newPreset;
|
||||
|
||||
this.capability.robot.config.set("goToLocationPresets", goToLocationPresets);
|
||||
res.sendStatus(201);
|
||||
res.sendStatus(200);
|
||||
} catch (e) {
|
||||
Logger.warn("Error while saving new goToLocationPreset", req.body);
|
||||
res.status(500).json(e.message);
|
||||
@ -144,7 +144,7 @@ class GoToLocationCapabilityRouter extends CapabilityRouter {
|
||||
|
||||
|
||||
this.capability.robot.config.set("goToLocationPresets", presets);
|
||||
res.sendStatus(201);
|
||||
res.sendStatus(200);
|
||||
} else {
|
||||
res.sendStatus(400);
|
||||
}
|
||||
|
||||
@ -71,7 +71,7 @@ class ZoneCleaningCapabilityRouter extends CapabilityRouter {
|
||||
zoneSettings[newPreset.id] = newPreset;
|
||||
|
||||
this.capability.robot.config.set("zonePresets", zoneSettings);
|
||||
res.sendStatus(201);
|
||||
res.sendStatus(200);
|
||||
} catch (e) {
|
||||
Logger.warn("Error while saving new zone", req.body);
|
||||
res.status(500).json(e.message);
|
||||
@ -149,7 +149,7 @@ class ZoneCleaningCapabilityRouter extends CapabilityRouter {
|
||||
|
||||
|
||||
this.capability.robot.config.set("zonePresets", zonePresets);
|
||||
res.sendStatus(201);
|
||||
res.sendStatus(200);
|
||||
} else {
|
||||
res.sendStatus(400);
|
||||
}
|
||||
|
||||
@ -169,8 +169,8 @@
|
||||
}
|
||||
},
|
||||
"responses": {
|
||||
"201": {
|
||||
"$ref": "#/components/responses/201"
|
||||
"200": {
|
||||
"$ref": "#/components/responses/200"
|
||||
},
|
||||
"400": {
|
||||
"$ref": "#/components/responses/400"
|
||||
|
||||
@ -66,8 +66,8 @@
|
||||
}
|
||||
},
|
||||
"responses": {
|
||||
"202": {
|
||||
"$ref": "#/components/responses/202"
|
||||
"200": {
|
||||
"$ref": "#/components/responses/200"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -0,0 +1,71 @@
|
||||
{
|
||||
"/api/v2/networkadvertisement/config": {
|
||||
"get": {
|
||||
"tags": [
|
||||
"NetworkAdvertisement"
|
||||
],
|
||||
"summary": "Get NetworkAdvertisementManager configuration",
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "Ok",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/NetworkAdvertisementConfigDTO"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"put": {
|
||||
"tags": [
|
||||
"NetworkAdvertisement"
|
||||
],
|
||||
"summary": "Update NetworkAdvertisementManager configuration",
|
||||
"requestBody": {
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/NetworkAdvertisementConfigDTO"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"responses": {
|
||||
"200": {
|
||||
"$ref": "#/components/responses/200"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/api/v2/networkadvertisement/properties": {
|
||||
"get": {
|
||||
"tags": [
|
||||
"NetworkAdvertisement"
|
||||
],
|
||||
"summary": "Get NetworkAdvertisement properties",
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "Ok",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
"port": {
|
||||
"type": "number"
|
||||
},
|
||||
"zeroconfHostname": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -99,8 +99,8 @@
|
||||
}
|
||||
},
|
||||
"responses": {
|
||||
"201": {
|
||||
"$ref": "#/components/responses/201"
|
||||
"200": {
|
||||
"$ref": "#/components/responses/200"
|
||||
},
|
||||
"400": {
|
||||
"$ref": "#/components/responses/400"
|
||||
@ -192,8 +192,8 @@
|
||||
}
|
||||
},
|
||||
"responses": {
|
||||
"201": {
|
||||
"$ref": "#/components/responses/201"
|
||||
"200": {
|
||||
"$ref": "#/components/responses/200"
|
||||
},
|
||||
"400": {
|
||||
"$ref": "#/components/responses/400"
|
||||
|
||||
@ -152,8 +152,8 @@
|
||||
},
|
||||
"description": "Log level retrieved from GET presets",
|
||||
"responses": {
|
||||
"202": {
|
||||
"$ref": "#/components/responses/202"
|
||||
"200": {
|
||||
"$ref": "#/components/responses/200"
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -192,8 +192,8 @@
|
||||
}
|
||||
},
|
||||
"responses": {
|
||||
"202": {
|
||||
"$ref": "#/components/responses/202"
|
||||
"200": {
|
||||
"$ref": "#/components/responses/200"
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -232,8 +232,8 @@
|
||||
}
|
||||
},
|
||||
"responses": {
|
||||
"201": {
|
||||
"$ref": "#/components/responses/201"
|
||||
"200": {
|
||||
"$ref": "#/components/responses/200"
|
||||
},
|
||||
"400": {
|
||||
"$ref": "#/components/responses/400"
|
||||
|
||||
@ -21,6 +21,8 @@ import {
|
||||
MQTTConfiguration,
|
||||
MQTTProperties,
|
||||
MQTTStatus,
|
||||
NetworkAdvertisementConfiguration,
|
||||
NetworkAdvertisementProperties,
|
||||
NTPClientConfiguration,
|
||||
NTPClientState,
|
||||
Point,
|
||||
@ -447,7 +449,7 @@ export const sendValetudoLogLevel = async (logLevel: SetLogLevelRequest): Promis
|
||||
await valetudoAPI
|
||||
.put("/valetudo/log/level", logLevel)
|
||||
.then(({ status }) => {
|
||||
if (status !== 202) {
|
||||
if (status !== 200) {
|
||||
throw new Error("Could not set new log level");
|
||||
}
|
||||
});
|
||||
@ -481,7 +483,7 @@ export const sendMQTTConfiguration = async (mqttConfiguration: MQTTConfiguration
|
||||
return valetudoAPI
|
||||
.put("/valetudo/config/interfaces/mqtt", mqttConfiguration)
|
||||
.then(({status}) => {
|
||||
if (status !== 202) {
|
||||
if (status !== 200) {
|
||||
throw new Error("Could not update MQTT configuration");
|
||||
}
|
||||
});
|
||||
@ -515,12 +517,38 @@ export const sendHTTPBasicAuthConfiguration = async (configuration: HTTPBasicAut
|
||||
return valetudoAPI
|
||||
.put("/valetudo/config/interfaces/http/auth/basic", configuration)
|
||||
.then(({status}) => {
|
||||
if (status !== 201) {
|
||||
if (status !== 200) {
|
||||
throw new Error("Could not update HTTP basic auth configuration");
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
export const fetchNetworkAdvertisementConfiguration = async (): Promise<NetworkAdvertisementConfiguration> => {
|
||||
return valetudoAPI
|
||||
.get<NetworkAdvertisementConfiguration>("/networkadvertisement/config")
|
||||
.then(({data}) => {
|
||||
return data;
|
||||
});
|
||||
};
|
||||
|
||||
export const sendNetworkAdvertisementConfiguration = async (configuration: NetworkAdvertisementConfiguration): Promise<void> => {
|
||||
return valetudoAPI
|
||||
.put("/networkadvertisement/config", configuration)
|
||||
.then(({status}) => {
|
||||
if (status !== 200) {
|
||||
throw new Error("Could not update NetworkAdvertisement configuration");
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
export const fetchNetworkAdvertisementProperties = async (): Promise<NetworkAdvertisementProperties> => {
|
||||
return valetudoAPI
|
||||
.get<NetworkAdvertisementProperties>("/networkadvertisement/properties")
|
||||
.then(({data}) => {
|
||||
return data;
|
||||
});
|
||||
};
|
||||
|
||||
export const fetchNTPClientState = async (): Promise<NTPClientState> => {
|
||||
return valetudoAPI
|
||||
.get<NTPClientState>("/ntpclient/state")
|
||||
@ -541,7 +569,7 @@ export const sendNTPClientConfiguration = async (configuration: NTPClientConfigu
|
||||
return valetudoAPI
|
||||
.put("/ntpclient/config", configuration)
|
||||
.then(({status}) => {
|
||||
if (status !== 202) {
|
||||
if (status !== 200) {
|
||||
throw new Error("Could not update NTP client configuration");
|
||||
}
|
||||
});
|
||||
@ -559,7 +587,7 @@ export const deleteTimer = async (id: string): Promise<void> => {
|
||||
|
||||
export const sendTimerCreation = async (timerData: Timer): Promise<void> => {
|
||||
await valetudoAPI.post("/timers", timerData).then(({ status }) => {
|
||||
if (status !== 201) {
|
||||
if (status !== 200) {
|
||||
throw new Error("Could not create timer");
|
||||
}
|
||||
});
|
||||
|
||||
@ -93,6 +93,9 @@ import {
|
||||
sendSetQuirkValueCommand,
|
||||
fetchRobotProperties,
|
||||
fetchMQTTStatus,
|
||||
fetchNetworkAdvertisementConfiguration,
|
||||
fetchNetworkAdvertisementProperties,
|
||||
sendNetworkAdvertisementConfiguration,
|
||||
} from "./client";
|
||||
import {
|
||||
PresetSelectionState,
|
||||
@ -113,6 +116,7 @@ import {
|
||||
MapSegmentEditSplitRequestParameters,
|
||||
MapSegmentRenameRequestParameters,
|
||||
MQTTConfiguration,
|
||||
NetworkAdvertisementConfiguration,
|
||||
NTPClientConfiguration,
|
||||
NTPClientState,
|
||||
Point,
|
||||
@ -148,6 +152,8 @@ enum CacheKey {
|
||||
MQTTStatus = "mqtt_status",
|
||||
MQTTProperties = "mqtt_properties",
|
||||
HTTPBasicAuth = "http_basic_auth",
|
||||
NetworkAdvertisementConfiguration = "network_advertisement_configuration",
|
||||
NetworkAdvertisementProperties = "network_advertisement_properties",
|
||||
NTPClientState = "ntp_client_state",
|
||||
NTPClientConfiguration = "ntp_client_configuration",
|
||||
Timers = "timers",
|
||||
@ -678,6 +684,28 @@ export const useHTTPBasicAuthConfigurationMutation = () => {
|
||||
);
|
||||
};
|
||||
|
||||
export const useNetworkAdvertisementConfigurationQuery = () => {
|
||||
return useQuery(CacheKey.NetworkAdvertisementConfiguration, fetchNetworkAdvertisementConfiguration, {
|
||||
staleTime: Infinity,
|
||||
});
|
||||
};
|
||||
|
||||
export const useNetworkAdvertisementConfigurationMutation = () => {
|
||||
return useValetudoFetchingMutation(
|
||||
useOnSettingsChangeError("Network Advertisement"),
|
||||
CacheKey.NetworkAdvertisementConfiguration,
|
||||
(networkAdvertisementConfiguration: NetworkAdvertisementConfiguration) => {
|
||||
return sendNetworkAdvertisementConfiguration(networkAdvertisementConfiguration).then(fetchNetworkAdvertisementConfiguration);
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
export const useNetworkAdvertisementPropertiesQuery = () => {
|
||||
return useQuery(CacheKey.NetworkAdvertisementProperties, fetchNetworkAdvertisementProperties, {
|
||||
staleTime: Infinity,
|
||||
});
|
||||
};
|
||||
|
||||
export const useNTPClientStateQuery = () => {
|
||||
return useQuery(CacheKey.NTPClientState, fetchNTPClientState, {
|
||||
staleTime: 5_000,
|
||||
|
||||
@ -263,6 +263,15 @@ export interface HTTPBasicAuthConfiguration {
|
||||
password: string;
|
||||
}
|
||||
|
||||
export interface NetworkAdvertisementConfiguration {
|
||||
enabled: boolean;
|
||||
}
|
||||
|
||||
export interface NetworkAdvertisementProperties {
|
||||
port: number;
|
||||
zeroconfHostname: string;
|
||||
}
|
||||
|
||||
export interface NTPClientState {
|
||||
__class: "ValetudoNTPClientDisabledState" | "ValetudoNTPClientEnabledState" | "ValetudoNTPClientErrorState" | "ValetudoNTPClientSyncedState";
|
||||
timestamp: string;
|
||||
|
||||
@ -171,6 +171,12 @@ const menuTree: Array<MenuEntry | MenuSubEntry | MenuSubheader> = [
|
||||
title: "MQTT Connectivity",
|
||||
parentRoute: "/settings/connectivity"
|
||||
},
|
||||
{
|
||||
kind: "MenuSubEntry",
|
||||
routeMatch: "/settings/connectivity/networkadvertisement",
|
||||
title: "Network Advertisement",
|
||||
parentRoute: "/settings/connectivity"
|
||||
},
|
||||
{
|
||||
kind: "MenuSubEntry",
|
||||
routeMatch: "/settings/connectivity/ntp",
|
||||
|
||||
@ -9,6 +9,7 @@ import Connectivity from "./connectivity/Connectivity";
|
||||
import NTPConnectivity from "./connectivity/NTPConnectivity";
|
||||
import AuthSettings from "./connectivity/AuthSettings";
|
||||
import WifiConnectivity from "./connectivity/WifiConnectivity";
|
||||
import NetworkAdvertisementSettings from "./connectivity/NetworkAdvertisementSettings";
|
||||
|
||||
const SettingsRouter = (): JSX.Element => {
|
||||
const {path} = useRouteMatch();
|
||||
@ -61,6 +62,9 @@ const SettingsRouter = (): JSX.Element => {
|
||||
<Route exact path={path + "/connectivity/mqtt"}>
|
||||
<MQTTConnectivity/>
|
||||
</Route>
|
||||
<Route exact path={path + "/connectivity/networkadvertisement"}>
|
||||
<NetworkAdvertisementSettings/>
|
||||
</Route>
|
||||
<Route exact path={path + "/connectivity/ntp"}>
|
||||
<NTPConnectivity/>
|
||||
</Route>
|
||||
|
||||
@ -6,7 +6,8 @@ import {MQTTIcon} from "../../components/CustomIcons";
|
||||
import {
|
||||
AccessTime as NTPIcon,
|
||||
VpnKey as AuthIcon,
|
||||
Wifi as WifiIcon
|
||||
Wifi as WifiIcon,
|
||||
AutoFixHigh as NetworkAdvertisementIcon
|
||||
} from "@mui/icons-material";
|
||||
import {ListMenu} from "../../components/list_menu/ListMenu";
|
||||
import {SpacerListMenuItem} from "../../components/list_menu/SpacerListMenuItem";
|
||||
@ -50,11 +51,21 @@ const Connectivity = (): JSX.Element => {
|
||||
key="ntpConnectivity"
|
||||
url="/settings/connectivity/ntp"
|
||||
primaryLabel="NTP Connectivity"
|
||||
secondaryLabel="Configure Valetudos integrated Network Time Protocol (NTP) client"
|
||||
secondaryLabel="Configure the integrated Network Time Protocol (NTP) client"
|
||||
icon={<NTPIcon/>}
|
||||
/>
|
||||
);
|
||||
|
||||
items.push(
|
||||
<LinkListMenuItem
|
||||
key="networkAdvertisementSettings"
|
||||
url="/settings/connectivity/networkadvertisement"
|
||||
primaryLabel="Network Advertisement"
|
||||
secondaryLabel="Control Bonjour/mDNS and SSDP/UPnP discoverability"
|
||||
icon={<NetworkAdvertisementIcon/>}
|
||||
/>
|
||||
);
|
||||
|
||||
items.push(
|
||||
<LinkListMenuItem
|
||||
key="authSettings"
|
||||
|
||||
@ -0,0 +1,146 @@
|
||||
import {
|
||||
Box,
|
||||
Checkbox,
|
||||
Divider,
|
||||
FormControlLabel,
|
||||
Grid,
|
||||
TextField,
|
||||
Typography
|
||||
} from "@mui/material";
|
||||
import React from "react";
|
||||
import {
|
||||
useNetworkAdvertisementConfigurationMutation,
|
||||
useNetworkAdvertisementConfigurationQuery,
|
||||
useNetworkAdvertisementPropertiesQuery
|
||||
} from "../../api";
|
||||
import LoadingFade from "../../components/LoadingFade";
|
||||
import {LoadingButton} from "@mui/lab";
|
||||
import InfoBox from "../../components/InfoBox";
|
||||
import PaperContainer from "../../components/PaperContainer";
|
||||
import {
|
||||
AutoFixHigh as NetworkAdvertisementIcon
|
||||
} from "@mui/icons-material";
|
||||
|
||||
const NetworkAdvertisementSettings = (): JSX.Element => {
|
||||
const {
|
||||
data: storedConfiguration,
|
||||
isLoading: configurationLoading,
|
||||
isError: configurationError,
|
||||
} = useNetworkAdvertisementConfigurationQuery();
|
||||
|
||||
const {
|
||||
data: properties,
|
||||
isLoading: propertiesLoading,
|
||||
isError: propertiesLoadError
|
||||
} = useNetworkAdvertisementPropertiesQuery();
|
||||
|
||||
const {mutate: updateConfiguration, isLoading: configurationUpdating} = useNetworkAdvertisementConfigurationMutation();
|
||||
|
||||
const [enabled, setEnabled] = React.useState(false);
|
||||
|
||||
const [configurationModified, setConfigurationModified] = React.useState<boolean>(false);
|
||||
|
||||
|
||||
React.useEffect(() => {
|
||||
if (storedConfiguration) {
|
||||
setEnabled(storedConfiguration.enabled);
|
||||
}
|
||||
}, [storedConfiguration]);
|
||||
|
||||
if (configurationLoading || propertiesLoading) {
|
||||
return (
|
||||
<LoadingFade/>
|
||||
);
|
||||
}
|
||||
|
||||
if (configurationError || propertiesLoadError || !storedConfiguration) {
|
||||
return <Typography color="error">Error loading Network Advertisement configuration</Typography>;
|
||||
}
|
||||
|
||||
return (
|
||||
<PaperContainer>
|
||||
<Grid container direction="row">
|
||||
<Box style={{width: "100%"}}>
|
||||
<Grid item container alignItems="center" spacing={1} justifyContent="space-between">
|
||||
<Grid item style={{display:"flex"}}>
|
||||
<Grid item style={{paddingRight: "8px"}}>
|
||||
<NetworkAdvertisementIcon/>
|
||||
</Grid>
|
||||
<Grid item>
|
||||
<Typography>Network Advertisement</Typography>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</Grid>
|
||||
<Divider sx={{mt: 1}}/>
|
||||
|
||||
<FormControlLabel
|
||||
control={
|
||||
<Checkbox
|
||||
checked={enabled}
|
||||
onChange={e => {
|
||||
setEnabled(e.target.checked);
|
||||
setConfigurationModified(true);
|
||||
}}
|
||||
/>
|
||||
}
|
||||
label="Network Advertisement enabled"
|
||||
sx={{mb: 1}}
|
||||
/>
|
||||
<Grid container spacing={1} sx={{mb: 1, mt: "1rem"}} direction="row">
|
||||
<Grid item xs="auto" style={{flexGrow: 1}}>
|
||||
<TextField
|
||||
style={{width: "100%"}}
|
||||
label="Zeroconf Hostname"
|
||||
value={properties?.zeroconfHostname ?? ""}
|
||||
variant="standard"
|
||||
disabled={true}
|
||||
InputProps={{
|
||||
readOnly: true,
|
||||
}}
|
||||
/>
|
||||
</Grid>
|
||||
</Grid>
|
||||
|
||||
<InfoBox
|
||||
boxShadow={5}
|
||||
style={{
|
||||
marginTop: "3rem",
|
||||
marginBottom: "2rem"
|
||||
}}
|
||||
>
|
||||
<Typography color="info">
|
||||
When running Valetudo in embedded mode, it will advertise its presence on your local network
|
||||
via both Bonjour/mDNS and SSDP/UPnP to enable other software such as the android companion app
|
||||
or the windows explorer to discover it.
|
||||
<br/><br/>
|
||||
Please note that disabling this feature <em>will break</em> the companion app as well as other
|
||||
things that may be able to auto-discover Valetudo instances on your network.
|
||||
</Typography>
|
||||
</InfoBox>
|
||||
|
||||
<Divider sx={{mt: 1}} style={{marginBottom: "1rem"}}/>
|
||||
<Grid container>
|
||||
<Grid item style={{marginLeft: "auto"}}>
|
||||
<LoadingButton
|
||||
loading={configurationUpdating}
|
||||
color="primary"
|
||||
variant="outlined"
|
||||
disabled={!configurationModified}
|
||||
onClick={() => {
|
||||
updateConfiguration({
|
||||
enabled
|
||||
});
|
||||
setConfigurationModified(false);
|
||||
}}
|
||||
>
|
||||
Save configuration
|
||||
</LoadingButton>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</Box>
|
||||
</Grid>
|
||||
</PaperContainer>
|
||||
);
|
||||
};
|
||||
|
||||
export default NetworkAdvertisementSettings;
|
||||
@ -25,6 +25,7 @@ const options = {
|
||||
{name: "Robot", description: "Robot API"},
|
||||
{name: "System", description: "System API"},
|
||||
{name: "MQTT", description: "MQTT Controller API"},
|
||||
{name: "NetworkAdvertisement", description: "Network Advertisement Manager API"},
|
||||
{name: "NTP", description: "NTP Client API"},
|
||||
{name: "Timers", description: "Timers API"},
|
||||
{name: "Updater", description: "Update Valetudo using Valetudo"},
|
||||
|
||||
Loading…
Reference in New Issue
Block a user