trainoverlord: switch from train based blocking to tag based blocking
This commit is contained in:
parent
29b887504d
commit
96638d6f8d
@ -4,7 +4,7 @@ set(CMAKE_AUTOUIC ON)
|
||||
set(CMAKE_AUTOMOC ON)
|
||||
set(CMAKE_AUTORCC ON)
|
||||
|
||||
set(CMAKE_CXX_STANDARD 17)
|
||||
set(CMAKE_CXX_STANDARD 20)
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||
|
||||
find_package(QT NAMES Qt6 Qt5 COMPONENTS Widgets Network SerialPort REQUIRED)
|
||||
@ -23,6 +23,7 @@ set(COMMON_SOURCES
|
||||
../common/items/train.h
|
||||
../common/items/turnout.cpp
|
||||
../common/items/turnout.h
|
||||
../common/nfcuid.h
|
||||
)
|
||||
|
||||
include_directories(PRIVATE
|
||||
|
@ -37,10 +37,15 @@ void ItemStore::addItems(const std::vector<std::shared_ptr<Item>>& itemIn)
|
||||
const uint8_t uidBytes[] = {154, 110, 34, 218};
|
||||
train->tags.push_back(NfcUid(uidBytes, sizeof(uidBytes)));
|
||||
}
|
||||
else if(train->getTrainId() == 1)
|
||||
{
|
||||
const uint8_t uidBytes[] = {83, 118, 122, 215};
|
||||
train->tags.push_back(NfcUid(uidBytes, sizeof(uidBytes)));
|
||||
}
|
||||
else if(train->getTrainId() == 3)
|
||||
{
|
||||
const uint8_t uidBytes[] = {136, 83, 111, 26};
|
||||
train->tags.push_back(NfcUid(uidBytes, sizeof(uidBytes)));
|
||||
train->tags.push_back(NfcUid({83, 111, 26, 174}));
|
||||
train->tags.push_back(NfcUid({83, 63, 78, 170}));
|
||||
}
|
||||
else if(train->getTrainId() == 4)
|
||||
{
|
||||
|
@ -44,21 +44,14 @@ void Train::reverse()
|
||||
micro->trainReverse(train_id_);
|
||||
}
|
||||
|
||||
int Train::ownsTag(NfcUid uid)
|
||||
bool Train::ownsTag(NfcUid uid)
|
||||
{
|
||||
for(size_t i = 0; i < tags.size(); ++i)
|
||||
{
|
||||
if(uid == tags[i])
|
||||
{
|
||||
if(i == 0)
|
||||
return getDirection() == FORWARD ? TAG_FRONT : TAG_BACK;
|
||||
else if(i == tags.size()-1)
|
||||
return getDirection() == REVERSE ? TAG_FRONT : TAG_BACK;
|
||||
else
|
||||
return TAG_CENTER;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return TAG_NONE;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Train::suspend()
|
||||
|
@ -3,8 +3,8 @@
|
||||
|
||||
#include <vector>
|
||||
#include "item.h"
|
||||
#include "../microcontroller.h"
|
||||
#include "../nfcuid.h"
|
||||
#include "microcontroller.h"
|
||||
#include "nfcuid.h"
|
||||
|
||||
class Train : public Item
|
||||
{
|
||||
@ -18,10 +18,6 @@ public:
|
||||
static constexpr int FORWARD = 1;
|
||||
static constexpr int REVERSE = -1;
|
||||
static constexpr int TAG_FRONT = 0;
|
||||
static constexpr int TAG_BACK = 1;
|
||||
static constexpr int TAG_CENTER = 2;
|
||||
static constexpr int TAG_NONE = -1;
|
||||
|
||||
static Microcontroller *micro;
|
||||
std::vector<NfcUid> tags;
|
||||
|
||||
@ -41,15 +37,8 @@ public slots:
|
||||
bool resume();
|
||||
bool suspendend();
|
||||
int getDirection();
|
||||
int ownsTag(NfcUid uid);
|
||||
bool ownsTag(NfcUid uid);
|
||||
bool hasBackTag();
|
||||
bool passedReader(const NfcUid &uid)
|
||||
{
|
||||
if(lastReader_ == uid.reader)
|
||||
return false;
|
||||
lastReader_ = uid.reader;
|
||||
return true;
|
||||
}
|
||||
uint8_t getTrainId()
|
||||
{
|
||||
return train_id_;
|
||||
|
@ -146,13 +146,16 @@ void Microcontroller::processNfcLine(const QString& buffer)
|
||||
if(tokens.size() < 4)
|
||||
return;
|
||||
|
||||
if(tokens[1].startsWith("NUMBER"))
|
||||
return;
|
||||
|
||||
NfcUid uid;
|
||||
uid.reader = tokens[1].toUInt();
|
||||
uint8_t reader = tokens[1].toUInt();
|
||||
tokens = tokens[3].split(':');
|
||||
uid.length = tokens.length();
|
||||
for(size_t i = 0; i < uid.length; ++i)
|
||||
uid.bytes[i] = tokens[i].toInt();
|
||||
gotTag(uid);
|
||||
gotTag(reader, uid);
|
||||
}
|
||||
|
||||
void Microcontroller::processList(const QString& buffer)
|
||||
|
@ -74,7 +74,7 @@ signals:
|
||||
void itemChanged(ItemData relay);
|
||||
void auxStateChanged(int value);
|
||||
void gotItemList(std::vector<std::shared_ptr<Item>>&);
|
||||
void gotTag(NfcUid uid);
|
||||
void gotTag(uint8_t reader, NfcUid uid);
|
||||
};
|
||||
|
||||
#endif // MICROCONTROLLER_H
|
||||
|
@ -6,10 +6,9 @@
|
||||
class NfcUid
|
||||
{
|
||||
public:
|
||||
uint8_t reader;
|
||||
uint8_t bytes[10];
|
||||
uint8_t length;
|
||||
bool operator==(NfcUid& in) const
|
||||
bool operator==(const NfcUid& in) const
|
||||
{
|
||||
if(length != in.length)
|
||||
return false;
|
||||
@ -20,18 +19,24 @@ public:
|
||||
}
|
||||
return true;
|
||||
}
|
||||
bool operator!=(NfcUid& in) const
|
||||
bool operator!=(const NfcUid& in) const
|
||||
{
|
||||
return !operator==(in);
|
||||
}
|
||||
NfcUid(){}
|
||||
NfcUid(const uint8_t* const bytesIn, uint8_t lengthIn, uint8_t readerIn = 0):
|
||||
reader(readerIn), length(lengthIn)
|
||||
NfcUid(const std::initializer_list<const uint8_t> list)
|
||||
{
|
||||
length = list.size();
|
||||
uint8_t i = 0;
|
||||
for(std::initializer_list<const uint8_t>::iterator iter = list.begin(); iter != list.end(); ++iter)
|
||||
bytes[i++] = *iter;
|
||||
}
|
||||
NfcUid(const uint8_t* const bytesIn, uint8_t lengthIn): length(lengthIn)
|
||||
{
|
||||
for(uint8_t i = 0; i < length; ++i)
|
||||
bytes[i] = bytesIn[i];
|
||||
}
|
||||
std::string toString()
|
||||
std::string toString() const
|
||||
{
|
||||
std::string str;
|
||||
for(uint8_t i = 0; i < length; ++i)
|
||||
@ -45,3 +50,4 @@ public:
|
||||
};
|
||||
|
||||
#endif // NFCUID_H
|
||||
|
||||
|
@ -1,9 +1,12 @@
|
||||
#include "block.h"
|
||||
#include <QJsonArray>
|
||||
#include <QTimer>
|
||||
#include <layout.h>
|
||||
#include "nfcuid.h"
|
||||
|
||||
Block::Block(uint32_t id):
|
||||
id_(id)
|
||||
|
||||
Block::Block(OverlordItemStore* items, uint32_t id):
|
||||
items_(items), id_(id)
|
||||
{
|
||||
|
||||
}
|
||||
@ -13,29 +16,36 @@ void Block::addBorder(std::shared_ptr<BlockBorder> border)
|
||||
borders_.push_back(border);
|
||||
std::shared_ptr<Block> block = border->getOtherBlock(this);
|
||||
if(!block || block.get() == this)
|
||||
{
|
||||
qWarning()<<__func__<<"no other block in border"<<border->id();
|
||||
return;
|
||||
}
|
||||
connect(block.get(), &Block::blockedChanged, this, &Block::checkWaits);
|
||||
}
|
||||
|
||||
bool Block::blocked()
|
||||
{
|
||||
if(trains_.empty() && waits_.empty())
|
||||
if(tags_.empty() && waits_.empty())
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Block::ownsTrain(std::weak_ptr<Train> train)
|
||||
bool Block::ownsTag(const NfcUid& tag)
|
||||
{
|
||||
std::shared_ptr<Train> trainPtr = train.lock();
|
||||
if(!trainPtr)
|
||||
return false;
|
||||
|
||||
for(auto ownedTrain : trains_)
|
||||
for(const NfcUid& candiate : tags_)
|
||||
{
|
||||
if(ownedTrain.lock() == trainPtr)
|
||||
if(candiate == tag)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Block::tagIsOfOwnedTrain(const NfcUid& tag)
|
||||
{
|
||||
std::shared_ptr<Train> train = items_->getTrainThatOwns(tag);
|
||||
if(!train)
|
||||
return false;
|
||||
for(const NfcUid& canidate : tags_)
|
||||
{
|
||||
std::shared_ptr<Train> canidateTrain = items_->getTrainThatOwns(canidate);
|
||||
if(*canidateTrain == *train)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
@ -53,17 +63,23 @@ bool Block::ownsBorder(std::shared_ptr<BlockBorder> border)
|
||||
return false;
|
||||
}
|
||||
|
||||
void Block::checkWaits(bool ign)
|
||||
void Block::checkWaits(bool isBlocked)
|
||||
{
|
||||
qDebug()<<__func__;
|
||||
(void)ign;
|
||||
if(isBlocked)
|
||||
return;
|
||||
bool wasBlocked = blocked();
|
||||
for(std::vector<TrainWait>::iterator iter = waits_.begin(); iter != waits_.end();)
|
||||
for(std::vector<Wait>::iterator iter = waits_.begin(); iter != waits_.end();)
|
||||
{
|
||||
if(iter->type != WAIT_TYPE_BLOCK)
|
||||
{
|
||||
++iter;
|
||||
continue;
|
||||
}
|
||||
|
||||
std::shared_ptr<Block> block = iter->targetBlock.lock();
|
||||
std::shared_ptr<Train> train = iter->train.lock();
|
||||
qDebug()<<__func__<<"trying to push train"<<train->getTrainId()<<"to block"<<block->id();
|
||||
if(block && train && train->suspendend() && block->pushTrain(iter->train))
|
||||
if(block && train && train->suspendend() && block->pushTag(iter->tag))
|
||||
{
|
||||
train->resume();
|
||||
std::shared_ptr<BlockBorder> border = iter->border.lock();
|
||||
@ -84,41 +100,89 @@ void Block::checkWaits(bool ign)
|
||||
blockedChanged(!wasBlocked);
|
||||
}
|
||||
|
||||
void Block::updateBorders()
|
||||
bool Block::pushTag(const NfcUid& tag)
|
||||
{
|
||||
for(std::shared_ptr<BlockBorder> broder : borders_)
|
||||
if(!blocked() || tagIsOfOwnedTrain(tag))
|
||||
{
|
||||
broder->updateSignals();
|
||||
addTag(tag);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void Block::removeTraverse(std::shared_ptr<Train> train)
|
||||
{
|
||||
bool wasBlocked = blocked();
|
||||
for(std::vector<Wait>::iterator iter = waits_.begin(); iter != waits_.end();)
|
||||
{
|
||||
if(iter->type == WAIT_TYPE_TIMED_TRAVERSE)
|
||||
{
|
||||
std::shared_ptr<Train> iterTrain = iter->train.lock();
|
||||
if(!iterTrain)
|
||||
{
|
||||
iter = waits_.erase(iter);
|
||||
continue;
|
||||
}
|
||||
if(*iterTrain == *train)
|
||||
{
|
||||
qDebug()<<"Train"<<iterTrain->getTrainId()<<"removed from traverse wait for block"<<id_;
|
||||
iter = waits_.erase(iter);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
++iter;
|
||||
}
|
||||
if(wasBlocked != blocked())
|
||||
blockedChanged(!wasBlocked);
|
||||
}
|
||||
|
||||
void Block::addTraverseWait(const NfcUid& tag)
|
||||
{
|
||||
std::shared_ptr<Train> train = items_->getTrainThatOwns(tag);
|
||||
if(!train)
|
||||
return;
|
||||
if(!train->hasBackTag())
|
||||
{
|
||||
qDebug()<<"Train"<<train->getTrainId()<<"added as timed traverse wait for block"<<id_;
|
||||
Wait wait;
|
||||
wait.tag = tag;
|
||||
wait.train = train;
|
||||
wait.type = WAIT_TYPE_TIMED_TRAVERSE;
|
||||
waits_.push_back(wait);
|
||||
QTimer::singleShot(5000, this, [this, train](){removeTraverse(train);});
|
||||
}
|
||||
}
|
||||
|
||||
bool Block::pushTrain(std::weak_ptr<Train> train)
|
||||
void Block::addBlockWait(const NfcUid& tag, std::shared_ptr<Block> block, std::shared_ptr<BlockBorder> border)
|
||||
{
|
||||
if(blocked())
|
||||
return false;
|
||||
|
||||
addTrain(train);
|
||||
return true;
|
||||
std::shared_ptr<Train> train = items_->getTrainThatOwns(tag);
|
||||
if(!train)
|
||||
return;
|
||||
Wait wait;
|
||||
wait.type = WAIT_TYPE_BLOCK;
|
||||
wait.train = train;
|
||||
wait.direction = train->getDirection();
|
||||
wait.targetBlock = block;
|
||||
wait.border = border;
|
||||
wait.tag = tag;
|
||||
connect(train.get(), &Train::unsuspended, this, &Block::unsuspendedTrain);
|
||||
waits_.push_back(wait);
|
||||
qDebug()<<"Train"<<train->getTrainId()<<"is wating at border for block"<<block->id();
|
||||
}
|
||||
|
||||
void Block::addTrain(std::weak_ptr<Train> train)
|
||||
void Block::addTag(const NfcUid& tag)
|
||||
{
|
||||
std::shared_ptr<Train> trainPtr = train.lock();
|
||||
if(!trainPtr)
|
||||
return;
|
||||
qDebug()<<"Train"<<trainPtr->getTrainId()<<"added to block"<<id_;
|
||||
bool wasBlocked = blocked();
|
||||
trains_.push_back(train);
|
||||
tags_.push_back(tag);
|
||||
if(wasBlocked != blocked())
|
||||
blockedChanged(!wasBlocked);
|
||||
updateBorders();
|
||||
}
|
||||
|
||||
void Block::unsuspendedTrain(uint32_t id, int direction)
|
||||
{
|
||||
qDebug()<<"Train with item id"<<id<<"reports unsuspended";
|
||||
bool wasBlocked = blocked();
|
||||
for(std::vector<TrainWait>::iterator iter = waits_.begin(); iter != waits_.end(); ++iter)
|
||||
for(std::vector<Wait>::iterator iter = waits_.begin(); iter != waits_.end(); ++iter)
|
||||
{
|
||||
std::shared_ptr<Train> workTrain = iter->train.lock();
|
||||
if(!workTrain)
|
||||
@ -131,45 +195,43 @@ void Block::unsuspendedTrain(uint32_t id, int direction)
|
||||
{
|
||||
std::shared_ptr<Block> block = iter->targetBlock.lock();
|
||||
disconnect(workTrain.get(), &Train::unsuspended, this, &Block::unsuspendedTrain);
|
||||
if(iter->direction == direction)
|
||||
{
|
||||
if(block)
|
||||
block->addTrain(workTrain);
|
||||
}
|
||||
else
|
||||
{
|
||||
addTrain(workTrain);
|
||||
}
|
||||
if(block)
|
||||
block->addTag(iter->tag);
|
||||
waits_.erase(iter);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(wasBlocked != blocked())
|
||||
blockedChanged(!wasBlocked);
|
||||
updateBorders();
|
||||
}
|
||||
|
||||
void Block::removeTrain(std::weak_ptr<Train> train)
|
||||
void Block::removeTag(const NfcUid& tag)
|
||||
{
|
||||
std::shared_ptr<Train> trainPtr = train.lock();
|
||||
if(!trainPtr)
|
||||
return;
|
||||
|
||||
for(std::vector<std::weak_ptr<Train>>::iterator iter = trains_.begin(); iter != trains_.end(); ++iter)
|
||||
for(std::vector<NfcUid>::iterator iter = tags_.begin(); iter != tags_.end(); ++iter)
|
||||
{
|
||||
if(iter->lock() == trainPtr)
|
||||
if(*iter == tag)
|
||||
{
|
||||
qDebug()<<"Train"<<trainPtr->getTrainId()<<"removed from to block"<<id_;
|
||||
trains_.erase(iter);
|
||||
tags_.erase(iter);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Block::trainArrivedAtBorder(std::weak_ptr<BlockBorder> borderIn, std::weak_ptr<Train> trainIn)
|
||||
void Block::purgeTag(const NfcUid& tag)
|
||||
{
|
||||
qDebug()<<__func__<<"block"<<id();
|
||||
bool wasBlocked = blocked();
|
||||
removeTag(tag);
|
||||
std::shared_ptr<Train> train = items_->getTrainThatOwns(tag);
|
||||
if(train)
|
||||
removeTraverse(train);
|
||||
if(wasBlocked != blocked())
|
||||
blockedChanged(!wasBlocked);
|
||||
}
|
||||
|
||||
void Block::tagArrivedAtBorder(NfcUid tag, std::weak_ptr<BlockBorder> borderIn)
|
||||
{
|
||||
bool wasBlocked = blocked();
|
||||
qDebug()<<__func__<<"block"<<id();
|
||||
std::shared_ptr<BlockBorder> border = borderIn.lock();
|
||||
if(!border)
|
||||
{
|
||||
@ -182,37 +244,28 @@ void Block::trainArrivedAtBorder(std::weak_ptr<BlockBorder> borderIn, std::weak_
|
||||
|
||||
qDebug()<<"Block"<<id_<<"owns subject border";
|
||||
|
||||
if(!ownsTrain(trainIn))
|
||||
if(!ownsTag(tag))
|
||||
return;
|
||||
|
||||
qDebug()<<"Block"<<id_<<"owns subject train";
|
||||
qDebug()<<"Block"<<id_<<"owns subject tag";
|
||||
|
||||
std::shared_ptr block = border->getOtherBlock(this);
|
||||
if(block)
|
||||
{
|
||||
std::shared_ptr<Train> workTrain = trainIn.lock();
|
||||
if(workTrain)
|
||||
if(!block->pushTag(tag))
|
||||
{
|
||||
if(!block->pushTrain(trainIn))
|
||||
{
|
||||
workTrain->suspend();
|
||||
TrainWait wait;
|
||||
wait.train = trainIn;
|
||||
wait.direction = workTrain->getDirection();
|
||||
wait.targetBlock = block;
|
||||
wait.border = border;
|
||||
connect(workTrain.get(), &Train::unsuspended, this, &Block::unsuspendedTrain);
|
||||
waits_.push_back(wait);
|
||||
qDebug()<<"Train"<<workTrain->getTrainId()<<"is wating at border for block"<<block->id();
|
||||
if(!block->trains_.empty() && block->trains_[0].lock())
|
||||
qDebug()<<"for train"<<block->trains_[0].lock()->getTrainId()<<"to leave";
|
||||
}
|
||||
removeTrain(workTrain);
|
||||
std::shared_ptr<Train> train = items_->getTrainThatOwns(tag);
|
||||
train->suspend();
|
||||
addBlockWait(tag, block, border);
|
||||
}
|
||||
else
|
||||
{
|
||||
addTraverseWait(tag);
|
||||
}
|
||||
removeTag(tag);
|
||||
}
|
||||
if(wasBlocked != blocked())
|
||||
blockedChanged(blocked());
|
||||
updateBorders();
|
||||
blockedChanged(!wasBlocked);
|
||||
}
|
||||
|
||||
void Block::store(QJsonObject &json)
|
||||
@ -252,3 +305,4 @@ void Block::populate(const QJsonObject& json, Layout* layout)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -7,6 +7,7 @@
|
||||
#include <QJsonObject>
|
||||
#include "blockborder.h"
|
||||
#include "train.h"
|
||||
#include "overlorditemstore.h"
|
||||
|
||||
class BlockBorder;
|
||||
class Layout;
|
||||
@ -16,50 +17,59 @@ class Block: public QObject
|
||||
Q_OBJECT
|
||||
protected:
|
||||
static constexpr int WAIT_TYPE_BLOCK = 0;
|
||||
static constexpr int WAIT_TYPE_TRAVERSE = 1;
|
||||
static constexpr int WAIT_TYPE_TIMED_TRAVERSE = 1;
|
||||
|
||||
struct TrainWait
|
||||
struct Wait
|
||||
{
|
||||
int type;
|
||||
int direction;
|
||||
NfcUid tag;
|
||||
std::weak_ptr<Train> train;
|
||||
std::weak_ptr<Block> targetBlock;
|
||||
std::weak_ptr<BlockBorder> border;
|
||||
};
|
||||
|
||||
std::vector< std::shared_ptr<BlockBorder> > borders_;
|
||||
std::vector< std::weak_ptr<Train> > trains_;
|
||||
std::vector<TrainWait> waits_;
|
||||
std::vector<NfcUid> tags_;
|
||||
std::vector<Wait> waits_;
|
||||
uint32_t id_;
|
||||
OverlordItemStore* items_;
|
||||
|
||||
protected slots:
|
||||
void unsuspendedTrain(uint32_t id, int direction);
|
||||
void removeTraverse(std::shared_ptr<Train> train);
|
||||
|
||||
protected:
|
||||
void checkWaits(bool blocked = false);
|
||||
void updateBorders();
|
||||
void addTraverseWait(const NfcUid& tag);
|
||||
void addBlockWait(const NfcUid& tag, std::shared_ptr<Block> block, std::shared_ptr<BlockBorder> border);
|
||||
void removeTag(const NfcUid& tag);
|
||||
bool tagIsOfOwnedTrain(const NfcUid& tag);
|
||||
|
||||
public:
|
||||
Block(uint32_t id = QRandomGenerator::global()->generate());
|
||||
void addBorder(std::shared_ptr<BlockBorder> border);
|
||||
bool blocked();
|
||||
bool ownsTrain(std::weak_ptr<Train> train);
|
||||
bool ownsBorder(std::shared_ptr<BlockBorder> border);
|
||||
std::vector< std::shared_ptr<BlockBorder> > getBorders(){return borders_;}
|
||||
Block(OverlordItemStore* items, uint32_t id = QRandomGenerator::global()->generate());
|
||||
uint32_t id(){return id_;}
|
||||
void removeTrain(std::weak_ptr<Train> train);
|
||||
|
||||
void addBorder(std::shared_ptr<BlockBorder> border);
|
||||
std::vector< std::shared_ptr<BlockBorder> > getBorders(){return borders_;}
|
||||
bool ownsBorder(std::shared_ptr<BlockBorder> border);
|
||||
|
||||
bool pushTag(const NfcUid& tag);
|
||||
void addTag(const NfcUid& tag);
|
||||
void purgeTag(const NfcUid& tag);
|
||||
bool ownsTag(const NfcUid& tag);
|
||||
|
||||
bool blocked();
|
||||
|
||||
void store(QJsonObject& json);
|
||||
void load(const QJsonObject& json);
|
||||
void populate(const QJsonObject& json, Layout* layout);
|
||||
|
||||
public slots:
|
||||
bool pushTrain(std::weak_ptr<Train> train);
|
||||
void addTrain(std::weak_ptr<Train> train);
|
||||
void trainArrivedAtBorder(std::weak_ptr<BlockBorder> border, std::weak_ptr<Train> train);
|
||||
void tagArrivedAtBorder(NfcUid tag, std::weak_ptr<BlockBorder> border);
|
||||
|
||||
signals:
|
||||
void blockedChanged(bool blocked);
|
||||
void trainAddedToBlock(int blockId, std::weak_ptr<Train> train);
|
||||
};
|
||||
|
||||
#endif // BLOCK_H
|
||||
|
@ -2,9 +2,9 @@
|
||||
#include <QJsonArray>
|
||||
#include <layout.h>
|
||||
|
||||
BlockBorder::BlockBorder(uint8_t reader, std::pair<std::weak_ptr<Block>, std::weak_ptr<Block>> blocks, uint32_t id): reader_(reader), blocks_(blocks), id_(id)
|
||||
BlockBorder::BlockBorder(uint8_t reader, std::pair<std::weak_ptr<Block>, std::weak_ptr<Block>> blocks, uint32_t id): reader_(reader), id_(id)
|
||||
{
|
||||
|
||||
setBlocks(blocks);
|
||||
}
|
||||
|
||||
bool BlockBorder::isReader(uint8_t reader)
|
||||
@ -17,6 +17,17 @@ uint8_t BlockBorder::getReader()
|
||||
return reader_;
|
||||
}
|
||||
|
||||
void BlockBorder::setBlocks(std::pair<std::weak_ptr<Block>, std::weak_ptr<Block>> blocks)
|
||||
{
|
||||
blocks_ = blocks;
|
||||
std::shared_ptr<Block> first = blocks.first.lock();
|
||||
if(first)
|
||||
connect(first.get(), &Block::blockedChanged, this, &BlockBorder::blockedChanged);
|
||||
std::shared_ptr<Block> second = blocks.second.lock();
|
||||
if(second)
|
||||
connect(second.get(), &Block::blockedChanged, this, &BlockBorder::blockedChanged);
|
||||
}
|
||||
|
||||
void BlockBorder::setSignal(std::weak_ptr<Signal> signalWeak, int8_t value)
|
||||
{
|
||||
std::shared_ptr<Signal> signal = signalWeak.lock();
|
||||
@ -26,6 +37,12 @@ void BlockBorder::setSignal(std::weak_ptr<Signal> signalWeak, int8_t value)
|
||||
}
|
||||
}
|
||||
|
||||
void BlockBorder::blockedChanged(bool blocked)
|
||||
{
|
||||
(void)blocked;
|
||||
updateSignals();
|
||||
}
|
||||
|
||||
void BlockBorder::updateSignals()
|
||||
{
|
||||
for(size_t i = 0; i < signals_.size(); ++i)
|
||||
@ -119,19 +136,37 @@ void BlockBorder::load(const QJsonObject& json)
|
||||
{
|
||||
if(arrayObj.isObject())
|
||||
{
|
||||
signalIds_.push_back(std::pair<uint32_t, bool>(static_cast<uint32_t>(json["SignalId"].toDouble(INT32_MAX)), static_cast<bool>(json["Direction"].toDouble(0))));
|
||||
QJsonObject arrayObjObj = arrayObj.toObject();
|
||||
signalIds_.push_back(std::pair<uint32_t, bool>(static_cast<uint32_t>(arrayObjObj["SignalId"].toDouble(INT32_MAX)), static_cast<bool>(arrayObjObj["Direction"].toDouble(0))));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void BlockBorder::informOfSignal(std::shared_ptr<Signal> signal)
|
||||
bool BlockBorder::hasMissingSingal()
|
||||
{
|
||||
for(auto& signal : signalIds_)
|
||||
{
|
||||
qDebug()<<"Missing signal id:"<<signal.first<<"Direction:"<<signal.second;
|
||||
}
|
||||
return !signalIds_.empty();
|
||||
}
|
||||
|
||||
void BlockBorder::informOfItem(std::weak_ptr<Item> item)
|
||||
{
|
||||
std::shared_ptr<Item> workItem = item.lock();
|
||||
if(!workItem)
|
||||
return;
|
||||
std::shared_ptr<Signal> signal = std::dynamic_pointer_cast<Signal>(workItem);
|
||||
if(!signal)
|
||||
return;
|
||||
for(const std::pair<uint32_t, bool>& signalPair : signalIds_)
|
||||
{
|
||||
if(signalPair.first == signal->getSignalId())
|
||||
{
|
||||
signals_.push_back(signal);
|
||||
signalDirections_.push_back(signalPair.second);
|
||||
qDebug()<<"Border"<<id_<<"got Signal"<<signal->getSignalId();
|
||||
}
|
||||
}
|
||||
std::erase_if(signalIds_, [signal](std::pair<uint32_t, bool> pair) -> bool{return pair.first == signal->getSignalId();});
|
||||
}
|
||||
|
@ -3,12 +3,14 @@
|
||||
#include "trainsignal.h"
|
||||
#include "block.h"
|
||||
#include <QJsonObject>
|
||||
#include <QObject>
|
||||
|
||||
class Block;
|
||||
class Layout;
|
||||
|
||||
class BlockBorder
|
||||
class BlockBorder: public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
private:
|
||||
uint64_t reader_;
|
||||
uint32_t id_;
|
||||
@ -26,13 +28,17 @@ public:
|
||||
void updateSignals();
|
||||
std::shared_ptr<Block> getOtherBlock(Block* block);
|
||||
std::pair<std::weak_ptr<Block>, std::weak_ptr<Block>> getBlocks(){return blocks_;}
|
||||
void setBlocks(std::pair<std::weak_ptr<Block>, std::weak_ptr<Block>> blocks){blocks_ = blocks;}
|
||||
void setBlocks(std::pair<std::weak_ptr<Block>, std::weak_ptr<Block>> blocks);
|
||||
void addSignal(std::weak_ptr<Signal> signal, std::shared_ptr<Block> block);
|
||||
void informOfSignal(std::shared_ptr<Signal> signal);
|
||||
void informOfItem(std::weak_ptr<Item> item);
|
||||
bool hasMissingSingal();
|
||||
std::shared_ptr<Block> getOverlap(BlockBorder* border);
|
||||
uint32_t id() {return id_;}
|
||||
void store(QJsonObject& json);
|
||||
void load(const QJsonObject& json);
|
||||
|
||||
public slots:
|
||||
void blockedChanged(bool blocked);
|
||||
};
|
||||
|
||||
#endif // BLOCKBORDER_H
|
||||
|
@ -2,39 +2,32 @@
|
||||
#include <memory>
|
||||
#include <QJsonArray>
|
||||
|
||||
Layout::Layout(QObject *parent): QObject{parent}
|
||||
Layout::Layout(OverlordItemStore* items, QObject *parent): QObject{parent}, items_(items)
|
||||
{
|
||||
}
|
||||
|
||||
void Layout::itemAdded(std::weak_ptr<Item> itemIn)
|
||||
{
|
||||
std::shared_ptr<Item> item = itemIn.lock();
|
||||
if(!item)
|
||||
return;
|
||||
std::shared_ptr<Train> train = std::dynamic_pointer_cast<Train>(item);
|
||||
std::shared_ptr<Signal> signal = std::dynamic_pointer_cast<Signal>(item);
|
||||
}
|
||||
|
||||
void Layout::removeTrainFromAllBlocks(std::shared_ptr<Train> train)
|
||||
void Layout::removeTagFromAllBlocks(const NfcUid& tag)
|
||||
{
|
||||
for(std::shared_ptr<Block> block : blocks_)
|
||||
block->removeTrain(train);
|
||||
{
|
||||
block->purgeTag(tag);
|
||||
}
|
||||
}
|
||||
|
||||
void Layout::registerTrainInLimbo(std::shared_ptr<Train> train, std::shared_ptr<BlockBorder> border)
|
||||
void Layout::registerTagInLimbo(const NfcUid& tag, std::shared_ptr<BlockBorder> border)
|
||||
{
|
||||
for(auto iter = trainLimbo_.begin(); iter != trainLimbo_.end(); ++iter)
|
||||
for(auto iter = limbo_.begin(); iter != limbo_.end(); ++iter)
|
||||
{
|
||||
std::shared_ptr<Train> limboTrain = iter->first.lock();
|
||||
NfcUid limboTag = iter->first;
|
||||
std::shared_ptr<BlockBorder> limboBorder = iter->second.lock();
|
||||
if(!limboTrain || !limboBorder)
|
||||
if(!limboBorder)
|
||||
{
|
||||
trainLimbo_.erase(iter);
|
||||
registerTrainInLimbo(train, border);
|
||||
limbo_.erase(iter);
|
||||
registerTagInLimbo(tag, border);
|
||||
return;
|
||||
}
|
||||
|
||||
if(*train == *limboTrain)
|
||||
if(limboTag == tag)
|
||||
{
|
||||
if(border == limboBorder)
|
||||
return;
|
||||
@ -42,10 +35,10 @@ void Layout::registerTrainInLimbo(std::shared_ptr<Train> train, std::shared_ptr<
|
||||
std::shared_ptr<Block> overlap = border->getOverlap(limboBorder.get());
|
||||
if(overlap)
|
||||
{
|
||||
qDebug()<<"Train"<<train->getTrainId()<<"removed from limbo and added to block"<<overlap->id()<<"while crossing border"<<border->id();
|
||||
overlap->addTrain(train);
|
||||
overlap->trainArrivedAtBorder(border, train);
|
||||
trainLimbo_.erase(iter);
|
||||
qDebug()<<"Tag"<<tag.toString().c_str()<<"removed from limbo and added to block"<<overlap->id()<<"while crossing border"<<border->id();
|
||||
overlap->addTag(tag);
|
||||
overlap->tagArrivedAtBorder(tag, border);
|
||||
limbo_.erase(iter);
|
||||
return;
|
||||
}
|
||||
else
|
||||
@ -59,12 +52,12 @@ void Layout::registerTrainInLimbo(std::shared_ptr<Train> train, std::shared_ptr<
|
||||
std::shared_ptr<Block> first = border->getBlocks().first.lock();
|
||||
std::shared_ptr<Block> second = border->getBlocks().second.lock();
|
||||
|
||||
qDebug()<<"Train"<<train->getTrainId()<<"added to limbo between block"<<
|
||||
qDebug()<<"Tag"<<tag.toString().c_str()<<"added to limbo between block"<<
|
||||
(first ? QString::number(first->id()) : "invalid")<<"and block"<<(second ? QString::number(second->id()) : "invalid");
|
||||
trainLimbo_.push_back(std::pair<std::weak_ptr<Train>, std::weak_ptr<BlockBorder>>(train, border));
|
||||
limbo_.push_back(std::pair<NfcUid, std::weak_ptr<BlockBorder>>(tag, border));
|
||||
}
|
||||
|
||||
void Layout::trainArrivedAtReader(uint8_t reader, std::shared_ptr<Train> train, int tagType)
|
||||
void Layout::tagArrivedAtReader(uint8_t reader, NfcUid tag)
|
||||
{
|
||||
std::shared_ptr<BlockBorder> border;
|
||||
for(std::shared_ptr<BlockBorder> borderTest : borders_)
|
||||
@ -80,29 +73,31 @@ void Layout::trainArrivedAtReader(uint8_t reader, std::shared_ptr<Train> train,
|
||||
qWarning()<<"reader "<<reader<<"is not registerd with any border";
|
||||
return;
|
||||
}
|
||||
qDebug()<<"Train"<<train->getTrainId()<<"arrived at border"<<border->id();
|
||||
|
||||
bool trainHandled = false;
|
||||
for(std::shared_ptr<Block> block : blocks_)
|
||||
std::shared_ptr<Train> train = items_->getTrainThatOwns(tag);
|
||||
qDebug()<<"Train"<<(train ? train->getTrainId() : -1)<<"Tag"<<tag.toString().c_str()<<"arrived at border"<<border->id();
|
||||
|
||||
bool tagHandled = false;
|
||||
for(std::shared_ptr<Block>& block : blocks_)
|
||||
{
|
||||
if(block->ownsTrain(train))
|
||||
if(block->ownsTag(tag))
|
||||
{
|
||||
trainHandled = true;
|
||||
tagHandled = true;
|
||||
if(block->ownsBorder(border))
|
||||
{
|
||||
block->trainArrivedAtBorder(border, train);
|
||||
block->tagArrivedAtBorder(tag, border);
|
||||
}
|
||||
else
|
||||
{
|
||||
removeTrainFromAllBlocks(train);
|
||||
registerTrainInLimbo(train, border);
|
||||
removeTagFromAllBlocks(tag);
|
||||
registerTagInLimbo(tag, border);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(!trainHandled)
|
||||
registerTrainInLimbo(train, border);
|
||||
if(!tagHandled)
|
||||
registerTagInLimbo(tag, border);
|
||||
}
|
||||
|
||||
void Layout::addBlock(std::shared_ptr<Block> block)
|
||||
@ -166,7 +161,7 @@ void Layout::load(const QJsonObject& json)
|
||||
{
|
||||
const QJsonObject jsonObject = object.toObject();
|
||||
blockJsonObjects.push_back(jsonObject);
|
||||
std::shared_ptr<Block> block(new Block);
|
||||
std::shared_ptr<Block> block(new Block(items_));
|
||||
block->load(jsonObject);
|
||||
blocks_.push_back(block);
|
||||
}
|
||||
@ -203,13 +198,18 @@ void Layout::load(const QJsonObject& json)
|
||||
first = block;
|
||||
else if(!second)
|
||||
second = block;
|
||||
else if(!second)
|
||||
else
|
||||
qWarning()<<"border with id"<<border->id()<<"is assigned to more than 2 blocks";
|
||||
}
|
||||
}
|
||||
if(!first || !second)
|
||||
qWarning()<<"border with id"<<border->id()<<"is assigned to less than than 2 blocks";
|
||||
border->setBlocks(std::pair<std::weak_ptr<Block>, std::weak_ptr<Block>>(first, second));
|
||||
|
||||
for(std::shared_ptr<Item>& item : *items_->getItems())
|
||||
border->informOfItem(item);
|
||||
|
||||
connect(items_, &ItemStore::itemAdded, border.get(), &BlockBorder::informOfItem);
|
||||
}
|
||||
|
||||
for(size_t i = 0; i < blocks_.size(); ++i)
|
||||
|
@ -6,6 +6,7 @@
|
||||
#include <vector>
|
||||
|
||||
#include "block.h"
|
||||
#include "overlorditemstore.h"
|
||||
#include "blockborder.h"
|
||||
#include "microcontroller.h"
|
||||
#include "itemstore.h"
|
||||
@ -18,13 +19,15 @@ private:
|
||||
private:
|
||||
std::vector<std::shared_ptr<Block>> blocks_;
|
||||
std::vector<std::shared_ptr<BlockBorder>> borders_;
|
||||
std::vector<std::pair<std::weak_ptr<Train>, std::weak_ptr<BlockBorder>>> trainLimbo_;
|
||||
std::vector<std::pair<NfcUid, std::weak_ptr<BlockBorder>>> limbo_;
|
||||
|
||||
void removeTrainFromAllBlocks(std::shared_ptr<Train> train);
|
||||
void registerTrainInLimbo(std::shared_ptr<Train> train, std::shared_ptr<BlockBorder>);
|
||||
void removeTagFromAllBlocks(const NfcUid& tag);
|
||||
void registerTagInLimbo(const NfcUid& tag, std::shared_ptr<BlockBorder>);
|
||||
|
||||
OverlordItemStore *items_;
|
||||
|
||||
public:
|
||||
explicit Layout(QObject *parent = nullptr);
|
||||
explicit Layout(OverlordItemStore *items, QObject *parent = nullptr);
|
||||
void addBlock(std::shared_ptr<Block> block);
|
||||
void addBorder(std::shared_ptr<BlockBorder> border);
|
||||
void store(QJsonObject& json);
|
||||
@ -33,11 +36,7 @@ public:
|
||||
std::shared_ptr<Block> getBlock(uint32_t id);
|
||||
|
||||
public slots:
|
||||
void trainArrivedAtReader(uint8_t reader, std::shared_ptr<Train> train, int tagType);
|
||||
void itemAdded(std::weak_ptr<Item> item);
|
||||
|
||||
signals:
|
||||
void trainArrivedAtBorder(std::weak_ptr<BlockBorder>, std::weak_ptr<Train> train, int tagType);
|
||||
void tagArrivedAtReader(uint8_t reader, NfcUid tag);
|
||||
};
|
||||
|
||||
#endif // BLOCKSTORE_H
|
||||
|
@ -6,19 +6,15 @@ OverlordItemStore::OverlordItemStore(QObject *parent): ItemStore(parent)
|
||||
{
|
||||
}
|
||||
|
||||
void OverlordItemStore::gotNfcTag(NfcUid uid)
|
||||
std::shared_ptr<Train> OverlordItemStore::getTrainThatOwns(const NfcUid& uid)
|
||||
{
|
||||
for(std::shared_ptr<Item> item : items_)
|
||||
{
|
||||
std::shared_ptr<Train> train = std::dynamic_pointer_cast<Train>(item);
|
||||
if(!train)
|
||||
continue;
|
||||
int owns = train->ownsTag(uid);
|
||||
if(owns == Train::TAG_FRONT || owns == Train::TAG_BACK)
|
||||
{
|
||||
qDebug()<<"Train"<<train->getTrainId()<<"arrived at reader"<<uid.reader;
|
||||
trainArrivedAtReader(uid.reader, train, owns);
|
||||
return;
|
||||
}
|
||||
if(train->ownsTag(uid))
|
||||
return train;
|
||||
}
|
||||
return std::shared_ptr<Train>();
|
||||
}
|
||||
|
@ -7,10 +7,5 @@ class OverlordItemStore: public ItemStore
|
||||
Q_OBJECT
|
||||
public:
|
||||
OverlordItemStore(QObject *parent = nullptr);
|
||||
|
||||
public slots:
|
||||
void gotNfcTag(NfcUid);
|
||||
|
||||
signals:
|
||||
void trainArrivedAtReader(uint8_t reader, std::shared_ptr<Train> train, int tagType);
|
||||
std::shared_ptr<Train> getTrainThatOwns(const NfcUid& uid);
|
||||
};
|
||||
|
@ -129,13 +129,10 @@ int main(int argc, char *argv[])
|
||||
}
|
||||
|
||||
OverlordItemStore items;
|
||||
Layout layout;
|
||||
|
||||
QObject::connect(&items, &OverlordItemStore::itemAdded, &layout, &Layout::itemAdded);
|
||||
QObject::connect(&items, &OverlordItemStore::trainArrivedAtReader, &layout, &Layout::trainArrivedAtReader);
|
||||
Layout layout(&items);
|
||||
|
||||
Microcontroller micro(µSocket);
|
||||
QObject::connect(µ, &Microcontroller::gotTag, &items, &OverlordItemStore::gotNfcTag);
|
||||
QObject::connect(µ, &Microcontroller::gotTag, &layout, &Layout::tagArrivedAtReader);
|
||||
QObject::connect(µ, &Microcontroller::gotItemList, &items, &OverlordItemStore::addItems);
|
||||
QObject::connect(µ, &Microcontroller::itemChanged, &items, &OverlordItemStore::itemStateChanged);
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user