From c0f7bc4741a25e9bb2369ddf929cb7ccc62db763 Mon Sep 17 00:00:00 2001 From: Sacha Weatherstone Date: Sun, 8 Jan 2023 19:27:04 +1000 Subject: [PATCH] Add audio config --- .../PageComponents/ModuleConfig/Audio.tsx | 122 ++++++++++++++++++ src/pages/Config/ModuleConfig.tsx | 5 + src/validation/moduleConfig/audio.ts | 26 ++++ 3 files changed, 153 insertions(+) create mode 100644 src/components/PageComponents/ModuleConfig/Audio.tsx create mode 100644 src/validation/moduleConfig/audio.ts diff --git a/src/components/PageComponents/ModuleConfig/Audio.tsx b/src/components/PageComponents/ModuleConfig/Audio.tsx new file mode 100644 index 00000000..16d06285 --- /dev/null +++ b/src/components/PageComponents/ModuleConfig/Audio.tsx @@ -0,0 +1,122 @@ +import type React from "react"; +import { useEffect } from "react"; + +import { Controller, useForm } from "react-hook-form"; +import { toast } from "react-hot-toast"; + +import { Input } from "@app/components/form/Input.js"; +import { Select } from "@app/components/form/Select.js"; +import { Toggle } from "@app/components/form/Toggle.js"; +import { AudioValidation } from "@app/validation/moduleConfig/audio.js"; +import { Form } from "@components/form/Form"; +import { useDevice } from "@core/providers/useDevice.js"; +import { renderOptions } from "@core/utils/selectEnumOptions.js"; +import { classValidatorResolver } from "@hookform/resolvers/class-validator"; +import { Protobuf } from "@meshtastic/meshtasticjs"; + +export const Audio = (): JSX.Element => { + const { moduleConfig, connection, setModuleConfig } = useDevice(); + const { + register, + handleSubmit, + formState: { isDirty }, + reset, + control + } = useForm({ + defaultValues: moduleConfig.audio, + resolver: classValidatorResolver(AudioValidation) + }); + + useEffect(() => { + reset(moduleConfig.audio); + }, [reset, moduleConfig.audio]); + + const onSubmit = handleSubmit((data) => { + if (connection) { + void toast.promise( + connection + .setModuleConfig({ + moduleConfig: { + payloadVariant: { + oneofKind: "audio", + audio: data + } + } + }) + .then(() => + setModuleConfig({ + payloadVariant: { + oneofKind: "audio", + audio: data + } + }) + ), + { + loading: "Saving...", + success: "Saved Audio Config, Restarting Node", + error: "No response received" + } + ); + } + }); + + return ( +
reset(moduleConfig.audio)} + dirty={isDirty} + onSubmit={onSubmit} + > + ( + + )} + /> + + + + + + + + ); +}; diff --git a/src/pages/Config/ModuleConfig.tsx b/src/pages/Config/ModuleConfig.tsx index da2c005a..6efb9966 100644 --- a/src/pages/Config/ModuleConfig.tsx +++ b/src/pages/Config/ModuleConfig.tsx @@ -1,6 +1,7 @@ import type React from "react"; import { Fragment } from "react"; +import { Audio } from "@app/components/PageComponents/ModuleConfig/Audio.js"; import { CannedMessage } from "@components/PageComponents/ModuleConfig/CannedMessage"; import { ExternalNotification } from "@components/PageComponents/ModuleConfig/ExternalNotification.js"; import { MQTT } from "@components/PageComponents/ModuleConfig/MQTT.js"; @@ -39,6 +40,10 @@ export const ModuleConfig = (): JSX.Element => { { label: "Canned Message", element: CannedMessage + }, + { + label: "Audio Config", + element: Audio } ]; diff --git a/src/validation/moduleConfig/audio.ts b/src/validation/moduleConfig/audio.ts new file mode 100644 index 00000000..bf81752e --- /dev/null +++ b/src/validation/moduleConfig/audio.ts @@ -0,0 +1,26 @@ +import { IsBoolean, IsEnum, IsInt } from "class-validator"; + +import { Protobuf } from "@meshtastic/meshtasticjs"; + +export class AudioValidation implements Protobuf.ModuleConfig_AudioConfig { + @IsBoolean() + codec2Enabled: boolean; + + @IsInt() + pttPin: number; + + @IsEnum(Protobuf.ModuleConfig_AudioConfig_Audio_Baud) + bitrate: Protobuf.ModuleConfig_AudioConfig_Audio_Baud; + + @IsInt() + i2SWs: number; + + @IsInt() + i2SSd: number; + + @IsInt() + i2SDin: number; + + @IsInt() + i2SSck: number; +}