diff --git a/src/RobotNode/.run/Dixon-Attach.run.xml b/src/RobotNode/.run/Dixon-Attach.run.xml
new file mode 100644
index 0000000..af036a6
--- /dev/null
+++ b/src/RobotNode/.run/Dixon-Attach.run.xml
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/RobotNode/CardioCenter/Heart.cpp b/src/RobotNode/CardioCenter/Heart.cpp
index b0c2bba..7881654 100644
--- a/src/RobotNode/CardioCenter/Heart.cpp
+++ b/src/RobotNode/CardioCenter/Heart.cpp
@@ -1,6 +1,8 @@
#include "Heart.h"
#include
+#include "../DixonNodeState.h"
+
namespace cardio
{
Heart::Heart(const char* chipName, const unsigned int lineOffset)
@@ -13,6 +15,10 @@ namespace cardio
void Heart::beat()
{
+ if (const auto nodeStatus = DixonNodeState::instance().getNodeStatus();
+ nodeStatus == NodeStatus::Stopped || nodeStatus == NodeStatus::Stopping)
+ return;
+
const auto now = std::chrono::steady_clock::now();
if (const auto elapsed = std::chrono::duration_cast
(now - _lastBeat); elapsed.count() >= 500)
@@ -32,11 +38,13 @@ namespace cardio
gpiod::line_request Heart::get_line_request(gpiod::chip& chip, const unsigned int lineOffset)
{
- const auto settings = gpiod::line_settings()
- .set_direction(gpiod::line::direction::OUTPUT);
+ const auto settings = gpiod::line_settings() // Force it to a known state immediately on acquisition
+ .set_output_value(gpiod::line::value::INACTIVE)
+ .set_direction(gpiod::line::direction::OUTPUT);
return chip.prepare_request()
- .add_line_settings(lineOffset, settings)
- .do_request();
+ .set_consumer("dixon-robot")
+ .add_line_settings(lineOffset, settings)
+ .do_request();
}
}
diff --git a/src/RobotNode/DixonBrain.cpp b/src/RobotNode/DixonBrain.cpp
index 0047d32..e05226f 100644
--- a/src/RobotNode/DixonBrain.cpp
+++ b/src/RobotNode/DixonBrain.cpp
@@ -18,10 +18,10 @@ DixonBrain::~DixonBrain()
void DixonBrain::start()
{
- if (state_.isBrainRunning())
+ if (state_.getNodeStatus() != NodeStatus::Stopped)
return;
- state_.setBrainRunning(true);
+ state_.setNodeStatus(NodeStatus::Running);
loopThread_ = std::thread(&DixonBrain::runLoop, this);
@@ -30,22 +30,25 @@ void DixonBrain::start()
void DixonBrain::stop()
{
- if (!state_.isBrainRunning())
+ if (state_.getNodeStatus() == NodeStatus::Stopped)
return;
- state_.setBrainRunning(false);
+ state_.setNodeStatus(NodeStatus::Stopping);
+
if (loopThread_.joinable())
loopThread_.join();
heart_.stop();
+ state_.setNodeStatus(NodeStatus::Stopped);
+
std::cout << "DixonBrain stopped\n";
}
void DixonBrain::runLoop()
{
- while (state_.isBrainRunning())
+ while (state_.getNodeStatus() != NodeStatus::Stopped)
{
heart_.beat();
// TODO: main control logic
diff --git a/src/RobotNode/DixonNodeState.cpp b/src/RobotNode/DixonNodeState.cpp
index 1b50986..4741a7b 100644
--- a/src/RobotNode/DixonNodeState.cpp
+++ b/src/RobotNode/DixonNodeState.cpp
@@ -16,12 +16,12 @@ bool DixonNodeState::isConnected() const
return connected_;
}
-void DixonNodeState::setBrainRunning(bool value)
+void DixonNodeState::setNodeStatus(NodeStatus value)
{
- brainRunning_ = value;
+ node_status_ = value;
}
-bool DixonNodeState::isBrainRunning() const
+NodeStatus DixonNodeState::getNodeStatus() const
{
- return brainRunning_;
-}
\ No newline at end of file
+ return node_status_;
+}
diff --git a/src/RobotNode/DixonNodeState.h b/src/RobotNode/DixonNodeState.h
index c64f598..a686810 100644
--- a/src/RobotNode/DixonNodeState.h
+++ b/src/RobotNode/DixonNodeState.h
@@ -1,16 +1,24 @@
#pragma once
#include
+
+enum class NodeStatus : int {
+ Starting,
+ Running,
+ Stopping,
+ Stopped
+};
+
class DixonNodeState
{
public:
static DixonNodeState& instance();
void setConnected(bool value);
- bool isConnected() const;
+ [[nodiscard]] bool isConnected() const;
- void setBrainRunning(bool value);
- bool isBrainRunning() const;
+ void setNodeStatus(NodeStatus value);
+ [[nodiscard]] NodeStatus getNodeStatus() const;
DixonNodeState(const DixonNodeState&) = delete;
DixonNodeState& operator=(const DixonNodeState&) = delete;
@@ -22,5 +30,5 @@ private:
~DixonNodeState() = default;
std::atomic connected_ = false;
- std::atomic brainRunning_ = false;
+ std::atomic node_status_ = NodeStatus::Stopped;
};
\ No newline at end of file
diff --git a/src/RobotNode/main.cpp b/src/RobotNode/main.cpp
index 094eefa..68c1e69 100644
--- a/src/RobotNode/main.cpp
+++ b/src/RobotNode/main.cpp
@@ -1,25 +1,51 @@
+#include
#include
#include "DixonBrain.h"
-#include "DixonNodeState.h"
#include "Version.h" // The generated header
+
+
+void signal_handler(int signal) {
+ if (signal == SIGINT || signal == SIGTERM) {
+ std::cout << "\nShutdown signal received (" << signal << ")." << std::endl;
+
+ // Use your atomic flag to tell the brain to stop looping
+ DixonNodeState::instance().setNodeStatus(NodeStatus::Stopping);
+ }
+}
+
+
int main()
{
// The "Splash Screen"
std::cout << "Starting Dixon v" << DIXON_VERSION << "...\n";
+ std::signal(SIGINT, signal_handler);
+ std::signal(SIGTERM, signal_handler);
+
// Create the brain controller
DixonBrain brain;
// Start the brain's control loop
brain.start();
- std::cout << "Dixon is running. Press Enter to stop...\n";
- std::cin.get();
+ std::cout << "Dixon is alive...\n";
+ auto count = 1;
+ while (DixonNodeState::instance().getNodeStatus() == NodeStatus::Running)
+ {
+
+ count++;
+ if (count>10)
+ {
+ count = 0;
+ std::cout << "Dixon state is " << static_cast( DixonNodeState::instance().getNodeStatus()) << "\n";
+ }
+ std::this_thread::sleep_for(std::chrono::milliseconds(100));
+
+ }
// Stop the brain cleanly
brain.stop();
-
- std::cout << "Dixon shut down.\n";
+ std::cout << "Dixon has left the building...\n";
return 0;
}
\ No newline at end of file
diff --git a/src/RobotNode/version.txt b/src/RobotNode/version.txt
index 492b167..3f11ef6 100644
--- a/src/RobotNode/version.txt
+++ b/src/RobotNode/version.txt
@@ -1 +1 @@
-1.0.12
\ No newline at end of file
+1.0.27
\ No newline at end of file