Reinserts original comments

This commit is contained in:
torsten committed 2026-10-14 12:56:16 +00:00
1 parent 1dd1e86355
commit b662e4daf9
112 files changed
+7113 -5131

No files matched your search

@@ -1,5 +1,10 @@
/**
* Thin wrapper around json telegram data
* $Id$
* $HeadURL$
* $Author$
* Created by Christian Ehrlicher, SLSE, 2016-04-22
*/
#include "CoPrtCnvCentralTelegram.hpp"
#include <QtCore/QJsonDocument>
@@ -79,4 +84,4 @@ void CoPrtCnvCentralTelegram::ensureByteArray()
}
}
} // namespace N_CoPrtCnv
@@ -1,5 +1,10 @@
/**
* Thin wrapper around json telegram data
* $Id$
* $HeadURL$
* $Author$
* Created by Christian Ehrlicher, SLSE, 2016-04-22
*/
#pragma once
@@ -10,8 +15,11 @@
namespace N_CoPrtCnv
{
/**
* The central-telegram, an subclass of XDR_Wrapper_it used for creation of
* telegrams with telegramId. It also contains the deletion of dynamic allocated
* space within central-telegrams.
*/
class COPRTCNV_EXPORT CoPrtCnvCentralTelegram final
{
public:
@@ -42,8 +50,8 @@ namespace N_CoPrtCnv
void setData(const QByteArray &data);
QByteArray data();
QJsonObject json();
QJsonObject jsonData();
QJsonObject json(); // complete json
QJsonObject jsonData(); // json()["data"]
TrainingAreaBase::TetraIcd::TelegramId telegramId();
void setCounter(qint32 counter);
qint32 counter();
@@ -1,16 +1,16 @@
// **************************************************************************
//
// @RDE_HEADER@
//
// **************************************************************************
//
// $HeadURL$
// $LastChangedBy$
// $LastChangedDate$
// $LastChangedRevision$
//
// Helper to dump the data in hex
// **************************************************************************
#include "CoPrtCnvHexDumpHelper.hpp"
#include "CoPrtCnvRadioTelegram.hpp"
@@ -24,9 +24,9 @@ static std::string dumpSammeldeaktivierung(const N_CoPrtCnv::CoPrtCnvRadioTelegr
const int SIZE_POS = sammelTelegram->getTelID() == GEF_WF_SAMMELDEAKTIVIERUNG_DUS_MINEN ? 2 : 1;
std::stringstream sstream;
unsigned int cnt = sammelTelegram->getPayloadDataUInt32(ANZAHL_POS, SIZE_POS);
unsigned int cnt = sammelTelegram->getPayloadDataUInt32(ANZAHL_POS, SIZE_POS); // anzahl
for (unsigned int i = 0; i < cnt; ++i) {
uint16_t telId = sammelTelegram->getPayloadDataUInt32(ANZAHL_POS + SIZE_POS + 2 * i, 2);
uint16_t telId = sammelTelegram->getPayloadDataUInt32(ANZAHL_POS + SIZE_POS + 2 * i, 2); // add kennung
sstream << telId << " ";
}
return sstream.str();
@@ -1,16 +1,16 @@
// **************************************************************************
//
// @RDE_HEADER@
//
// **************************************************************************
//
// $HeadURL$
// $LastChangedBy$
// $LastChangedDate$
// $LastChangedRevision$
//
// Helper to dump the data in hex
// **************************************************************************
#pragma once
#include <QtCore/QString>
@@ -1,15 +1,15 @@
// **************************************************************************
//
// (C) Copyright 2009 Swiss SIMTEC AG
//
// **************************************************************************
//
// $HeadURL$
// $LastChangedBy$
// $LastChangedDate$
// $LastChangedRevision$
//
// **************************************************************************
#pragma once
@@ -17,26 +17,38 @@
namespace N_CoPrtCnv
{
/**
* The header used for injection-data
*
* @author alois.wismer
* @version 1.0
* @created 06-Aug-2010 10:27:55
*/
struct CoPrtCnvInjectionHeader
{
/**
* The m_Id1 and m_Id2 are used to detect rubish data.
*/
uint32_t m_Id1;
/**
* The m_Id1 and m_Id2 are used to detect rubish data.
*/
uint32_t m_Id2;
/**
* 0 => unknown
* 1 => central-telegram
* 2 => radio-telegram
* all others: unknown
*/
enum Destination
{
eUnknown = 0,
eCentral = 1,
eRadio = 2
} m_Kind;
/**
* The size of following data
*/
uint16_t m_Size;
CoPrtCnvInjectionHeader()
@@ -1,15 +1,15 @@
// **************************************************************************
//
// (C) Copyright 2009 Swiss SIMTEC AG
//
// **************************************************************************
//
// $HeadURL$
// $LastChangedBy$
// $LastChangedDate$
// $LastChangedRevision$
//
// **************************************************************************
#pragma once
@@ -17,12 +17,18 @@
namespace N_CoPrtCnv
{
/**
* @author alois.wismer
* @version 1.0
* @created 12-Mrz-2010 16:07:19
*/
struct CoPrtCnvLogHeader
{
/**
* @author alois.wismer
* @version 1.0
* @created 12-Mrz-2010 16:04:42
*/
enum E_CoPrtCnvProtocol
{
e_DestProtocolCentral = 0,
@@ -34,19 +40,24 @@ namespace N_CoPrtCnv
e_DestReceive = 0x40000000,
e_DestSend = 0xC0000000
};
/**
* length of data, including length of this header
*/
short m_Length = 0;
short m_Version = 0;
int m_Priority = 0;
/**
* We do not use E_CoPrtCnvProtocol here, because we want a size of 4 bytes
*/
int m_Protocol = 0;
/**
* needed for correct alignment when compiling on 64-bit systems
*/
int m_Reserved = 0;
/**
* Upper 4 bytes => seconds
* Lower 4 byte => microseconds
*/
uint64_t m_Time = 0;
};
}
File diff suppressed because it is too large. Load diff
@@ -1,15 +1,15 @@
// **************************************************************************
//
// (C) Copyright 2009 Swiss SIMTEC AG
//
// **************************************************************************
//
// $HeadURL$
// $LastChangedBy$
// $LastChangedDate$
// $LastChangedRevision$
//
// **************************************************************************
#pragma once
@@ -28,27 +28,42 @@ class CoPrtCnvRadioTelegram;
class CoPrtCnvCentralTelegram;
/**
* This class is responsible to convert radio-telegrams into central-telegrams and
* vice versa.
* @author alois.wismer
* @version 1.0
* @created 19-Mrz-2010 13:32:40
*/
namespace CoPrtCnvTelegramConverter
{
/**
* Converts central-telegrams to radio-telegrams.
* Returns NULL if conversion was failed.
*
* @param a_telegram
*/
COPRTCNV_EXPORT CoPrtCnvRadioTelegram *convertToRadio(CoPrtCnvCentralTelegram *a_telegram);
COPRTCNV_EXPORT CoPrtCnvRadioTelegram *convertToRadio(const TrainingAreaBase::TetraIcd::TrainingAreaTelegram *a_telegram);
/**
* converts a radiotelegram into a central.
* returns nullptr if conversion failed
*
* @param a_radioTelegram
*/
COPRTCNV_EXPORT CoPrtCnvCentralTelegram *convertToCentral(const CoPrtCnvRadioTelegram *a_radioTelegram);
COPRTCNV_EXPORT TrainingAreaBase::TetraIcd::TrainingAreaTelegram *convertToTabTele(const CoPrtCnvRadioTelegram *a_radioTelegram);
/**
* Set the text codec to use for string send to/received from tetra
*/
COPRTCNV_EXPORT void setTetraTextCodec(const char *codecName);
/**
* Set to trueif single fire (WIRKFELD_EINZELGESCHOSS) has two bytes for diameter, otherwise only one byte is used
*/
COPRTCNV_EXPORT void setUse2BytesForSingleFireDiameter(bool bUse);
COPRTCNV_EXPORT void setUsePvSan(bool bUse);
@@ -1,5 +1,10 @@
/**
* Telegram IDs used in ICD52
* $Id$
* $HeadURL$
* $Author$
* Created by hjl, SLSE, 2016-11-14
*/
#pragma once
@@ -39,7 +39,7 @@ int main(int argc, char **argv)
QCoreApplication app(argc, argv);
// Check alle 30 Sekunden
NGL::NGLLoggerBootstrap::createNGLRootLogger("log4cxx_tetra.props", false);
NGL::INGLLogger &logger(NGL::NGLLoggerBootstrap::getNGLRootLogger());
@@ -79,21 +79,21 @@ int main(int argc, char **argv)
s_eqIds += eqId;
}
//fprintf(stdout, "Counter;EqID;TelID;TelTime;LogTime;Diff\n");
while (true)
{
// read the header of telegram-entry
N_CoPrtCnv::CoPrtCnvLogHeader lh;
if (sizeof(lh) == telegramFile.read((char *)&lh, sizeof(lh)))
{
if (lh.m_Version == 3)
{
// read the telegram itself
qint64 telegramLength = lh.m_Length - sizeof(lh);
QByteArray telegramData(telegramLength, Qt::Uninitialized);
if (telegramLength == telegramFile.read(telegramData.data(), telegramLength))
{
// add the telegram to telegram-list
N_CoPrtCnv::CoPrtCnvLogHeader::E_CoPrtCnvProtocol dest = (N_CoPrtCnv::CoPrtCnvLogHeader::E_CoPrtCnvProtocol)
(lh.m_Protocol & N_CoPrtCnv::CoPrtCnvLogHeader::e_DestProtocolMask);
@@ -1,17 +1,17 @@
// **************************************************************************
//
// (C) Copyright 2009 Swiss SIMTEC AG
//
// **************************************************************************
//
// $HeadURL$
// $LastChangedBy$
// $LastChangedDate$
// $LastChangedRevision$
//
// **************************************************************************
// manual class headers
#include "IntegerCalculator.hpp"
#include <sstream>
@@ -27,35 +27,35 @@ IntegerCalculator::IntegerCalculator()
{
}
// ---------------------------------------------------------------
// Converts the expressen in a_calcText into a signed value.
// Returns whether an error happend in the variable a_error.
// If an error happend, the variable a_addErrorText can
// contain more informaition about the error (see E_Error for
// more information about errors).
// ---------------------------------------------------------------
int64_t IntegerCalculator::calc(const std::string& a_calcText, E_Error& a_error, std::string* a_addErrorText)
{
std::string calcText = a_calcText;
// separate operations from variables
for (auto iter = m_OperationList.begin(); iter != m_OperationList.end(); ++iter)
replace(calcText, iter->first, " "+iter->first+" ");
// separate paranthesis from variables
replace(calcText, "(", " ( ");
replace(calcText, ")", " ) ");
// now calculate the expression
m_ParanthesisCount = 0;
m_Error = e_Ok;
m_AdditionalErrorText = "";
size_t pos = 0;
bool dummy;
int64_t value = calc(calcText, pos, dummy, "", 0, "+");
int64_t value = calc(calcText, pos, dummy, "", 0, "+"); // todo: use member-variable m_CalcText
//M_INFO("calc: " << calcText << " value: " << value);
// check the paranthesis
if (m_Error == e_Ok)
{
if (m_ParanthesisCount > 0)
@@ -72,7 +72,7 @@ int64_t IntegerCalculator::calc(const std::string& a_calcText, E_Error& a_error,
}
}
// actions if a failure happens
a_error = m_Error;
if (a_error != e_Ok)
{
@@ -85,9 +85,9 @@ int64_t IntegerCalculator::calc(const std::string& a_calcText, E_Error& a_error,
return value;
}
// ---------------------------------------------------------------
// Adds or changes a case-sensitive variable to the calculator.
// ---------------------------------------------------------------
void IntegerCalculator::addVariable(const std::string& a_name, const int64_t a_value)
{
std::map<std::string, int64_t>::iterator iter = m_VariableList.find(a_name);
@@ -97,9 +97,9 @@ void IntegerCalculator::addVariable(const std::string& a_name, const int64_t a_v
}
// ---------------------------------------------------------------
// Removes a case-sensitive variable from the calculator.
// ---------------------------------------------------------------
void IntegerCalculator::removeVariable(const std::string& a_name)
{
std::map<std::string, int64_t>::iterator iter = m_VariableList.find(a_name);
@@ -108,9 +108,9 @@ void IntegerCalculator::removeVariable(const std::string& a_name)
}
// ---------------------------------------------------------------
// Calculates the expression (recursive)
// ---------------------------------------------------------------
int64_t IntegerCalculator::calc(const std::string& a_calcText, size_t& a_pos, bool& a_IsEndParanthesis,
const std::string& a_prevOp, const int64_t a_prevValue,
const std::string& a_initOp)
@@ -134,12 +134,12 @@ int64_t IntegerCalculator::calc(const std::string& a_calcText, size_t& a_pos, bo
int64_t value2 = calcSign(calc(calcText, ++a_pos, dummy), isNegative);
value1 = doOperation(value1, operation, value2);
size_t tmpPos = a_pos;
// get next operation to check priority of operation
size_t tmpPos = a_pos; // do not change the position, we only pre-read
std::string nextOp = getToken(a_calcText, tmpPos);
if (isOperation(nextOp) && isOperation(a_prevOp) && !isOperationPriorityHigher(nextOp, a_prevOp))
{
// end of higher priority operation
return value1;
}
@@ -154,19 +154,19 @@ int64_t IntegerCalculator::calc(const std::string& a_calcText, size_t& a_pos, bo
}
else if (isDigit(calcText[a_pos]))
{
// value
// -----
int64_t value2 = calcSign(convertValue(calcText, a_pos), isNegative);
if (calcWithPriority(calcText, a_pos, value1, operation, value2, a_prevOp)) return value1;
}
else
{
// operation or variable
// ---------------------
std::string oldOperation = operation;
operation = getToken(calcText, a_pos);
// is it a variable?
if (!isOperation(operation))
{
int64_t value2 = 0;
@@ -178,14 +178,14 @@ int64_t IntegerCalculator::calc(const std::string& a_calcText, size_t& a_pos, bo
}
else
{
// error
m_Error = e_UnknownOperationOrVariable;
m_AdditionalErrorText = operation;
}
}
else
{
// do we have a sign?
if (oldOperation != "")
{
if (operation == "+")
@@ -211,25 +211,25 @@ int64_t IntegerCalculator::calc(const std::string& a_calcText, size_t& a_pos, bo
}
// ---------------------------------------------------------------
// Calculates an operation with respecting the priority of
// operations. This will be done with recursion.
// ---------------------------------------------------------------
bool IntegerCalculator::calcWithPriority(const std::string& a_calcText, size_t& a_pos, int64_t& a_value1, std::string& a_operation, int64_t a_value2, const std::string& a_prevOp)
{
bool isParaEnd = false;
size_t tmpPos = a_pos;
// get next operation to check priority of operation
size_t tmpPos = a_pos; // only pre-read
std::string nextOp = getToken(a_calcText, tmpPos);
if (isOperation(a_operation) && isOperation(nextOp) && isOperationPriorityHigher(nextOp, a_operation))
{
// next operation has higher priority => calc the next operation first
a_value2 = calc(a_calcText, a_pos, isParaEnd, a_operation, a_value2);
}
a_value1 = doOperation(a_value1, a_operation, a_value2);
if (isParaEnd || (isOperation(nextOp) && isOperation(a_prevOp) && !isOperationPriorityHigher(nextOp, a_prevOp)))
{
// end of higher priority operation
return true;
}
a_operation = "";
@@ -237,12 +237,12 @@ bool IntegerCalculator::calcWithPriority(const std::string& a_calcText, size_t&
}
// ---------------------------------------------------------------
// Returns the inverted a_value if a_isNegative is true.
// a_isNegative will be false after calling this function.
// If a_isNegative is true, the NOT inverted a_value will be
// returned.
// ---------------------------------------------------------------
int64_t IntegerCalculator::calcSign(const int64_t a_value, bool& a_isNegative)
{
if (a_isNegative)
@@ -254,16 +254,16 @@ int64_t IntegerCalculator::calcSign(const int64_t a_value, bool& a_isNegative)
}
// ---------------------------------------------------------------
// Converts the value in form of text to a number. The Text
// can be decimal, hex (0x) or binary (0b).
// ---------------------------------------------------------------
int64_t IntegerCalculator::convertValue(const std::string &a_valueText, size_t& a_pos)
{
std::string valueText = a_valueText.substr(a_pos);
int base = 10;
size_t startpos = 0;
// hex- and binary-stuff
bool isHex = (0 == valueText.find("0X")) || (0 == valueText.find("0x"));
bool isBin = (0 == valueText.find("0B")) || (0 == valueText.find("0b"));
if (isHex)
@@ -276,7 +276,7 @@ int64_t IntegerCalculator::convertValue(const std::string &a_valueText, size_t&
base = 2;
startpos = 2;
}
// search end of value
size_t i;
for (i=startpos; i<valueText.length(); i++)
{
@@ -285,7 +285,7 @@ int64_t IntegerCalculator::convertValue(const std::string &a_valueText, size_t&
break;
}
}
// check the next char, it must be a space
if (valueText.length() > i && valueText[i] != ' ')
{
m_Error = e_InvalidOperand;
@@ -299,7 +299,7 @@ int64_t IntegerCalculator::convertValue(const std::string &a_valueText, size_t&
stream.str(valueText.substr(startpos, i-startpos));
if (2 == base)
{
// our stl is not able to read in binary-values, therefore we have to implement it ourself
const std::string binValueAsText = stream.str();
for (const char c : binValueAsText)
{
@@ -317,20 +317,20 @@ int64_t IntegerCalculator::convertValue(const std::string &a_valueText, size_t&
}
// ---------------------------------------------------------------
// Returns the next token (with space as separator). Heading
// spaces will be ignored.
// ---------------------------------------------------------------
std::string IntegerCalculator::getToken(const std::string &a_calcText, size_t& a_pos)
{
// skip spaces at begin
while (a_pos < a_calcText.length())
{
if (a_calcText[a_pos] == ' ') a_pos++;
else break;
}
// search until next space (or end)
size_t startPos = a_pos;
while (a_pos < a_calcText.length())
{
@@ -341,9 +341,9 @@ std::string IntegerCalculator::getToken(const std::string &a_calcText, size_t& a
}
// ---------------------------------------------------------------
// returns true if a_operation is a known operation.
// ---------------------------------------------------------------
bool IntegerCalculator::isOperation(const std::string& a_operation) const
{
std::map<std::string, int>::const_iterator iter = m_OperationList.find(a_operation);
@@ -351,13 +351,13 @@ bool IntegerCalculator::isOperation(const std::string& a_operation) const
}
// ---------------------------------------------------------------
// Calculates the opeation a_operations with a_value1 as first
// and a_value2 as second operand.
// ---------------------------------------------------------------
int64_t IntegerCalculator::doOperation(const int64_t a_value1, const std::string& a_operation, const int64_t a_value2)
{
// M_INFO("" << a_value1 << " " << a_operation << " " << a_value2);
if (("+" == a_operation) || a_operation.empty())
{
return a_value1 + a_value2;
@@ -409,23 +409,23 @@ int64_t IntegerCalculator::doOperation(const int64_t a_value1, const std::string
}
// ---------------------------------------------------------------
// returns true if priority of a_opeation1 is higher than
// priority of a_operation2.
// ---------------------------------------------------------------
bool IntegerCalculator::isOperationPriorityHigher(const std::string& a_operation1, const std::string& a_operation2) const
{
return (getPriority(a_operation1) > getPriority(a_operation2));
}
// ---------------------------------------------------------------
// Returns true if the variable named a_variableName is known
// and a_value will be filled with its value. If the variable
// is not found false will be returned.
// Overload this virtual function if you want to implement
// your own variable-list.
// ---------------------------------------------------------------
bool IntegerCalculator::getVariableValue(const std::string& a_variableName, int64_t& a_value) const
{
auto iter = m_VariableList.find(a_variableName);
@@ -435,37 +435,37 @@ bool IntegerCalculator::getVariableValue(const std::string& a_variableName, int6
return true;
}
// error
return false;
}
// ---------------------------------------------------------------
// Returns true if a_char is a digit. When a_isHex is true,
// also the charactes a-f will be accepted as digits. When
// a_isBin is true, only 0 and 1 will be treated as digit.
// ---------------------------------------------------------------
bool IntegerCalculator::isDigit(const char a_char, const bool a_isHex, const bool a_isBin)
{
if (a_isHex)
{
// for hex-values also A..F are 'digits'
return (a_char >= '0' && a_char <= '9') || (a_char >= 'A' && a_char <= 'F') || (a_char >= 'a' && a_char <= 'f');
}
else if (a_isBin)
{
// for binary-values only 0 and 1 are allowed
return (a_char >= '0' && a_char <= '1');
}
// normal digits
return (a_char >= '0' && a_char <= '9');
}
// ---------------------------------------------------------------
// Returns the priority of the operation. A higher value means
// more priority.
// ---------------------------------------------------------------
int16_t IntegerCalculator::getPriority(const std::string& a_operation) const
{
std::map<std::string, int>::const_iterator iter = m_OperationList.find(a_operation);
@@ -476,10 +476,10 @@ int16_t IntegerCalculator::getPriority(const std::string& a_operation) const
}
// ---------------------------------------------------------------
// replaces in a_haystack all a_searchText with a_replaceText
// (not greedy).
// ---------------------------------------------------------------
void IntegerCalculator::replace(std::string& a_haystack, const std::string &a_searchText, const std::string &a_replaceText)
{
std::string::size_type searchSize = a_searchText.length();
@@ -494,4 +494,4 @@ void IntegerCalculator::replace(std::string& a_haystack, const std::string &a_se
}
}
}
} // namespace N_SST
@@ -1,15 +1,15 @@
// **************************************************************************
//
// (C) Copyright 2009 Swiss SIMTEC AG
//
// **************************************************************************
//
// $HeadURL$
// $LastChangedBy$
// $LastChangedDate$
// $LastChangedRevision$
//
// **************************************************************************
#pragma once
@@ -18,39 +18,66 @@
namespace N_SST
{
/**
* This class calculates algebraic texts with integer values and returns its
* result as a signed value. It handles the operations - +, -, *, /, %, <<, >>. It
* understands the paranthesis and priorities of operations, like * before -. It
* also computes with variables, which names are case-sensitive. The values can be
* decimal, hexadecimal (0x) or binary (0b). The variable-system implemented
* virtual, so you can implement your own variable system (see getVariableValue()).
*
*
* @author alois.wismer
* @version 1.0
* @created 12-Mai-2010 16:26:43
*/
class IntegerCalculator
{
public:
/**
* Describes the error happend while calculation of an expression
*
* @author alois.wismer
* @version 1.0
* @created 17-Mai-2010 16:38:24
*/
enum E_Error
{
/**
* No error happend
*/
e_Ok,
/**
* The divisor is 0
*/
e_DivisionByZero,
/**
* The operation/variable is not known. a_addErrorText will contain the unknown
* operation/variable.
*/
e_UnknownOperationOrVariable,
/**
* Between to operators no variable/operand exists. a_addErrorText contains the 2
* operations.
*/
e_NoOperandBetweenOperators,
/**
* The operand contains invalid characters. a_addErrorText contains the invalid
* operand.
*/
e_InvalidOperand,
/**
* There are more ) than (
*/
e_MissingLeftParanthesis,
/**
* There are more ) than (
*/
e_MissingRightParanthesis,
/**
* Something else went wrong
*/
e_UnknownError
};
@@ -58,84 +85,171 @@ namespace N_SST
IntegerCalculator();
virtual ~IntegerCalculator() = default;
/**
* Converts the expressen in a_calcText into a signed value. Returns whether an
* error happend in the variable a_error. If an error happend, the variable
* a_addErrorText can contain more informaition about the error (see E_Error for
* more information about errors).
*
* @param a_calcText
* @param a_error
* @param a_addErrorText
*/
int64_t calc(const std::string& a_calcText, E_Error& a_error, std::string* a_addErrorText = nullptr);
/**
* Adds or changes a case-sensitive variable to the calculator.
*
* @param a_name
* @param a_value
*/
void addVariable(const std::string& a_name, const int64_t a_value);
/**
* Removes a case-sensitive variable from the calculator.
*
* @param a_name
*/
void removeVariable(const std::string& a_name);
protected:
/**
* Contains all supported operations
*/
const std::map<std::string, int> m_OperationList;
/**
* Contains all variables
*/
std::map<std::string, int64_t> m_VariableList;
/**
* The additional text for errors
*/
std::string m_AdditionalErrorText;
/**
* The number of open paranthesis
*/
int32_t m_ParanthesisCount;
E_Error m_Error;
/**
* Calculates the expression (recursive)
*
* @param a_calcText
* @param a_pos
* @param a_IsEndParanthesis
* @param a_prevOp
* @param a_prevValue
* @param a_initOp
*/
int64_t calc(const std::string& a_calcText, size_t& a_pos, bool& a_IsEndParanthesis,
const std::string& a_prevOp = std::string(), const int64_t a_prevValue = 0,
const std::string& a_initOp = std::string());
/**
* Calculates an operation with respecting the priority of operations. This will
* be done with recursion.
*
* @param a_calcText
* @param a_pos
* @param a_value1
* @param a_operation
* @param a_value2
* @param a_prevOp
*/
bool calcWithPriority(const std::string& a_calcText, size_t& a_pos, int64_t& a_value1,
std::string& a_operation, int64_t a_value2, const std::string& a_prevOp);
/**
* Returns the inverted a_value if a_isNegative is true. a_isNegative will be
* false after calling this function.
* If a_isNegative is true, the NOT inverted a_value will be returned.
*
* @param a_value
* @param a_isNegative
*/
static int64_t calcSign(const int64_t a_value, bool& a_isNegative);
/**
* Converts the value in form of text to a number. The Text can be decimal, hex
* (0x) or binary (0b).
*
* @param a_valueText
* @param a_pos
*/
int64_t convertValue(const std::string& a_valueText, size_t& a_pos);
/**
* Returns the next token (with space as separator). Heading spaces will be
* ignored.
*
* @param a_calcText
* @param a_pos
*/
static std::string getToken(const std::string& a_calcText, size_t& a_pos);
/**
* returns true if a_operation is a known operation.
*
* @param a_operation
*/
bool isOperation(const std::string& a_operation) const;
/**
* Calculates the opeation a_operations with a_value1 as first and a_value2 as
* second operand.
*
* @param a_value1
* @param a_operation
* @param a_value2
*/
int64_t doOperation(const int64_t a_value1, const std::string& a_operation, const int64_t a_value2);
/**
* returns true if priority of a_opeation1 is higher than priority of a_operation2.
*
*
* @param a_operation1
* @param a_operation2
*/
bool isOperationPriorityHigher(const std::string& a_operation1, const std::string& a_operation2) const;
/**
* Returns true if the variable named a_variableName is known and a_value will be
* filled with its value. If the variable is not found false will be returned.
* Overload this virtual function if you want to implement your own variable-list.
*
* @param a_variableName
* @param a_value
*/
virtual bool getVariableValue(const std::string& a_variableName, int64_t& a_value) const;
/**
* Returns true if a_char is a digit. When a_isHex is true, also the charactes a-f
* will be accepted as digits. When a_isBin is true, only 0 and 1 will be treated
* as digit.
*
* @param a_char
* @param a_isHex
* @param a_isBin
*/
static bool isDigit(const char a_char, const bool a_isHex = false, const bool a_isBin = false);
/**
* Returns the priority of the operation. A higher value means more priority.
*
* @param a_operation
*/
int16_t getPriority(const std::string& a_operation) const;
/**
* replaces in a_haystack all a_searchText with a_replaceText (not greedy).
*
* @param a_haystack
* @param a_searchText
* @param a_replaceText
*/
static void replace(std::string& a_haystack, const std::string& a_searchText, const std::string& a_replaceText);
};
@@ -1,5 +1,10 @@
/**
* @RDE_HEADER@
* Edit boolean values
* $Id$
* $HeadURL$
* $Author$
*/
#include "LogViewBooleanEdit.hpp"
#include "LogViewField.hpp"
@@ -8,7 +13,7 @@
namespace N_LogView
{
// ---------------------------------------------------------------
LogViewBooleanEdit::LogViewBooleanEdit(LogViewField* a_field, QWidget* a_parent, const bool a_readonly)
: QCheckBox (a_parent)
, LogViewWidget(a_field, this, a_parent, a_readonly)
@@ -19,7 +24,7 @@ LogViewBooleanEdit::LogViewBooleanEdit(LogViewField* a_field, QWidget* a_parent,
setEnabled(!a_readonly);
}
// ---------------------------------------------------------------
bool LogViewBooleanEdit::saveContent(LogViewTelegram* a_telegram)
{
if (m_Valid)
@@ -33,4 +38,4 @@ bool LogViewBooleanEdit::saveContent(LogViewTelegram* a_telegram)
return false;
}
}
} // namespace N_LogView
@@ -1,5 +1,10 @@
/**
* @RDE_HEADER@
* Edit boolean values
* $Id$
* $HeadURL$
* $Author$
*/
#pragma once
@@ -1,17 +1,17 @@
// **************************************************************************
//
// (C) Copyright 2009 Swiss SIMTEC AG
//
// **************************************************************************
//
// $HeadURL$
// $LastChangedBy$
// $LastChangedDate$
// $LastChangedRevision$
//
// **************************************************************************
// manual class headers
#include "LogViewDateTimeEdit.hpp"
#include <time.h>
#include "LogViewField.hpp"
@@ -20,7 +20,7 @@
namespace N_LogView
{
// ---------------------------------------------------------------
LogViewDateTimeEdit::LogViewDateTimeEdit(LogViewField* a_field, QWidget* a_parent, const bool a_readonly)
: QDateTimeEdit(a_parent)
, LogViewWidget(a_field, this, a_parent, a_readonly)
@@ -31,7 +31,7 @@ LogViewDateTimeEdit::LogViewDateTimeEdit(LogViewField* a_field, QWidget* a_paren
setAlignment(a_field->isRightAligned() ? Qt::AlignRight : Qt::AlignLeft);
}
// date-time-field
qint64 unixTime = 0;
if (a_field->hasContent())
{
@@ -40,34 +40,34 @@ LogViewDateTimeEdit::LogViewDateTimeEdit(LogViewField* a_field, QWidget* a_paren
else
unixTime = a_field->value(0, true).toInt() * 1000LL;
}
// take actual date and time if time is 0
if (0 == unixTime && !a_readonly)
unixTime = ::time(nullptr) * 1000LL;
//valueWidget = new QDateTimeEdit(dateTime);
setDateTime(QDateTime::fromMSecsSinceEpoch(unixTime));
setDisplayFormat(QLatin1String("dd MMM yyyy hh:mm:ss"));
setCalendarPopup(true);
updateToolTip(QString::number(unixTime));
//setToolTip(a_field->getToolTipText());
// checkAndOvertakeContent();
connect(this, &LogViewDateTimeEdit::editingFinished,
this, &LogViewDateTimeEdit::checkAndOvertakeContent);
}
// ---------------------------------------------------------------
void LogViewDateTimeEdit::checkAndOvertakeContent()
{
updateToolTip(QString::number(dateTime().toMSecsSinceEpoch() / 1000));
}
// ---------------------------------------------------------------
// Writes the content into telegram.
// Returns true if successful.
// ---------------------------------------------------------------
bool LogViewDateTimeEdit::saveContent(LogViewTelegram* a_telegram)
{
if (a_telegram->isJsonTelegram())
@@ -76,11 +76,11 @@ bool LogViewDateTimeEdit::saveContent(LogViewTelegram* a_telegram)
}
else
{
a_telegram->setNextFieldAsGpsTimeField();
a_telegram->setNextFieldAsGpsTimeField(); // fixme: muss noch der feldname auf GPS Zeit geprüft werden?
a_telegram->setUIntX(getSize(), dateTime().toMSecsSinceEpoch() / 1000);
}
return true;
}
}
} // namespace N_LogView
@@ -1,15 +1,15 @@
// **************************************************************************
//
// (C) Copyright 2009 Swiss SIMTEC AG
//
// **************************************************************************
//
// $HeadURL$
// $LastChangedBy$
// $LastChangedDate$
// $LastChangedRevision$
//
// **************************************************************************
#pragma once
@@ -18,18 +18,31 @@
namespace N_LogView
{
/**
* Used for date & time
*
* @author alois.wismer
* @version 1.0
* @created 20-Mai-2010 17:41:28
*/
class LogViewDateTimeEdit : public QDateTimeEdit, public LogViewWidget
{
Q_OBJECT
public:
/**
*
* @param a_field
* @param a_parent
* @param a_readonly
*/
LogViewDateTimeEdit(LogViewField* a_field, QWidget* a_parent, const bool a_readonly);
/**
* Writes the content into telegram.
* Returns true if successful.
*
* @param a_telegram
*/
bool saveContent(LogViewTelegram* a_telegram) override;
public slots:
@@ -1,17 +1,17 @@
// **************************************************************************
//
// (C) Copyright 2009 Swiss SIMTEC AG
//
// **************************************************************************
//
// $HeadURL$
// $LastChangedBy$
// $LastChangedDate$
// $LastChangedRevision$
//
// **************************************************************************
// manual class headers
#include "LogViewEnumEdit.hpp"
#include "LogViewXdrStruct.hpp"
#include "LogViewXdrValue.hpp"
@@ -23,17 +23,17 @@ namespace N_LogView
{
// ---------------------------------------------------------------
LogViewEnumEdit::LogViewEnumEdit(LogViewField* a_field, QWidget* a_parent, const bool a_readonly, const int a_index)
: QComboBox(a_parent)
, LogViewWidget(a_field, this, a_parent, a_readonly)
{
QString value = a_field->value(a_index);
// show the tool-tip with special-case for TETRA bitfields
setToolTip(a_field->toolTipText());
// fill combobox
bool bCurrentIndexSet = false;
int i = 0;
while (LogViewXdrValue* child = (static_cast<const LogViewXdrStruct*>(a_field->xdrElement()))->getChildAsValue(i++))
@@ -61,32 +61,32 @@ LogViewEnumEdit::LogViewEnumEdit(LogViewField* a_field, QWidget* a_parent, const
setCurrentIndex(findText(value));
}
// connect signals
connect(this, QOverload<int>::of(&LogViewEnumEdit::currentIndexChanged),
this, &LogViewEnumEdit::checkAndOvertakeContent);
}
// ---------------------------------------------------------------
uint16_t LogViewEnumEdit::getSize() const
{
// todo: check ob wirklich ein struct
const LogViewXdrStruct* xdrStruct = static_cast<const LogViewXdrStruct*>(m_Field->xdrElement());
return xdrStruct->getEnumSize();
}
// ---------------------------------------------------------------
void LogViewEnumEdit::checkAndOvertakeContent()
{
updateToolTip(itemData(currentIndex()).toString());
}
// ---------------------------------------------------------------
// Writes the content into telegram.
// Returns true if successful.
// ---------------------------------------------------------------
bool LogViewEnumEdit::saveContent(LogViewTelegram* a_telegram)
{
bool ok;
@@ -99,7 +99,7 @@ bool LogViewEnumEdit::saveContent(LogViewTelegram* a_telegram)
a_telegram->setUIntX(getSize(), value);
return true;
}
return false;
return false; // failure while conversion
}
}
} // namespace N_LogView
@@ -1,15 +1,15 @@
// **************************************************************************
//
// (C) Copyright 2009 Swiss SIMTEC AG
//
// **************************************************************************
//
// $HeadURL$
// $LastChangedBy$
// $LastChangedDate$
// $LastChangedRevision$
//
// **************************************************************************
#pragma once
@@ -18,21 +18,35 @@
namespace N_LogView
{
/**
* Used for enums
*
* @author alois.wismer
* @version 1.0
* @created 21-Mai-2010 09:31:16
*/
class LogViewEnumEdit : public QComboBox, public LogViewWidget
{
Q_OBJECT
public:
/**
*
* @param a_field
* @param a_parent
* @param a_readonly
* @param a_index the array-index
*/
LogViewEnumEdit(LogViewField* a_field, QWidget* a_parent, const bool a_readonly, const int a_index);
uint16_t getSize() const override;
/**
* Writes the content into telegram.
* Returns true if successful.
*
* @param a_telegram
*/
bool saveContent(LogViewTelegram* a_telegram) override;
protected slots:
@@ -1,15 +1,15 @@
// **************************************************************************
//
// (C) Copyright 2009 Swiss SIMTEC AG
//
// **************************************************************************
//
// $HeadURL$
// $LastChangedBy$
// $LastChangedDate$
// $LastChangedRevision$
//
// **************************************************************************
#include "LogViewField.hpp"
#include <utility>
@@ -20,7 +20,7 @@
namespace N_LogView
{
// ---------------------------------------------------------------
LogViewField::LogViewField(const QString& a_name, const E_FieldKind a_kind, const LogViewXdrElement* a_xdrElement)
: m_logger(getLogger("LogViewField")),
m_Name(a_name),
@@ -36,7 +36,7 @@ LogViewField::LogViewField(const QString& a_name, const E_FieldKind a_kind, cons
{
}
// ---------------------------------------------------------------
LogViewField::~LogViewField()
{
for (LogViewField *f : std::as_const(m_Child))
@@ -70,14 +70,14 @@ LogViewField *LogViewField::clone(int arrayIdx) const
}
// ---------------------------------------------------------------
void LogViewField::addChild(LogViewField* a_child)
{
if (a_child)
m_Child.push_back(a_child);
}
// ---------------------------------------------------------------
void LogViewField::removeLastChild()
{
if (m_Child.empty())
@@ -86,7 +86,7 @@ void LogViewField::removeLastChild()
}
// ---------------------------------------------------------------
LogViewField* LogViewField::child(int arrayIdx)
{
if (m_Child.size() > arrayIdx)
@@ -94,13 +94,13 @@ LogViewField* LogViewField::child(int arrayIdx)
return nullptr;
}
// ---------------------------------------------------------------
void LogViewField::addValue(const QString &value)
{
m_ValueList.append(value);
}
// ---------------------------------------------------------------
void LogViewField::addValueBinaryHex(const QString &value)
{
const QByteArray ba = QByteArray::fromHex(value.toLatin1());
@@ -109,13 +109,13 @@ void LogViewField::addValueBinaryHex(const QString &value)
}
// ---------------------------------------------------------------
// Returns the value at position a_index converted to a string.
// If the field is a date-time-field, the returned value is
// converted to a string containing date and time, execpt when
// a_doNotMakeSpecialConversions is set to true, the unix-time
// will be returned as value.
// ---------------------------------------------------------------
QString LogViewField::value(int arrayIdx, const bool a_doNotMakeSpecialConversions) const
{
if (m_ValueList.size() > arrayIdx)
@@ -133,7 +133,7 @@ QString LogViewField::value(int arrayIdx, const bool a_doNotMakeSpecialConversio
return QString();
}
// ---------------------------------------------------------------
int64_t LogViewField::getHighestValue() const
{
switch (m_XdrElement->getKind())
@@ -141,9 +141,9 @@ int64_t LogViewField::getHighestValue() const
case LogViewXdrElement::e_KindStandardType:
{
int64_t highest = 1;
//const LogViewXdrStandardType* xdrStandardType = static_cast<const LogViewXdrStandardType*>(m_XdrElement);
uint16_t bitSize = 8*static_cast<const LogViewXdrStandardType*>(m_XdrElement)->getEditSize();
// fixme: mache configurierbar
if ((0 == m_Name.compare(QLatin1String("utm nordwert"), Qt::CaseInsensitive)) ||
(0 == m_Name.compare(QLatin1String("utm ostwert"), Qt::CaseInsensitive)))
bitSize -= 8;
@@ -172,7 +172,7 @@ int64_t LogViewField::getHighestValue() const
}
// ---------------------------------------------------------------
int64_t LogViewField::getLowestValue() const
{
switch (m_XdrElement->getKind())
@@ -180,7 +180,7 @@ int64_t LogViewField::getLowestValue() const
case LogViewXdrElement::e_KindStandardType:
{
int64_t lowest = 0;
//const LogViewXdrStandardType* xdrStandardType = static_cast<const LogViewXdrStandardType*>(a_field->getXdrElement());
switch (static_cast<const LogViewXdrStandardType*>(m_XdrElement)->getValueKind()) {
case LogViewXdrStandardType::e_Boolean:
return 0;
@@ -201,12 +201,12 @@ int64_t LogViewField::getLowestValue() const
}
// ---------------------------------------------------------------
void LogViewField::dump(const QString &a_indent) const
{
INFO_LOG(m_logger) << a_indent << "[";
INFO_LOG(m_logger) << a_indent << "Field[" << m_Name << "]: m_Kind=" << m_Kind << " m_Offset=" << m_Offset << " m_Size=" << m_Size << " m_MaxArraySize=" << m_MaxArraySize << " m_IsRightAligned=" << m_IsRightAligned << " m_IsDynamicArray=" << m_IsDynamicArray << " m_ToolTipText=" << m_ToolTipText;
// m_XdrElement->dump();
for (int i=0; i<m_ValueList.size(); i++)
INFO_LOG(m_logger) << a_indent << "m_Value[" << i << "]=" << m_ValueList[i];
@@ -217,25 +217,25 @@ void LogViewField::dump(const QString &a_indent) const
}
// ---------------------------------------------------------------
// Makes the text <a_uncleanText> pretty for human readable.
// It does following:
// - generates umlaute (ä, ö, ü)
// - removes _rt at end
// - replaces _ with space
// - uppercase of every word
// ---------------------------------------------------------------
QString LogViewField::makeClean(const QString &text)
{
QString a_uncleanText = text;
// remove _rt at end
if (a_uncleanText.endsWith(QLatin1String("_rt")))
a_uncleanText = a_uncleanText.left(a_uncleanText.length() - 3);
// replace _ with space
a_uncleanText = a_uncleanText.replace(QLatin1Char('_'), QLatin1Char(' '));
// first character of every word must be uppercase
int pos = 0;
while (a_uncleanText.length() > pos)
{
@@ -250,9 +250,9 @@ QString LogViewField::makeClean(const QString &text)
}
// ---------------------------------------------------------------
// returns true if the field is a date-time
// ---------------------------------------------------------------
bool LogViewField::isDateTimeField() const
{
QString name = m_Name.toLower();
@@ -266,11 +266,11 @@ bool LogViewField::isMSecsField() const
}
// ---------------------------------------------------------------
void LogViewField::setMaxArraySize(uint16_t newVal, const bool a_isDynamic)
{
m_MaxArraySize = newVal;
m_IsDynamicArray = a_isDynamic;
}
}
} // namespace N_LogView
@@ -1,15 +1,15 @@
// **************************************************************************
//
// (C) Copyright 2009 Swiss SIMTEC AG
//
// **************************************************************************
//
// $HeadURL$
// $LastChangedBy$
// $LastChangedDate$
// $LastChangedRevision$
//
// **************************************************************************
#pragma once
@@ -57,8 +57,15 @@ namespace N_LogView
void addValue(const QString &value);
void addValueBinaryHex(const QString &value);
/**
* Returns the value at position a_index converted to a string. If the field is a
* date-time-field, the returned value is converted to a string containing date
* and time, execpt when a_doNotMakeSpecialConversions is set to true, the unix-
* time will be returned as value.
*
* @param a_index
* @param a_doNotMakeSpecialConversions
*/
QString value(int arrayIdx, const bool a_doNotMakeSpecialConversions = false) const;
int valueListSize() const { return m_ValueList.size(); }
@@ -74,12 +81,21 @@ namespace N_LogView
int64_t getHighestValue() const;
int64_t getLowestValue() const;
/**
*
* @param a_indent
*/
void dump(const QString &a_indent = QString()) const;
/**
* Makes the text <a_uncleanText> pretty for human readable. It does following:
* - generates umlaute (ä, ö, ü)
* - removes _rt at end
* - replaces _ with space
* - uppercase of every word
*
* @param a_uncleanText
*/
static QString makeClean(const QString &text);
@@ -89,8 +105,9 @@ namespace N_LogView
const LogViewXdrElement* xdrElement() const { return m_XdrElement; }
/**
* returns true if the field is a date-time
*/
bool isDateTimeField() const;
bool isMSecsField() const;
@@ -98,8 +115,9 @@ namespace N_LogView
uint16_t maxArraySize() const { return m_MaxArraySize; }
void setMaxArraySize(uint16_t newVal, const bool a_isDynamic);
/**
* True if the array is dynamic.
*/
bool isDynamicArray() const { return m_IsDynamicArray; }
@@ -124,8 +142,9 @@ namespace N_LogView
uint16_t m_Offset;
int m_Size;
uint16_t m_MaxArraySize;
/**
* True if the array is dynamic.
*/
bool m_IsDynamicArray;
bool m_HasContent;
bool m_bDeleteXdr;
@@ -1,17 +1,17 @@
// **************************************************************************
//
// (C) Copyright 2009 Swiss SIMTEC AG
//
// **************************************************************************
//
// $HeadURL$
// $LastChangedBy$
// $LastChangedDate$
// $LastChangedRevision$
//
// **************************************************************************
// manual class headers
#include "LogViewGui.hpp"
#include "LogViewTelegram.hpp"
@@ -50,7 +50,7 @@
namespace N_LogView
{
// static member initialization
const QLatin1String LogViewGui::WINDOW_GROUP("MainWindow");
const QLatin1String LogViewGui::SIZE("Size");
const QLatin1String LogViewGui::SCREEN("Screen");
@@ -59,9 +59,9 @@ const QLatin1String LogViewGui::SPLITTPOS("SplittPos");
const QLatin1String LogViewGui::TOOLBOXINDEX("ToolBoxIndex");
// ---------------------------------------------------------------
// ---------------------------------------------------------------
LogViewGui::LogViewGui(QWidget* a_parent)
: QMainWindow(a_parent)
, RADIO_BUTTON_ICON_SIZE(16, 16)
@@ -79,7 +79,7 @@ LogViewGui::LogViewGui(QWidget* a_parent)
QSettings settings;
settings.beginGroup(WINDOW_GROUP);
// status-bar
m_InjectionStatus = new QLabel(this);
m_InjectionStatus->setFrameStyle(QFrame::Panel | QFrame::Sunken);
statusBar()->addPermanentWidget(m_InjectionStatus);
@@ -90,11 +90,11 @@ LogViewGui::LogViewGui(QWidget* a_parent)
m_TelegramStatus->setFrameStyle(QFrame::Panel | QFrame::Sunken);
statusBar()->addPermanentWidget(m_TelegramStatus);
// tool-bar
// --------
QToolBar* toolBar = addToolBar(tr("Datei"));
toolBar->setToolButtonStyle(Qt::ToolButtonTextUnderIcon);
// tool-bar: new logfile
QString tipText;
QAction* action = new QAction(tr("Neue Log-Datei"), this);
action->setIcon(QIcon(QLatin1String(":icons/16x16/document-new.png")));
@@ -104,7 +104,7 @@ LogViewGui::LogViewGui(QWidget* a_parent)
action->setToolTip(tipText);
connect(action, &QAction::triggered, this, &LogViewGui::newTelegramFile);
toolBar->addAction(action);
// tool-bar: add logfile
action = new QAction(tr("Log-Datei hinzu"), this);
action->setIcon(QIcon(QLatin1String(":icons/16x16/document-import.png")));
action->setShortcut(tr("Ctrl+O"));
@@ -113,7 +113,7 @@ LogViewGui::LogViewGui(QWidget* a_parent)
action->setToolTip(tipText);
connect(action, &QAction::triggered, this, &LogViewGui::loadTelegramFile);
toolBar->addAction(action);
// tool-bar: reload
m_reloadAction = new QAction(tr("&Reload"), this);
m_reloadAction->setCheckable(true);
m_reloadAction->setChecked(m_DoReload);
@@ -124,7 +124,7 @@ LogViewGui::LogViewGui(QWidget* a_parent)
m_reloadAction->setToolTip(tipText);
connect(m_reloadAction, &QAction::triggered, this, &LogViewGui::reloadOnOff);
toolBar->addAction(m_reloadAction);
// tool-bar: settings
action = new QAction(tr("&Einstellungen"), this);
action->setIcon(QIcon(QLatin1String(":icons/16x16/configure.png")));
action->setShortcut(tr("Ctrl+E"));
@@ -133,7 +133,7 @@ LogViewGui::LogViewGui(QWidget* a_parent)
action->setToolTip(tipText);
connect(action, &QAction::triggered, this, &LogViewGui::changeSettings);
toolBar->addAction(action);
// tool-bar: exit
toolBar->addSeparator();
action = new QAction(tr("&Beenden"), this);
action->setIcon(QIcon(QLatin1String(":icons/16x16/edit-delete.png")));
@@ -148,8 +148,8 @@ LogViewGui::LogViewGui(QWidget* a_parent)
createTetraSelectionWidget();
createWlsSelectionWidget();
// participant-selection
// ---------------------
m_ParticipantTableView = new QTableView(this);
m_participantProxyModel = new QSortFilterProxyModel(this);
m_participantModel = new ParticipantModel(this);
@@ -175,7 +175,7 @@ LogViewGui::LogViewGui(QWidget* a_parent)
m_ParticipantSelectionGroup->setLayout(participantBox);
connect(m_ParticipantSelectionGroup, &QGroupBox::toggled, this, &LogViewGui::selectedParticipantChanged);
// left side (filters)
m_ToolBox = new QToolBox(this);
m_ToolBox->addItem(m_CentralSelectionGroup, QIcon(QLatin1String(":/image/Central.png")), tr("&Zentral-Telegramm-Filter"));
m_ToolBox->addItem(m_TetraSelectionGroup, QIcon(QLatin1String(":/image/Tetra.png")), tr("TET&RA-Telegramm-Filter"));
@@ -184,8 +184,8 @@ LogViewGui::LogViewGui(QWidget* a_parent)
m_ToolBox->addItem(m_EditTelegramController->tableView(), QIcon(QLatin1String(":icons/16x16/document-edit.png")), tr("&Edit && Sende Telegramme"));
m_ToolBox->setCurrentIndex(settings.value(TOOLBOXINDEX).toInt());
// right side (logged telegrams)
// -----------------------------
m_logTelegramView = new QTableView(this);
m_logTelegramView->setAlternatingRowColors(true);
m_logTelegramView->setSelectionBehavior(QAbstractItemView::SelectRows);
@@ -194,9 +194,9 @@ LogViewGui::LogViewGui(QWidget* a_parent)
m_logTelegramView->verticalHeader()->setMinimumSectionSize(QApplication::font().pointSize() * 2.5);
m_logTelegramView->verticalHeader()->setDefaultSectionSize(QApplication::font().pointSize() * 2.5);
m_logTelegramView->verticalHeader()->setSectionResizeMode(QHeaderView::Fixed);
m_logTelegramView->setContextMenuPolicy(Qt::CustomContextMenu);
m_logTelegramView->setContextMenuPolicy(Qt::CustomContextMenu); //Custom Contextmenu enabled
connect(m_logTelegramView, &QTableView::customContextMenuRequested,
this, &LogViewGui::customMenuRequested);
this, &LogViewGui::customMenuRequested); //connect table to contextmenu
m_telegramModel = new TelegramModel(m_logTelegramView);
m_telegramProxyModel = new TelegramProxyModel(m_logTelegramView);
m_telegramProxyModel->setSourceModel(m_telegramModel);
@@ -212,7 +212,7 @@ LogViewGui::LogViewGui(QWidget* a_parent)
QGroupBox* telegramGroup = new QGroupBox(tr("&Log-Telegramme"), this);
telegramGroup->setLayout(telegramBox);
// splitter between toolbox and log-telegram-list
m_Splitter = new QSplitter(Qt::Horizontal, this);
m_Splitter->addWidget(m_ToolBox);
m_Splitter->addWidget(telegramGroup);
@@ -231,8 +231,8 @@ LogViewGui::LogViewGui(QWidget* a_parent)
m_Splitter->setSizes(splitterSizes);
setCentralWidget(m_Splitter);
// initialize the telegram-filters (this should be done before load of telegrams, otherwise the telegram-list
// will be shown several times and this could be slow when the telegram-list is slow)
m_CentralSelectionGroup->setChecked(true);
m_ackCentralTelCheckBox->setChecked(true);
m_ackCentralTelCheckBox->setChecked(false);
@@ -258,7 +258,7 @@ LogViewGui::LogViewGui(QWidget* a_parent)
m_SentWlsTelCheckBox->setChecked(true);
m_ReceivedWlsTelCheckBox->setChecked(true);
// set the size and position of main-window
QSize size = settings.value(SIZE, sizeHint()).toSize();
resize(size.isNull() ? QSize(1280, 768) : size);
move(settings.value(POS, QPoint(0, 0)).toPoint());
@@ -273,13 +273,13 @@ LogViewGui::LogViewGui(QWidget* a_parent)
void LogViewGui::createCentralSelectionWidget()
{
// send-checkbox
m_SentCentralTelCheckBox = createRadioButton(tr("&gesendete Telegramme"), QLatin1String(":/image/P2C.png"));
// received-checkbox
m_ReceivedCentralTelCheckBox = createRadioButton(tr("&empfangene Telegramme"), QLatin1String(":/image/C2P.png"));
// pos-checkbox
m_PosCentralTelCheckBox = createRadioButton(tr("&Positionsmeldungen"), QLatin1String(":/image/CentralPos.png"));
// ack-checkbox
m_ackCentralTelCheckBox = createRadioButton(tr("&Bestaetigungstelegramme"), QLatin1String(":/image/CentralAck.png"));
QVBoxLayout* centralFilterBox = new QVBoxLayout;
@@ -298,21 +298,21 @@ void LogViewGui::createCentralSelectionWidget()
void LogViewGui::createTetraSelectionWidget()
{
// sent-checkbox
m_SentTetraTelCheckBox = createRadioButton(tr("&gesendete Telegramme"), QLatin1String(":/image/T2P.png"));
// received-checkbox
m_ReceivedTetraTelCheckBox = createRadioButton(tr("&empfangene Telegramme"), QLatin1String(":/image/P2T.png"));
// pos-checkbox
m_PosTetraTelCheckBox = createRadioButton(tr("&Positionsmeldungen"), QLatin1String(":/image/TetraPos.png"));
// fragmented-checkbox
m_FragmentedTetraTelCheckBox = createRadioButton(tr("&Fragmentierte Meldungen"), QLatin1String(":/image/TetraFragmented.png"));
// login-checkbox
m_LoginTetraTelCheckBox = createRadioButton(tr("&Loginmeldungen"), QLatin1String(":/image/TetraLogin.png"));
// register-checkbox
m_RegisterTetraTelCheckBox = createRadioButton(tr("&Registermeldungen"), QLatin1String(":/image/TetraRegister.png"));
// report-checkbox
m_ReportTetraTelCheckBox = createRadioButton(tr("&Reportmeldungen"), QLatin1String(":/image/TetraReport.png"));
// air-interface-load-checkbox
m_AirInterfaceLoadTetraTelCheckBox = createRadioButton(tr("&Air-Load Meldungen"), QLatin1String(":/image/TetraAirInterface.png"));
QVBoxLayout* tetraFilterBox = new QVBoxLayout;
@@ -335,11 +335,11 @@ void LogViewGui::createTetraSelectionWidget()
void LogViewGui::createWlsSelectionWidget()
{
// send-checkbox
m_SentWlsTelCheckBox = createRadioButton(tr("&gesendete Telegramme"), QLatin1String(":/image/P2W.png"));
// received-checkbox
m_ReceivedWlsTelCheckBox = createRadioButton(tr("&empfangene Telegramme"), QLatin1String(":/image/W2P.png"));
// pos-checkbox
m_PosWlsTelCheckBox = createRadioButton(tr("&Positionsmeldungen"), QLatin1String(":/image/WlsPos.png"));
QVBoxLayout* wlsFilterBox = new QVBoxLayout;
@@ -356,10 +356,10 @@ void LogViewGui::createWlsSelectionWidget()
}
// ---------------------------------------------------------------
void LogViewGui::customMenuRequested(const QPoint &pos)
{
//create Menu with Actions
QMenu menu(this);
menu.addAction(tr("Add Telegram to EditList"), this, &LogViewGui::addTelegramToEdit);
menu.addAction(tr("Show HexData"), this, &LogViewGui::showHexData);
@@ -376,7 +376,7 @@ void LogViewGui::customMenuRequested(const QPoint &pos)
}
// ---------------------------------------------------------------
void LogViewGui::addTelegramToEdit()
{
for (const QModelIndex &orig: m_logTelegramView->selectionModel()->selectedRows())
@@ -390,7 +390,7 @@ void LogViewGui::addTelegramToEdit()
}
// ---------------------------------------------------------------
void LogViewGui::showHexData()
{
const QModelIndex idx = m_telegramProxyModel->mapToSource(m_logTelegramView->currentIndex());
@@ -402,7 +402,7 @@ void LogViewGui::showHexData()
showTelegramDialog->showDataDump(tele, false);
}
// ---------------------------------------------------------------
void LogViewGui::exportAsCsv()
{
const int idx = m_ActualLogfile.lastIndexOf(QLatin1Char('.'));
@@ -441,7 +441,7 @@ void LogViewGui::exportAsCsv()
f.write("\n");
}
f.close();
}
}// ---------------------------------------------------------------
void LogViewGui::exportAsJson()
{
@@ -468,7 +468,7 @@ void LogViewGui::exportAsJson()
f.close();
}
// ---------------------------------------------------------------
void LogViewGui::onStartLogReplay()
{
#ifndef LTS_DEBUG
@@ -526,7 +526,7 @@ void LogViewGui::onReplayTimerTimeout()
if (!checkTele())
return;
uint64_t nextSendTime = (tele->getLogTimeMsec() - curSendTime);
uint64_t nextSendTime = (tele->getLogTimeMsec() - curSendTime); // micro -> milli
DEBUG_LOG(m_logger) << "Next SendTime: " << nextSendTime
<< ", telId: " << tele->getTelId()
<< ", next row: " << m_currentReplayRow
@@ -536,13 +536,13 @@ void LogViewGui::onReplayTimerTimeout()
m_replayTimer->start(nextSendTime);
}
// ---------------------------------------------------------------
void LogViewGui::loadSpecificationFiles()
{
QSettings settings;
settings.beginGroup(LogViewOptionDialog::SPEC_FILES_GROUP);
// load central-protocol spezification
QString defString = QCoreApplication::applicationDirPath() + QLatin1String("/training_area_telegrams.h");
QString filename = settings.value(LogViewOptionDialog::P0_FILENAME, defString).toString();
INFO_LOG(m_logger) << "Load central-protocol spezification-file: " << filename.toStdString();
@@ -553,7 +553,7 @@ void LogViewGui::loadSpecificationFiles()
}
LogViewTelegram::jsonParser()->parse(filename);
// load tetra-protocol spezification
defString = QCoreApplication::applicationDirPath() + QLatin1String("/zsksxd_tetraForLogView.x");
filename = settings.value(LogViewOptionDialog::P5_FILENAME, defString).toString();
INFO_LOG(m_logger) << "Load tetra-protocol spezification-file: " << filename.toStdString();
@@ -570,29 +570,29 @@ void LogViewGui::loadSpecificationFiles()
}
// ---------------------------------------------------------------
void LogViewGui::newTelegramFile()
{
if (m_TailTimer) m_TailTimer->stop();
// delete all participants
m_participantModel->clearParticipants();
m_telegramModel->clearTelegrams();
m_participantListTelCount.clear();
m_participantListIssi.clear();
m_ParticipantStatus->setText(tr("0 Teilnehmer"));
// load a telegram-file
loadTelegramFile();
}
// ---------------------------------------------------------------
void LogViewGui::loadTelegramFile()
{
const QLatin1String DIR("Dir");
QSettings settings;
settings.beginGroup(QLatin1String("LogFiles"));
QString filename = QFileDialog::getOpenFileName(this, tr("Bitte eine Log-Datei auswaehlen"), settings.value(DIR).toString(), LogViewOptionDialog::KRLOG_FILES);
QString filename = QFileDialog::getOpenFileName(this, tr("Bitte eine Log-Datei auswaehlen"), settings.value(DIR).toString(), LogViewOptionDialog::KRLOG_FILES/*tr("Log-Dateien (*.krlog)")*/);
if (filename.isEmpty())
return;
@@ -605,7 +605,7 @@ void LogViewGui::loadTelegramFile()
m_logTelegramView->resizeColumnsToContents();
m_ParticipantTableView->resizeColumnsToContents();
// start the time for checking whether new entries were added to the log-file
if (!m_TailTimer)
m_TailTimer = new QTimer(this);
connect(m_TailTimer, &QTimer::timeout, this, &LogViewGui::updateLogfile, Qt::QueuedConnection);
@@ -614,11 +614,11 @@ void LogViewGui::loadTelegramFile()
}
// ---------------------------------------------------------------
// Checks whether the size of actual logfile has changed. If
// yes, the new log-entries will be read and shown within
// table.
// ---------------------------------------------------------------
void LogViewGui::updateLogfile()
{
if(!m_DoReload)
@@ -636,12 +636,12 @@ void LogViewGui::updateLogfile()
catch (const std::exception& e)
{
WARNING_LOG(m_logger) << "Error: " << e.what();
// simply read the telegram in the next update
}
}
else
{
//check if one newer file exists and load it
QString dateFromFile;
const QString format = QStringLiteral("yyMMdd_hh");
for (int iterator = fileInfo.baseName().size() - format.size(); iterator < fileInfo.baseName().size(); ++iterator)
@@ -677,10 +677,10 @@ void LogViewGui::updateLogfile()
}
// ---------------------------------------------------------------
void LogViewGui::readTelegramsFromLogFile(const QString& a_fileName, const qint64 a_filePos)
{
// open the log-file
QFile telegramFile(a_fileName);
if (telegramFile.open(QIODevice::ReadOnly))
{
@@ -690,7 +690,7 @@ void LogViewGui::readTelegramsFromLogFile(const QString& a_fileName, const qint6
m_logTelegramView->blockSignals(true);
m_logTelegramView->setUpdatesEnabled(false);
QVector<QSharedPointer<LogViewTelegram> > newTelegrams;
// read the header of telegram-entry
N_CoPrtCnv::CoPrtCnvLogHeader lh;
while (true)
{
@@ -698,7 +698,7 @@ void LogViewGui::readTelegramsFromLogFile(const QString& a_fileName, const qint6
{
if (lh.m_Version == 3 || lh.m_Version == 4)
{
// read the telegram itself
qint64 telegramLength = lh.m_Length - sizeof(lh);
QByteArray buf(telegramLength, Qt::Uninitialized);
if (telegramLength == telegramFile.read(buf.data(), telegramLength))
@@ -708,11 +708,11 @@ void LogViewGui::readTelegramsFromLogFile(const QString& a_fileName, const qint6
if (lh.m_Version == 4)
buf = qUncompress(buf);
// add the telegram to telegram-list
N_CoPrtCnv::CoPrtCnvLogHeader::E_CoPrtCnvProtocol protocol =
static_cast<N_CoPrtCnv::CoPrtCnvLogHeader::E_CoPrtCnvProtocol>(lh.m_Protocol);
QSharedPointer<LogViewTelegram> telegram(new LogViewTelegram(protocol, lh.m_Time, buf));
// this checks the telegram and raises a messagebox if the telegram is wrong
if (!telegram->isValid())
{
ERROR_LOG(m_logger) << "Trying to read/parse unknown data from logfile '" << a_fileName
@@ -721,7 +721,7 @@ void LogViewGui::readTelegramsFromLogFile(const QString& a_fileName, const qint6
}
newTelegrams.push_back(telegram);
// add the pariticipant to the participant-list
addToParticipantList(telegram);
}
}
@@ -754,7 +754,7 @@ void LogViewGui::readTelegramsFromLogFile(const QString& a_fileName, const qint6
}
// ---------------------------------------------------------------
void LogViewGui::selectedParticipantChanged()
{
std::set<int> selectedParticipantIds;
@@ -762,7 +762,7 @@ void LogViewGui::selectedParticipantChanged()
const QModelIndexList selectedParticipants = m_ParticipantTableView->selectionModel()->selectedRows(0);
for (const QModelIndex &participantIdx : selectedParticipants)
{
// row 0 -> eqId
const QModelIndex idx = m_participantProxyModel->mapToSource(participantIdx);
selectedParticipantIds.insert(m_participantModel->data(idx).toInt());
}
@@ -788,7 +788,7 @@ static void updateFilteredPosTelegramIds(std::set<int> &teleIds, bool bEnable)
}
}
// ---------------------------------------------------------------
void LogViewGui::showTelegramTable()
{
updateFilteredPosTelegramIds(m_CentralTelegramFilterList, m_PosCentralTelCheckBox->isChecked());
@@ -872,7 +872,7 @@ void LogViewGui::syncParticipantList()
m_participantModel->addUpdateParticipants(eqIds, issis, numberOfTelegrams);
}
// ---------------------------------------------------------------
void LogViewGui::changeSettings()
{
LogViewOptionDialog optionDialog(this);
@@ -883,7 +883,7 @@ void LogViewGui::changeSettings()
}
// ---------------------------------------------------------------
QCheckBox* LogViewGui::createRadioButton(const QString& a_buttonName, const QString& a_iconName)
{
QCheckBox* checkBox = new QCheckBox(a_buttonName, this);
@@ -894,10 +894,10 @@ QCheckBox* LogViewGui::createRadioButton(const QString& a_buttonName, const QStr
}
// ---------------------------------------------------------------
// starts the thread, which trys to connect to the injection-
// server of PrtCnv
// ---------------------------------------------------------------
void LogViewGui::startInjectionThread()
{
if (m_InjectionThread)
@@ -933,26 +933,26 @@ void LogViewGui::startInjectionThread()
}
// ---------------------------------------------------------------
// Toggles whether the logfile must be periodically checked
// for changes
// ---------------------------------------------------------------
void LogViewGui::reloadOnOff()
{
m_DoReload = !m_DoReload;
}
// ---------------------------------------------------------------
void LogViewGui::closeEvent(QCloseEvent* a_closeEvent)
{
QSettings settings;
settings.beginGroup(WINDOW_GROUP);
// store the actual toolbox selection
settings.setValue(TOOLBOXINDEX, m_ToolBox->currentIndex());
// store the actual size
settings.setValue(SIZE, size());
QPoint position = pos();
settings.setValue(POS, position);
@@ -960,7 +960,7 @@ void LogViewGui::closeEvent(QCloseEvent* a_closeEvent)
int screenNbr = QGuiApplication::screens().indexOf(scr);
settings.setValue(SCREEN, screenNbr);
// store the splitter-position
const QList<int> splitterSizes = m_Splitter->sizes();
QList<QVariant> splitterSizesAsVariant;
splitterSizesAsVariant.reserve(splitterSizes.size());
@@ -974,14 +974,14 @@ void LogViewGui::closeEvent(QCloseEvent* a_closeEvent)
QMainWindow::closeEvent(a_closeEvent);
}
// ---------------------------------------------------------------
void LogViewGui::updateInjectionStatus(const QString& a_picName, const QString& a_toopTipText)
{
m_InjectionStatus->setPixmap(QPixmap(a_picName));
m_InjectionStatus->setToolTip(a_toopTipText);
}
// ---------------------------------------------------------------
void LogViewGui::onLogTelegramViewDoubleClicked(const QModelIndex &index)
{
if (!m_telegramProxyModel || !m_telegramModel)
@@ -1005,4 +1005,4 @@ void LogViewGui::onSettingsChanged(uint32_t changedFlags)
startInjectionThread();
}
}
} // namespace N_LogView
@@ -1,15 +1,15 @@
// **************************************************************************
//
// (C) Copyright 2009 Swiss SIMTEC AG
//
// **************************************************************************
//
// $HeadURL$
// $LastChangedBy$
// $LastChangedDate$
// $LastChangedRevision$
//
// **************************************************************************
#pragma once
@@ -41,8 +41,11 @@ namespace N_LogView
class LogViewInjectionThread;
class TelegramEdit;
/**
* @author alois.wismer
* @version 1.0
* @created 03-Feb-2010 16:44:53
*/
class LogViewGui : public QMainWindow
{
Q_OBJECT
@@ -60,14 +63,14 @@ protected:
static const QLatin1String POS;
static const QLatin1String SPLITTPOS;
static const QLatin1String TOOLBOXINDEX;
// Central
QGroupBox *m_CentralSelectionGroup;
std::set<int> m_CentralTelegramFilterList;
QCheckBox* m_SentCentralTelCheckBox;
QCheckBox* m_ReceivedCentralTelCheckBox;
QCheckBox* m_PosCentralTelCheckBox;
QCheckBox* m_ackCentralTelCheckBox;
// Tetra
QGroupBox *m_TetraSelectionGroup;
std::set<int> m_TetraTelegramFilterList;
QCheckBox* m_SentTetraTelCheckBox;
@@ -78,7 +81,7 @@ protected:
QCheckBox* m_ReportTetraTelCheckBox;
QCheckBox* m_FragmentedTetraTelCheckBox;
QCheckBox* m_AirInterfaceLoadTetraTelCheckBox;
// Wls
QGroupBox *m_WlsSelectionGroup;
std::set<int> m_WlsTelegramFilterList;
QCheckBox* m_SentWlsTelCheckBox;
@@ -114,9 +117,9 @@ protected:
QLabel *m_InjectionStatus;
// ausstg, telcount
QHash<int, int> m_participantListTelCount;
// ausstg, issi
QHash<int, int> m_participantListIssi;
QAction *m_reloadAction;
@@ -125,14 +128,16 @@ protected:
protected:
void readTelegramsFromLogFile(const QString& a_fileName, const qint64 a_filePos = 0);
/**
* returns true if the participant was added to the list
*/
void addToParticipantList(const QSharedPointer<LogViewTelegram> &a_telegram);
void syncParticipantList();
QCheckBox* createRadioButton(const QString& a_buttonName, const QString& a_iconName);
/**
* starts the thread, which trys to connect to the injection-server of PrtCnv
*/
void startInjectionThread();
void closeEvent(QCloseEvent* a_closeEvent) override;
@@ -157,25 +162,31 @@ protected slots:
void loadTelegramFile();
/**
* Checks whether the size of actual logfile has changed. If yes, the new log-
* entries will be read and shown within table.
*/
void updateLogfile();
void selectedParticipantChanged();
void showTelegramTable();
//SLOT for creating the ContextMenu
void customMenuRequested(const QPoint &pos);
void changeSettings();
/**
* Toggles whether the logfile must be periodically checked for changes
*/
void reloadOnOff();
/**
*
* @param a_picName
* @param a_toopTipText
*/
void updateInjectionStatus(const QString& a_picName, const QString& a_toopTipText);
void onLogTelegramViewDoubleClicked(const QModelIndex &index);
@@ -1,17 +1,17 @@
// **************************************************************************
//
// (C) Copyright 2009 Swiss SIMTEC AG
//
// **************************************************************************
//
// $HeadURL$
// $LastChangedBy$
// $LastChangedDate$
// $LastChangedRevision$
//
// **************************************************************************
// manual class headers
#include "LogViewInjectionThread.hpp"
#include "LogViewTelegram.hpp"
@@ -30,13 +30,13 @@ LogViewInjectionThread::LogViewInjectionThread()
, m_Socket(nullptr)
, m_Timer(nullptr)
{
// load the settings (and write default-values if not defined)
QSettings settings;
settings.beginGroup(LogViewOptionDialog::INJECTION_GROUP);
m_Hostname = settings.value(LogViewOptionDialog::INJECTION_HOSTNAME).toString();
if (m_Hostname.isEmpty())
{
// set default-hostname if nothing was set
m_Hostname = QLatin1String("localhost");
settings.setValue(LogViewOptionDialog::INJECTION_HOSTNAME, m_Hostname);
}
@@ -48,7 +48,7 @@ LogViewInjectionThread::LogViewInjectionThread()
}
}
// ---------------------------------------------------------------
void LogViewInjectionThread::run()
{
emit updateStatus(QLatin1String(":/image/RedLamp.png"),
@@ -59,7 +59,7 @@ void LogViewInjectionThread::run()
}
// ---------------------------------------------------------------
void LogViewInjectionThread::setPort(uint16_t port)
{
m_Port = port;
@@ -69,17 +69,17 @@ void LogViewInjectionThread::setPort(uint16_t port)
}
// ---------------------------------------------------------------
bool LogViewInjectionThread::isSendingPossible() const
{
return m_SendingPossible;
}
// ---------------------------------------------------------------
void LogViewInjectionThread::tryToConnect()
{
//m_Timer->setInterval(3000);
if (!m_Socket)
{
m_Socket = new QTcpSocket(this);
@@ -87,7 +87,7 @@ void LogViewInjectionThread::tryToConnect()
connect(m_Socket, &QTcpSocket::disconnected, this, &LogViewInjectionThread::doDisconnect);
}
// we need a timer for retrying connection
if (!m_Timer)
{
m_Timer = new QTimer(this);
@@ -101,7 +101,7 @@ void LogViewInjectionThread::tryToConnect()
}
// ---------------------------------------------------------------
void LogViewInjectionThread::doConnect()
{
INFO_LOG(m_logger) << "LogView has successful connected to injection-server of TETRA-If";
@@ -112,7 +112,7 @@ void LogViewInjectionThread::doConnect()
}
// ---------------------------------------------------------------
void LogViewInjectionThread::doDisconnect()
{
INFO_LOG(m_logger) << "LogView was disconnected from injection-server of TETRA-If";
@@ -123,7 +123,7 @@ void LogViewInjectionThread::doDisconnect()
}
// ---------------------------------------------------------------
void LogViewInjectionThread::sendTelegram(LogViewTelegram* a_telegram, const bool a_doSendAsCentralTelegram)
{
INFO_LOG(m_logger) << "inject " << (a_doSendAsCentralTelegram ? "central" : "Tetra") << " telegram";
@@ -140,4 +140,4 @@ void LogViewInjectionThread::sendTelegram(LogViewTelegram* a_telegram, const boo
m_Socket->write(data);
}
}
} // namespace N_LogView
@@ -1,15 +1,15 @@
// **************************************************************************
//
// (C) Copyright 2009 Swiss SIMTEC AG
//
// **************************************************************************
//
// $HeadURL$
// $LastChangedBy$
// $LastChangedDate$
// $LastChangedRevision$
//
// **************************************************************************
#pragma once
@@ -24,8 +24,11 @@ namespace N_LogView
{
class LogViewTelegram;
/**
* @author alois.wismer
* @version 1.0
* @created 05-Aug-2010 16:02:15
*/
class LogViewInjectionThread : public QThread
{
Q_OBJECT
@@ -39,8 +42,11 @@ namespace N_LogView
bool isSendingPossible() const;
/**
*
* @param a_telegram
* @param a_doSendAsCentralTelegram
*/
void sendTelegram(LogViewTelegram* a_telegram, const bool a_doSendAsCentralTelegram);
protected:
@@ -67,8 +73,11 @@ namespace N_LogView
public:
signals:
/**
*
* @param a_picName
* @param a_toolTipText
*/
void updateStatus(const QString& a_picName, const QString& a_toolTipText);
};
@@ -25,7 +25,7 @@ int main(int argc, char *argv[])
buf[len] = '\0';
dir = buf;
} else {
// fallback
dir = argv[0];
}
#endif
@@ -1,5 +1,10 @@
/**
* @RDE_HEADER@
* some models for LogViewGui
* $Id$
* $HeadURL$
* $Author$
*/
#include "LogViewModels.hpp"
@@ -10,20 +15,20 @@
namespace N_LogView
{
// ---------------------------------------------------------------
// ---------------------------------------------------------------
int ParticipantModel::rowCount(const QModelIndex &parent) const
{
return parent.isValid() ? 0 : m_particpants.size();
}
// ---------------------------------------------------------------
int ParticipantModel::columnCount(const QModelIndex &parent) const
{
return parent.isValid() ? 0 : 3;
}
// ---------------------------------------------------------------
QVariant ParticipantModel::data(const QModelIndex &index, int role) const
{
if (index.isValid() && index.row() < m_particpants.size())
@@ -58,7 +63,7 @@ QVariant ParticipantModel::data(const QModelIndex &index, int role) const
if (role == Qt::BackgroundRole)
{
if (p.first == 0)
return QVariant();
return QVariant(); // 0 aussen vor lassen
if (m_participantHeatmap.isEmpty())
updateHeatMap();
return m_participantHeatmap.value(p.first);
@@ -67,7 +72,7 @@ QVariant ParticipantModel::data(const QModelIndex &index, int role) const
return QVariant();
}
// ---------------------------------------------------------------
QVariant ParticipantModel::headerData(int section,
Qt::Orientation orientation,
int role) const
@@ -89,7 +94,7 @@ QVariant ParticipantModel::headerData(int section,
return QAbstractTableModel::headerData(section, orientation, role);
}
// ---------------------------------------------------------------
void ParticipantModel::clearParticipants()
{
beginResetModel();
@@ -99,7 +104,7 @@ void ParticipantModel::clearParticipants()
endResetModel();
}
// ---------------------------------------------------------------
bool ParticipantModel::addUpdateParticipants(const QVector<int> &eqIds,
const QVector<int> &issis,
const QVector<int> &numberOfTelegrams)
@@ -130,13 +135,13 @@ bool ParticipantModel::addUpdateParticipants(const QVector<int> &eqIds,
return true;
}
// ---------------------------------------------------------------
void ParticipantModel::updateHeatMap() const
{
int maxNumberOfTelegrams = 0;
for (auto it = m_particpantMap.begin(); it != m_particpantMap.end(); ++it)
{
if (it.key() == 0)
if (it.key() == 0) // EqId 0 aussen vor lassen
continue;
maxNumberOfTelegrams = std::max(it.value(), maxNumberOfTelegrams);
}
@@ -146,7 +151,7 @@ void ParticipantModel::updateHeatMap() const
for (auto it = m_particpantMap.begin(); it != m_particpantMap.end(); ++it)
{
const int eqId = it.key();
if (eqId == 0)
if (eqId == 0) // EqId 0 aussen vor lassen
continue;
const int nbrTelegrams = it.value();
@@ -159,20 +164,20 @@ void ParticipantModel::updateHeatMap() const
}
}
// ---------------------------------------------------------------
// ---------------------------------------------------------------
int TelegramModel::rowCount(const QModelIndex &parent) const
{
return parent.isValid() ? 0 : m_telegrams.size();
}
// ---------------------------------------------------------------
int TelegramModel::columnCount(const QModelIndex &parent) const
{
return parent.isValid() ? 0 : 6;
}
// ---------------------------------------------------------------
QVariant TelegramModel::data(const QModelIndex &index, int role) const
{
if (index.isValid() && index.row() < m_telegrams.size())
@@ -226,7 +231,7 @@ QVariant TelegramModel::data(const QModelIndex &index, int role) const
return QVariant();
}
// ---------------------------------------------------------------
QVariant TelegramModel::headerData(int section,
Qt::Orientation orientation,
int role) const
@@ -257,7 +262,7 @@ QVariant TelegramModel::headerData(int section,
return QAbstractTableModel::headerData(section, orientation, role);
}
// ---------------------------------------------------------------
void TelegramModel::clearTelegrams()
{
beginResetModel();
@@ -265,7 +270,7 @@ void TelegramModel::clearTelegrams()
endResetModel();
}
// ---------------------------------------------------------------
void TelegramModel::appendTelegrams(const QVector<QSharedPointer<LogViewTelegram> > &telegrams)
{
if (telegrams.isEmpty())
@@ -275,7 +280,7 @@ void TelegramModel::appendTelegrams(const QVector<QSharedPointer<LogViewTelegram
endInsertRows();
}
// ---------------------------------------------------------------
void TelegramModel::appendTelegram(const QSharedPointer<LogViewTelegram> &telegram)
{
beginInsertRows(QModelIndex(), m_telegrams.size(), m_telegrams.size());
@@ -283,7 +288,7 @@ void TelegramModel::appendTelegram(const QSharedPointer<LogViewTelegram> &telegr
endInsertRows();
}
// ---------------------------------------------------------------
QSharedPointer<LogViewTelegram> TelegramModel::telegram(int row) const
{
if (row >= 0 && row < m_telegrams.size())
@@ -291,8 +296,8 @@ QSharedPointer<LogViewTelegram> TelegramModel::telegram(int row) const
return QSharedPointer<LogViewTelegram>();
}
// ---------------------------------------------------------------
// ---------------------------------------------------------------
void TelegramProxyModel::setFilterByEquipmentIds(bool bFilterByEquipmentIds)
{
if (m_bFilterByEquipmentIds == bFilterByEquipmentIds)
@@ -304,7 +309,7 @@ void TelegramProxyModel::setFilterByEquipmentIds(bool bFilterByEquipmentIds)
endFilterChange();
}
// ---------------------------------------------------------------
void TelegramProxyModel::setAllowedEquipmentIds(const std::set<int> &allowedEquipmentIds)
{
if (m_allowedEquipmentIds == allowedEquipmentIds)
@@ -316,7 +321,7 @@ void TelegramProxyModel::setAllowedEquipmentIds(const std::set<int> &allowedEqui
endFilterChange();
}
// ---------------------------------------------------------------
void TelegramProxyModel::setFilteredCentralTelegramIds(const std::set<int> &filteredCentralTelegramIds)
{
if (m_filteredCentralTelegramIds == filteredCentralTelegramIds)
@@ -328,7 +333,7 @@ void TelegramProxyModel::setFilteredCentralTelegramIds(const std::set<int> &filt
endFilterChange();
}
// ---------------------------------------------------------------
void TelegramProxyModel::setFilteredTetraTelegramIds(const std::set<int> &filteredTetraTelegramIds)
{
if (m_filteredTetraTelegramIds == filteredTetraTelegramIds)
@@ -340,7 +345,7 @@ void TelegramProxyModel::setFilteredTetraTelegramIds(const std::set<int> &filter
endFilterChange();
}
// ---------------------------------------------------------------
void TelegramProxyModel::setFilteredWlsTelegramIds(const std::set<int> &filteredWlsTelegramIds)
{
if (m_filteredWlsTelegramIds == filteredWlsTelegramIds)
@@ -353,7 +358,7 @@ void TelegramProxyModel::setFilteredWlsTelegramIds(const std::set<int> &filtered
}
// ---------------------------------------------------------------
void TelegramProxyModel::setFilterCentralTelegrams(N_CoPrtCnv::CoPrtCnvLogHeader::E_CoPrtCnvProtocol direction,
bool bFilter)
{
@@ -371,7 +376,7 @@ void TelegramProxyModel::setFilterCentralTelegrams(N_CoPrtCnv::CoPrtCnvLogHeader
endFilterChange();
}
// ---------------------------------------------------------------
void TelegramProxyModel::setFilterTetraTelegrams(N_CoPrtCnv::CoPrtCnvLogHeader::E_CoPrtCnvProtocol direction,
bool bFilter)
{
@@ -389,7 +394,7 @@ void TelegramProxyModel::setFilterTetraTelegrams(N_CoPrtCnv::CoPrtCnvLogHeader::
endFilterChange();
}
// ---------------------------------------------------------------
void TelegramProxyModel::setFilterTetraPDU(N_CoPrtCnv::CoPrtCnvRadioTelegram::E_PDU_Type pduType,
bool bFilter)
{
@@ -424,7 +429,7 @@ void TelegramProxyModel::setFilterWlsTelegrams(N_CoPrtCnv::CoPrtCnvLogHeader::E_
endFilterChange();
}
// ---------------------------------------------------------------
void TelegramProxyModel::setFilterTetraLogin(bool bFilter)
{
if (m_bFilterLoginTelegrams == bFilter)
@@ -436,7 +441,7 @@ void TelegramProxyModel::setFilterTetraLogin(bool bFilter)
endFilterChange();
}
// ---------------------------------------------------------------
void TelegramProxyModel::setFilterTetraFragmented(bool bFilter)
{
if (m_bFilterFragmentedTelegrams == bFilter)
@@ -448,7 +453,7 @@ void TelegramProxyModel::setFilterTetraFragmented(bool bFilter)
endFilterChange();
}
// ---------------------------------------------------------------
QSharedPointer<LogViewTelegram> TelegramProxyModel::telegram(int row) const
{
const TelegramModel *tm = qobject_cast<TelegramModel *>(sourceModel());
@@ -458,7 +463,7 @@ QSharedPointer<LogViewTelegram> TelegramProxyModel::telegram(int row) const
return tm->telegram(srcRow);
}
// ---------------------------------------------------------------
bool TelegramProxyModel::lessThan(const QModelIndex &left, const QModelIndex &right) const
{
if (left.column() != right.column())
@@ -489,10 +494,10 @@ bool TelegramProxyModel::lessThan(const QModelIndex &left, const QModelIndex &ri
return QSortFilterProxyModel::lessThan(left, right);
}
// ---------------------------------------------------------------
bool TelegramProxyModel::filterAcceptsRow(int source_row, const QModelIndex &source_parent) const
{
// TODO: optimize
const TelegramModel *tm = qobject_cast<TelegramModel *>(sourceModel());
if (!tm)
return QSortFilterProxyModel::filterAcceptsRow(source_row, source_parent);
@@ -578,4 +583,4 @@ bool TelegramProxyModel::filterAcceptsRow(int source_row, const QModelIndex &sou
}
return true;
}
}
} // namespace N_LogView;
@@ -1,5 +1,10 @@
/**
* @RDE_HEADER@
* some models for LogViewGui
* $Id$
* $HeadURL$
* $Author$
*/
#pragma once
@@ -37,11 +42,11 @@ public:
protected:
void updateHeatMap() const;
protected:
// eqId , issi
QVector<QPair<int, int> > m_particpants;
// eqid, count telegrams
QHash<int, int> m_particpantMap;
// eqId, QColor for heatmap
mutable QHash<int, QColor> m_participantHeatmap;
};
@@ -106,4 +111,4 @@ protected:
std::set<N_CoPrtCnv::CoPrtCnvRadioTelegram::E_PDU_Type> m_filterTetraPDU;
};
}
} // namespace N_LogView
@@ -1,15 +1,15 @@
// **************************************************************************
//
// (C) Copyright 2009 Swiss SIMTEC AG
//
// **************************************************************************
//
// $HeadURL$
// $LastChangedBy$
// $LastChangedDate$
// $LastChangedRevision$
//
// **************************************************************************
#include "LogViewOptionDialog.hpp"
#include <QtCore/QCoreApplication>
@@ -28,7 +28,7 @@
namespace N_LogView
{
// static member initialization
const QString LogViewOptionDialog::SPEC_FILES = tr("Spezifikations-Dateien (*.x)");
const QString LogViewOptionDialog::KRLOG_FILES = tr("Log-Dateien (*.krlog)");
const QLatin1String LogViewOptionDialog::SPEC_FILES_GROUP("SpecFiles");
@@ -44,13 +44,13 @@ const QLatin1String LogViewOptionDialog::INJECTION_HOSTNAME("InjectionHostname")
const QLatin1String LogViewOptionDialog::INJECTION_PORT("InjectionPort");
// ---------------------------------------------------------------
LogViewOptionDialog::LogViewOptionDialog(QWidget* a_parent)
: QDialog(a_parent)
{
QVBoxLayout* layout = new QVBoxLayout(this);
// telegram specification files
m_Settings.beginGroup(LogViewOptionDialog::SPEC_FILES_GROUP);
QGroupBox* groupBox = new QGroupBox(tr("Telegramm-Spezifikations-Dateien"), this);
layout->addWidget(groupBox);
@@ -81,7 +81,7 @@ LogViewOptionDialog::LogViewOptionDialog(QWidget* a_parent)
groupBox->setLayout(groupLayout);
m_Settings.endGroup();
// injection
m_Settings.beginGroup(LogViewOptionDialog::INJECTION_GROUP);
groupBox = new QGroupBox(tr("Telegram Injection Server"), this);
layout->addWidget(groupBox);
@@ -102,18 +102,18 @@ LogViewOptionDialog::LogViewOptionDialog(QWidget* a_parent)
groupBox->setLayout(injectLayout);
m_Settings.endGroup();
// buttons
layout->addStretch();
QDialogButtonBox* buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel);
connect(buttonBox, &QDialogButtonBox::accepted, this, &LogViewOptionDialog::save);
connect(buttonBox, &QDialogButtonBox::rejected, this, &LogViewOptionDialog::reject);
layout->addWidget(buttonBox);
//setLayout(layout);
}
// ---------------------------------------------------------------
void LogViewOptionDialog::browseP0File()
{
QString newFilename = QFileDialog::getOpenFileName(this,
@@ -131,7 +131,7 @@ void LogViewOptionDialog::browseP0File()
}
// ---------------------------------------------------------------
void LogViewOptionDialog::browseP5File()
{
QString newFilename = QFileDialog::getOpenFileName(this, tr("Protokollkonverter - TETRA Spezifikations-Datei"), m_Settings.value(DIR).toString(), SPEC_FILES);
@@ -145,13 +145,13 @@ void LogViewOptionDialog::browseP5File()
}
}
// ---------------------------------------------------------------
void LogViewOptionDialog::save()
{
uint32_t changedFlags = 0;
// check group wise for changes
// specification files
m_Settings.beginGroup(LogViewOptionDialog::SPEC_FILES_GROUP);
QString string = m_Settings.value(P0_FILENAME).toString();
if ((string != m_P0Edit->text()) ||
@@ -163,7 +163,7 @@ void LogViewOptionDialog::save()
}
m_Settings.endGroup();
// injection settings
m_Settings.beginGroup(LogViewOptionDialog::INJECTION_GROUP);
if ((m_Settings.value(INJECTION_HOSTNAME).toString() != m_InjectHostnameEdit->text()) ||
(m_Settings.value(INJECTION_PORT).toString() != m_InjectPortEdit->text()))
@@ -179,4 +179,4 @@ void LogViewOptionDialog::save()
accept();
}
}
} // namespace N_LogView
@@ -1,15 +1,15 @@
// **************************************************************************
//
// (C) Copyright 2009 Swiss SIMTEC AG
//
// **************************************************************************
//
// $HeadURL$
// $LastChangedBy$
// $LastChangedDate$
// $LastChangedRevision$
//
// **************************************************************************
#pragma once
@@ -20,8 +20,13 @@ class QLineEdit;
namespace N_LogView
{
/**
* This class lets the user view and change the settings of the application
*
* @author alois.wismer
* @version 1.0
* @created 09-Mrz-2010 14:49:40
*/
class LogViewOptionDialog : public QDialog
{
Q_OBJECT
@@ -50,12 +55,14 @@ public:
static const QLatin1String INJECTION_PORT;
/**
*
* @param a_parent a_parent
*/
explicit LogViewOptionDialog(QWidget* a_parent);
signals:
void settingsChanged(uint32_t changed);
void settingsChanged(uint32_t changed); // bitfield of SettingsChangedFlag enum
protected:
@@ -1,15 +1,15 @@
// **************************************************************************
//
// (C) Copyright 2009 Swiss SIMTEC AG
//
// **************************************************************************
//
// $HeadURL$
// $LastChangedBy$
// $LastChangedDate$
// $LastChangedRevision$
//
// **************************************************************************
#include "LogViewSpinBox.hpp"
#include "LogViewField.hpp"
@@ -17,43 +17,43 @@
namespace N_LogView
{
// ---------------------------------------------------------------
LogViewSpinBox::LogViewSpinBox(LogViewField* a_field, QWidget* a_parent, const int a_value)
: QSpinBox(a_parent)
, LogViewWidget(a_field, this, a_parent, false)
{
// set range
uint16_t maxArraySize = a_field->maxArraySize();
setRange(0, maxArraySize);
// set the actual value
setValue(a_value);
// set tooltip-text
setToolTip(tr("<nobr>Wertebereich: 0..%1</nobr>").arg(maxArraySize));
// connect
connect(this, &LogViewSpinBox::editingFinished,
this, &LogViewSpinBox::finishEditing);
}
// ---------------------------------------------------------------
void LogViewSpinBox::finishEditing()
{
emit valueEditingFinished(text().toInt());
}
// ---------------------------------------------------------------
// Writes the content into telegram.
// Returns true if successful.
// ---------------------------------------------------------------
bool LogViewSpinBox::saveContent(LogViewTelegram* a_telegram)
{
Q_UNUSED(a_telegram);
// not yet implemented
return false;
}
}
} // namespace N_LogView
@@ -1,15 +1,15 @@
// **************************************************************************
//
// (C) Copyright 2009 Swiss SIMTEC AG
//
// **************************************************************************
//
// $HeadURL$
// $LastChangedBy$
// $LastChangedDate$
// $LastChangedRevision$
//
// **************************************************************************
#pragma once
@@ -18,26 +18,41 @@
namespace N_LogView
{
/**
* Used for changing size of dyn. arrays.
*
* @author alois.wismer
* @version 1.0
* @created 25-Mai-2010 10:39:45
*/
class LogViewSpinBox : public QSpinBox, public LogViewWidget
{
Q_OBJECT
public:
/**
*
* @param a_field
* @param a_parent
* @param a_value
*/
LogViewSpinBox(LogViewField* a_field, QWidget* a_parent, const int a_value);
/**
* Writes the content into telegram.
* Returns true if successful.
*
* @param a_telegram
*/
bool saveContent(LogViewTelegram* a_telegram) override;
protected slots:
void finishEditing();
signals:
/**
*
* @param a_newValue
*/
void valueEditingFinished(int a_newValue);
};
@@ -1,15 +1,15 @@
// **************************************************************************
//
// (C) Copyright 2009 Swiss SIMTEC AG
//
// **************************************************************************
//
// $HeadURL$
// $LastChangedBy$
// $LastChangedDate$
// $LastChangedRevision$
//
// **************************************************************************
#include "LogViewTabWidget.hpp"
#include <QtWidgets/QFrame>
@@ -36,14 +36,14 @@ LogViewTabWidget::LogViewTabWidget(LogViewField* a_field, LogViewTelegramDialog*
}
// ---------------------------------------------------------------
void LogViewTabWidget::changeSize(const int a_newSize)
{
// add new tabs
for (int i = count(); i < a_newSize; i++)
addTab(m_Field, true, i);
// remove old tabs
while (count() > a_newSize)
{
QStringList path = m_Field->jsonPath();
@@ -56,19 +56,19 @@ void LogViewTabWidget::changeSize(const int a_newSize)
setVisible(a_newSize > 0);
m_TelegramDialog->makePretty();
m_TelegramDialog->makePretty(); // fixme: funktioniert so nicht, muss als signal realisiert werden
}
// ---------------------------------------------------------------
// Writes the content into telegram.
// Returns true if successful.
// ---------------------------------------------------------------
bool LogViewTabWidget::saveContent(LogViewTelegram* a_telegram)
{
if (a_telegram->isJsonTelegram())
return true;
// if m_SpinBox is NULL, we have a static array => no size has to be stored
if (m_SpinBox)
{
if (!isValid())
@@ -79,7 +79,7 @@ bool LogViewTabWidget::saveContent(LogViewTelegram* a_telegram)
}
// ---------------------------------------------------------------
void LogViewTabWidget::addTab(LogViewField* a_field, const bool a_isEmpty, int arrayIdx)
{
if (arrayIdx < 0)
@@ -122,11 +122,11 @@ void LogViewTabWidget::addTab(LogViewField* a_field, const bool a_isEmpty, int a
}
m_TelegramDialog->showTree(childTree, box);
// todo: sind nach dem dyn. array noch weitere Felder, so wird addTab nicht richtig funktionieren, weil die
// neuen Felder des Tabs am Ende von m_EditInfoList hinzugefügt werden => diese müssen mittendrin (an der richtigen
// position) eingefügt werden.
// update spinbox
if (m_SpinBox)
{
int spinValue = m_SpinBox->value();
@@ -137,4 +137,4 @@ void LogViewTabWidget::addTab(LogViewField* a_field, const bool a_isEmpty, int a
setVisible(true);
}
}
} // namespace N_LogView
@@ -1,15 +1,15 @@
// **************************************************************************
//
// (C) Copyright 2009 Swiss SIMTEC AG
//
// **************************************************************************
//
// $HeadURL$
// $LastChangedBy$
// $LastChangedDate$
// $LastChangedRevision$
//
// **************************************************************************
#pragma once
@@ -23,8 +23,13 @@ namespace N_LogView
class LogViewTelegramDialog;
class LogViewSpinBox;
/**
* Used for arrays of structures
*
* @author alois.wismer
* @version 1.0
* @created 26-Mai-2010 17:12:30
*/
class LogViewTabWidget : public QTabWidget, public LogViewWidget
{
Q_OBJECT
@@ -36,8 +41,10 @@ namespace N_LogView
void addTab(LogViewField* a_field, const bool a_isEmpty, int arrayIdx);
public slots:
/**
*
* @param a_newSize
*/
void changeSize(const int a_newSize);
protected:
@@ -1,17 +1,17 @@
// **************************************************************************
//
// (C) Copyright 2009 Swiss SIMTEC AG
//
// **************************************************************************
//
// $HeadURL$
// $LastChangedBy$
// $LastChangedDate$
// $LastChangedRevision$
//
// **************************************************************************
// manual class headers
#include "LogViewTableWidget.hpp"
#include "LogViewField.hpp"
#include <QtWidgets/QHeaderView>
@@ -55,18 +55,18 @@ LogViewTableWidget::LogViewTableWidget(LogViewField* a_field, QWidget* a_parent,
}
setAlternatingRowColors(true);
// make pretty
// horizontalHeader()->setResizeMode(2, QHeaderView::Stretch);
updateToolTip();
// for debugging only
// INFO_LOG(m_logger) << "type=" << static_cast<const LogViewXdrStandardType*>(a_field->getXdrElement())->getValueKind();
// INFO_LOG(m_logger) << "name=" << static_cast<const LogViewXdrStandardType*>(a_field->getXdrElement())->getName().toStdString();
// a_field->getXdrElement()->dump();
// fill in the values
// fixme: implementiere den Fall isHasContent() false
int nbrOfRows = a_field->valueListSize();
setRowCount(nbrOfRows);
for (int i = 0; i < nbrOfRows; i++)
@@ -74,20 +74,20 @@ LogViewTableWidget::LogViewTableWidget(LogViewField* a_field, QWidget* a_parent,
makePretty();
// connect signals
connect(this, &LogViewTableWidget::itemChanged,
this, &LogViewTableWidget::checkAndOvertakeContent);
}
// ---------------------------------------------------------------
void LogViewTableWidget::changeSize(const int a_newSize)
{
setRowCount(a_newSize);
disconnect(this, &LogViewTableWidget::itemChanged,
this, &LogViewTableWidget::checkAndOvertakeContent);
// check and set the new fields
for (int i = 0; i < a_newSize; i++)
changeRow(i, QLatin1String("0"));
@@ -100,14 +100,14 @@ void LogViewTableWidget::changeSize(const int a_newSize)
}
// ---------------------------------------------------------------
void LogViewTableWidget::changeRow(const int a_rowIndex, const QString& a_value)
{
// INFO_LOG(m_logger) << "a_rowIndex=" << a_rowIndex << " a_value=" << a_value.toStdString();
if (m_IsEnum)
{
// enum
QWidget* enumItem = cellWidget(a_rowIndex, 0);
if (!enumItem)
setCellWidget(a_rowIndex, 0, new LogViewEnumEdit(m_Field, this, m_Readonly, a_rowIndex));
@@ -117,12 +117,12 @@ void LogViewTableWidget::changeRow(const int a_rowIndex, const QString& a_value)
QFont font;
font.setStyleHint(QFont::TypeWriter);
font.setFamily(QString());
// decimal
QTableWidgetItem* decItem = item(a_rowIndex, 0);
if (!decItem)
{
decItem = new QTableWidgetItem();
//decItem->setData(Qt::DisplayRole, 0);
decItem->setText(a_value);
decItem->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled);
if (!m_Readonly)
@@ -134,7 +134,7 @@ void LogViewTableWidget::changeRow(const int a_rowIndex, const QString& a_value)
setItem(a_rowIndex, 0, decItem);
}
// hexadecimal
QTableWidgetItem* hexItem = item(a_rowIndex, 1);
if (!hexItem)
{
@@ -145,7 +145,7 @@ void LogViewTableWidget::changeRow(const int a_rowIndex, const QString& a_value)
setItem(a_rowIndex, 1, hexItem);
}
// binary
if (!m_IsFloat)
{
QTableWidgetItem* binItem = item(a_rowIndex, 2);
@@ -159,14 +159,14 @@ void LogViewTableWidget::changeRow(const int a_rowIndex, const QString& a_value)
}
}
// set the values
checkAndOvertakeContent(decItem);
makePretty();
}
}
// ---------------------------------------------------------------
void LogViewTableWidget::checkAndOvertakeContent(QTableWidgetItem* a_changedItem)
{
if (a_changedItem->column() != 0) return;
@@ -179,30 +179,30 @@ void LogViewTableWidget::checkAndOvertakeContent(QTableWidgetItem* a_changedItem
int64_t intValue = 0;
double floatValue = 0.0;
// get the calculated and checked value
if (m_IsFloat)
floatValue = getFloat(text, (uint64_t&)intValue, ok, true);
else
intValue = getInteger(text, ok);
// handle errors
if (!ok)
{
setFocus();
setCurrentCell(row, 0);
// selectAll();
setCurrentCell(row, 0); // todo: funktioniert nicht
return;
}
// set the decimal value
QTableWidgetItem* decField = item(row, 0);
if (decField) decField->setText(QString::number(m_IsFloat ? floatValue : intValue));
// set the hex value
QTableWidgetItem* hexField = item(row, 1);
if (hexField) hexField->setText(toHex(intValue));
// set the binary value
if (!m_IsFloat)
{
QTableWidgetItem* binField = item(row, 2);
@@ -211,33 +211,33 @@ void LogViewTableWidget::checkAndOvertakeContent(QTableWidgetItem* a_changedItem
}
// ---------------------------------------------------------------
void LogViewTableWidget::makePretty()
{
//horizontalHeader()->setResizeMode(2, QHeaderView::Stretch);
resizeColumnsToContents();
resizeRowsToContents();
// set the height of table-widget
//// QWidget* cellWdg = tableWidget->cellWidget(0, 0);
// int showRows = 7;
// if (m_Field->getValueListSize() < (showRows-1))
// {
// showRows = m_Field->getValueListSize()+1;
// setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
// }
// else
// {
// setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded);
// }
// setFixedHeight(showRows*tableWidget->rowHeight(0));
}
// ---------------------------------------------------------------
// Writes the content into telegram.
// Returns true if successful.
// ---------------------------------------------------------------
bool LogViewTableWidget::saveContent(LogViewTelegram* a_telegram)
{
if (!isValid())
@@ -271,14 +271,14 @@ bool LogViewTableWidget::saveContent(LogViewTelegram* a_telegram)
{
arraySize = rowCount();
a_telegram->setUIntX(LogViewTelegram::SIZE_CENTRAL_DYN_ARRAY_SIZE, arraySize);
// fixme: bei vielen Telegrammen muss Länge auf die Länge des Textes gesetzt werden. Dies kann nicht automatisch gemacht werden. Aber vielleicht kann man schauen, ob vor dem dyn. Array ein Feld Länge vorkommt, oder hartcodieren, oder konfigurierbaren
}
else
{
// todo: teste mit opaque[]
arraySize = m_Field->maxArraySize();
}
// copy the data
INFO_LOG(m_logger) << "arraySize=" << arraySize;
for (int i = 0; i < arraySize; i++)
{
@@ -309,4 +309,4 @@ bool LogViewTableWidget::saveContent(LogViewTelegram* a_telegram)
return true;
}
}
} // namespace N_LogView
@@ -1,15 +1,15 @@
// **************************************************************************
//
// (C) Copyright 2009 Swiss SIMTEC AG
//
// **************************************************************************
//
// $HeadURL$
// $LastChangedBy$
// $LastChangedDate$
// $LastChangedRevision$
//
// **************************************************************************
#pragma once
@@ -19,16 +19,25 @@
namespace N_LogView
{
/**
* Used for arrays of data (opaque)
*
* @author alois.wismer
* @version 1.0
* @created 25-Mai-2010 09:34:24
*/
class LogViewTableWidget : public QTableWidget, public LogViewWidget
{
Q_OBJECT
public:
LogViewTableWidget(LogViewField* a_field, QWidget* a_parent, const bool a_readonly, NGL::INGLLogger& logger);
/**
* Writes the content into telegram.
* Returns true if successful.
*
* @param a_telegram
*/
bool saveContent(LogViewTelegram* a_telegram) override;
public slots:
File diff suppressed because it is too large. Load diff
@@ -1,15 +1,15 @@
// **************************************************************************
//
// (C) Copyright 2009 Swiss SIMTEC AG
//
// **************************************************************************
//
// $HeadURL$
// $LastChangedBy$
// $LastChangedDate$
// $LastChangedRevision$
//
// **************************************************************************
#pragma once
@@ -32,14 +32,29 @@ namespace N_LogView
class LogViewTetraTelegramsParser;
class LogViewXdrParser;
class LogViewXdrType;
/**
* The header and the data of a logged or a edited telegram.
*
* Writing telegrams:
* 1. allocate a telegram with the constructor LogViewTelegram(N_CoPrtCnv::
* CoPrtCnvLogHeader::e_DestProtocolCentral, telegramId)
* 2. prepare with resetOffset()
* 3. write data with setUIntX()
* 4. finish with setNewSize();
*
* @author alois.wismer
* @version 1.0
* @created 04-Feb-2010 13:15:43
*/
class LogViewTelegram final
{
public:
/**
* @author alois.wismer
* @version 1.0
* @created 12-Mrz-2010 11:04:14
*/
enum E_Validity
{
e_NotYetEvaluated,
@@ -47,8 +62,11 @@ namespace N_LogView
e_Invalid
};
/**
* @author alois.wismer
* @version 1.0
* @created 05-Mai-2010 09:07:22
*/
enum E_Column
{
e_ColName,
@@ -61,55 +79,88 @@ namespace N_LogView
~LogViewTelegram();
/**
* The size of the field which defines the size of the dyn. array for central-
* telegrams
*/
static const uint16_t SIZE_CENTRAL_DYN_ARRAY_SIZE;
/**
* Copy ctor
*/
LogViewTelegram(const LogViewTelegram &o);
// no assignment (needed)
LogViewTelegram &operator=(const LogViewTelegram &o) = delete;
/**
* Constructor for new telegrams (only receive central-telegrams are allowd),
* which will be edited
*
* @param a_destination
* @param a_telId
*/
LogViewTelegram(const N_CoPrtCnv::CoPrtCnvLogHeader::E_CoPrtCnvProtocol a_destination,
int telegramId);
/**
* Constructor for existing telegrams
*
* @param a_destination
* @param a_unixTime
* @param a_telegramData
* @param a_telegramSize
*/
LogViewTelegram(const N_CoPrtCnv::CoPrtCnvLogHeader::E_CoPrtCnvProtocol a_destination,
const quint64 a_unixTime,
const QByteArray &a_telegramData);
/**
* Writes a_value with size a_size at actual position of m_Data (given with
* m_ActOffset). m_ActOffset will be updated after writing data.
* If the size of m_Data is not big enough, it will be made bigger.
*
* @param a_size
* @param a_value
* @param a_byteOrder
*/
void setUIntX(const uint8_t a_size,
quint64 a_value,
const LogViewXdrStandardType::E_ByteOrder a_byteOrder = LogViewXdrStandardType::e_ByteOrderBigEndian);
/**
* Returns true if a_data could be written.
* Returns false if a_offset is outside of range and therefore a_data could not be
* written.
*
* @param a_offset
* @param a_data
*/
bool setData(const uint16_t a_offset, const uint8_t a_data);
/**
* Returns the log-time of the telegram
*/
quint64 getLogTime() const { return m_LogTime; }
quint64 getLogTimeMsec() const;
/**
* Returns the log-time of the telegram as pretty formatted text
*/
QString getLogTimeText() const;
QString getDestinationText() const;
/**
* Returns the gps-time of the telegram
*/
quint64 getGpsTime() const { return m_GpsTime; }
/**
* Returns the GPS-time of the telegram as pretty formatted text. Only telegrams
* from TETRA to central have a GPS-time, for all other telegrams an empty string
* will be returned.
*/
QString getGpsTimeText() const;
@@ -118,12 +169,19 @@ namespace N_LogView
int getParticipantId() const { return m_ParticipantId; }
/**
* Returns the difference between GPS-time and log-time in seconds. Only telegrams
* from TETRA to central have a GPS-time (and therefore only for this telegrams a
* time-difference can be calculated), for all other telegrams 0 will be returned.
*/
int32_t getDelay() const;
/**
* Returns the tool-tip text for the with a_col defined column for this telegram.
* Its content depends on the type and subtype of telegram.
*
* @param a_col
*/
QString getToolTipText(const E_Column a_col);
@@ -172,20 +230,28 @@ namespace N_LogView
QByteArray getData(QJsonDocument::JsonFormat format = QJsonDocument::JsonFormat::Compact) const;
/**
* The time to wait after sending this telegram in milliseconds.
*/
uint32_t getWaitTime() const { return m_WaitTime; }
/**
* The time to wait after sending this telegram in milliseconds.
*
* @param newVal
*/
void setWaitTime(uint32_t newVal) { m_WaitTime = newVal; }
/**
* The name of the telegram, shown in edit-list
*/
QString getName() const { return m_Name; }
/**
* The name of the telegram, shown in edit-list
*
* @param newVal
*/
void setName(const QString &newVal) { m_Name = newVal; }
@@ -197,8 +263,9 @@ namespace N_LogView
void actualizeGpsTime();
/**
* Create the tooltip text for the column 'Name'
*/
void createToolTipTextForColName();
@@ -209,31 +276,40 @@ namespace N_LogView
protected:
/**
* The name of the telegram, shown in edit-list
*/
QString m_Name;
/**
* The tooltip text for caching purposes
*/
std::vector<QString> m_ToolTipText;
/**
* The time to wait after sending this telegram in milliseconds.
*/
uint32_t m_WaitTime;
int m_ParticipantId;
/**
* The ISSI of TETRA-Protocol
*/
uint32_t m_ISSI;
/**
* The allocated size of m_Data. (Used for optimizing of speed)
*/
int m_AllocatedSize;
static const LogViewXdrParser* m_Parser;
uint16_t m_ActOffset;
QVector<uint16_t> m_GpsFieldOffset;
int m_TelId;
/**
* used for dyn. array in TETRA-Protocol
*/
uint32_t m_LastUnsignedValue;
/**
* This value will be used for the dyn-array-method e_DynArrayMsgLength. This
* value will be subtracted from the message-length to get the size of the dynamic
* array.
*/
uint16_t m_MaxArraySize;
static const uint16_t START_OFFSET_CENTRAL;
static const uint16_t POS_CENTRAL_COUNTER;
@@ -302,55 +378,90 @@ namespace N_LogView
static QString typeFromStructInformation(const StructInformation &si, const QString &name);
static MemberInformation memberFromStructInformation(const StructInformation &si, const QString &name);
/**
*
* @param a_offset
*/
uint16_t getUInt16(const uint16_t a_offset) const;
/**
*
* @param a_offset
*/
uint32_t getUInt32(const uint16_t a_offset) const;
/**
*
* @param a_offset
*/
int32_t getInt32(const uint16_t a_offset) const;
/**
*
* @param a_offset
* @param a_size
* @param a_byteOrder
*/
quint64 getUIntX(const uint16_t a_offset, const uint8_t a_size, const LogViewXdrStandardType::E_ByteOrder a_byteOrder = LogViewXdrStandardType::e_ByteOrderBigEndian) const;
/**
*
* @param a_offset
* @param a_size
* @param a_byteOrder
*/
int32_t getSIntX(const uint16_t a_offset, const uint8_t a_size, const LogViewXdrStandardType::E_ByteOrder a_byteOrder = LogViewXdrStandardType::e_ByteOrderBigEndian) const;
/**
*
* @param a_offset
* @param a_size
*/
char getChar(const uint16_t a_offset, const uint8_t a_size) const;
/**
*
* @param a_standardType
* @param a_offset
* @param a_arraySize
*/
LogViewField* getContent(const LogViewXdrStandardType* a_standardType, uint16_t& a_offset, const uint16_t a_arraySize);
/**
*
* @param a_xdrType
*/
bool isScalar(const LogViewXdrType* a_xdrType) const;
/**
*
* @param a_errorText
* @param a_title
*/
void showMessageBox(const QString& a_errorText, const QString& a_title = QObject::tr("Invalid telegram")) const;
/**
*
* @param a_offset
*/
uint16_t getDynArraySize(uint16_t& a_offset) const;
/**
*
* @param a_name
* @param a_value
*/
static QString formatToolTipLine(const QString& a_name, const uint32_t a_value)
{
return formatToolTipLine(a_name, QString::number(a_value), a_value);
}
/**
*
* @param a_name
* @param a_text
* @param a_value
*/
static QString formatToolTipLine(const QString& a_name, const QString& a_text, const uint32_t a_value);
static QString formatToolTipLine(const QString& a_name, const std::string& a_text, const uint32_t a_value)
@@ -358,8 +469,11 @@ namespace N_LogView
return formatToolTipLine(a_name, QString::fromStdString(a_text), a_value);
}
/**
* returns the data-byte at a_offset. Returns 0 if a_offset is outside of range.
*
* @param a_offset
*/
uint8_t getData(const uint16_t a_offset) const;
private:
@@ -1,15 +1,15 @@
// **************************************************************************
//
// (C) Copyright 2009 Swiss SIMTEC AG
//
// **************************************************************************
//
// $HeadURL$
// $LastChangedBy$
// $LastChangedDate$
// $LastChangedRevision$
//
// **************************************************************************
#include "LogViewTelegramDialog.hpp"
#include <utility>
@@ -42,6 +42,9 @@
namespace N_LogView
{
// todo:
// - feld einfärben wenn geändert, wenn falsch
// - mache hartcodierte oder konfigurierbare ranges für spezielle Werte wie GPS-Position: signed 24-bit
@@ -55,7 +58,7 @@ LogViewTelegramDialog::LogViewTelegramDialog(QWidget *a_parent, const bool a_rea
setAttribute(Qt::WA_DeleteOnClose);
}
// ---------------------------------------------------------------
void LogViewTelegramDialog::showDialog(const QSharedPointer<LogViewTelegram> &a_telegram)
{
delete layout();
@@ -71,13 +74,13 @@ void LogViewTelegramDialog::showDialog(const QSharedPointer<LogViewTelegram> &a_
QGridLayout *dialogLayout = new QGridLayout;
if (!m_ReadOnly)
{
// edit wait-time
QLabel *waitTimeLabel = new QLabel(tr("Wartezeit [ms]"), this);
dialogLayout->addWidget(waitTimeLabel, dialogLayout->rowCount(), 0);
m_WaitTimeEdit = new QLineEdit(QString::number(a_telegram->getWaitTime()), this);
dialogLayout->addWidget(m_WaitTimeEdit, dialogLayout->rowCount() - 1, 1);
// edit name
QLabel *nameLabel = new QLabel(tr("Name"), this);
dialogLayout->addWidget(nameLabel, dialogLayout->rowCount(), 0);
m_NameEdit = new QLineEdit(a_telegram->getName(), this);
@@ -89,16 +92,16 @@ void LogViewTelegramDialog::showDialog(const QSharedPointer<LogViewTelegram> &a_
dialogLayout->addWidget(f, dialogLayout->rowCount(), 0, 1, 2);
}
//INFO_LOG(m_logger) << "--------------- create dialog " << fieldTree->getName().toStdString() << "--------------";
//m_fieldTree->dump();
showTree(m_fieldTree.data(), dialogLayout);
if (this->findChild<LogViewTableWidget *>() == nullptr)
dialogLayout->setRowStretch(dialogLayout->rowCount(), 1);
// build the dialog
QVBoxLayout *mainLayout = new QVBoxLayout(this);
// make dialog scrollable
m_contentsWidget = new QWidget;
m_contentsWidget->setLayout(dialogLayout);
@@ -108,7 +111,7 @@ void LogViewTelegramDialog::showDialog(const QSharedPointer<LogViewTelegram> &a_
mainLayout->addWidget(m_ScrollArea);
// buttons
QHBoxLayout *btnLayout = new QHBoxLayout;
btnLayout->addStretch();
showButtons(btnLayout);
@@ -127,19 +130,19 @@ void LogViewTelegramDialog::showDialog(const QSharedPointer<LogViewTelegram> &a_
}
// ---------------------------------------------------------------
void LogViewTelegramDialog::showDataDump(const QSharedPointer<LogViewTelegram> &a_telegram, bool showErrorMessage)
{
QVBoxLayout *layout = new QVBoxLayout;
layout->addWidget(new QLabel(tr("Telegramm-Dump")));
if (showErrorMessage)
// show error-message in dialog
layout->addWidget(new QLabel(tr("Konnte Dialog basierend auf Struktur \'%1\' nicht generieren!").arg(a_telegram->getStructName())));
else
layout->addWidget(new QLabel(tr("HexData from \'%1\' - telegram:").arg(a_telegram->getName())));
// generate the telegram-dump
QString theDump = QLatin1String("<code>");
const QByteArray &data = a_telegram->getData();
for (int i = 0; i < data.size(); i++)
@@ -167,11 +170,11 @@ void LogViewTelegramDialog::showDataDump(const QSharedPointer<LogViewTelegram> &
}
// ---------------------------------------------------------------
void LogViewTelegramDialog::makePretty()
{
return;
// set the size and position of dialog
int sbWidth = m_ScrollArea->width() - m_ScrollArea->viewport()->width();
int wDiff = m_contentsWidget->width() - m_ScrollArea->width();
int hDiff = m_contentsWidget->height() - m_ScrollArea->viewport()->height();
@@ -179,15 +182,15 @@ void LogViewTelegramDialog::makePretty()
int newWidth = std::min(width() + wDiff + sbWidth, screenSize.width() * 9 / 10);
int newHeight = std::min(height() + hDiff, screenSize.height() * 9 / 10);
//setGeometry(winGeo);
//QSize size = settings.value(SIZE, sizeHint()).toSize();
resize(QSize(newWidth, newHeight));
//move(settings.value(POS, QPoint(0, 0)).toPoint());
// --------------------------------------------------------------------
}
// ---------------------------------------------------------------
void LogViewTelegramDialog::showTree(LogViewField *a_fieldTree, QGridLayout *a_box)
{
int i = 0;
@@ -227,7 +230,7 @@ void LogViewTelegramDialog::showTree(LogViewField *a_fieldTree, QGridLayout *a_b
}
// ---------------------------------------------------------------
void LogViewTelegramDialog::fillTelegram(LogViewTelegram *a_telegram)
{
INFO_LOG(m_logger) << "******************************************";
@@ -239,12 +242,12 @@ void LogViewTelegramDialog::fillTelegram(LogViewTelegram *a_telegram)
if (!ptr->isValid())
{
INFO_LOG(m_logger) << ptr->field()->name() << " is invalid";
return;
return; // abort when a value is not vaild
}
}
// now save the values
// -------------------
a_telegram->resetOffset();
a_telegram->clearJsonData();
for (auto ptr : std::as_const(m_EditInfoList))
@@ -258,12 +261,12 @@ void LogViewTelegramDialog::fillTelegram(LogViewTelegram *a_telegram)
}
// ---------------------------------------------------------------
void LogViewTelegramDialog::saveTelegram()
{
fillTelegram(m_Telegram.data());
// save wait-time and name
N_SST::IntegerCalculator calculator;
N_SST::IntegerCalculator::E_Error error;
m_Telegram->setWaitTime(calculator.calc(m_WaitTimeEdit->text().toStdString(), error));
@@ -272,19 +275,19 @@ void LogViewTelegramDialog::saveTelegram()
accept();
}
// ---------------------------------------------------------------
void LogViewTelegramDialog::sendCurrentTelegram()
{
emit sendTelegram(m_Telegram);
}
// ---------------------------------------------------------------
void LogViewTelegramDialog::showButtons(QLayout *a_layout)
{
if (N_CoPrtCnv::CoPrtCnvLogHeader::e_DestProtocolCentral == m_Telegram->getProtocol())
{
QPushButton *btnSend = new QPushButton(QIcon(QLatin1String(":icons/16x16/mail-send.png")), tr("&Send"));
btnSend->setEnabled(true);
btnSend->setEnabled(true); // TODO: Status ob wirklich möglich ggf. überprüfen
connect(btnSend, &QPushButton::clicked, this, &LogViewTelegramDialog::sendCurrentTelegram);
a_layout->addWidget(btnSend);
}
@@ -304,48 +307,48 @@ void LogViewTelegramDialog::showButtons(QLayout *a_layout)
QPushButton *btnOk = new QPushButton(QIcon(QLatin1String(":icons/16x16/dialog-ok-apply.png")), tr("&OK"));
btnOk->setDefault(true);
// fixme: absturz, wenn feld ungültiger wert enthält und ok gedrückt wird
connect(btnOk, &QPushButton::clicked, this, &LogViewTelegramDialog::saveTelegram);
a_layout->addWidget(btnOk);
}
}
// ---------------------------------------------------------------
void LogViewTelegramDialog::showEditField(LogViewField *a_logViewField, QGridLayout *a_box)
{
// INFO_LOG(m_logger) << a_logViewField->getName() <<
// << " a_logViewField->getValueListSize()=" << a_logViewField->getValueListSize()
// << " a_logViewField->isIsDynamicArray()=" << a_logViewField->isIsDynamicArray()
// << " a_logViewField->getValue(0)=" << a_logViewField->getValue(0).toStdString()
// << " a_logViewField->getXdrElement())->getValueKind()=" << (int)(static_cast<const LogViewXdrStandardType*>(a_logViewField->getXdrElement())->getValueKind())
// ;
switch (a_logViewField->valueListSize())
{
case 1:
// 1 field (single or multi-line)
if (m_ReadOnly || !a_logViewField->isDynamicArray() || (LogViewXdrStandardType::e_Character == static_cast<const LogViewXdrStandardType *>(a_logViewField->xdrElement())->getValueKind()))
{
QLabel *label = new QLabel(a_logViewField->cleanName());
a_box->addWidget(label, a_box->rowCount(), 0);
LogViewWidget *valueWidget = nullptr;
//QString value = a_logViewField->getValue(0);
// if (-1 == value.indexOf("<br>") && value.length() < 80)
{
// single line
// -----------
if (LogViewXdrElement::e_KindEnum == a_logViewField->xdrElement()->getKind())
{
// enum => combobox
// ----------------
valueWidget = new LogViewEnumEdit(a_logViewField, this, m_ReadOnly, 0);
}
else
{
if (a_logViewField->isDateTimeField() || a_logViewField->isMSecsField())
{
// date-time-field
// ---------------
valueWidget = new LogViewDateTimeEdit(a_logViewField, this, m_ReadOnly);
}
else
@@ -361,7 +364,7 @@ void LogViewTelegramDialog::showEditField(LogViewField *a_logViewField, QGridLay
case LogViewXdrStandardType::e_Data:
valueWidget = new LogViewValueEdit(a_logViewField, this, m_ReadOnly);
break;
case LogViewXdrStandardType::e_Character:
case LogViewXdrStandardType::e_Character: // Text
valueWidget = new LogViewTextEdit(a_logViewField, this, m_ReadOnly);
break;
}
@@ -370,21 +373,21 @@ void LogViewTelegramDialog::showEditField(LogViewField *a_logViewField, QGridLay
if (valueWidget)
m_EditInfoList.push_back(valueWidget);
}
// else
// {
// // ----------------------------------------------------------------
// // fixme: not used => take away
// // multi-line
// valueWidget = new QTextEdit(value);
// static_cast<QTextEdit*>(valueWidget)->setReadOnly(true);
// // make proper width of widget
// QFontMetrics fm(valueWidget->font());
// // the 0 (at end) are here, because QFontMetrics does not understand the <code> and <b> tags.
// // So not the correct font will be used for calculating the width.
// // The solution here is suboptimal, but will hopefully work with a lot of fonts...
// valueWidget->setMinimumWidth(fm.width("0000: 00 00 00 00 00 00 00")*1.7);
// // ----------------------------------------------------------------
// }
QWidget *w = dynamic_cast<QWidget *>(valueWidget);
if (w)
a_box->addWidget(w, a_box->rowCount() - 1, 1);
@@ -392,24 +395,24 @@ void LogViewTelegramDialog::showEditField(LogViewField *a_logViewField, QGridLay
WARNING_LOG(m_logger) << "Internal error - LogViewWidget is not derived from QWidget... !?";
break;
}
// fall through for not read-only and dyn. array
Q_FALLTHROUGH();
case 0:
if (m_ReadOnly)
{
// no field
a_box->addWidget(new QLabel(tr("Keine %1").arg(a_logViewField->cleanName())));
break;
}
// fall through for not read-only
Q_FALLTHROUGH();
default:
{
// show the title of table
QLabel *label = new QLabel(a_logViewField->cleanName());
a_box->addWidget(label, a_box->rowCount(), 0);
// show the spin-box for changing the dyn. array-size
LogViewSpinBox *spinBox = nullptr;
if (!m_ReadOnly && a_logViewField->isDynamicArray())
{
@@ -422,7 +425,7 @@ void LogViewTelegramDialog::showEditField(LogViewField *a_logViewField, QGridLay
m_EditInfoList.push_back(tableWidget);
a_box->addWidget(tableWidget, a_box->rowCount(), 0, 1, 2);
// connect signals
if (spinBox)
{
connect(spinBox, &LogViewSpinBox::valueEditingFinished,
@@ -434,13 +437,13 @@ void LogViewTelegramDialog::showEditField(LogViewField *a_logViewField, QGridLay
}
// ---------------------------------------------------------------
void LogViewTelegramDialog::showTab(LogViewField *a_logViewField, QGridLayout *a_box)
{
LogViewSpinBox *spinBox = nullptr;
if (!m_ReadOnly && a_logViewField->isDynamicArray())
{
// show the spin-box for changing the dyn. array-size
QLabel *label = new QLabel(a_logViewField->cleanName());
a_box->addWidget(label, a_box->rowCount(), 0);
spinBox = new LogViewSpinBox(a_logViewField, this, 0);
@@ -451,14 +454,14 @@ void LogViewTelegramDialog::showTab(LogViewField *a_logViewField, QGridLayout *a
m_EditInfoList.push_back(dynamic_cast<LogViewWidget *>(a_tabWidget));
a_box->addWidget(a_tabWidget, a_box->rowCount(), 0, 1, 2);
// connect signals
if (spinBox)
{
connect(spinBox, &LogViewSpinBox::valueEditingFinished,
a_tabWidget, &LogViewTabWidget::changeSize);
}
// add the tab
if (a_logViewField->hasContent())
{
for (int i = 0; i < a_logViewField->childCount(); ++i)
@@ -466,7 +469,7 @@ void LogViewTelegramDialog::showTab(LogViewField *a_logViewField, QGridLayout *a
}
}
// ---------------------------------------------------------------
bool LogViewTelegramDialog::removeItemsFromEditInfoList(const QStringList &jsonPath)
{
if (m_EditInfoList.empty())
@@ -496,4 +499,4 @@ bool LogViewTelegramDialog::removeItemsFromEditInfoList(const QStringList &jsonP
}
}
} // namespace N_LogView
@@ -1,15 +1,15 @@
// **************************************************************************
//
// (C) Copyright 2009 Swiss SIMTEC AG
//
// **************************************************************************
//
// $HeadURL$
// $LastChangedBy$
// $LastChangedDate$
// $LastChangedRevision$
//
// **************************************************************************
#pragma once
@@ -29,8 +29,11 @@ class LogViewWidget;
class LogViewTelegram;
class LogViewField;
/**
* @author alois.wismer
* @version 1.0
* @created 09-Feb-2010 15:05:05
*/
class LogViewTelegramDialog : public QDialog
{
Q_OBJECT
@@ -42,8 +45,9 @@ public:
void makePretty();
void showTree(LogViewField *a_fieldTree, QGridLayout *a_box);
/**
* Removes the elements from m_EditInfoList matching the path
*/
bool removeItemsFromEditInfoList(const QStringList &jsonPath);
Q_SIGNALS:
@@ -1,5 +1,10 @@
/**
* @RDE_HEADER@
* some models for LogViewGui
* $Id$
* $HeadURL$
* $Author$
*/
#include "LogViewTelegramEdit.hpp"
@@ -125,16 +130,16 @@ void TelegramEdit::tableViewCustomContextMenu(const QPoint &pos)
{
QMenu menu;
// add, edit and remove telegrams
// ------------------------------
menu.addAction(m_addTeleAction);
menu.addAction(m_editTeleAction);
menu.addAction(m_copyTeleAction);
menu.addAction(m_pasteTeleAction);
menu.addAction(m_deleteTeleAction);
// move telegram up/down
// ---------------------
menu.addSeparator();
menu.addAction(m_moveTeleUpAction);
menu.addAction(m_moveTeleDownAction);
@@ -142,32 +147,32 @@ void TelegramEdit::tableViewCustomContextMenu(const QPoint &pos)
menu.addSeparator();
const bool itemSelected = m_tableView->currentIndex().isValid();
// is it a central-telegram?
bool isCentral = false;
QSharedPointer<LogViewTelegram> tele = m_EditModel->telegram(m_tableView->currentIndex().row());
if (tele)
isCentral = (tele->getProtocol() == N_CoPrtCnv::CoPrtCnvLogHeader::e_DestProtocolCentral);
// inject telegram
// ---------------
if (isInjectionPossible())
{
QAction *action = menu.addAction(QIcon(QLatin1String(":/image/InjectCentral.png")), tr("Injektiere Zentral-Telegramm"));
// only central-telegrams can be injected
action->setEnabled(itemSelected && isCentral);
connect(action, &QAction::triggered, this, &TelegramEdit::injectCentralTelegram);
action = menu.addAction(QIcon(QLatin1String(":/image/InjectTetra.png")), tr("Injektiere Tetra-Telegramm"));
// only central-telegrams can be injected
action->setEnabled(itemSelected && isCentral);
connect(action, &QAction::triggered, this, &TelegramEdit::injectTetraTelegram);
menu.addSeparator();
// send and loop telegrams
// -----------------------
action = menu.addAction(QIcon(QLatin1String(":icons/16x16/mail-send.png")), tr("Sende Telegramm"));
// only central-telegrams can be sent
action->setEnabled(itemSelected && isCentral);
connect(action, &QAction::triggered, this, &TelegramEdit::sendCurrentTelegram);
@@ -184,8 +189,8 @@ void TelegramEdit::tableViewCustomContextMenu(const QPoint &pos)
action->setEnabled(itemSelected);
connect(action, &QAction::triggered, this, &TelegramEdit::sequenceTelegrams);
// load/save telegram-list
// -----------------------
menu.addSeparator();
}
@@ -196,17 +201,17 @@ void TelegramEdit::tableViewCustomContextMenu(const QPoint &pos)
menu.exec(m_tableView->viewport()->mapToGlobal(pos));
}
// ---------------------------------------------------------------
// Adds a_telegram at a_row in table. If there is already a
// telegram it will be overwritten.
// If a_row is -1, the telegram will be added at end.
// If false is false, a_telegram will be ignored, a
// dialog for selecting an empty telegram will be shown
// instead.
// ---------------------------------------------------------------
void TelegramEdit::addTelegram()
{
// add telegram for editing
LogViewTelegramSelectionDialog telegramSelectionDialog(m_tableView);
if (QDialog::Accepted == telegramSelectionDialog.exec())
{
@@ -214,7 +219,7 @@ void TelegramEdit::addTelegram()
telegramSelectionDialog.getSelectedTelegramId()));
m_curEditTelegramRow = m_EditModel->appendTelegram(newTelegram);
// show the edit-telegram-dialog
LogViewTelegramDialog *editTelegramDialog = new LogViewTelegramDialog(m_tableView, false);
connect(editTelegramDialog, &LogViewTelegramDialog::finished,
this, &TelegramEdit::editTelegramDialogFinished);
@@ -238,13 +243,13 @@ QModelIndex TelegramEdit::currentSelectedIndex() const
void TelegramEdit::editTelegramDialogFinished()
{
//model über geänderte Daten informieren
m_EditModel->emitDataChanged(m_curEditTelegramRow);
}
// ---------------------------------------------------------------
// shows a telegram-dialog, where the telegram can be changed.
// ---------------------------------------------------------------
void TelegramEdit::editTelegram()
{
m_curEditTelegramRow = currentSelectedIndex().row();
@@ -255,18 +260,18 @@ void TelegramEdit::editTelegram()
editTelegramDialog->showDialog(currentSelectedTelegram());
}
// ---------------------------------------------------------------
// shows a non-editable telegram-dialog
// ---------------------------------------------------------------
void TelegramEdit::showTelegram()
{
LogViewTelegramDialog *showTelegramDialog = new LogViewTelegramDialog(m_tableView, true);
showTelegramDialog->showDialog(currentSelectedTelegram());
//
// qulonglong dataPtr = m_TelegramTableWidget->item(a_tableWidget->row(), 0)->data(Qt::UserRole).toULongLong();
// LogViewTelegram* telegram = (LogViewTelegram*)dataPtr;
// LogViewTelegramDialog* telegramDialog = new LogViewTelegramDialog(this);
// telegramDialog->showDialog(telegram);
}
void TelegramEdit::deleteTelegram()
@@ -324,7 +329,7 @@ void TelegramEdit::sendTelegram(const QSharedPointer<LogViewTelegram> &a_telegra
void TelegramEdit::loopTelegrams()
{
//gucken ob loop schon gestartet oder nicht
if (m_DoLoop)
{
m_DoLoop = false;
@@ -348,7 +353,7 @@ void TelegramEdit::loopNextTelegram()
if (!m_DoLoop)
return;
++m_currentRowToSend;
// am Ende ?
if (m_currentRowToSend >= m_tableView->model()->rowCount())
m_currentRowToSend = 0;
@@ -363,7 +368,7 @@ void TelegramEdit::loopNextTelegram()
void TelegramEdit::sequenceTelegrams()
{
m_currentRowToSend = currentSelectedIndex().row();
if (m_currentRowToSend < 0)
if (m_currentRowToSend < 0) // invalid index
return;
QSharedPointer<LogViewTelegram> tele = currentSelectedTelegram();
sendTelegram(tele);
@@ -432,7 +437,7 @@ void TelegramEdit::moveDown()
void TelegramEdit::saveTelegramList()
{
// get the filename
QSettings settings;
QString newFilename = QFileDialog::getSaveFileName(m_tableView,
tr("Dateiname der Telegrammliste"),
@@ -443,22 +448,22 @@ void TelegramEdit::saveTelegramList()
if (!newFilename.contains(QLatin1Char('.')))
newFilename += QLatin1String(".tgl");
// save the actual directory
QDir dir;
settings.beginGroup(s_EDIT_TELEGRAM_GROUP());
settings.setValue(s_DIR(), dir.filePath(newFilename));
settings.endGroup();
// save the telegram-list
QFile telegramFile(newFilename);
(void)telegramFile.open(QIODevice::WriteOnly);
QDataStream stream(&telegramFile);
// write the header
uint32_t version = 1;
stream << s_TELEGRAMLIST_FILE_ID() << version;
// write the telegrams
int rows = m_tableView->model()->rowCount();
stream << rows;
for (int i = 0; i < rows; i++)
@@ -493,7 +498,7 @@ void TelegramEdit::loadTelegramListReplace()
void TelegramEdit::loadTelegramList(bool checkAppend)
{
// get the filename
QSettings settings;
QString newFilename = QFileDialog::getOpenFileName(m_tableView,
tr("Dateiname der Telegrammliste"),
@@ -501,24 +506,24 @@ void TelegramEdit::loadTelegramList(bool checkAppend)
s_TELEGRAMLIST_FILES());
if (!newFilename.isEmpty())
{
// save the actual directory
QDir dir;
settings.beginGroup(s_EDIT_TELEGRAM_GROUP());
settings.setValue(s_DIR(), dir.filePath(newFilename));
settings.endGroup();
// delete the actual telegram-list
{
if (!checkAppend)
m_EditModel->clearTelegrams();
}
// load the telegram-list
QFile telegramFile(newFilename);
(void)telegramFile.open(QIODevice::ReadOnly);
QDataStream stream(&telegramFile);
// read the header
QString id;
stream >> id;
if (id != s_TELEGRAMLIST_FILE_ID())
@@ -534,7 +539,7 @@ void TelegramEdit::loadTelegramList(bool checkAppend)
return;
}
// read the telegrams
int rows = 0;
QVector<uint16_t> gpsFieldOffset;
stream >> rows;
@@ -565,13 +570,13 @@ void TelegramEdit::loadTelegramList(bool checkAppend)
}
}
// ---------------------------------------------------------------
bool TelegramEdit::isInjectionPossible() const
{
return m_InjectionThread ? m_InjectionThread->isSendingPossible() : false;
}
// ---------------------------------------------------------------
void TelegramEdit::onSelectionChanged()
{
const QModelIndex idx = currentSelectedIndex();
@@ -583,4 +588,4 @@ void TelegramEdit::onSelectionChanged()
m_moveTeleDownAction->setEnabled(idx.isValid() && idx.row() < m_EditModel->rowCount() - 1);
}
}
} // namespace N_LogView
@@ -1,5 +1,10 @@
/**
* @RDE_HEADER@
* some models for LogViewGui
* $Id$
* $HeadURL$
* $Author$
*/
#pragma once
@@ -1,5 +1,10 @@
/**
* @RDE_HEADER@
* some models for LogViewGui
* $Id$
* $HeadURL$
* $Author$
*/
#include "LogViewTelegramEditModel.hpp"
#include <algorithm>
@@ -7,19 +12,19 @@
namespace N_LogView
{
// ---------------------------------------------------------------
int TelegramEditModel::rowCount(const QModelIndex &parent) const
{
return parent.isValid() ? 0 : m_telegrams.size();
}
// ---------------------------------------------------------------
int TelegramEditModel::columnCount(const QModelIndex &parent) const
{
return parent.isValid() ? 0 : 3;
}
// ---------------------------------------------------------------
QVariant TelegramEditModel::data(const QModelIndex &index, int role) const
{
if (index.isValid() && index.row() < m_telegrams.size())
@@ -47,7 +52,7 @@ QVariant TelegramEditModel::data(const QModelIndex &index, int role) const
return QVariant();
}
// ---------------------------------------------------------------
QVariant TelegramEditModel::headerData(int section,
Qt::Orientation orientation,
int role) const
@@ -69,7 +74,7 @@ QVariant TelegramEditModel::headerData(int section,
return QAbstractTableModel::headerData(section, orientation, role);
}
// ---------------------------------------------------------------
void TelegramEditModel::clearTelegrams()
{
beginResetModel();
@@ -77,7 +82,7 @@ void TelegramEditModel::clearTelegrams()
endResetModel();
}
// ---------------------------------------------------------------
void TelegramEditModel::appendTelegrams(const QVector<QSharedPointer<LogViewTelegram> > &telegrams)
{
if (telegrams.isEmpty())
@@ -87,17 +92,17 @@ void TelegramEditModel::appendTelegrams(const QVector<QSharedPointer<LogViewTele
endInsertRows();
}
// ---------------------------------------------------------------
int TelegramEditModel::appendTelegram(const QSharedPointer<LogViewTelegram> &telegram)
{
beginInsertRows(QModelIndex(), m_telegrams.size(), m_telegrams.size());
m_telegrams.push_back(telegram);
telegram->rebuildJsonString();
endInsertRows();
return m_telegrams.size() - 1;
return m_telegrams.size() - 1; // row
}
// ---------------------------------------------------------------
QSharedPointer<LogViewTelegram> TelegramEditModel::telegram(int row) const
{
if (row >= 0 && row < m_telegrams.size())
@@ -105,7 +110,7 @@ QSharedPointer<LogViewTelegram> TelegramEditModel::telegram(int row) const
return QSharedPointer<LogViewTelegram>();
}
// ---------------------------------------------------------------
bool TelegramEditModel::moveUp(int row)
{
if (row <= 0 || row >= m_telegrams.size())
@@ -116,7 +121,7 @@ bool TelegramEditModel::moveUp(int row)
return true;
}
// ---------------------------------------------------------------
bool TelegramEditModel::moveDown(int row)
{
if (row >= (m_telegrams.size() - 1))
@@ -127,7 +132,7 @@ bool TelegramEditModel::moveDown(int row)
return true;
}
// ---------------------------------------------------------------
void TelegramEditModel::emitDataChanged(int row)
{
QModelIndex top = createIndex(row, 0);
@@ -135,12 +140,12 @@ void TelegramEditModel::emitDataChanged(int row)
emit dataChanged(top, bottom, {Qt::DisplayRole, Qt::ToolTipRole});
}
// ---------------------------------------------------------------
void TelegramEditModel::removeTelegrams(const QSet<int> &rows)
{
QList<int> rowList = rows.values();
std::sort(rowList.begin(), rowList.end());
// von oben her löschen um ein Verschieben der Indizes zu vermeiden
for (int i = rowList.size() - 1 ; i >= 0; --i)
{
int row = rowList.at(i);
@@ -150,7 +155,7 @@ void TelegramEditModel::removeTelegrams(const QSet<int> &rows)
}
}
// ---------------------------------------------------------------
void TelegramEditModel::pasteRows(int row, const QSharedPointer<LogViewTelegram> &tele)
{
if (row < 0 || row > m_telegrams.size())
@@ -160,4 +165,4 @@ void TelegramEditModel::pasteRows(int row, const QSharedPointer<LogViewTelegram>
endInsertRows();
}
}
} // namespace N_LogView
@@ -1,5 +1,10 @@
/**
* @RDE_HEADER@
* some models for LogViewGui
* $Id$
* $HeadURL$
* $Author$
*/
#pragma once
@@ -1,15 +1,15 @@
// **************************************************************************
//
// (C) Copyright 2009 Swiss SIMTEC AG
//
// **************************************************************************
//
// $HeadURL$
// $LastChangedBy$
// $LastChangedDate$
// $LastChangedRevision$
//
// **************************************************************************
#include "LogViewTelegramSelectionDialog.hpp"
#include <QtWidgets/QLabel>
@@ -23,7 +23,7 @@
namespace N_LogView
{
static int s_currentRow = 0;
// ---------------------------------------------------------------
LogViewTelegramSelectionDialog::LogViewTelegramSelectionDialog(QWidget* a_parent)
: QDialog(a_parent)
{
@@ -34,7 +34,7 @@ LogViewTelegramSelectionDialog::LogViewTelegramSelectionDialog(QWidget* a_parent
const auto telegramMap = LogViewTelegram::jsonParser()->telegramsToCreate();
for (auto it = telegramMap.cbegin(); it != telegramMap.cend(); ++it)
{
if (it.key() == 0)
if (it.key() == 0) // ACK
continue;
auto lwi = new QListWidgetItem(it.value() + QStringLiteral(" (%1)").arg(it.key()));
lwi->setData(Qt::UserRole, it.key());
@@ -51,7 +51,7 @@ LogViewTelegramSelectionDialog::LogViewTelegramSelectionDialog(QWidget* a_parent
}
// ---------------------------------------------------------------
void LogViewTelegramSelectionDialog::selectTelegram(QListWidgetItem* a_telegramItem)
{
s_currentRow = m_TelegramList->currentRow();
@@ -59,4 +59,4 @@ void LogViewTelegramSelectionDialog::selectTelegram(QListWidgetItem* a_telegramI
accept();
}
}
} // namespace N_LogView
@@ -1,15 +1,15 @@
// **************************************************************************
//
// (C) Copyright 2009 Swiss SIMTEC AG
//
// **************************************************************************
//
// $HeadURL$
// $LastChangedBy$
// $LastChangedDate$
// $LastChangedRevision$
//
// **************************************************************************
#pragma once
@@ -19,22 +19,29 @@ class QListWidgetItem;
namespace N_LogView
{
/**
* @author alois.wismer
* @version 1.0
* @created 05-Mai-2010 17:24:14
*/
class LogViewTelegramSelectionDialog : public QDialog
{
Q_OBJECT
public:
/**
*
* @param a_parent
*/
explicit LogViewTelegramSelectionDialog(QWidget* a_parent);
int getSelectedTelegramId() const { return m_SelectedTelegramId; }
protected slots:
/**
*
* @param a_telegramItem
*/
void selectTelegram(QListWidgetItem* a_telegramItem);
protected:
@@ -1,5 +1,10 @@
/**
* Parses training_area_telegrams.h
* $Id$
* $HeadURL$
* $Author$
* Created by Christian Ehrlicher, SLSE, 2016-04-14
*/
#include "LogViewTetraTelegramsParser.hpp"
#include <utility>
@@ -67,7 +72,7 @@ static void fillBasemembers(StructInformation &si, const QHash<QString, StructIn
return;
StructInformation base = structs.value(si.baseStruct);
fillBasemembers(base, structs);
si.member = (base.member + si.member);
si.member = (base.member + si.member); // base first
}
bool LogViewTetraTelegramsParser::parse(const QString &filename)
@@ -75,7 +80,7 @@ bool LogViewTetraTelegramsParser::parse(const QString &filename)
m_telegramIdEnum = EnumInformation();
m_enums.clear();
m_structs.clear();
//m_pods.clear(); // only set once
m_visibleTelegrams.clear();
QFile f(filename);
@@ -174,7 +179,7 @@ int LogViewTetraTelegramsParser::parseStruct(const QVector<QStringView> &lines,
continue;
if (base.endsWith(QLatin1Char(',')))
base.chop(1);
if (base.endsWith(QLatin1Char('>')))
if (base.endsWith(QLatin1Char('>'))) // helper template - ignore
{
si.isVisible = true;
continue;
@@ -287,8 +292,8 @@ int LogViewTetraTelegramsParser::parseEnum(const QVector<QStringView> &lines, in
return -1;
enumName = tokens.at(2);
}
if (enumName.endsWith(QLatin1Char(';')))
return iStartPos;
if (enumName.endsWith(QLatin1Char(';'))) // forward decl
return iStartPos; // move to next line
EnumInformation ei;
ei.type = enumName.toString();
@@ -311,7 +316,7 @@ int LogViewTetraTelegramsParser::parseEnum(const QVector<QStringView> &lines, in
{
if (tokens.size() == 4 && tokens.at(0) == QLatin1String("}") && tokens.at(3).endsWith(QLatin1Char(';')) && si)
{
// enum in struct with direct decl of member
MemberInformation mi;
if (ns.isEmpty())
mi.type = ei.type;
@@ -386,7 +391,7 @@ int LogViewTetraTelegramsParser::parseConstraint(const QVector<QStringView> &lin
}
if (tokens.at(0) == QLatin1String("};"))
break;
if (tokens.size() != 8 || tokens.at(2) != QLatin1String("TelegramId"))
if (tokens.size() != 8 || tokens.at(2) != QLatin1String("TelegramId")) // static constexpr TelegramId id() { return TelegramId::INIT; }
{
++i;
continue;
@@ -477,7 +482,7 @@ QVector<QStringView> LogViewTetraTelegramsParser::tokenize(const QStringView &li
const QStringView &token = ret.at(i);
if (token.startsWith(QLatin1String("//")))
{
// all comment after this - merge into one
if (i == ret.size() - 1)
break;
const QStringView &lastToken = ret.last();
@@ -535,4 +540,4 @@ bool LogViewTetraTelegramsParser::validStructTokens(const QVector<QStringView> &
return false;
}
}
} // namespace N_LogView
@@ -1,5 +1,10 @@
/**
* Parses training_area_telegrams.h
* $Id$
* $HeadURL$
* $Author$
* Created by Christian Ehrlicher, SLSE, 2016-04-14
*/
#pragma once
@@ -27,7 +32,7 @@ struct MemberInformation
struct StructInformation
{
QString type;
QString baseStruct;
QString baseStruct; // we only allow one base...
QVector<MemberInformation> member;
bool isVisible = false;
@@ -87,4 +92,4 @@ private:
QHash<int, QString> m_visibleTelegrams;
NGL::INGLLogger &m_logger;
};
}
} // namespace LogView
@@ -1,15 +1,15 @@
// **************************************************************************
//
// (C) Copyright 2009 Swiss SIMTEC AG
//
// **************************************************************************
//
// $HeadURL$
// $LastChangedBy$
// $LastChangedDate$
// $LastChangedRevision$
//
// **************************************************************************
#include "LogViewTextEdit.hpp"
#include "LogViewField.hpp"
@@ -18,7 +18,7 @@
namespace N_LogView
{
// ---------------------------------------------------------------
LogViewTextEdit::LogViewTextEdit(LogViewField* a_field, QWidget* a_parent, const bool a_readonly)
: QLineEdit(a_parent)
, LogViewWidget(a_field, this, a_parent, a_readonly)
@@ -32,12 +32,12 @@ LogViewTextEdit::LogViewTextEdit(LogViewField* a_field, QWidget* a_parent, const
setAlignment(a_field->isRightAligned() ? Qt::AlignRight : Qt::AlignLeft);
}
// set a validator for number of chars
uint16_t maxArraySize = a_field->maxArraySize();
setMaxLength(maxArraySize);
updateToolTip(value);
// make proper width of widget
QFontMetrics fm(font());
#if QT_VERSION < QT_VERSION_CHECK(5, 11, 0)
setMinimumWidth(fm.width(QLatin1Char(' ') + value + QLatin1Char(' ')));
@@ -45,23 +45,23 @@ LogViewTextEdit::LogViewTextEdit(LogViewField* a_field, QWidget* a_parent, const
setMinimumWidth(fm.horizontalAdvance(QLatin1Char(' ') + value + QLatin1Char(' ')));
#endif
// connect signals
connect(this, &LogViewTextEdit::editingFinished,
this, &LogViewTextEdit::checkAndOvertakeContent);
}
// ---------------------------------------------------------------
void LogViewTextEdit::checkAndOvertakeContent()
{
updateToolTip(text());
updateToolTip(text()); // fixme nach jedem zeichen updaten
m_Valid = true;
}
// ---------------------------------------------------------------
// Writes the content into telegram.
// Returns true if successful.
// ---------------------------------------------------------------
bool LogViewTextEdit::saveContent(LogViewTelegram* a_telegram)
{
if (!isValid())
@@ -79,18 +79,18 @@ bool LogViewTextEdit::saveContent(LogViewTelegram* a_telegram)
{
arraySize = content.length();
a_telegram->setUIntX(LogViewTelegram::SIZE_CENTRAL_DYN_ARRAY_SIZE, arraySize);
// fixme: bei vielen Telegrammen muss Länge auf die Länge des Textes gesetzt werden. Dies kann nicht automatisch gemacht werden. Aber vielleicht kann man schauen, ob vor dem dyn. Array ein Feld Länge vorkommt, oder hartcodieren, oder konfigurierbaren
}
else
{
arraySize = m_Field->maxArraySize();
}
// copy the text
for (int i = 0; i < arraySize; i++)
a_telegram->setUIntX(size, i < content.length() ? content[i].toLatin1() : 0);
}
return true;
}
}
} // namespace N_LogView
@@ -1,15 +1,15 @@
// **************************************************************************
//
// (C) Copyright 2009 Swiss SIMTEC AG
//
// **************************************************************************
//
// $HeadURL$
// $LastChangedBy$
// $LastChangedDate$
// $LastChangedRevision$
//
// **************************************************************************
#pragma once
@@ -18,18 +18,31 @@
namespace N_LogView
{
/**
* Used for arrays of char and string.
*
* @author alois.wismer
* @version 1.0
* @created 21-Mai-2010 10:28:05
*/
class LogViewTextEdit : public QLineEdit, public LogViewWidget
{
Q_OBJECT
public:
/**
*
* @param a_field
* @param a_parent
* @param a_readonly
*/
LogViewTextEdit(LogViewField* a_field, QWidget* a_parent, const bool a_readonly);
/**
* Writes the content into telegram.
* Returns true if successful.
*
* @param a_telegram
*/
bool saveContent(LogViewTelegram* a_telegram) override;
protected slots:
@@ -1,15 +1,15 @@
// **************************************************************************
//
// (C) Copyright 2009 Swiss SIMTEC AG
//
// **************************************************************************
//
// $HeadURL$
// $LastChangedBy$
// $LastChangedDate$
// $LastChangedRevision$
//
// **************************************************************************
#include "LogViewValueEdit.hpp"
#include "LogViewField.hpp"
@@ -18,7 +18,7 @@
namespace N_LogView
{
// ---------------------------------------------------------------
LogViewValueEdit::LogViewValueEdit(LogViewField* a_field, QWidget* a_parent, const bool a_readonly)
: QLineEdit(a_parent)
, LogViewWidget(a_field, this, a_parent, a_readonly)
@@ -31,10 +31,10 @@ LogViewValueEdit::LogViewValueEdit(LogViewField* a_field, QWidget* a_parent, con
setText(valueText);
// checkAndOvertakeContent();
updateToolTip(valueText);
// make proper width of widget
QFontMetrics fm(font());
#if QT_VERSION < QT_VERSION_CHECK(5, 11, 0)
setMinimumWidth(fm.width(QLatin1Char(' ') + valueText + QLatin1Char(' ')));
@@ -55,28 +55,28 @@ LogViewValueEdit::LogViewValueEdit(LogViewField* a_field, QWidget* a_parent, con
}
// ---------------------------------------------------------------
void LogViewValueEdit::checkAndOvertakeContent()
{
bool ok;
int64_t intValue = 0;
double floatValue = 0.0;
// get the calculated and checked value
if (m_IsFloat)
floatValue = getFloat(text(), (uint64_t&)intValue, ok);
else
intValue = getInteger(text(), ok);
// handle errors
if (!ok)
{
setFocus();
selectAll();
return;
return; // abort
}
// update
if (m_IsFloat)
setText(QString::number(floatValue));
else
@@ -86,10 +86,10 @@ void LogViewValueEdit::checkAndOvertakeContent()
}
// ---------------------------------------------------------------
// Writes the content into telegram.
// Returns true if successful.
// ---------------------------------------------------------------
bool LogViewValueEdit::saveContent(LogViewTelegram* a_telegram)
{
if (m_Valid)
@@ -97,7 +97,7 @@ bool LogViewValueEdit::saveContent(LogViewTelegram* a_telegram)
bool ok;
if (m_IsFloat)
{
// save the float or double-value
uint64_t valueAsUint64;
const double value = getFloat(text(), valueAsUint64, ok);
if (ok)
@@ -117,7 +117,7 @@ bool LogViewValueEdit::saveContent(LogViewTelegram* a_telegram)
}
else
{
// save the integer-value
qint64 intValue = getInteger(text(), ok);
if (ok)
{
@@ -132,4 +132,4 @@ bool LogViewValueEdit::saveContent(LogViewTelegram* a_telegram)
return false;
}
}
} // namespace N_LogView
@@ -1,15 +1,15 @@
// **************************************************************************
//
// (C) Copyright 2009 Swiss SIMTEC AG
//
// **************************************************************************
//
// $HeadURL$
// $LastChangedBy$
// $LastChangedDate$
// $LastChangedRevision$
//
// **************************************************************************
#pragma once
@@ -18,18 +18,31 @@
namespace N_LogView
{
/**
* Used for scalar signed or unsigned values
*
* @author alois.wismer
* @version 1.0
* @created 20-Mai-2010 14:47:50
*/
class LogViewValueEdit : public QLineEdit, public LogViewWidget
{
Q_OBJECT
public:
/**
*
* @param a_field
* @param a_parent
* @param a_readonly
*/
LogViewValueEdit(LogViewField* a_field, QWidget* a_parent, const bool a_readonly);
/**
* Writes the content into telegram.
* Returns true if successful.
*
* @param a_telegram
*/
bool saveContent(LogViewTelegram* a_telegram) override;
protected:
@@ -1,17 +1,17 @@
// **************************************************************************
//
// (C) Copyright 2009 Swiss SIMTEC AG
//
// **************************************************************************
//
// $HeadURL$
// $LastChangedBy$
// $LastChangedDate$
// $LastChangedRevision$
//
// **************************************************************************
// manual class headers
#include "LogViewWidget.hpp"
#include "LogViewField.hpp"
@@ -23,7 +23,7 @@
namespace N_LogView
{
// ---------------------------------------------------------------
LogViewWidget::LogViewWidget(LogViewField* a_field, QWidget* a_widget, QWidget* a_parent, bool a_readonly)
: m_Readonly(a_readonly)
, m_Valid(true)
@@ -34,21 +34,21 @@ LogViewWidget::LogViewWidget(LogViewField* a_field, QWidget* a_widget, QWidget*
{
}
// ---------------------------------------------------------------
uint16_t LogViewWidget::getSize() const
{
// todo: check whether really a standardtype
const LogViewXdrStandardType* xdrStandardType = static_cast<const LogViewXdrStandardType*>(m_Field->xdrElement());
return xdrStandardType->getValueSize();
}
// ---------------------------------------------------------------
void LogViewWidget::showMessageBox(const QString &a_errorText) const
{
QMessageBox::warning(m_Parent, QObject::tr("Fehler"), a_errorText);
}
// ---------------------------------------------------------------
void LogViewWidget::updateToolTip(const QString &a_text)
{
bool isList = m_Field->valueListSize() > 1 || m_Field->isDynamicArray();
@@ -74,7 +74,7 @@ void LogViewWidget::updateToolTip(const QString &a_text)
}
else
{
// fixme: bei 3-byte werten werden fälschlicherweise 4 Bytes angezeigt
if (m_Field->isDateTimeField())
{
m_Widget->setToolTip(QObject::tr("Unixzeit: %1 ").arg(a_text));
@@ -83,13 +83,13 @@ void LogViewWidget::updateToolTip(const QString &a_text)
{
m_Widget->setToolTip(QString());
}
// actual value in hex and binary
if (!isList)
{
int64_t value = a_text.toLong();
m_Widget->setToolTip(QStringLiteral("%1<b>%2</b> %3").arg(m_Widget->toolTip(), toHex(value), toBin(value)));
}
// range
if (!m_Field->isDateTimeField() && !m_Readonly)
{
const QString sep(isList ? QString() : QStringLiteral("<br>"));
@@ -120,12 +120,12 @@ void LogViewWidget::updateToolTip(const QString &a_text)
}
// ---------------------------------------------------------------
double LogViewWidget::getFloat(const QString& a_text, uint64_t& a_FloatAsData, bool& a_ok, const bool a_reverse)
{
// INFO_LOG(m_logger) << "a_text=" << a_text.toStdString();
//LogViewXdrStandardType::E_ByteOrder byteOrder = ((LogViewXdrStandardType*)m_Field->xdrElement())->getByteOrder();
double value;
if (8 == getSize())
{
@@ -136,14 +136,14 @@ double LogViewWidget::getFloat(const QString& a_text, uint64_t& a_FloatAsData, b
a_FloatAsData = LogViewTelegram::floatToXdr(value);
}
// show error-message
// fixme zeige fehler genauer
if (!a_ok)
showMessageBox(QStringLiteral("Inalid real value: '%1'").arg(a_text));
m_Valid = a_ok;
// swap for display data on table
if (a_reverse)
{
int j = getSize() - 1;
@@ -157,7 +157,7 @@ double LogViewWidget::getFloat(const QString& a_text, uint64_t& a_FloatAsData, b
}
}
// set the upper 4 bytes to 0 for float
if (4 == getSize())
{
((uint8_t*)&a_FloatAsData)[4] = 0;
@@ -169,17 +169,17 @@ double LogViewWidget::getFloat(const QString& a_text, uint64_t& a_FloatAsData, b
}
// ---------------------------------------------------------------
// Converts a_text into a signed integer and returns it. The
// parameter a_ok will be true if all was successful. The
// attribute m_Valid will be set to a_ok.
// The range will be checked, if the value is out of range, an
// error will be shown as messge-box and a_ok will be false.
// The input a_text can be a calculation.
// ---------------------------------------------------------------
int64_t LogViewWidget::getInteger(const QString& a_text, bool& a_ok)
{
// calculate the expression into a number
N_SST::IntegerCalculator calculator;
N_SST::IntegerCalculator::E_Error error;
int64_t value = calculator.calc(a_text.toStdString(), error);
@@ -187,7 +187,7 @@ int64_t LogViewWidget::getInteger(const QString& a_text, bool& a_ok)
a_ok = true;
if (N_SST::IntegerCalculator::e_Ok != error)
{
// todo: show exact error-message
if (a_text != m_LastErrorValueText)
{
showMessageBox(QString::fromUtf8("Die Berechnung '%1' ist falsch").arg(a_text));
@@ -197,19 +197,19 @@ int64_t LogViewWidget::getInteger(const QString& a_text, bool& a_ok)
}
else
{
// check the range
int64_t highest = m_Field->getHighestValue();
if (value > highest)
{
a_ok = false;
// fixme: dieser Trick mit m_LastErrorValueText ist für den Benutzer etwas verwirrend, da
// plötzlich keine Reaktion mehr auf Tab, Ok oder wählen eines anderen Feldes passiert...
if (a_text != m_LastErrorValueText)
{
showMessageBox(QString::fromUtf8("Der Wert '%1' ist zu hoch. Maximalwert: %2").arg(a_text).arg(highest));
m_LastErrorValueText = a_text;
}
return value;
return value; // abort
}
int64_t lowest = m_Field->getLowestValue();
if (value < lowest)
@@ -220,11 +220,11 @@ int64_t LogViewWidget::getInteger(const QString& a_text, bool& a_ok)
showMessageBox(QString::fromUtf8("Der Wert '%1' ist zu tief. Minimalwert: %2").arg(a_text).arg(lowest));
m_LastErrorValueText = a_text;
}
return value;
return value; // abort
}
m_Valid = true;
}
return value;
}
}
} // namespace N_LogView
@@ -1,15 +1,15 @@
// **************************************************************************
//
// (C) Copyright 2009 Swiss SIMTEC AG
//
// **************************************************************************
//
// $HeadURL$
// $LastChangedBy$
// $LastChangedDate$
// $LastChangedRevision$
//
// **************************************************************************
#pragma once
@@ -36,8 +36,11 @@ inline QString toBin(T num)
class LogViewField;
class LogViewTelegram;
/**
* @author alois.wismer
* @version 1.0
* @created 20-Mai-2010 14:51:17
*/
class LogViewWidget
{
public:
@@ -48,12 +51,17 @@ public:
LogViewField* field() const { return m_Field; }
bool isValid() const { return m_Valid; }
/**
* The content if the field is a text-field
*/
QString getText() const { return m_Text; }
/**
* Writes the content into telegram.
* Returns true if successful.
*
* @param a_telegram
*/
virtual bool saveContent(LogViewTelegram* a_telegram) = 0;
protected:
@@ -61,16 +69,25 @@ protected:
void updateToolTip(const QString &a_text = QString());
double getFloat(const QString& a_text, uint64_t& a_FloatAsData, bool& a_ok, const bool a_reverse = false);
/**
* Converts a_text into a signed integer and returns it. The parameter a_ok will
* be true if all was successful. The attribute m_Valid will be set to a_ok.
* The range will be checked, if the value is out of range, an error will be shown
* as messge-box and a_ok will be false.
* The input a_text can be a calculation.
*
* @param a_text
* @param a_ok
*/
int64_t getInteger(const QString& a_text, bool& a_ok);
protected:
bool m_Readonly;
bool m_Valid;
/**
* The content if the field is a text-field
*/
QString m_Text;
QString m_LastErrorValueText;
QWidget *m_Widget;
@@ -1,24 +1,24 @@
// **************************************************************************
//
// (C) Copyright 2009 Swiss SIMTEC AG
//
// **************************************************************************
//
// $HeadURL$
// $LastChangedBy$
// $LastChangedDate$
// $LastChangedRevision$
//
// **************************************************************************
#include "LogViewXdrElement.hpp"
namespace N_LogView
{
// ---------------------------------------------------------------
// Constructor of a struct or enum
// ---------------------------------------------------------------
LogViewXdrElement::LogViewXdrElement(const QString& a_name, const E_ElementKind a_kind, const char *loggerName)
: m_Name(a_name)
, m_Kind(a_kind)
@@ -28,14 +28,14 @@ LogViewXdrElement::LogViewXdrElement(const QString& a_name, const E_ElementKind
ERROR_LOG(m_logger) << "Element \'" << a_name.toStdString() << "\' has a problem";
}
// ---------------------------------------------------------------
void LogViewXdrElement::dump() const
{
INFO_LOG(m_logger) << "Element[" << getName() << "]: kind=" << getKindName();
}
// ---------------------------------------------------------------
QString LogViewXdrElement::getKindName() const
{
switch (getKind())
@@ -58,4 +58,4 @@ QString LogViewXdrElement::getKindName() const
return QStringLiteral("Unknown (%1)").arg(getKind());
}
}
} // namespace N_LogView
@@ -1,15 +1,15 @@
// **************************************************************************
//
// (C) Copyright 2009 Swiss SIMTEC AG
//
// **************************************************************************
//
// $HeadURL$
// $LastChangedBy$
// $LastChangedDate$
// $LastChangedRevision$
//
// **************************************************************************
#pragma once
@@ -18,14 +18,20 @@
namespace N_LogView
{
/**
* @author alois.wismer
* @version 1.0
* @created 05-Feb-2010 11:24:56
*/
class LogViewXdrElement
{
public:
/**
* @author alois.wismer
* @version 1.0
* @created 10-Feb-2010 11:34:47
*/
enum E_ElementKind
{
e_KindStandardType,
@@ -40,8 +46,12 @@ namespace N_LogView
virtual ~LogViewXdrElement() = default;
protected:
/**
* Constructor of a struct or enum
*
* @param a_name
* @param a_kind
*/
LogViewXdrElement(const QString& a_name, const E_ElementKind a_kind, const char *loggerName);
public:
@@ -1,21 +1,21 @@
// **************************************************************************
//
// (C) Copyright 2009 Swiss SIMTEC AG
//
// **************************************************************************
//
// $HeadURL$
// $LastChangedBy$
// $LastChangedDate$
// $LastChangedRevision$
//
// **************************************************************************
// manual class headers
#include "LogViewXdrParser.hpp"
#include <utility>
// from cpp_includes
#include "LogViewXdrElement.hpp"
#include <QtWidgets/QMessageBox>
#include "LogViewXdrStruct.hpp"
@@ -46,7 +46,7 @@ LogViewXdrParser::~LogViewXdrParser()
delete elem.second;
}
// ---------------------------------------------------------------
void LogViewXdrParser::addStandardType(const QString& a_name, const uint16_t a_dataSize, const uint16_t a_realSize, const LogViewXdrStandardType::E_ValueKind a_kind, const LogViewXdrStandardType::E_DynArraySizeMethod a_dynArraySizeMethod, const LogViewXdrStandardType::E_ByteOrder a_byteOrder)
{
QString name = a_name.trimmed();
@@ -59,7 +59,7 @@ void LogViewXdrParser::addStandardType(const QString& a_name, const uint16_t a_d
}
// ---------------------------------------------------------------
void LogViewXdrParser::parseX_File(const QString& a_fileName)
{
for (const auto &elem : m_ElementMap)
@@ -73,7 +73,7 @@ void LogViewXdrParser::parseX_File(const QString& a_fileName)
m_ActElement = nullptr;
m_State = e_ParseMain;
// define some (XDR-)standard-types
addStandardType(QLatin1String("unsigned short"), 4, 2, LogViewXdrStandardType::e_Unsigned);
addStandardType(QLatin1String("unsigned int"), 4, 4, LogViewXdrStandardType::e_Unsigned);
addStandardType(QLatin1String("short"), 4, 2, LogViewXdrStandardType::e_Signed);
@@ -89,7 +89,7 @@ void LogViewXdrParser::parseX_File(const QString& a_fileName)
addStandardType(QLatin1String("opaque"), 1, 1, LogViewXdrStandardType::e_Data);
addStandardType(QLatin1String("string"), 1, 1, LogViewXdrStandardType::e_Character);
// for tetra-telegrams
addStandardType(QLatin1String("alpha"), 1, 1, LogViewXdrStandardType::e_Character);
addStandardType(QLatin1String("UInt8"), 1, 1, LogViewXdrStandardType::e_Unsigned);
addStandardType(QLatin1String("UInt16"), 2, 2, LogViewXdrStandardType::e_Unsigned);
@@ -97,20 +97,20 @@ void LogViewXdrParser::parseX_File(const QString& a_fileName)
addStandardType(QLatin1String("SInt8"), 1, 1, LogViewXdrStandardType::e_Signed);
addStandardType(QLatin1String("SInt16"), 2, 2, LogViewXdrStandardType::e_Signed);
addStandardType(QLatin1String("SInt24"), 3, 3, LogViewXdrStandardType::e_Signed);
// little-endian values (for TETRA-header)
addStandardType(QLatin1String("UInt16LE"), 2, 2, LogViewXdrStandardType::e_Unsigned, LogViewXdrStandardType::e_DynArrayMsgLength, LogViewXdrStandardType::e_ByteOrderLittleEndian);
addStandardType(QLatin1String("UInt32LE"), 4, 4, LogViewXdrStandardType::e_Unsigned, LogViewXdrStandardType::e_DynArrayMsgLength, LogViewXdrStandardType::e_ByteOrderLittleEndian);
// index for next dyn. array (only for TETRA)
addStandardType(QLatin1String("UInt8Idx"), 1, 1, LogViewXdrStandardType::e_Unsigned, LogViewXdrStandardType::e_DynArrayIndex);
addStandardType(QLatin1String("UInt16Idx"), 2, 2, LogViewXdrStandardType::e_Unsigned, LogViewXdrStandardType::e_DynArrayIndex);
addStandardType(QLatin1String("UInt16LEIdx"), 2, 2, LogViewXdrStandardType::e_Unsigned, LogViewXdrStandardType::e_DynArrayIndex, LogViewXdrStandardType::e_ByteOrderLittleEndian);
// index (div 8) for next dyn. array (only for TETRA)
addStandardType(QLatin1String("UInt8IdxDiv8"), 1, 1, LogViewXdrStandardType::e_Unsigned, LogViewXdrStandardType::e_DynArrayIndexDiv8);
addStandardType(QLatin1String("UInt16IdxDiv8"), 2, 2, LogViewXdrStandardType::e_Unsigned, LogViewXdrStandardType::e_DynArrayIndexDiv8);
const auto DEFINE_NAME = QLatin1String("%#define");
// parse the file
m_Filename = a_fileName;
m_State = e_ParseMain;
QFile xFile(a_fileName);
@@ -124,25 +124,25 @@ void LogViewXdrParser::parseX_File(const QString& a_fileName)
m_Line = lastLines + QLatin1Char(' ') + in.readLine();
m_Line = m_Line.simplified();
m_LineNbr++;
// INFO_LOG(m_logger) << m_LineNbr << ": " << m_Line.toStdString();
// ignore lines with %
if (m_Line.startsWith(QLatin1Char('%')) && !m_Line.startsWith(DEFINE_NAME))
{
continue;
}
// remove comments (sourounded with /* */)
const QString cleanLine = removeComments(m_Line).simplified();
// ignore empty lines
if (cleanLine.isEmpty())
{
continue;
}
// INFO_LOG(m_logger) << "w/o comment: \'" << cleanLine.toStdString() << "\'";
// read in whole construct
if (m_DoReadUntilSemicolon && !cleanLine.endsWith(QLatin1Char(';')))
{
lastLines = cleanLine;
@@ -153,7 +153,7 @@ void LogViewXdrParser::parseX_File(const QString& a_fileName)
lastLines.clear();
// check whether it is the begin of a construct
if (e_ParseMain == m_State)
{
if (cleanLine.startsWith(QLatin1String("union ")))
@@ -166,7 +166,7 @@ void LogViewXdrParser::parseX_File(const QString& a_fileName)
}
}
// parse the line when we are within
switch (m_State)
{
case e_ParseUnion:
@@ -208,7 +208,7 @@ void LogViewXdrParser::parseX_File(const QString& a_fileName)
}
}
xFile.close();
// erase all parsing-values (otherwise errormessages will have wrong informations)
m_LineNbr = 0;
m_Line.clear();
}
@@ -219,12 +219,12 @@ void LogViewXdrParser::parseX_File(const QString& a_fileName)
}
// ---------------------------------------------------------------
QString LogViewXdrParser::removeComments(const QString& a_line)
{
static const QChar slash(QLatin1Char('/'));
static const QChar asterik(QLatin1Char('*'));
// remove comments (sourounded with /* */)
QString cleanLine; cleanLine.reserve(a_line.size());
QString::const_iterator iter = a_line.begin();
QString::const_iterator end = a_line.end();
@@ -232,38 +232,38 @@ QString LogViewXdrParser::removeComments(const QString& a_line)
{
if (!m_WithinComment)
{
// does comment begin?
if (slash == *iter)
{
if (++iter != end)
{
if (asterik == *iter)
{
// yes, comment begins
m_WithinComment = true;
}
else
{
// no comment begin
cleanLine.append(slash);
cleanLine.append(*iter);
}
}
else
{
// end of line
cleanLine.append(slash);
}
}
else
{
// no
cleanLine.append(*iter);
}
}
else
{
// does comment end?
if (asterik == *iter)
{
if (++iter != end)
@@ -282,26 +282,26 @@ QString LogViewXdrParser::removeComments(const QString& a_line)
}
// ---------------------------------------------------------------
void LogViewXdrParser::parseTypedef(const QString &a_line)
{
fillWordList(a_line);
// typedef: "typedef telegramm_id_int_et telegramm_id_et;"
// -------
// keyword 'typedef'
if (isNextWord("typedef"))
{
// get type
bool ok;
QString type = getNextType(ok);
getElement(type);
// fixme: make boolean for structure wrong and gray out telegrams with wrong struct
getElement(type); // do not abort when type does not exist, otherwise we will never get an error, when we try to show a telegram with a wrong structure
// get name
QString name = getNextWord("Name");
if (name.isEmpty()) return;
if (!isNextWord(";")) return;
// all ok
uint16_t dynArrayOffset;
uint16_t arraySize = parseArray(name, dynArrayOffset);
LogViewXdrType* typedefElement = new LogViewXdrType(name, type, arraySize, dynArrayOffset, LogViewXdrElement::e_KindTypedef);
@@ -311,7 +311,7 @@ void LogViewXdrParser::parseTypedef(const QString &a_line)
}
// ---------------------------------------------------------------
void LogViewXdrParser::parseDefine(const QString &a_line)
{
const QString line = a_line.trimmed();
@@ -324,12 +324,12 @@ void LogViewXdrParser::parseDefine(const QString &a_line)
if (sepPos >= 0)
substitution = substitution.left(sepPos).trimmed();
// convert to number
bool ok = false;
const int64_t value = calcValue(substitution.toString(), ok);
if (ok)
{
//INFO_LOG(m_logger) << "Define: name=" << name.toStdString() << " subst=" << substitution.toStdString() << " value=" << value;
m_DefinesMap.insert(std::make_pair(name, LogViewXdrValue(name, value, LogViewXdrElement::e_KindDefine)));
}
}
@@ -340,7 +340,7 @@ void LogViewXdrParser::parseDefine(const QString &a_line)
}
// ---------------------------------------------------------------
void LogViewXdrParser::parseEnum(const QString &a_line, const uint16_t a_enumSize)
{
if (QLatin1String("};") != a_line)
@@ -348,8 +348,8 @@ void LogViewXdrParser::parseEnum(const QString &a_line, const uint16_t a_enumSiz
switch(m_State)
{
default:
// first line of enum containing the name
// i.e.: "enum telegramm_id_int_et {"
if (a_line.endsWith(QLatin1String(" {")))
{
m_State = e_ParseEnum;
@@ -370,20 +370,20 @@ void LogViewXdrParser::parseEnum(const QString &a_line, const uint16_t a_enumSiz
case e_ParseEnum:
{
// middle lines of struct containing the elements
// i.e.: "MANIPULATIONSMELDUNG = 2,"
QString name;
QString valueText;
if (parseEnumLine(a_line, name, valueText))
{
// is the valueText a previous enum-element?
bool error = true;
uint32_t enumValue = m_ActElement->getChildValue(valueText, &error);
if (!error)
{
valueText = QString::number(enumValue);
}
// calculate
bool ok;
int64_t value = calcValue(valueText, ok);
if (ok)
@@ -397,30 +397,30 @@ void LogViewXdrParser::parseEnum(const QString &a_line, const uint16_t a_enumSiz
}
else
{
// end of struct
m_State = e_ParseMain;
//INFO_LOG(m_logger) << "CheckEnum " << m_ActElement->getName().toStdString();
// check(*m_ActElement);
}
}
// ---------------------------------------------------------------
void LogViewXdrParser::parseStruct(const QString &a_line)
{
fillWordList(a_line);
if (!m_DoReadUntilSemicolon)
{
// first line of struct: "struct gef_wirkfeld_flaechendeckendes_feuer_meldung_rt {"
// --------------------
// keyword 'union'
if (isNextWord("struct"))
{
// union name
QString structName = getNextWord("Struktur-Name");
if (structName.isEmpty()) return;
if (!isNextWord("{")) return;
// all ok => proceed parsing union
m_ActElement = new LogViewXdrStruct(structName, LogViewXdrElement::e_KindStruct);
if (!addToElementMap(structName, m_ActElement))
{
@@ -436,15 +436,15 @@ void LogViewXdrParser::parseStruct(const QString &a_line)
{
if (!isNextWord("}", false))
{
// next lines of struct: "gef_header_rt:3..6 header;"
// --------------------
// get type
bool ok;
QString type = getNextType(ok);
if (!ok) return;
if (m_UnionType != type) getElement(type);
// fixme: make boolean for structure wrong and gray out telegrams with wrong struct
if (m_UnionType != type) getElement(type); // do not abort when type does not exist, otherwise we will never get an error, when we try to show a telegram with a wrong structure
// get bitfield (if any) ":2..5"
int16_t firstBit = -1;
int16_t lastBit = -1;
bool isLast = true;
@@ -454,11 +454,11 @@ void LogViewXdrParser::parseStruct(const QString &a_line)
QString bitfield = getNextWord("Bitfield");
isLast = parseBitfield(bitfield, firstBit, lastBit);
}
// get name
QString name = getNextWord("Name");
if (name.isEmpty()) return;
if (!isNextWord(";")) return;
// all ok
uint16_t dynArrayOffset;
uint16_t arraySize = parseArray(name, dynArrayOffset);
if(firstBit >= 0)
@@ -471,51 +471,51 @@ void LogViewXdrParser::parseStruct(const QString &a_line)
}
else
{
// end of struct "};"
if (!isNextWord("}")) return;
if (!isNextWord(";")) return;
m_State = e_ParseMain;
m_DoReadUntilSemicolon = false;
// INFO_LOG(m_logger) << "CheckStruct \'" << m_ActElement->getName().toStdString() << "\'";
// if (m_ActElement->getName() != "intern_tele") // fixme: remove this structure from element-map
// {
// check(*m_ActElement);
// }
}
}
}
// ---------------------------------------------------------------
void LogViewXdrParser::parseUnion(const QString& a_line)
{
// we can not really parse the union, we expect that only 1 union exists, and this
// union holds all the telegrams, which we insert into a telegram-list
static const LogViewXdrStruct* telegramIdType = nullptr;
fillWordList(a_line);
if (!m_DoReadUntilSemicolon)
{
// first line of union "union gef_tg_nd_ switch (gef_telegramm_id_et telegramm_id) {"
// -------------------
// keyword 'union'
if (isNextWord("union"))
{
// union name
m_UnionType = getNextWord("Union-Typ");
if (m_UnionType.isEmpty()) return;
// keyword 'switch'
if (!isNextWord("switch")) return;
if (!isNextWord("(")) return;
// telegram-id-type
getNextEnum(telegramIdType);
if (telegramIdType == nullptr) return;
// telegram-id-name
QString name = getNextWord("Parameter-Name");
if (name.isEmpty()) return;
if (!isNextWord(")")) return;
if (!isNextWord("{")) return;
// all ok => proceed parsing union
m_State = e_ParseUnion;
m_DoReadUntilSemicolon = true;
}
@@ -527,29 +527,29 @@ void LogViewXdrParser::parseUnion(const QString& a_line)
QString keyword = getNextWord();
if (keyword == QLatin1String("case"))
{
// next lines of union "case GEF_INIT: gef_init_meldung_rt init_meldung;"
// -------------------
QStringList constExprList;
QString type;
do
{
// get constant-expression
QString constExpression = getNextWord("Konstanten-Ausdruck");
if (constExpression.isEmpty()) return;
constExprList << constExpression;
// check double-point
if (!isNextWord(":")) return;
// get type or another case
type = getNextWord("Typ");
if (type.isEmpty()) return;
}
while (type == QLatin1String("case"));
getElement(type);
// fixme: make boolean for structure wrong and gray out telegrams with wrong struct
getElement(type); // do not abort when type does not exist, otherwise we will never get an error, when we try to show a telegram with a wrong structure
// get name
QString name = getNextWord("Name");
if (name.isEmpty()) return;
// check semicolon
if (!isNextWord(";")) return;
for (const QString &constExpr : std::as_const(constExprList))
@@ -558,7 +558,7 @@ void LogViewXdrParser::parseUnion(const QString& a_line)
int32_t telegramId = static_cast<int>(telegramIdType->getChildValue(constExpr, &error));
if (!error)
{
m_TelegramMap.insert(std::make_pair(telegramId, LogViewXdrType(constExpr, type, 1, 0, LogViewXdrElement::e_KindEnumElement)));
m_TelegramMap.insert(std::make_pair(telegramId, LogViewXdrType(constExpr, type, 1, 0, LogViewXdrElement::e_KindEnumElement))); // fixme: e_KindCaseElement und 1 entfernen
}
else
{
@@ -568,14 +568,14 @@ void LogViewXdrParser::parseUnion(const QString& a_line)
}
else if (keyword == QLatin1String("default"))
{
// check double-point
if (isNextWord(":"))
{
QString defaultDefinition = getNextWord();
if (defaultDefinition == QLatin1String("void"))
{
isNextWord(";");
// all ok
}
else
{
@@ -590,18 +590,18 @@ void LogViewXdrParser::parseUnion(const QString& a_line)
}
else
{
// end of union "};"
if (!isNextWord("}")) return;
if (!isNextWord(";")) return;
m_State = e_ParseMain;
m_DoReadUntilSemicolon = false;
//check(*m_ActElement);
}
}
}
// ---------------------------------------------------------------
bool LogViewXdrParser::parseEnumLine(const QString& a_line, QString& a_name, QString& a_value) const
{
QString line;
@@ -626,14 +626,14 @@ bool LogViewXdrParser::parseEnumLine(const QString& a_line, QString& a_name, QSt
{
showErrorMessage(QObject::tr("konnte Trennzeichen <b>\'=\'</b> zwischen Name und Wert nicht finden!"));
}
return false;
return false; // failure happenend
}
// ---------------------------------------------------------------
// Shows an error-message containing the line-nbr, the line
// itself and an additional error-text
// ---------------------------------------------------------------
void LogViewXdrParser::showErrorMessage(const QString& a_errorText) const
{
const auto tlws = QApplication::topLevelWidgets();
@@ -643,10 +643,10 @@ void LogViewXdrParser::showErrorMessage(const QString& a_errorText) const
}
// ---------------------------------------------------------------
int64_t LogViewXdrParser::calcValue(const QString& a_calcText, bool& a_isOk)
{
// ignore strings
a_isOk = false;
int64_t value = 0;
if (!a_calcText.startsWith(QLatin1Char('\"')))
@@ -655,7 +655,7 @@ int64_t LogViewXdrParser::calcValue(const QString& a_calcText, bool& a_isOk)
std::string errorText;
value = calc(a_calcText.toStdString(), error, &errorText);
// show error if one happend
if (error != N_SST::IntegerCalculator::e_Ok)
{
switch (error)
@@ -695,21 +695,21 @@ int64_t LogViewXdrParser::calcValue(const QString& a_calcText, bool& a_isOk)
}
// ---------------------------------------------------------------
bool LogViewXdrParser::getVariableValue(const std::string& a_variableName, int64_t& a_value) const
{
return getDefine(QString::fromStdString(a_variableName), a_value);
}
// ---------------------------------------------------------------
// This function delivers the name of the telegram and the
// name of its structure. The telegram will be defined with
// a_telegramId.
// The name will be delivered as return-parameter; the
// structure-name as out parameter a_structName.
// If the telegram was not found, error-texts instead names
// will be returned.
// ---------------------------------------------------------------
QString LogViewXdrParser::getTelegramName(int a_telegramId) const
{
const auto iter = m_TelegramMap.find(a_telegramId);
@@ -719,7 +719,7 @@ QString LogViewXdrParser::getTelegramName(int a_telegramId) const
return QObject::tr("<telegramId \'%1\' not found!>").arg(a_telegramId);
}
// ---------------------------------------------------------------
QString LogViewXdrParser::getStructName(int a_telegramId) const
{
const auto iter = m_TelegramMap.find(a_telegramId);
@@ -729,7 +729,7 @@ QString LogViewXdrParser::getStructName(int a_telegramId) const
return QObject::tr("<telegramId \'%1\' not found!>").arg(a_telegramId);
}
// ---------------------------------------------------------------
bool LogViewXdrParser::getDefine(const QString& a_name, int64_t& a_value) const
{
const auto iter = m_DefinesMap.find(a_name);
@@ -742,7 +742,7 @@ bool LogViewXdrParser::getDefine(const QString& a_name, int64_t& a_value) const
}
// ---------------------------------------------------------------
const LogViewXdrElement* LogViewXdrParser::getElement(const QString& a_name) const
{
const auto iter = m_ElementMap.find(a_name);
@@ -754,27 +754,27 @@ const LogViewXdrElement* LogViewXdrParser::getElement(const QString& a_name) con
}
// ---------------------------------------------------------------
uint16_t LogViewXdrParser::parseArray(QString& a_name, uint16_t& a_dynArrayMsgOffset) const
{
a_dynArrayMsgOffset = 0;
QString oldName = a_name;
// is it a static array []?
// ------------------------
int pos = a_name.indexOf(QLatin1Char('['));
if (pos >= 0)
{
int endPos = a_name.indexOf(QLatin1Char(']'));
if (endPos > pos)
{
// get the array-size
QString arraySizeText = a_name.mid(pos+1, endPos-pos-1);
// set new name
a_name = a_name.left(pos);
// INFO_LOG(m_logger) << "new a_name=" << a_name.toStdString() << " arraySizeText=" << arraySizeText.toStdString();
int64_t arraySizeValue = 1;
// check whether it is a define
if (!getDefine(arraySizeText, arraySizeValue))
{
bool ok = false;
@@ -784,7 +784,7 @@ uint16_t LogViewXdrParser::parseArray(QString& a_name, uint16_t& a_dynArrayMsgOf
showErrorMessage(QObject::tr("%1: <b>[%2]</b> is not a number").arg(oldName, arraySizeText));
}
}
// INFO_LOG(m_logger) << "ArraySize=" << arraySizeValue;
return arraySizeValue;
}
else
@@ -795,22 +795,22 @@ uint16_t LogViewXdrParser::parseArray(QString& a_name, uint16_t& a_dynArrayMsgOf
else
{
// is it an dynamic array <>?
// --------------------------
//INFO_LOG(m_logger) << "check for <";
pos = a_name.indexOf(QLatin1Char('<'));
if (pos >= 0)
{
int endPos = a_name.indexOf(QLatin1Char('>'));
if (endPos > pos)
{
// get the array-size
QString arraySizeText = a_name.mid(pos+1, endPos-pos-1);
//INFO_LOG(m_logger) << "pos=" << pos << " endPos=" << endPos << " => " << arraySizeText.toStdString();
// set new name
a_name = a_name.left(pos);
// INFO_LOG(m_logger) << "new a_name=" << a_name.toStdString() << " arraySizeText=" << arraySizeText.toStdString();
// check whether it is a define
int64_t arraySizeValue = 1;
if (!getDefine(arraySizeText, arraySizeValue))
{
@@ -822,11 +822,11 @@ uint16_t LogViewXdrParser::parseArray(QString& a_name, uint16_t& a_dynArrayMsgOf
}
else
{
// INFO_LOG(m_logger) << "a_name=" << a_name.toStdString() << " a_dynArrayMsgOffset=" << a_dynArrayMsgOffset;
}
}
a_dynArrayMsgOffset = arraySizeValue;
// INFO_LOG(m_logger) << a_name.toStdString() << " is a dynamic array with size=" << arraySizeValue;
return 0;
}
else
@@ -839,14 +839,14 @@ uint16_t LogViewXdrParser::parseArray(QString& a_name, uint16_t& a_dynArrayMsgOf
}
// ---------------------------------------------------------------
bool LogViewXdrParser::isNextWord(const char *a_word, const bool a_doIncrement)
{
const QString word = QString::fromUtf8(a_word);
bool ok = (m_WordListIndex < m_WordList.size() &&
m_WordList.at(m_WordListIndex) == word);
// show error-message
if (!ok && a_doIncrement)
{
if (m_WordListIndex > 0)
@@ -861,7 +861,7 @@ bool LogViewXdrParser::isNextWord(const char *a_word, const bool a_doIncrement)
}
// ---------------------------------------------------------------
void LogViewXdrParser::fillWordList(const QString& a_line)
{
QString line = a_line;
@@ -873,15 +873,15 @@ void LogViewXdrParser::fillWordList(const QString& a_line)
line.replace(QLatin1Char(';'), QLatin1String(" ; "));
m_WordList = line.split(QLatin1Char(' '), Qt::SkipEmptyParts);
m_WordListIndex = 0;
// ----------------------
// for debugging only
// foreach (const QString &str, qAsConst(m_WordList))
// INFO_LOG(m_logger) << "word=" << str.toStdString();
// ----------------------
}
// ---------------------------------------------------------------
QString LogViewXdrParser::getNextWord(const char *a_errorText)
{
QString word;
@@ -901,7 +901,7 @@ QString LogViewXdrParser::getNextWord(const char *a_errorText)
}
// ---------------------------------------------------------------
QString LogViewXdrParser::getNextType(bool& a_ok)
{
a_ok = true;
@@ -918,7 +918,7 @@ QString LogViewXdrParser::getNextType(bool& a_ok)
}
// ---------------------------------------------------------------
QString LogViewXdrParser::getNextEnum(const LogViewXdrStruct*& a_enumStruct)
{
QString type;
@@ -943,15 +943,15 @@ QString LogViewXdrParser::getNextEnum(const LogViewXdrStruct*& a_enumStruct)
}
// ---------------------------------------------------------------
bool LogViewXdrParser::parseBitfield(const QString& a_fieldText, int16_t& a_firstBit, int16_t& a_lastBit) const
{
// INFO_LOG(m_logger) << "a_fieldText=" << a_fieldText.toStdString();
// bitfield-definition: "0..2"
a_firstBit = -1;
a_lastBit = -1;
bool isLast = true;
// first bit
int doublePointPos = a_fieldText.indexOf(QLatin1String(".."));
if (doublePointPos != -1)
{
@@ -960,9 +960,9 @@ bool LogViewXdrParser::parseBitfield(const QString& a_fieldText, int16_t& a_firs
a_firstBit = bitText.toInt(&ok);
if (ok)
{
// last bit
bitText = a_fieldText.mid(doublePointPos+2);
// is it the last bitfield of this data-value (indicated by !)
if (bitText.endsWith(QLatin1Char('!')))
{
isLast = true;
@@ -975,8 +975,8 @@ bool LogViewXdrParser::parseBitfield(const QString& a_fieldText, int16_t& a_firs
a_lastBit = bitText.toInt(&ok);
if (ok)
{
// remove bitfield-stuff
// a_line = a_line.remove(bitfieldPos, endPos-bitfieldPos);
}
else
{
@@ -996,12 +996,12 @@ bool LogViewXdrParser::parseBitfield(const QString& a_fieldText, int16_t& a_firs
}
// ---------------------------------------------------------------
// adds an element to the element-map if it does not already
// exist within this map.
// If it exists, an error-message will be raised instead and
// false will be returned.
// ---------------------------------------------------------------
bool LogViewXdrParser::addToElementMap(const QString& a_name, LogViewXdrElement* a_element)
{
if (m_ElementMap.find(a_name) == m_ElementMap.end())
@@ -1013,5 +1013,5 @@ bool LogViewXdrParser::addToElementMap(const QString& a_name, LogViewXdrElement*
return false;
}
}
} // namespace N_LogView
@@ -1,15 +1,15 @@
// **************************************************************************
//
// (C) Copyright 2009 Swiss SIMTEC AG
//
// **************************************************************************
//
// $HeadURL$
// $LastChangedBy$
// $LastChangedDate$
// $LastChangedRevision$
//
// **************************************************************************
#pragma once
@@ -29,14 +29,22 @@ namespace N_LogView
class LogViewXdrValue;
class LogViewXdrType;
/**
* @author alois.wismer
* @version 1.0
* @created 05-Feb-2010 10:46:58
*/
class LogViewXdrParser : public N_SST::IntegerCalculator
{
public:
/**
* Defines in which structure the parser is parsing now
*
* @author alois.wismer
* @version 1.0
* @created 08-Feb-2010 17:44:52
*/
enum E_ParseState
{
e_ParseMain,
@@ -50,24 +58,43 @@ namespace N_LogView
~LogViewXdrParser();
/**
*
* @param a_fileName
*/
void parseX_File(const QString& a_fileName);
/**
* This function delivers the name of the telegram.
* The telegram will be defined with a_telegramId.
* The name will be delivered as return-parameter.
* If the telegram was not found, error-texts instead names will be returned.
*
* @param a_telegramId
*/
QString getTelegramName(int a_telegramId) const;
/**
* This function delivers the structure name of the telegram.
* The telegram will be defined with a_telegramId.
* The structure name will be delivered as return-parameter
* If the telegram was not found, error-texts instead names will be returned.
*
* @param a_telegramId
*/
QString getStructName(int a_telegramId) const;
/**
*
* @param a_name
* @param a_value
*/
bool getDefine(const QString& a_name, int64_t& a_value) const;
/**
*
* @param a_name
*/
const LogViewXdrElement* getElement(const QString& a_name) const;
protected:
@@ -80,8 +107,10 @@ namespace N_LogView
bool m_DoReadUntilSemicolon;
QStringList m_WordList;
int m_WordListIndex;
/**
* This will be used to suppress an error-message when parsing the overall
* telegram structure.
*/
QString m_UnionType;
std::map<QString, LogViewXdrElement*> m_ElementMap;
@@ -93,8 +122,15 @@ namespace N_LogView
std::map<int, LogViewXdrType> m_TelegramMap;
/**
*
* @param a_name
* @param a_dataSize
* @param a_realSize
* @param a_kind
* @param a_dynArraySizeMethod
* @param a_byteOrder
*/
void addStandardType(const QString& a_name,
const uint16_t a_dataSize,
const uint16_t a_realSize,
@@ -102,76 +138,130 @@ namespace N_LogView
const LogViewXdrStandardType::E_DynArraySizeMethod a_dynArraySizeMethod = LogViewXdrStandardType::e_DynArrayMsgLength,
const LogViewXdrStandardType::E_ByteOrder a_byteOrder = LogViewXdrStandardType::e_ByteOrderBigEndian);
/**
*
* @param a_line
*/
QString removeComments(const QString& a_line);
/**
*
* @param a_line
*/
void parseTypedef(const QString &a_line);
/**
*
* @param a_line
*/
void parseDefine(const QString &a_line);
/**
*
* @param a_line
* @param a_enumSize The size in bytes of an enum-value
*/
void parseEnum(const QString &a_line, const uint16_t a_enumSize = 4);
/**
*
* @param a_line
*/
void parseStruct(const QString &a_line);
/**
*
* @param a_line
*/
void parseUnion(const QString& a_line);
/**
*
* @param a_line
* @param a_name
* @param a_value
*/
bool parseEnumLine(const QString& a_line, QString& a_name, QString& a_value) const;
/**
* Shows an error-message containing the line-nbr, the line itself and an
* additional error-text
*
* @param a_errorText
*/
void showErrorMessage(const QString& a_errorText) const;
/**
*
* @param a_calcText
* @param a_isOk
*/
int64_t calcValue(const QString& a_calcText, bool& a_isOk);
/**
*
* @param a_variableName
* @param a_value
*/
bool getVariableValue(const std::string& a_variableName, int64_t& a_value) const override;
/**
*
* @param a_name
* @param a_dynArrayMsgOffset This offset will be used for the dyn-array-method
* e_DynArrayMsgLength. Here the value in <x> will be subtracted from the message-
* length to get the size of the dynamic array.
*/
uint16_t parseArray(QString& a_name, uint16_t& a_dynArrayMsgOffset) const;
/**
*
* @param a_word
* @param a_doIncrement
*/
bool isNextWord(const char *a_word, const bool a_doIncrement = true);
/**
*
* @param a_line
*/
void fillWordList(const QString& a_line);
/**
*
* @param a_errorText
*/
QString getNextWord(const char *a_errorText = nullptr);
/**
*
* @param a_ok
*/
QString getNextType(bool& a_ok);
/**
*
* @param a_enumStruct
*/
QString getNextEnum(const LogViewXdrStruct*& a_enumStruct);
/**
*
* @param a_fieldText
* @param a_firstBit
* @param a_lastBit
*/
bool parseBitfield(const QString& a_fieldText, int16_t& a_firstBit, int16_t& a_lastBit) const;
/**
* adds an element to the element-map if it does not already exist within this map.
*
* If it exists, an error-message will be raised instead and false will be
* returned.
*
* @param a_name
* @param a_element
*/
bool addToElementMap(const QString& a_name, LogViewXdrElement* a_element);
private:
@@ -1,26 +1,26 @@
// **************************************************************************
//
// (C) Copyright 2009 Swiss SIMTEC AG
//
// **************************************************************************
//
// $HeadURL$
// $LastChangedBy$
// $LastChangedDate$
// $LastChangedRevision$
//
// **************************************************************************
// manual class headers
#include "LogViewXdrStandardType.hpp"
namespace N_LogView
{
// ---------------------------------------------------------------
// (a_valueKind must be Unsigned, if a_dynArraySizeMethod is
// e_DynArray...)
// ---------------------------------------------------------------
LogViewXdrStandardType::LogViewXdrStandardType(const QString& a_name, const int a_valueSize,
const int a_editSize, const E_ValueKind a_valueKind,
const E_DynArraySizeMethod a_dynArraySizeMethod, E_ByteOrder a_byteOrder)
@@ -33,20 +33,20 @@ LogViewXdrStandardType::LogViewXdrStandardType(const QString& a_name, const int
{}
// ---------------------------------------------------------------
uint16_t LogViewXdrStandardType::getValueSize() const
{
return m_ValueSize;
}
// ---------------------------------------------------------------
LogViewXdrStandardType::E_ValueKind LogViewXdrStandardType::getValueKind() const
{
return m_ValueKind;
}
// ---------------------------------------------------------------
void LogViewXdrStandardType::dump() const
{
INFO_LOG(m_logger) << "Element[" << getName()
@@ -58,27 +58,27 @@ void LogViewXdrStandardType::dump() const
<< " byteOrder=" << getByteOrder();
}
// ---------------------------------------------------------------
LogViewXdrStandardType::E_DynArraySizeMethod LogViewXdrStandardType::getDynArraySizeMethod() const
{
return m_DynArraySizeMethod;
}
// ---------------------------------------------------------------
LogViewXdrStandardType::E_ByteOrder LogViewXdrStandardType::getByteOrder() const
{
return m_ByteOrder;
}
// ---------------------------------------------------------------
// The 'real' size of the value, which will be allowd when
// editing this value
// ---------------------------------------------------------------
uint16_t LogViewXdrStandardType::getEditSize() const
{
return m_EditSize;
}
}
} // namespace N_LogView
@@ -1,15 +1,15 @@
// **************************************************************************
//
// (C) Copyright 2009 Swiss SIMTEC AG
//
// **************************************************************************
//
// $HeadURL$
// $LastChangedBy$
// $LastChangedDate$
// $LastChangedRevision$
//
// **************************************************************************
#pragma once
@@ -17,61 +17,91 @@
namespace N_LogView
{
/**
* This class represents the standardtypes like int, char, ...
* It holds the the size of this type and its representation to user
* (signed/unsigned value or character)
*
* @author alois.wismer
* @version 1.0
* @created 16-Feb-2010 14:22:20
*/
class LogViewXdrStandardType final : public LogViewXdrElement
{
public:
/**
* @author alois.wismer
* @version 1.0
* @created 16-Feb-2010 14:34:38
*/
enum E_ValueKind
{
/**
* An unsigned 32-bit integer
*/
e_Unsigned,
/**
* An signed 32-bit integer
*/
e_Signed,
/**
* A floating-point number
*/
e_Float,
/**
* A character or string
*/
e_Character,
/**
* A boolean value
*/
e_Boolean,
/**
* Hex-Data "0000: F7 A5 07 ..."
*/
e_Data
};
/**
* @author alois.wismer
* @version 1.0
* @created 31-Mrz-2010 10:27:31
*/
enum E_ByteOrder
{
e_ByteOrderBigEndian,
e_ByteOrderLittleEndian
};
/**
* @author alois.wismer
* @version 1.0
* @created 29-Mrz-2010 13:58:44
*/
enum E_DynArraySizeMethod
{
/**
* Size of dyn array depends on message-size (size - m_DynArrayOffset) (or no dyn
* array)
* The value within <> in struct-element will be used for m_DynArrayOffset.
*/
e_DynArrayMsgLength,
/**
* Size of dyn array is defined by a field (StandardType must be Unsigned)
*/
e_DynArrayIndex,
/**
* Size of dyn array is defined by a field, which will be divided by 8 (used for
* bitfields) (StandardType must be Unsigned)
*/
e_DynArrayIndexDiv8
};
/**
* (a_valueKind must be Unsigned, if a_dynArraySizeMethod is e_DynArray...)
*
*/
LogViewXdrStandardType(const QString &a_name,
const int a_valueSize,
const int a_editSize,
@@ -94,17 +124,20 @@ namespace N_LogView
LogViewXdrStandardType::E_ByteOrder getByteOrder() const;
/**
* The 'real' size of the value, which will be allowd when editing this value
*/
uint16_t getEditSize() const;
protected:
/**
* The size of this value as stored data. It may be bigger as the real (edit) size.
*/
int m_ValueSize;
/**
* The 'real' size of the value, which will be allowd when editing this value
*/
int m_EditSize;
E_ValueKind m_ValueKind;
@@ -1,15 +1,15 @@
// **************************************************************************
//
// (C) Copyright 2009 Swiss SIMTEC AG
//
// **************************************************************************
//
// $HeadURL$
// $LastChangedBy$
// $LastChangedDate$
// $LastChangedRevision$
//
// **************************************************************************
#include "LogViewXdrStruct.hpp"
#include "LogViewXdrValue.hpp"
@@ -18,7 +18,7 @@
namespace N_LogView
{
// ---------------------------------------------------------------
LogViewXdrStruct::LogViewXdrStruct(const QString& a_name, const LogViewXdrElement::E_ElementKind a_kind, uint16_t enumSize)
: LogViewXdrElement(a_name, a_kind, "LogViewXdrStruct")
, m_EnumSize(enumSize)
@@ -32,20 +32,20 @@ LogViewXdrStruct::~LogViewXdrStruct()
}
// ---------------------------------------------------------------
void LogViewXdrStruct::addElement(const QString& a_name, const QString& a_type, const uint16_t a_arraySize, const uint16_t a_dynArrayOffset, const E_ElementKind a_kind, const int16_t a_firstBit, const int16_t a_lastBit, const bool a_isLast)
{
m_ChildList.push_back(new LogViewXdrType(a_name, a_type, a_arraySize, a_dynArrayOffset, a_kind, a_firstBit, a_lastBit, a_isLast));
}
// ---------------------------------------------------------------
void LogViewXdrStruct::addElement(const QString& a_name, const uint32_t a_value, const E_ElementKind a_kind)
{
m_ChildList.push_back(new LogViewXdrValue(a_name, a_value, a_kind));
}
// ---------------------------------------------------------------
LogViewXdrElement* LogViewXdrStruct::getChild(const uint32_t a_childIndex) const
{
if (m_ChildList.size() > a_childIndex)
@@ -55,21 +55,21 @@ LogViewXdrElement* LogViewXdrStruct::getChild(const uint32_t a_childIndex) const
}
// ---------------------------------------------------------------
LogViewXdrType* LogViewXdrStruct::getChildAsType(const uint32_t a_childIndex) const
{
return static_cast<LogViewXdrType*>(getChild(a_childIndex));
return static_cast<LogViewXdrType*>(getChild(a_childIndex)); // fixme: check ob es wirklich ein XdrType ist
}
// ---------------------------------------------------------------
LogViewXdrValue* LogViewXdrStruct::getChildAsValue(const uint32_t a_childIndex) const
{
return static_cast<LogViewXdrValue*>(getChild(a_childIndex));
return static_cast<LogViewXdrValue*>(getChild(a_childIndex)); // fixme: check ob es wirklich ein XdrValue ist
}
// ---------------------------------------------------------------
void LogViewXdrStruct::dump() const
{
INFO_LOG(m_logger) << "Element[" << getName().toStdString() << "]: kind=" << getKindName().toStdString() << " enumSize=" << getEnumSize();
@@ -84,7 +84,7 @@ void LogViewXdrStruct::dump() const
INFO_LOG(m_logger) << "-------------- childs end -----------------";
}
// ---------------------------------------------------------------
uint32_t LogViewXdrStruct::getChildValue(const QString& a_name, bool* a_error) const
{
if (a_error)
@@ -101,5 +101,5 @@ uint32_t LogViewXdrStruct::getChildValue(const QString& a_name, bool* a_error) c
return 0;
}
}
} // namespace N_LogView
@@ -1,15 +1,15 @@
// **************************************************************************
//
// (C) Copyright 2009 Swiss SIMTEC AG
//
// **************************************************************************
//
// $HeadURL$
// $LastChangedBy$
// $LastChangedDate$
// $LastChangedRevision$
//
// **************************************************************************
#pragma once
@@ -17,7 +17,7 @@
#include "LogViewXdrElement.hpp"
#include <vector>
// forward declarations from stereotyped includes
namespace N_LogView
{
class LogViewXdrValue;
@@ -29,8 +29,13 @@ namespace N_LogView
namespace N_LogView
{
/**
* This class represents elements which have childs.
* This are enum and struct.
* @author alois.wismer
* @version 1.0
* @created 31-Mrz-2010 11:59:19
*/
class LogViewXdrStruct final : public LogViewXdrElement
{
public:
@@ -1,22 +1,22 @@
// **************************************************************************
//
// (C) Copyright 2009 Swiss SIMTEC AG
//
// **************************************************************************
//
// $HeadURL$
// $LastChangedBy$
// $LastChangedDate$
// $LastChangedRevision$
//
// **************************************************************************
#include "LogViewXdrType.hpp"
namespace N_LogView
{
// ---------------------------------------------------------------
LogViewXdrType::LogViewXdrType(const QString& a_name, const QString& a_type, const uint16_t a_arraySize, const uint16_t a_dynArrayOffset, const E_ElementKind a_kind)
: LogViewXdrElement(a_name, a_kind, "LogViewXdrElement")
, m_Type(a_type)
@@ -29,7 +29,7 @@ LogViewXdrType::LogViewXdrType(const QString& a_name, const QString& a_type, con
}
// ---------------------------------------------------------------
LogViewXdrType::LogViewXdrType(const QString& a_name, const QString& a_type, const uint16_t a_arraySize, const uint16_t a_dynArrayOffset, const E_ElementKind a_kind, const int16_t a_firstBit, const int16_t a_lastBit, const bool a_isLast)
: LogViewXdrElement(a_name, a_kind, "LogViewXdrType")
, m_Type(a_type)
@@ -42,7 +42,7 @@ LogViewXdrType::LogViewXdrType(const QString& a_name, const QString& a_type, con
}
// ---------------------------------------------------------------
void LogViewXdrType::dump() const
{
INFO_LOG(m_logger) << "Element[" << getName()
@@ -56,27 +56,27 @@ void LogViewXdrType::dump() const
}
// ---------------------------------------------------------------
const QString& LogViewXdrType::getType() const
{
return m_Type;
}
// ---------------------------------------------------------------
// 0 => opaque
// 1 => normal (scalar) element
// >1 => array
// ---------------------------------------------------------------
uint16_t LogViewXdrType::getArraySize() const
{
return m_ArraySize;
}
// ---------------------------------------------------------------
bool LogViewXdrType::maskValue(uint32_t& a_value, const uint16_t a_size, QString& a_tooltip) const
{
// INFO_LOG(m_logger) << "firstBit=" << m_FirstBit << " lastBit=" << m_LastBit << " isLast=" << m_IsLast;
if (m_FirstBit != -1 && m_LastBit != -1)
{
DEBUG_LOG(m_logger) << "MaskValue for Element " << m_Name
@@ -86,9 +86,9 @@ bool LogViewXdrType::maskValue(uint32_t& a_value, const uint16_t a_size, QString
<< " isLast: " << m_IsLast;
uint16_t bitshift = (a_size*8)-m_LastBit-1;
uint32_t mask = (1<<(m_LastBit-m_FirstBit+1))-1;
// INFO_LOG(m_logger) << "value=" << a_value << " bitshift=" << bitshift << " mask=" << mask;
a_value = (a_value >> bitshift) & mask;
// make bold the corresponding bits in the bitfield
a_tooltip.insert(a_tooltip.length()-(a_size*8)+m_FirstBit, QLatin1String("<b>"));
a_tooltip.insert(a_tooltip.length()-(a_size*8)+m_LastBit+1, QLatin1String("</b>"));
return m_IsLast;
@@ -97,10 +97,10 @@ bool LogViewXdrType::maskValue(uint32_t& a_value, const uint16_t a_size, QString
}
// ---------------------------------------------------------------
uint16_t LogViewXdrType::getMaxArraySize() const
{
return m_MaxArraySize;
}
}
} // namespace N_LogView
@@ -1,15 +1,15 @@
// **************************************************************************
//
// (C) Copyright 2009 Swiss SIMTEC AG
//
// **************************************************************************
//
// $HeadURL$
// $LastChangedBy$
// $LastChangedDate$
// $LastChangedRevision$
//
// **************************************************************************
#pragma once
@@ -17,18 +17,43 @@
namespace N_LogView
{
/**
* This class represents XDR-elements which have a type and an arraySize. This are
* typedefs and struct-elements.
* The arraySize has following possibilities:
* 0 => opaque
* 1 => scalar
* >1 => array
*
* @author alois.wismer
* @version 1.0
* @created 16-Feb-2010 15:48:24
*/
class LogViewXdrType final : public LogViewXdrElement
{
public:
/**
*
* @param a_name
* @param a_type
* @param a_arraySize
* @param a_dynArrayOffset
* @param a_kind
*/
LogViewXdrType(const QString& a_name, const QString& a_type, const uint16_t a_arraySize, const uint16_t a_dynArrayOffset, const E_ElementKind a_kind);
/**
*
* @param a_name
* @param a_type
* @param a_arraySize
* @param a_dynArrayOffset
* @param a_kind
* @param a_firstBit
* @param a_lastBit
* @param a_isLast
*/
LogViewXdrType(const QString& a_name, const QString& a_type, const uint16_t a_arraySize, const uint16_t a_dynArrayOffset, const E_ElementKind a_kind, const int16_t a_firstBit, const int16_t a_lastBit, const bool a_isLast);
@@ -37,12 +62,19 @@ namespace N_LogView
const QString& getType() const;
/**
* 0 => opaque
* 1 => normal (scalar) element
* >1 => array
*/
uint16_t getArraySize() const;
/**
*
* @param a_value
* @param a_size
* @param a_tooltip
*/
bool maskValue(uint32_t& a_value, const uint16_t a_size, QString& a_tooltip) const;
@@ -51,20 +83,27 @@ namespace N_LogView
protected:
QString m_Type;
/**
* 0 => opaque
* 1 => normal (scalar) element
* >1 => array
*/
uint16_t m_ArraySize;
/**
* The maximum size of the array. Interesting for dynamic arrays.
*/
uint16_t m_MaxArraySize;
/**
* The first relevant bit, if we have bitfield-enum
*/
int16_t m_FirstBit;
/**
* The last relevant bit, if we have bitfield-enum
*/
int16_t m_LastBit;
/**
* used to step to next values when reading out content-data of bit-fields
*/
bool m_IsLast;
};
@@ -1,15 +1,15 @@
// **************************************************************************
//
// (C) Copyright 2009 Swiss SIMTEC AG
//
// **************************************************************************
//
// $HeadURL$
// $LastChangedBy$
// $LastChangedDate$
// $LastChangedRevision$
//
// **************************************************************************
#include "LogViewXdrValue.hpp"
@@ -17,24 +17,24 @@
namespace N_LogView
{
// ---------------------------------------------------------------
LogViewXdrValue::LogViewXdrValue(const QString& a_name, const int64_t a_value, const LogViewXdrElement::E_ElementKind a_kind)
: LogViewXdrElement(a_name, a_kind, "LogViewXdrValue")
, m_Value(a_value)
{}
// ---------------------------------------------------------------
void LogViewXdrValue::dump() const
{
INFO_LOG(m_logger) << "Element[" << getName() << "]: kind=" << getKindName() << " value=" << getValue();
}
// ---------------------------------------------------------------
int64_t LogViewXdrValue::getValue() const
{
return m_Value;
}
}
} // namespace N_LogView
@@ -1,15 +1,15 @@
// **************************************************************************
//
// (C) Copyright 2009 Swiss SIMTEC AG
//
// **************************************************************************
//
// $HeadURL$
// $LastChangedBy$
// $LastChangedDate$
// $LastChangedRevision$
//
// **************************************************************************
#pragma once
@@ -17,8 +17,14 @@
namespace N_LogView
{
/**
* This class represents XDR-elements which have a value. This are #defines and
* enum-elements.
*
* @author alois.wismer
* @version 1.0
* @created 17-Feb-2010 11:17:53
*/
class LogViewXdrValue final : public LogViewXdrElement
{
public:
@@ -1,5 +1,10 @@
/**
* @RDE_HEADER@
* Building Config - logging facility
* $Id$
* $HeadURL$
* $Author$
*/
#include "logger.h"
@@ -29,4 +34,4 @@ LOGGER_T getLogger(const char *name)
}
}
}
} // namespace LogView
@@ -1,5 +1,10 @@
/**
* @RDE_HEADER@
* Logging for AudioVideoManagement
* $Id$
* $HeadURL$
* $Author$
*/
#pragma once
@@ -14,4 +19,4 @@ inline LOGGER_T getLogger(const QString &loggerName)
{
return getLogger(loggerName.toUtf8().constData());
}
}
} // namespace LogView
@@ -1,15 +1,15 @@
// **************************************************************************
//
// (C) Copyright 2009 Swiss SIMTEC AG
//
// **************************************************************************
//
// $HeadURL$
// $LastChangedBy$
// $LastChangedDate$
//
// Implementation of the Class AppComponent
// **************************************************************************
#include "AppComponent.hpp"
@@ -84,5 +84,5 @@ IAppComponent *AppComponent::getChild(const QString &a_name)
return nullptr;
}
}
} // namespace N_AppComponent
@@ -1,14 +1,14 @@
// **************************************************************************
//
// (C) Copyright 2009 Swiss SIMTEC AG
//
// **************************************************************************
// $HeadURL$
// $LastChangedBy$
// $LastChangedDate$
//
// Implementation of the Class AppComponent
// **************************************************************************
#pragma once
@@ -1,14 +1,14 @@
// **************************************************************************
//
// (C) Copyright 2009 Swiss SIMTEC AG
//
// **************************************************************************
// $HeadURL$
// $LastChangedBy$
// $LastChangedDate$
//
// Implementation of the Class IAppComponent
// **************************************************************************
#pragma once
@@ -13,7 +13,7 @@ int main(int argc, char **argv)
{
QCoreApplication app(argc, argv);
// Check alle 30 Sekunden
NGL::NGLLoggerBootstrap::createNGLRootLogger("log4cxx_tetra.props", false);
NGL::INGLLogger &logger(NGL::NGLLoggerBootstrap::getNGLRootLogger());
@@ -1,5 +1,9 @@
/**
* Tetra-Interface für Lasttest
* $Id$
* $HeadURL$
* $Author$
*/
#include "tetra_if.h"
#include <utility>
@@ -48,7 +52,7 @@ void TetraIF::start()
void TetraIF::listenMode(const QStringList &args)
{
// take input and write them to and output directory
if (args.count() > 1)
usage();
m_outputDir = QCoreApplication::applicationDirPath();
@@ -177,7 +181,7 @@ void TetraIF::onReadyRead()
do
{
DEBUG_LOG(m_logger) << "Got " << m_socket->bytesAvailable() << " bytes from socket";
// read the 4-byte frame-header for find out the length of whole telegram
N_CoPrtCnv::CoPrtCnvRadioTelegram::PrtCnvRadioGwHeader header;
if (m_socket->bytesAvailable() < int(sizeof(header)))
return;
@@ -234,24 +238,24 @@ void TetraIF::handleReceivedTelegram(const QByteArray &data)
switch (type)
{
// response to register indication
case N_CoPrtCnv::CoPrtCnvRadioTelegram::e_RegisterRsp:
handleRegisterRsp(data.at(5));
handleRegisterRsp(data.at(5)); // registration status
break;
// payload telegram
case N_CoPrtCnv::CoPrtCnvRadioTelegram::e_DataIndReq:
handleDataIndReq(data);
break;
// ack-telegram - not handled here
case N_CoPrtCnv::CoPrtCnvRadioTelegram::e_ReportIndReq:
// handleReportIndReq(data);
break;
// air-interface-load-telegram - not handled here
case N_CoPrtCnv::CoPrtCnvRadioTelegram::e_AirInterfaceLoadReq:
// handleAirInterfaceLoadReq(data);
break;
default:
@@ -297,7 +301,7 @@ void TetraIF::handleRegisterRsp(const uint8_t a_registrationStatus)
void TetraIF::dumpData(const QByteArray &data)
{
// im Listen-Mode -> Ausgabe in Directory
if (m_outputDir.isEmpty())
return;
const qint64 msecs = QDateTime::currentMSecsSinceEpoch();
@@ -332,7 +336,7 @@ void TetraIF::dumpData(const QByteArray &data)
<< " for writing - error: "
<< f.errorString();
}
// 27 Bytes Header entfernen
f.write(&data.data()[27], data.size() - 27);
f.close();
}
@@ -341,7 +345,7 @@ void TetraIF::dumpData(const QByteArray &data)
void TetraIF::onSendData()
{
++m_secondFragment;
// we're called every 10ms
if (m_secondFragment == 100)
{
m_secondFragment = 0;
@@ -358,7 +362,7 @@ void TetraIF::onSendData()
{
for (unsigned short dest_issi : std::as_const(m_issiList))
{
// GEF_BESTAETIGUNG -> Dummy, gets overridden by setPayloadDataComplete()
m_data[0] = s_randomChar++;
N_CoPrtCnv::CoPrtCnvRadioTelegram tele(GEF_BESTAETIGUNG, m_data.size(), dest_issi);
tele.setPayloadDataComplete(m_data);
@@ -383,7 +387,7 @@ void TetraIF::onSendData()
void TetraIF::parseISSIs(const QStringList &issiList)
{
m_issiList.clear();
// broadcast
if (issiList.count() == 0)
{
m_issiList += 0;
@@ -430,7 +434,7 @@ void TetraIF::handleDataIndReq(const QByteArray &data)
break;
}
delete radioTelegram;
delete radioTelegram; // this deletes also a_data
}
}
@@ -438,7 +442,7 @@ void TetraIF::handleLoginTelegram(N_CoPrtCnv::CoPrtCnvRadioTelegram *a_loginTele
{
uint16_t identity = a_loginTelegram->getIdentity();
uint32_t issi = a_loginTelegram->getSrcISSI();
// is it a login request?
if (N_CoPrtCnv::CoPrtCnvRadioTelegram::e_LoginRequest == (a_loginTelegram->getPayloadDataUInt8(2) & N_CoPrtCnv::CoPrtCnvRadioTelegram::e_LoginStatusMask))
{
bool sent = sendLoginResponse(issi);
@@ -456,33 +460,33 @@ bool TetraIF::sendLoginResponse(const uint32_t a_ISSI)
++m_SendCounter;
N_CoPrtCnv::CoPrtCnvRadioTelegram *a_telegram = new N_CoPrtCnv::CoPrtCnvRadioTelegram(GEF_BESTAETIGUNG, 20, a_ISSI);
a_telegram->setZaehler(m_SendCounter);
// set our ISSI
a_telegram->setDestISSI(a_ISSI);
a_telegram->setSrcISSI(2);
gef_telegramm_id_et telId = a_telegram->isNormalTelegram() ? a_telegram->getTelID() : GEF_BESTAETIGUNG;
// send telegram to radio
INFO_LOG(m_logger) << "Send telegram to radio: telId=" << telId << " wcounter=" << a_telegram->zaehler() << " size= 28";
// Protokoll-Byte wird hier mit als Datenbyte missbraucht...
a_telegram->setProtocolIdentifier(N_CoPrtCnv::CoPrtCnvRadioTelegram::e_TDSMessageWithoutSDS_TL);
a_telegram->setPayloadData(0x01);
a_telegram->setPayloadData(0x04);
a_telegram->getData()[22] = 0x0d;
// Bitanzahl anpassen
a_telegram->getData()[22] = 0x0d; // Warum 13 (bzw. 21) ??
char *data = a_telegram->getData();
data[02] = 0x18;
// Header - complete Payload in Bytes
data[02] = 0x18; // 24 Bytes
// Len in Bits
data[22] = 0x0d;
data[23] = 0x00;
// Len in Bytes
data[24] = 0x02;
data[25] = 0x00;
// Data
data[13] = 0x00;
data[26] = 0x01;
data[27] = 0x40;
@@ -1,5 +1,9 @@
/**
* Tetra-Interface für Lasttest
* $Id$
* $HeadURL$
* $Author$
*/
#pragma once
#include <QtCore/QObject>
#include <QtNetwork/QHostAddress>
@@ -22,10 +22,10 @@ MainWindow::MainWindow(QWidget *parent) :
MainWindow::~MainWindow()
{
m_files.clear();
//m_logfile.~QString();
//delete m_logfileList;
// m_logZeiten.~QString();
//delete ui;
}
void MainWindow::changeEvent(QEvent *e)
@@ -43,10 +43,10 @@ void MainWindow::changeEvent(QEvent *e)
void MainWindow::init()
{
//Connect Signals & Slots
connect(ui->pushButtonOrdnerFinden, &QPushButton::clicked, this, &MainWindow::slot_findFolder);
connect(ui->pushButtonAnalysieren, &QPushButton::clicked, this, &MainWindow::slot_analysieren);
//m_logfileList = new QList<LogfileInfo>();
ui->progressBar->setValue(0);
ui->labelResult->setText(QString());
QIntValidator intVal;
@@ -57,9 +57,16 @@ void MainWindow::init()
void MainWindow::slot_findFolder()
{
//hier liegt der fehler???, der erst beim zweiten mal ausführen des Dateibrowsers in erscheinung tritt
/*QFileDialog dial(this);
dial.setFileMode(QFileDialog::Directory);
dial.setViewMode(QFileDialog::List);
QStringList files;
if (dial.exec())
files = dial.selectedFiles();
QString name = files.at(0);
//testblabla
*/
QString name = QFileDialog::getExistingDirectory(this, tr("Choose folder"), QDir::homePath(), QFileDialog::DontResolveSymlinks);
ui->lineEditOrdner->setText(name);
ui->labelResult->setText(QString());
@@ -74,7 +81,7 @@ void MainWindow::slot_analysieren()
ISSI = QLatin1String("1");
m_logfileList.clear();
//alle DAteien in dem Ordner finden
QDir folder(ui->lineEditOrdner->text());
m_files = folder.entryList();
folder.~QDir();
@@ -83,7 +90,7 @@ void MainWindow::slot_analysieren()
const QString issitext = ISSI + QLatin1String("-1");
for (int i = 0; i < m_files.count(); i++)
{
//Dateinamen entfernen, die keine Payload-Logs sind
QString name = m_files[i];
if (name.contains(paytext))
{
@@ -136,7 +143,7 @@ void MainWindow::readFiles()
QFile file(filename);
if (file.open(QIODevice::ReadOnly))
{
//Datei auslesen
QByteArray ar = file.read(150);
file.close();
if (ar.size() > 36)
@@ -144,21 +151,21 @@ void MainWindow::readFiles()
QString issi = getISSI(ar);
QByteArray bytes = ar;
//Laufende Nummer
bytes.remove(0, 34);
bytes.remove(2, 150);
uint nr = bytes[0] & 255;
nr *= 256;
nr += bytes[1] & 255;
//BytesNr 34+35
//Sendezeit
bytes = ar;
bytes.remove(0, 30);
bytes.remove(4, 150);
const QByteArray test = bytes.toHex();
qint64 zeit = test.toLongLong(nullptr, 16);
//Byte 30-33
const QDateTime timeStart(QDateTime::fromMSecsSinceEpoch(zeit * 1000));
writeToLogfile(issi, timeStart, getTimestamp(m_files[j]), m_files[j], nr);
@@ -172,7 +179,7 @@ void MainWindow::readFiles()
val *= (j + 1);
val += 20;
ui->progressBar->setValue(int(val));
// ui->progressBar->repaint();
}
}
@@ -273,7 +280,7 @@ QDateTime MainWindow::getTimestamp(const QString &filename) const
QString MainWindow::getISSI(QByteArray ar)
{
//wird nur für die "2-timestamp"-Dateien verwendet
ar.remove(0, 5);
ar.remove(4, 200);
QByteArray issi = ar.toHex();
@@ -310,7 +317,7 @@ QString MainWindow::getISSI(QByteArray ar)
int MainWindow::auswerten()
{
//Logfile vorbereiten
QFile f(m_logfile);
if (!f.open(QIODevice::Append | QIODevice::Text))
return -1;
@@ -319,7 +326,7 @@ int MainWindow::auswerten()
issis.reserve(100);
for (int i = 0; i < m_logfileList.count(); i++)
{
//Unterschiedliche Issis finden
issis += m_logfileList.at(i).issi;
}
ui->progressBar->setValue(94);
@@ -329,7 +336,7 @@ int MainWindow::auswerten()
int i = 0;
for (const QString &issi : std::as_const(issis))
{
//für jede Issi die Nummern in timestampMap einlesen --> geordnet nach Zeitstempel
numList.clear();
for (int j = 0; j < m_logfileList.count(); j++)
{
@@ -344,7 +351,7 @@ int MainWindow::auswerten()
f.write(text);
fehlcount += fehlendeNumsEintragen(numList, f);
// delete numList;
double val = 5;
val /= issis.count();
@@ -360,7 +367,7 @@ int MainWindow::auswerten()
int MainWindow::fehlendeNumsEintragen(const QVector<uint> &numList, QFile &f)
{
//schreibt die fehlenden Nummern in das Logfile und die GUI
QVector<uint> fehlendeNums = getFehlendeNums(numList);
QByteArray text = QByteArray::number(fehlendeNums.count());
text += " lost messages\n";
@@ -370,7 +377,7 @@ int MainWindow::fehlendeNumsEintragen(const QVector<uint> &numList, QFile &f)
text += QByteArray::number(fehlendeNums.at(j));
text += ", ";
}
// delete fehlendeNums;
text += ")\n";
f.write(text);
@@ -380,13 +387,13 @@ int MainWindow::fehlendeNumsEintragen(const QVector<uint> &numList, QFile &f)
QVector<uint> MainWindow::getFehlendeNums(const QVector<uint> &numsDurchgang)
{
//ermittelt die fehlenden Nummern pro Durchgang
uint count = numsDurchgang.count();
uint maxnum = 0;
uint minnum = 999999;
for (uint k = 0; k < count; k++)
{
//höchste und niedrigste Num finden
if (numsDurchgang.at(k) > maxnum)
maxnum = numsDurchgang.at(k);
if (numsDurchgang.at(k) < minnum)
@@ -396,7 +403,7 @@ QVector<uint> MainWindow::getFehlendeNums(const QVector<uint> &numsDurchgang)
QVector<uint> fehlendeNum;
for (uint z = minnum; z <= maxnum; z++)
{
//liste nach fehlenden werten durchsuchen
bool vorhanden = false;
for (uint j = 0; j < count; j++)
{
@@ -425,5 +432,5 @@ void MainWindow::writeLogZeiten(const QDateTime &beginn, const QDateTime &end, c
file.write(msg.toUtf8());
file.close();
//delete end;
}
@@ -51,7 +51,7 @@ private:
const QDateTime &timestamp,
const QString &filename,
uint lfdNr);
QString getISSI(QByteArray ar);
QString getISSI(QByteArray ar);//Für alte TPUS
int auswerten();
QVector<uint> getFehlendeNums(const QVector<uint> &numsDurchgang);
int fehlendeNumsEintragen(const QVector<uint> &numList, QFile &file);
@@ -66,4 +66,4 @@ private slots:
#endif
#endif // MAINWINDOW_H
@@ -1,16 +1,16 @@
// **************************************************************************
//
// (C) Copyright 2009 Swiss SIMTEC AG
//
// **************************************************************************
//
// $HeadURL$
// $LastChangedBy$
// $LastChangedDate$
// $LastChangedRevision$
//
// Implementation of the Class PrtCnvApplication
// **************************************************************************
#include "PrtCnvApplication.hpp"
#include "PrtCnvThreadStarter.hpp"
@@ -65,9 +65,9 @@ PrtCnvApplication::~PrtCnvApplication()
}
// ---------------------------------------------------------------
// Synchronisation of threads before create().
// ---------------------------------------------------------------
void PrtCnvApplication::waitForCreate(const E_ThreadId a_threadId)
{
INFO_LOG(m_logger) << "Wait for others until we can create " << threadIdToString(a_threadId);
@@ -111,9 +111,9 @@ void PrtCnvApplication::waitForCreate(const E_ThreadId a_threadId)
}
// ---------------------------------------------------------------
// Synchronisation of threads before init().
// ---------------------------------------------------------------
void PrtCnvApplication::waitForInit(E_ThreadId a_threadId)
{
INFO_LOG(m_logger) << "Wait for others until we can initialize " << threadIdToString(a_threadId);
@@ -152,9 +152,9 @@ void PrtCnvApplication::waitForInit(E_ThreadId a_threadId)
INFO_LOG(m_logger) << "Now we can initialize " << threadIdToString(a_threadId);
}
// ---------------------------------------------------------------
// Synchronisation of threads before start().
// ---------------------------------------------------------------
void PrtCnvApplication::waitForStart(E_ThreadId a_threadId)
{
INFO_LOG(m_logger) << "Wait for others until we can start " << threadIdToString(a_threadId);
@@ -209,17 +209,17 @@ void PrtCnvApplication::waitForStart(E_ThreadId a_threadId)
}
// ---------------------------------------------------------------
// Synchronisation of threads before execution of thread.
// ---------------------------------------------------------------
void PrtCnvApplication::waitForExec(E_ThreadId a_threadId)
{
setStarted(a_threadId);
}
// ---------------------------------------------------------------
// Starts the main-application
// ---------------------------------------------------------------
void PrtCnvApplication::startApp()
{
createApplication();
@@ -258,9 +258,9 @@ void PrtCnvApplication::setConfigFile(const QString &configFile)
m_ConfigFileName = configFile;
}
// ---------------------------------------------------------------
// Creates the childs
// ---------------------------------------------------------------
int32_t PrtCnvApplication::createApplication()
{
setName(QStringLiteral("Common"));
@@ -283,12 +283,12 @@ int32_t PrtCnvApplication::createApplication()
return 0;
}
// ---------------------------------------------------------------
// Starts the childs and then the main application
// ---------------------------------------------------------------
int32_t PrtCnvApplication::start()
{
// start and create threads
for (const auto &ti : m_threadInfo)
ti.thread->start();
@@ -298,9 +298,9 @@ int32_t PrtCnvApplication::start()
}
// ---------------------------------------------------------------
// Returns the desired thread-starter
// ---------------------------------------------------------------
PrtCnv::PrtCnvThreadStarter *PrtCnvApplication::getThreadStarter(const E_ThreadId a_threadId)
{
if (a_threadId < e_Central || a_threadId >= e_ThreadIdMax)
@@ -334,7 +334,7 @@ void PrtCnvApplication::logWlsTelegram(const TrainingAreaBase::TetraIcd::Trainin
t->writeWlsTelegramLog(tele, bIsSend, 0);
}
// ---------------------------------------------------------------
bool PrtCnvApplication::isConstructed(const E_ThreadId a_threadId) const
{
if (a_threadId < e_Central || a_threadId >= e_ThreadIdMax)
@@ -343,7 +343,7 @@ bool PrtCnvApplication::isConstructed(const E_ThreadId a_threadId) const
return m_threadInfo[a_threadId].isConstructed;
}
// ---------------------------------------------------------------
void PrtCnvApplication::setConstructed(const E_ThreadId a_threadId)
{
if (a_threadId < e_Central || a_threadId >= e_ThreadIdMax)
@@ -352,7 +352,7 @@ void PrtCnvApplication::setConstructed(const E_ThreadId a_threadId)
m_threadInfo[a_threadId].isConstructed = true;
}
// ---------------------------------------------------------------
bool PrtCnvApplication::isInitialized(const E_ThreadId a_threadId) const
{
if (a_threadId < e_Central || a_threadId >= e_ThreadIdMax)
@@ -361,7 +361,7 @@ bool PrtCnvApplication::isInitialized(const E_ThreadId a_threadId) const
return m_threadInfo[a_threadId].isInitialized;
}
// ---------------------------------------------------------------
void PrtCnvApplication::setInitialized(const E_ThreadId a_threadId)
{
if (a_threadId < e_Central || a_threadId >= e_ThreadIdMax)
@@ -370,7 +370,7 @@ void PrtCnvApplication::setInitialized(const E_ThreadId a_threadId)
m_threadInfo[a_threadId].isInitialized = true;
}
// ---------------------------------------------------------------
bool PrtCnvApplication::isCreated(const E_ThreadId a_threadId) const
{
if (a_threadId < e_Central || a_threadId >= e_ThreadIdMax)
@@ -379,7 +379,7 @@ bool PrtCnvApplication::isCreated(const E_ThreadId a_threadId) const
return m_threadInfo[a_threadId].isCreated;
}
// ---------------------------------------------------------------
void PrtCnvApplication::setCreated(const E_ThreadId a_threadId)
{
if (a_threadId < e_Central || a_threadId >= e_ThreadIdMax)
@@ -388,7 +388,7 @@ void PrtCnvApplication::setCreated(const E_ThreadId a_threadId)
m_threadInfo[a_threadId].isCreated = true;
}
// ---------------------------------------------------------------
bool PrtCnvApplication::isStarted(const E_ThreadId a_threadId) const
{
if (a_threadId < e_Central || a_threadId >= e_ThreadIdMax)
@@ -397,7 +397,7 @@ bool PrtCnvApplication::isStarted(const E_ThreadId a_threadId) const
return m_threadInfo[a_threadId].isStarted;
}
// ---------------------------------------------------------------
void PrtCnvApplication::setStarted(const E_ThreadId a_threadId)
{
if (a_threadId < e_Central || a_threadId >= e_ThreadIdMax)
@@ -406,4 +406,4 @@ void PrtCnvApplication::setStarted(const E_ThreadId a_threadId)
m_threadInfo[a_threadId].isStarted = true;
}
}
} // namespace PrtCnv
@@ -1,16 +1,16 @@
// **************************************************************************
//
// (C) Copyright 2009 Swiss SIMTEC AG
//
// **************************************************************************
//
// $HeadURL$
// $LastChangedBy$
// $LastChangedDate$
// $LastChangedRevision$
//
// Implementation of the Class PrtCnvApplication
// **************************************************************************
#pragma once
@@ -23,20 +23,32 @@
#include "prtcnvlib_export.h"
#include <TrainingAreaBase/training_area_telegrams.h>
/**
* Here are all project specific classes of protocol-converter implemented.
*/
namespace PrtCnv
{
class PrtCnvThreadStarter;
/**
* The main-application of protocol-converter. It is responsible for starting and
* controlling the threads of this application.
*
* @author alois.wismer
* @version 1.0
* @created 23-Jun-2009 17:48:47
*/
class PRTCNVLIB_EXPORT PrtCnvApplication : public QObject, public N_AppComponent::AppComponent
{
Q_OBJECT
public:
/**
* This enum will be used to unique identify the threads
*
* @author alois.wismer
* @version 1.0
* @created 19-Jan-2010 17:09:00
*/
enum E_ThreadId
{
e_Central,
@@ -50,8 +62,9 @@ namespace PrtCnv
PrtCnvApplication();
~PrtCnvApplication();
/**
* Starts the main-application
*/
void startApp();
void shutdownApp();
static void setCleanDb(bool bCleanDb);
@@ -59,33 +72,51 @@ namespace PrtCnv
int exerciseId() const { return m_exerciseId; }
void setConfigFile(const QString &configFile);
/**
* Starts the childs and then the main application
*/
int32_t start() override;
/**
* Synchronisation of threads before init().
*
* @param a_threadId id of the calling thread
*/
void waitForInit(E_ThreadId a_threadId);
/**
* Synchronisation of threads before start().
*
* @param a_threadId id of the calling thread
*/
void waitForStart(E_ThreadId a_threadId);
/**
* Synchronisation of threads before create().
*
* @param a_threadId Id of the calling thread
*/
void waitForCreate(const E_ThreadId a_threadId);
/**
* Synchronisation of threads before execution of thread.
*
* @param a_threadId id of the calling thread
*/
void waitForExec(E_ThreadId a_threadId);
/**
* Returns the desired thread-starter
*
* @param a_threadId Id of the desired thread-started (corresponding thread has
* the same id)
*/
PrtCnvThreadStarter* getThreadStarter(const E_ThreadId a_threadId);
/**
* @brief Set the database connection parameter when used as library
*/
void setDatabaseConnectionParams(const QString &driver,
const QString &hostName,
const QString &database,
@@ -108,45 +139,59 @@ signals:
void outgoingBroadcastTelegramsRequest(int equipmentNumber, int broadcastIndex, int resetCounter);
void warehouseMessageFromPtrCnv(const QByteArray &jsonData);
protected:
/**
* Creates the childs
*/
int32_t createApplication();
/**
* Returns true when the specified thread is
* already constructed
*/
bool isConstructed(const E_ThreadId a_threadId) const;
/**
* The specifed thread is now constructed
*/
void setConstructed(const E_ThreadId a_threadId);
/**
* Returns true when the specified thread is
* already initialized
*/
bool isInitialized(const E_ThreadId a_threadId) const;
/**
* The specifed thread is now initialized
*/
void setInitialized(const E_ThreadId a_threadId);
/**
* Returns true when the specified thread is
* already created
*/
bool isCreated(const E_ThreadId a_threadId) const;
/**
* The specifed thread is now created
*/
void setCreated(const E_ThreadId a_threadId);
/**
* Returns true when the specified thread is
* already started
*/
bool isStarted(const E_ThreadId a_threadId) const;
/**
* The specifed thread is now started
*/
void setStarted(const E_ThreadId a_threadId);
protected:
/**
* Used to get configuration-parameter
*/
NGL::Settings *m_Config;
struct ThreadInfo
@@ -157,11 +202,13 @@ protected:
bool isInitialized = false;
bool isStarted = false;
} m_threadInfo[e_ThreadIdMax];
/**
* The name of the config-file
*/
QString m_ConfigFileName;
/**
* The exerciseId (or zero if not set)
*/
int m_exerciseId;
File diff suppressed because it is too large. Load diff
@@ -1,15 +1,15 @@
// **************************************************************************
//
// (C) Copyright 2009 Swiss SIMTEC AG
//
// **************************************************************************
//
// $HeadURL$
// $LastChangedBy$
// $LastChangedDate$
// $LastChangedRevision$
//
// **************************************************************************
#pragma once
@@ -39,15 +39,27 @@ namespace PrtCnv
{
class PrtCnvDbThread;
/**
* This class is responsible for handling all the broadcast stuff. This includes:
* - sending the broadcast 3 times
* - sending Broadcast-Nachforderungen to TNE
* - store and manage the broadcast-list
* - measure the Broadcast-Nachforderung-statistic
* @author wia
* @version 1.0
* @updated 30-Apr-2010 11:21:05
*/
class PrtCnvBroadcastMgr final : public QObject
{
Q_OBJECT
public:
/**
* The different states the broadcast-manager can be.
* @author wia
* @version 1.0
* @updated 30-Apr-2010 11:21:05
*/
enum E_State
{
e_ST_UNDEFINED,
@@ -57,74 +69,124 @@ public:
PrtCnvBroadcastMgr();
/**
* returns true when the telegram should be sent to central
*
* @param a_radioTelegram
*/
bool handleRadioTelegram(const N_CoPrtCnv::CoPrtCnvRadioTelegram &a_radioTelegram);
/**
* Creates all subcomponents
*/
int32_t create(NGL::Settings *settings);
/**
* Initializes the variables.
*/
int32_t init();
/**
* returns the next normal broadcast to send.
* a_doDelete is true, when the caller has to delete the telegram when no longer
* using it.
* Use the same a_actualTime in one tick-loop.
*
* @param a_beginSearchWithBroadcastIndex
* @param a_actualTime
* @param a_doDelete true if telegram must be deleted after using it
*/
std::shared_ptr<N_CoPrtCnv::CoPrtCnvRadioTelegram> getNextBroadcastTelegramToSend(const uint16_t a_beginSearchWithBroadcastIndex,
const time_t a_currentTime);
/**
* sets the DbThread used for get the stored broadcast-telegrams
*
* @param a_dbThread
*/
void setDbThread(PrtCnvDbThread *a_dbThread);
/**
* Initializes the broadcast-manager. If a_deleteTelegrams is true, all stored
* telegrams and maps will be deleted.
*
* @param a_deleteTelegrams
*/
void cleanAndInit(const bool a_deleteTelegrams);
/**
* Removes all Nop out of broadcast-list and numerates the broadcast-index of kept
* broadcast-telegrams new.
*
* @param a_doRestore
*/
void handleOverrunOfBroadcastCounter(const bool a_doRestore = false);
/**
* returns the next broadcast to send for nachforderungen
*/
std::shared_ptr<N_CoPrtCnv::CoPrtCnvRadioTelegram> getNextNachforderungTelegramToSend();
/**
* dumps important values, only for debugging
*/
void dump();
/**
* Restores data after crash for seamless proceeding of work.
*/
void restoreAfterCrash();
/**
* Returns the actual broadcast-index for normal broadcasts.
*/
uint16_t getBroadcastIndex() const;
/**
* Returns the broadcastindex for the next broadcast
*/
uint16_t getNextBroadcastIndex();
/**
* Adds the telegram a_broadcastOnlyTelegram (which must have set already the
* broadcast-index) to the broadcast-map. The telegram will be attached to an
* already existing broadcast-telegram with same broadcast-index in the map,
* otherwise it will be marked as broadcast-only.
* If the there is already an broadcast-only-telegram attached, nothing will be
* done.
*
* @param a_broadcastOnlyTelegram
*/
void addBroadcastOnlyTelegramToMap(const std::shared_ptr<N_CoPrtCnv::CoPrtCnvRadioTelegram> &a_broadcastOnlyTelegram);
/**
* Increments the tick-counter of broadcast-manager and informs the broadcast-
* manager about the traffic-load.
*
* @param a_isHighLoad
* @param a_isFullLoad
*/
void incTickAndSetTrafficLoad(const bool a_isHighLoad, const bool a_isFullLoad);
/**
* Checks if the given id is in m_deactivatedAesMine2bcIndex/m_deactivatedDusMine2bcIndex/m_deactivatedFuncAreaMine2bcIndex
*
* @brief isEffectSimulationIdDeactivated
* @param effectsimulationId
* @return
*/
bool isEffectSimulationIdDeactivated(const uint16_t effectsimulationId) const;
/**
* Adds the TNE to the nachforderungs-list
*
* @param a_radioTelegram
*/
void handleNachforderungBroadcastTelegram(int identity, int broadcastIndex, int resetCounter);
protected:
@@ -136,99 +198,166 @@ protected:
EquipNoBcIndex() = default;
EquipNoBcIndex(int e, int b) : equipNo(e), bcIndex(b) {}
};
/**
* Map of TNE, that sent a NachforderungBroadcast-Telegram.
* Key: identity of TNE; Value: broadcast-counter
*/
std::vector<EquipNoBcIndex> m_claimerArray;
/**
* Time (in SendGap-ticks) spent for collection NachforderungeBroadcast, before
* sending broadcasts begins
* This value will be used for normal load.
*/
uint16_t m_ClaimWindow;
/**
* the factor for widening claim-window before sending broadcasts when we have
* high load traffic
*/
uint16_t m_HighLoadFactor;
/**
* the number of TPUs needed for sending the broadcasts as broadcast instead
* directed
*/
uint16_t m_BroadcastLimit;
/**
* Used to get configuration-parameter.
*/
NGL::Settings *m_Config;
/**
* Actual time (in SendGap-ticks) spent for collection NachforderungeBroadcast,
* before sending broadcasts begins. This value changes depending on downlink-load.
*/
uint16_t m_ActClaimWindow;
/**
* The state of broadcast-manager.
*/
PrtCnvBroadcastMgr::E_State m_State;
uint16_t m_TickCounter;
/**
* The actual broadcast-index for sending nachforderungen
*/
PrtCnvDbThread *m_DbThread;
/**
* sorted by broadcast-index
*/
std::map<uint16_t, std::shared_ptr<N_CoPrtCnv::CoPrtCnvRadioTelegram>> m_BroadcastMap;
std::vector<std::shared_ptr<N_CoPrtCnv::CoPrtCnvRadioTelegram>> m_broadcastTelegamsToSend;
/**
* Contains all telegrams which must only be stored once for nachforderungen
*/
std::map<gef_telegramm_id_et, std::shared_ptr<N_CoPrtCnv::CoPrtCnvRadioTelegram>> m_LastTelegramMap;
/**
* Contains all wirkfeld-telegrams which must be stored for nachforderungen
* ordered by wirkfeldkennung.
*/
std::multimap<uint16_t, std::shared_ptr<N_CoPrtCnv::CoPrtCnvRadioTelegram>> m_WirkfeldTelegramMapByKennung;
/**
* Contains all wirkfeld-telegrams which must be stored for nachforderungen
* ordered by expiration-time.
*/
std::multimap<time_t, std::shared_ptr<N_CoPrtCnv::CoPrtCnvRadioTelegram>> m_WirkfeldTelegramMapByTime;
/**
* Contains all funktionsraum-telegrams which must be stored for nachforderungen
* ordered by funktionsraumkennung.
*/
std::map<uint16_t, std::shared_ptr<N_CoPrtCnv::CoPrtCnvRadioTelegram>> m_FunktionsraumTelegramMap;
/**
* Contains all technik-funktionsraum-telegrams which must be stored for nachforderungen
* ordered by funktionsraumkennung.
*/
std::map<uint16_t, std::shared_ptr<N_CoPrtCnv::CoPrtCnvRadioTelegram>> m_TechnikFunktionsraumTelegramMap;
/**
* The actual broadcast-index for normal broadcast
*/
uint16_t m_BroadcastIndex;
/**
* True if send-traffic is on full-load => no nachforderungen will be sent
*/
bool m_IsFullLoad;
/**
* The highest broadcast-index of 3rd time sent broadcast-telegram (for optimize
* by time)
*/
uint16_t m_FinishedBroadcastIndex;
/**
* The broadcast-index of the 1st broadcast-telegram which has been sent 1 time
* only (for optimize by time)
*/
uint16_t m_FirstBroadcastIndexOfBc1;
/**
* adds the radio-telegram to the broadcast-map, or generates the sammeltelegramme
*
* @param a_radioTelegram
*/
void addToBroadcastMap(const std::shared_ptr<N_CoPrtCnv::CoPrtCnvRadioTelegram> &a_radioTelegram);
/**
* returns the Nachforderungs-telegram with this broadcast-index from the
* broadcast-map with sammeltelegrams. If the telegram with a_broadcastIndex does
* not exist, a NOP-telegram will be returned, which must be consumed immediately
* and must never be deleted.
* The parameter a_broadcastIndex will be updated to the value of found telegram.
* ATTENTION: the returned a_broadcastIndex could be different from the value
* returned by getBroadcastIndex(), for example in NOP-telegrams
* getBroadcastIndex() returns the Anfang, but a_broadcastIndex will be the Ende.
*
* @param a_broadcastIndex
*/
std::shared_ptr<N_CoPrtCnv::CoPrtCnvRadioTelegram> getNachforderungsTelegram(int curBcIndex, int startBcIndex, int &nextBcIndex);
/**
* searches the kennung within sammeltelegram.
* returns -1 when kennung not found
*
* @param a_sammelTelegram
* @param a_kennung
*/
int getSammeltelegramIndex(const std::shared_ptr<N_CoPrtCnv::CoPrtCnvRadioTelegram> &a_sammelTelegram,
const uint16_t a_kennung) const;
/**
* Moves a_radioTelegram to a_newBroadcastIndex in broadcast-map.
* If a_radioTelegram has an attached broadcast-only-telegram, the broadcastOnly-
* telegram will be detached and kept on the old broadcast-index position.
* If a_attachTelegram in not NULL, this telegram will be attached to
* a_radioTelegram.
*
* @param a_radioTelegram The radio-telegram to be moved
* @param a_newBroadcastIndex The new broadcast-index
* @param a_attachTelegram The telegram to be attached
*/
void moveTelegramInBroadcastMap(const std::shared_ptr<N_CoPrtCnv::CoPrtCnvRadioTelegram> &a_radioTelegram,
const uint16_t a_newBroadcastIndex,
const std::shared_ptr<N_CoPrtCnv::CoPrtCnvRadioTelegram> &a_attachTelegram = {});
/**
* Removes the telegram a_radioTelegram from the broadcast-map. If the
* a_radioTelegram has an attached telegram, the attached telegram will be
* detached and added to broadcast-map as broadcast-only telegram.
* If the telegram is an attached BC-only-telegram, it will be detached.
* The telegram itself will be deleted when a_doDeleteTelegram is true.
* ATTENTION: iterators to m_BroadcastMap could be invalid after calling this
* function
*
* @param a_radioTelegram
* @param a_doDeleteTelegram
*/
void removeFromBroadcastMap(const std::shared_ptr<N_CoPrtCnv::CoPrtCnvRadioTelegram> &a_radioTelegram);
void removeFromBroadcastMapFunc(const std::function<bool(const std::shared_ptr<N_CoPrtCnv::CoPrtCnvRadioTelegram> &)> &pred);
void removeDusMineDeactivationFromBroadcastMap(int dusMineId);
@@ -242,25 +371,25 @@ protected:
bool removeFromDeactivatedAesArea(int aesAreaId);
bool addToDeactivatedAesArea(int aesAreaId, int bcIndex);
// QHash<mineId, broadcastIndexDeactivated>
QHash<int, int> m_deactivatedAesArea2bcIndex;
// QMap<broadcastIndexDeactivated, mineId>, keep sorted!
QMap<int, int> m_deactivatedBcIndex2AesArea;
std::shared_ptr<N_CoPrtCnv::CoPrtCnvRadioTelegram>createAccuTeleDeactivatedAesAreas(int curBcIndex, int startBcIndex) const;
bool removeFromDeactivatedFuncArea(int aesAreaId);
bool addToDeactivatedFuncArea(int aesAreaId, int bcIndex);
// QHash<mineId, broadcastIndexDeactivated>
QHash<int, int> m_deactivatedFuncArea2bcIndex;
// QHash<broadcastIndexDeactivated, mineId>, keep sorted!
QMap<int, int> m_deactivatedBcIndex2FuncArea;
std::shared_ptr<N_CoPrtCnv::CoPrtCnvRadioTelegram>createAccuTeleDeactivatedFuncAreas(int curBcIndex, int startBcIndex) const;
bool removeFromDeactivatedDusMine(int dusMineId);
bool addToDeactivatedDusMine(int dusMineId, int bcIndex);
// QHash<mineId, broadcastIndexDeactivated>
QHash<int, int> m_deactivatedDusMine2bcIndex;
// QHash<broadcastIndexDeactivated, mineId>, keep sorted!
QMap<int, int> m_deactivatedBcIndex2DusMine;
std::shared_ptr<N_CoPrtCnv::CoPrtCnvRadioTelegram> createAccuTeleDeactivatedDusMines(int curBcIndex, int startBcIndex) const;
@@ -269,80 +398,165 @@ protected:
QSet<int> m_activatedDusMines;
std::shared_ptr<N_CoPrtCnv::CoPrtCnvRadioTelegram> createAccuTeleActivatedDusMines(int curBcIndex);
/**
* Removes the kennung from the sammeltelegram.
* If the sammeltelegram is empty after remove of kennung, it will be taken out of
* broadcast-map (but not deleted) and a_sammelTelRemoved will be true. A attached
* braodcast-only-telegram will be deattached and inserted into broadcast-map.
* Returns true if kennung was successful removed, otherwise the kennung was not
* found within sammeltelegram
*
* @param a_sammelTelegram
* @param a_kennung
* @param a_anzahlPos
* @param a_anzahlSize
* @param a_sammelTelRemoved
*/
bool removeFromSammeltelegram(const std::shared_ptr<N_CoPrtCnv::CoPrtCnvRadioTelegram> &a_sammelTelegram,
const uint16_t a_kennung,
const uint16_t a_anzahlPos,
const uint8_t a_anzahlSize,
bool &a_sammelTelRemoved);
/**
* used for telegrams that must only exists once in BC-list
*
* @param a_newRadioTelegram
*/
void replaceLastTelegramAndAddAtEnd(const std::shared_ptr<N_CoPrtCnv::CoPrtCnvRadioTelegram> &a_newRadioTelegram);
/**
* Small helper to dump all wf-ids from a sammeltelegramm
*/
std::string dumpSammeldeaktivierung(const N_CoPrtCnv::CoPrtCnvRadioTelegram *sammelTelegram);
/**
* Gets the braodcast-telegrams from Db, which were sent 1st time and adds them to
* the maps. Expired telegrams will be removed.
*
* @param a_doRestore
*/
void getAllFinishedBroadcastsFromDb(const bool a_doRestore = false);
/**
* Takes expired wirkfeld-telegrams out of maps.
*/
void removeExpiredTelegrams();
/**
* Removes the wirkfeld-telegrams with this kennung from the by time and by
* kennung maps.
* Replace this telegrams with Nop in BC-list.
* Finally the telegram will be deleted.
*
* @param a_kennung
*/
void removeWirkfeldTelegrams(const uint16_t a_kennung);
/**
* adds the wirkfeld-telegram to the by time and by kennung maps
*
* @param a_radioTelegram
* @param a_wirkfeldKennung
* @param a_telId
* @param a_minenKennung
*/
void addWirkfeldTelegram(const std::shared_ptr<N_CoPrtCnv::CoPrtCnvRadioTelegram> &a_radioTelegram,
const uint16_t a_wirkfeldKennung, const gef_telegramm_id_et a_telId = GEF_BESTAETIGUNG,
const uint16_t a_minenKennung = 0);
/**
* Deactivates the mine in the corresponding "WirkfeldstatusMinensperre"-telegram
* and moves the "WirkfeldstatusMinensperre"-telegram to the position of
* "DeactiviereEinzelmine"-telegram.
* Returns true if the "WirkfeldstatusMinensperre"-telegram was already sent 3
* times as normal broadcast.
*
* @param a_wirkfeldKennung
* @param a_minenKennung
* @param a_broadcastIndex
*/
bool deactivateEinzelmineFromMinensperre(const uint16_t a_wirkfeldKennung, const uint16_t a_minenKennung, const uint16_t a_broadcastIndex);
/**
* Returns a NOP-telegramm filled with the desired values.
*
* @param a_from
* @param a_to
*/
std::shared_ptr<N_CoPrtCnv::CoPrtCnvRadioTelegram> getNopTelegram(const uint16_t a_from, const uint16_t a_to);
/**
* Removes the telegram a_radioTelegram from all maps (broadcast-, wirkfeld-,
* funktionsraum- and lastTelegram-map).
* If the telegram is a attached BC-only-telegram, it will be detached.
* The telegram itself will be deleted when a_doDeleteTelegram is true.
* ATTENTION: iterators to all maps could be invalid after calling this function
*
* @param a_radioTelegram
* @param a_doDeleteTelegram
*/
void removeFromAllMaps(const std::shared_ptr<N_CoPrtCnv::CoPrtCnvRadioTelegram> &a_radioTelegram);
/**
* Detaches an existing radio-telegram and adds it to the broadcast-map
*
* @param a_radioTelegram The telegram which could contain an attached telegram
*/
void detachTelegram(const std::shared_ptr<N_CoPrtCnv::CoPrtCnvRadioTelegram> &a_radioTelegram);
/**
* Removes the telegram with a_funktionsraumKennung from funktionsraum-map and
* from the broadcast-map.
* If the telegram is a attached BC-only-telegram, it will be detached.
* The telegram itself will be deleted.
* ATTENTION: iterators to m_FunktionsraumTelegramMap could be invalid after
* calling this function
*
* @param a_funktionsraumKennung
*/
void removeFromFunktionsAndBroadcastMaps(const uint16_t a_funktionsraumKennung);
void removeFromTechnikFunktionsAndBroadcastMaps(const uint16_t a_funktionsraumKennung);
/**
* Removes the telegram where wirkfeldTelegramMapByKennungIterator points to from
* wirkfeld-maps and from the broadcast-map.
* If the telegram is a attached BC-only-telegram, it will be detached.
* The telegram itself will be deleted.
* ATTENTION: iterators to m_WirkfeldTelegramMapByKennung and
* m_WirkfeldTelegramMapByTime could be invalid after calling this function
*
* @param a_wirkfeldTelegramMapByKennungIterator
*/
void removeFromWirkfeldAndBroadcastMaps(const std::multimap<uint16_t, std::shared_ptr<N_CoPrtCnv::CoPrtCnvRadioTelegram>>::iterator &a_wirkfeldTelegramMapByKennungIterator);
/**
* Handles the REAKTIVIERUNG_DUS_MINE-telegram for normal-broadcasts and
* nachforderungen.
*
* @param a_radioTelegram The GEF_REAKTIVIERUNG_DUS_MINE-telegram
*/
void reactivateDusMine(const std::shared_ptr<N_CoPrtCnv::CoPrtCnvRadioTelegram> &a_radioTelegram);
/**
* Handles the DEAKTIVIERUNG_EINZELMINE-telegram for normal-broadcasts and
* nachforderungen. This includes deactivation of mines from minen-sperre and DUS-
* mines.
*
* @param a_radioTelegram The GEF_REAKTIVIERUNG_DUS_MINE-telegram
*/
void deactivateSingleMine(const std::shared_ptr<N_CoPrtCnv::CoPrtCnvRadioTelegram> &a_radioTelegram);
/**
* Prepares values for start sending nachforderungen
*/
void prepareForSendNachforderungen();
/**
* returns the next nachforderung to send and prepares collecting window if no
* more nachforderungen are to be sent
*/
std::shared_ptr<N_CoPrtCnv::CoPrtCnvRadioTelegram> evaluateNextNachforderungToSend();
Q_SIGNALS:
@@ -1,16 +1,16 @@
// **************************************************************************
//
// (C) Copyright 2009 Swiss SIMTEC AG
//
// **************************************************************************
//
// $HeadURL$
// $LastChangedBy$
// $LastChangedDate$
// $LastChangedRevision$
//
// Implementation of the Class PrtCnvCentralThread
// **************************************************************************
#include "PrtCnvCentralThread.hpp"
#include "PrtCnvRadioThread.hpp"
@@ -35,7 +35,7 @@
namespace PrtCnv
{
// ---------------------------------------------------------------
PrtCnvCentralThread::PrtCnvCentralThread(PrtCnv::PrtCnvThreadStarter* a_parent)
: PrtCnvThread(a_parent, "PrtCnvCentralThread")
, m_webSocket(nullptr)
@@ -66,9 +66,9 @@ PrtCnvCentralThread::~PrtCnvCentralThread()
destroy();
}
// ---------------------------------------------------------------
// Creates all subcomponents and connects signals to slots
// ---------------------------------------------------------------
int32_t PrtCnvCentralThread::create(NGL::Settings *settings)
{
PrtCnvThread::create(settings);
@@ -115,9 +115,9 @@ int32_t PrtCnvCentralThread::create(NGL::Settings *settings)
}
// ---------------------------------------------------------------
// Deallocates subcomponents.
// ---------------------------------------------------------------
int32_t PrtCnvCentralThread::destroy()
{
INFO_LOG(m_logger) << "Destroy";
@@ -129,9 +129,9 @@ int32_t PrtCnvCentralThread::destroy()
return 0;
}
// ---------------------------------------------------------------
// Initializes the variables.
// ---------------------------------------------------------------
int32_t PrtCnvCentralThread::init()
{
INFO_LOG(m_logger) << "Init";
@@ -143,7 +143,7 @@ int32_t PrtCnvCentralThread::init()
m_sendAckTimer->setInterval(m_Config->getInteger(getName(), QStringLiteral("AckTimeout"), 900));
m_VirtualTeilnehmerId = m_Config->getInteger(QStringLiteral("Common"), QStringLiteral("VirtualIdPrtCnv"), 90);
m_maxEqID = m_Config->getInteger(QStringLiteral("Common"), QStringLiteral("MaxEqID"), 50000);
m_maxEqID = m_Config->getInteger(QStringLiteral("Common"), QStringLiteral("MaxEqID"), 50000); //or max unsigned short 65535
return 0;
}
@@ -155,9 +155,9 @@ int32_t PrtCnvCentralThread::deinit()
return 0;
}
// ---------------------------------------------------------------
// Starts the thread and connects to TCP-server
// ---------------------------------------------------------------
int32_t PrtCnvCentralThread::start()
{
INFO_LOG(m_logger) << "Start";
@@ -176,9 +176,9 @@ int32_t PrtCnvCentralThread::start()
return 0;
}
// ---------------------------------------------------------------
// Stops the thread
// ---------------------------------------------------------------
int32_t PrtCnvCentralThread::stop()
{
INFO_LOG(m_logger) << "Stop";
@@ -188,31 +188,31 @@ int32_t PrtCnvCentralThread::stop()
}
// ---------------------------------------------------------------
// see base-class
// ---------------------------------------------------------------
void PrtCnvCentralThread::connected()
{
INFO_LOG(m_logger) << "Central-Socket connected m_Socket=" << m_webSocket;
m_SendCounter = 0;
m_SendCounter = 0; // we reset this counter after every connect to 0 => next telegram to send has counter 1 (preincrement)
m_LastSendCounter = 0;
m_ReceiveCounter = 0;
m_ReceiveCounter = 0; // send 0 until we get a telegram, we reset this counter after every connect to 0 => the next telegram from central must be 1
m_ReceiveAckCounter = 0;
m_aliveTimer->start();
if (m_bRadioThreadInitDone)
m_sendAckTimer->start();
m_State = PrtCnvSocketThread::e_WORKING;
emit checkSendToCentral();
emit checkSendToCentral(); // start sending telegrams for central still in list (reconnection)
}
// ---------------------------------------------------------------
// see base-class
// ---------------------------------------------------------------
void PrtCnvCentralThread::disconnected()
{
INFO_LOG(m_logger) << "disconnected m_Socket=" << m_webSocket;
// for the case central is disconnecting, we have to disconnect also, otherwise
// we could send rubish (still resisting in buffers) after a reconnection
if (PrtCnvSocketThread::e_WORKING == m_State && m_webSocket)
m_webSocket->close();
@@ -233,10 +233,10 @@ void PrtCnvCentralThread::disconnected()
}
// ---------------------------------------------------------------
// Stores that radio-thread has stopped. Cleans the Db and
// reinitializes when central-thread has also stopped.
// ---------------------------------------------------------------
void PrtCnvCentralThread::radioStopped()
{
m_RadioStopped = true;
@@ -245,25 +245,25 @@ void PrtCnvCentralThread::radioStopped()
}
// ---------------------------------------------------------------
// Calls clean of radio-thread and Db-thread and initializes
// the variables for rework.
// ---------------------------------------------------------------
void PrtCnvCentralThread::cleanAndReinit()
{
INFO_LOG(m_logger) << "cleanAndReinit";
emit cleanRadio();
// reinit mit sicherung und löschung der datenbestände
m_ReceiveAckCounter = 0;
m_DbThread->cleanAndInit();
m_DoCleanup = false;
}
// ---------------------------------------------------------------
// Starts radio-thread and itself for proceeding work after
// cleaning the Db.
// ---------------------------------------------------------------
void PrtCnvCentralThread::radioCleant()
{
if (!m_DoCleanup)
@@ -280,16 +280,16 @@ void PrtCnvCentralThread::radioCleant()
}
}
// ---------------------------------------------------------------
// see base-class
// ---------------------------------------------------------------
void PrtCnvCentralThread::onTextMessageReceived(const QString &msg)
{
// eat all pending readyReadyRead
if (m_DoCleanup)
return;
if (PrtCnvSocketThread::e_WORKING != m_State)
return;
return; // do nothing when we are not in working state
onDirectTextMessageReceived(msg.toUtf8());
}
@@ -298,7 +298,7 @@ void PrtCnvCentralThread::onDirectTextMessageReceived(const QByteArray &baJson)
try
{
if (baJson.isEmpty())
throw std::exception();
throw std::exception(); // FIXME: use own exception
const QJsonObject obj = QJsonDocument::fromJson(baJson).object();
const QJsonValue typeId = obj.value(QStringLiteral("typeId"));
@@ -311,16 +311,16 @@ void PrtCnvCentralThread::onDirectTextMessageReceived(const QByteArray &baJson)
m_aliveTimer->start();
// which kind of telegram is it?
if (telegram.telegramId() == TrainingAreaBase::TetraIcd::BESTAETIGUNG)
{
// it is an ack-telegram
handleAck(&telegram);
}
else
{
DEBUG_LOG(m_logger) << "Received telegram '" << baJson << "'";
// a payload-telegram
handleTelegram(&telegram);
}
}
@@ -328,7 +328,7 @@ void PrtCnvCentralThread::onDirectTextMessageReceived(const QByteArray &baJson)
{
ERROR_LOG(m_logger) << "JSon conversion error happenend. Error:"
<< e.what() << ", msg: " << baJson;
// inform central about the failure
TrainingAreaBase::TetraIcd::CtaDataError tele;
tele.header.equipmentNumber = m_VirtualTeilnehmerId;
tele.header.timeStamp = time(nullptr) * 1000LL;
@@ -339,21 +339,21 @@ void PrtCnvCentralThread::onDirectTextMessageReceived(const QByteArray &baJson)
}
}
// ---------------------------------------------------------------
void PrtCnvCentralThread::stateChanged(QAbstractSocket::SocketState newState)
{
INFO_LOG(m_logger) << "Websocket changed to state " << newState;
}
// ---------------------------------------------------------------
// Stores a telegram to be sent to radio in volatile radio-
// list and permanent in DB.
// ---------------------------------------------------------------
void PrtCnvCentralThread::handleTelegram(N_CoPrtCnv::CoPrtCnvCentralTelegram *a_telegram)
{
// => check with receive-counter if we lost a telegram or we get a telegram twice.
// => in this cases neither store the telegram nor send an ack (just ignore and read the next telegram)
// => the receive-counter will be hold on the last correct received telegram
DEBUG_LOG(m_logger) << "Receive Central-Telegram with telId=" << a_telegram->telegramId()
<< "; rcounter=" << a_telegram->counter();
if (checkAndUpdateReceiveCounter(a_telegram->counter()))
@@ -383,7 +383,7 @@ void PrtCnvCentralThread::handleTelegram(N_CoPrtCnv::CoPrtCnvCentralTelegram *a_
case AreaEffectSimulationType::GasPipeDetonation:
case AreaEffectSimulationType::SpecialArea:
case AreaEffectSimulationType::Unknown:
Q_ASSERT(false);
Q_ASSERT(false); // should not happen but who knows
break;
case AreaEffectSimulationType::BeStillWarning:
case AreaEffectSimulationType::DangerZoneExplosion:
@@ -400,7 +400,7 @@ void PrtCnvCentralThread::handleTelegram(N_CoPrtCnv::CoPrtCnvCentralTelegram *a_
bool bSomethingChanged = false;
for (int i = 0; i < msms.mineCount; ++i)
{
if (!LtsUtils::BitArray::testBit(msms.mineState, i))
if (!LtsUtils::BitArray::testBit(msms.mineState, i)) // 0 = triggered
{
INFO_LOG(m_logger) << "Testing bit " << i << " ... not set = triggered";
if (!oldTriggeredMines.contains(i))
@@ -419,7 +419,7 @@ void PrtCnvCentralThread::handleTelegram(N_CoPrtCnv::CoPrtCnvCentralTelegram *a_
return;
}
INFO_LOG(m_logger) << "MineState telegram contains new informations... " << msms.aesDdsId;
oldTriggeredMines = newTriggeredMines;
oldTriggeredMines = newTriggeredMines; // update in m_alreadyTriggeredMines[]
}
std::shared_ptr<N_CoPrtCnv::CoPrtCnvRadioTelegram>
@@ -427,7 +427,7 @@ void PrtCnvCentralThread::handleTelegram(N_CoPrtCnv::CoPrtCnvCentralTelegram *a_
if (radioTelegram)
{
if (radioTelegram->getIdentity() <= m_maxEqID) {
// save data in persistent database
m_DbThread->storeRadioTelegram(radioTelegram, a_telegram->counter());
} else {
WARNING_LOG(m_logger) << "Central telegram with telId=" << a_telegram->telegramId()
@@ -445,20 +445,20 @@ void PrtCnvCentralThread::handleTelegram(N_CoPrtCnv::CoPrtCnvCentralTelegram *a_
emit checkSendToRadio();
}
// ---------------------------------------------------------------
// The counter will be set to a_startCounter if a_maxCounter
// is reached
// returns true if receive-counter is ok
// returns false if a telegram is repeated or lost
// ---------------------------------------------------------------
bool PrtCnvCentralThread::checkAndUpdateReceiveCounter(const int32_t a_counter)
{
TRACE_LOG(m_logger) << "checkAndUpdateReceiveCounter: " << a_counter << ", " << m_ReceiveCounter;
// check for wrap
if (std::numeric_limits<int32_t>::max() == ++m_ReceiveCounter)
m_ReceiveCounter = 0;
// has the counter the expected value?
if (m_ReceiveCounter != a_counter)
{
if (m_ReceiveCounter > a_counter)
@@ -473,30 +473,43 @@ bool PrtCnvCentralThread::checkAndUpdateReceiveCounter(const int32_t a_counter)
}
#if 0
m_ReceiveCounter--;
return false;
return false; // failure
#else
m_ReceiveCounter = a_counter;
return true;
#endif
}
return true;
return true; // all ok
}
// ---------------------------------------------------------------
// used to send periodically an ack to central
// ---------------------------------------------------------------
void PrtCnvCentralThread::timeoutTick()
{
//NOTICE_LOG(m_logger) << "timeoutTick, " << m_DoCleanup << ", " << m_State;
if (m_DoCleanup)
return;
return; // eat all pending timeouts
if (PrtCnvSocketThread::e_WORKING != m_State)
return;
return; // do nothing when we are not in working state
/*
// Das bringt nur noch mehr Traffic wenn zskskp die gesendeten Daten
// nicht schnell genug abarbeiten kann - deshalb ersteinmal auskommentiert
// do we have to resend unacked telegrams
if (m_DbThread->resendCentralTelegrams(m_LastSendCounter))
{
emit checkSendToCentral(); // resend
}
else
{
// nothing has to be resent => update m_LastSendCounter
m_LastSendCounter = m_SendCounter;
}
*/
// do we have to inject a central-telegram?
try
{
N_CoPrtCnv::CoPrtCnvCentralTelegram *centralInjectTelegram;
@@ -512,13 +525,13 @@ void PrtCnvCentralThread::timeoutTick()
<< " => could not inject radio-telegram, but we proceed...";
}
// send the periodically ack-telegram to central
sendAck();
}
// ---------------------------------------------------------------
// see base-class
// ---------------------------------------------------------------
void PrtCnvCentralThread::timeoutAliveAndConnection()
{
INFO_LOG(m_logger) << "timeoutAliveAndConnection socketState="
@@ -543,16 +556,16 @@ void PrtCnvCentralThread::timeoutAliveAndConnection()
}
}
// ---------------------------------------------------------------
// Sends a ack-telegram to central.
// ---------------------------------------------------------------
void PrtCnvCentralThread::sendAck()
{
TrainingAreaBase::TetraIcd::Acknowledge ack;
ack.timeStamp = time(nullptr) * 1000;
ack.ackCounter = m_ReceiveAckCounter;
N_CoPrtCnv::CoPrtCnvCentralTelegram tele(ack);
// send to socket
if (m_webSocket)
m_webSocket->sendTextMessage(QString::fromUtf8(tele.data()));
else
@@ -562,10 +575,10 @@ void PrtCnvCentralThread::sendAck()
}
// ---------------------------------------------------------------
// Sends a central-telegram to socket or file, depending on
// configuration. Before sending, the send-counter will be set.
// ---------------------------------------------------------------
void PrtCnvCentralThread::sendTelegram(N_CoPrtCnv::CoPrtCnvCentralTelegram *a_telegram)
{
PrtCnvStoredCentralTelegram *handle = nullptr;
@@ -573,11 +586,11 @@ void PrtCnvCentralThread::sendTelegram(N_CoPrtCnv::CoPrtCnvCentralTelegram *a_te
}
// ---------------------------------------------------------------
// Sends a central-telegram to socket or file, depending on
// configuration. Before sending, the send-counter will be set.
// After sending the Db will be updated.
// ---------------------------------------------------------------
void PrtCnvCentralThread::sendTelegram(N_CoPrtCnv::CoPrtCnvCentralTelegram *a_telegram,
PrtCnvStoredCentralTelegram *a_handle)
{
@@ -585,43 +598,43 @@ void PrtCnvCentralThread::sendTelegram(N_CoPrtCnv::CoPrtCnvCentralTelegram *a_te
if (a_telegram->telegramId() == TelegramId::DEAKTIVIERUNG_EINZELMINE)
{
const MineTriggered tele(MineTriggered::fromJson(a_telegram->jsonData()));
m_alreadyTriggeredMines[tele.mineAreaId].insert(tele.mineIndex - 1);
m_alreadyTriggeredMines[tele.mineAreaId].insert(tele.mineIndex - 1); // starts at 1 ...
INFO_LOG(m_logger) << "Adding triggered mine with id " << tele.mineIndex << " to area id " << tele.mineAreaId;
}
// set the counter, but keep old counter if we resend the telegram
const int writeCounter = a_handle ? a_handle->writeCounter() : 0;
if (writeCounter != 0)
a_telegram->setCounter(writeCounter);
else
a_telegram->setCounter(++m_SendCounter);
// send telegram to central
DEBUG_LOG(m_logger) << "Send telegram to central: telId=" << a_telegram->telegramId()
<< " wcounter=" << a_telegram->counter();
// send to socket
if (m_webSocket)
m_webSocket->sendTextMessage(QString::fromUtf8(a_telegram->data()));
else
emit directTextMessage(a_telegram->data());
// mark in Db telegram as sent
if (a_handle)
m_DbThread->centralTelegramSent(a_telegram->counter(), a_handle);
m_LogThread->writeCentralTelegramLog(a_telegram, true, 1);
}
// ---------------------------------------------------------------
// Processes the telegram
// AnforderungStatistikBroadcastNachforderugen. The function
// fills the answer telegram StatistikBroadNachforderungen
// with the actual statistic.
// ---------------------------------------------------------------
void PrtCnvCentralThread::handleAnforderungStatistikBroadcastNachforderungen()
{
const auto nachforderungsStat = m_DbThread->getClaimStatistics();
// inform central about the failure
TrainingAreaBase::TetraIcd::BroadcastStatistics tele;
tele.header.equipmentNumber = m_VirtualTeilnehmerId;
tele.header.timeStamp = time(nullptr) * 1000LL;
@@ -638,14 +651,14 @@ void PrtCnvCentralThread::handleAnforderungStatistikBroadcastNachforderungen()
sendTelegram(&telegram);
}
// ---------------------------------------------------------------
// Checks whether a telegram must be sent and sends it.
// ---------------------------------------------------------------
void PrtCnvCentralThread::checkSend()
{
// eat all pending checkSend-signals, if we have to cleanup
if (m_DoCleanup) return;
if (PrtCnvSocketThread::e_WORKING != m_State) return;
if (PrtCnvSocketThread::e_WORKING != m_State) return; // do nothing when we are not in working state
PrtCnvStoredCentralTelegram *handle = nullptr;
auto *centralTelegram = m_DbThread->getNextCentralTelegram(handle);
if (centralTelegram)
@@ -656,26 +669,26 @@ void PrtCnvCentralThread::checkSend()
}
}
// ---------------------------------------------------------------
// Removes telegrams from ToCentral-table, if the central
// acknowledges their reception
// ---------------------------------------------------------------
void PrtCnvCentralThread::handleAck(N_CoPrtCnv::CoPrtCnvCentralTelegram *a_telegram)
{
TrainingAreaBase::TetraIcd::Acknowledge ack(TrainingAreaBase::TetraIcd::Acknowledge::fromJson(a_telegram->jsonData()));
// INFO_LOG(m_logger) << "Got Central-Ack with wcounter=" << a_ackTelegram.zaehler();
m_DbThread->ackCentralTelegrams(ack.ackCounter);
}
// ---------------------------------------------------------------
// Will be called from Db-thread when telegrams were stored
// permanent. This function will then send the ack to central
// (socket-based) or delete the telegramfiles (file-based)
// ---------------------------------------------------------------
void PrtCnvCentralThread::permanentStored(int32_t a_centralCounter)
{
if (m_DoCleanup) return;
if (PrtCnvSocketThread::e_WORKING != m_State) return;
if (m_DoCleanup) return; // eat all pending permanentStored
if (PrtCnvSocketThread::e_WORKING != m_State) return; // do nothing when we are not in working state
DEBUG_LOG(m_logger) << "got permanentStored a_centralCounter=" << a_centralCounter;
if (0 != a_centralCounter && a_centralCounter > m_ReceiveAckCounter)
{
@@ -732,10 +745,10 @@ void PrtCnvCentralThread::onRadioThreadInitDone()
m_sendAckTimer->start();
}
// ---------------------------------------------------------------
// returns true if telegram should be converted, stored and
// sent to radio
// ---------------------------------------------------------------
bool PrtCnvCentralThread::handleSpecialTelegram(N_CoPrtCnv::CoPrtCnvCentralTelegram *a_telegram)
{
using namespace TrainingAreaBase::TetraIcd;
@@ -750,17 +763,17 @@ bool PrtCnvCentralThread::handleSpecialTelegram(N_CoPrtCnv::CoPrtCnvCentralTeleg
case ExerciseStateData::ExerciseState::Terminated:
{
INFO_LOG(m_logger) << "Got Betriebszustandsmeldung Uebung_Aufraeumen => disconnect, cleanup and reconnect";
m_DbThread->setMachineState(1);
m_DbThread->setMachineState(1); // store permanent that we cleanup now, so we will proceed cleanup, after a crash
// send ack before disconnecting
permanentStored(a_telegram->counter());
m_DoCleanup = true;
m_CentralStopped = false;
m_RadioStopped = false;
// INFO_LOG(m_logger) << "stop timer";
m_sendAckTimer->stop();
m_DbThread->waitUntilDbWritten();
disconnectSocket();
m_RadioThread->prepareCleanUp();
m_RadioThread->prepareCleanUp(); // this makes empty the message-queue of radio-thread faster
emit stopRadio();
m_reconnectTimer->start();
break;
@@ -779,7 +792,7 @@ bool PrtCnvCentralThread::handleSpecialTelegram(N_CoPrtCnv::CoPrtCnvCentralTeleg
return false;
}
case Constraints<RequestBroadcastStatistics>::id():
// here we must not use sendAck(), because it could be that we ack central-telegrams which are not yet stored permanent
m_DbThread->centralCounterReadyForAck(a_telegram->counter());
handleAnforderungStatistikBroadcastNachforderungen();
return false;
@@ -796,7 +809,7 @@ bool PrtCnvCentralThread::handleSpecialTelegram(N_CoPrtCnv::CoPrtCnvCentralTeleg
return true;
}
// ---------------------------------------------------------------
void PrtCnvCentralThread::connectSocket()
{
const QString host = m_Config->getString(getName(), QStringLiteral("HostName"), QStringLiteral("EXCTDS01"));
@@ -827,7 +840,7 @@ void PrtCnvCentralThread::connectSocket()
m_State = PrtCnvSocketThread::e_CONNECTING;
}
// ---------------------------------------------------------------
void PrtCnvCentralThread::disconnectSocket()
{
m_State = PrtCnvSocketThread::e_INITIAL;
@@ -841,4 +854,4 @@ void PrtCnvCentralThread::disconnectSocket()
m_webSocket = nullptr;
}
}
} // namespace PrtCnv
@@ -1,16 +1,16 @@
// **************************************************************************
//
// (C) Copyright 2009 Swiss SIMTEC AG
//
// **************************************************************************
//
// $HeadURL$
// $LastChangedBy$
// $LastChangedDate$
// $LastChangedRevision$
//
// Implementation of the Class PrtCnvCentralThread
// **************************************************************************
#pragma once
@@ -27,8 +27,15 @@ namespace PrtCnv
{
class PrtCnvRadioThread;
class PrtCnvThreadStarter;
/**
* This class handles the protocoll to central. This includes:
* - connection with files instead sockets (configurable)
* - send and receive telegrams
*
* @author
* @version 1.0
* @created 05-Jan-2006 13:34:28
*/
class PrtCnvCentralThread : public PrtCnv::PrtCnvThread
{
Q_OBJECT
@@ -37,199 +44,270 @@ private:
public:
/**
* @author wia
* @version 1.0
* @updated 02-Jul-2009 14:32:58
*/
~PrtCnvCentralThread();
/**
* @param a_parent The pointer to the starter-thread
*/
explicit PrtCnvCentralThread(PrtCnvThreadStarter* a_parent);
/**
* Creates all subcomponents and connects signals to slots
*/
int32_t create(NGL::Settings *settings) override;
int32_t deinit() override;
/**
* Deallocates subcomponents.
*/
int32_t destroy() override;
/**
* Initializes the variables.
*/
int32_t init() override;
/**
* Starts the thread and connects to TCP-server
*/
int32_t start() override;
/**
* Stops the thread
*/
int32_t stop() override;
// for direct communication
void onDirectTextMessageReceived(const QByteArray &baJson);
signals:
// for direct communication
void directTextMessage(const QByteArray &baJson);
/**
* Signal to start sending a telegram to central
*/
void checkSendToCentral();
/**
* Signal to start sending a telegram to radio
*/
void checkSendToRadio();
/**
* Signal to stop radio
*/
void stopRadio();
/**
* Signal to start cleaning-process of radio-thread
*/
void cleanRadio();
/**
* Signal to restart work of radio-thread
*/
void startRadio();
protected:
/**
* For reading/writing json telegrams to socket
*/
QWebSocket *m_webSocket;
/**
* The send-counter (only for sockets)
*/
int32_t m_SendCounter;
public slots:
/**
* Checks whether a telegram must be sent and sends it.
*/
void checkSend();
/**
* Stores that radio-thread has stopped. Cleans the Db and reinitializes when
* central-thread has also stopped.
*/
void radioStopped();
/**
* Starts radio-thread and itself for proceeding work after cleaning the Db.
*/
void radioCleant();
/**
* Will be called from Db-thread when telegrams were stored permanent. This
* function will then send the ack to central (socket-based) or delete the
* telegramfiles (file-based)
*
* @param a_centralCounter
*/
void permanentStored(int32_t a_centralCounter);
// called from Radio thread to indicate current connection state
void onTetraConnectionState(bool bConnected);
// called from Radio thread to indicate the license state of an equipment
void onPlayerLicencedChanged(int equipNo, N_CoPrtCnv::E_LicensingKind kind);
protected slots:
// an effect siumlation was (de)activated
void onAreaEffectSimulationDeactivated(int wirkfeldKennung);
void onAreaEffectSimulationActivated(int wirkfeldKennung);
// radio thread completely initialized
void onRadioThreadInitDone();
/**
* called when websocket is connected
*/
void connected();
/**
* called when websocket is disconnected
*/
void disconnected();
/**
* used to send periodically an ack to central
*/
void timeoutTick();
/**
* see base-class
*/
void timeoutAliveAndConnection();
void onTextMessageReceived(const QString &msg);
void stateChanged(QAbstractSocket::SocketState newState);
protected:
/**
* Sends a ack-telegram to central.
*/
void sendAck();
/**
* Stores a telegram to be sent to radio in volatile radio-list and permanent in
* DB.
*
* @param a_telegram
*/
void handleTelegram(N_CoPrtCnv::CoPrtCnvCentralTelegram *a_telegram);
bool checkAndUpdateReceiveCounter(const int32_t a_counter);
/**
* Sends a central-telegram to socket or file, depending on configuration. Before
* sending, the send-counter will be set. After sending the Db will be updated.
*
* @param a_telegram The central-telegram to be sent.
* @param a_handle The handle assigned to telegram to be sent, we got from Db.
*/
void sendTelegram(N_CoPrtCnv::CoPrtCnvCentralTelegram *a_telegram,
PrtCnvStoredCentralTelegram *a_handle);
/**
* Processes the telegram AnforderungStatistikBroadcastNachforderugen. The
* function fills the answer telegram StatistikBroadNachforderungen with the
* actual statistic.
*
* @param a_umgMldTelegram
*/
void handleAnforderungStatistikBroadcastNachforderungen();
/**
* Removes telegrams from ToCentral-table, if the central acknowledges their
* reception
*
* @param a_ackTelegram
*/
void handleAck(N_CoPrtCnv::CoPrtCnvCentralTelegram *a_telegram);
/**
* Calls clean of radio-thread and Db-thread and initializes the variables for
* rework.
*/
void cleanAndReinit();
/**
* returns true if telegram should be converted, stored and sent to radio
*
* @param a_telegram
*/
bool handleSpecialTelegram(N_CoPrtCnv::CoPrtCnvCentralTelegram *a_telegram);
/**
* Sends a central-telegram to socket or file, depending on configuration. Before
* sending, the send-counter will be set.
*
* @param a_telegram The central-telegram to be sent.
*/
void sendTelegram(N_CoPrtCnv::CoPrtCnvCentralTelegram *a_telegram);
/**
* Connect as client to a TCP-server on ip-address configured as HostName and Port
* configured as Port
*/
void connectSocket();
/**
* Disconnects from TCP-server
*/
void disconnectSocket();
protected:
/**
* used for periodically send an ack to central
*/
PrtCnvRadioThread *m_RadioThread;
/**
* True if radio has stopped work
*/
bool m_RadioStopped;
/**
* True if central has stopped work
*/
bool m_CentralStopped;
/**
* Used for resending unacked telegrams
*/
int32_t m_LastSendCounter;
/**
* The (virtual) identify of the protocol-converter
*/
uint16_t m_VirtualTeilnehmerId;
/**
* The maximum equipment-ID for tetra - all telegrams with an higher ID will
* be silently ignored
*/
uint16_t m_maxEqID;
// timer to reconnect when no ack from central is coming anymore
QTimer *m_aliveTimer;
// timer to send ack to central
QTimer *m_sendAckTimer;
// timer to reconnect to central
QTimer *m_reconnectTimer;
/**
* True if the database has to be cleant up (used for fast empty of signal buffers)
*/
QAtomicInt m_DoCleanup;
PrtCnvDbThread *m_DbThread;
// log telegrams in file
PrtCnvTelegramLogThread *m_LogThread;
// get injected telegrams
PrtCnvInjectionThread *m_InjectionThread;
/**
* Counter of received telegrams (only for sockets)
*/
int32_t m_ReceiveCounter;
/**
* Acknowledged telegrams counter (only for sockets)
*/
int32_t m_ReceiveAckCounter;
/**
* The state-event-machine state
*/
PrtCnvSocketThread::E_State m_State;
// set with all already deactivated effect simulations to not send deactivate telegram twice
QSet<int> m_deactivatedAreaEffectSimulations;
// multimap with all mine areas and it's already triggered mines
QHash<int, QSet<int>> m_alreadyTriggeredMines;
// true when we don't use socket but direct connections (through onDirectTextMessageReceived)
bool m_bDirectConnection;
bool m_bRadioThreadInitDone;
File diff suppressed because it is too large. Load diff
@@ -1,16 +1,16 @@
// **************************************************************************
//
// (C) Copyright 2009 Swiss SIMTEC AG
//
// **************************************************************************
//
// $HeadURL$
// $LastChangedBy$
// $LastChangedDate$
// $LastChangedRevision$
//
// Implementation of the Class PrtCnvDbThread
// **************************************************************************
#pragma once
@@ -37,15 +37,28 @@ namespace PrtCnv
class PrtCnvStoredCentralTelegram;
class PrtCnvStoredRadioTelegram;
class PrtCnvMember;
/**
* Handles all data which must be stored permanent:
* - central-telegrams
* - radio-telegrams
* - radio-members (TNE)
* - reset-counter
* - states
*
* @author wia
* @version 1.0
* @created 28-Jul-2009 16:08:53
*/
class PrtCnvDbThread : public PrtCnvThread
{
Q_OBJECT
public:
/**
* Constructor with thread-starter as argument
*
* @param a_parent
*/
PrtCnvDbThread(const QString &dbDriver,
const QString &dbHostName,
const QString &dbDatabaseName,
@@ -55,161 +68,287 @@ namespace PrtCnv
PrtCnvThreadStarter* a_parent);
~PrtCnvDbThread();
/**
* starts this thread and its childs
*/
int32_t start() override;
/**
* stops this thread and its childs
*/
int32_t stop() override;
/**
* creates this thread and its childs
*/
int32_t create(NGL::Settings *settings) override;
/**
* initializes this thread and its childs
*/
int32_t init() override;
/**
* Indicates the Db, which telegrams were successful received by central. This
* will delete this telegrams from Db.
*
* @param a_counter
*/
void ackCentralTelegrams(int32_t a_counter);
/**
* returns the next telegram to send to central.
* returns NULL if no telegram found.
* ATTENTION: The caller is responsible to deallocate the returned
* centralTelegram!
*
* @param a_handle
*/
N_CoPrtCnv::CoPrtCnvCentralTelegram *getNextCentralTelegram(PrtCnvStoredCentralTelegram *& a_handle);
/**
* Marks the central-telegram as to be sent
*
* @param a_counter The counter the telegram has while sent
* @param a_handle The telegram-handle gotten from getNextCentralTelegram()
*/
void centralTelegramSent(const int32_t a_counter, PrtCnvStoredCentralTelegram *a_handle);
/**
* Updates the counter for unsuccessful sending the telegram. If a maximal value
* of this counter is reached, the central-telegram will be deleted.
* a_handle could be deleted after calling this function!
* This function could block some milliseconds, because it must wait until all
* changes are written to DB.
*
* @param a_handle The telegram-handle gotten from getNextCentralTelegram()
*/
void centralTelegramCouldNotBeSent(PrtCnvStoredCentralTelegram *a_handle);
/**
* Marks the radio-telegram as to be sent
*
* @param a_sendCounter
* @param a_handle
* @param a_broadcastIndex
*/
void radioTelegramSent(const uint32_t a_sendCounter, PrtCnvStoredRadioTelegram *a_handle, const uint32_t a_broadcastIndex);
/**
* returns the next telegram to send to radio, respecting the priority.
* returns NULL if no radio-telegram found.
*
* @param a_handle
*/
std::shared_ptr<N_CoPrtCnv::CoPrtCnvRadioTelegram> getNextRadioTelegram(PrtCnvStoredRadioTelegram *&a_handle);
/**
* returns the next broadcast-telegram from list.
* Deletes the telegram from this list.
* returns NULL if list empty.
*/
std::shared_ptr<N_CoPrtCnv::CoPrtCnvRadioTelegram> getNextBroadcastTelegram();
/**
* stores the telegram to be sent to central in working-list and also in Db.
* Because storing data in XDR_Wrapper_it-format is complicated (has pointer to
* data), we store them in the radio-telegram-format).
* Attention: Be aware that centralTelegram and radioTelegram contain the same
* data.
* The DbThread takes control over centralTelegram and radioTelegram and deletes
* them when no longer needed.
*
* @param a_centralTelegram
* @param a_radioTelegram Must be the same telegram like the central-telegram
* (used for storing the telegram in Db)
*/
void storeCentralTelegram(const std::shared_ptr<N_CoPrtCnv::CoPrtCnvCentralTelegram> &a_centralTelegram,
const N_CoPrtCnv::CoPrtCnvRadioTelegram &a_radioTelegram);
/**
* Stores the telegram to be sent to radio in working-list and also in Db.
* The DbThread takes control over a_telegram and deletes it when no longer needed.
*
*
* @param a_telegram
* @param a_readCounter
*/
void storeRadioTelegram(const std::shared_ptr<N_CoPrtCnv::CoPrtCnvRadioTelegram> &a_telegram, const int32_t a_readCounter);
/**
* This function causes acking a central-telegram, which must not be stored
* permanent in Db, because it will be handled immediately (i.e.
* AnforderungStatistikBroadcastNachforderungen).
*
* @param a_centralCounter The read-counter of the central-telegram
*/
void centralCounterReadyForAck(const int32_t a_centralCounter);
/**
* Adds an sql-command in the sql-command-list. On next iteration of
* storePermanent() all command in list will be executed.
*
* @param a_sqlCommand
*/
void addSqlCommand(const QString &sql);
/**
* erases and initializes the database
*/
void cleanAndInit();
/**
* Checks whether central-telegrams have to be resent. If yes, all actions will be
* done, that getNextCentralTelegram() delivers the telegram(s) to be resent.
* Returns true if there must telegrams be resent.
*
* @param a_lastSendCounter The counter of the telegram we expect a ack-
* telegram has been received
*/
bool resendCentralTelegrams(const int32_t a_lastSendCounter);
/**
* Prepares the telegrams not yet acked from central for reconnection. This will
* be done by setting the write-counter to 0.
*/
void prepareCentralTelegramsForReconnection();
/**
* Blocks until all SQL-commands were written to DB.
*/
void waitUntilDbWritten();
/**
* returns NULL if no member found
*
* @param a_ISSI
*/
PrtCnvMember* getMemberByISSI(const uint32_t a_ISSI) const;
/**
* returns NULL if member not found
*
* @param a_id
*/
PrtCnvMember* getMemberById(const uint16_t a_id);
/**
* Licenses the member
*
* @param a_member
* @param a_doLicense
*/
bool licenseMember(PrtCnvMember *a_member, const bool a_doLicense = true);
/**
* Updates the current exercise for this member
*/
void updateExerciseIdForMember(PrtCnvMember *a_member, int newExerciseId);
/**
* adds a member in the 2 maps, sorted by id and ISSI
* returns the new member
*
* @param a_identity
* @param a_ISSI
*/
PrtCnvMember* addMember(const int a_identity, const int a_ISSI);
/**
* removes the member in the 2 maps, sorted by id and ISSI
*
* @param a_member
*/
void removeMember(PrtCnvMember* a_member);
/**
* Returns the actual reset-counter
*/
uint8_t getResetCounter() const;
/**
* Sets the actual reset-counter
*
* @param newVal
*/
void setResetCounter(uint8_t newVal);
/**
* The actual 'Betriebszustaende Gefechtsfeld' which will be sent to TNEs
* periodically
*/
uint8_t getBattleFieldOperatingState() const;
/**
* Sets or unsets pause, depending on a_doSet.
* (Bit 0 in UMGEBUNGS_MELDUNG(2))
* @param a_doSet
*/
void setPause(const bool a_doSet = true);
/**
* Set the inhibit time for position telegrams (1 .. 31 Seconds)
* (Bit 1-5 in UMGEBUNGS_MELDUNG(2))
* @param a_doSet
*/
void setPositionSendTime(unsigned int sendTime);
/**
* Set the current air load to be sent with the Umgebungsmeldung
* (Bit 6-7 in UMGEBUNGS_MELDUNG(2))
* @param airLoad The current air-load received from Tetra
*/
void setAirLoad(PrtCnvRadioThread::E_TrafficLoad airLoad);
/**
* Returns true if the resetCounter itself is different than the reset-counter of
* the environment-telegram
*/
bool isEnvironmentResetCounterOld() const;
/**
* Returns the actual Umgebungsmeldung
*/
std::shared_ptr<N_CoPrtCnv::CoPrtCnvRadioTelegram> getEnvironmentTelegram();
/**
* Sets the resetcounter of the environment-telegram to the actual reset-counter.
*/
void setResetCounterOnEnvironment();
/**
* Increments the counter for nachforderungen of the TNE with id a_identity.
*
* @param a_identity The identity of the TNE, which asked for nachforderung
*/
void incClaimCount(int a_identity);
/**
* Fills the map with nachforderungsstatistic.
* Returns the number of elements in map.
*
* @param a_statisticMap this map will be filled with pairs of
* ausstattungsnummer and amount of nachforderungen
*/
std::map<int32_t, int32_t> getClaimStatistics() const;
/**
* Sets the actual machine-state permanent, used to proceed cleaning db after a
* crash.
*
* @param a_newMachineState The new machine-state. 0 => working; 1 => cleaning
* DB
*/
void setMachineState(const int a_newMachineState);
/**
* Returns true if protocol-converter was crashed while cleanup DB.
*/
bool mustProceedCleanup() const;
protected:
void closeDb();
/**
* List of telegrams to be sent to central
*/
std::vector<PrtCnvStoredCentralTelegram*> m_CentralList;
@@ -224,18 +363,23 @@ namespace PrtCnv
mutable QRecursiveMutex m_CentralListMutex;
/**
* The permanent DB
*/
QSqlDatabase m_db;
/**
* The last counter received from central as ack. Used for deleting no longer used
* central-telegrams and for resending of central-telegrams.
*/
QAtomicInt m_CentralAckCounter;
/**
* Used for optimizing deletion of no longer needed central-telegrams.
*/
unsigned int m_OldCentralAckCounter;
/**
* List of telegrams to be sent to radio
*/
std::list<PrtCnvStoredRadioTelegram*> m_RadioList;
@@ -252,77 +396,104 @@ namespace PrtCnv
std::list<PrtCnvStoredRadioTelegram*> m_BroadcastList;
/**
* Used to wait until cleaning is finished and to suppress storing data within
* database while cleaning
*/
bool m_DoClean;
/**
* Used for waiting data written to DB
*/
bool m_DoWaitUntilSqlWritten;
/**
* Holds all logged in members ordered by Id.
*/
std::unordered_map<int,PrtCnvMember*> m_MemberListById;
/**
* Holds all logged in members ordered by ISSI
*/
std::unordered_map<int,PrtCnvMember*> m_MemberListByISSI;
/**
* Used to prevent data storing within DB while restoring after crash
*/
bool m_DoStorePermanent;
/**
* the actual reset-counter
*/
uint8_t m_ResetCounter;
/**
* The actual 'Betriebszustaende Gefechtsfeld' which will be sent to TNEs
* periodically
*/
uint8_t m_BattleFieldOperatingState;
/**
* The actual telegram "Umgebungsmeldung"
*/
PrtCnvStoredRadioTelegram* m_EnvironmentTelegram;
/**
* True if cleanup has to be proceed after crash.
*/
bool m_DoProceedCleanup;
/**
* Used to optimize send the signal permanentStored
*/
int32_t m_OldCentralCounter;
/**
* For ensure that not too much storePermanent-signals will be queued
*/
QBasicAtomicInt m_StorePermanentPending;
/**
* nbr of unsuccessful send-attempts, before telegram will be deleted without
* sending it
*/
uint32_t m_NbrOfAttempts;
/**
* creates or restores the permanent database
*/
bool createDatabase();
/**
* Sends a signal storePermanent if not already such a signal is pending
*/
void sendStorePermanentSignal();
/**
* Helper for storePermanent()
*/
void storeCentralTelegrams();
/**
* Helper for storePermanent()
*/
int32_t storeRadioTelegrams();
/**
* Helper for storePermanent()
*/
void handleSqlCommandList();
/**
* Delete all telegrams with the ids in telegramsToDelete
* from a given table
*/
void deleteTelegramsFromDbById(const QString &table);
/**
* Update the write counter for the telegrams in
* telegramsToUpdateCounter for the given table
*/
void updateTelegramsWriteCounter(const QString &table);
/**
* Update the broadcast counter for the telegrams in
* telegramsToUpdateCounter for the given table
*/
void updateTelegramsBroadcast(const QString &table);
/**
* Reinitialize the database
*/
void reinitDatabase();
QString toCentralTableName() const { return tableName(QStringLiteral("prtcnv_to_central")); }
@@ -332,31 +503,39 @@ namespace PrtCnv
QString versionTableName() const { return tableName(QStringLiteral("prtcnv_version")); }
QString tableName(const QString &table) const { return m_dbSchemaName.isEmpty() ? table : m_dbSchemaName + QLatin1Char('.') + table; }
protected slots:
/**
* Stores the radio-telegrams, central-telegrams in Db and executes the sql-
* command-list.
*/
void storePermanent();
/**
* cleans up this thread and its childs
*/
void clean();
public:
signals:
/**
* Signal to call storePermanent()
*/
void doStorePermanent();
/**
* Signal to inform central-thread about stored telegrams
*
* @param a_centralCounter
*/
void permanentStored(int32_t a_centralCounter);
/**
* a signal to erase the permanent database
*/
void doClean();
void playerLicencedChanged(int equipNo, N_CoPrtCnv::E_LicensingKind kind);
private:
// local caches to memory (re)allocation all the time
// note: std::vector.clear() does not release memory and therefore
// a reallocation in the next turn is not neccessary
std::vector<int64_t> m_telegramsToDelete;
std::vector<std::pair<int64_t, int32_t> > m_telegramsToUpdateCounter;
std::vector<std::pair<int64_t, int32_t> > m_telegramsToUpdateBC;
@@ -1,17 +1,17 @@
// **************************************************************************
//
// (C) Copyright 2009 Swiss SIMTEC AG
//
// **************************************************************************
//
// $HeadURL$
// $LastChangedBy$
// $LastChangedDate$
// $LastChangedRevision$
//
// **************************************************************************
// manual class headers
#include "PrtCnvInjectionSocket.hpp"
#include <CoPrtCnv/CoPrtCnvInjectionHeader.hpp>
#include <CoPrtCnv/CoPrtCnvCentralTelegram.hpp>
@@ -33,9 +33,9 @@ PrtCnvInjectionSocket::~PrtCnvInjectionSocket()
delete m_Socket;
}
// ---------------------------------------------------------------
// Disconnects a TCP-client
// ---------------------------------------------------------------
void PrtCnvInjectionSocket::disconnectClient()
{
INFO_LOG(m_logger) << "A client has disconnected from the injection-server";
@@ -43,9 +43,9 @@ void PrtCnvInjectionSocket::disconnectClient()
}
// ---------------------------------------------------------------
// Reads in TCP-data and handles them
// ---------------------------------------------------------------
void PrtCnvInjectionSocket::processInputData()
{
INFO_LOG(m_logger) << "Injection-server has data received";
@@ -55,7 +55,7 @@ void PrtCnvInjectionSocket::processInputData()
{
if (injectionHeader.isIdCorrect())
{
// check whether all bytes are available
qint64 available = m_Socket->bytesAvailable();
if (available < qint64(injectionHeader.m_Size + sizeof(injectionHeader)))
{
@@ -64,15 +64,15 @@ void PrtCnvInjectionSocket::processInputData()
<< injectionHeader.m_Id1 << " id2=" << injectionHeader.m_Id2
<< " kind=" << (int)injectionHeader.m_Kind << " size="
<< injectionHeader.m_Size;
return;
return; // try it later, when (maybe) enough bytes are available...
}
// enough bytes => read now all in
m_Socket->read((char*)&injectionHeader, sizeof(injectionHeader));
if (injectionHeader.isIdCorrect())
{
//INFO_LOG(m_logger) << "kind=" << (int)injectionHeader.m_Kind << " size=" << injectionHeader.m_Size;
// read the data
QByteArray data(injectionHeader.m_Size, Qt::Uninitialized);
m_Socket->read(data.data(), injectionHeader.m_Size);
@@ -111,7 +111,7 @@ void PrtCnvInjectionSocket::processInputData()
}
}
// ---------------------------------------------------------------
void PrtCnvInjectionSocket::setSocket(QTcpSocket* a_socket, PrtCnvInjectionThread* a_server)
{
m_Socket = a_socket;
@@ -124,4 +124,4 @@ void PrtCnvInjectionSocket::setSocket(QTcpSocket* a_socket, PrtCnvInjectionThrea
}
}
}
} // namespace PrtCnv
@@ -1,15 +1,15 @@
// **************************************************************************
//
// (C) Copyright 2009 Swiss SIMTEC AG
//
// **************************************************************************
//
// $HeadURL$
// $LastChangedBy$
// $LastChangedDate$
// $LastChangedRevision$
//
// **************************************************************************
#pragma once
@@ -21,8 +21,13 @@ class QTcpSocket;
namespace PrtCnv
{
class PrtCnvInjectionThread;
/**
* Used for receiving the socket signals
*
* @author alois.wismer
* @version 1.0
* @created 06-Aug-2010 16:41:44
*/
class PrtCnvInjectionSocket : public QObject
{
Q_OBJECT
@@ -31,8 +36,11 @@ namespace PrtCnv
PrtCnvInjectionSocket();
~PrtCnvInjectionSocket();
/**
*
* @param a_socket
* @param a_server
*/
void setSocket(QTcpSocket* a_socket, PrtCnvInjectionThread* a_server);
protected:
@@ -42,19 +50,23 @@ namespace PrtCnv
NGL::INGLLogger &m_logger;
protected slots:
/**
* Disconnects a TCP-client
*/
void disconnectClient();
/**
* Reads in TCP-data and handles them
*/
void processInputData();
public:
signals:
/**
*
* @param a_injectSocket
*/
void disconnected(PrtCnvInjectionSocket* a_injectSocket);
@@ -1,17 +1,17 @@
// **************************************************************************
//
// (C) Copyright 2009 Swiss SIMTEC AG
//
// **************************************************************************
//
// $HeadURL$
// $LastChangedBy$
// $LastChangedDate$
// $LastChangedRevision$
//
// **************************************************************************
// manual class headers
#include "PrtCnvInjectionThread.hpp"
#include "PrtCnvInjectionSocket.hpp"
@@ -23,7 +23,7 @@
namespace PrtCnv
{
// ---------------------------------------------------------------
PrtCnvInjectionThread::PrtCnvInjectionThread(PrtCnvThreadStarter* a_parent)
: PrtCnvThread(a_parent, "PrtCnvInjectionThread")
, m_Port(46666)
@@ -41,7 +41,7 @@ PrtCnvInjectionThread::~PrtCnvInjectionThread()
delete m_RadioListMutex;
}
// ---------------------------------------------------------------
int32_t PrtCnvInjectionThread::create(NGL::Settings *settings)
{
INFO_LOG(m_logger) << "create";
@@ -52,7 +52,7 @@ int32_t PrtCnvInjectionThread::create(NGL::Settings *settings)
m_Enabled = m_Config->getBoolean(getName(), QStringLiteral("Enable"), false);
// prepare a tcp-server for simulating central
if (m_Enabled)
{
m_Server = new QTcpServer(this);
@@ -64,7 +64,7 @@ int32_t PrtCnvInjectionThread::create(NGL::Settings *settings)
}
// ---------------------------------------------------------------
int32_t PrtCnvInjectionThread::init()
{
INFO_LOG(m_logger) << "init";
@@ -76,15 +76,15 @@ int32_t PrtCnvInjectionThread::init()
// ---------------------------------------------------------------
// Starts the thread and listen for TCP-clients
// ---------------------------------------------------------------
int32_t PrtCnvInjectionThread::start()
{
INFO_LOG(m_logger) << "Start";
PrtCnvThread::start();
// start the TCP-server
if (m_Enabled)
{
m_Server->setMaxPendingConnections(1);
@@ -97,9 +97,9 @@ int32_t PrtCnvInjectionThread::start()
// ---------------------------------------------------------------
// Connects a TCP-client
// ---------------------------------------------------------------
void PrtCnvInjectionThread::connectClient()
{
INFO_LOG(m_logger) << "A client has connected to the injection-server";
@@ -111,9 +111,9 @@ void PrtCnvInjectionThread::connectClient()
// ---------------------------------------------------------------
// Disconnects a TCP-client
// ---------------------------------------------------------------
void PrtCnvInjectionThread::disconnectClient(PrtCnvInjectionSocket *a_injectionSocket)
{
auto it = m_SocketList.find(a_injectionSocket);
@@ -125,13 +125,13 @@ void PrtCnvInjectionThread::disconnectClient(PrtCnvInjectionSocket *a_injectionS
// ---------------------------------------------------------------
// Returns the next central-telegram to be injected. It will
// automatically be taken out of the list.
// The caller is responsible to delete the telegram, if no
// longer used.
// Returns NULL if no central-telegram available
// ---------------------------------------------------------------
N_CoPrtCnv::CoPrtCnvCentralTelegram *PrtCnvInjectionThread::getNextCentralInjectionTelegram()
{
QMutexLocker l(m_CentralListMutex);
@@ -144,13 +144,13 @@ N_CoPrtCnv::CoPrtCnvCentralTelegram *PrtCnvInjectionThread::getNextCentralInject
}
// ---------------------------------------------------------------
// Returns the next radio-telegram to be injected. It will
// automatically be taken out of the list.
// The caller is responsible to delete the telegram, if no
// longer used.
// Returns NULL if no radio-telegram available
// ---------------------------------------------------------------
N_CoPrtCnv::CoPrtCnvCentralTelegram *PrtCnvInjectionThread::getNextRadioInjectionTelegram()
{
QMutexLocker l(m_RadioListMutex);
@@ -163,7 +163,7 @@ N_CoPrtCnv::CoPrtCnvCentralTelegram *PrtCnvInjectionThread::getNextRadioInjectio
}
// ---------------------------------------------------------------
void PrtCnvInjectionThread::addToCentralList(N_CoPrtCnv::CoPrtCnvCentralTelegram *a_telegram)
{
QMutexLocker l(m_CentralListMutex);
@@ -171,12 +171,12 @@ void PrtCnvInjectionThread::addToCentralList(N_CoPrtCnv::CoPrtCnvCentralTelegram
}
// ---------------------------------------------------------------
void PrtCnvInjectionThread::addToRadioList(N_CoPrtCnv::CoPrtCnvCentralTelegram *a_telegram)
{
QMutexLocker l(m_RadioListMutex);
m_RadioTelegramList.push(a_telegram);
}
}
} // namespace PrtCnv
@@ -1,15 +1,15 @@
// **************************************************************************
//
// (C) Copyright 2009 Swiss SIMTEC AG
//
// **************************************************************************
//
// $HeadURL$
// $LastChangedBy$
// $LastChangedDate$
// $LastChangedRevision$
//
// **************************************************************************
#pragma once
@@ -28,8 +28,16 @@ class CoPrtCnvCentralTelegram;
namespace PrtCnv
{
class PrtCnvInjectionSocket;
/**
* This class represents a thread, which acts as TCP-Server. The LogView-
* application can connect to it and send radio- or central-telegrams. The
* telegrams will be stored within this class and can be taken by another thread.
* This mechanism will be used for inject telegrams to protocol-converter.
*
* @author alois.wismer
* @version 1.0
* @created 05-Aug-2010 11:17:06
*/
class PrtCnvInjectionThread : public PrtCnvThread
{
Q_OBJECT
@@ -37,8 +45,10 @@ namespace PrtCnv
~PrtCnvInjectionThread();
/**
*
* @param a_parent
*/
explicit PrtCnvInjectionThread(PrtCnvThreadStarter* a_parent);
@@ -47,31 +57,48 @@ namespace PrtCnv
int32_t init() override;
/**
* Starts the thread and listen for TCP-clients
*/
int32_t start() override;
/**
* Returns the next central-telegram to be injected. It will automatically be
* taken out of the list.
* The caller is responsible to delete the telegram, if no longer used.
* Returns NULL if no central-telegram available
*/
N_CoPrtCnv::CoPrtCnvCentralTelegram *getNextCentralInjectionTelegram();
/**
* Returns the next radio-telegram to be injected. It will automatically be taken
* out of the list.
* The caller is responsible to delete the telegram, if no longer used.
* Returns NULL if no radio-telegram available
*/
N_CoPrtCnv::CoPrtCnvCentralTelegram *getNextRadioInjectionTelegram();
/**
*
* @param a_telegram
*/
void addToCentralList(N_CoPrtCnv::CoPrtCnvCentralTelegram *a_telegram);
/**
*
* @param a_telegram
*/
void addToRadioList(N_CoPrtCnv::CoPrtCnvCentralTelegram *a_telegram);
protected:
protected: /**
* The port of the injection-server (configurable with key 'Port' in group
* [Injection])
*/
uint16_t m_Port;
/**
* true if injection-server is enabled (configurable with key 'Enable' in group
* [Injection])
*/
bool m_Enabled;
QTcpServer *m_Server;
@@ -89,11 +116,15 @@ namespace PrtCnv
public slots:
/**
* Connects a TCP-client
*/
void connectClient();
/**
* Disconnects a TCP-client
*
* @param a_injectionSocket
*/
void disconnectClient(PrtCnvInjectionSocket* a_injectionSocket);
};
@@ -1,18 +1,24 @@
// **************************************************************************
//
// (C) Copyright 2009 Swiss SIMTEC AG
//
// **************************************************************************
//
// $HeadURL$
// $LastChangedBy$
// $LastChangedDate$
// $LastChangedRevision$
//
// **************************************************************************
/*!
*
* \page Tetra-Interface Tetra-Interface
*
* This component is needed to communicate between the Server software and the players in
* the field via Tetra. It's an extra component due to historical reasons only.
*
*/
#include "PrtCnvApplication.hpp"
#include <NGLLogger/INGLLogger.h>
@@ -25,41 +31,41 @@
#include <unistd.h>
#endif
// ---------------------------------------------------------------
// Become a daemon
// ---------------------------------------------------------------
static void daemonize()
{
#ifndef WIN32
pid_t pid, sid;
/* already a daemon */
if ( getppid() == 1 )
return;
/* Fork off the parent process */
pid = fork();
if (pid < 0) {
exit(EXIT_FAILURE);
}
/* If we got a good PID, then we can exit the parent process. */
if (pid > 0) {
exit(EXIT_SUCCESS);
}
/* At this point we are executing as the child process */
/* Change the file mode mask */
umask(0);
/* Create a new SID for the child process */
sid = setsid();
if (sid < 0) {
exit(EXIT_FAILURE);
}
/* Change the current working directory. This prevents the current
directory from being locked; hence not being able to remove it. */
if ((chdir("/")) < 0) {
exit(EXIT_FAILURE);
}
@@ -1,26 +1,26 @@
// **************************************************************************
//
// (C) Copyright 2009 Swiss SIMTEC AG
//
// **************************************************************************
//
// $HeadURL$
// $LastChangedBy$
// $LastChangedDate$
// $LastChangedRevision$
//
// **************************************************************************
// manual class headers
#include "PrtCnvMember.hpp"
#include <CoPrtCnv/CoPrtCnvRadioTelegram.hpp>
namespace PrtCnv
{
// ---------------------------------------------------------------
// Constructor with id and ISSI as parameter
// ---------------------------------------------------------------
PrtCnvMember::PrtCnvMember(int a_id, int a_issi)
: m_ISSI(a_issi)
, m_ClaimCount(0)
@@ -35,9 +35,9 @@ PrtCnvMember::~PrtCnvMember()
}
// ---------------------------------------------------------------
// Adds a radio-telegram-fragment to this member.
// ---------------------------------------------------------------
void PrtCnvMember::addFragmentedTelegram(const N_CoPrtCnv::CoPrtCnvRadioTelegram &a_radioTelegram)
{
m_FragmentedTelegramList.insert(std::make_pair(a_radioTelegram.getFragmentCounter(),
@@ -46,28 +46,28 @@ void PrtCnvMember::addFragmentedTelegram(const N_CoPrtCnv::CoPrtCnvRadioTelegram
// ---------------------------------------------------------------
// Returns the telegram-Id of the fragmented telegram assiged
// to this member.
// If not evaluable: 0 will be returned.
// ---------------------------------------------------------------
gef_telegramm_id_et PrtCnvMember::getFragmentedTelegramId() const
{
// the fragment with the highest counter is the first fragment
for (auto rit = m_FragmentedTelegramList.rbegin(); rit != m_FragmentedTelegramList.rend(); ++rit)
{
N_CoPrtCnv::CoPrtCnvRadioTelegram *firstFragment = rit->second;
if (N_CoPrtCnv::CoPrtCnvRadioTelegram::e_FirstFragment == firstFragment->getFragmentStatus())
return firstFragment->getTelID();
}
return GEF_BESTAETIGUNG;
return GEF_BESTAETIGUNG; // no telegram found => return 0 (= GEF_BESTAETIGUNG)
}
// ---------------------------------------------------------------
// Erases the radio-telegram-fragments assiged to this member.
// The fragments itself will be deleted.
// ---------------------------------------------------------------
void PrtCnvMember::clearFragmentedList()
{
for (auto it : m_FragmentedTelegramList)
@@ -76,23 +76,23 @@ void PrtCnvMember::clearFragmentedList()
}
// ---------------------------------------------------------------
// Returns the radio-telegram-fragments assembled to a only
// big radio-telegram. The fragments will not be deleted.
// Returns NULL if it was impossible to assemble the telegram.
// ---------------------------------------------------------------
QByteArray PrtCnvMember::getUnfragmentedTelegramData() const
{
return N_CoPrtCnv::CoPrtCnvRadioTelegram::getUnfragmentedData(m_FragmentedTelegramList);
}
// ---------------------------------------------------------------
// Returns true if the fragment-list is empty
// ---------------------------------------------------------------
bool PrtCnvMember::isFragmentedListEmpty() const
{
return m_FragmentedTelegramList.empty();
}
}
} // namespace PrtCnv
@@ -1,15 +1,15 @@
// **************************************************************************
//
// (C) Copyright 2009 Swiss SIMTEC AG
//
// **************************************************************************
//
// $HeadURL$
// $LastChangedBy$
// $LastChangedDate$
// $LastChangedRevision$
//
// **************************************************************************
#pragma once
@@ -17,7 +17,7 @@
#include <map>
#include <QtCore/QByteArray>
// manual class imports
namespace N_CoPrtCnv
@@ -27,14 +27,23 @@ namespace N_CoPrtCnv
namespace PrtCnv
{
/**
* Hold the data of a TNE (Client on radio-side) needed for login, licensing,
* nachforderungs-statistic and reading fragmented telegrams from TNE.
* @author wia
* @version 1.0
* @updated 16-Mrz-2010 11:20:11
*/
class PrtCnvMember final
{
public:
/**
* The status of the member
* @author wia
* @version 1.0
* @updated 16-Mrz-2010 11:20:11
*/
enum E_MemberStatus
{
e_Ok,
@@ -44,40 +53,55 @@ namespace PrtCnv
};
~PrtCnvMember();
/**
* Constructor with id and ISSI as parameter
*
* @param a_id
* @param a_issi
*/
PrtCnvMember(int a_id, int a_issi);
/**
* Adds a radio-telegram-fragment to this member.
*
* @param a_radioTelegram
*/
void addFragmentedTelegram(const N_CoPrtCnv::CoPrtCnvRadioTelegram &a_radioTelegram);
/**
* Returns the telegram-Id of the fragmented telegram assiged to this member.
* If not evaluable: 0 will be returned.
*/
gef_telegramm_id_et getFragmentedTelegramId() const;
/**
* Erases the radio-telegram-fragments assiged to this member. The fragments
* itself will be deleted.
*/
void clearFragmentedList();
/**
* Returns the radio-telegram-fragments assembled to a only big radio-telegram.
* The fragments will not be deleted.
* Returns NULL if it was impossible to assemble the telegram.
*/
QByteArray getUnfragmentedTelegramData() const;
/**
* Returns true if the fragment-list is empty
*/
bool isFragmentedListEmpty() const;
public:
// The ISSI of this TNE (0..0xFFFFFF)
int m_ISSI;
// Counts the Nachforderungen asked from this TNE
int m_ClaimCount;
// the exercise where the member is currently logged in
int m_loggedInExerciseId;
// The identification (also called Ausstattungs-Nummer) of this TNE (0..10000)
int m_Id;
// true if TNE is licensed
bool m_Licensed;
private:
// Map of radio-telegram-fragments ordered by fragment-number
std::multimap<uint16_t,N_CoPrtCnv::CoPrtCnvRadioTelegram*> m_FragmentedTelegramList;
};
File diff suppressed because it is too large. Load diff
@@ -1,16 +1,16 @@
// **************************************************************************
//
// (C) Copyright 2009 Swiss SIMTEC AG
//
// **************************************************************************
//
// $HeadURL$
// $LastChangedBy$
// $LastChangedDate$
// $LastChangedRevision$
//
// Implementation of the Class PrtCnvRadioThread
// **************************************************************************
#pragma once
#include "PrtCnvSocketThread.hpp"
@@ -38,8 +38,17 @@ struct BiteError
class PrtCnvMember;
class PrtCnvRadioTrafficThread;
class PrtCnvStoredRadioTelegram;
/**
* This class handles the protocol to radio. This includes:
* - handle login and licensing of TNEs
* - send and receive normal telegrams
* - send normal broadcasts and nachforderungen
* - optimize bandwith usage
*
* @author
* @version 1.0
* @created 05-Jan-2006 13:34:41
*/
class PrtCnvRadioThread : public PrtCnv::PrtCnvSocketThread
{
Q_OBJECT
@@ -47,25 +56,33 @@ struct BiteError
public:
PrtCnvRadioThread(int exerciseId, PrtCnvThreadStarter* a_parent);
/**
* Creates all subcomponents and connects signals to slots
*/
int32_t create(NGL::Settings *settings) override;
/**
* Deallocates subcomponents.
*/
int32_t destroy() override;
/**
* Initializes the variables.
*/
int32_t init() override;
/**
* Starts the thread and connects to TCP-server
*/
int32_t start() override;
/**
* Makes empty the message-queue faster, because the messages will be consumed
* without action.
*/
void prepareCleanUp();
/**
* Immediatelly send the environment telegramm to inform the players
* about the new state
*/
void sendEnvironmentTelegramTimerNow();
void exerciseEquipmentChanged(const TrainingAreaBase::TetraIcd::ExerciseEquipmentAssignmentComplete &data);
@@ -80,124 +97,165 @@ public:
int masterIssi);
protected:
/**
* Pointer to central-thread
*/
PrtCnvCentralThread *m_CentralThread;
/**
* Pointer to radio traffic counter thread
*/
PrtCnvRadioTrafficThread *m_radioTrafficThread;
public:
Q_SIGNALS:
/**
* Signal to start sending a telegram to central
*/
void checkSendToCentral();
/**
* Signal to start sending a telegram to radio
*/
void checkSendToRadio();
/**
* Signal to indicate thread has finished the cleaning-phase
*/
void cleant();
/**
* Signal to indicate thread has stopped work
*/
void stopped();
/**
* a new equipment exercise mapping was received, check if member (all when identiy = -1)
* is still in this exercise
*/
void checkMemberForValidLogin(int identity, int issi);
// emitted when the tetra connection state changes
void tetraConnectionState(bool connected);
// an effect siumlation was (de)activated
void areaEffectSimulationActivated(int wirkfeldKennung);
void areaEffectSimulationDeactivated(int wirkfeldKennung);
// initialization of the thread is finished
void initDone();
// a player was (un)licensed
void playerLicencedChanged(int equipNo, N_CoPrtCnv::E_LicensingKind kind);
void warehouseMessageFromPtrCnv(const QByteArray &jsonData);
protected:
/**
* Counts the sended telegrams
*/
uint32_t m_SendCounter;
/**
* The ISSI of the protocol-converter
*/
uint32_t m_HostISSI;
/**
* The lowest vaild value for the counter
*/
const uint32_t START_COUNTER;
/**
* One more than the highest vaild value for the counter
*/
const uint32_t END_COUNTER;
/**
* This timer will be used for periodically send the Umgebungsmeldung to TNEs
*/
QTimer *m_EnvironmentTelegramTimer;
/**
* The ISSI used for broadcast-telegrams
*/
uint32_t m_BroadcastISSI;
/**
* The directory and prefix for the login-log-file
*/
QString m_LoginPathWithPrefix;
/**
* Übungskennung (used for login-logfile name)
*/
int m_ExerciseId;
/**
* Bit-map for evaluating whether a playerid is valid
*/
std::set<uint16_t> m_AllowedIdentities;
/**
* true => TPU will be licensed whether selftest and configtest fails or not
*/
bool m_DoLicenseDespiteSelftestOrConfigFailure;
/**
* true => identify of TPU will be checked, whether allowed
*/
bool m_DoCheckIdentity;
PrtCnvBroadcastMgr m_BroadcastManager;
/**
* True => received telegrams will be dumped to common log-file
*/
bool m_DoDumpReceivedTelegrams;
/**
* True => sent telegrams will be dumped to common log-file
*/
bool m_DoDumpSentTelegrams;
/**
* True => radio-telegrams will be sent in SDS-TL-format
*/
bool m_DoUseSDSTL;
/**
* Identities that need an active position response after licensing
*/
std::set<uint16_t> m_DoNeedActPosResp;
/**
* The ISSI used for emergency call-telegrams
*/
uint32_t m_EmergencyCallISSI;
/**
* Sends a telegram to radio. It will be fragmented if needed. It will be checked,
* whether the receiver is logged in, licensed, the content is valid and the
* telegram is not expired and an error-message will be sent to central if needed.
* It will be tested, whether the maximal broadcast-counter is reached and if it
* is, the needed action will be done.
*
* @param a_telegram
* @param a_handle
* @param a_doCheckWhetherExpired
*/
void sendTelegram(const std::shared_ptr<N_CoPrtCnv::CoPrtCnvRadioTelegram> &a_telegram,
PrtCnvStoredRadioTelegram *a_handle,
const bool a_doCheckWhetherExpired = true);
/**
* Sends the register-indication to TETRA
*/
void doRegister();
/**
* Send a register group message to TETRA
*/
void registerGroups();
/**
* Processes the register-response-telegram
*
* @param a_regsitrationStatus
*/
void handleRegisterRsp(const uint8_t a_regsitrationStatus);
public:
/**
* @author alois.wismer
* @version 1.0
* @updated 06-Apr-2010 16:01:59
*/
enum class E_TrafficLoad
{
Unknown = -1,
@@ -206,12 +264,14 @@ public:
FullLoad
};
protected:
/**
* Holds the radio-telegram for sending Umgebungsmeldung periodically
*/
N_CoPrtCnv::CoPrtCnvRadioTelegram *m_EnvironmentTelegram;
/**
* load of traffic from Protocolconverter to TETRA
*/
E_TrafficLoad m_SendLoad;
uint32_t m_SendQueueFullLoad;
@@ -219,79 +279,125 @@ public:
uint32_t m_SendTelegramsNormalLoad;
uint32_t m_SendTelegramsHighLoad;
uint32_t m_SendTelegramsFullLoad;
/**
* The number of telegrams sent within the last second
*/
uint32_t m_SentTelegrams;
/**
* The number of bytes sent within last second
*/
uint32_t m_SentBytes;
/**
* how many times tick must be called until 1 second has elapsed
*/
uint32_t m_TickCounter;
/**
* how many times tick was called (used for knowing when 1 second has elapsed,
* which we use for sent-bytes and receive-bytes statistics)
*/
uint32_t m_TicksPerSecond;
/**
* How many values we use for computing average
*/
static const int AVERAGE_COUNT = 10;
/**
* The last few number of bytes sent, used for calculating the average
*/
uint32_t m_SentBytesAverage[AVERAGE_COUNT];
/**
* index for writing into aveage-array
*/
uint8_t m_AverageIndex;
/**
* The number of telegrams sent within the last second
*/
uint32_t m_ReceivedTelegrams;
/**
* The number of bytes sent within last second
*/
uint32_t m_ReceivedBytes;
/**
* The last few number of bytes sent, used for calculating the average
*/
uint32_t m_ReceivedBytesAverage[AVERAGE_COUNT];
/**
* The groups which should be listened to
*/
std::set<uint32_t> m_ListenGroups;
/**
* @brief use scrambling yes/no (Radio/UseScrambling)
*/
bool m_bUseScrambling;
/**
* The logger object for statistics
*/
NGL::INGLLogger &m_loggerStats;
// mapping which equipNos are in which exercise
std::unordered_map<int, std::unordered_set<int>> m_exerciseEquipmentAssignments;
std::unordered_map<int, TrainingAreaBase::TetraIcd::GroupIssiInformation> m_groupIssiInformation;
mutable QRecursiveMutex m_exerciseEquipmentAssignmentMutex;
private:
/**
* generates an answer to TNE from protocoll-converter for some special radio-
* telegrams (i.e. NachforderungBroadcast, BITE-Meldung)
* returns true when the telegram must be sent to central
*
* @param a_centralTelegram
* @param a_radioTelegram
*/
bool sendAnswer(const N_CoPrtCnv::CoPrtCnvRadioTelegram &a_radioTelegram);
/**
* After calling this function, the caller must no longer use a_data, because this
* function 'consumes' a_data and will delete a_data, when no longer needed.
*
* @param a_data A pointer to the telegram-data, including frame-header.
* Control over a_data will be lost (see description of function itself)
*/
void handleReceivedTelegram(const QByteArray &data);
/**
* Processes the data-indication-telegram
*
* @param a_data
* @param bDoDeleteData is set to true when the caller can properly delete the data
*/
void handleDataIndReq(const QByteArray &data, bool bIsMaybeScrambled);
/**
* Processes the login-telegram
*
* @param a_loginTelegram
*/
void handleLoginTelegram(const N_CoPrtCnv::CoPrtCnvRadioTelegram &a_loginTelegram);
/**
* Processes a fragment of a telegram
*
* @param a_fragmentedTelegram
*/
void handleFragmentedTelegram(const N_CoPrtCnv::CoPrtCnvRadioTelegram &a_fragmentedTelegram);
/**
* Sends a telegram "FehlermeldungGefechtsfeld" to central
*
* @param a_identity
* @param a_errorCause
* @param a_telegramId
*/
void sendFehlermeldungGefechtsfeldToCentral(const uint16_t a_identity,
const TrainingAreaBase::TetraIcd::CtaDataError::Reason a_errorCause,
const gef_telegramm_id_et a_telegramId = GEF_BESTAETIGUNG);
/**
* Returns the ISSI of TNE with a_TNE_Id
*
* @param a_TNE_Id
*/
uint32_t getDestinationISSI(const uint16_t a_TNE_Id) const;
/**
* Processes the BITE/BITE extended-telegram
*
* @param a_BITE_CentralTelegram
*/
bool handleBITEEXT_Telegram(const N_CoPrtCnv::CoPrtCnvRadioTelegram &a_BITE_RadioTelegram);
bool handleBITE_Telegram(const N_CoPrtCnv::CoPrtCnvRadioTelegram &a_BITE_RadioTelegram,
TrainingAreaBase::TetraIcd::BiteReport::LoginType anmeldeart,
@@ -302,47 +408,86 @@ public:
const QList<PrtCnv::BiteError> &fehlerListe
);
/**
* Sends a login-telegram to radio
*
* @param a_loginTelegramStatus
* @param a_identity
* @param a_ISSI
*/
void sendLoginResponse(const N_CoPrtCnv::CoPrtCnvRadioTelegram::E_LoginStatus a_loginTelegramStatus, const uint16_t a_identity, const uint32_t a_ISSI);
void sendLoginResponse(const N_CoPrtCnv::CoPrtCnvRadioTelegram::E_LoginStatus a_loginTelegramStatus,
const uint16_t a_identity, const uint32_t a_ISSI, const TrainingAreaBase::TetraIcd::GroupIssiInformation &group);
/**
* Sends a telegram "LizenzierungTNE" to radio
*
* @param a_identity AusstattungsId
* @param a_issi
* @param a_licensingKind
* @param a_errorCause
*/
void sendLizenzierungTneToRadio(const uint16_t a_identity, const uint32_t a_issi,
const N_CoPrtCnv::E_LicensingKind a_licensingKind,
const N_CoPrtCnv::E_LicensingErrorCode a_errorCause);
/**
* Writes the login of a TNE to the login-logfile
*
* @param a_radioTelegram
* @param a_prosaText
*/
void writeLoginLog(const N_CoPrtCnv::CoPrtCnvRadioTelegram &a_radioTelegram, const QString &a_prosaText);
void writeLoginLog(const N_CoPrtCnv::CoPrtCnvRadioTelegram *a_radioTelegram, const QString &a_prosaText);
void writeLoginLog(uint32_t identity, uint32_t issi, const QString &a_prosaText);
/**
* Receives the file with allowed playerId, or the lowest and hightest allowed
* playerIds
*/
void initIdentityArray();
/**
* Reads one line of the playerId-file.
* Aborts when not successful
*
* @param a_idAsText
* @param a_line
* @param a_fileName
*/
uint16_t readIdentity(const QByteArray& a_idAsText, const uint32_t a_line, const QString& a_fileName);
/**
* Checks whether the playerId is allowd.
*
* @param a_identity
*/
bool isIdentityValid(uint16_t a_identity) const;
/**
* Allows this playerId.
*
* @param a_identity
*/
void setIdentityVaild(uint16_t a_identity);
/**
* Fragment a telegram and sends the fragments to radio.
*
* @param a_telegram
*/
void sendFragmentedTelegram(const std::shared_ptr<N_CoPrtCnv::CoPrtCnvRadioTelegram> &a_telegram);
/**
* sends the telegram to radio-socket
* returns the broadcastIndex (0 if it was no broadcast)
*
* @param a_telegram
*/
uint16_t sendToSocket(const std::shared_ptr<N_CoPrtCnv::CoPrtCnvRadioTelegram> &a_telegram);
/**
* Processes the report-indication-telegram
*
* @param a_data
*/
void handleReportIndReq(const QByteArray &data);
void prepareWareHouseMessage(qint32 equipNr,
bool doLicence,
@@ -353,59 +498,78 @@ public:
const QList<PrtCnv::BiteError> &fehlerListe);
protected Q_SLOTS:
/**
* @brief oslot to handle call to sendEnvironmentTelegramTimerNow in correct thread
*/
void onSendEnvironmentTelegramTimerNow();
/**
* see base-class
*/
void timeoutAliveAndConnection() override;
/**
* Processes the periodical stuff, like broadcasts and nachforderungen
*/
void timeoutTick() override;
/**
* Checks whether a normal telegram must be sent and sends it.
*/
void checkSend();
/**
* see base-class
*/
void readyRead() override;
/**
* see base-class
*/
void disconnected() override;
/**
* see base-class
*/
void connected() override;
/**
* Processes the periodical sending of Umgebungsmeldung
*/
void timeoutEnvironmentTelegram();
/**
* Clean the DB.
*/
void doClean();
/**
* Restart work after cleaning Db
*/
void doStart();
/**
* Stops work for cleaning DB
*/
void doStop();
// a broadcastTelegrams request was received from EXCON (e.g. through Wls)
void onBroadcastTelegramsRequestFromCentral(int equipmentNumber, int broadcastIndex, int resetCounter);
private:
/**
* Processes the status-telegram
*
* @param data
*/
void handleStatusIndReq(const QByteArray &data);
/**
* Processes the air-interface-report-telegram
*
* @param a_data
*/
void handleAirInterfaceLoadReq(const QByteArray &data);
/**
* Computes and logs the sent- and receive-statistics
*/
void computeAndLogTrafficStatistics();
/**
* returns true, if at the moment no more telegrams should be sent
*/
bool isSendLimitReached() const;
@@ -1,16 +1,16 @@
// **************************************************************************
//
// @RDE_HEADER@
//
// **************************************************************************
//
// $HeadURL$
// $LastChangedBy$
// $LastChangedDate$
// $LastChangedRevision$
//
// Implementation of the Class PrtCnvRadioTrafficThread
// **************************************************************************
#include "PrtCnvRadioTrafficThread.hpp"
#include "PrtCnvDbThread.hpp"
@@ -46,7 +46,7 @@ void PrtCnvRadioTrafficThread::newTelegramArrived(unsigned int size)
int32_t PrtCnvRadioTrafficThread::start()
{
// read data from m_Config
const QString trafficControlGroup(QStringLiteral("TrafficControl"));
int highLoad = m_Config->getInteger(trafficControlGroup, QStringLiteral("ReceiveQueueHighLoad"), 60);
int fullLoad = m_Config->getInteger(trafficControlGroup, QStringLiteral("ReceiveQueueFullLoad"), 80);
@@ -55,7 +55,7 @@ int32_t PrtCnvRadioTrafficThread::start()
float trafficPerReceiverKB = m_Config->getFloat(trafficControlGroup, QStringLiteral("ReceiveThroughput"), 3.6f);
int cntTransceiver = m_Config->getInteger(trafficControlGroup, QStringLiteral("TransceiverCount"), 6);
// sanity checks
if (highLoad < 0 || highLoad > 100)
highLoad = 60;
if (fullLoad < highLoad || fullLoad > 100)
@@ -74,7 +74,7 @@ int32_t PrtCnvRadioTrafficThread::start()
m_fullLoad = maxTrafficBytes * fullLoad / 100.f;
m_highLoad = maxTrafficBytes * highLoad / 100.f;
m_hystLoad = maxTrafficBytes * hystLoad / 100.f;
m_cleanupTimeout = avgTime * 1000;
m_cleanupTimeout = avgTime * 1000; // ms
DEBUG_LOG(m_logger) << "Read config ReceiveQueueHighLoad: " << highLoad;
DEBUG_LOG(m_logger) << "Read config ReceiveQueueFullLoad: " << fullLoad;
@@ -100,12 +100,12 @@ void PrtCnvRadioTrafficThread::onCalculateTrafficLoad()
unsigned int payload = 0;
{
QMutexLocker l(&m_mutex);
// fuer aktuelle Sekunde haben wir noch nicht alle Daten
for (int i = 1; i <= m_cleanupTimeout / 1000; ++i)
payload += m_data.value(curTime - i);
}
// Durchschnitt ...
payload /= (m_cleanupTimeout / 1000);
INFO_LOG(m_logger) << "Average Payload in the last "
@@ -116,34 +116,34 @@ void PrtCnvRadioTrafficThread::onCalculateTrafficLoad()
PrtCnvRadioThread::E_TrafficLoad newReceiveLoad;
if (payload >= m_fullLoad)
{
// full load
newReceiveLoad = PrtCnvRadioThread::E_TrafficLoad::FullLoad;
// Hysterese nach oben
if (m_receiveLoad == PrtCnvRadioThread::E_TrafficLoad::HighLoad)
{
// wenn cnt in Bereich m_fullLoad ... m_fullLoad + m_hystLoad
// -> noch warten
if(payload < m_fullLoad + m_hystLoad)
newReceiveLoad = PrtCnvRadioThread::E_TrafficLoad::HighLoad;
}
}
else if (payload >= m_highLoad)
{
// high load
newReceiveLoad = PrtCnvRadioThread::E_TrafficLoad::HighLoad;
// Hysterese nach oben
if (m_receiveLoad == PrtCnvRadioThread::E_TrafficLoad::NormalLoad)
{
// wenn cnt in Bereich m_highLoad ... m_highLoad + m_hystLoad
// -> noch warten
if (payload < m_highLoad + m_hystLoad)
newReceiveLoad = PrtCnvRadioThread::E_TrafficLoad::NormalLoad;
}
// Hysterese nach unten
if (m_receiveLoad == PrtCnvRadioThread::E_TrafficLoad::FullLoad)
{
// wenn cnt in Bereich m_fullLoad ... m_fullLoad - m_hystLoad
// -> noch warten
if (payload >= m_fullLoad - m_hystLoad)
newReceiveLoad = PrtCnvRadioThread::E_TrafficLoad::FullLoad;
}
@@ -151,11 +151,11 @@ void PrtCnvRadioTrafficThread::onCalculateTrafficLoad()
else
{
newReceiveLoad = PrtCnvRadioThread::E_TrafficLoad::NormalLoad;
// Hysterese nach unten
if (m_receiveLoad == PrtCnvRadioThread::E_TrafficLoad::HighLoad)
{
// wenn cnt in Bereich m_highLoad ... m_highLoad - m_hystLoad
// -> noch warten
if(payload >= m_highLoad - m_hystLoad)
newReceiveLoad = PrtCnvRadioThread::E_TrafficLoad::HighLoad;
}
@@ -163,7 +163,7 @@ void PrtCnvRadioTrafficThread::onCalculateTrafficLoad()
if (m_receiveLoad != newReceiveLoad)
{
m_receiveLoad = newReceiveLoad;
// Achtung: Nicht mehr als 31 Sekunden erlaubt
unsigned int wartezeit_posmldg = (static_cast<unsigned int>(m_receiveLoad) * 10) + 1;
INFO_LOG(m_logger) << "New traffic load: " << m_receiveLoad;
@@ -191,18 +191,18 @@ void PrtCnvRadioTrafficThread::onCleanupTimeout()
while (it != m_data.end())
{
const time_t key = it.key();
// 10 als Puffer (siehe auch onCalculateTrafficLoad())
if (key < curTime - m_cleanupTimeout - 10)
{
m_data.erase(it++);
m_telegrams.remove(key);
continue;
}
break;
break; // arbitrarily ordered
}
}
QTimer::singleShot(m_cleanupTimeout, this, &PrtCnvRadioTrafficThread::onCleanupTimeout);
}
}
} // namespace PrtCnv
@@ -1,16 +1,16 @@
// **************************************************************************
//
// @RDE_HEADER@
//
// **************************************************************************
//
// $HeadURL$
// $LastChangedBy$
// $LastChangedDate$
// $LastChangedRevision$
//
// Implementation of the Class PrtCnvRadioTrafficThread
// **************************************************************************
#pragma once
#include "PrtCnvThread.hpp"
@@ -21,63 +21,76 @@
namespace PrtCnv
{
/**
* This class handles the traffic counting for the
* incoming radio data
*/
class PrtCnvRadioTrafficThread final : public PrtCnvThread
{
Q_OBJECT
public:
explicit PrtCnvRadioTrafficThread(PrtCnvThreadStarter* a_parent);
/**
* A new telegram arrived.
*/
void newTelegramArrived(unsigned int size);
/**
* Start the thread handling
*/
int32_t start() override;
protected Q_SLOTS:
/**
* Timeout to recalculate traffic load
*/
void onCalculateTrafficLoad();
/**
* Timeout to throw away old data
*/
void onCleanupTimeout();
protected:
/**
* The current traffic load
*/
PrtCnvRadioThread::E_TrafficLoad m_receiveLoad;
/**
* Full load
*/
unsigned int m_fullLoad;
/**
* High load
*/
unsigned int m_highLoad;
/**
* Hysterese
*/
unsigned int m_hystLoad;
/**
* Timeout for recalculation
*/
int m_calcTimeout;
/**
* Timeout until data is thrown away
*/
int m_cleanupTimeout;
QRecursiveMutex m_mutex;
/**
* map<time, nTelegrams>
*/
QMap<time_t, unsigned int> m_data;
QMap<time_t, unsigned int> m_telegrams;
};
}
} // namespace PrtCnv
@@ -1,16 +1,16 @@
// **************************************************************************
//
// (C) Copyright 2009 Swiss SIMTEC AG
//
// **************************************************************************
//
// $HeadURL$
// $LastChangedBy$
// $LastChangedDate$
// $LastChangedRevision$
//
// Implementation of the Class PrtCnvSocketThread
// **************************************************************************
#include "PrtCnvSocketThread.hpp"
#include <utility>
@@ -25,9 +25,9 @@
namespace PrtCnv
{
// ---------------------------------------------------------------
// Constructor with pointer to thread-starter as parameter
// ---------------------------------------------------------------
PrtCnvSocketThread::PrtCnvSocketThread(PrtCnv::PrtCnvThreadStarter* a_parent, const char *loggerName)
: PrtCnvThread(a_parent, loggerName)
, m_ConnectionTimer(nullptr)
@@ -54,9 +54,9 @@ PrtCnvSocketThread::~PrtCnvSocketThread()
cleanup();
}
// ---------------------------------------------------------------
// Creates all subcomponents and connects signals to slots
// ---------------------------------------------------------------
int32_t PrtCnvSocketThread::create(NGL::Settings *settings)
{
PrtCnvThread::create(settings);
@@ -76,10 +76,10 @@ int32_t PrtCnvSocketThread::create(NGL::Settings *settings)
return 0;
}
// ---------------------------------------------------------------
// Creates a new socket to avoid getting old stuff from the
// former socket when reconnecting
// ---------------------------------------------------------------
void PrtCnvSocketThread::createNewSocket()
{
INFO_LOG(m_logger) << "createNewSocket m_oldSocket=" << m_Socket;
@@ -87,11 +87,11 @@ void PrtCnvSocketThread::createNewSocket()
if (m_Socket)
{
m_Socket->disconnectFromHost();
m_Socket->disconnect();
m_Socket->disconnectFromHost(); // Falls noch connected
m_Socket->disconnect(); // Alle Signals/Slots aufräumen
if (m_Socket->state() != QAbstractSocket::UnconnectedState)
m_Socket->waitForDisconnected();
m_Socket->deleteLater();
m_Socket->deleteLater(); // und weg damit
}
m_Socket = new QTcpSocket(this);
@@ -106,9 +106,9 @@ void PrtCnvSocketThread::createNewSocket()
connect(m_Socket, &QTcpSocket::readyRead, this, &PrtCnvSocketThread::readyRead, Qt::QueuedConnection);
}
// ---------------------------------------------------------------
// Deallocates subcomponents.
// ---------------------------------------------------------------
int32_t PrtCnvSocketThread::destroy()
{
PrtCnvThread::destroy();
@@ -124,9 +124,9 @@ void PrtCnvSocketThread::cleanup()
}
// ---------------------------------------------------------------
// Initializes the variables.
// ---------------------------------------------------------------
int32_t PrtCnvSocketThread::init()
{
INFO_LOG(m_logger) << "PrtCnvSocketThread::init()";
@@ -140,10 +140,10 @@ int32_t PrtCnvSocketThread::init()
return 0;
}
// ---------------------------------------------------------------
// Connect as client to a TCP-server on ip-address configured
// as HostName and Port configured as Port
// ---------------------------------------------------------------
void PrtCnvSocketThread::connectSocket()
{
int sockState = m_Socket ? m_Socket->state() : -1;
@@ -152,7 +152,7 @@ void PrtCnvSocketThread::connectSocket()
{
if (m_Socket)
{
m_Socket->disconnectFromHost();
m_Socket->disconnectFromHost(); // Falls noch connected
if (m_Socket->state() != QAbstractSocket::UnconnectedState)
m_Socket->waitForDisconnected();
}
@@ -175,9 +175,9 @@ void PrtCnvSocketThread::connectSocket()
}
}
// ---------------------------------------------------------------
// Disconnects from TCP-server
// ---------------------------------------------------------------
void PrtCnvSocketThread::disconnectSocket()
{
m_Socket->disconnectFromHost();
@@ -186,46 +186,46 @@ void PrtCnvSocketThread::disconnectSocket()
}
// ---------------------------------------------------------------
// Will be called from Qt-Framework when we have connected to
// TCP-server
// ---------------------------------------------------------------
void PrtCnvSocketThread::connected()
{
INFO_LOG(m_logger) << "connected (implement connected() in inherited class, if you want use this signal...)";
}
// ---------------------------------------------------------------
// Will be called from Qt-Framework when we have disconnected
// to TCP-server
// ---------------------------------------------------------------
void PrtCnvSocketThread::disconnected()
{
INFO_LOG(m_logger) << "got signal 'disconnected' (implement disconnected() in inherited class, if you want use this signal...)";
}
// ---------------------------------------------------------------
// Will be called from Qt-Framework when we have have read
// data over socket
// ---------------------------------------------------------------
void PrtCnvSocketThread::readyRead()
{
INFO_LOG(m_logger) << "got signal 'newData' (implement newData() in inherited class, if you want use this signal...)";
}
// ---------------------------------------------------------------
// this slot is used for connection, disconnection and alive
// timeouts
// ---------------------------------------------------------------
void PrtCnvSocketThread::timeoutAliveAndConnection()
{
INFO_LOG(m_logger) << "got signal 'reconnectTimeout' (implement reconnectTimeout() in inherited class, if you want use this signal...)";
}
// ---------------------------------------------------------------
// Will be called from Qt-Framework when we have a socket-error
// ---------------------------------------------------------------
void PrtCnvSocketThread::error(QAbstractSocket::SocketError a_socketError)
{
switch (a_socketError)
@@ -237,7 +237,7 @@ void PrtCnvSocketThread::error(QAbstractSocket::SocketError a_socketError)
ERROR_LOG(m_logger) << getName() << ": RemoteHostClosedError";
break;
case QAbstractSocket::HostNotFoundError:
//ERROR_LOG(m_logger) << getName() << ": HostNotFoundError";
break;
default:
ERROR_LOG(m_logger) << getName() << ": got signal 'error(QAbstractSocket::SocketError=" << a_socketError << ")'";
@@ -245,28 +245,28 @@ void PrtCnvSocketThread::error(QAbstractSocket::SocketError a_socketError)
}
// ---------------------------------------------------------------
// Will be called from Qt-Framework when the host was found
// ---------------------------------------------------------------
void PrtCnvSocketThread::hostFound()
{
// INFO_LOG(m_logger) << "got signal 'hostFound' (implement hostFound() in inherited class, if you want use this signal...)";
}
// ---------------------------------------------------------------
// Will be called from Qt-Framework when socket-state has
// changed
// ---------------------------------------------------------------
void PrtCnvSocketThread::stateChanged(QAbstractSocket::SocketState a_socketState)
{
Q_UNUSED(a_socketState);
// INFO_LOG(m_logger) << "got signal 'stateChanged(" << ao_socketState << ")' (implement stateChanged() in inherited class, if you want use this signal...)";
}
// ---------------------------------------------------------------
// calls storeRadioTelegram of DbThread, see there
// ---------------------------------------------------------------
void PrtCnvSocketThread::storeRadioTelegram(const std::shared_ptr<N_CoPrtCnv::CoPrtCnvRadioTelegram> &a_telegram,
const uint32_t a_readCounter)
{
@@ -274,9 +274,9 @@ void PrtCnvSocketThread::storeRadioTelegram(const std::shared_ptr<N_CoPrtCnv::Co
}
// ---------------------------------------------------------------
// used to check whether the other side is still alive
// ---------------------------------------------------------------
void PrtCnvSocketThread::startAliveTimer()
{
m_ConnectionTimer->setInterval(m_AliveTimeout);
@@ -284,9 +284,9 @@ void PrtCnvSocketThread::startAliveTimer()
}
// ---------------------------------------------------------------
// used to retry connection
// ---------------------------------------------------------------
void PrtCnvSocketThread::startConnectionTimer()
{
m_ConnectionTimer->setInterval(m_ConnectTimeout);
@@ -294,10 +294,10 @@ void PrtCnvSocketThread::startConnectionTimer()
}
// ---------------------------------------------------------------
// used to abort connection, when normal disconnection is not
// successful
// ---------------------------------------------------------------
void PrtCnvSocketThread::startDisconnectionTimer()
{
m_ConnectionTimer->setInterval(m_DisconnectTimeout);
@@ -305,36 +305,36 @@ void PrtCnvSocketThread::startDisconnectionTimer()
}
// ---------------------------------------------------------------
// used for periodically ticks (i.e. for acks or sending
// nachforderungen)
// ---------------------------------------------------------------
void PrtCnvSocketThread::startTickTimer()
{
// INFO_LOG(m_logger) << "start timer";
m_TickTimer->setInterval(m_TickTimeout);
m_TickTimer->start();
}
// ---------------------------------------------------------------
// The counter will be set to a_startCounter if a_maxCounter
// is reached
// returns true if receive-counter is ok
// returns false if a telegram is repeated or lost
// ---------------------------------------------------------------
bool PrtCnvSocketThread::checkAndUpdateReceiveCounter(const uint32_t a_counter, const uint32_t a_maxCounter, const uint32_t a_startCounter)
{
TRACE_LOG(m_logger) << "checkAndUpdateReceiveCounter: " << a_counter << ", " << m_ReceiveCounter;
// check for wrap
if (a_maxCounter == ++m_ReceiveCounter)
{
m_ReceiveCounter = a_startCounter;
}
// has the counter the expected value?
if (m_ReceiveCounter != a_counter)
{
//if (m_ReceiveCounter != 1)
{
if (m_ReceiveCounter > a_counter)
{
@@ -349,13 +349,13 @@ bool PrtCnvSocketThread::checkAndUpdateReceiveCounter(const uint32_t a_counter,
}
#if 0
m_ReceiveCounter--;
return false;
return false; // failure
#else
m_ReceiveCounter = a_counter;
return true;
#endif
}
return true;
return true; // all ok
}
void PrtCnvSocketThread::readHostAdresses()
@@ -380,4 +380,4 @@ void PrtCnvSocketThread::readHostAdresses()
}
}
} // namespace PrtCnv
@@ -1,16 +1,16 @@
// **************************************************************************
//
// (C) Copyright 2009 Swiss SIMTEC AG
//
// **************************************************************************
//
// $HeadURL$
// $LastChangedBy$
// $LastChangedDate$
// $LastChangedRevision$
//
// Implementation of the Class PrtCnvSocketThread
// **************************************************************************
#pragma once
@@ -33,15 +33,30 @@ namespace PrtCnv
class PrtCnvDbThread;
class PrtCnvTelegramLogThread;
class PrtCnvInjectionThread;
/**
* The father-class of radio- and central-thread. It implements common-parts like
* - socket-connection and -disconnection
* - telegram-counter
* - timers
* - telegram-log
* - thread-state
*
* @author wia
* @version 1.0
* @created 26-Jun-2009 07:39:05
*/
class PrtCnvSocketThread : public PrtCnvThread
{
Q_OBJECT
public:
/**
* The different states for the state-event-machine
*
* @author wia
* @version 1.0
* @created 02-Jul-2009 14:16:49
*/
enum E_State
{
e_INITIAL,
@@ -51,139 +66,195 @@ namespace PrtCnv
e_DISCONNECTING,
e_REINIT
};
/**
* Constructor with pointer to thread-starter as parameter
*
* @param a_parent
*/
PrtCnvSocketThread(PrtCnvThreadStarter* a_parent, const char *loggerName);
~PrtCnvSocketThread();
/**
* Creates all subcomponents and connects signals to slots
*/
int32_t create(NGL::Settings *settings) override;
/**
* Creates a new socket to avoid getting old stuff from the
* former socket when reconnecting
*/
void createNewSocket();
/**
* Initializes the variables.
*/
int32_t init() override;
/**
* Deallocates subcomponents.
*/
int32_t destroy() override;
void cleanup();
protected:
/**
* this timer is used for controlling connection and disconnection
*/
QTimer *m_ConnectionTimer;
/**
* The TCP-socket
*/
QTcpSocket *m_Socket;
/**
* Return the hostname to connect to
*/
void readHostAdresses();
protected slots:
/**
* Will be called from Qt-Framework when we have connected to TCP-server
*/
virtual void connected();
/**
* Will be called from Qt-Framework when we have have read data over socket
*/
virtual void readyRead();
/**
* this slot is used for connection, disconnection and alive timeouts
*/
virtual void timeoutAliveAndConnection();
/**
* @brief Processes the periodical stuff, like broadcasts, acks
*/
virtual void timeoutTick() {}
/**
* Will be called from Qt-Framework when we have a socket-error
*
* @param a_socketError
*/
virtual void error(QAbstractSocket::SocketError a_socketError);
/**
* Will be called from Qt-Framework when the host was found
*/
virtual void hostFound();
/**
* Will be called from Qt-Framework when socket-state has changed
*
* @param a_socketState
*/
virtual void stateChanged(QAbstractSocket::SocketState a_socketState);
protected:
/**
* used for periodically send an ack to central
*/
QTimer *m_TickTimer;
/**
* Counter of received telegrams (only for sockets)
*/
uint32_t m_ReceiveCounter;
/**
* Acknowledged telegrams counter (only for sockets)
*/
uint32_t m_ReceiveAckCounter;
/**
* The state-event-machine state
*/
PrtCnvSocketThread::E_State m_State;
/**
* Pointer to DbThread
*/
PrtCnvDbThread *m_DbThread;
/**
* The time to wait until connection has happenend [ms]. After this time
* connection will be retryed.
*/
int32_t m_ConnectTimeout;
/**
* The time to wait until disconnection has happenend [ms]. After this time has
* elapsed it will be aborted.
*/
int32_t m_DisconnectTimeout;
/**
* The period to wait until timeout of connection is detected [ms]
*/
int32_t m_AliveTimeout;
/**
* The period of m_TickTimer [ms]
*/
int32_t m_TickTimeout;
/**
* True if the database has to be cleant up (used for fast empty of signal buffers)
*/
QAtomicInt m_DoCleanup;
/**
* for independent logging of telegrams
*/
PrtCnvTelegramLogThread *m_LogThread;
PrtCnvInjectionThread *m_InjectionThread;
/**
* A vector with hostname - port pairs to connect to
*/
QVector<QPair<QString, uint16_t> > m_hostAdresses;
/**
* The current index to connect to in m_hostAdresses
*/
int m_currentHostAdressIndex;
/**
* Will be called from Qt-Framework when we have disconnected to TCP-server
*/
virtual void disconnected();
/**
* used to check whether the other side is still alive
*/
void startAliveTimer();
/**
* used to retry connection
*/
void startConnectionTimer();
/**
* used to abort connection, when normal disconnection is not successful
*/
void startDisconnectionTimer();
/**
* Connect as client to a TCP-server on ip-address configured as HostName and Port
* configured as Port
*/
void connectSocket();
/**
* Disconnects from TCP-server
*/
void disconnectSocket();
/**
* used for periodically ticks (i.e. for acks or sending nachforderungen)
*/
void startTickTimer();
/**
* The counter will be set to a_startCounter if a_maxCounter is reached
* returns true if receive-counter is ok
* returns false if a telegram is repeated or lost
*
* @param a_counter
* @param a_maxCounter
* @param a_startCounter
*/
bool checkAndUpdateReceiveCounter(const uint32_t a_counter, const uint32_t a_maxCounter, const uint32_t a_startCounter);
/**
* calls storeRadioTelegram of DbThread, see there
*
* @param a_telegram
* @param a_readCounter
*/
void storeRadioTelegram(const std::shared_ptr<N_CoPrtCnv::CoPrtCnvRadioTelegram> &a_telegram, const uint32_t a_readCounter);
};
@@ -1,5 +1,10 @@
/**
* Helper to store/fetch a central telegram into/from database
* $Id$
* $HeadURL$
* $Author$
* Created by Christian Ehrlicher, SLSE, 2016-04-22
*/
#pragma once
@@ -19,20 +24,27 @@ public:
int writeCounter() const { return m_WriteCounter; }
/**
* Assigned central-telegram.
*/
std::shared_ptr<N_CoPrtCnv::CoPrtCnvCentralTelegram> m_CentralTelegram;
/**
* The number of unsuccessful attempts to send the telegram to central
*/
uint32_t m_Attempts = 0;
/**
* The counter while sending this telegram to central
*/
int m_WriteCounter = 0;
/**
* True if the telegram must be resent.
*/
bool m_DoResend = false;
/**
* True if the telegram must be deleted.
* Use this boolean only if you want delete a telegram as an exception (i.e.
* corrupt telegram, which cannot be sent)
*/
bool m_DoDelete = false;
};
@@ -1,5 +1,10 @@
/**
* Helper to store/fetch a radio telegram into/from database
* $Id$
* $HeadURL$
* $Author$
* Created by Christian Ehrlicher, SLSE, 2016-04-22
*/
#pragma once
@@ -12,20 +17,26 @@ class PrtCnvStoredRadioTelegram : public PrtCnv::PrtCnvStoredTelegram
public:
using PrtCnv::PrtCnvStoredTelegram::PrtCnvStoredTelegram;
/**
* The counter while reading this telegram from central
*/
int32_t m_ReadCounter = 0;
/**
* The broadcast index if it is a broadcast-telegram and it was sent first time,
* otherwise 0.
*/
uint16_t m_BroadcastIndex = 0;
/**
* The frame-counter while sending this telegram to radio.
*/
uint8_t m_WriteCounter = 0;
/**
* True if telegram must be deleted.
*/
bool m_DoDelete = false;
/**
* True if telegram was sent.
*/
bool m_IsSent = false;
};
@@ -1,5 +1,10 @@
/**
* Helper to store/fetch a telegram into/from database
* $Id$
* $HeadURL$
* $Author$
* Created by Christian Ehrlicher, SLSE, 2016-04-22
*/
#pragma once
@@ -1,17 +1,17 @@
// **************************************************************************
//
// (C) Copyright 2009 Swiss SIMTEC AG
//
// **************************************************************************
//
// $HeadURL$
// $LastChangedBy$
// $LastChangedDate$
// $LastChangedRevision$
//
// **************************************************************************
// manual class headers
#include "PrtCnvTelegramLogThread.hpp"
#include <CoPrtCnv/CoPrtCnvCentralTelegram.hpp>
#include <CoPrtCnv/CoPrtCnvLogHeader.hpp>
@@ -28,7 +28,7 @@
static int gettimeofday(struct timeval *__p, void *__t)
{
union {
unsigned long long ns100;
unsigned long long ns100; /*time since 1 Jan 1601 in 100ns units */
FILETIME ft;
} now;
@@ -48,7 +48,7 @@ static int gettimeofday(struct timeval *__p, void *__t)
namespace PrtCnv
{
// ---------------------------------------------------------------
PrtCnvTelegramLogThread::PrtCnvTelegramLogThread(PrtCnvThreadStarter* a_parent)
: PrtCnvThread(a_parent, "PrtCnvTelegramLogThread")
, m_DoLogCentralTelegram(true)
@@ -58,7 +58,7 @@ PrtCnvTelegramLogThread::PrtCnvTelegramLogThread(PrtCnvThreadStarter* a_parent)
m_Name = QStringLiteral("TelegramLog");
}
// ---------------------------------------------------------------
int32_t PrtCnvTelegramLogThread::create(NGL::Settings *settings)
{
PrtCnvThread::create(settings);
@@ -71,7 +71,7 @@ int32_t PrtCnvTelegramLogThread::create(NGL::Settings *settings)
}
// ---------------------------------------------------------------
int32_t PrtCnvTelegramLogThread::init()
{
PrtCnvThread::init();
@@ -86,7 +86,7 @@ int32_t PrtCnvTelegramLogThread::init()
if (!m_LogTelegramPathWithPrefix.endsWith(QLatin1Char('_')))
m_LogTelegramPathWithPrefix += QLatin1Char('_');
// create the telegram-log-path when it not yet exists
QFileInfo fileInfo(m_LogTelegramPathWithPrefix);
QDir dir;
dir.mkpath(fileInfo.absolutePath());
@@ -101,9 +101,9 @@ static inline int setSend(int protocol, bool bIsSend)
return (protocol | (bIsSend ? N_CoPrtCnv::CoPrtCnvLogHeader::e_DestSend : N_CoPrtCnv::CoPrtCnvLogHeader::e_DestReceive));
}
// ---------------------------------------------------------------
// Writes a received or sent central-telegram into log-file
// ---------------------------------------------------------------
void PrtCnvTelegramLogThread::writeCentralTelegramLog(N_CoPrtCnv::CoPrtCnvCentralTelegram *a_centralTelegram, bool a_isSend, int a_priority)
{
if (!m_DoLogCentralTelegram)
@@ -115,9 +115,9 @@ void PrtCnvTelegramLogThread::writeCentralTelegramLog(N_CoPrtCnv::CoPrtCnvCentra
}
// ---------------------------------------------------------------
// Writes a received or sent wls-telegram into log-file
// ---------------------------------------------------------------
void PrtCnvTelegramLogThread::writeWlsTelegramLog(const TrainingAreaBase::TetraIcd::TrainingAreaTelegram *tele, bool a_isSend, int a_priority)
{
if (!m_DoLogWlsTelegram)
@@ -130,9 +130,9 @@ void PrtCnvTelegramLogThread::writeWlsTelegramLog(const TrainingAreaBase::TetraI
}
// ---------------------------------------------------------------
// Writes a received or sent radio-telegram into log-file
// ---------------------------------------------------------------
void PrtCnvTelegramLogThread::writeRadioTelegramLog(const QByteArray &tele, bool a_isSend, int a_priority)
{
if (!m_DoLogRadioTelegram)
@@ -144,27 +144,27 @@ void PrtCnvTelegramLogThread::writeRadioTelegramLog(const QByteArray &tele, bool
}
// ---------------------------------------------------------------
// Writes the telegram to the file
// ---------------------------------------------------------------
void PrtCnvTelegramLogThread::writeTelegramLog(const QByteArray &a_data, int a_protocolType, int a_priority)
{
// get time with microseconds
timeval tv;
gettimeofday(&tv, nullptr);
uint64_t exactTime = tv.tv_sec;
exactTime = exactTime << 32;
exactTime += tv.tv_usec;
// generate the filename of the telegram-file: "PrefixYYMMDD_HH.krlog"
QString fileName = QStringLiteral("%1%2.krlog")
.arg(m_LogTelegramPathWithPrefix, QDateTime::fromSecsSinceEpoch(tv.tv_sec).toString(QStringLiteral("yyMMdd_hh")));
// open the log-file
QFile telegramFile(fileName);
(void)telegramFile.open(QIODevice::WriteOnly | QIODevice::Append);
// write header
N_CoPrtCnv::CoPrtCnvLogHeader lh;
lh.m_Length = a_data.size() + sizeof(N_CoPrtCnv::CoPrtCnvLogHeader);
lh.m_Version = 3;
@@ -174,9 +174,9 @@ void PrtCnvTelegramLogThread::writeTelegramLog(const QByteArray &a_data, int a_p
lh.m_Reserved = 0;
telegramFile.write(reinterpret_cast<const char*>(&lh), sizeof(N_CoPrtCnv::CoPrtCnvLogHeader));
// write telegram-data
telegramFile.write(a_data);
telegramFile.close();
}
}
} // namespace PrtCnv
Loaded 100 of 112 files, more files were not shown because too many files have changed in this diff. Show more