Skip to content

Commit 1821abd

Browse files
committed
Implement CAN BUS collision handling simulation
1 parent e117cb6 commit 1821abd

File tree

6 files changed

+131
-61
lines changed

6 files changed

+131
-61
lines changed
Lines changed: 40 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,43 +1,55 @@
11
#pragma once
22
#include <mutex>
3-
#include <utility>
4-
#include "server_connection.h"
3+
#include <thread>
4+
#include <atomic>
5+
#include "../include/server_connection.h"
56
#include <iostream>
7+
#include "packet.h"
8+
#include "global_clock.h"
69

7-
class BusManager
8-
{
9-
private:
10-
ServerConnection server;
11-
12-
// Singleton instance
13-
static BusManager* instance;
14-
static std::mutex managerMutex;
15-
//SyncCommunication syncCommunication;
16-
17-
// Sending according to broadcast variable
18-
ErrorCode sendToClients(const Packet &packet);
19-
20-
// Private constructor
21-
BusManager(std::vector<uint32_t> idShouldConnect, uint32_t limit);
10+
// Manager class responsible for handling CAN BUS-like communication and collision management
11+
class BusManager {
12+
public:
13+
// Returns the singleton instance of Manager
14+
static BusManager *getInstance(std::vector<uint32_t> idShouldConnect,
15+
uint32_t limit);
2216

23-
public:
24-
//Static function to return a singleton instance
25-
static BusManager* getInstance(std::vector<uint32_t> idShouldConnect, uint32_t limit);
26-
27-
// Sends to the server to listen for requests
17+
// Starts server connection
2818
ErrorCode startConnection();
2919

3020
// Stops server connection
3121
static void stopConnection();
3222

33-
// Receives the packet that arrived and checks it before sending it out
23+
// Receives a packet and checks for collisions before sending
3424
void receiveData(Packet &p);
3525

36-
// Implementation according to the conflict management of the CAN bus protocol
37-
Packet checkCollision(Packet &currentPacket);
26+
// Destructor for cleaning up
27+
~BusManager();
28+
private:
29+
ServerConnection server; // Handles communication with the server
30+
static BusManager *instance; // Singleton instance
31+
static std::mutex managerMutex; // Mutex for singleton
32+
Packet *lastPacket; // Stores the last packet received
33+
std::mutex lastPacketMutex; // Protects access to lastPacket
34+
std::atomic<bool> stopFlag; // Indicates if the collision timer should stop
35+
std::thread collisionTimerThread; // Thread for collision management
36+
37+
// Private constructor to ensure singleton pattern
38+
BusManager(std::vector<uint32_t> idShouldConnect, uint32_t limit);
39+
40+
// Sends packet to clients based on whether it's broadcast or unicast
41+
ErrorCode sendToClients(const Packet &packet);
42+
43+
// Starts the timer to check for packet collisions
44+
void startCollisionTimer();
45+
46+
// Checks if the current packet collides with the last one
47+
void checkCollision(Packet &currentPacket);
48+
49+
// Determines packet priority in case of collision, based on CAN BUS protocol
50+
Packet *packetPriority(Packet &a, Packet &b);
3851

39-
// Implement a priority check according to the CAN bus
40-
Packet packetPriority(Packet &a, Packet &b);
52+
// Sends the last packet if necessary and clears it
53+
void checkLastPacket();
4154

42-
~BusManager();
4355
};

communication/include/client_connection.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
#include "../sockets/real_socket.h"
1313
#include <string>
1414
#include "error_code.h"
15+
#include "../include/global_clock.h"
1516

1617
#define PORT 8080
1718
#define IP "127.0.0.1"

communication/include/communication.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
#pragma once
22
#include <unordered_map>
3+
#include <future>
34
#include "client_connection.h"
45
#include "../sockets/Isocket.h"
56
#include "error_code.h"

communication/src/bus_manager.cpp

Lines changed: 87 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,23 @@
11
#include "../include/bus_manager.h"
22

3-
BusManager* BusManager::instance = nullptr;
3+
// Initialize static instance to nullptr
4+
BusManager *BusManager::instance = nullptr;
45
std::mutex BusManager::managerMutex;
56

6-
//Private constructor
7-
BusManager::BusManager(std::vector<uint32_t> idShouldConnect, uint32_t limit) :server(8080, std::bind(&BusManager::receiveData, this, std::placeholders::_1))//,syncCommunication(idShouldConnect, limit)
7+
// Private constructor: initializes the server and starts the collision timer
8+
BusManager::BusManager(std::vector<uint32_t> idShouldConnect, uint32_t limit)
9+
: server(8080,
10+
std::bind(&BusManager::receiveData, this, std::placeholders::_1)),
11+
lastPacket(nullptr), stopFlag(false)
812
{
9-
// Setup the signal handler for SIGINT
13+
startCollisionTimer(); // Start collision management timer
1014
}
1115

12-
// Static function to return a singleton instance
13-
BusManager* BusManager::getInstance(std::vector<uint32_t> idShouldConnect, uint32_t limit) {
16+
// Singleton getter: ensures only one instance of Manager
17+
BusManager *BusManager::getInstance(std::vector<uint32_t> idShouldConnect,
18+
uint32_t limit)
19+
{
1420
if (instance == nullptr) {
15-
// Lock the mutex to prevent multiple threads from creating instances simultaneously
1621
std::lock_guard<std::mutex> lock(managerMutex);
1722
if (instance == nullptr) {
1823
instance = new BusManager(idShouldConnect, limit);
@@ -21,44 +26,88 @@ BusManager* BusManager::getInstance(std::vector<uint32_t> idShouldConnect, uint3
2126
return instance;
2227
}
2328

24-
// Sends to the server to listen for requests
29+
// Starts the server connection and listens for incoming requests
2530
ErrorCode BusManager::startConnection()
2631
{
27-
28-
ErrorCode isConnected = server.startConnection();
29-
//syncCommunication.notifyProcess()
30-
return isConnected;
32+
return server.startConnection();
3133
}
3234

33-
// Receives the packet that arrived and checks it before sending it out
35+
// Receives a packet, checks for collisions, and sends it if valid
3436
void BusManager::receiveData(Packet &p)
3537
{
36-
ErrorCode res = sendToClients(p);
37-
38-
// Checking the case of collision and priority in functions : checkCollision,packetPriority
39-
// Packet* resolvedPacket = checkCollision(*p);
40-
// if (resolvedPacket)
41-
// server.sendToClients(*resolvedPacket);
38+
checkCollision(p); // Handle packet collisions
4239
}
4340

44-
// Sending according to broadcast variable
41+
// Sends a packet either as broadcast or to a specific destination
4542
ErrorCode BusManager::sendToClients(const Packet &packet)
4643
{
47-
if(packet.getIsBroadcast())
48-
return server.sendBroadcast(packet);
49-
return server.sendDestination(packet);
44+
if (packet.getIsBroadcast()) {
45+
return server.sendBroadcast(packet); // Broadcast message
46+
}
47+
return server.sendDestination(packet); // Send to specific client
5048
}
5149

52-
// Implement according to the conflict management of the CAN bus protocol
53-
Packet BusManager::checkCollision(Packet &currentPacket)
50+
// Manages collisions based on the CAN BUS protocol
51+
void BusManager::checkCollision(Packet &currentPacket)
5452
{
55-
return currentPacket;
53+
std::lock_guard<std::mutex> lock(lastPacketMutex);
54+
if (lastPacket == nullptr) {
55+
// No previous packet, store the current one
56+
lastPacket = new Packet(currentPacket);
57+
if (lastPacket == nullptr) {
58+
}
59+
}
60+
else {
61+
if (lastPacket->getTimestamp() == currentPacket.getTimestamp()) {
62+
// Same timestamp indicates potential collision, check priority
63+
Packet *prioritizedPacket =
64+
packetPriority(*lastPacket, currentPacket);
65+
if (prioritizedPacket == &currentPacket) {
66+
delete lastPacket; // Replace last packet if current packet has priority
67+
lastPacket = new Packet(currentPacket);
68+
}
69+
}
70+
}
5671
}
5772

58-
// Implement a priority check according to the CAN bus
59-
Packet BusManager::packetPriority(Packet &a, Packet &b)
73+
// Determines which packet has higher priority (CAN BUS logic)
74+
Packet *BusManager::packetPriority(Packet &a, Packet &b)
6075
{
61-
return (a.getSrcId() < b.getSrcId()) ? a : b;
76+
if (a.getIsPassive() && !b.getIsPassive()) {
77+
return &b; // Non-passive packet takes priority
78+
}
79+
else if (!a.getIsPassive() && b.getIsPassive()) {
80+
return &a; // Non-passive packet takes priority
81+
}
82+
else {
83+
return (a > b) ? &a
84+
: &b; // If both are the same type, compare based on ID
85+
}
86+
}
87+
88+
// Starts the collision timer to periodically check for packet collisions
89+
void BusManager::startCollisionTimer()
90+
{
91+
stopFlag = false;
92+
collisionTimerThread = std::thread([this]() {
93+
while (!stopFlag) {
94+
GlobalClock::waitForNextTick();
95+
if (!stopFlag) {
96+
checkLastPacket(); // Check and send last packet if necessary
97+
}
98+
}
99+
});
100+
}
101+
102+
// Checks the last packet and sends it if it hasn't been sent yet
103+
void BusManager::checkLastPacket()
104+
{
105+
std::lock_guard<std::mutex> lock(lastPacketMutex);
106+
if (lastPacket != nullptr) {
107+
ErrorCode res = sendToClients(*lastPacket);
108+
delete lastPacket; // Clear last packet after sending
109+
lastPacket = nullptr;
110+
}
62111
}
63112

64113
//shut down the server
@@ -69,6 +118,13 @@ void BusManager::stopConnection()
69118
}
70119
}
71120

72-
BusManager::~BusManager() {
121+
// Destructor: ensures proper cleanup of threads and resources
122+
BusManager::~BusManager()
123+
{
124+
stopFlag = true; // Stop collision timer thread
125+
if (collisionTimerThread.joinable()) {
126+
collisionTimerThread.join();
127+
}
128+
delete lastPacket; // Clean up lastPacket
73129
instance = nullptr;
74-
}
130+
}

communication/src/client_connection.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ ErrorCode ClientConnection::sendPacket(Packet &packet)
4444
//If send executed before start
4545
if (!connected)
4646
return ErrorCode::CONNECTION_FAILED;
47-
47+
packet.setTimestamp(GlobalClock::getCurrentTick());
4848
ssize_t bytesSent = socketInterface->send(clientSocket, &packet, sizeof(Packet), 0);
4949
if (bytesSent==0) {
5050
closeConnection();

communication/src/communication.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
#include "../include/communication.h"
2-
#include <future>
32

43
Communication* Communication::instance = nullptr;
54

@@ -50,6 +49,7 @@ ErrorCode Communication::sendMessage(void *data, size_t dataSize, uint32_t destI
5049
ErrorCode res = client.sendPacket(packet);
5150
if (res != ErrorCode::SUCCESS)
5251
return res;
52+
std::this_thread::sleep_for(std::chrono::seconds(2));
5353
}
5454

5555
return ErrorCode::SUCCESS;

0 commit comments

Comments
 (0)