PR-777 Add the data exchange for modbus

This commit is contained in:
Garret Fick 2019-11-18 14:34:10 -05:00
parent 9458b89d85
commit 465d9bcefc
5 changed files with 63 additions and 25 deletions

View File

@ -241,7 +241,7 @@ int write_holding_register(unsigned char* buffer, int buffer_size, IndexedStrate
{
int16_t start = mb_to_word(buffer[8], buffer[9]);
modbus_errno err = strategy->WriteHoldingRegister(start, buffer + 9, 2);
modbus_errno err = strategy->WriteHoldingRegister(start, buffer + 9);
if (err) {
return modbus_error(buffer, ERR_ILLEGAL_DATA_ADDRESS);
}
@ -308,7 +308,7 @@ int write_multiple_registers(unsigned char* buffer, int buffer_size, IndexedStra
/// @param buffer_size
/// @param user_data The mapping strategy.
/// @return size of the response message in bytes
int process_modbus_message(unsigned char *buffer, int buffer_size, void* user_data)
int modbus_process_message(unsigned char *buffer, int buffer_size, void* user_data)
{
auto strategy = reinterpret_cast<IndexedStrategy*>(user_data);
int message_length = 0;
@ -376,6 +376,29 @@ int process_modbus_message(unsigned char *buffer, int buffer_size, void* user_da
return message_length;
}
/// Arguments that are passed to the thread to exchange modbus data with the
/// runtime.
struct ModbusExchangeArgs {
IndexedStrategy* strategy;
volatile bool* run;
std::chrono::milliseconds interval;
};
/// The main function for the thread that is responsible for exchanging
/// modbus data with the located variables.
void* modbus_exchange_data(void* args) {
auto exchange_args = reinterpret_cast<ModbusExchangeArgs*>(args);
while (*exchange_args->run) {
spdlog::trace("Exchanging modbus master data");
exchange_args->strategy->Exchange();
this_thread::sleep_for(exchange_args->interval);
}
delete exchange_args;
return nullptr;
}
/// Container for reading in configuration from the config.ini
/// This is populated with values from the config file.
@ -447,8 +470,24 @@ int8_t modbus_slave_run(std::unique_ptr<std::istream, std::function<void(std::is
IndexedStrategy strategy(bindings);
pthread_t exchange_data_thread;
auto args = new ModbusExchangeArgs {
.strategy=&strategy,
.run=&run,
.interval=std::chrono::milliseconds(100)
};
int ret = pthread_create(&exchange_data_thread, NULL, modbus_exchange_data, args);
if (ret == 0) {
pthread_detach(exchange_data_thread);
} else {
delete args;
}
spdlog::info("Starting modbus slave on port {}", config.port);
startServer(config.port, run, &process_modbus_message, &strategy);
startServer(config.port, run, &modbus_process_message, &strategy);
pthread_join(exchange_data_thread, nullptr);
return 0;
}

View File

@ -23,7 +23,7 @@
class GlueVariablesBinding;
/// @brief Process an individual modbus message.
int process_modbus_message(unsigned char *buffer, int buffer_size,
int modbus_process_message(unsigned char *buffer, int buffer_size,
void* user_data);
/// @brief Start the modbus slave server.

View File

@ -132,8 +132,8 @@ int createSocket(uint16_t port)
////////////////////////////////////////////////////////////////////////////////
/// @brief Blocking call. Wait here for the client to connect.
/// @param socket_fd
/// @param protocol_type
/// @param socket_fd The socket file descriptor.
/// @param run_server A flag to terminate this client.
/// @return file descriptor to communicate with the client
////////////////////////////////////////////////////////////////////////////////
int waitForClient(int socket_fd, volatile bool& run_server)
@ -153,6 +153,7 @@ int waitForClient(int socket_fd, volatile bool& run_server)
SetSocketBlockingEnabled(client_fd, true);
break;
}
this_thread::sleep_for(chrono::milliseconds(100));
}
@ -228,16 +229,14 @@ void *handleConnections(void *arguments)
delete args;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief Function to start the server.
/// @brief Function to start a socket server.
///
/// It receives the port number as argument and
/// creates an infinite loop to listen and parse the messages sent by the
/// clients
/// @param port
/// @param protocol_type
/// @see stopServer()
////////////////////////////////////////////////////////////////////////////////
/// @param port The port to listen on.
/// @param process_message A function to run to process socket messages.
/// @param user_data Passed into the process_message function as client data.
void startServer(uint16_t port, volatile bool& run_server, process_message_fn process_message, void* user_data)
{
int socket_fd, client_fd;

View File

@ -98,7 +98,7 @@ SCENARIO("indexed_strategy", "")
{
int_val = 0;
uint8_t buffer[2] = { 0, 1 };
REQUIRE(strategy.WriteHoldingRegister(0, buffer, 2) == 0);
REQUIRE(strategy.WriteHoldingRegister(0, buffer) == 0);
strategy.Exchange();
REQUIRE(int_val == 1);
}
@ -139,7 +139,7 @@ SCENARIO("indexed_strategy", "")
{
int_val = 0;
uint8_t buffer[2] = { 0, 1 };
REQUIRE(strategy.WriteHoldingRegister(1024, buffer, 2) == 0);
REQUIRE(strategy.WriteHoldingRegister(1024, buffer) == 0);
strategy.Exchange();
REQUIRE(int_val == 1);
}

View File

@ -65,7 +65,7 @@ SCENARIO("slave", "")
{
// FS, Start, Num, CRC
uint8_t buffer[BUF_SIZE] = { HEADER, 1, 0, 0, 0, 9, 0 };
int size = process_modbus_message(buffer, BUF_SIZE, &strategy);
int size = modbus_process_message(buffer, BUF_SIZE, &strategy);
REQUIRE(buffer[7] == 0x01);
REQUIRE(buffer[8] == 0x02);
REQUIRE(buffer[9] == 0xCD);
@ -77,7 +77,7 @@ SCENARIO("slave", "")
{
// FS, Start, Num, CRC
uint8_t buffer[BUF_SIZE] = { HEADER, 1, 0, 1, 0, 8, 0 };
int size = process_modbus_message(buffer, BUF_SIZE, &strategy);
int size = modbus_process_message(buffer, BUF_SIZE, &strategy);
REQUIRE(buffer[7] == 0x01);
REQUIRE(buffer[8] == 0x01);
REQUIRE(buffer[9] == 0xE6);
@ -88,7 +88,7 @@ SCENARIO("slave", "")
{
// FS, Start, Num, By, Values, CRC
uint8_t buffer[BUF_SIZE] = { HEADER, 15, 0, 0, 0, 9, 2, 0xCD, 0x01, 0 };
int size = process_modbus_message(buffer, BUF_SIZE, &strategy);
int size = modbus_process_message(buffer, BUF_SIZE, &strategy);
REQUIRE(buffer[7] == 15);
REQUIRE(buffer[8] == 0);
REQUIRE(buffer[9] == 0);
@ -135,7 +135,7 @@ SCENARIO("slave", "")
{
// FS, Start, Num, CRC
uint8_t buffer[BUF_SIZE] = { HEADER, 2, 0, 0, 0, 9, 0 };
int size = process_modbus_message(buffer, BUF_SIZE, &strategy);
int size = modbus_process_message(buffer, BUF_SIZE, &strategy);
REQUIRE(buffer[7] == 0x02);
REQUIRE(buffer[8] == 0x02);
REQUIRE(buffer[9] == 0xCD);
@ -147,7 +147,7 @@ SCENARIO("slave", "")
{
// FS, Start, Num, CRC
uint8_t buffer[BUF_SIZE] = { HEADER, 2, 0, 1, 0, 8, 0 };
int size = process_modbus_message(buffer, BUF_SIZE, &strategy);
int size = modbus_process_message(buffer, BUF_SIZE, &strategy);
REQUIRE(buffer[7] == 0x02);
REQUIRE(buffer[8] == 0x01);
REQUIRE(buffer[9] == 0xE6);
@ -176,7 +176,7 @@ SCENARIO("slave", "")
{
// FS, Start, Num, CRC
uint8_t buffer[BUF_SIZE] = { HEADER, 3, 0, 0, 0, 1, 0 };
int size = process_modbus_message(buffer, BUF_SIZE, &strategy);
int size = modbus_process_message(buffer, BUF_SIZE, &strategy);
REQUIRE(buffer[7] == 0x03);
REQUIRE(buffer[8] == 0x02);
REQUIRE(buffer[9] == 0x00);
@ -188,7 +188,7 @@ SCENARIO("slave", "")
{
// FS, Start, Num, CRC
uint8_t buffer[BUF_SIZE] = { HEADER, 3, 0x04, 0, 0, 1, 0 };
int size = process_modbus_message(buffer, BUF_SIZE, &strategy);
int size = modbus_process_message(buffer, BUF_SIZE, &strategy);
REQUIRE(buffer[7] == 0x03);
REQUIRE(buffer[8] == 0x02);
REQUIRE(buffer[9] == 0x00);
@ -200,7 +200,7 @@ SCENARIO("slave", "")
{
// FS, Start, Val, CRC
uint8_t buffer[BUF_SIZE] = { HEADER, 6, 0, 0, 0, 0x03, 0 };
int size = process_modbus_message(buffer, BUF_SIZE, &strategy);
int size = modbus_process_message(buffer, BUF_SIZE, &strategy);
REQUIRE(buffer[7] == 0x06);
REQUIRE(buffer[8] == 0x00);
REQUIRE(buffer[9] == 0x00);
@ -213,7 +213,7 @@ SCENARIO("slave", "")
{
// FS, Start, Num, By, Val, CRC
uint8_t buffer[BUF_SIZE] = { HEADER, 16, 0, 0, 0, 1, 2, 0, 0x02, 0 };
int size = process_modbus_message(buffer, BUF_SIZE, &strategy);
int size = modbus_process_message(buffer, BUF_SIZE, &strategy);
REQUIRE(buffer[7] == 16);
REQUIRE(buffer[8] == 0x00);
REQUIRE(buffer[9] == 0x00);
@ -240,7 +240,7 @@ SCENARIO("slave", "")
{
// FS, Start, Num, CRC
uint8_t buffer[BUF_SIZE] = { HEADER, 4, 0, 0, 0, 1, 0 };
int size = process_modbus_message(buffer, BUF_SIZE, &strategy);
int size = modbus_process_message(buffer, BUF_SIZE, &strategy);
REQUIRE(buffer[7] == 0x04);
REQUIRE(buffer[8] == 0x02);
REQUIRE(buffer[9] == 0x00);
@ -270,7 +270,7 @@ SCENARIO("slave", "")
{
// FS, Start, Num, CRC
uint8_t buffer[BUF_SIZE] = { HEADER, 5, 0, 0, 0xFF, 0, 0 };
int size = process_modbus_message(buffer, BUF_SIZE, &strategy);
int size = modbus_process_message(buffer, BUF_SIZE, &strategy);
REQUIRE(buffer[7] == 0x05);
REQUIRE(buffer[8] == 0x00);
REQUIRE(buffer[9] == 0x00);