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.
This commit is contained in:
Russell Gilbert 2026-03-14 09:04:42 +00:00
parent a353c48d21
commit 6bf5809ed8
4 changed files with 53 additions and 17 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_organ_message(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_organ_message(&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,6 +11,7 @@ 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 {
@ -20,6 +22,7 @@ impl Heart {
feedback_to_brain_tx: tx, feedback_to_brain_tx: tx,
last_beat_time: 0, last_beat_time: 0,
timestamp: 0, timestamp: 0,
life_state: LifeState::Dead,
} }
} }
@ -32,36 +35,47 @@ 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(),
response, response,
}; };

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
} }