Compare commits

...

4 commits

Author SHA1 Message Date
33ae160566 RustyLee Cleans up code formatting
Removes unnecessary line breaks and comments, improving code readability and consistency.
Consolidates multi-line function signatures and variable declarations into single lines.
2026-03-14 09:44:17 +00:00
8195a3ccad RustyLee: Adds organ lifecycle state tracking
Introduces a `last_reported_state` field to `OrganSocket` for better management of each organ's lifecycle status.

Updates `OrganSocket` and `Heart` constructors to accept an initial `LifeState`, allowing for more flexible initialization. The `OrganFactory` is adjusted to pass this state during organ creation.

This change provides a centralized mechanism for monitoring the state of all spawned organs.
2026-03-14 09:41:06 +00:00
175e01e361 RustyLee: Adds organ ID to brain messages
Includes a unique identifier for the sending organ in `BrainMessage`.
Enables the Brain to differentiate and respond appropriately to messages from various organs.
Refactors `Brain` method for clearer communication flow.
2026-03-14 09:14:45 +00:00
6bf5809ed8 RustyLee: Implements initial system wake-up protocol
The Brain now broadcasts a 'Waken' command to all connected organs during its startup phase. Organs, like the Heart, transition to an 'Awake' state upon receiving this command and provide feedback. The Brain then updates its own 'LifeState' to 'Awake' once organs acknowledge the wake-up.

This change establishes a fundamental handshake, ensuring that core system functions only activate once the components are initialized and responsive. It introduces the `LifeState::Awake` and `OrganCommand::Waken` states for this purpose.
2026-03-14 09:04:42 +00:00
6 changed files with 68 additions and 36 deletions

View file

@ -36,6 +36,8 @@ impl Brain {
} }
fn execute_brain_loop(&mut self) { fn execute_brain_loop(&mut self) {
self.broadcast_to_organs(OrganCommand::Waken);
loop { loop {
while let Ok(command) = self.divine_rx.try_recv() { while let Ok(command) = self.divine_rx.try_recv() {
self.handle_divine_command(command) self.handle_divine_command(command)
@ -50,7 +52,7 @@ impl Brain {
} }
while let Ok(message) = self.organ_rx.try_recv() { while let Ok(message) = self.organ_rx.try_recv() {
self.process_message_from_organ(message);
} }
self.rest(); self.rest();
@ -133,10 +135,29 @@ impl Brain {
} }
} }
fn broadcast_to_organs(&self, command: OrganCommand) {
for OrganSocket { tx, id,.. } in &self.organ_sockets {
let envelope = OrganCommandEnvelope{
command: command.clone(),
issued_at: Time::time_stamp_millis(),
};
debug!("sending command to organ {:?}.", id);
_ = tx.send(envelope);
}
}
fn is_ready(&self) -> bool { fn is_ready(&self) -> bool {
self.state != LifeState::Dead && self.state != LifeState::Dead &&
self.state != Genisys && self.state != Genisys &&
self.state != Buried self.state != Buried
} }
fn process_message_from_organ(&mut self, message: BrainMessage) {
debug!("organ message received: {:?}.", message);
if let OrganCommand::Waken = message.organ_command.command {
self.state = LifeState::Awake;
}
}
} }

View file

@ -7,7 +7,7 @@ pub enum LifeState {
Genisys, Genisys,
// Sleeping, // Sleeping,
// Wakening, // Wakening,
// Awake, Awake,
// DeepThought, // DeepThought,
// ActionFocused, // ActionFocused,
// Flight, // Flight,
@ -23,7 +23,7 @@ impl fmt::Display for LifeState {
LifeState::Genisys => "In Genesis", LifeState::Genisys => "In Genesis",
// LifeState::Sleeping => "Sleeping", // LifeState::Sleeping => "Sleeping",
// LifeState::Wakening => "Wakening", // LifeState::Wakening => "Wakening",
// LifeState::Awake => "Fully Awake", LifeState::Awake => "Fully Awake",
// LifeState::DeepThought => "In Deep Thought", // LifeState::DeepThought => "In Deep Thought",
// LifeState::ActionFocused => "Action Focused", // LifeState::ActionFocused => "Action Focused",
// LifeState::Flight => "In Flight", // LifeState::Flight => "In Flight",

View file

@ -1,6 +1,7 @@
use std::sync::mpsc; use std::sync::mpsc;
use std::sync::mpsc::{Receiver, Sender}; use std::sync::mpsc::{Receiver, Sender};
use tracing::{debug, info, instrument}; use tracing::{debug, info, instrument};
use crate::lifecycle::LifeState;
use crate::protocols::{BrainMessage, OrganCommand, OrganCommandEnvelope, OrganResponse}; use crate::protocols::{BrainMessage, OrganCommand, OrganCommandEnvelope, OrganResponse};
use crate::system::time::Time; use crate::system::time::Time;
@ -10,16 +11,18 @@ pub struct Heart {
feedback_to_brain_tx: mpsc::Sender<BrainMessage>, feedback_to_brain_tx: mpsc::Sender<BrainMessage>,
last_beat_time: u64, last_beat_time: u64,
timestamp: u64, timestamp: u64,
life_state: LifeState,
} }
impl Heart { impl Heart {
pub(crate) fn new(id: u32, rx: Receiver<OrganCommandEnvelope>, tx: Sender<BrainMessage>) -> Self { pub(crate) fn new(id: u32, initial_life_state: LifeState, rx: Receiver<OrganCommandEnvelope>, tx: Sender<BrainMessage>) -> Self {
Self { Self {
id, id,
brain_command_rx: rx, brain_command_rx: rx,
feedback_to_brain_tx: tx, feedback_to_brain_tx: tx,
last_beat_time: 0, last_beat_time: 0,
timestamp: 0, timestamp: 0,
life_state: initial_life_state,
} }
} }
@ -32,36 +35,48 @@ impl Heart {
debug!("Received brain command: {:?}", envelope); debug!("Received brain command: {:?}", envelope);
match envelope.command { match envelope.command {
OrganCommand::Waken => {
self.wake_up(envelope);
}
OrganCommand::Beat(_) => { OrganCommand::Beat(_) => {
if self.ready_to_beat() { if self.ready_to_beat() {
self.beat(); self.beat(envelope);
} }
} }
_ => { _ => {
self.send_response_brain(envelope, OrganResponse::Ignored)
} }
} }
let response = OrganResponse::Ok;
self.send_response_brain(envelope, response);
} }
} }
fn ready_to_beat(&self) -> bool { fn ready_to_beat(&self) -> bool {
self.timestamp >= self.last_beat_time + 500 self.is_ready_state() && self.timestamp >= self.last_beat_time + 500
} }
fn beat(&mut self) { fn is_ready_state(&self) -> bool {
self.life_state == LifeState::Awake
}
fn beat(&mut self, command_envelope: OrganCommandEnvelope) {
self.last_beat_time = self.timestamp; self.last_beat_time = self.timestamp;
info!("Beat time: {}", self.last_beat_time); debug!("Beat time: {}", self.last_beat_time);
self.send_response_brain(command_envelope, OrganResponse::Ok);
} }
fn send_response_brain(&self, envelope: OrganCommandEnvelope, response: OrganResponse) { fn wake_up(&mut self, command_envelope: OrganCommandEnvelope) {
self.life_state = LifeState::Awake;
debug!("Awake");
self.send_response_brain(command_envelope, OrganResponse::Ok);
}
fn send_response_brain(&self, command_envelope: OrganCommandEnvelope, response: OrganResponse) {
let reply = BrainMessage { let reply = BrainMessage {
organ_command: envelope, organ_command: command_envelope,
responded_at: self.timestamp, responded_at: Time::time_stamp_millis(),
organ_id: self.id,
response, response,
}; };

View file

@ -1,5 +1,6 @@
use std::sync::mpsc::{self, Receiver, Sender}; use std::sync::mpsc::{self, Receiver, Sender};
use std::thread; use std::thread;
use crate::lifecycle::LifeState;
use crate::organs::organ_socket::OrganSocket; use crate::organs::organ_socket::OrganSocket;
use crate::organs::heart::Heart; // Assuming Heart is our first organ use crate::organs::heart::Heart; // Assuming Heart is our first organ
use crate::protocols::{OrganCommandEnvelope, BrainMessage}; use crate::protocols::{OrganCommandEnvelope, BrainMessage};
@ -17,19 +18,11 @@ impl OrganFactory {
} }
impl OrganFactory { impl OrganFactory {
pub fn build_organs( pub fn build_organs(brain_tx: Sender<BrainMessage>) -> Vec<OrganSocket> {
// The Brain's "Inbox" mouth - we'll clone this for each organ
brain_tx: Sender<BrainMessage>
) -> Vec<OrganSocket> {
let mut sockets = Vec::new(); let mut sockets = Vec::new();
let mut ids = 1..;
// Let's spawn a Heart as an example (ID: 1) sockets.push(Self::spawn_heart(ids.next().unwrap(), brain_tx.clone()));
// In a real factory, you might loop through a config list here
let heart_socket = Self::spawn_heart(1, brain_tx.clone());
sockets.push(heart_socket);
// Add more organs here...
// let lung_socket = Self::spawn_lung(2, brain_tx.clone());
tracing::info!(count = sockets.len(), "Organ collection built and threads spawned"); tracing::info!(count = sockets.len(), "Organ collection built and threads spawned");
@ -37,13 +30,12 @@ impl OrganFactory {
} }
fn spawn_heart(id: u32, feedback_to_brain_tx: Sender<BrainMessage>) -> OrganSocket { fn spawn_heart(id: u32, feedback_to_brain_tx: Sender<BrainMessage>) -> OrganSocket {
let (brain_command_to_organ_tx, brain_command_to_organ_rx) = let initial_life_state = LifeState::Dead;
Self::get_organ_channels(); let (brain_command_to_organ_tx, brain_command_to_organ_rx) = Self::get_organ_channels();
let socket = OrganSocket::new(id, initial_life_state, brain_command_to_organ_tx);
let socket = OrganSocket::new(id, brain_command_to_organ_tx);
thread::spawn(move || { thread::spawn(move || {
let mut heart = Heart::new(id, brain_command_to_organ_rx, feedback_to_brain_tx); let mut heart = Heart::new(id, initial_life_state, brain_command_to_organ_rx, feedback_to_brain_tx);
heart.start(); heart.start();
}); });

View file

@ -1,15 +1,17 @@
use std::time::{SystemTime, UNIX_EPOCH}; use std::time::{SystemTime, UNIX_EPOCH};
use std::sync::mpsc::Sender; use std::sync::mpsc::Sender;
use crate::lifecycle::LifeState;
use crate::protocols::{OrganCommand, OrganCommandEnvelope}; use crate::protocols::{OrganCommand, OrganCommandEnvelope};
pub struct OrganSocket { pub struct OrganSocket {
pub id: u32, pub id: u32,
pub last_reported_state : LifeState,
pub tx: Sender<OrganCommandEnvelope>, pub tx: Sender<OrganCommandEnvelope>,
} }
impl OrganSocket { impl OrganSocket {
pub fn new(id: u32, tx: Sender<OrganCommandEnvelope>) -> Self { pub fn new(id: u32, initial_state: LifeState, tx: Sender<OrganCommandEnvelope>) -> Self {
Self { id, tx } Self { id, tx, last_reported_state: initial_state }
} }
pub fn send(&self, command: OrganCommand) { pub fn send(&self, command: OrganCommand) {

View file

@ -1,9 +1,9 @@
use crate::coordinates::Point3D; use crate::coordinates::Point3D;
#[derive(Debug)] #[derive(Debug, Clone)]
pub enum OrganCommand { pub enum OrganCommand {
// Sleep, // Sleep,
// Waken, Waken,
// Pause, // Pause,
// Resume, // Resume,
Beat (u32), Beat (u32),
@ -19,6 +19,7 @@ pub enum OrganCommand {
#[derive(Debug)] #[derive(Debug)]
pub enum OrganResponse { pub enum OrganResponse {
Ok, Ok,
Ignored,
Rejected Rejected
} }
@ -32,5 +33,6 @@ pub struct OrganCommandEnvelope {
pub struct BrainMessage { pub struct BrainMessage {
pub organ_command: OrganCommandEnvelope, pub organ_command: OrganCommandEnvelope,
pub responded_at: u64, pub responded_at: u64,
pub organ_id: u32,
pub response: OrganResponse, pub response: OrganResponse,
} }