From 4dd80e53fd93174e6b4547a469020267b96cd670 Mon Sep 17 00:00:00 2001 From: Daniel Bulant Date: Tue, 5 May 2026 23:19:31 +0200 Subject: [PATCH] continued integration --- dev-proxy/index.ts | 108 +++++++++++++++++++++++++-------------------- pico/Cargo.lock | 7 +++ pico/Cargo.toml | 1 + pico/src/main.rs | 92 ++++++++++++++++++++++++++++++++++++-- 4 files changed, 158 insertions(+), 50 deletions(-) diff --git a/dev-proxy/index.ts b/dev-proxy/index.ts index 46c3c46..cc50584 100644 --- a/dev-proxy/index.ts +++ b/dev-proxy/index.ts @@ -1,56 +1,70 @@ -import type { - PartySocketEvent, - PartyState, -} from "../api/src/party-types"; +import type { Socket } from "bun"; +import type { PartySocketEvent, PartyState } from "../api/src/party-types"; -let last_ep_port: null|number = null -let last_ep_addr: null|string = null +const sockets = new Set(); +let lastData: string; -const socket = await Bun.udpSocket({ - port: 7070, - socket: { - data(socket, buf, port, addr) { - // console.log(`message from ${addr}:${port}:`); - last_ep_addr = addr - last_ep_port = port - const str = buf.toString(); - console.log(str); - const opts = str.split(" ").map(t => t.trim().split("=")) - const parsedOpts = Object.fromEntries(opts) - const { in1, in2, in3, in4, angle } = parsedOpts - }, - }, +const socket = Bun.listen({ + port: 7070, + hostname: "0.0.0.0", + socket: { + data(socket, buf) { + const str = new TextDecoder().decode(buf); + }, + open(socket) { + sockets.add(socket); + if (lastData) socket.write(lastData); + }, + close(socket) { + sockets.delete(socket); + }, + }, }); +const ws: WebSocket | null = new WebSocket( + "ws://localhost:4000/api/dev-socket/ws", +); -let ws: WebSocket | null = new WebSocket("ws://localhost:4000/api/dev-socket/ws"); - -ws.onerror = e => { - console.error(e) -} +ws.onerror = (e) => { + console.error(e); +}; ws.onopen = () => { - console.log("WebSocket open") -} + console.log("WebSocket open"); +}; -ws.onmessage = e => { - const data = JSON.parse(e.data) as PartySocketEvent; - console.log(data) - switch (data.type) { - case "party_status": - const { party } = data; - if (!party) return; - const partyData = party.data; - if (!partyData) return; - const { currentQuestion } = partyData - console.log(currentQuestion) - let text = currentQuestion?.text - if (text && last_ep_port !== null && last_ep_addr !== null) { - socket.send(text, last_ep_port, last_ep_addr) - // ws?.send(text) - } - break; - } -} +ws.onmessage = (e) => { + const data = JSON.parse(e.data) as PartySocketEvent; + console.log(data); + switch (data.type) { + case "party_status": { + const { party } = data; + if (!party) return; + const partyData = party.data; + if (!partyData) return; + const { currentQuestion } = partyData; + console.log(currentQuestion); + const text = currentQuestion?.text; + if (!text) return; + const obj = { + type: currentQuestion.type, + points: currentQuestion.points, + } as Record; + if (currentQuestion.type === "numeric") { + obj.rangeMin = currentQuestion.range.min; + obj.rangeMax = currentQuestion.range.max; + } + const objText = Object.entries(obj) + .map(([k, v]) => `${k}=${v}`) + .join(" "); + const writeData = `$$\n${objText}\n${text}\n`; + lastData = writeData; + for (const socket of sockets) { + socket.write(writeData); + } + break; + } + } +}; -console.log("Started on :7070") +console.log("Started on :7070"); diff --git a/pico/Cargo.lock b/pico/Cargo.lock index 25f69d2..3c9e56d 100644 --- a/pico/Cargo.lock +++ b/pico/Cargo.lock @@ -1259,6 +1259,12 @@ version = "1.21.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" +[[package]] +name = "owned_str" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57b42c259c35d8ad3e87b6dbedd4818b7b54a112f6370fdf11cd45d2f355d0f4" + [[package]] name = "panic-probe" version = "1.0.0" @@ -1342,6 +1348,7 @@ dependencies = [ "embedded-io 0.7.1", "embedded-io-async 0.7.0", "log", + "owned_str", "panic-probe", "portable-atomic", "static_cell", diff --git a/pico/Cargo.toml b/pico/Cargo.toml index 2924702..be339de 100644 --- a/pico/Cargo.toml +++ b/pico/Cargo.toml @@ -14,6 +14,7 @@ as5600 = "0.8.0" embassy-futures = "0.1.2" embedded-io-async = "0.7.0" embedded-io = "0.7.1" +owned_str = "0.1.2" embassy-sync = "0.8.0" arrayvec = { version = "0.7.6", default-features = false } embassy-net = { version = "0.9.1",features = ["defmt", "icmp", "tcp", "udp", "raw", "dhcpv4", "medium-ethernet", "dns", "proto-ipv4", "proto-ipv6", "multicast"]} diff --git a/pico/src/main.rs b/pico/src/main.rs index c10dfb9..0cbb723 100644 --- a/pico/src/main.rs +++ b/pico/src/main.rs @@ -9,6 +9,8 @@ use embassy_rp::multicore::{Stack, spawn_core1}; use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex; use embassy_sync::channel::Channel; use embassy_sync::mutex::Mutex; +use embedded_io::Write; +use owned_str::OwnedStr; use crate::buffer::{WriteBuffer, wait_for_config}; use crate::screen::{SCREEN_BUFFER, lcd_display_task}; @@ -198,14 +200,98 @@ async fn network_setup_task( uwrite!(SCREEN_BUFFER.lock().await.line1(), "tcpok"); } - let (mut read, mut write) = socket.split(); + let (read, write) = socket.split(); join(tcp_read_loop(read), tcp_write_loop(write)).await; } -async fn tcp_read_loop(read: TcpReader<'_>) {} +enum QuestionType { + Choice, + Numeric { min: i32, max: i32 }, +} -async fn tcp_write_loop(write: TcpWriter<'_>) {} +struct QuestionData { + text: OwnedStr<256>, + q_type: QuestionType, + points: i32, +} + +async fn tcp_read_loop(mut read: TcpReader<'_>) { + let mut buf = [0u8; 1024]; + + while let Ok(len) = read.read(&mut buf).await { + if len == 0 { + continue; + } + let Ok(str) = str::from_utf8(&buf[..len]) else { + continue; + }; + let mut counter = 0; + let mut question_data = None; + for line in str.lines() { + if line == "$$" { + counter = 1; + continue; + } + if counter == 1 { + let mut q_type = QuestionType::Choice; + let mut points = -1; + + for pairs in line.split(" ") { + let (key, value) = pairs.split_once("=").unwrap(); + if key == "type" { + q_type = if value == "choice" { + QuestionType::Choice + } else { + QuestionType::Numeric { min: -1, max: -1 } + }; + } + if key == "points" { + points = value.parse().unwrap(); + } + if key == "rangeMin" || key == "rangeMax" { + match q_type { + QuestionType::Choice => {} + QuestionType::Numeric { + ref mut min, + ref mut max, + } => { + if key == "rangeMin" { + *min = value.parse().unwrap(); + } else { + *max = value.parse().unwrap(); + } + } + } + } + } + + question_data = Some(QuestionData { + text: OwnedStr::new(), + q_type, + points, + }); + counter = 2; + continue; + } + if counter == 2 { + question_data.as_mut().unwrap().text = OwnedStr::from_str(line).unwrap(); + counter = 0; + } + } + } +} + +async fn tcp_write_loop(mut write: TcpWriter<'_>) { + let mut buffer = WriteBuffer::<256>::new(); + loop { + let data = INPUT.receive().await; + let angle = *ANGLE.lock().await; + core::writeln!(buffer, "button={} angle={}", data, angle).ok(); + write.write(&*buffer).await.ok(); + buffer.clear(); + } +} static mut CORE1_STACK: Stack<4096> = Stack::new(); static EXECUTOR0: StaticCell = StaticCell::new();