Created
July 20, 2016 21:20
-
-
Save fernandoc1/25eee61378b0c190d9a4e3b6d2028818 to your computer and use it in GitHub Desktop.
modbus server with bit pooling.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <unistd.h> | |
#include <string.h> | |
#include <stdlib.h> | |
#include <errno.h> | |
#include <modbus/modbus.h> | |
#include <iostream> | |
#include <thread> | |
#include <mutex> | |
#include <chrono> | |
#include <vector> | |
#include <cstdio> | |
#include <cstdlib> | |
class ModbusAgent | |
{ | |
modbus_t* context; | |
std::mutex poolRegisterMutex; | |
std::thread* poolThread; | |
bool pooling; | |
template <typename T> int checkVectorSize(int initialPosition, int finalPosition, std::vector<T>& values) | |
{ | |
int expectedSize = finalPosition - initialPosition; | |
if(values.size() != expectedSize) | |
{ | |
values.resize(expectedSize); | |
} | |
return expectedSize; | |
} | |
void poolingBitThread(int position) | |
{ | |
uint8_t lastReadValue = 0; | |
while(pooling) | |
{ | |
uint8_t regValue = 0; | |
if(modbus_flush(this->context) != 0) | |
{ | |
throw std::runtime_error("Flush pooling register failed"); | |
} | |
int numOfRegistersRead = modbus_read_bits(this->context, position, 1, ®Value); | |
if(numOfRegistersRead == 1) | |
{ | |
if(lastReadValue != regValue) | |
{ | |
std::cout << "Value changed to " << (int)regValue << std::endl; | |
lastReadValue = regValue; | |
} | |
} | |
else | |
{ | |
throw std::runtime_error("Pooling register failed"); | |
} | |
std::this_thread::sleep_for(std::chrono::milliseconds(500)); | |
} | |
} | |
void poolingRegisterThread(int position) | |
{ | |
uint16_t lastReadValue = 0; | |
while(pooling) | |
{ | |
uint16_t regValue = 0; | |
if(modbus_flush(this->context) != 0) | |
{ | |
throw std::runtime_error("Flush pooling register failed"); | |
} | |
int numOfRegistersRead = modbus_read_registers(this->context, position, 1, ®Value); | |
if(numOfRegistersRead == 1) | |
{ | |
if(lastReadValue != regValue) | |
{ | |
std::cout << "Value changed to " << regValue << std::endl; | |
lastReadValue = regValue; | |
} | |
} | |
else | |
{ | |
throw std::runtime_error("Pooling register failed"); | |
} | |
std::this_thread::sleep_for(std::chrono::seconds(1)); | |
} | |
} | |
public: | |
ModbusAgent(std::string ip, uint16_t port) | |
: context(modbus_new_tcp(ip.c_str(), port)) | |
, pooling(true) | |
, poolThread(NULL) | |
{ | |
if(modbus_connect(this->context) == -1) | |
{ | |
throw std::runtime_error("Error while connecting to Modbus module"); | |
} | |
} | |
~ModbusAgent() | |
{ | |
modbus_close(this->context); | |
modbus_free(this->context); | |
} | |
int readRegisters(int initialPosition, int finalPosition, std::vector<uint16_t>& values) | |
{ | |
checkVectorSize(initialPosition, finalPosition, values); | |
return modbus_read_registers(this->context, initialPosition, finalPosition, values.data()); | |
} | |
int readBits(int initialPosition, int finalPosition, std::vector<uint8_t>& values) | |
{ | |
checkVectorSize(initialPosition, finalPosition, values); | |
return modbus_read_bits(this->context, initialPosition, finalPosition, values.data()); | |
} | |
int readInputBits(int initialPosition, int finalPosition, std::vector<uint8_t>& values) | |
{ | |
checkVectorSize(initialPosition, finalPosition, values); | |
return modbus_read_input_bits(this->context, initialPosition, finalPosition, values.data()); | |
} | |
virtual void poolRegister(int position) | |
{ | |
if(this->poolThread == NULL) | |
{ | |
//std::thread t(poolingRegisterThread);//&ModbusAgent::poolingRegisterThread, this); | |
this->poolThread = new std::thread(&ModbusAgent::poolingRegisterThread, this, position); | |
} | |
} | |
virtual void poolBit(int position) | |
{ | |
if(this->poolThread == NULL) | |
{ | |
this->poolThread = new std::thread(&ModbusAgent::poolingBitThread, this, position); | |
} | |
} | |
void waitPooling() | |
{ | |
if(this->poolThread != NULL) | |
{ | |
this->poolThread->join(); | |
} | |
} | |
void stopPooling() | |
{ | |
pooling = false; | |
} | |
}; | |
int main() | |
{ | |
ModbusAgent mbus("127.0.0.1", 1502); | |
int numberOfRegs = 1; | |
//std::vector<uint16_t> regs(numberOfRegs); | |
std::vector<uint8_t> regs(numberOfRegs); | |
//mbus.readRegisters(0, numberOfRegs, regs); | |
mbus.readBits(0, numberOfRegs, regs); | |
for(int i = 0; i < regs.size(); i++) | |
{ | |
std::cout << "[" << i << "] " << (int)regs[i] << std::endl; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment