trainoverlord: switch from train based blocking to tag based blocking

This commit is contained in:
uvos 2022-03-23 15:00:56 +01:00
parent 29b887504d
commit 96638d6f8d
16 changed files with 291 additions and 202 deletions

View File

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

View File

@ -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)
{

View File

@ -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()

View File

@ -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_;

View File

@ -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)

View File

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

View File

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

View File

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

View File

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

View File

@ -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();});
}

View File

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

View File

@ -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)

View File

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

View File

@ -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>();
}

View File

@ -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);
};

View File

@ -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(&microSocket);
QObject::connect(&micro, &Microcontroller::gotTag, &items, &OverlordItemStore::gotNfcTag);
QObject::connect(&micro, &Microcontroller::gotTag, &layout, &Layout::tagArrivedAtReader);
QObject::connect(&micro, &Microcontroller::gotItemList, &items, &OverlordItemStore::addItems);
QObject::connect(&micro, &Microcontroller::itemChanged, &items, &OverlordItemStore::itemStateChanged);