Compare commits
13 Commits
Author | SHA1 | Date | |
---|---|---|---|
![]() |
7b99b75def | ||
![]() |
48e433ff1e | ||
![]() |
f3d43bbd65 | ||
![]() |
186275d1dd | ||
![]() |
8068f82f13 | ||
![]() |
c4f2006e8f | ||
![]() |
7b50441da2 | ||
![]() |
940f6ea1b5 | ||
![]() |
a48d1238a2 | ||
![]() |
7aaa0c0aab | ||
![]() |
00bf392931 | ||
![]() |
7d2ad1cd49 | ||
![]() |
307b467ac1 |
@ -3,7 +3,7 @@ run-name: ${{ gitea.actor }} build
|
||||
on: [push]
|
||||
|
||||
jobs:
|
||||
build:
|
||||
build-go:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
@ -21,3 +21,21 @@ jobs:
|
||||
run: cd admin && go get .
|
||||
- name: "[admin] Build"
|
||||
run: cd admin && go build -v ./...
|
||||
build-nuxt:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Setup Bun 1.2.0
|
||||
uses: oven-sh/setup-bun@v2
|
||||
with:
|
||||
bun-version: 1.2.0
|
||||
- name: Display Bun version
|
||||
run: bun --version
|
||||
- name: test 1
|
||||
run: ls
|
||||
- name: test 2
|
||||
run: cd web && ls
|
||||
- name: "[web] Install dependencies"
|
||||
run: cd web && bun install
|
||||
- name: "[web] Build"
|
||||
run: cd web && bun run build
|
2
.gitignore
vendored
2
.gitignore
vendored
@ -85,8 +85,6 @@ __pycache__/
|
||||
|
||||
## Node
|
||||
node_modules
|
||||
package-lock.json
|
||||
package.json
|
||||
/src/doc/rustc-dev-guide/mermaid.min.js
|
||||
|
||||
## Rustdoc GUI tests
|
||||
|
@ -1,3 +1,4 @@
|
||||
import gc
|
||||
import utime
|
||||
import ujson
|
||||
import network
|
||||
@ -17,6 +18,7 @@ class App:
|
||||
|
||||
opened: bool = False
|
||||
previously_opened: bool = False
|
||||
wlan: network.WLAN
|
||||
|
||||
led = Pin(15, Pin.OUT)
|
||||
trigger = Pin(2, Pin.OUT)
|
||||
@ -55,18 +57,18 @@ class App:
|
||||
|
||||
def connect(self):
|
||||
print("Connecting to Wi-Fi...")
|
||||
wlan = network.WLAN(network.STA_IF)
|
||||
self.wlan = network.WLAN(network.STA_IF)
|
||||
|
||||
wlan.active(False)
|
||||
self.wlan.active(False)
|
||||
utime.sleep_ms(250)
|
||||
wlan.active(True)
|
||||
self.wlan.active(True)
|
||||
utime.sleep_ms(250)
|
||||
|
||||
wlan.connect(self.ssid, self.password)
|
||||
self.wlan.connect(self.ssid, self.password)
|
||||
utime.sleep_ms(100)
|
||||
|
||||
retry_count = 0
|
||||
while not wlan.isconnected():
|
||||
while not self.wlan.isconnected():
|
||||
if retry_count >= MAX_CONNECTION_RETRIES:
|
||||
print("Max connection retries reached")
|
||||
exit(1)
|
||||
@ -80,22 +82,14 @@ class App:
|
||||
|
||||
if retry_count % 10 == 0:
|
||||
print("Attempting to restart connection...")
|
||||
wlan.connect(self.ssid, self.password)
|
||||
self.wlan.connect(self.ssid, self.password)
|
||||
for _ in range(10):
|
||||
self.led.toggle()
|
||||
utime.sleep_ms(50)
|
||||
|
||||
print(f"Connected with IP {wlan.ifconfig()[0]}")
|
||||
print(f"Connected with IP {self.wlan.ifconfig()[0]}")
|
||||
self.update_server()
|
||||
|
||||
def health_check_server(self):
|
||||
print("Health checking server...", end="\r")
|
||||
try:
|
||||
r = urequests.get(f"{self.server}/")
|
||||
print(f"Server healthy [{r.status_code}]{" " * 8}")
|
||||
except Exception as e:
|
||||
print(f"Error occurred: {e}")
|
||||
|
||||
def update_server(self):
|
||||
print("Updating state...", end="\r")
|
||||
data = {"opened": self.opened}
|
||||
@ -111,24 +105,32 @@ class App:
|
||||
except Exception as e:
|
||||
print(f"Error occurred: {e}")
|
||||
|
||||
def measure_distance(self):
|
||||
def measure_distance(self) -> float:
|
||||
self.trigger.low()
|
||||
utime.sleep_us(2)
|
||||
self.trigger.high()
|
||||
utime.sleep_us(10)
|
||||
self.trigger.low()
|
||||
|
||||
start_time = utime.ticks_us()
|
||||
sent_time = utime.ticks_us()
|
||||
while self.echo.value() == 0:
|
||||
print("hey", end="\r")
|
||||
sent_time = utime.ticks_us()
|
||||
if sent_time - start_time >= 100_000: # if it takes more than 100ms, stop
|
||||
return -1
|
||||
|
||||
start_time = utime.ticks_us()
|
||||
received_time = utime.ticks_us()
|
||||
while self.echo.value() == 1:
|
||||
print("ho", end="\r")
|
||||
received_time = utime.ticks_us()
|
||||
if received_time - start_time >= 100_000: # same
|
||||
return -1
|
||||
|
||||
delta_time = received_time - sent_time
|
||||
distance = delta_time / 1_000_000 * SOUND_SPEED / 2
|
||||
print(f"Distance: {distance} cm")
|
||||
print(f"Distance: {distance:0<5} cm; mem_free = {gc.mem_free()}")
|
||||
|
||||
return distance
|
||||
|
||||
@ -139,6 +141,9 @@ class App:
|
||||
i = 0
|
||||
while True:
|
||||
try:
|
||||
if not self.wlan.isconnected():
|
||||
self.connect()
|
||||
|
||||
distance = self.measure_distance()
|
||||
self.opened = distance >= THRESHOLD_DISTANCE
|
||||
|
||||
@ -157,13 +162,14 @@ class App:
|
||||
self.previously_opened = True
|
||||
|
||||
if i >= 20:
|
||||
print("Blinking...")
|
||||
self.led.toggle()
|
||||
utime.sleep_ms(100)
|
||||
self.led.toggle()
|
||||
utime.sleep_ms(400)
|
||||
|
||||
i = 0
|
||||
self.health_check_server()
|
||||
gc.collect()
|
||||
else:
|
||||
utime.sleep_ms(500)
|
||||
|
||||
@ -172,5 +178,6 @@ class App:
|
||||
|
||||
i += 1
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
App().run()
|
||||
|
@ -73,6 +73,10 @@ func main() {
|
||||
LogLevel: log.ERROR,
|
||||
}))
|
||||
app.Use(middleware.Secure())
|
||||
app.Use(middleware.CORSWithConfig(middleware.CORSConfig{
|
||||
AllowOrigins: []string{"*"},
|
||||
AllowHeaders: []string{echo.HeaderOrigin, echo.HeaderContentType, echo.HeaderAccept, echo.HeaderAuthorization},
|
||||
}))
|
||||
|
||||
app.Use(middleware.LoggerWithConfig(middleware.LoggerConfig{
|
||||
Format: "${time_custom} ${method} ${uri} ---> ${status} in ${latency_human} (${bytes_out} bytes)\n",
|
||||
@ -213,7 +217,8 @@ func main() {
|
||||
|
||||
func authed(next echo.HandlerFunc) echo.HandlerFunc {
|
||||
return func(c echo.Context) error {
|
||||
if c.Request().Header.Get("Authorization") != token {
|
||||
provided := c.Request().Header.Get("Authorization")
|
||||
if provided != fmt.Sprintf("Bearer %s", token) {
|
||||
return c.NoContent(http.StatusUnauthorized)
|
||||
}
|
||||
|
||||
|
24
web/.gitignore
vendored
Normal file
24
web/.gitignore
vendored
Normal file
@ -0,0 +1,24 @@
|
||||
# Nuxt dev/build outputs
|
||||
.output
|
||||
.data
|
||||
.nuxt
|
||||
.nitro
|
||||
.cache
|
||||
dist
|
||||
|
||||
# Node dependencies
|
||||
node_modules
|
||||
|
||||
# Logs
|
||||
logs
|
||||
*.log
|
||||
|
||||
# Misc
|
||||
.DS_Store
|
||||
.fleet
|
||||
.idea
|
||||
|
||||
# Local env files
|
||||
.env
|
||||
.env.*
|
||||
!.env.example
|
6
web/.prettierrc
Normal file
6
web/.prettierrc
Normal file
@ -0,0 +1,6 @@
|
||||
{
|
||||
"trailingComma": "es5",
|
||||
"tabWidth": 4,
|
||||
"semi": false,
|
||||
"singleQuote": false
|
||||
}
|
9
web/app.vue
Normal file
9
web/app.vue
Normal file
@ -0,0 +1,9 @@
|
||||
<template>
|
||||
<UApp>
|
||||
<NuxtPage />
|
||||
</UApp>
|
||||
</template>
|
||||
|
||||
<style>
|
||||
@import "assets/css/main.css";
|
||||
</style>
|
2
web/assets/css/main.css
Normal file
2
web/assets/css/main.css
Normal file
@ -0,0 +1,2 @@
|
||||
@import "tailwindcss";
|
||||
@import "@nuxt/ui";
|
3
web/assets/css/tailwind.css
Normal file
3
web/assets/css/tailwind.css
Normal file
@ -0,0 +1,3 @@
|
||||
@tailwind base;
|
||||
@tailwind components;
|
||||
@tailwind utilities;
|
2004
web/bun.lock
Normal file
2004
web/bun.lock
Normal file
File diff suppressed because it is too large
Load Diff
3
web/composables/useToken.ts
Normal file
3
web/composables/useToken.ts
Normal file
@ -0,0 +1,3 @@
|
||||
export function useToken() {
|
||||
return useCookie<string | undefined>("token");
|
||||
}
|
6
web/nuxt.config.ts
Normal file
6
web/nuxt.config.ts
Normal file
@ -0,0 +1,6 @@
|
||||
// https://nuxt.com/docs/api/configuration/nuxt-config
|
||||
export default defineNuxtConfig({
|
||||
compatibilityDate: "2025-05-15",
|
||||
devtools: { enabled: true },
|
||||
modules: ["@nuxt/icon", "@nuxt/ui", "@nuxtjs/tailwindcss"],
|
||||
});
|
25
web/package.json
Normal file
25
web/package.json
Normal file
@ -0,0 +1,25 @@
|
||||
{
|
||||
"name": "nuxt-app",
|
||||
"private": true,
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"build": "nuxt build",
|
||||
"dev": "nuxt dev",
|
||||
"generate": "nuxt generate",
|
||||
"preview": "nuxt preview",
|
||||
"postinstall": "nuxt prepare"
|
||||
},
|
||||
"dependencies": {
|
||||
"@nuxt/icon": "1.13.0",
|
||||
"@nuxt/ui": "3.1.3",
|
||||
"@nuxtjs/tailwindcss": "7.0.0-beta.0",
|
||||
"nuxt": "^3.17.5",
|
||||
"typescript": "^5.6.3",
|
||||
"valibot": "^1.1.0",
|
||||
"vue": "^3.5.16",
|
||||
"vue-router": "^4.5.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"prettier": "^3.5.3"
|
||||
}
|
||||
}
|
24
web/pages/index.vue
Normal file
24
web/pages/index.vue
Normal file
@ -0,0 +1,24 @@
|
||||
<template>
|
||||
<main class="flex items-center justify-center min-w-screen min-h-screen">
|
||||
<UButton
|
||||
icon="material-symbols:lock"
|
||||
size="xl"
|
||||
color="primary"
|
||||
variant="solid"
|
||||
>
|
||||
Lock
|
||||
</UButton>
|
||||
</main>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
const token = useToken();
|
||||
const locked = true;
|
||||
|
||||
onMounted(() => {
|
||||
if (!token.value) {
|
||||
return navigateTo("/token");
|
||||
}
|
||||
console.log(token.value);
|
||||
});
|
||||
</script>
|
75
web/pages/token.vue
Normal file
75
web/pages/token.vue
Normal file
@ -0,0 +1,75 @@
|
||||
<template>
|
||||
<main class="flex items-center justify-center min-w-screen min-h-screen">
|
||||
<UForm
|
||||
:schema="schema"
|
||||
:state="state"
|
||||
@submit="onSubmit"
|
||||
class="flex flex-col items-end justify-center gap-y-2"
|
||||
>
|
||||
<UFormField label="Token" name="token" size="xl" required>
|
||||
<UInput
|
||||
v-model="state.token"
|
||||
placeholder="Your token..."
|
||||
size="xl"
|
||||
/>
|
||||
</UFormField>
|
||||
|
||||
<UButton type="submit" size="xl"> Submit</UButton>
|
||||
</UForm>
|
||||
</main>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import * as v from "valibot"
|
||||
import type { FormSubmitEvent } from "@nuxt/ui"
|
||||
|
||||
const token = useToken()
|
||||
|
||||
const schema = v.object({
|
||||
token: v.pipe(v.string(), v.nonEmpty("Please enter your token")),
|
||||
})
|
||||
type Schema = v.InferOutput<typeof schema>
|
||||
|
||||
const state = reactive({
|
||||
token: "",
|
||||
})
|
||||
const toast = useToast()
|
||||
|
||||
async function onSubmit(event: FormSubmitEvent<Schema>) {
|
||||
const received = event.data.token
|
||||
await $fetch("https://door.svitan.dev/open", {
|
||||
method: "GET",
|
||||
headers: {
|
||||
Authorization: `Bearer ${received}`,
|
||||
},
|
||||
async onRequestError({ error }) {
|
||||
toast.add({
|
||||
title: "Error occurred",
|
||||
description: error.message,
|
||||
color: "error",
|
||||
})
|
||||
},
|
||||
async onResponse({ response }) {
|
||||
if (response.status === 200) {
|
||||
toast.add({ title: "Token saved", color: "success" })
|
||||
token.value = received
|
||||
navigateTo("/")
|
||||
} else if (response.status === 401) {
|
||||
toast.add({ title: "Token not valid", color: "error" })
|
||||
} else {
|
||||
toast.add({
|
||||
title: "Error occurred",
|
||||
description: await response.text(),
|
||||
color: "error",
|
||||
})
|
||||
}
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
if (token.value) {
|
||||
return navigateTo("/")
|
||||
}
|
||||
})
|
||||
</script>
|
BIN
web/public/favicon.ico
Normal file
BIN
web/public/favicon.ico
Normal file
Binary file not shown.
After Width: | Height: | Size: 264 KiB |
2
web/public/robots.txt
Normal file
2
web/public/robots.txt
Normal file
@ -0,0 +1,2 @@
|
||||
User-Agent: *
|
||||
Disallow: /
|
3
web/server/tsconfig.json
Normal file
3
web/server/tsconfig.json
Normal file
@ -0,0 +1,3 @@
|
||||
{
|
||||
"extends": "../.nuxt/tsconfig.server.json"
|
||||
}
|
11
web/tailwind.config.js
Normal file
11
web/tailwind.config.js
Normal file
@ -0,0 +1,11 @@
|
||||
module.exports = {
|
||||
purge: [],
|
||||
darkMode: "class", // or 'media' or 'class'
|
||||
theme: {
|
||||
extend: {},
|
||||
},
|
||||
variants: {
|
||||
extend: {},
|
||||
},
|
||||
plugins: [],
|
||||
};
|
4
web/tsconfig.json
Normal file
4
web/tsconfig.json
Normal file
@ -0,0 +1,4 @@
|
||||
{
|
||||
// https://nuxt.com/docs/guide/concepts/typescript
|
||||
"extends": "./.nuxt/tsconfig.json"
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user