1use core::net::IpAddr;
2
3use bevy::{
4 app::{Plugin, Update},
5 ecs::{
6 component::Component,
7 entity::Entity,
8 lifecycle::HookContext,
9 name::Name,
10 resource::Resource,
11 system::{Commands, Res, ResMut},
12 world::DeferredWorld,
13 },
14 prelude::Deref,
15};
16use rapidhash::RapidHashSet;
17
18use crate::net::DiscoverResponse;
19
20#[derive(Debug, Resource, Default)]
21pub struct UniqueDevices(pub RapidHashSet<DeviceSocket>);
22
23#[derive(Debug, Component)]
24pub struct Device;
25
26#[derive(Debug, Clone, Component, Hash, PartialEq, Eq)]
27#[component(immutable, on_remove = on_remove_device)]
28pub struct DeviceSocket {
29 pub address: String,
30 pub port: u16,
31 pub ip: IpAddr,
32}
33
34#[derive(Debug, Component, Default, Clone, Copy)]
35pub struct DeviceDetector {
36 pub blip_threshold: usize,
37 pub blip_size: usize,
38 pub max_duty: u16,
39 pub duty: u16,
40}
41
42fn on_remove_device(mut world: DeferredWorld, context: HookContext) {
43 let component = world
44 .entity(context.entity)
45 .get::<DeviceSocket>()
46 .cloned()
47 .unwrap();
48 let mut devices = world.resource_mut::<UniqueDevices>();
49
50 devices.0.remove(&component);
51}
52
53#[derive(Debug, Component)]
54#[component(immutable)]
55pub struct StormLevel(pub u16);
56
57#[derive(Debug, Component, Deref)]
58#[component(immutable)]
59pub struct Timestamp(pub jiff::Timestamp);
60
61impl Timestamp {
62 pub fn from_seconds(stamp: i64) -> Result<Self, jiff::Error> {
63 jiff::Timestamp::from_second(stamp).map(Self)
64 }
65
66 pub fn from_microseconds(stamp: i64) -> Result<Self, jiff::Error> {
67 jiff::Timestamp::from_microsecond(stamp).map(Self)
68 }
69}
70
71#[derive(Debug, Component, Deref)]
72#[component(immutable)]
73pub struct StormSignal(Vec<i16>);
74
75impl StormSignal {
76 pub fn new(value: Vec<i16>) -> Self {
77 Self(value)
78 }
79}
80
81#[derive(Debug, Component, Deref)]
82#[component(immutable)]
83pub struct SignalAverage(pub u16);
84
85impl SignalAverage {
86 pub fn new(value: u16) -> Self {
87 Self(value)
88 }
89}
90
91#[derive(Debug, Component, Deref)]
92#[component(immutable)]
93pub struct SignalPeaks(Vec<u16>);
94
95impl SignalPeaks {
96 pub fn new(value: Vec<u16>) -> Self {
97 Self(value)
98 }
99}
100
101#[derive(Debug, Component)]
102#[relationship(relationship_target = Signals)]
103pub struct SignalSource(pub Entity);
104
105#[derive(Component, Debug, Deref)]
106#[relationship_target(relationship = SignalSource, linked_spawn)]
107pub struct Signals {
108 signals: Vec<Entity>,
109}
110
111#[derive(Debug, Component)]
112#[relationship(relationship_target = StormLevels)]
113pub struct StormSource(pub Entity);
114
115#[derive(Component, Debug, Deref)]
116#[relationship_target(relationship = StormSource, linked_spawn)]
117pub struct StormLevels {
118 levels: Vec<Entity>,
119}
120
121#[derive(Debug)]
122pub enum ConnectionState {
123 Disconnected,
124 Connecting,
125 Connected,
126}
127
128impl core::fmt::Display for ConnectionState {
129 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
130 match self {
131 Self::Disconnected => write!(f, "Disconnected"),
132 Self::Connecting => write!(f, "Connecting"),
133 Self::Connected => write!(f, "Connected"),
134 }
135 }
136}
137
138#[derive(Debug, Resource)]
139pub struct ConnectedDevice {
140 pub device: Entity,
141 pub connection_state: ConnectionState,
142}
143
144fn register_devices(
145 incoming: Res<DiscoverResponse>,
146 mut unique: ResMut<UniqueDevices>,
147 mut commands: Commands,
148) {
149 let mut devices = Vec::new();
150
151 while let Ok(discovered) = incoming.0.try_recv() {
152 let device_addr = DeviceSocket {
153 address: discovered.address,
154 port: discovered.port,
155 ip: discovered.ip,
156 };
157
158 if !unique.0.contains(&device_addr) {
159 unique.0.insert(device_addr.clone());
160 devices.push((Device, Name::new(discovered.host), device_addr));
161 }
162 }
163
164 if !devices.is_empty() {
165 commands.spawn_batch(devices);
166 }
167}
168
169#[derive(Debug)]
170pub struct DevicePlugin;
171
172impl Plugin for DevicePlugin {
173 fn build(&self, app: &mut bevy::app::App) {
174 app.init_resource::<UniqueDevices>()
175 .add_systems(Update, register_devices);
176 }
177}