🎨 Renames topics

This commit is contained in:
Rune Harlyk
2025-09-01 18:44:42 +02:00
parent 527764b0b5
commit df087decdb
12 changed files with 142 additions and 136 deletions
@@ -1,48 +1,48 @@
<script lang="ts"> <script lang="ts">
import { page } from '$app/state'; import { page } from '$app/state'
import { modals } from 'svelte-modals'; import { modals } from 'svelte-modals'
import { notifications } from '$lib/components/toasts/notifications'; import { notifications } from '$lib/components/toasts/notifications'
import ConfirmDialog from '$lib/components/ConfirmDialog.svelte'; import ConfirmDialog from '$lib/components/ConfirmDialog.svelte'
import GithubUpdateDialog from '$lib/components/GithubUpdateDialog.svelte'; import GithubUpdateDialog from '$lib/components/GithubUpdateDialog.svelte'
import { compareVersions } from 'compare-versions'; import { compareVersions } from 'compare-versions'
import { onMount } from 'svelte'; import { onMount } from 'svelte'
import { api } from '$lib/api'; import { api } from '$lib/api'
import type { GithubRelease } from '$lib/types/models'; import type { GithubRelease } from '$lib/types/models'
import { useFeatureFlags } from '$lib/stores/featureFlags'; import { useFeatureFlags } from '$lib/stores/featureFlags'
import { Cancel, CloudDown, Firmware } from '../icons'; import { Cancel, CloudDown, Firmware } from '../icons'
const features = useFeatureFlags(); const features = useFeatureFlags()
interface Props { interface Props {
update?: boolean; update?: boolean
} }
let { update = $bindable(false) }: Props = $props(); let { update = $bindable(false) }: Props = $props()
let firmwareVersion: string = $state(''); let firmwareVersion: string = $state('')
let firmwareDownloadLink: string = $state(''); let firmwareDownloadLink: string = $state('')
async function getGithubAPI() { async function getGithubAPI() {
const headers = { const headers = {
accept: 'application/vnd.github+json', accept: 'application/vnd.github+json',
'X-GitHub-Api-Version': '2022-11-28', 'X-GitHub-Api-Version': '2022-11-28'
}; }
const result = await api.get<GithubRelease>( const result = await api.get<GithubRelease>(
`https://api.github.com/repos/${page.data.github}/releases/latest`, `https://api.github.com/repos/${page.data.github}/releases/latest`,
{ headers } { headers }
); )
if (result.inner.message === '404' || result.inner.message == 'Not Found') { if (result.inner.message === '404' || result.inner.message == 'Not Found') {
console.warn('Error: Could not find releases in the repository'); console.warn('Error: Could not find releases in the repository')
return; return
} }
if (result.isErr()) { if (result.isErr()) {
console.error('Error:', result.inner); console.error('Error:', result.inner)
return; return
} }
const results = result.inner; const results = result.inner
update = false; update = false
firmwareVersion = ''; firmwareVersion = ''
if (compareVersions(results.tag_name, $features.firmware_version as string) === 1) { if (compareVersions(results.tag_name, $features.firmware_version as string) === 1) {
// iterate over assets and find the correct one // iterate over assets and find the correct one
@@ -52,29 +52,29 @@
results.assets[i].name.includes('.bin') && results.assets[i].name.includes('.bin') &&
results.assets[i].name.includes($features.firmware_built_target as string) results.assets[i].name.includes($features.firmware_built_target as string)
) { ) {
update = true; update = true
firmwareVersion = results.tag_name; firmwareVersion = results.tag_name
firmwareDownloadLink = results.assets[i].browser_download_url; firmwareDownloadLink = results.assets[i].browser_download_url
notifications.info('Firmware update available.', 5000); notifications.info('Firmware update available.', 5000)
} }
} }
} }
} }
async function postGithubDownload(url: string) { async function postGithubDownload(url: string) {
const result = await api.post('/api/downloadUpdate', { download_url: url }); const result = await api.post('/api/downloadUpdate', { download_url: url })
if (result.isErr()) { if (result.isErr()) {
console.error('Error:', result.inner); console.error('Error:', result.inner)
return; return
} }
} }
onMount(async () => { onMount(async () => {
if ($features.download_firmware) { if ($features.download_firmware) {
await getGithubAPI(); await getGithubAPI()
setInterval(async () => await getGithubAPI(), 60 * 60 * 1000); // once per hour setInterval(async () => await getGithubAPI(), 60 * 60 * 1000) // once per hour
} }
}); })
function confirmGithubUpdate(url: string) { function confirmGithubUpdate(url: string) {
modals.open(ConfirmDialog, { modals.open(ConfirmDialog, {
@@ -82,15 +82,15 @@
message: 'Are you sure you want to overwrite the existing firmware with a new one?', message: 'Are you sure you want to overwrite the existing firmware with a new one?',
labels: { labels: {
cancel: { label: 'Abort', icon: Cancel }, cancel: { label: 'Abort', icon: Cancel },
confirm: { label: 'Update', icon: CloudDown }, confirm: { label: 'Update', icon: CloudDown }
}, },
onConfirm: () => { onConfirm: () => {
postGithubDownload(url); postGithubDownload(url)
modals.open(GithubUpdateDialog, { modals.open(GithubUpdateDialog, {
onConfirm: () => modals.closeAll(), onConfirm: () => modals.closeAll()
}); })
}, }
}); })
} }
</script> </script>
+31 -31
View File
@@ -1,45 +1,45 @@
import type { ControllerInput } from '$lib/types/models'; import type { ControllerInput } from '$lib/types/models'
import { persistentStore } from '$lib/utilities/svelte-utilities'; import { persistentStore } from '$lib/utilities/svelte-utilities'
import { writable, type Writable } from 'svelte/store'; import { writable, type Writable } from 'svelte/store'
export const emulateModel = writable(true); export const emulateModel = writable(true)
export const jointNames = persistentStore('joint_names', <string[]>[]); export const jointNames = persistentStore('joint_names', <string[]>[])
export const model = writable(); export const model = writable()
export const modes = [ export const modes = [
'deactivated', 'deactivated',
'idle', 'idle',
'calibration', 'calibration',
'rest', 'rest',
'stand', 'stand',
'crawl', 'crawl',
'walk' 'walk'
] as const; ] as const
export type Modes = (typeof modes)[number]; export type Modes = (typeof modes)[number]
export enum ModesEnum { export enum ModesEnum {
Deactivated, Deactivated,
Idle, Idle,
Calibration, Calibration,
Rest, Rest,
Stand, Stand,
Crawl, Crawl,
Walk Walk
} }
export const mode: Writable<ModesEnum> = writable(ModesEnum.Deactivated); export const mode: Writable<ModesEnum> = writable(ModesEnum.Deactivated)
export const outControllerData = writable([0, 0, 0, 0, 0, 1, 0]); export const outControllerData = writable([0, 0, 0, 0, 0, 1, 0])
export const kinematicData = writable([0, 0, 0, 0, 1, 0]); export const kinematicData = writable([0, 0, 0, 0, 1, 0])
export const input: Writable<ControllerInput> = writable({ export const input: Writable<ControllerInput> = writable({
left: { x: 0, y: 0 }, left: { x: 0, y: 0 },
right: { x: 0, y: 0 }, right: { x: 0, y: 0 },
height: 50, height: 0.5,
speed: 50, speed: 0.5,
s1: 50 s1: 0.05
}); })
+1 -1
View File
@@ -1,4 +1,4 @@
export enum Topics { export enum MessageTopic {
imu = 'imu', imu = 'imu',
mode = 'mode', mode = 'mode',
input = 'input', input = 'input',
+20 -14
View File
@@ -21,7 +21,9 @@
location, location,
useFeatureFlags useFeatureFlags
} from '$lib/stores' } from '$lib/stores'
import { Topics, type Analytics, type DownloadOTA } from '$lib/types/models' import { type Analytics, type DownloadOTA } from '$lib/types/models'
import { MessageTopic } from '$lib/types/models'
interface Props { interface Props {
children?: import('svelte').Snippet children?: import('svelte').Snippet
} }
@@ -36,10 +38,14 @@
addEventListeners() addEventListeners()
outControllerData.subscribe(data => socket.sendEvent(Topics.input, data)) outControllerData.subscribe(data => {
mode.subscribe(data => socket.sendEvent(Topics.mode, data)) console.log(data)
servoAnglesOut.subscribe(data => socket.sendEvent(Topics.angles, data))
kinematicData.subscribe(data => socket.sendEvent(Topics.position, data)) socket.sendEvent(MessageTopic.input, data)
})
mode.subscribe(data => socket.sendEvent(MessageTopic.mode, data))
servoAnglesOut.subscribe(data => socket.sendEvent(MessageTopic.angles, data))
kinematicData.subscribe(data => socket.sendEvent(MessageTopic.position, data))
}) })
onDestroy(() => { onDestroy(() => {
@@ -50,24 +56,24 @@
socket.on('open', handleOpen) socket.on('open', handleOpen)
socket.on('close', handleClose) socket.on('close', handleClose)
socket.on('error', handleError) socket.on('error', handleError)
socket.on(Topics.rssi, handleNetworkStatus) socket.on(MessageTopic.rssi, handleNetworkStatus)
socket.on(Topics.mode, (data: ModesEnum) => mode.set(data)) socket.on(MessageTopic.mode, (data: ModesEnum) => mode.set(data))
socket.on(Topics.analytics, handleAnalytics) socket.on(MessageTopic.analytics, handleAnalytics)
socket.on(Topics.angles, (angles: number[]) => { socket.on(MessageTopic.angles, (angles: number[]) => {
if (angles.length) servoAngles.set(angles) if (angles.length) servoAngles.set(angles)
}) })
features.subscribe(data => { features.subscribe(data => {
if (data?.download_firmware) socket.on(Topics.otastatus, handleOAT) if (data?.download_firmware) socket.on(MessageTopic.otastatus, handleOAT)
if (data?.sonar) socket.on(Topics.sonar, data => console.log(data)) if (data?.sonar) socket.on(MessageTopic.sonar, data => console.log(data))
}) })
} }
const removeEventListeners = () => { const removeEventListeners = () => {
socket.off(Topics.analytics, handleAnalytics) socket.off(MessageTopic.analytics, handleAnalytics)
socket.off('open', handleOpen) socket.off('open', handleOpen)
socket.off('close', handleClose) socket.off('close', handleClose)
socket.off(Topics.rssi, handleNetworkStatus) socket.off(MessageTopic.rssi, handleNetworkStatus)
socket.off(Topics.otastatus, handleOAT) socket.off(MessageTopic.otastatus, handleOAT)
} }
const handleOpen = () => { const handleOpen = () => {
+2 -2
View File
@@ -5,12 +5,12 @@
import { onMount } from 'svelte' import { onMount } from 'svelte'
import { mpu, socket } from '$lib/stores' import { mpu, socket } from '$lib/stores'
import { imu } from '$lib/stores/imu' import { imu } from '$lib/stores/imu'
import { Topics, type IMU } from '$lib/types/models' import { MessageTopic, type IMU } from '$lib/types/models'
let layout = $derived($views.find(v => v.name === $selectedView)!) let layout = $derived($views.find(v => v.name === $selectedView)!)
onMount(() => { onMount(() => {
socket.on(Topics.imu, (data: IMU) => { socket.on(MessageTopic.imu, (data: IMU) => {
imu.addData(data) imu.addData(data)
if (data.heading) if (data.heading)
mpu.update(mpuData => { mpu.update(mpuData => {
+4 -4
View File
@@ -2,7 +2,7 @@
import SettingsCard from '$lib/components/SettingsCard.svelte' import SettingsCard from '$lib/components/SettingsCard.svelte'
import { onMount } from 'svelte' import { onMount } from 'svelte'
import { socket } from '$lib/stores' import { socket } from '$lib/stores'
import { Topics, type I2CDevice } from '$lib/types/models' import { MessageTopic, type I2CDevice } from '$lib/types/models'
import { Connection } from '$lib/components/icons' import { Connection } from '$lib/components/icons'
import I2CSetting from './i2cSetting.svelte' import I2CSetting from './i2cSetting.svelte'
@@ -24,9 +24,9 @@
let isLoading = $state(false) let isLoading = $state(false)
onMount(() => { onMount(() => {
socket.on(Topics.i2cScan, handleScan) socket.on(MessageTopic.i2cScan, handleScan)
triggerScan() triggerScan()
return () => socket.off(Topics.i2cScan, handleScan) return () => socket.off(MessageTopic.i2cScan, handleScan)
}) })
const handleScan = (data: any) => { const handleScan = (data: any) => {
@@ -43,7 +43,7 @@
const triggerScan = () => { const triggerScan = () => {
isLoading = true isLoading = true
socket.sendEvent(Topics.i2cScan, '') socket.sendEvent(MessageTopic.i2cScan, '')
} }
</script> </script>
@@ -1,7 +1,7 @@
<script lang="ts"> <script lang="ts">
import { Cancel, Edit, EditOff, Power } from '$lib/components/icons' import { Cancel, Edit, EditOff, Power } from '$lib/components/icons'
import { socket } from '$lib/stores' import { socket } from '$lib/stores'
import { Topics, type PeripheralsConfiguration } from '$lib/types/models' import { MessageTopic, type PeripheralsConfiguration } from '$lib/types/models'
import { onMount } from 'svelte' import { onMount } from 'svelte'
import { modals } from 'svelte-modals' import { modals } from 'svelte-modals'
import ConfirmDialog from '$lib/components/ConfirmDialog.svelte' import ConfirmDialog from '$lib/components/ConfirmDialog.svelte'
@@ -10,9 +10,9 @@
let isEditing = $state(false) let isEditing = $state(false)
onMount(() => { onMount(() => {
socket.on(Topics.peripheralSettings, handleSettings) socket.on(MessageTopic.peripheralSettings, handleSettings)
socket.sendEvent(Topics.peripheralSettings, '') socket.sendEvent(MessageTopic.peripheralSettings, '')
return () => socket.off(Topics.peripheralSettings, handleSettings) return () => socket.off(MessageTopic.peripheralSettings, handleSettings)
}) })
const handleSettings = (data: any) => { const handleSettings = (data: any) => {
@@ -30,7 +30,7 @@
}, },
onConfirm: () => { onConfirm: () => {
modals.close() modals.close()
socket.sendEvent(Topics.peripheralSettings, settings) socket.sendEvent(MessageTopic.peripheralSettings, settings)
} }
}) })
} }
+3 -3
View File
@@ -6,7 +6,7 @@
import { slide } from 'svelte/transition' import { slide } from 'svelte/transition'
import { onDestroy, onMount } from 'svelte' import { onDestroy, onMount } from 'svelte'
import { socket } from '$lib/stores' import { socket } from '$lib/stores'
import { Topics, type IMU } from '$lib/types/models' import { MessageTopic, type IMU } from '$lib/types/models'
import { useFeatureFlags } from '$lib/stores/featureFlags' import { useFeatureFlags } from '$lib/stores/featureFlags'
import { Rotate3d } from '$lib/components/icons' import { Rotate3d } from '$lib/components/icons'
@@ -201,7 +201,7 @@
} }
onMount(() => { onMount(() => {
socket.on(Topics.imu, (data: IMU) => { socket.on(MessageTopic.imu, (data: IMU) => {
console.log(data) console.log(data)
imu.addData(data) imu.addData(data)
}) })
@@ -211,7 +211,7 @@
}) })
onDestroy(() => { onDestroy(() => {
socket.off(Topics.imu) socket.off(MessageTopic.imu)
clearInterval(intervalId) clearInterval(intervalId)
}) })
</script> </script>
@@ -1,6 +1,6 @@
<script lang="ts"> <script lang="ts">
import { socket } from '$lib/stores' import { socket } from '$lib/stores'
import { Topics } from '$lib/types/models' import { MessageTopic } from '$lib/types/models'
import { throttler as Throttler } from '$lib/utilities' import { throttler as Throttler } from '$lib/utilities'
let { servoId = $bindable(0), pwm = $bindable(306) } = $props() let { servoId = $bindable(0), pwm = $bindable(306) } = $props()
@@ -12,16 +12,16 @@
const throttler = new Throttler() const throttler = new Throttler()
const activateServo = () => { const activateServo = () => {
socket.sendEvent(Topics.servoState, { active: 1 }) socket.sendEvent(MessageTopic.servoState, { active: 1 })
} }
const deactivateServo = () => { const deactivateServo = () => {
socket.sendEvent(Topics.servoState, { active: 0 }) socket.sendEvent(MessageTopic.servoState, { active: 0 })
} }
const updatePWM = () => { const updatePWM = () => {
throttler.throttle(() => { throttler.throttle(() => {
socket.sendEvent(Topics.servoPWM, { servo_id: servoId, pwm }) socket.sendEvent(MessageTopic.servoPWM, { servo_id: servoId, pwm })
}, 10) }, 10)
} }
@@ -6,7 +6,7 @@
import Spinner from '$lib/components/Spinner.svelte' import Spinner from '$lib/components/Spinner.svelte'
import { slide } from 'svelte/transition' import { slide } from 'svelte/transition'
import { cubicOut } from 'svelte/easing' import { cubicOut } from 'svelte/easing'
import { type SystemInformation, type Analytics, Topics } from '$lib/types/models' import { type SystemInformation, type Analytics, MessageTopic } from '$lib/types/models'
import { socket } from '$lib/stores/socket' import { socket } from '$lib/stores/socket'
import { api } from '$lib/api' import { api } from '$lib/api'
import { convertSeconds } from '$lib/utilities' import { convertSeconds } from '$lib/utilities'
@@ -50,9 +50,9 @@
const postSleep = async () => await api.post('api/sleep') const postSleep = async () => await api.post('api/sleep')
onMount(() => socket.on(Topics.analytics, handleSystemData)) onMount(() => socket.on(MessageTopic.analytics, handleSystemData))
onDestroy(() => socket.off(Topics.analytics, handleSystemData)) onDestroy(() => socket.off(MessageTopic.analytics, handleSystemData))
const handleSystemData = (data: Analytics) => { const handleSystemData = (data: Analytics) => {
if (systemInformation) { if (systemInformation) {
systemInformation = { systemInformation = {
+24 -24
View File
@@ -19,50 +19,50 @@
'WPA2 Enterprise', 'WPA2 Enterprise',
'WPA3 PSK', 'WPA3 PSK',
'WPA2 WPA3 PSK', 'WPA2 WPA3 PSK',
'WAPI PSK', 'WAPI PSK'
]; ]
let listOfNetworks: NetworkItem[] = $state([]); let listOfNetworks: NetworkItem[] = $state([])
let scanActive = $state(false); let scanActive = $state(false)
let pollingId: ReturnType<typeof setTimeout> | number; let pollingId: ReturnType<typeof setTimeout> | number
async function scanNetworks() { async function scanNetworks() {
scanActive = true; scanActive = true
await api.get('/api/wifi/scan'); await api.get('/api/wifi/scan')
if ((await pollingResults()) == false) { if ((await pollingResults()) == false) {
pollingId = setInterval(() => pollingResults(), 1000); pollingId = setInterval(() => pollingResults(), 1000)
} }
return; return
} }
async function pollingResults() { async function pollingResults() {
const result = await api.get<NetworkList>('/api/wifi/networks'); const result = await api.get<NetworkList>('/api/wifi/networks')
if (result.isErr()) { if (result.isErr()) {
console.error(`Error occurred while fetching: `, result.inner); console.error(`Error occurred while fetching: `, result.inner)
return false; return false
} }
let response = result.inner; let response = result.inner
listOfNetworks = response.networks; listOfNetworks = response.networks
scanActive = false; scanActive = false
if (listOfNetworks.length) { if (listOfNetworks.length) {
clearInterval(pollingId); clearInterval(pollingId)
pollingId = 0; pollingId = 0
} }
return listOfNetworks.length; return listOfNetworks.length
} }
onMount(() => { onMount(() => {
scanNetworks(); scanNetworks()
}); })
onDestroy(() => { onDestroy(() => {
if (pollingId) { if (pollingId) {
clearInterval(pollingId); clearInterval(pollingId)
pollingId = 0; pollingId = 0
} }
}); })
</script> </script>
{#if isOpen} {#if isOpen}
@@ -89,7 +89,7 @@
<div <div
class="bg-base-200 rounded-btn my-1 flex items-center space-x-3 hover:scale-[1.02] active:scale-[0.98]" class="bg-base-200 rounded-btn my-1 flex items-center space-x-3 hover:scale-[1.02] active:scale-[0.98]"
onclick={() => { onclick={() => {
storeNetwork(network.ssid); storeNetwork(network.ssid)
}} }}
role="button" role="button"
tabindex="0"> tabindex="0">
+3 -3
View File
@@ -12,7 +12,7 @@
import Spinner from '$lib/components/Spinner.svelte' import Spinner from '$lib/components/Spinner.svelte'
import InfoDialog from '$lib/components/InfoDialog.svelte' import InfoDialog from '$lib/components/InfoDialog.svelte'
import { import {
Topics, MessageTopic,
type KnownNetworkItem, type KnownNetworkItem,
type WifiSettings, type WifiSettings,
type WifiStatus type WifiStatus
@@ -97,10 +97,10 @@
return wifiSettings return wifiSettings
} }
onDestroy(() => socket.off(Topics.WiFiSettings)) onDestroy(() => socket.off(MessageTopic.WiFiSettings))
onMount(() => { onMount(() => {
socket.on<WifiSettings>(Topics.WiFiSettings, data => { socket.on<WifiSettings>(MessageTopic.WiFiSettings, data => {
wifiSettings = data wifiSettings = data
dndNetworkList = wifiSettings.wifi_networks dndNetworkList = wifiSettings.wifi_networks
}) })