Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

IEC-104 server and client updates #22

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,14 @@ void ClientConnection::start(std::shared_ptr<ClientConnection> clientConnection)
}
}

int ClientConnection::convertBoolToDPValue(bool value)
{
if (value == 0)
return IEC60870_DOUBLE_POINT_OFF;
else
return IEC60870_DOUBLE_POINT_ON;
}

StatusMessage ClientConnection::readRegisterByTag(const std::string& tag, comms::RegisterDescriptor& rd)
{
auto status = getRegisterDescriptorByTag(tag, rd) ? STATUS_SUCCESS : STATUS_FAIL;
Expand All @@ -73,7 +81,7 @@ StatusMessage ClientConnection::readRegisterByTag(const std::string& tag, comms:
return sm;
}

StatusMessage ClientConnection::writeBinary(const std::string& tag, bool value)
StatusMessage ClientConnection::writeBinary(const std::string& tag, bool bvalue)
{
StatusMessage sm = STATUS_INIT;
comms::RegisterDescriptor rd;
Expand All @@ -86,15 +94,18 @@ StatusMessage ClientConnection::writeBinary(const std::string& tag, bool value)
return sm;
}

// Write boolean using protocol
std::cout << "Send single command C_SC_NA_1: " << tag << " -- " << value << std::endl;
InformationObject sc = (InformationObject)
SingleCommand_create(NULL, rd.mRegisterAddress, value, true, 0);
CS104_Connection_sendProcessCommandEx(mConnection, CS101_COT_ACTIVATION, 1, sc);
InformationObject_destroy(sc);
// Convert boolean to double point value
int value = ClientConnection::convertBoolToDPValue(bvalue);

// Update local data so we don't have to wait until the next poll
updateBinary(rd.mRegisterAddress, value);
// Write double point using protocol
std::cout << "Send double command C_DC_NA_1: " << tag << " -- " << bvalue << std::endl;
InformationObject dc = (InformationObject)
DoubleCommand_create(NULL, rd.mRegisterAddress, value, true, 0);
CS104_Connection_sendProcessCommandEx(mConnection, CS101_COT_ACTIVATION, 1, dc);
InformationObject_destroy(dc);

// Update local data so we don't have to wait until the next poll; save boolean to datastore
updateBinary(rd.mRegisterAddress, bvalue);
return sm;
}

Expand Down Expand Up @@ -194,29 +205,45 @@ bool ClientConnection::asduReceivedHandler(void* parameter, int address, CS101_A
}
}
// Binary values
else if (CS101_ASDU_getTypeID(asdu) == M_SP_NA_1) {
printf(" single point information:\n");
else if (CS101_ASDU_getTypeID(asdu) == M_DP_NA_1) {
printf(" double point information:\n");

int i;

for (i = 0; i < CS101_ASDU_getNumberOfElements(asdu); i++) {

SinglePointInformation io =
(SinglePointInformation) CS101_ASDU_getElement(asdu, i);
DoublePointInformation io =
(DoublePointInformation) CS101_ASDU_getElement(asdu, i);

uint16_t addr = InformationObject_getObjectAddress((InformationObject) io);
bool status = SinglePointInformation_getValue((SinglePointInformation) io);
DoublePointValue dp_value = DoublePointInformation_getValue((DoublePointInformation) io);

bool status = 0;
if (dp_value == IEC60870_DOUBLE_POINT_OFF)
{
status = 0;
}
else if (dp_value == IEC60870_DOUBLE_POINT_ON)
{
status = 1;
}
else
{
printf("IOA: %i- Double point value is in indeterminate state..defaulting to 0\n", addr);
status = 0;
}
printf(" IOA: %i value: %i\n", addr, status);

gClientConnection->updateBinary(addr, status);

SinglePointInformation_destroy(io);
DoublePointInformation_destroy(io);
}
}

return true;
}


} // namespace iec60870
} // namespace comms
} // namespace bennu
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@

#include "bennu/devices/modules/comms/base/Common.hpp"
#include "bennu/devices/modules/comms/iec60870-5/protocol/src/inc/api/cs104_connection.h"
#include "bennu/devices/modules/comms/iec60870-5/protocol/src/inc/api/cs101_information_objects.h"


namespace bennu {
Expand Down Expand Up @@ -74,13 +75,16 @@ class ClientConnection : public std::enable_shared_from_this<ClientConnection>
static void connectionHandler(void* parameter, CS104_Connection connection, CS104_ConnectionEvent event);
static bool asduReceivedHandler(void* parameter, int address, CS101_ASDU asdu);

static int convertBoolToDPValue(bool value);

private:
bool mRunning;
std::string mRtuEndpoint; // IP/Port or DevName of remote RTU
CS104_Connection mConnection; // 104 connection object
std::map<std::uint16_t, std::string> mBinaryAddressToTagMapping;
std::map<std::uint16_t, std::string> mAnalogAddressToTagMapping;
std::map<std::string, comms::RegisterDescriptor> mRegisters;


};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ void DataHandler::parseServerTree(std::shared_ptr<Server> server, const ptree& t
std::string endpoint = tree.get<std::string>("endpoint");
std::string log = tree.get<std::string>("event-logging", "iec60870-5-104-server.log");
server->configureEventLogging(log);
std::string subtype = tree.get<std::string>("subtype");
auto binaryInputs = tree.equal_range("binary-input");
for (auto iter = binaryInputs.first; iter != binaryInputs.second; ++iter)
{
Expand Down Expand Up @@ -88,7 +89,7 @@ void DataHandler::parseServerTree(std::shared_ptr<Server> server, const ptree& t
// Initialize and start 104 server
// - Pass server pointer to Server::start() so Server::gServer can be set statically
// and used inside static 104 handlers
server->start(endpoint, server, rPollRate);
server->start(endpoint, server, rPollRate, subtype);
}
catch (ptree_bad_path& e)
{
Expand Down
Loading