aboutsummaryrefslogtreecommitdiff
path: root/examples
diff options
context:
space:
mode:
authordiogo464 <[email protected]>2025-12-04 13:06:27 +0000
committerdiogo464 <[email protected]>2025-12-04 13:06:27 +0000
commit945f38391052773c6b16e54006a434ff7c9f5d98 (patch)
tree1f3360316f7304e26a788582bd488726bd8259d2 /examples
parentb3e47f9c9268e01533a809f83b4f3ecd379c4b22 (diff)
added more examples
Diffstat (limited to 'examples')
-rw-r--r--examples/button.rs38
-rw-r--r--examples/common/mod.rs18
-rw-r--r--examples/common/std_async_tcp.rs125
-rw-r--r--examples/constant-temperature.rs136
-rw-r--r--examples/random-temperature.rs43
5 files changed, 228 insertions, 132 deletions
diff --git a/examples/button.rs b/examples/button.rs
new file mode 100644
index 0000000..cfef3e3
--- /dev/null
+++ b/examples/button.rs
@@ -0,0 +1,38 @@
1mod common;
2
3use common::AsyncTcp;
4use embassy_executor::{Executor, Spawner};
5use static_cell::StaticCell;
6
7static RESOURCES: StaticCell<embassy_ha::DeviceResources> = StaticCell::new();
8
9#[embassy_executor::task]
10async fn main_task(spawner: Spawner) {
11 let mut stream = AsyncTcp::connect(std::env!("MQTT_ADDRESS"));
12
13 let mut device = embassy_ha::Device::new(
14 RESOURCES.init(Default::default()),
15 embassy_ha::DeviceConfig {
16 device_id: "example-device-id",
17 device_name: "Example Device Name",
18 manufacturer: "Example Device Manufacturer",
19 model: "Example Device Model",
20 },
21 );
22
23 let button = device.create_button("button-sensor-id", "Button Name");
24
25 spawner.must_spawn(button_task(button));
26
27 device.run(&mut stream).await;
28}
29
30#[embassy_executor::task]
31async fn button_task(mut button: embassy_ha::Button<'static>) {
32 loop {
33 button.pressed().await;
34 println!("The button has been pressed");
35 }
36}
37
38example_main!();
diff --git a/examples/common/mod.rs b/examples/common/mod.rs
new file mode 100644
index 0000000..fd61e9d
--- /dev/null
+++ b/examples/common/mod.rs
@@ -0,0 +1,18 @@
1mod std_async_tcp;
2use embassy_executor::Executor;
3use static_cell::StaticCell;
4pub use std_async_tcp::AsyncTcp;
5
6pub static EXECUTOR: StaticCell<Executor> = StaticCell::new();
7
8#[macro_export]
9macro_rules! example_main {
10 () => {
11 fn main() {
12 let executor = common::EXECUTOR.init(Executor::new());
13 executor.run(|spawner| {
14 spawner.must_spawn(main_task(spawner));
15 });
16 }
17 };
18}
diff --git a/examples/common/std_async_tcp.rs b/examples/common/std_async_tcp.rs
new file mode 100644
index 0000000..bd97fa9
--- /dev/null
+++ b/examples/common/std_async_tcp.rs
@@ -0,0 +1,125 @@
1use std::{
2 io::{Read, Write},
3 net::{TcpStream, ToSocketAddrs},
4 sync::{Arc, Mutex},
5 thread::JoinHandle,
6};
7
8use embassy_sync::waitqueue::AtomicWaker;
9
10pub struct AsyncTcp {
11 write_handle: JoinHandle<()>,
12 write_buffer: Arc<Mutex<Vec<u8>>>,
13 read_buffer: Arc<Mutex<Vec<u8>>>,
14 waker: Arc<AtomicWaker>,
15}
16
17impl AsyncTcp {
18 pub fn connect(addr: impl ToSocketAddrs) -> Self {
19 let stream = TcpStream::connect(addr).expect("failed to connect to remote");
20 let mut read_stream = stream.try_clone().unwrap();
21 let mut write_stream = stream;
22
23 let read_buffer: Arc<Mutex<Vec<u8>>> = Default::default();
24 let write_buffer: Arc<Mutex<Vec<u8>>> = Default::default();
25
26 let waker = Arc::new(AtomicWaker::new());
27
28 let write_handle = std::thread::spawn({
29 let write_buffer = write_buffer.clone();
30 move || {
31 loop {
32 let buffer = {
33 let mut buffer = write_buffer.lock().unwrap();
34 std::mem::take(&mut *buffer)
35 };
36 if !buffer.is_empty() {
37 println!("writing {} bytes", buffer.len());
38 write_stream.write_all(&buffer).unwrap();
39 write_stream.flush().unwrap();
40 } else {
41 std::thread::park();
42 }
43 }
44 }
45 });
46
47 std::thread::spawn({
48 let read_buffer = read_buffer.clone();
49 let waker = waker.clone();
50 move || {
51 let mut scratch = [0u8; 1024];
52 loop {
53 let n = read_stream.read(&mut scratch).unwrap();
54 if n == 0 {
55 panic!("EOF");
56 }
57
58 {
59 let mut buffer = read_buffer.lock().unwrap();
60 buffer.extend_from_slice(&scratch[..n]);
61 waker.wake();
62 }
63 }
64 }
65 });
66
67 Self {
68 write_handle,
69 write_buffer,
70 read_buffer,
71 waker,
72 }
73 }
74}
75
76impl embedded_io_async::ErrorType for AsyncTcp {
77 type Error = std::io::Error;
78}
79
80impl embedded_io_async::Write for AsyncTcp {
81 async fn write(&mut self, buf: &[u8]) -> Result<usize, Self::Error> {
82 {
83 let mut buffer = self.write_buffer.lock().unwrap();
84 buffer.extend_from_slice(buf);
85 }
86 self.write_handle.thread().unpark();
87 Ok(buf.len())
88 }
89}
90
91impl embedded_io_async::Read for AsyncTcp {
92 async fn read(&mut self, buf: &mut [u8]) -> Result<usize, Self::Error> {
93 struct WaitForWaker<'a>(&'a AtomicWaker, bool);
94
95 impl<'a> Future for WaitForWaker<'a> {
96 type Output = ();
97
98 fn poll(
99 mut self: std::pin::Pin<&mut Self>,
100 cx: &mut std::task::Context<'_>,
101 ) -> std::task::Poll<Self::Output> {
102 if self.1 {
103 std::task::Poll::Ready(())
104 } else {
105 self.as_mut().1 = true;
106 self.0.register(cx.waker());
107 std::task::Poll::Pending
108 }
109 }
110 }
111
112 loop {
113 {
114 let mut buffer = self.read_buffer.lock().unwrap();
115 if !buffer.is_empty() {
116 let copy_n = buf.len().min(buffer.len());
117 buf[..copy_n].copy_from_slice(&buffer[..copy_n]);
118 buffer.drain(..copy_n);
119 return Ok(copy_n);
120 }
121 }
122 WaitForWaker(&self.waker, false).await
123 }
124 }
125}
diff --git a/examples/constant-temperature.rs b/examples/constant-temperature.rs
index 27e1076..fed76e5 100644
--- a/examples/constant-temperature.rs
+++ b/examples/constant-temperature.rs
@@ -1,138 +1,15 @@
1use std::{ 1mod common;
2 io::{Read, Write},
3 net::{TcpStream, ToSocketAddrs},
4 sync::{Arc, Mutex},
5 thread::JoinHandle,
6};
7 2
3use common::AsyncTcp;
8use embassy_executor::{Executor, Spawner}; 4use embassy_executor::{Executor, Spawner};
9use embassy_sync::waitqueue::AtomicWaker;
10use embassy_time::Timer; 5use embassy_time::Timer;
11use static_cell::StaticCell; 6use static_cell::StaticCell;
12 7
13static EXECUTOR: StaticCell<Executor> = StaticCell::new();
14static RESOURCES: StaticCell<embassy_ha::DeviceResources> = StaticCell::new(); 8static RESOURCES: StaticCell<embassy_ha::DeviceResources> = StaticCell::new();
15 9
16struct AsyncTcp {
17 write_handle: JoinHandle<()>,
18 write_buffer: Arc<Mutex<Vec<u8>>>,
19 read_buffer: Arc<Mutex<Vec<u8>>>,
20 waker: Arc<AtomicWaker>,
21}
22
23impl AsyncTcp {
24 fn connect(addr: impl ToSocketAddrs) -> Self {
25 let stream = TcpStream::connect(addr).expect("failed to connect to remote");
26 let mut read_stream = stream.try_clone().unwrap();
27 let mut write_stream = stream;
28
29 let read_buffer: Arc<Mutex<Vec<u8>>> = Default::default();
30 let write_buffer: Arc<Mutex<Vec<u8>>> = Default::default();
31
32 let waker = Arc::new(AtomicWaker::new());
33
34 let write_handle = std::thread::spawn({
35 let write_buffer = write_buffer.clone();
36 move || {
37 loop {
38 let buffer = {
39 let mut buffer = write_buffer.lock().unwrap();
40 std::mem::take(&mut *buffer)
41 };
42 if !buffer.is_empty() {
43 println!("writing {} bytes", buffer.len());
44 write_stream.write_all(&buffer).unwrap();
45 write_stream.flush().unwrap();
46 } else {
47 std::thread::park();
48 }
49 }
50 }
51 });
52
53 std::thread::spawn({
54 let read_buffer = read_buffer.clone();
55 let waker = waker.clone();
56 move || {
57 let mut scratch = [0u8; 1024];
58 loop {
59 let n = read_stream.read(&mut scratch).unwrap();
60 if n == 0 {
61 panic!("EOF");
62 }
63
64 {
65 let mut buffer = read_buffer.lock().unwrap();
66 buffer.extend_from_slice(&scratch[..n]);
67 waker.wake();
68 }
69 }
70 }
71 });
72
73 Self {
74 write_handle,
75 write_buffer,
76 read_buffer,
77 waker,
78 }
79 }
80}
81
82impl embedded_io_async::ErrorType for AsyncTcp {
83 type Error = std::io::Error;
84}
85
86impl embedded_io_async::Write for AsyncTcp {
87 async fn write(&mut self, buf: &[u8]) -> Result<usize, Self::Error> {
88 {
89 let mut buffer = self.write_buffer.lock().unwrap();
90 buffer.extend_from_slice(buf);
91 }
92 self.write_handle.thread().unpark();
93 Ok(buf.len())
94 }
95}
96
97impl embedded_io_async::Read for AsyncTcp {
98 async fn read(&mut self, buf: &mut [u8]) -> Result<usize, Self::Error> {
99 struct WaitForWaker<'a>(&'a AtomicWaker, bool);
100
101 impl<'a> Future for WaitForWaker<'a> {
102 type Output = ();
103
104 fn poll(
105 mut self: std::pin::Pin<&mut Self>,
106 cx: &mut std::task::Context<'_>,
107 ) -> std::task::Poll<Self::Output> {
108 if self.1 {
109 std::task::Poll::Ready(())
110 } else {
111 self.as_mut().1 = true;
112 self.0.register(cx.waker());
113 std::task::Poll::Pending
114 }
115 }
116 }
117
118 loop {
119 {
120 let mut buffer = self.read_buffer.lock().unwrap();
121 if !buffer.is_empty() {
122 let copy_n = buf.len().min(buffer.len());
123 buf[..copy_n].copy_from_slice(&buffer[..copy_n]);
124 buffer.drain(..copy_n);
125 return Ok(copy_n);
126 }
127 }
128 WaitForWaker(&self.waker, false).await
129 }
130 }
131}
132
133#[embassy_executor::task] 10#[embassy_executor::task]
134async fn main_task(spawner: Spawner) { 11async fn main_task(spawner: Spawner) {
135 let mut stream = AsyncTcp::connect("mqtt.d464.sh:1883"); 12 let mut stream = AsyncTcp::connect(std::env!("MQTT_ADDRESS"));
136 13
137 let mut device = embassy_ha::Device::new( 14 let mut device = embassy_ha::Device::new(
138 RESOURCES.init(Default::default()), 15 RESOURCES.init(Default::default()),
@@ -163,9 +40,4 @@ async fn temperature(mut sensor: embassy_ha::TemperatureSensor<'static>) {
163 } 40 }
164} 41}
165 42
166fn main() { 43example_main!();
167 let executor = EXECUTOR.init(Executor::new());
168 executor.run(|spawner| {
169 spawner.must_spawn(main_task(spawner));
170 });
171}
diff --git a/examples/random-temperature.rs b/examples/random-temperature.rs
new file mode 100644
index 0000000..2bcae57
--- /dev/null
+++ b/examples/random-temperature.rs
@@ -0,0 +1,43 @@
1mod common;
2
3use common::AsyncTcp;
4use embassy_executor::{Executor, Spawner};
5use embassy_time::Timer;
6use static_cell::StaticCell;
7
8static RESOURCES: StaticCell<embassy_ha::DeviceResources> = StaticCell::new();
9
10#[embassy_executor::task]
11async fn main_task(spawner: Spawner) {
12 let mut stream = AsyncTcp::connect(std::env!("MQTT_ADDRESS"));
13
14 let mut device = embassy_ha::Device::new(
15 RESOURCES.init(Default::default()),
16 embassy_ha::DeviceConfig {
17 device_id: "example-device-id",
18 device_name: "Example Device Name",
19 manufacturer: "Example Device Manufacturer",
20 model: "Example Device Model",
21 },
22 );
23
24 let temperature_sensor = device.create_temperature_sensor(
25 "temperature-sensor-id",
26 "Temperature Sensor Name",
27 embassy_ha::TemperatureUnit::Celcius,
28 );
29
30 spawner.must_spawn(temperature(temperature_sensor));
31
32 device.run(&mut stream).await;
33}
34
35#[embassy_executor::task]
36async fn temperature(mut sensor: embassy_ha::TemperatureSensor<'static>) {
37 loop {
38 sensor.publish(rand::random_range(0.0..50.0));
39 Timer::after_secs(1).await;
40 }
41}
42
43example_main!();