Skip to content

Commit

Permalink
- added support for monitoring types with CP56Time2a time tags
Browse files Browse the repository at this point in the history
Signed-off-by: Michael Zillgith <[email protected]>
  • Loading branch information
mzillgith committed Oct 4, 2022
1 parent 7234139 commit 6cd2af9
Show file tree
Hide file tree
Showing 4 changed files with 785 additions and 30 deletions.
4 changes: 4 additions & 0 deletions include/iec104_datapoint.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ class IEC104DataPoint

bool isCommand();

bool isMessageTypeMatching(int msgTypeId);

bool isMatchingCommand(int typeId);

int m_ca;
Expand Down Expand Up @@ -111,6 +113,8 @@ class IEC104DataPoint
unsigned int refIoa : 24;
} param_mv; /* IEC60870_TYPE_PARAM_MV_... */

struct sCP56Time2a ts;

} m_value;
};

Expand Down
107 changes: 94 additions & 13 deletions src/iec104.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,11 @@ IEC104Server::m_getDataPoint(int ca, int ioa, int typeId)

IEC104DataPoint* dp = m_exchangeDefinitions[ca][ioa];

if (dp) {
if (dp->isMessageTypeMatching(typeId) == false)
dp = nullptr;
}

return dp;
}

Expand Down Expand Up @@ -220,6 +225,17 @@ IEC104Server::_monitoringThread()
}
}

static void
setTimestamp(CP56Time2a destTime, CP56Time2a srcTime)
{
if (srcTime) {
memcpy(destTime, srcTime, sizeof(struct sCP56Time2a));
}
else {
CP56Time2a_createFromMsTimestamp(destTime, Hal_getTimeInMs());
}
}

void
IEC104Server::m_updateDataPoint(IEC104DataPoint* dp, IEC60870_5_TypeID typeId, DatapointValue* value, CP56Time2a ts, uint8_t quality)
{
Expand All @@ -235,6 +251,10 @@ IEC104Server::m_updateDataPoint(IEC104DataPoint* dp, IEC60870_5_TypeID typeId, D
}

dp->m_value.sp.quality = quality;

if (typeId == M_SP_TB_1) {
setTimestamp(&(dp->m_value.ts), ts);
}
}

break;
Expand All @@ -247,6 +267,10 @@ IEC104Server::m_updateDataPoint(IEC104DataPoint* dp, IEC60870_5_TypeID typeId, D
}

dp->m_value.dp.quality = quality;

if (typeId == M_DP_TB_1) {
setTimestamp(&(dp->m_value.ts), ts);
}
}

break;
Expand All @@ -260,6 +284,10 @@ IEC104Server::m_updateDataPoint(IEC104DataPoint* dp, IEC60870_5_TypeID typeId, D
}

dp->m_value.stepPos.quality = quality;

if (typeId == M_ST_TB_1) {
setTimestamp(&(dp->m_value.ts), ts);
}
}
break;

Expand All @@ -271,6 +299,10 @@ IEC104Server::m_updateDataPoint(IEC104DataPoint* dp, IEC60870_5_TypeID typeId, D
}

dp->m_value.mv_normalized.quality = quality;

if (typeId == M_ME_TD_1) {
setTimestamp(&(dp->m_value.ts), ts);
}
}

break;
Expand All @@ -283,6 +315,10 @@ IEC104Server::m_updateDataPoint(IEC104DataPoint* dp, IEC60870_5_TypeID typeId, D
}

dp->m_value.mv_scaled.quality = quality;

if (typeId == M_ME_TE_1) {
setTimestamp(&(dp->m_value.ts), ts);
}
}

break;
Expand All @@ -295,6 +331,10 @@ IEC104Server::m_updateDataPoint(IEC104DataPoint* dp, IEC60870_5_TypeID typeId, D
}

dp->m_value.mv_short.quality = quality;

if (typeId == M_ME_TF_1) {
setTimestamp(&(dp->m_value.ts), ts);
}
}

break;
Expand All @@ -319,29 +359,71 @@ IEC104Server::m_enqueueSpontDatapoint(IEC104DataPoint* dp, CS101_CauseOfTransmis
}
break;

case M_SP_TB_1:
{
io = (InformationObject)SinglePointWithCP56Time2a_create(NULL, dp->m_ioa, dp->m_value.sp.value, dp->m_value.sp.quality, &(dp->m_value.ts));
}
break;

case M_DP_NA_1:
{
io = (InformationObject)DoublePointInformation_create(NULL, dp->m_ioa, (DoublePointValue)dp->m_value.dp.quality, dp->m_value.dp.quality);
}
break;

case M_DP_TB_1:
{
io = (InformationObject)DoublePointWithCP56Time2a_create(NULL, dp->m_ioa, (DoublePointValue)dp->m_value.dp.quality, dp->m_value.dp.quality, &(dp->m_value.ts));
}
break;

case M_ST_NA_1:
{
io = (InformationObject)StepPositionInformation_create(NULL, dp->m_ioa, dp->m_value.stepPos.posValue, dp->m_value.stepPos.transient, dp->m_value.stepPos.quality);
}
break;

case M_ST_TB_1:
{
io = (InformationObject)StepPositionWithCP56Time2a_create(NULL, dp->m_ioa, dp->m_value.stepPos.posValue, dp->m_value.stepPos.transient, dp->m_value.stepPos.quality, &(dp->m_value.ts));
}
break;

case M_ME_NA_1:
{
io = (InformationObject)MeasuredValueNormalized_create(NULL, dp->m_ioa, dp->m_value.mv_normalized.value, dp->m_value.mv_normalized.quality);
}
break;

case M_ME_TD_1:
{
io = (InformationObject)MeasuredValueNormalizedWithCP56Time2a_create(NULL, dp->m_ioa, dp->m_value.mv_normalized.value, dp->m_value.mv_normalized.quality, &(dp->m_value.ts));
}
break;

case M_ME_NB_1:
{
io = (InformationObject)MeasuredValueScaled_create(NULL, dp->m_ioa, dp->m_value.mv_scaled.value, dp->m_value.mv_scaled.quality);
}
break;

case M_ME_TE_1:
{
io = (InformationObject)MeasuredValueScaledWithCP56Time2a_create(NULL, dp->m_ioa, dp->m_value.mv_normalized.value, dp->m_value.mv_normalized.quality, &(dp->m_value.ts));
}
break;

case M_ME_NC_1:
{
io = (InformationObject)MeasuredValueShort_create(NULL, dp->m_ioa, dp->m_value.mv_short.value, dp->m_value.mv_short.quality);
}
break;
break;

case M_ME_TF_1:
{
io = (InformationObject)MeasuredValueShortWithCP56Time2a_create(NULL, dp->m_ioa, dp->m_value.mv_short.value, dp->m_value.mv_short.quality, &(dp->m_value.ts));
}
break;

default:
m_log->error("Unsupported type ID %i", typeId);
Expand Down Expand Up @@ -833,10 +915,8 @@ IEC104Server::send(const vector<Reading*>& readings)

for (Datapoint* dp : dataPoints) {

if (dp->getName() == "data_object") {

// m_log->info("Received data_object");

if (dp->getName() == "data_object")
{
int ca = -1;
int ioa = -1;
CS101_CauseOfTransmission cot = CS101_COT_UNKNOWN_COT;
Expand Down Expand Up @@ -871,6 +951,7 @@ IEC104Server::send(const vector<Reading*>& readings)
}
else if (objDp->getName() == "do_type") {
type = IEC104DataPoint::getTypeIdFromString(attrVal.toStringValue());
printf("TYPE: %s (%i)\n", attrVal.toStringValue().c_str(), type);
}
else if (objDp->getName() == "do_value") {
value = new DatapointValue(attrVal);
Expand Down Expand Up @@ -913,8 +994,6 @@ IEC104Server::send(const vector<Reading*>& readings)
}
}

// m_log->info(" data_object - CA: %i IOA: %i COT: %i", ca, ioa, cot);

if (cot == CS101_COT_ACTIVATION_CON)
{
handleActCon(type, ca, ioa);
Expand All @@ -925,14 +1004,16 @@ IEC104Server::send(const vector<Reading*>& readings)
}
else if (ca != -1 && ioa != -1 && cot != CS101_COT_UNKNOWN_COT && type != -1) {

IEC104DataPoint* dp = m_getDataPoint(ca, ioa, 0);
IEC104DataPoint* dp = m_getDataPoint(ca, ioa, type);

if (dp) {

CP56Time2a ts = NULL;

struct sCP56Time2a _ts;

if (hasTimestamp) {
ts = CP56Time2a_createFromMsTimestamp(NULL, timestamp);
ts = CP56Time2a_createFromMsTimestamp(&_ts, timestamp);

if (ts) {
CP56Time2a_setInvalid(ts, ts_iv);
Expand All @@ -949,7 +1030,7 @@ IEC104Server::send(const vector<Reading*>& readings)
}
}
else {
m_log->error("data point %i:%i not found", ca, ioa);
m_log->error("data point %i:%i not found or type not expected", ca, ioa);
}
}

Expand Down Expand Up @@ -995,14 +1076,14 @@ IEC104Server::rawMessageHandler(void* parameter,
int msgSize, bool sent)
{
if (sent)
Logger::getLogger()->info("SEND: ");
Logger::getLogger()->debug("SEND: ");
else
Logger::getLogger()->info("RCVD: ");
Logger::getLogger()->debug("RCVD: ");

int i;
for (i = 0; i < msgSize; i++)
{
Logger::getLogger()->info("%02x ", msg[i]);
Logger::getLogger()->debug("%02x ", msg[i]);
}
}

Expand Down
75 changes: 71 additions & 4 deletions src/iec104_datapoint.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -186,29 +186,96 @@ IEC104DataPoint::typeIdToDataType(int typeId)
return dataType;
}

int IEC104DataPoint::getTypeIdFromString(std::string typeIdStr)
int
IEC104DataPoint::getTypeIdFromString(std::string typeIdStr)
{
return mapAsduTypeId[typeIdStr];
}

std::string IEC104DataPoint::getStringFromTypeID(int typeId)
std::string
IEC104DataPoint::getStringFromTypeID(int typeId)
{
return mapAsduTypeIdStr[typeId];
}

bool IEC104DataPoint::isMonitoringType()
bool
IEC104DataPoint::isMonitoringType()
{
if (m_isCommand)
return false;
else
return true;
}

bool IEC104DataPoint::isCommand()
bool
IEC104DataPoint::isCommand()
{
return m_isCommand;
}

bool
IEC104DataPoint::isMessageTypeMatching(int expectedType)
{
bool isMatching = false;

switch (expectedType) {

case M_SP_NA_1:
case M_SP_TB_1:
if (m_type == IEC60870_TYPE_SP) {
isMatching = true;
}

break;

case M_DP_NA_1:
case M_DP_TB_1:
if (m_type == IEC60870_TYPE_DP) {
isMatching = true;
}

break;

case M_ME_NA_1:
case M_ME_TD_1:
if (m_type == IEC60870_TYPE_NORMALIZED) {
isMatching = true;
}

break;

case M_ME_NB_1:
case M_ME_TE_1:
if (m_type == IEC60870_TYPE_SCALED) {
isMatching = true;
}

break;

case M_ME_NC_1:
case M_ME_TF_1:
if (m_type == IEC60870_TYPE_SHORT) {
isMatching = true;
}

break;

case M_ST_NA_1:
case M_ST_TB_1:
if (m_type == IEC60870_TYPE_STEP_POS) {
isMatching = true;
}

break;

default:
//Type not supported
break;
}

return isMatching;
}

bool IEC104DataPoint::isMatchingCommand(int typeId)
{
if (isCommand()) {
Expand Down
Loading

0 comments on commit 6cd2af9

Please sign in to comment.