diff --git a/app/src/lib/api.ts b/app/src/lib/api.ts index 00009f2..04a81d8 100644 --- a/app/src/lib/api.ts +++ b/app/src/lib/api.ts @@ -2,7 +2,8 @@ import { get } from 'svelte/store' import { Err, Ok, type Result } from './utilities' import { apiLocation } from './stores/location-store' import type { MessageFns } from './platform_shared/filesystem' -import { Response } from './platform_shared/api' +import { Request, Response } from './platform_shared/api' +import { BinaryWriter } from '@bufbuild/protobuf/wire' export const api = { get(endpoint: string, params?: RequestInit) { @@ -13,6 +14,10 @@ export const api = { return sendRequest(endpoint, 'POST', data) }, + post_proto(endpoint: string, data: Request) { + return sendRequest(endpoint, 'POST', Request.encode(data)) + }, + put(endpoint: string, data?: unknown) { return sendRequest(endpoint, 'PUT', data) }, @@ -29,7 +34,11 @@ async function sendRequest( params?: RequestInit ): Promise> { endpoint = resolveUrl(endpoint) - const body = data !== null && typeof data !== 'undefined' ? JSON.stringify(data) : undefined + + const isProtobuf = data instanceof BinaryWriter + const body = data !== null && typeof data !== 'undefined' + ? (isProtobuf ? data.finish() : JSON.stringify(data)) + : undefined const request = { ...params, @@ -38,7 +47,7 @@ async function sendRequest( headers: { ...params?.headers, Authorization: 'Basic', - 'Content-Type': 'application/json' + 'Content-Type': isProtobuf ? 'application/x-protobuf' : 'application/json' } } diff --git a/app/src/lib/types/models.ts b/app/src/lib/types/models.ts index adfb7fc..148dc27 100644 --- a/app/src/lib/types/models.ts +++ b/app/src/lib/types/models.ts @@ -71,18 +71,6 @@ export type NetworkItem = { encryption_type: number } -export type ApSettings = { - provision_mode: number - ssid: string - password: string - channel: number - ssid_hidden: boolean - max_clients: number - local_ip: number - gateway_ip: number - subnet_mask: number -} - export type Rssi = { rssi: number ssid: string diff --git a/app/src/routes/wifi/ap/Accesspoint.svelte b/app/src/routes/wifi/ap/Accesspoint.svelte index 5995c65..1a498e5 100644 --- a/app/src/routes/wifi/ap/Accesspoint.svelte +++ b/app/src/routes/wifi/ap/Accesspoint.svelte @@ -6,15 +6,14 @@ import SettingsCard from '$lib/components/SettingsCard.svelte' import { notifications } from '$lib/components/toasts/notifications' import Spinner from '$lib/components/Spinner.svelte' - import { type ApSettings } from '$lib/types/models' import { api } from '$lib/api' import { ipToUint32, uint32ToIp, isValidIpString } from '$lib/utilities' import { AP, Devices, Home, MAC } from '$lib/components/icons' import StatusItem from '$lib/components/StatusItem.svelte' - import { APStatus, Response } from '$lib/platform_shared/api' + import { APSettings, APStatus, Request, Response } from '$lib/platform_shared/api' import { input } from '$lib/stores' - let apSettings: ApSettings | null = $state(null) + let apSettings: APSettings | null = $state(null) let apStatus: APStatus | null = $state(null) let ipDisplay = $state({ @@ -36,16 +35,16 @@ } async function getAPSettings() { - const result = await api.get('/api/ap/settings') + const result = await api.get('/api/ap/settings') if (result.isErr()) { console.error('Error:', result.inner) return } - apSettings = result.inner + apSettings = result.inner.apSettings! ipDisplay = { - local_ip: uint32ToIp(apSettings.local_ip), - gateway_ip: uint32ToIp(apSettings.gateway_ip), - subnet_mask: uint32ToIp(apSettings.subnet_mask) + local_ip: uint32ToIp(apSettings.localIp), + gateway_ip: uint32ToIp(apSettings.gatewayIp), + subnet_mask: uint32ToIp(apSettings.subnetMask) } return apSettings } @@ -88,15 +87,21 @@ subnet_mask: false }) - async function postAPSettings(data: ApSettings) { - const result = await api.post('/api/ap/settings', data) + async function postAPSettings(data: APSettings) { + const result = await api.post_proto('/api/ap/settings', Request.create({ apSettings: data })) if (result.isErr()) { notifications.error('User not authorized.', 3000) console.error('Error:', result.inner) return } + if (result.inner.statusCode !== 200) { + notifications.error(result.inner.errorMessage || 'Failed to update settings', 3000) + return + } + if (result.inner.apSettings) { + apSettings = result.inner.apSettings + } notifications.success('Access Point settings updated.', 3000) - apSettings = result.inner } function handleSubmitAP(e: Event) { @@ -119,7 +124,7 @@ formErrors.channel = false } - let maxClients = Number(apSettings.max_clients) + let maxClients = Number(apSettings.maxClients) if (1 > maxClients || maxClients > 8) { valid = false formErrors.max_clients = true @@ -149,9 +154,9 @@ } if (valid) { - apSettings.local_ip = ipToUint32(ipDisplay.local_ip) - apSettings.gateway_ip = ipToUint32(ipDisplay.gateway_ip) - apSettings.subnet_mask = ipToUint32(ipDisplay.subnet_mask) + apSettings.localIp = ipToUint32(ipDisplay.local_ip) + apSettings.gatewayIp = ipToUint32(ipDisplay.gateway_ip) + apSettings.subnetMask = ipToUint32(ipDisplay.subnet_mask) postAPSettings(apSettings) } } @@ -225,7 +230,7 @@ Hide SSID diff --git a/esp32/include/template/stateful_proto_endpoint.h b/esp32/include/template/stateful_proto_endpoint.h index 1f293f6..f90532f 100644 --- a/esp32/include/template/stateful_proto_endpoint.h +++ b/esp32/include/template/stateful_proto_endpoint.h @@ -105,6 +105,7 @@ class StatefulProtoEndpoint { esp_err_t sendErrorResponse(httpd_req_t* request, uint32_t statusCode, const char* message) { api_Response res = api_Response_init_zero; res.status_code = statusCode; + res.error_message = (char*)message; return NativeServer::sendProto(request, statusCode == 200 ? 200 : 400, res, api_Response_fields); } }; diff --git a/platform_shared/api.options b/platform_shared/api.options index ef65d81..9394a59 100644 --- a/platform_shared/api.options +++ b/platform_shared/api.options @@ -2,3 +2,5 @@ api.APSettings.ssid max_size:33 api.APSettings.password max_size:64 api.APStatus.mac_address max_size:18 + +api.Response.error_message type:FT_POINTER diff --git a/platform_shared/api.proto b/platform_shared/api.proto index ff7d3da..7b81ce6 100644 --- a/platform_shared/api.proto +++ b/platform_shared/api.proto @@ -59,6 +59,7 @@ message Request { // Response wrapper for REST endpoints message Response { uint32 status_code = 1; + string error_message = 2; oneof payload { APSettings ap_settings = 10;