wip device connection
This commit is contained in:
parent
3be0ed058b
commit
b01eccb447
8 changed files with 241 additions and 5 deletions
44
api/src/routes/device-socket.ts
Normal file
44
api/src/routes/device-socket.ts
Normal file
|
|
@ -0,0 +1,44 @@
|
||||||
|
import Elysia from "elysia"
|
||||||
|
import { broadcastQuizState, partyTopic, socketPartyId, userTopic } from "./party-socket"
|
||||||
|
import { getMemberRecord, getPartyStatus } from "../party-data"
|
||||||
|
import { db } from "../db"
|
||||||
|
|
||||||
|
export const partySocketApp = new Elysia()
|
||||||
|
.group("/dev-socket", (app) =>
|
||||||
|
app
|
||||||
|
.get("/test", () => ({ ok: 1 }))
|
||||||
|
.ws("/ws", {
|
||||||
|
async open(ws) {
|
||||||
|
let id = "zzxWcTUntIWTHkX8atEOv7Neiu7XEz9t"
|
||||||
|
ws.subscribe(userTopic(id))
|
||||||
|
const membership = await getMemberRecord(db, id);
|
||||||
|
if (!membership) {
|
||||||
|
ws.send(
|
||||||
|
JSON.stringify({
|
||||||
|
type: "snapshot",
|
||||||
|
party: null,
|
||||||
|
members: [],
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
socketPartyId.set(ws, membership.partyId);
|
||||||
|
ws.subscribe(partyTopic(membership.partyId));
|
||||||
|
|
||||||
|
const snapshot = await getPartyStatus(membership.partyId);
|
||||||
|
if (snapshot) {
|
||||||
|
ws.send(
|
||||||
|
JSON.stringify({
|
||||||
|
type: "snapshot",
|
||||||
|
party: snapshot.party,
|
||||||
|
members: snapshot.members,
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
|
||||||
|
await broadcastQuizState(ws, membership.partyId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
})
|
||||||
|
)
|
||||||
34
dev-proxy/.gitignore
vendored
Normal file
34
dev-proxy/.gitignore
vendored
Normal file
|
|
@ -0,0 +1,34 @@
|
||||||
|
# dependencies (bun install)
|
||||||
|
node_modules
|
||||||
|
|
||||||
|
# output
|
||||||
|
out
|
||||||
|
dist
|
||||||
|
*.tgz
|
||||||
|
|
||||||
|
# code coverage
|
||||||
|
coverage
|
||||||
|
*.lcov
|
||||||
|
|
||||||
|
# logs
|
||||||
|
logs
|
||||||
|
_.log
|
||||||
|
report.[0-9]_.[0-9]_.[0-9]_.[0-9]_.json
|
||||||
|
|
||||||
|
# dotenv environment variable files
|
||||||
|
.env
|
||||||
|
.env.development.local
|
||||||
|
.env.test.local
|
||||||
|
.env.production.local
|
||||||
|
.env.local
|
||||||
|
|
||||||
|
# caches
|
||||||
|
.eslintcache
|
||||||
|
.cache
|
||||||
|
*.tsbuildinfo
|
||||||
|
|
||||||
|
# IntelliJ based IDEs
|
||||||
|
.idea
|
||||||
|
|
||||||
|
# Finder (MacOS) folder config
|
||||||
|
.DS_Store
|
||||||
15
dev-proxy/README.md
Normal file
15
dev-proxy/README.md
Normal file
|
|
@ -0,0 +1,15 @@
|
||||||
|
# dev-proxy
|
||||||
|
|
||||||
|
To install dependencies:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
bun install
|
||||||
|
```
|
||||||
|
|
||||||
|
To run:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
bun run index.ts
|
||||||
|
```
|
||||||
|
|
||||||
|
This project was created using `bun init` in bun v1.3.11. [Bun](https://bun.com) is a fast all-in-one JavaScript runtime.
|
||||||
26
dev-proxy/bun.lock
Normal file
26
dev-proxy/bun.lock
Normal file
|
|
@ -0,0 +1,26 @@
|
||||||
|
{
|
||||||
|
"lockfileVersion": 1,
|
||||||
|
"configVersion": 1,
|
||||||
|
"workspaces": {
|
||||||
|
"": {
|
||||||
|
"name": "dev-proxy",
|
||||||
|
"devDependencies": {
|
||||||
|
"@types/bun": "latest",
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"typescript": "^5",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"packages": {
|
||||||
|
"@types/bun": ["@types/bun@1.3.13", "", { "dependencies": { "bun-types": "1.3.13" } }, "sha512-9fqXWk5YIHGGnUau9TEi+qdlTYDAnOj+xLCmSTwXfAIqXr2x4tytJb43E9uCvt09zJURKXwAtkoH4nLQfzeTXw=="],
|
||||||
|
|
||||||
|
"@types/node": ["@types/node@25.6.0", "", { "dependencies": { "undici-types": "~7.19.0" } }, "sha512-+qIYRKdNYJwY3vRCZMdJbPLJAtGjQBudzZzdzwQYkEPQd+PJGixUL5QfvCLDaULoLv+RhT3LDkwEfKaAkgSmNQ=="],
|
||||||
|
|
||||||
|
"bun-types": ["bun-types@1.3.13", "", { "dependencies": { "@types/node": "*" } }, "sha512-QXKeHLlOLqQX9LgYaHJfzdBaV21T63HhFJnvuRCcjZiaUDpbs5ED1MgxbMra71CsryN/1dAoXuJJJwIv/2drVA=="],
|
||||||
|
|
||||||
|
"typescript": ["typescript@5.9.3", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw=="],
|
||||||
|
|
||||||
|
"undici-types": ["undici-types@7.19.2", "", {}, "sha512-qYVnV5OEm2AW8cJMCpdV20CDyaN3g0AjDlOGf1OW4iaDEx8MwdtChUp4zu4H0VP3nDRF/8RKWH+IPp9uW0YGZg=="],
|
||||||
|
}
|
||||||
|
}
|
||||||
38
dev-proxy/index.ts
Normal file
38
dev-proxy/index.ts
Normal file
|
|
@ -0,0 +1,38 @@
|
||||||
|
import type {
|
||||||
|
PartySocketEvent,
|
||||||
|
PartyState,
|
||||||
|
} from "../api/src/party-types";
|
||||||
|
let ws: WebSocket | null = null;
|
||||||
|
|
||||||
|
Bun.listen({
|
||||||
|
hostname: "0.0.0.0",
|
||||||
|
port: 7070,
|
||||||
|
socket: {
|
||||||
|
data(socket, data) {
|
||||||
|
// in1={} in2={} in3={} in4={} angle={}
|
||||||
|
console.log("recv", data)
|
||||||
|
}, // message received from client
|
||||||
|
open(socket) {
|
||||||
|
console.log("Connected");
|
||||||
|
ws = new WebSocket("ws://localhost:3000/api/dev-socket/ws");
|
||||||
|
|
||||||
|
ws.onmessage = e => {
|
||||||
|
const data = JSON.parse(e.data) as PartySocketEvent;
|
||||||
|
switch (data.type) {
|
||||||
|
case "party_status":
|
||||||
|
const { party: { data: { currentQuestion } } } = data;
|
||||||
|
console.log(currentQuestion)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, // socket opened
|
||||||
|
close(socket, error) {
|
||||||
|
ws?.close();
|
||||||
|
ws = null;
|
||||||
|
}, // socket closed
|
||||||
|
drain(socket) {}, // socket ready for more data
|
||||||
|
error(socket, error) {}, // error handler
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
console.log("Started on :7070")
|
||||||
12
dev-proxy/package.json
Normal file
12
dev-proxy/package.json
Normal file
|
|
@ -0,0 +1,12 @@
|
||||||
|
{
|
||||||
|
"name": "dev-proxy",
|
||||||
|
"module": "index.ts",
|
||||||
|
"type": "module",
|
||||||
|
"private": true,
|
||||||
|
"devDependencies": {
|
||||||
|
"@types/bun": "latest"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"typescript": "^5"
|
||||||
|
}
|
||||||
|
}
|
||||||
29
dev-proxy/tsconfig.json
Normal file
29
dev-proxy/tsconfig.json
Normal file
|
|
@ -0,0 +1,29 @@
|
||||||
|
{
|
||||||
|
"compilerOptions": {
|
||||||
|
// Environment setup & latest features
|
||||||
|
"lib": ["ESNext"],
|
||||||
|
"target": "ESNext",
|
||||||
|
"module": "Preserve",
|
||||||
|
"moduleDetection": "force",
|
||||||
|
"jsx": "react-jsx",
|
||||||
|
"allowJs": true,
|
||||||
|
|
||||||
|
// Bundler mode
|
||||||
|
"moduleResolution": "bundler",
|
||||||
|
"allowImportingTsExtensions": true,
|
||||||
|
"verbatimModuleSyntax": true,
|
||||||
|
"noEmit": true,
|
||||||
|
|
||||||
|
// Best practices
|
||||||
|
"strict": true,
|
||||||
|
"skipLibCheck": true,
|
||||||
|
"noFallthroughCasesInSwitch": true,
|
||||||
|
"noUncheckedIndexedAccess": true,
|
||||||
|
"noImplicitOverride": true,
|
||||||
|
|
||||||
|
// Some stricter flags (disabled by default)
|
||||||
|
"noUnusedLocals": false,
|
||||||
|
"noUnusedParameters": false,
|
||||||
|
"noPropertyAccessFromIndexSignature": false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -3,6 +3,8 @@
|
||||||
|
|
||||||
use arrayvec::ArrayVec;
|
use arrayvec::ArrayVec;
|
||||||
use core::str::FromStr;
|
use core::str::FromStr;
|
||||||
|
use embassy_net::tcp::ConnectError;
|
||||||
|
use embedded_io::ReadReady;
|
||||||
|
|
||||||
use ag_lcd::{Blink, Cursor, Display, LcdDisplay};
|
use ag_lcd::{Blink, Cursor, Display, LcdDisplay};
|
||||||
use as5600::As5600;
|
use as5600::As5600;
|
||||||
|
|
@ -22,7 +24,7 @@ use embassy_rp::{bind_interrupts, dma};
|
||||||
use embassy_rp::{peripherals::USB, usb};
|
use embassy_rp::{peripherals::USB, usb};
|
||||||
use embassy_time::{Delay, Duration, Timer};
|
use embassy_time::{Delay, Duration, Timer};
|
||||||
use static_cell::StaticCell;
|
use static_cell::StaticCell;
|
||||||
use ufmt::uwrite;
|
use ufmt::{uWrite, uwrite};
|
||||||
use {defmt_rtt as _, panic_probe as _};
|
use {defmt_rtt as _, panic_probe as _};
|
||||||
|
|
||||||
bind_interrupts!(struct Irqs {
|
bind_interrupts!(struct Irqs {
|
||||||
|
|
@ -49,7 +51,7 @@ async fn net_task(mut runner: embassy_net::Runner<'static, cyw43::NetDriver<'sta
|
||||||
runner.run().await
|
runner.run().await
|
||||||
}
|
}
|
||||||
|
|
||||||
const WIFI_NETWORK: &str = "flamme";
|
const WIFI_NETWORK: &str = "aura";
|
||||||
const WIFI_PASSWORD: &str = "12345678";
|
const WIFI_PASSWORD: &str = "12345678";
|
||||||
|
|
||||||
#[embassy_executor::main]
|
#[embassy_executor::main]
|
||||||
|
|
@ -105,6 +107,8 @@ async fn main(spawner: Spawner) {
|
||||||
.with_display(Display::On)
|
.with_display(Display::On)
|
||||||
.with_blink(Blink::On)
|
.with_blink(Blink::On)
|
||||||
.with_cursor(Cursor::On)
|
.with_cursor(Cursor::On)
|
||||||
|
.with_lines(ag_lcd::Lines::TwoLines)
|
||||||
|
// .with_autoscroll(ag_lcd::AutoScroll::On)
|
||||||
.build();
|
.build();
|
||||||
lcd.set_cursor(Cursor::Off);
|
lcd.set_cursor(Cursor::Off);
|
||||||
lcd.set_blink(Blink::Off);
|
lcd.set_blink(Blink::Off);
|
||||||
|
|
@ -122,6 +126,8 @@ async fn main(spawner: Spawner) {
|
||||||
rng.next_u64(),
|
rng.next_u64(),
|
||||||
);
|
);
|
||||||
spawner.spawn(unwrap!(net_task(runner)));
|
spawner.spawn(unwrap!(net_task(runner)));
|
||||||
|
uwrite!(lcd, "con.");
|
||||||
|
|
||||||
while let Err(err) = control
|
while let Err(err) = control
|
||||||
.join(WIFI_NETWORK, JoinOptions::new(WIFI_PASSWORD.as_bytes()))
|
.join(WIFI_NETWORK, JoinOptions::new(WIFI_PASSWORD.as_bytes()))
|
||||||
.await
|
.await
|
||||||
|
|
@ -139,11 +145,13 @@ async fn main(spawner: Spawner) {
|
||||||
stack.wait_link_up().await;
|
stack.wait_link_up().await;
|
||||||
|
|
||||||
lcd.clear();
|
lcd.clear();
|
||||||
|
// lcd.home();
|
||||||
uwrite!(lcd, "dhcp.");
|
uwrite!(lcd, "dhcp.");
|
||||||
stack.wait_config_up().await;
|
stack.wait_config_up().await;
|
||||||
let cfg = wait_for_config(stack).await;
|
let cfg = wait_for_config(stack).await;
|
||||||
let local_addr = cfg.address.address();
|
let local_addr = cfg.address.address();
|
||||||
uwrite!(lcd, "IP address: {:?}", local_addr.octets());
|
info!("IP address: {:?}", local_addr);
|
||||||
|
// uwrite!(lcd, "IP address: {:?}", local_addr.octets());
|
||||||
|
|
||||||
let i2c = I2c::new_async(p.I2C0, p.PIN_5, p.PIN_4, Irqs, Config::default());
|
let i2c = I2c::new_async(p.I2C0, p.PIN_5, p.PIN_4, Irqs, Config::default());
|
||||||
let mut as5600 = As5600::new(i2c);
|
let mut as5600 = As5600::new(i2c);
|
||||||
|
|
@ -162,9 +170,23 @@ async fn main(spawner: Spawner) {
|
||||||
|
|
||||||
led.set_low();
|
led.set_low();
|
||||||
info!("Connecting...");
|
info!("Connecting...");
|
||||||
let host_addr = embassy_net::Ipv4Address::from_str("84.238.32.253").unwrap();
|
uwrite!(lcd, "con2.");
|
||||||
|
let host_addr = embassy_net::Ipv4Address::from_str("192.168.12.1").unwrap();
|
||||||
if let Err(e) = socket.connect((host_addr, 7070)).await {
|
if let Err(e) = socket.connect((host_addr, 7070)).await {
|
||||||
|
lcd.clear();
|
||||||
|
uwrite!(lcd, "conerr");
|
||||||
|
Timer::after(Duration::from_micros(100)).await;
|
||||||
|
lcd.set_position(0, 1);
|
||||||
|
let emsg = match e {
|
||||||
|
ConnectError::ConnectionReset => "rst",
|
||||||
|
ConnectError::InvalidState => "inv",
|
||||||
|
ConnectError::TimedOut => "tout",
|
||||||
|
ConnectError::NoRoute => "nroute",
|
||||||
|
};
|
||||||
|
uwrite!(lcd, "{}", emsg);
|
||||||
warn!("connect error: {:?}", e);
|
warn!("connect error: {:?}", e);
|
||||||
|
} else {
|
||||||
|
uwrite!(lcd, "conok");
|
||||||
}
|
}
|
||||||
info!("Connected to {:?}", socket.remote_endpoint());
|
info!("Connected to {:?}", socket.remote_endpoint());
|
||||||
|
|
||||||
|
|
@ -178,7 +200,7 @@ async fn main(spawner: Spawner) {
|
||||||
let angle = as5600.angle().unwrap_or(0);
|
let angle = as5600.angle().unwrap_or(0);
|
||||||
{
|
{
|
||||||
use embedded_io::Write;
|
use embedded_io::Write;
|
||||||
let _ = core::write!(
|
let _ = core::writeln!(
|
||||||
&mut buffer[..],
|
&mut buffer[..],
|
||||||
"in1={} in2={} in3={} in4={} angle={}",
|
"in1={} in2={} in3={} in4={} angle={}",
|
||||||
in1,
|
in1,
|
||||||
|
|
@ -192,6 +214,22 @@ async fn main(spawner: Spawner) {
|
||||||
use embedded_io_async::Write;
|
use embedded_io_async::Write;
|
||||||
let _ = socket.write_all(&*buffer).await;
|
let _ = socket.write_all(&*buffer).await;
|
||||||
}
|
}
|
||||||
|
if socket.read_ready().unwrap_or(false) {
|
||||||
|
let mut rx_buffer = [0; 4096];
|
||||||
|
let n = socket.read(&mut rx_buffer).await.unwrap_or(0);
|
||||||
|
if n > 0 {
|
||||||
|
lcd.clear();
|
||||||
|
lcd.home();
|
||||||
|
let s = core::str::from_utf8(&rx_buffer[..n]).unwrap_or("");
|
||||||
|
let npos = s.find('\n').unwrap_or(n);
|
||||||
|
let display_text = &s[..npos];
|
||||||
|
lcd.write_str(display_text).ok();
|
||||||
|
|
||||||
|
Timer::after(Duration::from_micros(100)).await;
|
||||||
|
lcd.set_position(0, 1);
|
||||||
|
lcd.write_str(&s[npos..]);
|
||||||
|
}
|
||||||
|
}
|
||||||
Timer::after(delay).await;
|
Timer::after(delay).await;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue