-
Notifications
You must be signed in to change notification settings - Fork 5
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Node: Fully working Dispatcher setup + Examples (#52)
Note, I also enforced styling/formatting standards with this PR. We're now using Google Linting standards. ![Code_UsG5SEfEIY](https://github.com/smartuni/teamagochi/assets/25822956/bfa93567-43d9-4666-a603-bb5ce48809b0)
- Loading branch information
Showing
16 changed files
with
1,536 additions
and
1,169 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,27 @@ | ||
## Teamagochi Node | ||
|
||
This is the folder for node (hardware) development. | ||
### Setup | ||
|
||
Make sure you have cloned the repository with the `--recursive` flag to include the submodules. If you haven't, you can run `git submodule update --init --recursive` to get them. | ||
|
||
### Development | ||
|
||
1. Install VSCode | ||
2. Install the C++ extension | ||
3. Open the workspace starting from the root of the repository (Not this folder) to get the correct include paths | ||
1. This is also important for the linter and other settings to work correctly | ||
4. Open a terminal at `node/code` and run `make compile-commands` to generate the compile commands file | ||
1. This helps the C++ extension with intellisense | ||
|
||
### Formatting | ||
|
||
If you followed the development setup instructions, VSCode should automatically format the code based on the Google standards. | ||
Please make sure to follow the Google standards to keep the code consistent. | ||
|
||
### Useful Commands | ||
|
||
- `make compile-commands` - Generate the compile commands file | ||
- `make build` - Build the project | ||
- `make flash` - Flash the project onto the Feather | ||
- `make term` - Open a serial terminal to the Feather | ||
- `make clean` - Clean the build directory |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
#include "dispatcher.hpp" | ||
#include "GLOBALS.hpp" | ||
|
||
Dispatcher::Dispatcher() { | ||
this->subscriptions = list<Subscription>(); | ||
} | ||
|
||
void Dispatcher::subscribe(list<EVENTS> events, kernel_pid_t pid) { | ||
Subscription sub; | ||
sub.event = events; | ||
sub.pid = pid; | ||
|
||
this->subscriptions.push_back(sub); | ||
} | ||
|
||
void Dispatcher::handleEvent(msg_t *event) { | ||
for (Subscription sub : this->subscriptions) { | ||
for (EVENTS e : sub.event) { | ||
if (e == event->type) { | ||
cout << "👀 PID: " << sub.pid << " was interested in event " << event->type << " notifying them" << endl; | ||
|
||
msg_t msg; | ||
msg.content.ptr = event->content.ptr; | ||
msg.content.value = event->content.value; | ||
msg.type = event->type; | ||
|
||
msg_try_send(&msg, sub.pid); | ||
} | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
#pragma once | ||
|
||
#include <cstdint> | ||
|
||
enum EVENTS: uint16_t { | ||
TERMINATE, | ||
WILDCARD, // Subscribe to all events [Special case] | ||
PING, | ||
PONG, | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
/** | ||
* @file GLOBALS.hpp | ||
* @brief Global variables for the project. | ||
* @author AnnsAnn <[email protected]> | ||
*/ | ||
|
||
#pragma once | ||
|
||
#include "thread.h" | ||
|
||
/** | ||
* @brief The dispatcher PID. Used to send events to the dispatcher. | ||
*/ | ||
extern kernel_pid_t DISPATCHER_PID; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,105 @@ | ||
/** | ||
* @brief DispatchHandler is an abstract class that receives events. | ||
* @author Tom <[email protected]> | ||
*/ | ||
#pragma once | ||
|
||
using namespace std; | ||
|
||
#include <iostream> | ||
|
||
#include "msg.h" | ||
#include "GLOBALS.hpp" | ||
#include "EVENTS.hpp" | ||
#include "thread.h" | ||
|
||
/** | ||
* DispatchHandler is an abstract class that receives events. | ||
* @see Dispatcher | ||
* If you want to receive events, you should inherit from this class and | ||
* implement the handleEvent function. handleData is optional, but you should | ||
* implement it if you want to receive data from the heightsensor. | ||
*/ | ||
class DispatchHandler { | ||
private: | ||
/** | ||
* @brief The event queue. | ||
*/ | ||
static const int QUEUE_SIZE = 8; | ||
msg_t rcv_queue[QUEUE_SIZE]; | ||
char internal_thread_stack [THREAD_STACKSIZE_MAIN]; | ||
kernel_pid_t internal_thread_pid; | ||
|
||
public: | ||
/** | ||
* @brief Constructor. | ||
* @details Initializes the event queue and starts the event loop. | ||
*/ | ||
DispatchHandler() { } | ||
|
||
/** | ||
* @brief Send an event to the dispatcher. | ||
* @param event The event to send. | ||
*/ | ||
void sendEvent(msg_t *event) { | ||
if (DISPATCHER_PID == -1) { | ||
cout << "Dispatcher PID not set yet!" << endl; | ||
return; | ||
} | ||
|
||
msg_try_send(event, DISPATCHER_PID); | ||
} | ||
|
||
kernel_pid_t getPID() { return this->internal_thread_pid; } | ||
|
||
/** | ||
* This quirky function does heinous things in order to make riot threads work with C++ classes. | ||
* @warning Warcrimes :3 | ||
*/ | ||
void startInternalThread() { | ||
cout << "Starting internal thread" << endl; | ||
this->internal_thread_pid = thread_create(internal_thread_stack, sizeof(internal_thread_stack), | ||
THREAD_PRIORITY_MAIN - 1, THREAD_CREATE_WOUT_YIELD, internalThreadEntryFunction, this, "DispatchHandler for Class"); | ||
} | ||
|
||
/** | ||
* @brief Starts the event loop. | ||
* @details This function will run forever and call the handleEvent function | ||
* for each event. | ||
*/ | ||
void startHandler() { | ||
msg_init_queue(rcv_queue, QUEUE_SIZE); | ||
|
||
// Event loop - Blocks when no events are available | ||
while (true) { | ||
msg_t message; | ||
msg_receive(&message); | ||
|
||
if (message.type == EVENTS::TERMINATE) { | ||
cout << "Received TERMINATE event, exiting..." << endl; | ||
return; | ||
} | ||
|
||
this->handleEvent(&message); | ||
} | ||
} | ||
|
||
/** | ||
* @brief Handle an event. | ||
* @param event The event to handle. | ||
* @warning Make sure to implement this function in your subclass. | ||
*/ | ||
virtual void handleEvent(msg_t *event) = 0; | ||
|
||
private: | ||
/** | ||
* @brief Internal thread entry function. | ||
* The C++11 thread compat layer doesn't appear to properly support C++ classes | ||
* so we have to do some (really) cursed pthread stuff to make it work. | ||
*/ | ||
static void *internalThreadEntryFunction(void *This) { | ||
((DispatchHandler *)This)->startHandler(); | ||
|
||
return NULL; | ||
} | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
#pragma once | ||
|
||
#include "dispatch_handler.hpp" | ||
#include "EVENTS.hpp" | ||
|
||
#include <list> | ||
|
||
using namespace std; | ||
|
||
struct Subscription { | ||
list<EVENTS> event; | ||
kernel_pid_t pid; | ||
}; | ||
|
||
class Dispatcher : public DispatchHandler { | ||
private: | ||
list<Subscription> subscriptions; | ||
|
||
public: | ||
Dispatcher(); | ||
|
||
/** | ||
* @brief Registers a PID to an event. | ||
* @details This function will register a PID to an event. When the event | ||
* is received, the PID will be sent the event. | ||
* @param events List of events to subscribe to. | ||
* @param pid The PID to send the event to. | ||
*/ | ||
void subscribe(list<EVENTS> events, kernel_pid_t pid); | ||
|
||
/** | ||
* Internally used to send an event to a PID. | ||
*/ | ||
void handleEvent(msg_t *event); | ||
}; |
Oops, something went wrong.