x-tools/Source/ModbusStudio/modbusstudio/sakmodbusfactory.cc
2024-03-20 20:01:09 +08:00

349 lines
11 KiB
C++

/***************************************************************************************************
* Copyright 2023 x-tools-author(x-tools@outlook.com). All rights reserved.
*
* The file is encoded using "utf8 with bom", it is a part of xTools project.
*
* xTools is licensed according to the terms in the file LICENCE(GPL V3) in the root of the source
* code directory.
**************************************************************************************************/
#include <QCoreApplication>
#include <QModbusTcpClient>
#include <QModbusTcpServer>
#if QT_VERSION < QT_VERSION_CHECK(6, 2, 0)
#include <QModbusRtuSerialMaster>
#include <QModbusRtuSerialSlave>
#else
#include <QModbusRtuSerialClient>
#include <QModbusRtuSerialServer>
#endif
#include "sakmodbusfactory.h"
SAKModbusFactory::SAKModbusFactory(QObject *parent)
: QObject(parent)
{}
SAKModbusFactory::~SAKModbusFactory() {}
SAKModbusFactory *SAKModbusFactory::Instance()
{
static SAKModbusFactory *factory = Q_NULLPTR;
if (!factory) {
factory = new SAKModbusFactory(qApp);
}
return factory;
}
const QString SAKModbusFactory::TypeName(int type)
{
if (type == kModbusRtuSerialClient) {
return tr("RTU Client");
} else if (type == kModbusRtuSerialServer) {
return tr("RTU Server");
} else if (type == kModbusTcpClient) {
return tr("TCP Client");
} else if (type == kModbusTcpServer) {
return tr("TCP Server");
}
Q_ASSERT_X(false, __FUNCTION__, "Unknown modebus device type");
qCWarning(kLoggingCategory) << "Unknown modebus device type";
return "Unknown";
}
QModbusDevice *SAKModbusFactory::CreateDevice(int type)
{
if (type == kModbusRtuSerialClient) {
qCInfo(kLoggingCategory) << "Create rtu serial client.";
#if QT_VERSION < QT_VERSION_CHECK(6, 2, 0)
return new QModbusRtuSerialMaster(this);
#else
return new QModbusRtuSerialClient(this);
#endif
} else if (type == kModbusRtuSerialServer) {
qCInfo(kLoggingCategory) << "Create rtu serial server.";
#if QT_VERSION < QT_VERSION_CHECK(6, 2, 0)
return new QModbusRtuSerialSlave(this);
#else
return new QModbusRtuSerialServer(this);
#endif
} else if (type == kModbusTcpClient) {
qCInfo(kLoggingCategory) << "Create tcp client.";
return new QModbusTcpClient();
} else if (type == kModbusTcpServer) {
qCInfo(kLoggingCategory) << "Create tcp server.";
return new QModbusTcpServer();
}
Q_ASSERT_X(false, __FUNCTION__, "Unknown modebus device type");
qCWarning(kLoggingCategory) << "Unknown modebus device type";
return Q_NULLPTR;
}
bool SAKModbusFactory::IsTcpDevice(QModbusDevice *modbus_device)
{
if (modbus_device) {
if (qobject_cast<QModbusTcpClient *>(modbus_device)) {
return true;
} else if (qobject_cast<QModbusTcpServer *>(modbus_device)) {
return true;
}
}
return false;
}
bool SAKModbusFactory::IsRtuSerialDevice(QModbusDevice *modbus_device)
{
if (modbus_device) {
#if QT_VERSION >= QT_VERSION_CHECK(6, 2, 0)
if (qobject_cast<QModbusRtuSerialClient *>(modbus_device)) {
#else
if (qobject_cast<QModbusRtuSerialMaster *>(modbus_device)) {
#endif
return true;
#if QT_VERSION >= QT_VERSION_CHECK(6, 2, 0)
} else if (qobject_cast<QModbusRtuSerialServer *>(modbus_device)) {
#else
} else if (qobject_cast<QModbusRtuSerialSlave *>(modbus_device)) {
#endif
return true;
}
}
return false;
}
bool SAKModbusFactory::IsTcpDeviceType(int type)
{
bool is_tcp = (type == kModbusTcpClient);
is_tcp |= (type == kModbusTcpServer);
return is_tcp;
}
bool SAKModbusFactory::IsRtuSerialDeviceType(int type)
{
bool is_rtu = (type == kModbusRtuSerialClient);
is_rtu |= (type == kModbusRtuSerialServer);
return is_rtu;
}
bool SAKModbusFactory::IsServerDevice(QModbusDevice *modbus_device)
{
if (modbus_device && qobject_cast<QModbusServer *>(modbus_device)) {
return true;
}
return false;
}
bool SAKModbusFactory::IsClientDevice(QModbusDevice *modbus_device)
{
if (modbus_device && qobject_cast<QModbusClient *>(modbus_device)) {
return true;
}
return false;
}
bool SAKModbusFactory::ConnectDeivce(QModbusDevice *modbus_device)
{
if (modbus_device) {
return modbus_device->connectDevice();
}
return false;
}
bool SAKModbusFactory::IsConnected(QModbusDevice *modbus_device)
{
if (modbus_device) {
if (modbus_device->state() == QModbusDevice::ConnectedState) {
return true;
}
}
return false;
}
bool SAKModbusFactory::IsValidModbusReply(QModbusReply *reply)
{
if (reply && !reply->isFinished()) {
return true;
}
return false;
}
bool SAKModbusFactory::SetServerData(QModbusDevice *server,
QModbusDataUnit::RegisterType table,
int address,
int data,
bool enable_log)
{
bool is_ok = false;
if (server && qobject_cast<QModbusServer *>(server)) {
QModbusServer *modbusServer = qobject_cast<QModbusServer *>(server);
is_ok = modbusServer->setData(table, address, data);
if (enable_log) {
qCInfo(kLoggingCategory) << "Set register data result:" << is_ok << "table:" << table
<< "address:" << address << "data:" << data;
}
}
return is_ok;
}
QList<quint16> SAKModbusFactory::GetServerData(QModbusDevice *server,
QModbusDataUnit::RegisterType table,
int address,
int quantity)
{
QList<quint16> values;
if (server && qobject_cast<QModbusServer *>(server)) {
QModbusServer *cooked_server = qobject_cast<QModbusServer *>(server);
for (int i = address; i < quantity; i++) {
quint16 value;
if (cooked_server->data(table, i, &value)) {
values.append(value);
} else {
qCWarning(kLoggingCategory) << "Parameters error!";
break;
}
}
} else {
qCWarning(kLoggingCategory) << "Can not get values from null object!";
}
return values;
}
void SAKModbusFactory::DeleteModbusDevuce(QModbusDevice **modbus_device)
{
if (*modbus_device) {
QModbusServer *server = qobject_cast<QModbusServer *>(*modbus_device);
if (server) {
server->disconnect();
}
(*modbus_device)->deleteLater();
(*modbus_device) = Q_NULLPTR;
}
}
QModbusDevice *SAKModbusFactory::CreateRtuSerialDevice(
int type, const QString &port_name, int parity, int baud_rate, int data_bits, int stop_bits)
{
QModbusDevice *device = CreateDevice(type);
if (IsRtuSerialDevice(device)) {
device->setConnectionParameter(QModbusDevice::SerialPortNameParameter, port_name);
device->setConnectionParameter(QModbusDevice::SerialBaudRateParameter, baud_rate);
device->setConnectionParameter(QModbusDevice::SerialDataBitsParameter, data_bits);
device->setConnectionParameter(QModbusDevice::SerialStopBitsParameter, stop_bits);
device->setConnectionParameter(QModbusDevice::SerialParityParameter, parity);
qCInfo(kLoggingCategory) << "Set rtu serial modbus device parameters:"
<< "port name:" << port_name << "baud rate:" << baud_rate
<< "data bits:" << data_bits << "stop bits" << stop_bits
<< "parity" << parity;
}
return device;
}
QModbusDevice *SAKModbusFactory::CreateTcpDevice(int type, QString address, int port)
{
QModbusDevice *device = CreateDevice(type);
if (IsTcpDevice(device)) {
device->setConnectionParameter(QModbusDevice::NetworkAddressParameter, address);
device->setConnectionParameter(QModbusDevice::NetworkPortParameter, port);
qCInfo(kLoggingCategory) << "Set tcp modbus device parameters:"
<< "ip address:" << address << "port" << port;
}
return device;
}
void SAKModbusFactory::SetClientDeviceParameters(QModbusDevice *client,
int timeout,
int number_of_retries)
{
if (client) {
qCInfo(kLoggingCategory) << "Set modbus client device parameters:"
<< "timeout:" << timeout << "number_of_retries"
<< number_of_retries;
QModbusClient *cooked_client = qobject_cast<QModbusClient *>(client);
cooked_client->setTimeout(timeout);
cooked_client->setNumberOfRetries(number_of_retries);
}
}
void SAKModbusFactory::SetServerDeviceParameters(QModbusDevice *server,
int address,
bool device_busy,
bool listen_only_mode)
{
if (server) {
qCInfo(kLoggingCategory) << "Set modbus server device parameters:"
<< "address:" << address << "device busy" << device_busy
<< "listen only mode:" << listen_only_mode;
QModbusServer *cooked_server = qobject_cast<QModbusServer *>(server);
cooked_server->setServerAddress(address);
cooked_server->setValue(QModbusServer::DeviceBusy, device_busy);
cooked_server->setValue(QModbusServer::ListenOnlyMode, listen_only_mode);
}
}
QModbusReply *SAKModbusFactory::SendWriteRequest(QModbusDevice *modbus_device,
int register_type,
int start_address,
#if QT_VERSION < QT_VERSION_CHECK(6, 2, 0)
QVector<quint16> values,
#else
QList<quint16> values,
#endif
int server_address)
{
if (modbus_device && IsClientDevice(modbus_device)) {
auto cooked_type = QModbusDataUnit::RegisterType(register_type);
QModbusDataUnit dataUnit(cooked_type, start_address, values);
if (dataUnit.isValid()) {
qCInfo(kLoggingCategory)
<< "register-type:" << register_type << " start-address:" << start_address
<< " serverAddress:" << server_address << " values:" << values;
auto *client = qobject_cast<QModbusClient *>(modbus_device);
QModbusReply *reply = client->sendWriteRequest(dataUnit, server_address);
return reply;
} else {
qCWarning(kLoggingCategory) << "Unvalid data unit!";
}
}
return Q_NULLPTR;
}
QModbusReply *SAKModbusFactory::SendRawRequest(QModbusDevice *modbus_device,
int server_address,
int function_code,
const QByteArray &data)
{
auto cooked_function_code = QModbusPdu::FunctionCode(function_code);
QModbusRequest request(cooked_function_code, data);
if (IsClientDevice(modbus_device)) {
QModbusClient *client = qobject_cast<QModbusClient *>(modbus_device);
return client->sendRawRequest(request, server_address);
}
return Q_NULLPTR;
}