Add qmodmaster and move udp app to applications
This commit is contained in:
107
Applications/qModMaster/src/eutils.cpp
Normal file
107
Applications/qModMaster/src/eutils.cpp
Normal file
@@ -0,0 +1,107 @@
|
||||
#include <QDebug>
|
||||
#include "eutils.h"
|
||||
|
||||
EUtils::EUtils()
|
||||
{
|
||||
}
|
||||
|
||||
QString EUtils::formatValue(int value,int frmt, bool is16Bit, bool isSigned=false)
|
||||
{
|
||||
QString convertedValue;
|
||||
|
||||
switch(frmt){
|
||||
|
||||
case EUtils::Bin://Binary
|
||||
if (is16Bit)
|
||||
if (isSigned)
|
||||
convertedValue = QString("%1").arg((signed short)value,16,2,QLatin1Char('0'));
|
||||
else
|
||||
convertedValue = QString("%1").arg((unsigned short)value,16,2,QLatin1Char('0'));
|
||||
else
|
||||
|
||||
convertedValue = QString("%1").arg(value,0,2);
|
||||
break;
|
||||
|
||||
case EUtils::Dec://Decimal - Unsigned Integer
|
||||
if (isSigned)
|
||||
convertedValue = QString("%1").arg((signed short)value,0,10);
|
||||
else
|
||||
convertedValue = QString("%1").arg((unsigned short)value,0,10);
|
||||
break;
|
||||
|
||||
case EUtils::Hex://Hex
|
||||
if (is16Bit)
|
||||
convertedValue = QString("%1").arg(value,4,16,QLatin1Char('0'));
|
||||
else
|
||||
convertedValue = QString("%1").arg(value,0,16);
|
||||
break;
|
||||
|
||||
default://Default
|
||||
convertedValue = QString("%1").arg(value,0,10);
|
||||
|
||||
}
|
||||
|
||||
return convertedValue.toUpper();
|
||||
|
||||
}
|
||||
|
||||
QString EUtils::formatValue32(int valueHi, int valueLo, int endian = EUtils::Little, int precision = -1)
|
||||
{
|
||||
union{
|
||||
struct{qint16 low, high;} reg;
|
||||
float value;
|
||||
} data;
|
||||
QString convertedValue;
|
||||
|
||||
if (endian == EUtils::Little){
|
||||
data.reg.high = valueLo;
|
||||
data.reg.low = valueHi;
|
||||
}
|
||||
else if (endian == EUtils::Big){
|
||||
data.reg.high = valueHi;
|
||||
data.reg.low = valueLo;
|
||||
}
|
||||
|
||||
convertedValue = QString("%1").arg(data.value, 0, 'G', precision);
|
||||
|
||||
return convertedValue.toUpper();
|
||||
|
||||
}
|
||||
|
||||
QString EUtils::formatValue32(float value, int precision = -1)
|
||||
{
|
||||
|
||||
QString convertedValue;
|
||||
|
||||
convertedValue = QString("%1").arg(value, 0, 'G', precision);
|
||||
|
||||
return convertedValue.toUpper();
|
||||
|
||||
}
|
||||
|
||||
QString EUtils::libmodbus_strerror(int errnum)
|
||||
{
|
||||
switch (errnum) {
|
||||
|
||||
case EINVAL:
|
||||
return "Protocol context is NULL";
|
||||
|
||||
case ETIMEDOUT:
|
||||
return "Timeout";
|
||||
|
||||
case ECONNRESET:
|
||||
return "Connection reset";
|
||||
|
||||
case ECONNREFUSED:
|
||||
return "Connection refused";
|
||||
|
||||
case EPIPE:
|
||||
return "Socket error";
|
||||
|
||||
default://Default
|
||||
return modbus_strerror(errno);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
173
Applications/qModMaster/src/eutils.h
Normal file
173
Applications/qModMaster/src/eutils.h
Normal file
@@ -0,0 +1,173 @@
|
||||
#ifndef EUTILS_H
|
||||
#define EUTILS_H
|
||||
|
||||
#include <QString>
|
||||
#include <QMap>
|
||||
#include <QTime>
|
||||
#include "modbus.h"
|
||||
|
||||
static const QString ModbusFunctionNames[]={"Read Coils (0x01)","Read Discrete Inputs (0x02)","Read Holding Registers (0x03)",
|
||||
"Read Input Registers (0x04)","Write Single Coil (0x05)","Write Single Register (0x06)",
|
||||
"Write Multiple Coils (0x0f)","Write Multiple Registers (0x10)","Report Server ID (0x11)"};
|
||||
static const int ModbusFunctionCodes[]={0x1,0x2,0x3,0x4,0x5,0x6,0xf,0x10,0x11};
|
||||
static const QString ModbusModeStamp[]={"[RTU]>","[TCP]>",""};
|
||||
|
||||
class EUtils
|
||||
{
|
||||
private:
|
||||
EUtils();
|
||||
|
||||
public:
|
||||
|
||||
static QString ModbusDataTypeName(int fCode)
|
||||
{
|
||||
switch(fCode)
|
||||
{
|
||||
case MODBUS_FC_READ_COILS:
|
||||
case MODBUS_FC_WRITE_SINGLE_COIL:
|
||||
case MODBUS_FC_WRITE_MULTIPLE_COILS:
|
||||
return "Coil (binary)";
|
||||
case MODBUS_FC_READ_DISCRETE_INPUTS:
|
||||
return "Discrete Input (binary)";
|
||||
case MODBUS_FC_READ_HOLDING_REGISTERS:
|
||||
case MODBUS_FC_WRITE_SINGLE_REGISTER:
|
||||
case MODBUS_FC_WRITE_MULTIPLE_REGISTERS:
|
||||
return "Holding Register (16 bit)";
|
||||
case MODBUS_FC_READ_INPUT_REGISTERS:
|
||||
return "Input Register (16 bit)";
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return "Unknown";
|
||||
}
|
||||
|
||||
static bool ModbusIsWriteFunction(int fCode)
|
||||
{
|
||||
switch(fCode)
|
||||
{
|
||||
case MODBUS_FC_READ_COILS:
|
||||
case MODBUS_FC_READ_DISCRETE_INPUTS:
|
||||
case MODBUS_FC_READ_HOLDING_REGISTERS:
|
||||
case MODBUS_FC_READ_INPUT_REGISTERS:
|
||||
return false;
|
||||
|
||||
case MODBUS_FC_WRITE_SINGLE_COIL:
|
||||
case MODBUS_FC_WRITE_MULTIPLE_COILS:
|
||||
case MODBUS_FC_WRITE_SINGLE_REGISTER:
|
||||
case MODBUS_FC_WRITE_MULTIPLE_REGISTERS:
|
||||
return true;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool ModbusIsWriteCoilsFunction(int fCode)
|
||||
{
|
||||
switch(fCode)
|
||||
{
|
||||
case MODBUS_FC_READ_COILS:
|
||||
case MODBUS_FC_READ_DISCRETE_INPUTS:
|
||||
case MODBUS_FC_READ_HOLDING_REGISTERS:
|
||||
case MODBUS_FC_READ_INPUT_REGISTERS:
|
||||
case MODBUS_FC_WRITE_SINGLE_REGISTER:
|
||||
case MODBUS_FC_WRITE_MULTIPLE_REGISTERS:
|
||||
return false;
|
||||
|
||||
case MODBUS_FC_WRITE_SINGLE_COIL:
|
||||
case MODBUS_FC_WRITE_MULTIPLE_COILS:
|
||||
return true;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool ModbusIsWriteRegistersFunction(int fCode)
|
||||
{
|
||||
switch(fCode)
|
||||
{
|
||||
case MODBUS_FC_READ_COILS:
|
||||
case MODBUS_FC_READ_DISCRETE_INPUTS:
|
||||
case MODBUS_FC_READ_HOLDING_REGISTERS:
|
||||
case MODBUS_FC_READ_INPUT_REGISTERS:
|
||||
case MODBUS_FC_WRITE_SINGLE_COIL:
|
||||
case MODBUS_FC_WRITE_MULTIPLE_COILS:
|
||||
return false;
|
||||
|
||||
case MODBUS_FC_WRITE_SINGLE_REGISTER:
|
||||
case MODBUS_FC_WRITE_MULTIPLE_REGISTERS:
|
||||
return true;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static QString ModbusFunctionName(int index)
|
||||
{
|
||||
return ModbusFunctionNames[index];
|
||||
}
|
||||
|
||||
static int ModbusFunctionCode(int index)
|
||||
{
|
||||
return ModbusFunctionCodes[index];
|
||||
}
|
||||
|
||||
static QString TxTimeStamp(int md)
|
||||
{
|
||||
return (ModbusModeStamp[md] + "Tx > " + QTime::currentTime().toString("HH:mm:ss:zzz"));
|
||||
}
|
||||
|
||||
static QString RxTimeStamp(int md)
|
||||
{
|
||||
return (ModbusModeStamp[md] + "Rx > " + QTime::currentTime().toString("HH:mm:ss:zzz"));
|
||||
}
|
||||
|
||||
static QString SysTimeStamp()
|
||||
{
|
||||
return ("Sys > " + QTime::currentTime().toString("HH:mm:ss:zzz"));
|
||||
}
|
||||
|
||||
static QChar parity(QString p)
|
||||
{
|
||||
//the first char is what we need
|
||||
return p.at(0);
|
||||
}
|
||||
|
||||
static QString endianness(int endian)
|
||||
{
|
||||
switch (endian)
|
||||
{
|
||||
case 0:
|
||||
return "Little";
|
||||
case 1:
|
||||
return "Big";
|
||||
default:
|
||||
return "N/A";
|
||||
}
|
||||
}
|
||||
|
||||
static enum {RTU = 0, TCP = 1, None = 0} ModbusMode;
|
||||
|
||||
static enum {Bin = 2, Dec = 10, Float = 11, Hex = 16} NumberFormat;
|
||||
static enum {Little =0, Big = 1} Endianness;
|
||||
|
||||
static enum {ReadCoils = 0x1, ReadDisInputs = 0x2,
|
||||
ReadHoldRegs = 0x3, ReadInputRegs = 0x4,
|
||||
WriteSingleCoil = 0x5, WriteSingleReg = 0x6,
|
||||
WriteMultiCoils = 0xf, WriteMultiRegs = 0x10} FunctionCodes;
|
||||
|
||||
static QString formatValue(int value,int frmt, bool is16Bit, bool isSigned);
|
||||
|
||||
static QString formatValue32(int valueHi, int valueLo, int endian, int precision);
|
||||
static QString formatValue32(float value, int precision);
|
||||
|
||||
static QString libmodbus_strerror(int errnum);
|
||||
|
||||
};
|
||||
|
||||
#endif // EUTILS_H
|
||||
76
Applications/qModMaster/src/infobar.cpp
Normal file
76
Applications/qModMaster/src/infobar.cpp
Normal file
@@ -0,0 +1,76 @@
|
||||
#include <QFrame>
|
||||
#include <QLabel>
|
||||
#include <QPushButton>
|
||||
#include <QHBoxLayout>
|
||||
#include "infobar.h"
|
||||
|
||||
InfoBar::InfoBar(QWidget *parent) : QFrame(parent)
|
||||
{
|
||||
label = new QLabel;
|
||||
|
||||
QPushButton *button = new QPushButton;
|
||||
button->setStyleSheet("QPushButton{image: url(:/icons/close8-black.png);\
|
||||
background-color: lightgrey;\
|
||||
border: none;\
|
||||
height: 12px;\
|
||||
width: 12px}\
|
||||
QPushButton:hover{image: url(:/icons/close8-red.png);\
|
||||
background-color: lightgrey;\
|
||||
border: none;\
|
||||
height: 12px;\
|
||||
width: 12px}\
|
||||
QPushButton:pressed{image: url(:/icons/close8-red.png);\
|
||||
background-color: lightgrey;\
|
||||
border: 1px solid darkgrey;\
|
||||
border-radius: 2px;\
|
||||
height: 12px;\
|
||||
width: 12px}");
|
||||
button->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
|
||||
button->setFocusPolicy(Qt::NoFocus);
|
||||
connect(button, SIGNAL(clicked()), this, SLOT(hide()));
|
||||
|
||||
QHBoxLayout *hboxlayout = new QHBoxLayout;
|
||||
hboxlayout->addWidget(label);
|
||||
hboxlayout->addWidget(button);
|
||||
|
||||
setLayout(hboxlayout);
|
||||
setFrameStyle(QFrame::Box);
|
||||
hide();
|
||||
}
|
||||
|
||||
InfoBar::InfoBar(QString message, InfoType type, QWidget *parent) : InfoBar(parent)
|
||||
{
|
||||
setMessage(message);
|
||||
setInfoType(type);
|
||||
}
|
||||
|
||||
void InfoBar::setInfoType(InfoType type)
|
||||
{
|
||||
switch (type) {
|
||||
case Question:
|
||||
setStyleSheet("color: black;\
|
||||
background-color: skyblue");
|
||||
break;
|
||||
case Error:
|
||||
setStyleSheet("color: white;\
|
||||
background-color: red");
|
||||
break;
|
||||
default:
|
||||
case Warning:
|
||||
setStyleSheet("color: black;\
|
||||
background-color: yellow");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void InfoBar::setMessage(QString message)
|
||||
{
|
||||
label->setText(message);
|
||||
}
|
||||
|
||||
void InfoBar::show(QString message, InfoType type)
|
||||
{
|
||||
setMessage(message);
|
||||
setInfoType(type);
|
||||
QFrame::show();
|
||||
}
|
||||
26
Applications/qModMaster/src/infobar.h
Normal file
26
Applications/qModMaster/src/infobar.h
Normal file
@@ -0,0 +1,26 @@
|
||||
#ifndef _MyInfoBar_H_
|
||||
#define _MyInfoBar_H_
|
||||
|
||||
#include <QLabel>
|
||||
#include <QFrame>
|
||||
|
||||
class InfoBar : public QFrame
|
||||
{
|
||||
Q_OBJECT
|
||||
private:
|
||||
QLabel *label;
|
||||
public:
|
||||
enum InfoType {
|
||||
Question,
|
||||
Warning,
|
||||
Error
|
||||
};
|
||||
|
||||
InfoBar(QWidget *parent = 0);
|
||||
InfoBar(QString message, InfoType type, QWidget *parent = 0);
|
||||
void setInfoType(InfoType type);
|
||||
void setMessage(QString message);
|
||||
void show(QString message, InfoType type);
|
||||
};
|
||||
|
||||
#endif
|
||||
63
Applications/qModMaster/src/main.cpp
Normal file
63
Applications/qModMaster/src/main.cpp
Normal file
@@ -0,0 +1,63 @@
|
||||
#include <QApplication>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <QDir>
|
||||
#include <QTranslator>
|
||||
|
||||
#include "QsLog.h"
|
||||
#include "QsLogDest.h"
|
||||
#include "mainwindow.h"
|
||||
#include "modbusadapter.h"
|
||||
#include "modbuscommsettings.h"
|
||||
|
||||
QTranslator *Translator;
|
||||
|
||||
//Logging Levels
|
||||
//TraceLevel : 0
|
||||
//DebugLevel : 1
|
||||
//InfoLevel : 2
|
||||
//WarnLevel : 3
|
||||
//ErrorLevel : 4
|
||||
//FatalLevel : 5
|
||||
//OffLevel : 6
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
|
||||
//qt dpi warnings
|
||||
qputenv("QT_DEVICE_PIXEL_RATIO", "0");
|
||||
qputenv("QT_AUTO_SCREEN_SCALE_FACTOR", "1");
|
||||
qputenv("QT_SCREEN_SCALE_FACTORS", "1");
|
||||
qputenv("QT_SCALE_FACTOR", "1");
|
||||
|
||||
//application startup
|
||||
QApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
|
||||
QApplication app(argc, argv);
|
||||
Translator = new QTranslator;
|
||||
Translator->load(":/translations/" + QCoreApplication::applicationName() + "_" + QLocale::system().name());
|
||||
app.installTranslator(Translator);
|
||||
|
||||
//init the logging mechanism
|
||||
QsLogging::Logger& logger = QsLogging::Logger::instance();
|
||||
logger.setLoggingLevel(QsLogging::OffLevel); // start with no logging
|
||||
const QString sLogPath(QDir(app.applicationDirPath()).filePath("QModMaster.log"));
|
||||
QsLogging::DestinationPtr fileDestination(QsLogging::DestinationFactory::MakeFileDestination(sLogPath,true,65535,7));
|
||||
QsLogging::DestinationPtr debugDestination(QsLogging::DestinationFactory::MakeDebugOutputDestination());
|
||||
logger.addDestination(debugDestination);
|
||||
logger.addDestination(fileDestination);
|
||||
|
||||
//Modbus Adapter
|
||||
ModbusAdapter modbus_adapt(NULL);
|
||||
//Program settings
|
||||
ModbusCommSettings settings("qModMaster.ini");
|
||||
|
||||
//show main window
|
||||
mainWin = new MainWindow(NULL, &modbus_adapt, &settings);
|
||||
//connect signals - slots
|
||||
QObject::connect(&modbus_adapt, SIGNAL(refreshView()), mainWin, SLOT(refreshView()));
|
||||
QObject::connect(mainWin, SIGNAL(resetCounters()), &modbus_adapt, SLOT(resetCounters()));
|
||||
mainWin->show();
|
||||
|
||||
return app.exec();
|
||||
|
||||
}
|
||||
860
Applications/qModMaster/src/mainwindow.cpp
Normal file
860
Applications/qModMaster/src/mainwindow.cpp
Normal file
@@ -0,0 +1,860 @@
|
||||
#include <QtDebug>
|
||||
#include <QCoreApplication>
|
||||
#include <QDesktopServices>
|
||||
#include <QUrl>
|
||||
#include <QTranslator>
|
||||
#include <QMessageBox>
|
||||
#include <QFileDialog>
|
||||
|
||||
#include "QsLog.h"
|
||||
#include "mainwindow.h"
|
||||
#include "ui_mainwindow.h"
|
||||
#include "eutils.h"
|
||||
|
||||
MainWindow *mainWin;
|
||||
|
||||
MainWindow::MainWindow(QWidget *parent, ModbusAdapter *adapter, ModbusCommSettings *settings) :
|
||||
QMainWindow(parent), m_modbus(adapter), m_modbusCommSettings(settings),
|
||||
ui(new Ui::MainWindow)
|
||||
{
|
||||
//setup UI
|
||||
ui->setupUi(this);
|
||||
ui->sbNoOfRegs->setEnabled(true);
|
||||
ui->actionRead_Write->setEnabled(false);
|
||||
ui->actionScan->setEnabled(false);
|
||||
ui->sbStartAddress->setMinimum(m_modbusCommSettings->baseAddr().toInt());
|
||||
ui->cmbFrmt->setCurrentIndex(m_modbusCommSettings->frmt());
|
||||
ui->cmbFunctionCode->setCurrentIndex(m_modbusCommSettings->functionCode());
|
||||
ui->cmbModbusMode->setCurrentIndex(m_modbusCommSettings->modbusMode());
|
||||
ui->sbSlaveID->setValue(m_modbusCommSettings->slaveID());
|
||||
ui->spInterval->setValue(m_modbusCommSettings->scanRate());
|
||||
ui->sbStartAddress->setValue(m_modbusCommSettings->startAddr());
|
||||
ui->sbNoOfRegs->setValue(m_modbusCommSettings->noOfRegs());
|
||||
ui->chkSigned->setVisible(false);
|
||||
ui->tblRegisters->setStyleSheet("QHeaderView::section { background-color:lightGray }");
|
||||
|
||||
//UI - dialogs
|
||||
m_dlgAbout = new About();
|
||||
connect(ui->actionAbout,SIGNAL(triggered()),m_dlgAbout,SLOT(show()));
|
||||
m_dlgModbusRTU = new SettingsModbusRTU(this,m_modbusCommSettings);
|
||||
connect(ui->actionSerial_RTU,SIGNAL(triggered()),this,SLOT(showSettingsModbusRTU()));
|
||||
m_dlgModbusTCP = new SettingsModbusTCP(this,m_modbusCommSettings);
|
||||
connect(ui->actionTCP,SIGNAL(triggered()),this,SLOT(showSettingsModbusTCP()));
|
||||
m_dlgSettings = new Settings(this,m_modbusCommSettings);
|
||||
connect(ui->actionSettings,SIGNAL(triggered()),this,SLOT(showSettings()));
|
||||
m_busMonitor = new BusMonitor(this, m_modbus->rawModel);
|
||||
connect(ui->actionBus_Monitor,SIGNAL(triggered()),this,SLOT(showBusMonitor()));
|
||||
m_tools = new Tools(this, m_modbus, m_modbusCommSettings);
|
||||
connect(ui->actionTools,SIGNAL(triggered()),this,SLOT(showTools()));
|
||||
|
||||
//UI - connections
|
||||
connect(ui->cmbModbusMode,SIGNAL(currentIndexChanged(int)),this,SLOT(changedModbusMode(int)));
|
||||
connect(ui->cmbFunctionCode,SIGNAL(currentIndexChanged(int)),this,SLOT(changedFunctionCode(int)));
|
||||
connect(ui->cmbFrmt,SIGNAL(currentIndexChanged(int)),this,SLOT(changedFrmt(int)));
|
||||
connect(ui->chkSigned,SIGNAL(toggled(bool)),this,SLOT(changedDecSign(bool)));
|
||||
connect(ui->cmbStartAddrBase,SIGNAL(currentIndexChanged(int)),this,SLOT(changedStartAddrBase(int)));
|
||||
connect(ui->sbSlaveID,SIGNAL(valueChanged(int)),this,SLOT(changedSlaveID(int)));
|
||||
connect(ui->sbNoOfRegs,SIGNAL(valueChanged(int)),this,SLOT(changedNoOfRegs(int)));
|
||||
connect(ui->sbStartAddress,SIGNAL(valueChanged(int)),this,SLOT(changedStartAddress(int)));
|
||||
connect(ui->spInterval,SIGNAL(valueChanged(int)),this,SLOT(changedScanRate(int)));
|
||||
connect(ui->sbPrecision,SIGNAL(valueChanged(int)),this,SLOT(changedFloatPrecision(int)));
|
||||
connect(ui->actionClear,SIGNAL(triggered()),this,SLOT(clearItems()));
|
||||
connect(ui->actionRead_Write,SIGNAL(triggered()),this,SLOT(modbusRequest()));
|
||||
connect(ui->actionScan,SIGNAL(toggled(bool)),this,SLOT(modbusScanCycle(bool)));
|
||||
connect(ui->actionConnect,SIGNAL(toggled(bool)),this,SLOT(changedConnect(bool)));
|
||||
connect(ui->actionReset_Counters,SIGNAL(triggered()),this,SIGNAL(resetCounters()));
|
||||
connect(ui->actionOpenLogFile,SIGNAL(triggered()),this,SLOT(openLogFile()));
|
||||
connect(ui->actionHeaders,SIGNAL(triggered(bool)),this,SLOT(showHeaders(bool)));
|
||||
connect(ui->actionModbus_Manual,SIGNAL(triggered()),this,SLOT(openModbusManual()));
|
||||
//connect(ui->actionEnglish_en_US,SIGNAL(triggered()),this,SLOT(changeLanguage()));
|
||||
//connect(ui->actionSimplified_Chinese_zh_CN,SIGNAL(triggered()),this,SLOT(changeLanguage()));
|
||||
//connect(ui->actionTraditional_Chinese_zh_TW,SIGNAL(triggered()),this,SLOT(changeLanguage()));
|
||||
connect(ui->actionLoad_Session,SIGNAL(triggered(bool)),this,SLOT(loadSession()));
|
||||
connect(ui->actionSave_Session,SIGNAL(triggered(bool)),this,SLOT(saveSession()));
|
||||
connect(m_dlgSettings, SIGNAL(changedEndianess(int)),this,SLOT(changedEndianess(int)));
|
||||
|
||||
//UI - status
|
||||
m_statusInd = new QLabel;
|
||||
m_statusInd->setFixedSize( 16, 16 );
|
||||
m_statusText = new QLabel;
|
||||
m_baseAddr = new QLabel(tr("Base Addr : ") + "0");
|
||||
m_statusPackets = new QLabel(tr("Packets : ") + "0");
|
||||
m_statusPackets->setStyleSheet("QLabel {color:blue;}");
|
||||
m_statusErrors = new QLabel(tr("Errors : ") + "0");
|
||||
m_statusErrors->setStyleSheet("QLabel {color:red;}");
|
||||
m_endian = new QLabel(tr("Endian : ") + EUtils::endianness(m_modbusCommSettings->endian()));
|
||||
m_endian->setStyleSheet("QLabel {color:black;}");
|
||||
ui->statusBar->addWidget(m_statusInd);
|
||||
ui->statusBar->addWidget(m_statusText, 10);
|
||||
ui->statusBar->addWidget(m_baseAddr, 10);
|
||||
ui->statusBar->addWidget(m_statusPackets, 10);
|
||||
ui->statusBar->addWidget(m_endian, 10);
|
||||
ui->statusBar->addWidget(m_statusErrors, 10);
|
||||
m_statusInd->setPixmap(QPixmap(":/img/ballorange-16.png"));
|
||||
|
||||
//Setup Toolbar
|
||||
ui->mainToolBar->addAction(ui->actionLoad_Session);
|
||||
ui->mainToolBar->addAction(ui->actionSave_Session);
|
||||
ui->mainToolBar->addAction(ui->actionConnect);
|
||||
ui->mainToolBar->addAction(ui->actionRead_Write);
|
||||
ui->mainToolBar->addAction(ui->actionScan);
|
||||
ui->mainToolBar->addAction(ui->actionClear);
|
||||
ui->mainToolBar->addAction(ui->actionReset_Counters);
|
||||
ui->mainToolBar->addSeparator();
|
||||
ui->mainToolBar->addAction(ui->actionOpenLogFile);
|
||||
ui->mainToolBar->addAction(ui->actionBus_Monitor);
|
||||
ui->mainToolBar->addAction(ui->actionTools);
|
||||
ui->mainToolBar->addAction(ui->actionHeaders);
|
||||
ui->mainToolBar->addSeparator();
|
||||
ui->mainToolBar->addAction(ui->actionSerial_RTU);
|
||||
ui->mainToolBar->addAction(ui->actionTCP);
|
||||
ui->mainToolBar->addAction(ui->actionSettings);
|
||||
ui->mainToolBar->addSeparator();
|
||||
ui->mainToolBar->addAction(ui->actionModbus_Manual);
|
||||
ui->mainToolBar->addAction(ui->actionAbout);
|
||||
ui->mainToolBar->addAction(ui->actionExit);
|
||||
|
||||
//Init models
|
||||
ui->tblRegisters->setItemDelegate(m_modbus->regModel->itemDelegate());
|
||||
ui->tblRegisters->setModel(m_modbus->regModel->model);
|
||||
ui->tblRegisters->horizontalHeader()->hide();
|
||||
ui->tblRegisters->verticalHeader()->hide();
|
||||
changedFrmt(m_modbusCommSettings->frmt());
|
||||
m_modbus->regModel->setStartAddrBase(10);
|
||||
m_modbus->regModel->setEndian(m_modbusCommSettings->endian());
|
||||
m_modbus->setBaseAddr(m_modbusCommSettings->baseAddr().toInt());
|
||||
m_modbus->regModel->setFloatPrecision(m_modbusCommSettings->floatPrecision());
|
||||
m_modbus->setReadOutputsBeforeWrite(m_modbusCommSettings->readOutputsBeforeWrite());
|
||||
clearItems();//init model ui
|
||||
|
||||
//Update UI
|
||||
changedFunctionCode(m_modbusCommSettings->functionCode());
|
||||
changedModbusMode(m_modbusCommSettings->modbusMode());
|
||||
updateStatusBar();
|
||||
refreshView();
|
||||
|
||||
//Logging level
|
||||
QsLogging::Logger::instance().setLoggingLevel((QsLogging::Level)m_modbusCommSettings->loggingLevel());
|
||||
QLOG_INFO()<< "Start Program" ;
|
||||
|
||||
}
|
||||
|
||||
MainWindow::~MainWindow()
|
||||
{
|
||||
|
||||
if (m_modbus)
|
||||
m_modbus->modbusDisConnect();
|
||||
delete ui;
|
||||
|
||||
QLOG_INFO()<< "Stop Program" ;
|
||||
|
||||
}
|
||||
|
||||
void MainWindow::showSettingsModbusRTU()
|
||||
{
|
||||
|
||||
//Show RTU Settings Dialog
|
||||
m_dlgModbusRTU->modbus_connected = m_modbus->isConnected();
|
||||
if (m_dlgModbusRTU->exec()==QDialog::Accepted) {
|
||||
QLOG_TRACE()<< "RTU settings changes accepted ";
|
||||
updateStatusBar();
|
||||
m_modbusCommSettings->saveSettings();
|
||||
}
|
||||
else
|
||||
QLOG_WARN()<< "RTU settings changes rejected ";
|
||||
|
||||
}
|
||||
|
||||
void MainWindow::showSettingsModbusTCP()
|
||||
{
|
||||
|
||||
//Show TCP Settings Dialog
|
||||
m_dlgModbusTCP->modbus_connected = m_modbus->isConnected();
|
||||
if (m_dlgModbusTCP->exec()==QDialog::Accepted) {
|
||||
QLOG_TRACE()<< "TCP settings changes accepted ";
|
||||
updateStatusBar();
|
||||
m_modbusCommSettings->saveSettings();
|
||||
}
|
||||
else
|
||||
QLOG_WARN()<< "TCP settings changes rejected ";
|
||||
|
||||
}
|
||||
|
||||
void MainWindow::showSettings()
|
||||
{
|
||||
|
||||
//Show General Settings Dialog
|
||||
m_dlgSettings->modbus_connected = m_modbus->isConnected();
|
||||
if (m_dlgSettings->exec()==QDialog::Accepted) {
|
||||
QLOG_TRACE()<< "Settings changes accepted ";
|
||||
m_modbus->rawModel->setMaxNoOfLines(m_modbusCommSettings->maxNoOfLines().toInt());
|
||||
m_modbus->setTimeOut(m_modbusCommSettings->timeOut().toInt());
|
||||
ui->sbStartAddress->setMinimum(m_modbusCommSettings->baseAddr().toInt());
|
||||
m_modbus->setBaseAddr(m_modbusCommSettings->baseAddr().toInt());
|
||||
m_modbus->regModel->setEndian(m_modbusCommSettings->endian());
|
||||
m_modbusCommSettings->saveSettings();
|
||||
}
|
||||
else
|
||||
QLOG_WARN()<< "Settings changes rejected ";
|
||||
|
||||
updateStatusBar();
|
||||
|
||||
}
|
||||
|
||||
void MainWindow::showBusMonitor()
|
||||
{
|
||||
|
||||
//Show Bus Monitor
|
||||
|
||||
m_modbus->rawModel->setMaxNoOfLines(m_modbusCommSettings->maxNoOfLines().toInt());
|
||||
m_busMonitor->move(this->x() + this->width() + 20, this->y());
|
||||
m_busMonitor->show();
|
||||
|
||||
}
|
||||
|
||||
void MainWindow::showTools()
|
||||
{
|
||||
|
||||
//Show Tools
|
||||
|
||||
m_tools->move(this->x() + this->width() + 40, this->y() + 20);
|
||||
m_tools->show();
|
||||
|
||||
}
|
||||
|
||||
void MainWindow::changedModbusMode(int currIndex)
|
||||
{
|
||||
|
||||
//Change lblSlave text : Slave Addr, Unit ID
|
||||
|
||||
QLOG_TRACE()<< "Modbus Mode changed. Index = " << currIndex;
|
||||
m_modbusCommSettings->setModbusMode(currIndex);
|
||||
m_modbusCommSettings->saveSettings();
|
||||
|
||||
if (currIndex == 0) { //RTU
|
||||
ui->lblSlave->setText("Slave Addr");
|
||||
}
|
||||
else { //TCP
|
||||
ui->lblSlave->setText("Unit ID");
|
||||
}
|
||||
|
||||
updateStatusBar();
|
||||
|
||||
}
|
||||
|
||||
void MainWindow::changedFunctionCode(int currIndex)
|
||||
{
|
||||
|
||||
//Enable-Disable number of coils or registers
|
||||
|
||||
QLOG_TRACE()<< "Function Code changed. Index = " << currIndex;
|
||||
m_modbusCommSettings->setFunctionCode(currIndex);
|
||||
m_modbusCommSettings->saveSettings();
|
||||
|
||||
const int functionCode = EUtils::ModbusFunctionCode(currIndex);
|
||||
QString String_number_of_coils(tr("Number of Coils"));
|
||||
QString String_number_of_inputs(tr("Number of Inputs"));
|
||||
QString String_number_of_registers(tr("Number of Registers"));
|
||||
switch(functionCode)//Label = Read Request, Write Request
|
||||
{
|
||||
case MODBUS_FC_READ_COILS:
|
||||
m_modbus->regModel->setIs16Bit(false);
|
||||
ui->sbNoOfRegs->setEnabled(true);
|
||||
ui->sbNoOfRegs->setMaximum(2000);
|
||||
ui->lblNoOfCoils->setText(String_number_of_coils);
|
||||
ui->cmbFrmt->setCurrentIndex(0);
|
||||
ui->cmbFrmt->setEnabled(false);
|
||||
break;
|
||||
case MODBUS_FC_READ_DISCRETE_INPUTS:
|
||||
m_modbus->regModel->setIs16Bit(false);
|
||||
ui->sbNoOfRegs->setEnabled(true);
|
||||
ui->sbNoOfRegs->setMaximum(2000);
|
||||
ui->lblNoOfCoils->setText(String_number_of_inputs);
|
||||
ui->cmbFrmt->setCurrentIndex(0);
|
||||
ui->cmbFrmt->setEnabled(false);
|
||||
break;
|
||||
case MODBUS_FC_READ_HOLDING_REGISTERS:
|
||||
m_modbus->regModel->setIs16Bit(true);
|
||||
ui->sbNoOfRegs->setEnabled(true);
|
||||
ui->sbNoOfRegs->setMaximum(125);
|
||||
ui->lblNoOfCoils->setText(String_number_of_registers);
|
||||
ui->cmbFrmt->setEnabled(true);
|
||||
break;
|
||||
case MODBUS_FC_READ_INPUT_REGISTERS:
|
||||
m_modbus->regModel->setIs16Bit(true);
|
||||
ui->sbNoOfRegs->setEnabled(true);
|
||||
ui->sbNoOfRegs->setMaximum(125);
|
||||
ui->lblNoOfCoils->setText(String_number_of_registers);
|
||||
ui->cmbFrmt->setEnabled(true);
|
||||
break;
|
||||
case MODBUS_FC_WRITE_SINGLE_COIL:
|
||||
m_modbus->regModel->setIs16Bit(false);
|
||||
ui->sbNoOfRegs->setValue(1);
|
||||
ui->sbNoOfRegs->setEnabled(false);
|
||||
ui->lblNoOfCoils->setText(String_number_of_coils);
|
||||
ui->cmbFrmt->setCurrentIndex(0);
|
||||
ui->cmbFrmt->setEnabled(false);
|
||||
break;
|
||||
case MODBUS_FC_WRITE_MULTIPLE_COILS:
|
||||
m_modbus->regModel->setIs16Bit(false);
|
||||
if (ui->sbNoOfRegs->value() < 2)
|
||||
ui->sbNoOfRegs->setValue(2);
|
||||
ui->sbNoOfRegs->setEnabled(true);
|
||||
ui->sbNoOfRegs->setMaximum(2000);
|
||||
ui->lblNoOfCoils->setText(String_number_of_coils);
|
||||
ui->cmbFrmt->setCurrentIndex(0);
|
||||
ui->cmbFrmt->setEnabled(false);
|
||||
break;
|
||||
case MODBUS_FC_WRITE_SINGLE_REGISTER:
|
||||
m_modbus->regModel->setIs16Bit(true);
|
||||
ui->sbNoOfRegs->setValue(1);
|
||||
ui->sbNoOfRegs->setEnabled(false);
|
||||
ui->lblNoOfCoils->setText(String_number_of_registers);
|
||||
ui->cmbFrmt->setEnabled(true);
|
||||
break;
|
||||
case MODBUS_FC_WRITE_MULTIPLE_REGISTERS:
|
||||
m_modbus->regModel->setIs16Bit(true);
|
||||
if (ui->sbNoOfRegs->value() < 2)
|
||||
ui->sbNoOfRegs->setValue(2);
|
||||
ui->sbNoOfRegs->setEnabled(true);
|
||||
ui->sbNoOfRegs->setMaximum(125);
|
||||
ui->lblNoOfCoils->setText(String_number_of_registers);
|
||||
ui->cmbFrmt->setEnabled(true);
|
||||
break;
|
||||
default:
|
||||
m_modbus->regModel->setIs16Bit(false);
|
||||
ui->sbNoOfRegs->setValue(1);
|
||||
ui->sbNoOfRegs->setEnabled(true);
|
||||
ui->sbNoOfRegs->setMaximum(2000);
|
||||
ui->lblNoOfCoils->setText(String_number_of_coils);
|
||||
ui->cmbFrmt->setEnabled(true);
|
||||
break;
|
||||
}
|
||||
|
||||
m_modbus->setNumOfRegs(ui->sbNoOfRegs->value());
|
||||
addItems();
|
||||
|
||||
}
|
||||
|
||||
void MainWindow::changedFrmt(int currIndex)
|
||||
{
|
||||
|
||||
//Change Format
|
||||
|
||||
QLOG_TRACE()<< "Format changed. Index = " << currIndex;
|
||||
m_modbusCommSettings->setFrmt(currIndex);
|
||||
m_modbusCommSettings->saveSettings();
|
||||
|
||||
switch(currIndex)
|
||||
{
|
||||
case 0:
|
||||
ui->chkSigned->setVisible(false);
|
||||
ui->chkSigned->setChecked(false);
|
||||
m_modbus->regModel->setFrmt(EUtils::Bin);
|
||||
ui->lblPrecision->setVisible(false);
|
||||
ui->sbPrecision->setVisible(false);
|
||||
ui->sbNoOfRegs->setMinimum(1);
|
||||
break;
|
||||
case 1:
|
||||
ui->chkSigned->setVisible(true);
|
||||
m_modbus->regModel->setFrmt(EUtils::Dec);
|
||||
ui->lblPrecision->setVisible(false);
|
||||
ui->sbPrecision->setVisible(false);
|
||||
ui->sbNoOfRegs->setMinimum(1);
|
||||
break;
|
||||
case 2:
|
||||
ui->chkSigned->setVisible(false);
|
||||
ui->chkSigned->setChecked(false);
|
||||
m_modbus->regModel->setFrmt(EUtils::Hex);
|
||||
ui->lblPrecision->setVisible(false);
|
||||
ui->sbPrecision->setVisible(false);
|
||||
ui->sbNoOfRegs->setMinimum(1);
|
||||
break;
|
||||
case 3:
|
||||
ui->chkSigned->setVisible(false);
|
||||
ui->chkSigned->setChecked(false);
|
||||
m_modbus->regModel->setFrmt(EUtils::Float);
|
||||
ui->lblPrecision->setVisible(true);
|
||||
ui->sbPrecision->setVisible(true);
|
||||
ui->sbNoOfRegs->setMinimum(1);
|
||||
break;
|
||||
default:
|
||||
m_modbus->regModel->setFrmt(EUtils::Dec);
|
||||
ui->chkSigned->setVisible(true);
|
||||
ui->lblPrecision->setVisible(false);
|
||||
ui->sbPrecision->setVisible(false);
|
||||
ui->sbNoOfRegs->setMinimum(1);
|
||||
break;
|
||||
}
|
||||
|
||||
//clear table on format change
|
||||
addItems();
|
||||
|
||||
}
|
||||
|
||||
void MainWindow::changedDecSign(bool value)
|
||||
{
|
||||
//Change Dec Signed - Unsigned
|
||||
|
||||
QLOG_TRACE()<< "Dec Signed-Unsigned changed. Signed = " << value;
|
||||
|
||||
m_modbus->regModel->setIsSigned(value);
|
||||
|
||||
}
|
||||
|
||||
void MainWindow::changedScanRate(int value)
|
||||
{
|
||||
|
||||
//Enable-Disable Time Interval
|
||||
|
||||
QLOG_TRACE()<< "ScanRate changed. Value = " << value;
|
||||
m_modbusCommSettings->setScanRate(value);
|
||||
m_modbusCommSettings->saveSettings();
|
||||
|
||||
m_modbus->setScanRate(value);
|
||||
|
||||
}
|
||||
|
||||
void MainWindow::changedConnect(bool value)
|
||||
{
|
||||
|
||||
//Connect - Disconnect
|
||||
|
||||
if (value) { //Connected
|
||||
modbusConnect(true);
|
||||
QLOG_INFO()<< "Connected ";
|
||||
}
|
||||
else { //Disconnected
|
||||
modbusConnect(false);
|
||||
QLOG_INFO()<< "Disconnected ";
|
||||
}
|
||||
|
||||
m_modbus->resetCounters();
|
||||
refreshView();
|
||||
|
||||
}
|
||||
|
||||
void MainWindow::changedSlaveID(int value)
|
||||
{
|
||||
|
||||
//Slave ID
|
||||
|
||||
QLOG_TRACE()<< "Slave ID Changed. Value = " << value;
|
||||
m_modbusCommSettings->setSlaveID(value);
|
||||
m_modbusCommSettings->saveSettings();
|
||||
|
||||
}
|
||||
|
||||
void MainWindow::changedEndianess(int endian)
|
||||
{
|
||||
|
||||
//Endianess
|
||||
|
||||
QLOG_TRACE()<< "Endianess Changed. Value = " << endian;
|
||||
|
||||
//clear table on endianess change
|
||||
addItems();
|
||||
|
||||
}
|
||||
|
||||
void MainWindow::openLogFile()
|
||||
{
|
||||
|
||||
//Open log file
|
||||
QString arg;
|
||||
QLOG_TRACE()<< "Open log file";
|
||||
|
||||
arg = "file:///" + QCoreApplication::applicationDirPath() + "/QModMaster.log";
|
||||
QDesktopServices::openUrl(QUrl(arg));
|
||||
|
||||
|
||||
}
|
||||
|
||||
void MainWindow::openModbusManual()
|
||||
{
|
||||
|
||||
//Open Modbus Manual
|
||||
QString arg;
|
||||
QLOG_TRACE()<< "Open Modbus Manual";
|
||||
|
||||
arg = "file:///" + QCoreApplication::applicationDirPath() + "/ManModbus/index.html";
|
||||
QDesktopServices::openUrl(QUrl(arg));
|
||||
|
||||
|
||||
}
|
||||
|
||||
void MainWindow::changedStartAddrBase(int currIndex)
|
||||
{
|
||||
|
||||
//Change Base
|
||||
|
||||
QLOG_TRACE()<< "Start Addr Base changed. Index = " << currIndex;
|
||||
|
||||
switch(currIndex)
|
||||
{
|
||||
case 0:
|
||||
ui->sbStartAddress->setDisplayIntegerBase(10);
|
||||
m_modbus->regModel->setStartAddrBase(10);
|
||||
break;
|
||||
case 1:
|
||||
ui->sbStartAddress->setDisplayIntegerBase(16);
|
||||
m_modbus->regModel->setStartAddrBase(16);
|
||||
break;
|
||||
default:
|
||||
ui->sbStartAddress->setDisplayIntegerBase(10);
|
||||
m_modbus->regModel->setStartAddrBase(10);
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void MainWindow::changedStartAddress(int value)
|
||||
{
|
||||
|
||||
//Start Address changed
|
||||
QLOG_TRACE()<< "Start Address changed. Value = " << value;
|
||||
m_modbusCommSettings->setStartAddr(value);
|
||||
m_modbusCommSettings->saveSettings();
|
||||
|
||||
m_modbus->setStartAddr(value);
|
||||
addItems();
|
||||
|
||||
}
|
||||
|
||||
void MainWindow::changedNoOfRegs(int value)
|
||||
{
|
||||
|
||||
//No of regs changed
|
||||
QLOG_TRACE()<< "No Of Regs changed. Value = " << value;
|
||||
m_modbusCommSettings->setNoOfRegs(value);
|
||||
m_modbusCommSettings->saveSettings();
|
||||
|
||||
m_modbus->setNumOfRegs(value);
|
||||
addItems();
|
||||
|
||||
}
|
||||
|
||||
void MainWindow::changedFloatPrecision(int precision)
|
||||
{
|
||||
|
||||
//Float precision changed
|
||||
m_modbusCommSettings->setfloatPrecision(precision);
|
||||
m_modbusCommSettings->saveSettings();
|
||||
m_modbus->regModel->setFloatPrecision(precision);
|
||||
|
||||
}
|
||||
void MainWindow::updateStatusBar()
|
||||
{
|
||||
|
||||
//Update status bar
|
||||
|
||||
QString msg;
|
||||
|
||||
if(ui->cmbModbusMode->currentIndex() == 0) { //RTU
|
||||
msg = "RTU : ";
|
||||
msg += m_modbusCommSettings->serialPortName() + " | ";
|
||||
msg += m_modbusCommSettings->baud() + ",";
|
||||
msg += m_modbusCommSettings->dataBits() + ",";
|
||||
msg += m_modbusCommSettings->stopBits() + ",";
|
||||
msg += m_modbusCommSettings->parity();
|
||||
}
|
||||
else {
|
||||
msg = "TCP : ";
|
||||
msg += m_modbusCommSettings->slaveIP() + ":";
|
||||
msg += m_modbusCommSettings->TCPPort();
|
||||
}
|
||||
|
||||
m_statusText->clear();
|
||||
m_statusText->setText(msg);
|
||||
|
||||
//Connection is valid
|
||||
if (m_modbus->isConnected()) {
|
||||
m_statusInd->setPixmap(QPixmap(":/icons/bullet-green-16.png"));
|
||||
}
|
||||
else {
|
||||
m_statusInd->setPixmap(QPixmap(":/icons/bullet-red-16.png"));
|
||||
}
|
||||
|
||||
//base Address
|
||||
m_baseAddr->setText("Base Addr : " + m_modbusCommSettings->baseAddr());
|
||||
|
||||
//endianness
|
||||
m_endian->setText(("Endian : ") + EUtils::endianness(m_modbusCommSettings->endian()));
|
||||
|
||||
}
|
||||
|
||||
void MainWindow::addItems()
|
||||
{
|
||||
int baseAddr;
|
||||
//add items
|
||||
|
||||
m_modbus->setSlave(ui->sbSlaveID->value());
|
||||
m_modbus->setFunctionCode(EUtils::ModbusFunctionCode(ui->cmbFunctionCode->currentIndex()));
|
||||
m_modbus->setNumOfRegs(ui->sbNoOfRegs->value());
|
||||
//get base address
|
||||
baseAddr = m_modbusCommSettings->baseAddr().toInt();
|
||||
m_modbus->setStartAddr(ui->sbStartAddress->value() - baseAddr);
|
||||
|
||||
QLOG_INFO()<< "Add Items. Function Code = " << QString::number(EUtils::ModbusFunctionCode(ui->cmbFunctionCode->currentIndex()),16);
|
||||
|
||||
m_modbus->addItems();
|
||||
|
||||
}
|
||||
|
||||
void MainWindow::clearItems()
|
||||
{
|
||||
|
||||
//Clear items from registers model
|
||||
|
||||
QLOG_TRACE()<< "clearItems" ;
|
||||
|
||||
m_modbus->regModel->clear();
|
||||
addItems();
|
||||
|
||||
}
|
||||
|
||||
void MainWindow::modbusRequest()
|
||||
{
|
||||
|
||||
//Request items from modbus adapter and add raw data to raw data model
|
||||
int rowCount = m_modbus->regModel->model->rowCount();
|
||||
int baseAddr;
|
||||
|
||||
QLOG_TRACE()<< "Request transaction. No or registers = " << rowCount;
|
||||
|
||||
if (rowCount == 0) {
|
||||
mainWin->showUpInfoBar(tr("Request failed\nAdd items to Registers Table."), InfoBar::Error);
|
||||
QLOG_WARN()<< "Request failed. No items in registers table ";
|
||||
return;
|
||||
}
|
||||
else if (m_modbus->regModel->getFrmt() == EUtils::Float &&
|
||||
ui->sbNoOfRegs->value() % 2 != 0) {
|
||||
mainWin->showUpInfoBar(tr("The number of registers must be even."), InfoBar::Error);
|
||||
QLOG_WARN()<< "Request failed. The number of registers must be even ";
|
||||
return;
|
||||
}
|
||||
else {
|
||||
mainWin->hideInfoBar();
|
||||
}
|
||||
|
||||
//get base address
|
||||
baseAddr = m_modbusCommSettings->baseAddr().toInt();
|
||||
|
||||
m_modbus->setSlave(ui->sbSlaveID->value());
|
||||
m_modbus->setFunctionCode(EUtils::ModbusFunctionCode(ui->cmbFunctionCode->currentIndex()));
|
||||
m_modbus->setStartAddr(ui->sbStartAddress->value() - baseAddr);
|
||||
m_modbus->setNumOfRegs(ui->sbNoOfRegs->value());
|
||||
|
||||
//Modbus data
|
||||
m_modbus->modbusTransaction();
|
||||
|
||||
}
|
||||
|
||||
void MainWindow::modbusScanCycle(bool value)
|
||||
{
|
||||
|
||||
//Request items from modbus adapter and add raw data to raw data model
|
||||
int rowCount = m_modbus->regModel->model->rowCount();
|
||||
int baseAddr;
|
||||
|
||||
if (value && rowCount == 0) {
|
||||
//mainWin->showUpInfoBar(tr("Request failed\nAdd items to Registers Table."), InfoBar::Error);
|
||||
QLOG_WARN()<< "Request failed. No items in registers table ";
|
||||
QMessageBox::critical(this, "QModMaster", tr("Request failed\nAdd items to Registers Table."));
|
||||
ui->actionScan->setChecked(false);
|
||||
return;
|
||||
}
|
||||
else if (value && m_modbus->regModel->getFrmt() == EUtils::Float &&
|
||||
ui->sbNoOfRegs->value() % 2 != 0) {
|
||||
//mainWin->showUpInfoBar(tr("The number of registers must be even."), InfoBar::Error);
|
||||
QLOG_WARN()<< "Request failed. The number of registers must be even ";
|
||||
QMessageBox::critical(this, "QModMaster", tr("The number of registers must be even."));
|
||||
ui->actionScan->setChecked(false);
|
||||
return;
|
||||
}
|
||||
else {
|
||||
mainWin->hideInfoBar();
|
||||
}
|
||||
|
||||
//get base address
|
||||
baseAddr = m_modbusCommSettings->baseAddr().toInt();
|
||||
|
||||
m_modbus->setSlave(ui->sbSlaveID->value());
|
||||
m_modbus->setFunctionCode(EUtils::ModbusFunctionCode(ui->cmbFunctionCode->currentIndex()));
|
||||
m_modbus->setStartAddr(ui->sbStartAddress->value() - baseAddr);
|
||||
m_modbus->setNumOfRegs(ui->sbNoOfRegs->value());
|
||||
|
||||
//Start-Stop poll timer
|
||||
QLOG_TRACE()<< "Scan time = " << value;
|
||||
if (value){
|
||||
if (ui->spInterval->value() < m_modbusCommSettings->timeOut().toInt() * 1000 * 2){
|
||||
mainWin->showUpInfoBar(tr("Scan rate should be at least 2 * Timeout."), InfoBar::Error);
|
||||
QLOG_ERROR()<< "Scan rate error. should be at least 2 * Timeout ";
|
||||
}
|
||||
else {
|
||||
m_modbus->setScanRate(ui->spInterval->value());
|
||||
m_modbus->startPollTimer();
|
||||
}
|
||||
}
|
||||
else
|
||||
m_modbus->stopPollTimer();
|
||||
|
||||
//Update UI
|
||||
ui->cmbFunctionCode->setEnabled(!value);
|
||||
ui->sbSlaveID->setEnabled(!value);
|
||||
ui->sbStartAddress->setEnabled(!value);
|
||||
ui->spInterval->setEnabled(!value);
|
||||
ui->cmbStartAddrBase->setEnabled(!value);
|
||||
if (!value)
|
||||
changedFunctionCode(ui->cmbFunctionCode->currentIndex());
|
||||
else
|
||||
ui->sbNoOfRegs->setEnabled(false);
|
||||
|
||||
}
|
||||
|
||||
void MainWindow::modbusConnect(bool connect)
|
||||
{
|
||||
|
||||
//Modbus connect - RTU/TCP
|
||||
QLOG_TRACE()<< "Modbus Connect. Value = " << connect;
|
||||
|
||||
if (connect) { //RTU
|
||||
if (ui->cmbModbusMode->currentIndex() == EUtils::RTU) {
|
||||
m_modbus->setSlave(ui->sbSlaveID->value());
|
||||
m_modbus->modbusConnectRTU(m_modbusCommSettings->serialPortName(),
|
||||
m_modbusCommSettings->baud().toInt(),
|
||||
EUtils::parity(m_modbusCommSettings->parity()),
|
||||
m_modbusCommSettings->dataBits().toInt(),
|
||||
m_modbusCommSettings->stopBits().toInt(),
|
||||
m_modbusCommSettings->RTS().toInt(),
|
||||
m_modbusCommSettings->timeOut().toInt()
|
||||
);
|
||||
}
|
||||
else { //TCP
|
||||
m_modbus->modbusConnectTCP(m_modbusCommSettings->slaveIP(),
|
||||
m_modbusCommSettings->TCPPort().toInt(),
|
||||
m_modbusCommSettings->timeOut().toInt());
|
||||
}
|
||||
}
|
||||
else { //Disconnect
|
||||
m_modbus->modbusDisConnect();
|
||||
ui->actionScan->setChecked(false);
|
||||
}
|
||||
|
||||
updateStatusBar();
|
||||
|
||||
//Update UI
|
||||
ui->actionLoad_Session->setEnabled(!m_modbus->isConnected());
|
||||
ui->actionSave_Session->setEnabled(!m_modbus->isConnected());
|
||||
ui->actionConnect->setChecked(m_modbus->isConnected());
|
||||
ui->actionRead_Write->setEnabled(m_modbus->isConnected());
|
||||
ui->actionScan->setEnabled(m_modbus->isConnected());
|
||||
ui->cmbModbusMode->setEnabled(!m_modbus->isConnected());
|
||||
|
||||
}
|
||||
|
||||
void MainWindow::showHeaders(bool value)
|
||||
{
|
||||
QLOG_TRACE()<< "Show Headers = " << value;
|
||||
|
||||
if (value){
|
||||
ui->tblRegisters->horizontalHeader()->show();
|
||||
ui->tblRegisters->verticalHeader()->show();
|
||||
}
|
||||
else {
|
||||
ui->tblRegisters->horizontalHeader()->hide();
|
||||
ui->tblRegisters->verticalHeader()->hide();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void MainWindow::refreshView()
|
||||
{
|
||||
|
||||
QLOG_TRACE()<< "Packets sent / received = " << m_modbus->packets() << ", errors = " << m_modbus->errors();
|
||||
ui->tblRegisters->resizeColumnsToContents();
|
||||
|
||||
m_statusPackets->setText(tr("Packets : ") + QString("%1").arg(m_modbus->packets()));
|
||||
m_statusErrors->setText(tr("Errors : ") + QString("%1").arg(m_modbus->errors()));
|
||||
|
||||
}
|
||||
|
||||
void MainWindow::loadSession()
|
||||
{
|
||||
QString fName;
|
||||
|
||||
QLOG_TRACE()<< "load session";
|
||||
fName = QFileDialog::getOpenFileName(this,
|
||||
"Load Session file",
|
||||
"",
|
||||
"Session Files (*.ses);;All Files (*.*)");
|
||||
//check
|
||||
if (fName != ""){
|
||||
m_modbusCommSettings->loadSession(fName);
|
||||
//Update UI
|
||||
ui->sbStartAddress->setMinimum(m_modbusCommSettings->baseAddr().toInt());
|
||||
ui->cmbFrmt->setCurrentIndex(m_modbusCommSettings->frmt());
|
||||
ui->sbPrecision->setValue(m_modbusCommSettings->floatPrecision());
|
||||
ui->cmbFunctionCode->setCurrentIndex(m_modbusCommSettings->functionCode());
|
||||
ui->cmbModbusMode->setCurrentIndex(m_modbusCommSettings->modbusMode());
|
||||
ui->sbSlaveID->setValue(m_modbusCommSettings->slaveID());
|
||||
ui->spInterval->setValue(m_modbusCommSettings->scanRate());
|
||||
ui->sbStartAddress->setValue(m_modbusCommSettings->startAddr());
|
||||
ui->sbNoOfRegs->setValue(m_modbusCommSettings->noOfRegs());
|
||||
updateStatusBar();
|
||||
refreshView();
|
||||
QMessageBox::information(this, "QModMaster", "Load session file : " + fName);
|
||||
}
|
||||
else
|
||||
QMessageBox::information(this, "QModMaster", "Cancel operation Or no file selected");
|
||||
|
||||
}
|
||||
|
||||
void MainWindow::saveSession()
|
||||
{
|
||||
QString fName;
|
||||
|
||||
QLOG_TRACE()<< "save session";
|
||||
fName = QFileDialog::getSaveFileName(this,
|
||||
"Save Session file",
|
||||
"",
|
||||
"Session Files (*.ses)");
|
||||
|
||||
//check
|
||||
if (fName != ""){
|
||||
m_modbusCommSettings->saveSession(fName);
|
||||
QMessageBox::information(this, "QModMaster", "Save session file : " + fName);
|
||||
}
|
||||
else
|
||||
QMessageBox::information(this, "QModMaster", "Cancel operation Or no file selected");
|
||||
|
||||
}
|
||||
void MainWindow::showUpInfoBar(QString message, InfoBar::InfoType type)
|
||||
{
|
||||
ui->infobar->show(message, type);
|
||||
}
|
||||
|
||||
void MainWindow::hideInfoBar()
|
||||
{
|
||||
ui->infobar->hide();
|
||||
}
|
||||
|
||||
void MainWindow::changeEvent(QEvent* event)
|
||||
{
|
||||
if(event->type() == QEvent::LanguageChange)
|
||||
{
|
||||
ui->retranslateUi(this);
|
||||
}
|
||||
QMainWindow::changeEvent(event);
|
||||
}
|
||||
|
||||
void MainWindow::changeLanguage()
|
||||
{
|
||||
// Not Used
|
||||
|
||||
extern QTranslator *Translator;
|
||||
QCoreApplication::removeTranslator(Translator);
|
||||
Translator->load(":/translations/" + QCoreApplication::applicationName() + sender()->objectName().right(6));
|
||||
QCoreApplication::installTranslator(Translator);
|
||||
}
|
||||
|
||||
94
Applications/qModMaster/src/mainwindow.h
Normal file
94
Applications/qModMaster/src/mainwindow.h
Normal file
@@ -0,0 +1,94 @@
|
||||
#ifndef MAINWINDOW_H
|
||||
#define MAINWINDOW_H
|
||||
|
||||
#include <QMainWindow>
|
||||
#include <QSettings>
|
||||
#include <QLabel>
|
||||
#include <QString>
|
||||
#include <QProcess>
|
||||
|
||||
#include "forms/about.h"
|
||||
#include "forms/settingsmodbusrtu.h"
|
||||
#include "forms/settingsmodbustcp.h"
|
||||
#include "forms/settings.h"
|
||||
#include "forms/busmonitor.h"
|
||||
#include "forms/tools.h"
|
||||
#include "modbuscommsettings.h"
|
||||
#include "modbusadapter.h"
|
||||
#include "infobar.h"
|
||||
|
||||
namespace Ui {
|
||||
class MainWindow;
|
||||
}
|
||||
|
||||
class MainWindow : public QMainWindow
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit MainWindow(QWidget *parent = 0, ModbusAdapter *adapter = 0, ModbusCommSettings *settings = 0);
|
||||
~MainWindow();
|
||||
void showUpInfoBar(QString message, InfoBar::InfoType type);
|
||||
void hideInfoBar();
|
||||
|
||||
private:
|
||||
Ui::MainWindow *ui;
|
||||
//UI - Dialogs
|
||||
About *m_dlgAbout;
|
||||
SettingsModbusRTU *m_dlgModbusRTU;
|
||||
SettingsModbusTCP *m_dlgModbusTCP;
|
||||
Settings *m_dlgSettings;
|
||||
BusMonitor *m_busMonitor;
|
||||
Tools *m_tools;
|
||||
|
||||
ModbusCommSettings *m_modbusCommSettings;
|
||||
void updateStatusBar();
|
||||
QLabel *m_statusText;
|
||||
QLabel *m_statusInd;
|
||||
QLabel *m_baseAddr;
|
||||
QLabel *m_statusPackets;
|
||||
QLabel *m_statusErrors;
|
||||
QLabel *m_endian;
|
||||
ModbusAdapter *m_modbus;
|
||||
void modbusConnect(bool connect);
|
||||
|
||||
void changeEvent(QEvent* event);
|
||||
|
||||
private slots:
|
||||
void showSettingsModbusRTU();
|
||||
void showSettingsModbusTCP();
|
||||
void showSettings();
|
||||
void showBusMonitor();
|
||||
void showTools();
|
||||
void changedModbusMode(int currIndex);
|
||||
void changedFunctionCode(int currIndex);
|
||||
void changedFrmt(int currIndex);
|
||||
void changedDecSign(bool value);
|
||||
void changedStartAddrBase(int currIndex);
|
||||
void changedScanRate(int value);
|
||||
void changedConnect(bool value);
|
||||
void changedStartAddress(int value);
|
||||
void changedNoOfRegs(int value);
|
||||
void changedSlaveID(int value);
|
||||
void changedFloatPrecision(int precision);
|
||||
void changedEndianess(int endian);
|
||||
void addItems();
|
||||
void clearItems();
|
||||
void openLogFile();
|
||||
void modbusScanCycle(bool value);
|
||||
void modbusRequest();
|
||||
void refreshView();
|
||||
void changeLanguage();
|
||||
void openModbusManual();
|
||||
void loadSession();
|
||||
void saveSession();
|
||||
void showHeaders(bool value);
|
||||
|
||||
signals:
|
||||
void resetCounters();
|
||||
|
||||
};
|
||||
|
||||
extern MainWindow *mainWin;
|
||||
|
||||
#endif // MAINWINDOW_H
|
||||
580
Applications/qModMaster/src/modbusadapter.cpp
Normal file
580
Applications/qModMaster/src/modbusadapter.cpp
Normal file
@@ -0,0 +1,580 @@
|
||||
#include <QApplication>
|
||||
#include <QtDebug>
|
||||
#include "modbusadapter.h"
|
||||
#include "mainwindow.h"
|
||||
|
||||
#include "QsLog.h"
|
||||
#include <errno.h>
|
||||
|
||||
ModbusAdapter *m_instance;
|
||||
|
||||
ModbusAdapter::ModbusAdapter(QObject *parent) :
|
||||
QObject(parent),
|
||||
m_modbus(NULL)
|
||||
{
|
||||
m_instance = this;
|
||||
regModel=new RegistersModel(this);
|
||||
rawModel=new RawDataModel(this);
|
||||
m_connected = false;
|
||||
m_ModBusMode = EUtils::None;
|
||||
m_pollTimer = new QTimer(this);
|
||||
m_timeOut = 0;
|
||||
m_transactionIsPending = false;
|
||||
m_packets = 0;
|
||||
m_errors = 0;
|
||||
m_readOutputsBeforeWrite = true;
|
||||
connect(m_pollTimer,SIGNAL(timeout()),this,SLOT(modbusTransaction()));
|
||||
connect(regModel,SIGNAL(refreshView()),this,SIGNAL(refreshView()));
|
||||
//setup memory for data
|
||||
dest = (uint8_t *) malloc(2000 * sizeof(uint8_t));
|
||||
memset(dest, 0, 2000 * sizeof(uint8_t));
|
||||
dest16 = (uint16_t *) malloc(125 * sizeof(uint16_t));
|
||||
memset(dest16, 0, 125 * sizeof(uint16_t));
|
||||
|
||||
}
|
||||
|
||||
ModbusAdapter::~ModbusAdapter()
|
||||
{
|
||||
free(dest);
|
||||
free(dest16);
|
||||
}
|
||||
|
||||
void ModbusAdapter::modbusConnectRTU(QString port, int baud, QChar parity, int dataBits, int stopBits, int RTS, int timeOut)
|
||||
{
|
||||
//Modbus RTU connect
|
||||
QString line;
|
||||
modbusDisConnect();
|
||||
|
||||
QLOG_INFO()<< "Modbus Connect RTU";
|
||||
|
||||
m_modbus = modbus_new_rtu(port.toLatin1().constData(),baud,parity.toLatin1(),dataBits,stopBits,RTS);
|
||||
line = "Connecting to Serial Port [" + port + "]...";
|
||||
QLOG_TRACE() << line;
|
||||
|
||||
//Debug messages from libmodbus
|
||||
#ifdef LIB_MODBUS_DEBUG_OUTPUT
|
||||
modbus_set_debug(m_modbus, 1);
|
||||
#endif
|
||||
|
||||
m_timeOut = timeOut;
|
||||
|
||||
if(m_modbus == NULL){
|
||||
mainWin->showUpInfoBar(tr("Unable to create the libmodbus context."), InfoBar::Error);
|
||||
QLOG_ERROR()<< "Connection failed. Unable to create the libmodbus context";
|
||||
return;
|
||||
}
|
||||
else if(m_modbus && modbus_set_slave(m_modbus, m_slave) == -1){
|
||||
modbus_free(m_modbus);
|
||||
mainWin->showUpInfoBar(tr("Invalid slave ID."), InfoBar::Error);
|
||||
QLOG_ERROR()<< "Connection failed. Invalid slave ID";
|
||||
return;
|
||||
}
|
||||
else if(m_modbus && modbus_connect(m_modbus) == -1) {
|
||||
modbus_free(m_modbus);
|
||||
mainWin->showUpInfoBar(tr("Connection failed\nCould not connect to serial port."), InfoBar::Error);
|
||||
QLOG_ERROR()<< "Connection failed. Could not connect to serial port";
|
||||
m_connected = false;
|
||||
line += "Failed";
|
||||
}
|
||||
else {
|
||||
//error recovery mode
|
||||
modbus_set_error_recovery(m_modbus, MODBUS_ERROR_RECOVERY_PROTOCOL);
|
||||
//response_timeout;
|
||||
modbus_set_response_timeout(m_modbus, timeOut, 0);
|
||||
m_connected = true;
|
||||
line += "OK";
|
||||
mainWin->hideInfoBar();
|
||||
QLOG_TRACE() << line;
|
||||
}
|
||||
|
||||
m_ModBusMode = EUtils::RTU;
|
||||
|
||||
//Add line to raw data model
|
||||
line = EUtils::SysTimeStamp() + " - " + line;
|
||||
rawModel->addLine(line);
|
||||
|
||||
}
|
||||
|
||||
void ModbusAdapter::modbusConnectTCP(QString ip, int port, int timeOut)
|
||||
{
|
||||
//Modbus TCP connect
|
||||
QString strippedIP = "";
|
||||
QString line;
|
||||
modbusDisConnect();
|
||||
|
||||
QLOG_INFO()<< "Modbus Connect TCP";
|
||||
|
||||
line = "Connecting to IP : " + ip + ":" + QString::number(port);
|
||||
QLOG_TRACE() << line;
|
||||
strippedIP = stripIP(ip);
|
||||
if (strippedIP == ""){
|
||||
mainWin->showUpInfoBar(tr("Connection failed\nBlank IP Address."), InfoBar::Error);
|
||||
QLOG_ERROR()<< "Connection failed. Blank IP Address";
|
||||
return;
|
||||
}
|
||||
else {
|
||||
m_modbus = modbus_new_tcp(strippedIP.toLatin1().constData(), port);
|
||||
mainWin->hideInfoBar();
|
||||
QLOG_TRACE() << "Connecting to IP : " << ip << ":" << port;
|
||||
}
|
||||
|
||||
//Debug messages from libmodbus
|
||||
#ifdef LIB_MODBUS_DEBUG_OUTPUT
|
||||
modbus_set_debug(m_modbus, 1);
|
||||
#endif
|
||||
|
||||
m_timeOut = timeOut;
|
||||
|
||||
if(m_modbus == NULL){
|
||||
mainWin->showUpInfoBar(tr("Unable to create the libmodbus context."), InfoBar::Error);
|
||||
QLOG_ERROR()<< "Connection failed. Unable to create the libmodbus context";
|
||||
return;
|
||||
}
|
||||
else if(m_modbus && modbus_connect(m_modbus) == -1) {
|
||||
modbus_free(m_modbus);
|
||||
mainWin->showUpInfoBar(tr("Connection failed\nCould not connect to TCP port."), InfoBar::Error);
|
||||
QLOG_ERROR()<< "Connection to IP : " << ip << ":" << port << "...failed. Could not connect to TCP port";
|
||||
m_connected = false;
|
||||
line += " Failed";
|
||||
}
|
||||
else {
|
||||
//error recovery mode
|
||||
modbus_set_error_recovery(m_modbus, MODBUS_ERROR_RECOVERY_PROTOCOL);
|
||||
//response_timeout;
|
||||
modbus_set_response_timeout(m_modbus, timeOut, 0);
|
||||
m_connected = true;
|
||||
line += " OK";
|
||||
mainWin->hideInfoBar();
|
||||
QLOG_TRACE() << line;
|
||||
}
|
||||
|
||||
m_ModBusMode = EUtils::TCP;
|
||||
|
||||
//Add line to raw data model
|
||||
line = EUtils::SysTimeStamp() + " - " + line;
|
||||
rawModel->addLine(line);
|
||||
|
||||
}
|
||||
|
||||
|
||||
void ModbusAdapter::modbusDisConnect()
|
||||
{
|
||||
//Modbus disconnect
|
||||
|
||||
QLOG_INFO()<< "Modbus disconnected";
|
||||
|
||||
if(m_modbus) {
|
||||
if (m_connected){
|
||||
modbus_close(m_modbus);
|
||||
modbus_free(m_modbus);
|
||||
}
|
||||
m_modbus = NULL;
|
||||
}
|
||||
|
||||
m_connected = false;
|
||||
|
||||
m_ModBusMode = EUtils::None;
|
||||
|
||||
}
|
||||
|
||||
bool ModbusAdapter::isConnected()
|
||||
{
|
||||
//Modbus is connected
|
||||
|
||||
return m_connected;
|
||||
}
|
||||
|
||||
void ModbusAdapter::modbusTransaction()
|
||||
{
|
||||
//Modbus request data
|
||||
|
||||
QLOG_INFO() << "Modbus Transaction. Function Code = " << m_functionCode;
|
||||
m_packets += 1;
|
||||
|
||||
QApplication::setOverrideCursor(Qt::WaitCursor);
|
||||
|
||||
switch(m_functionCode)
|
||||
{
|
||||
case MODBUS_FC_READ_COILS:
|
||||
case MODBUS_FC_READ_DISCRETE_INPUTS:
|
||||
case MODBUS_FC_READ_HOLDING_REGISTERS:
|
||||
case MODBUS_FC_READ_INPUT_REGISTERS:
|
||||
modbusReadData(m_slave,m_functionCode,m_startAddr,m_numOfRegs);
|
||||
break;
|
||||
|
||||
case MODBUS_FC_WRITE_SINGLE_COIL:
|
||||
case MODBUS_FC_WRITE_SINGLE_REGISTER:
|
||||
case MODBUS_FC_WRITE_MULTIPLE_COILS:
|
||||
case MODBUS_FC_WRITE_MULTIPLE_REGISTERS:
|
||||
modbusWriteData(m_slave,m_functionCode,m_startAddr,m_numOfRegs);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
QApplication::setOverrideCursor(Qt::ArrowCursor);
|
||||
|
||||
emit(refreshView());
|
||||
|
||||
}
|
||||
|
||||
void ModbusAdapter::modbusReadData(int slave, int functionCode, int startAddress, int noOfItems)
|
||||
{
|
||||
|
||||
QLOG_INFO() << "Modbus Read Data ";
|
||||
|
||||
if(m_modbus == NULL) return;
|
||||
|
||||
int ret = -1; //return value from read functions
|
||||
bool is16Bit = false;
|
||||
|
||||
modbus_set_slave(m_modbus, slave);
|
||||
//request data from modbus
|
||||
switch(functionCode)
|
||||
{
|
||||
case MODBUS_FC_READ_COILS:
|
||||
ret = modbus_read_bits(m_modbus, startAddress, noOfItems, dest);
|
||||
break;
|
||||
|
||||
case MODBUS_FC_READ_DISCRETE_INPUTS:
|
||||
ret = modbus_read_input_bits(m_modbus, startAddress, noOfItems, dest);
|
||||
break;
|
||||
|
||||
case MODBUS_FC_READ_HOLDING_REGISTERS:
|
||||
ret = modbus_read_registers(m_modbus, startAddress, noOfItems, dest16);
|
||||
is16Bit = true;
|
||||
break;
|
||||
|
||||
case MODBUS_FC_READ_INPUT_REGISTERS:
|
||||
ret = modbus_read_input_registers(m_modbus, startAddress, noOfItems, dest16);
|
||||
is16Bit = true;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
QLOG_TRACE() << "Modbus Read Data return value = " << ret << ", errno = " << errno;
|
||||
|
||||
//update data model
|
||||
if(ret == noOfItems)
|
||||
{
|
||||
if (regModel->getFrmt() != EUtils::Float)
|
||||
{
|
||||
for(int i = 0; i < noOfItems; ++i)
|
||||
{
|
||||
int data = is16Bit ? dest16[i] : dest[i];
|
||||
regModel->setValue(i,data);
|
||||
}
|
||||
}
|
||||
else//read float values
|
||||
{
|
||||
for(int i = 0; i < noOfItems - 1; i+=2)
|
||||
{
|
||||
int dataHi = is16Bit ? dest16[i] : dest[i];
|
||||
int dataLo = is16Bit ? dest16[i+1] : dest[i+1];
|
||||
regModel->setValue32(i/2,dataHi,dataLo);
|
||||
}
|
||||
}
|
||||
|
||||
mainWin->hideInfoBar();
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
regModel->setNoValidValues();
|
||||
m_errors += 1;
|
||||
|
||||
QString line = "";
|
||||
if(ret < 0) {
|
||||
line = QString("Error : ") + EUtils::libmodbus_strerror(errno);
|
||||
QLOG_ERROR() << "Read Data failed. " << line;
|
||||
rawModel->addLine(EUtils::SysTimeStamp() + " - " + line);
|
||||
line = QString(tr("Read data failed.\nError : ")) + EUtils::libmodbus_strerror(errno);
|
||||
}
|
||||
else {
|
||||
line = QString("Number of registers returned does not match number of registers requested!. Error : ") + EUtils::libmodbus_strerror(errno);
|
||||
QLOG_ERROR() << "Read Data failed. " << line;
|
||||
rawModel->addLine(EUtils::SysTimeStamp() + " - " + line);
|
||||
line = QString(tr("Read data failed.\nNumber of registers returned does not match number of registers requested!. Error : ")) + EUtils::libmodbus_strerror(errno);
|
||||
}
|
||||
|
||||
mainWin->showUpInfoBar(line, InfoBar::Error);
|
||||
modbus_flush(m_modbus); //flush data
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void ModbusAdapter::modbusWriteData(int slave, int functionCode, int startAddress, int noOfItems)
|
||||
{
|
||||
|
||||
QLOG_INFO() << "Modbus Write Data ";
|
||||
|
||||
if(m_modbus == NULL) return;
|
||||
|
||||
int ret = -1; //return value from functions
|
||||
|
||||
union{
|
||||
struct{qint16 low, high;} reg;
|
||||
float value;
|
||||
} modelData;
|
||||
|
||||
modbus_set_slave(m_modbus, slave);
|
||||
//request data from modbus
|
||||
switch(functionCode)
|
||||
{
|
||||
case MODBUS_FC_WRITE_SINGLE_COIL:
|
||||
ret = modbus_write_bit(m_modbus, startAddress,regModel->value(0));
|
||||
noOfItems = 1;
|
||||
break;
|
||||
|
||||
case MODBUS_FC_WRITE_SINGLE_REGISTER:
|
||||
ret = modbus_write_register( m_modbus, startAddress,regModel->value(0));
|
||||
noOfItems = 1;
|
||||
break;
|
||||
|
||||
case MODBUS_FC_WRITE_MULTIPLE_COILS:
|
||||
{
|
||||
uint8_t * data = new uint8_t[noOfItems];
|
||||
for(int i = 0; i < noOfItems; ++i)
|
||||
{
|
||||
data[i] = regModel->value(i);
|
||||
}
|
||||
ret = modbus_write_bits(m_modbus, startAddress, noOfItems, data);
|
||||
delete[] data;
|
||||
break;
|
||||
}
|
||||
case MODBUS_FC_WRITE_MULTIPLE_REGISTERS:
|
||||
{
|
||||
if (regModel->getFrmt() != EUtils::Float) {
|
||||
uint16_t * data = new uint16_t[noOfItems];
|
||||
for(int i = 0; i < noOfItems; ++i)
|
||||
{
|
||||
data[i] = regModel->value(i);
|
||||
}
|
||||
ret = modbus_write_registers(m_modbus, startAddress, noOfItems, data);
|
||||
delete[] data;
|
||||
break;
|
||||
}
|
||||
else { //write float values
|
||||
uint16_t * data = new uint16_t[noOfItems];
|
||||
for(int i = 0; i < noOfItems - 1; i+=2)
|
||||
{
|
||||
modelData.value = regModel->floatValue(i/2);
|
||||
if (regModel->getEndian() == EUtils::Little){
|
||||
data[i] = modelData.reg.low;
|
||||
data[i+1] = modelData.reg.high;
|
||||
}
|
||||
else if (regModel->getEndian() == EUtils::Big){
|
||||
data[i] = modelData.reg.high;
|
||||
data[i+1] = modelData.reg.low;
|
||||
}
|
||||
}
|
||||
ret = modbus_write_registers(m_modbus, startAddress, noOfItems, data);
|
||||
delete[] data;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
QLOG_TRACE() << "Modbus Write Data return value = " << ret << ", errno = " << errno;;
|
||||
|
||||
//update data model
|
||||
if(ret == noOfItems)
|
||||
{
|
||||
//values written correctly
|
||||
rawModel->addLine(EUtils::SysTimeStamp() + " - values written correctly.");
|
||||
mainWin->hideInfoBar();
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
regModel->setNoValidValues();
|
||||
m_errors += 1;
|
||||
|
||||
QString line;
|
||||
if(ret < 0) {
|
||||
line = QString("Error : ") + EUtils::libmodbus_strerror(errno);
|
||||
QLOG_ERROR() << "Write Data failed. " << line;
|
||||
rawModel->addLine(EUtils::SysTimeStamp() + " - " + line);
|
||||
line = QString(tr("Write data failed.\nError : ")) + EUtils::libmodbus_strerror(errno);
|
||||
}
|
||||
else {
|
||||
line = QString("Number of registers returned does not match number of registers requested!. Error : ") + EUtils::libmodbus_strerror(errno);
|
||||
QLOG_ERROR() << "Write Data failed. " << line;
|
||||
rawModel->addLine(EUtils::SysTimeStamp() + " - " + line);
|
||||
line = QString(tr("Write data failed.\nNumber of registers returned does not match number of registers requested!. Error : ")) + EUtils::libmodbus_strerror(errno);
|
||||
}
|
||||
|
||||
mainWin->showUpInfoBar(line, InfoBar::Error);
|
||||
modbus_flush(m_modbus); //flush data
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void ModbusAdapter::busMonitorRequestData(uint8_t * data, int dataLen)
|
||||
{
|
||||
|
||||
//Request Raw data from port - Update raw data model
|
||||
|
||||
QString line;
|
||||
|
||||
for(int i = 0; i < dataLen; ++i ) {
|
||||
line += QString().asprintf( "%.2x ", data[i] );
|
||||
}
|
||||
|
||||
QLOG_INFO() << "Tx Data : " << line;
|
||||
line = EUtils::TxTimeStamp(m_ModBusMode) + " - " + line.toUpper();
|
||||
|
||||
rawModel->addLine(line);
|
||||
|
||||
m_transactionIsPending = true;
|
||||
|
||||
}
|
||||
void ModbusAdapter::busMonitorResponseData(uint8_t * data, int dataLen)
|
||||
{
|
||||
|
||||
//Response Raw data from port - Update raw data model
|
||||
|
||||
QString line;
|
||||
|
||||
for(int i = 0; i < dataLen; ++i ) {
|
||||
line += QString().asprintf( "%.2x ", data[i] );
|
||||
}
|
||||
|
||||
QLOG_INFO() << "Rx Data : " << line;
|
||||
line = EUtils::RxTimeStamp(m_ModBusMode) + " - " + line.toUpper();
|
||||
|
||||
rawModel->addLine(line);
|
||||
|
||||
m_transactionIsPending = false;
|
||||
|
||||
}
|
||||
|
||||
void ModbusAdapter::setSlave(int slave)
|
||||
{
|
||||
m_slave = slave;
|
||||
}
|
||||
|
||||
void ModbusAdapter::setFunctionCode(int functionCode)
|
||||
{
|
||||
m_functionCode = functionCode;
|
||||
}
|
||||
|
||||
void ModbusAdapter::setStartAddr(int addr)
|
||||
{
|
||||
m_startAddr = addr;
|
||||
}
|
||||
|
||||
void ModbusAdapter::setBaseAddr(int baseAddr)
|
||||
{
|
||||
m_baseAddr = baseAddr;
|
||||
}
|
||||
|
||||
void ModbusAdapter::setNumOfRegs(int num)
|
||||
{
|
||||
m_numOfRegs = num;
|
||||
}
|
||||
|
||||
void ModbusAdapter::addItems()
|
||||
{
|
||||
//TODO - fix base addr
|
||||
regModel->addItems(m_startAddr + m_baseAddr, m_numOfRegs, EUtils::ModbusIsWriteFunction(m_functionCode));
|
||||
//If it is a write function -> read registers
|
||||
if (!m_connected || !m_readOutputsBeforeWrite)
|
||||
return;
|
||||
else if (EUtils::ModbusIsWriteCoilsFunction(m_functionCode)){
|
||||
modbusReadData(m_slave,EUtils::ReadCoils,m_startAddr,m_numOfRegs);
|
||||
emit(refreshView());
|
||||
}
|
||||
else if (EUtils::ModbusIsWriteRegistersFunction(m_functionCode)){
|
||||
modbusReadData(m_slave,EUtils::ReadHoldRegs,m_startAddr,m_numOfRegs);
|
||||
emit(refreshView());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void ModbusAdapter::setScanRate(int scanRate)
|
||||
{
|
||||
m_scanRate = scanRate;
|
||||
}
|
||||
|
||||
void ModbusAdapter::resetCounters()
|
||||
{
|
||||
m_packets = 0;
|
||||
m_errors = 0;
|
||||
emit(refreshView());
|
||||
}
|
||||
|
||||
int ModbusAdapter::packets()
|
||||
{
|
||||
return m_packets;
|
||||
}
|
||||
|
||||
int ModbusAdapter::errors()
|
||||
{
|
||||
return m_errors;
|
||||
}
|
||||
|
||||
void ModbusAdapter::startPollTimer()
|
||||
{
|
||||
m_pollTimer->start(m_scanRate);
|
||||
}
|
||||
|
||||
void ModbusAdapter::stopPollTimer()
|
||||
{
|
||||
m_pollTimer->stop();
|
||||
}
|
||||
|
||||
void ModbusAdapter::setTimeOut(int timeOut)
|
||||
{
|
||||
|
||||
m_timeOut = timeOut;
|
||||
|
||||
}
|
||||
|
||||
QString ModbusAdapter::stripIP(QString ip)
|
||||
{
|
||||
//Strip zero's from IP
|
||||
QStringList ipBytes;
|
||||
QString res = "";
|
||||
int i;
|
||||
|
||||
ipBytes = ip.split(".");
|
||||
if (ipBytes.size() == 4){
|
||||
res = QString("").setNum(ipBytes[0].toInt());
|
||||
i = 1;
|
||||
while (i < ipBytes.size()){
|
||||
res = res + "." + QString("").setNum(ipBytes[i].toInt());
|
||||
i++;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
else
|
||||
return "";
|
||||
|
||||
}
|
||||
|
||||
void ModbusAdapter::setReadOutputsBeforeWrite(bool readOutputsBeforeWrite){
|
||||
|
||||
m_readOutputsBeforeWrite = readOutputsBeforeWrite;
|
||||
|
||||
}
|
||||
|
||||
|
||||
extern "C" {
|
||||
|
||||
void busMonitorRawResponseData(uint8_t * data, int dataLen)
|
||||
{
|
||||
m_instance->busMonitorResponseData(data, dataLen);
|
||||
}
|
||||
|
||||
void busMonitorRawRequestData(uint8_t * data, int dataLen)
|
||||
{
|
||||
m_instance->busMonitorRequestData(data, dataLen);
|
||||
}
|
||||
|
||||
}
|
||||
74
Applications/qModMaster/src/modbusadapter.h
Normal file
74
Applications/qModMaster/src/modbusadapter.h
Normal file
@@ -0,0 +1,74 @@
|
||||
#ifndef MODBUSADAPTER_H
|
||||
#define MODBUSADAPTER_H
|
||||
|
||||
#include <QObject>
|
||||
#include "modbus.h"
|
||||
#include "registersmodel.h"
|
||||
#include "rawdatamodel.h"
|
||||
#include <QTimer>
|
||||
#include "eutils.h"
|
||||
|
||||
class ModbusAdapter : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit ModbusAdapter(QObject *parent = 0);
|
||||
~ModbusAdapter();
|
||||
void busMonitorRequestData(uint8_t * data,int dataLen);
|
||||
void busMonitorResponseData(uint8_t * data,int dataLen);
|
||||
|
||||
void modbusConnectRTU(QString port, int baud, QChar parity, int dataBits, int stopBits, int RTS, int timeOut=1);
|
||||
void modbusConnectTCP(QString ip, int port, int timeOut=1);
|
||||
void modbusDisConnect();
|
||||
RegistersModel *regModel;
|
||||
RawDataModel *rawModel;
|
||||
bool isConnected();
|
||||
|
||||
void setSlave(int slave);
|
||||
void setFunctionCode(int functionCode);
|
||||
void setStartAddr(int addr);
|
||||
void setNumOfRegs(int num);
|
||||
void setBaseAddr(int baseAddr);
|
||||
void addItems();
|
||||
void setReadOutputsBeforeWrite(bool readOutputsBeforeWrite);
|
||||
|
||||
void setScanRate(int scanRate);
|
||||
void setTimeOut(int timeOut);
|
||||
void startPollTimer();
|
||||
void stopPollTimer();
|
||||
int packets();
|
||||
int errors();
|
||||
modbus_t * m_modbus;
|
||||
|
||||
private:
|
||||
void modbusReadData(int slave, int functionCode, int startAddress, int noOfItems);
|
||||
void modbusWriteData(int slave, int functionCode, int startAddress, int noOfItems);
|
||||
QString stripIP(QString ip);
|
||||
bool m_connected;
|
||||
int m_ModBusMode;
|
||||
int m_slave;
|
||||
int m_functionCode;
|
||||
int m_startAddr;
|
||||
int m_baseAddr;
|
||||
|
||||
int m_numOfRegs;
|
||||
int m_scanRate;
|
||||
QTimer *m_pollTimer;
|
||||
int m_packets;
|
||||
int m_errors;
|
||||
int m_timeOut;
|
||||
bool m_transactionIsPending;
|
||||
bool m_readOutputsBeforeWrite;
|
||||
uint8_t *dest;
|
||||
uint16_t *dest16;
|
||||
|
||||
signals:
|
||||
void refreshView();
|
||||
|
||||
public slots:
|
||||
void modbusTransaction();
|
||||
void resetCounters();
|
||||
|
||||
};
|
||||
|
||||
#endif // MODBUSADAPTER_H
|
||||
445
Applications/qModMaster/src/modbuscommsettings.cpp
Normal file
445
Applications/qModMaster/src/modbuscommsettings.cpp
Normal file
@@ -0,0 +1,445 @@
|
||||
#include "modbuscommsettings.h"
|
||||
#include "QsLog.h"
|
||||
|
||||
ModbusCommSettings::ModbusCommSettings(const QString &fileName, Format format , QObject *parent)
|
||||
: QSettings(fileName, format, parent)
|
||||
{
|
||||
this->loadSettings();
|
||||
}
|
||||
|
||||
void ModbusCommSettings::loadSettings()
|
||||
{
|
||||
|
||||
load(this);
|
||||
|
||||
}
|
||||
|
||||
void ModbusCommSettings::saveSettings()
|
||||
{
|
||||
|
||||
save(this);
|
||||
|
||||
}
|
||||
|
||||
QString ModbusCommSettings::TCPPort()
|
||||
{
|
||||
return m_TCPPort;
|
||||
}
|
||||
|
||||
void ModbusCommSettings::setTCPPort(QString tcpPort)
|
||||
{
|
||||
m_TCPPort = tcpPort;
|
||||
}
|
||||
|
||||
void ModbusCommSettings::setSlaveIP(QString IP)
|
||||
{
|
||||
m_slaveIP = IP;
|
||||
}
|
||||
|
||||
QString ModbusCommSettings::slaveIP()
|
||||
{
|
||||
return m_slaveIP;
|
||||
}
|
||||
|
||||
QString ModbusCommSettings::serialDev()
|
||||
{
|
||||
return m_serialDev;
|
||||
}
|
||||
|
||||
QString ModbusCommSettings::serialPort()
|
||||
{
|
||||
return m_serialPort;
|
||||
}
|
||||
|
||||
QString ModbusCommSettings::serialPortName()
|
||||
{
|
||||
return m_serialPortName;
|
||||
}
|
||||
|
||||
void ModbusCommSettings::setSerialPort(QString serialPort, QString serialDev)
|
||||
{
|
||||
int serialPortNo;
|
||||
|
||||
m_serialDev = serialDev;
|
||||
m_serialPort = serialPort;
|
||||
serialPortNo = serialPort.toInt();
|
||||
#ifdef Q_OS_WIN32
|
||||
if (serialPortNo > 9)
|
||||
m_serialPortName = "\\\\.\\COM" + serialPort;
|
||||
else
|
||||
m_serialPortName = "COM" + serialPort;
|
||||
#else
|
||||
m_serialPortName = serialDev;
|
||||
m_serialPortName += QStringLiteral("%1").arg(serialPort.toInt() - 1);
|
||||
#endif
|
||||
}
|
||||
|
||||
QString ModbusCommSettings::baud()
|
||||
{
|
||||
return m_baud;
|
||||
}
|
||||
|
||||
void ModbusCommSettings::setBaud(QString baud)
|
||||
{
|
||||
m_baud = baud;
|
||||
}
|
||||
|
||||
QString ModbusCommSettings::dataBits()
|
||||
{
|
||||
return m_dataBits;
|
||||
}
|
||||
|
||||
void ModbusCommSettings::setDataBits(QString dataBits)
|
||||
{
|
||||
m_dataBits = dataBits;
|
||||
}
|
||||
|
||||
QString ModbusCommSettings::stopBits()
|
||||
{
|
||||
return m_stopBits;
|
||||
}
|
||||
|
||||
void ModbusCommSettings::setStopBits(QString stopBits)
|
||||
{
|
||||
m_stopBits = stopBits;
|
||||
}
|
||||
|
||||
QString ModbusCommSettings::parity()
|
||||
{
|
||||
return m_parity;
|
||||
}
|
||||
|
||||
void ModbusCommSettings::setParity(QString parity)
|
||||
{
|
||||
m_parity = parity;
|
||||
}
|
||||
|
||||
QString ModbusCommSettings::RTS()
|
||||
{
|
||||
return m_RTS;
|
||||
}
|
||||
|
||||
void ModbusCommSettings::setRTS(QString RTS)
|
||||
{
|
||||
m_RTS = RTS;
|
||||
}
|
||||
|
||||
QString ModbusCommSettings::maxNoOfLines()
|
||||
{
|
||||
return m_maxNoOfLines;
|
||||
}
|
||||
|
||||
void ModbusCommSettings::setMaxNoOfLines(QString maxNoOfLines)
|
||||
{
|
||||
m_maxNoOfLines = maxNoOfLines;
|
||||
}
|
||||
|
||||
QString ModbusCommSettings::baseAddr()
|
||||
{
|
||||
return m_baseAddr;
|
||||
}
|
||||
|
||||
void ModbusCommSettings::setBaseAddr(QString baseAddr)
|
||||
{
|
||||
m_baseAddr = baseAddr;
|
||||
}
|
||||
|
||||
QString ModbusCommSettings::timeOut()
|
||||
{
|
||||
return m_timeOut;
|
||||
}
|
||||
|
||||
void ModbusCommSettings::setTimeOut(QString timeOut)
|
||||
{
|
||||
m_timeOut = timeOut;
|
||||
}
|
||||
|
||||
int ModbusCommSettings::endian()
|
||||
{
|
||||
return m_endian;
|
||||
}
|
||||
|
||||
void ModbusCommSettings::setEndian(int endian)
|
||||
{
|
||||
m_endian = endian;
|
||||
}
|
||||
|
||||
int ModbusCommSettings::loggingLevel()
|
||||
{
|
||||
return m_loggingLevel;
|
||||
}
|
||||
|
||||
bool ModbusCommSettings::readOutputsBeforeWrite()
|
||||
{
|
||||
return m_readOutputsBeforeWrite;
|
||||
}
|
||||
|
||||
int ModbusCommSettings::modbusMode()
|
||||
{
|
||||
return m_modbusMode;
|
||||
}
|
||||
|
||||
void ModbusCommSettings::setModbusMode(int modbusMode)
|
||||
{
|
||||
m_modbusMode = modbusMode;
|
||||
}
|
||||
|
||||
int ModbusCommSettings::slaveID()
|
||||
{
|
||||
return m_slaveID;
|
||||
}
|
||||
|
||||
void ModbusCommSettings::setSlaveID(int slaveID)
|
||||
{
|
||||
m_slaveID = slaveID;
|
||||
}
|
||||
|
||||
int ModbusCommSettings::scanRate()
|
||||
{
|
||||
return m_scanRate;
|
||||
}
|
||||
|
||||
void ModbusCommSettings::setScanRate(int scanRate)
|
||||
{
|
||||
m_scanRate = scanRate;
|
||||
}
|
||||
|
||||
int ModbusCommSettings::functionCode()
|
||||
{
|
||||
return m_functionCode;
|
||||
}
|
||||
|
||||
void ModbusCommSettings::setFunctionCode(int functionCode)
|
||||
{
|
||||
m_functionCode = functionCode;
|
||||
}
|
||||
|
||||
int ModbusCommSettings::startAddr()
|
||||
{
|
||||
return m_startAddr;
|
||||
}
|
||||
|
||||
void ModbusCommSettings::setStartAddr(int startAddr)
|
||||
{
|
||||
m_startAddr = startAddr;
|
||||
}
|
||||
|
||||
int ModbusCommSettings::noOfRegs()
|
||||
{
|
||||
return m_noOfRegs;
|
||||
}
|
||||
|
||||
void ModbusCommSettings::setNoOfRegs(int noOfRegs)
|
||||
{
|
||||
m_noOfRegs = noOfRegs;
|
||||
}
|
||||
|
||||
int ModbusCommSettings::frmt()
|
||||
{
|
||||
return m_frmt;
|
||||
}
|
||||
|
||||
void ModbusCommSettings::setFrmt(int frmt)
|
||||
{
|
||||
m_frmt = frmt;
|
||||
}
|
||||
|
||||
int ModbusCommSettings::floatPrecision()
|
||||
{
|
||||
return m_floatPrecision;
|
||||
}
|
||||
|
||||
void ModbusCommSettings::setfloatPrecision(int precision)
|
||||
{
|
||||
m_floatPrecision = precision;
|
||||
}
|
||||
|
||||
void ModbusCommSettings::loadSession(QString fName)
|
||||
{
|
||||
|
||||
QLOG_INFO()<< "Load session config from file " << fName;
|
||||
QSettings m_save_session(fName, QSettings::IniFormat, this);
|
||||
load(&m_save_session);
|
||||
|
||||
}
|
||||
|
||||
void ModbusCommSettings::saveSession(QString fName)
|
||||
{
|
||||
|
||||
QLOG_INFO()<< "Save session config to file " << fName;
|
||||
QSettings m_save_session(fName, QSettings::IniFormat, this);
|
||||
save(&m_save_session);
|
||||
|
||||
}
|
||||
|
||||
void ModbusCommSettings::load(QSettings *s)
|
||||
{
|
||||
|
||||
if (s->value("TCP/TCPPort").isNull())
|
||||
m_TCPPort = "502";
|
||||
else
|
||||
m_TCPPort = s->value("TCP/TCPPort").toString();
|
||||
|
||||
if (s->value("TCP/SlaveIP").isNull())
|
||||
m_slaveIP = "127.000.000.001";
|
||||
else
|
||||
m_slaveIP = s->value("TCP/SlaveIP").toString();
|
||||
|
||||
if (s->value("RTU/SerialDev").isNull())
|
||||
#ifdef Q_OS_WIN32
|
||||
m_serialDev = "COM";
|
||||
#else
|
||||
m_serialDev = "/dev/ttyS";
|
||||
#endif
|
||||
else
|
||||
#ifdef Q_OS_WIN32
|
||||
m_serialDev = "COM";
|
||||
#else
|
||||
m_serialDev = s->value("RTU/SerialDev").toString();
|
||||
#endif
|
||||
if (s->value("RTU/SerialPort").isNull())
|
||||
{
|
||||
m_serialPort = "1";
|
||||
#ifdef Q_OS_WIN32
|
||||
m_serialPortName = "COM" + m_serialPort;
|
||||
#else
|
||||
m_serialPortName = m_serialDev;
|
||||
m_serialPortName += QStringLiteral("%1").arg(m_serialPort.toInt() - 1);
|
||||
#endif
|
||||
}
|
||||
else {
|
||||
m_serialPort = s->value("RTU/SerialPort").toString();
|
||||
m_serialPortName = s->value("RTU/SerialPortName").toString();
|
||||
}
|
||||
|
||||
if (s->value("RTU/Baud").isNull())
|
||||
m_baud = "9600";
|
||||
else
|
||||
m_baud = s->value("RTU/Baud").toString();
|
||||
|
||||
if (s->value("RTU/DataBits").isNull())
|
||||
m_dataBits = "8";
|
||||
else
|
||||
m_dataBits = s->value("RTU/DataBits").toString();
|
||||
|
||||
if (s->value("RTU/StopBits").isNull())
|
||||
m_stopBits = "1";
|
||||
else
|
||||
m_stopBits = s->value("RTU/StopBits").toString();
|
||||
|
||||
if (s->value("RTU/Parity").isNull())
|
||||
m_parity = "None";
|
||||
else
|
||||
m_parity = s->value("RTU/Parity").toString();
|
||||
|
||||
if (s->value("RTU/RTS").isNull())
|
||||
#ifdef Q_OS_WIN32
|
||||
m_RTS = "Disable";
|
||||
#else
|
||||
m_RTS = "None";
|
||||
#endif
|
||||
else
|
||||
m_RTS = s->value("RTU/RTS").toString();
|
||||
|
||||
if (s->value("Var/MaxNoOfLines").toInt() == 0 ||
|
||||
s->value("Var/MaxNoOfLines").isNull())
|
||||
m_maxNoOfLines = "60";
|
||||
else
|
||||
m_maxNoOfLines = s->value("Var/MaxNoOfLines").toString();
|
||||
|
||||
if (s->value("Var/BaseAddr").isNull())
|
||||
m_baseAddr = "1";
|
||||
else
|
||||
m_baseAddr = s->value("Var/BaseAddr").toString();
|
||||
|
||||
if (s->value("Var/TimeOut").isNull())
|
||||
m_timeOut = "0";
|
||||
else
|
||||
m_timeOut = s->value("Var/TimeOut").toString();
|
||||
|
||||
if (s->value("Var/LoggingLevel").isNull())
|
||||
m_loggingLevel = 3; //warning level
|
||||
else
|
||||
m_loggingLevel = s->value("Var/LoggingLevel").toInt();
|
||||
|
||||
if (s->value("Var/ReadOutputsBeforeWrite").isNull())
|
||||
m_readOutputsBeforeWrite = true;
|
||||
else
|
||||
m_readOutputsBeforeWrite = s->value("Var/ReadOutputsBeforeWrite").toBool();
|
||||
|
||||
if (s->value("Var/Endian").isNull())
|
||||
m_endian = 0;
|
||||
else
|
||||
m_endian = s->value("Var/Endian").toInt();
|
||||
|
||||
if (s->value("Session/ModBusMode").isNull())
|
||||
m_modbusMode = 0; //RTU
|
||||
else
|
||||
m_modbusMode = s->value("Session/ModBusMode").toInt();
|
||||
|
||||
if (s->value("Session/SlaveID").isNull())
|
||||
m_slaveID = 1;
|
||||
else
|
||||
m_slaveID = s->value("Session/SlaveID").toInt();
|
||||
|
||||
if (s->value("Session/ScanRate").isNull())
|
||||
m_scanRate = 1000;
|
||||
else
|
||||
m_scanRate = s->value("Session/ScanRate").toInt();
|
||||
|
||||
if (s->value("Session/FunctionCode").isNull())
|
||||
m_functionCode = 0; //FC1 : Read Coils
|
||||
else
|
||||
m_functionCode = s->value("Session/FunctionCode").toInt();
|
||||
|
||||
if (s->value("Session/StartAddr").isNull())
|
||||
m_startAddr = 0;
|
||||
else
|
||||
m_startAddr = s->value("Session/StartAddr").toInt();
|
||||
|
||||
if (s->value("Session/NoOfRegs").isNull())
|
||||
m_noOfRegs = 0;
|
||||
else
|
||||
m_noOfRegs = s->value("Session/NoOfRegs").toInt();
|
||||
|
||||
if (s->value("Session/Format").isNull())
|
||||
m_frmt = 1; //Dec
|
||||
else
|
||||
m_frmt = s->value("Session/Format").toInt();
|
||||
|
||||
if (s->value("Session/FloatPrecision").isNull())
|
||||
m_floatPrecision = 3;
|
||||
else
|
||||
m_floatPrecision = s->value("Session/FloatPrecision").toInt();
|
||||
|
||||
}
|
||||
|
||||
void ModbusCommSettings::save(QSettings *s)
|
||||
{
|
||||
|
||||
s->setValue("TCP/TCPPort",m_TCPPort);
|
||||
s->setValue("TCP/SlaveIP",m_slaveIP);
|
||||
s->setValue("RTU/SerialDev",m_serialDev);
|
||||
s->setValue("RTU/SerialPort",m_serialPort);
|
||||
s->setValue("RTU/SerialPortName",m_serialPortName);
|
||||
s->setValue("RTU/Baud",m_baud);
|
||||
s->setValue("RTU/DataBits",m_dataBits);
|
||||
s->setValue("RTU/StopBits",m_stopBits);
|
||||
s->setValue("RTU/Parity",m_parity);
|
||||
s->setValue("RTU/RTS",m_RTS);
|
||||
s->setValue("Var/MaxNoOfLines",m_maxNoOfLines);
|
||||
s->setValue("Var/BaseAddr",m_baseAddr);
|
||||
s->setValue("Var/TimeOut",m_timeOut);
|
||||
s->setValue("Var/LoggingLevel",m_loggingLevel);
|
||||
s->setValue("Var/ReadOutputsBeforeWrite",m_readOutputsBeforeWrite);
|
||||
s->setValue("Var/Endian",m_endian);
|
||||
s->setValue("Session/ModBusMode",m_modbusMode);
|
||||
s->setValue("Session/SlaveID",m_slaveID);
|
||||
s->setValue("Session/ScanRate",m_scanRate);
|
||||
s->setValue("Session/FunctionCode",m_functionCode);
|
||||
s->setValue("Session/StartAddr",m_startAddr);
|
||||
s->setValue("Session/NoOfRegs",m_noOfRegs);
|
||||
s->setValue("Session/Format",m_frmt);
|
||||
s->setValue("Session/FloatPrecision",m_floatPrecision);
|
||||
|
||||
}
|
||||
107
Applications/qModMaster/src/modbuscommsettings.h
Normal file
107
Applications/qModMaster/src/modbuscommsettings.h
Normal file
@@ -0,0 +1,107 @@
|
||||
#ifndef MODBUSCOMMSETTINGS_H
|
||||
#define MODBUSCOMMSETTINGS_H
|
||||
|
||||
#include <QSettings>
|
||||
|
||||
class ModbusCommSettings : public QSettings
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit ModbusCommSettings(QObject *parent = 0) : QSettings(parent) { }
|
||||
ModbusCommSettings(const QString &fileName, Format format = QSettings::IniFormat, QObject *parent = 0);
|
||||
//TCP
|
||||
QString TCPPort();
|
||||
void setTCPPort(QString tcpPort);
|
||||
void setSlaveIP(QString IP);
|
||||
QString slaveIP();
|
||||
//Serial
|
||||
QString serialDev();
|
||||
QString serialPort();
|
||||
QString serialPortName();
|
||||
void setSerialPort(QString serialPort, QString serialDev = "");
|
||||
QString baud();
|
||||
void setBaud(QString baud);
|
||||
QString dataBits();
|
||||
void setDataBits(QString dataBits);
|
||||
QString stopBits();
|
||||
void setStopBits(QString stopBits);
|
||||
QString parity();
|
||||
void setParity(QString parity);
|
||||
QString RTS();
|
||||
void setRTS(QString RTS);
|
||||
//Var
|
||||
QString maxNoOfLines();
|
||||
void setMaxNoOfLines(QString maxNoOfLines);
|
||||
QString baseAddr();
|
||||
void setBaseAddr(QString baseAddr);
|
||||
QString timeOut();
|
||||
void setTimeOut(QString timeOut);
|
||||
int endian();
|
||||
void setEndian(int endian);
|
||||
void loadSettings();
|
||||
void saveSettings();
|
||||
//logging
|
||||
int loggingLevel();
|
||||
//
|
||||
bool readOutputsBeforeWrite();
|
||||
//session
|
||||
int modbusMode();
|
||||
void setModbusMode(int modbusMode);
|
||||
int slaveID();
|
||||
void setSlaveID(int slaveID);
|
||||
int scanRate();
|
||||
void setScanRate(int scanRate);
|
||||
int functionCode();
|
||||
void setFunctionCode(int functionCode);
|
||||
int startAddr();
|
||||
void setStartAddr(int startAddr);
|
||||
int noOfRegs();
|
||||
void setNoOfRegs(int noOfRegs);
|
||||
int frmt();
|
||||
void setFrmt(int frmt);
|
||||
int floatPrecision();
|
||||
void setfloatPrecision(int precision);
|
||||
void loadSession(QString fName);
|
||||
void saveSession(QString fName);
|
||||
|
||||
private:
|
||||
//TCP
|
||||
QString m_TCPPort;
|
||||
QString m_slaveIP;
|
||||
//Serial
|
||||
QString m_serialDev;
|
||||
QString m_serialPort;
|
||||
QString m_serialPortName;
|
||||
QString m_baud;
|
||||
QString m_dataBits;
|
||||
QString m_stopBits;
|
||||
QString m_parity;
|
||||
QString m_RTS;
|
||||
//Var
|
||||
QString m_maxNoOfLines;
|
||||
QString m_baseAddr;
|
||||
QString m_timeOut;
|
||||
int m_endian;
|
||||
void load(QSettings *s);
|
||||
void save(QSettings *s);
|
||||
//Log
|
||||
int m_loggingLevel;
|
||||
//read outputs before write
|
||||
bool m_readOutputsBeforeWrite;
|
||||
//Session vars
|
||||
int m_modbusMode;
|
||||
int m_slaveID;
|
||||
int m_scanRate;
|
||||
int m_functionCode;
|
||||
int m_startAddr;
|
||||
int m_noOfRegs;
|
||||
int m_frmt;
|
||||
int m_floatPrecision;
|
||||
|
||||
signals:
|
||||
|
||||
public slots:
|
||||
|
||||
};
|
||||
|
||||
#endif // MODBUSCOMMSETTINGS_H
|
||||
12
Applications/qModMaster/src/rawdatadelegate.cpp
Normal file
12
Applications/qModMaster/src/rawdatadelegate.cpp
Normal file
@@ -0,0 +1,12 @@
|
||||
#include "rawdatadelegate.h"
|
||||
#include <QtDebug>
|
||||
#include <QPainter>
|
||||
|
||||
//TODO : use delegate
|
||||
void RawDataDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option,
|
||||
const QModelIndex &index) const
|
||||
{
|
||||
|
||||
QStyledItemDelegate::paint(painter, option, index);
|
||||
|
||||
}
|
||||
17
Applications/qModMaster/src/rawdatadelegate.h
Normal file
17
Applications/qModMaster/src/rawdatadelegate.h
Normal file
@@ -0,0 +1,17 @@
|
||||
#ifndef RAWDATADELEGATE_H
|
||||
#define RAWDATADELEGATE_H
|
||||
|
||||
#include <QStyledItemDelegate>
|
||||
|
||||
class RawDataDelegate : public QStyledItemDelegate
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
RawDataDelegate(QWidget *parent = 0) : QStyledItemDelegate(parent) {}
|
||||
|
||||
void paint(QPainter *painter, const QStyleOptionViewItem &option,
|
||||
const QModelIndex &index) const;
|
||||
|
||||
};
|
||||
#endif // RAWDATADELEGATE_H
|
||||
44
Applications/qModMaster/src/rawdatamodel.cpp
Normal file
44
Applications/qModMaster/src/rawdatamodel.cpp
Normal file
@@ -0,0 +1,44 @@
|
||||
#include "rawdatamodel.h"
|
||||
#include "QsLog.h"
|
||||
#include <QtDebug>
|
||||
|
||||
RawDataModel::RawDataModel(QObject *parent) :
|
||||
QObject(parent)
|
||||
{
|
||||
model = new QStringListModel(this);
|
||||
m_addLinesEnabled = false;
|
||||
}
|
||||
|
||||
void RawDataModel::addLine(QString line)
|
||||
{
|
||||
|
||||
if (!m_addLinesEnabled) return;
|
||||
|
||||
QLOG_TRACE() << "Raw Data Model Line = " << line << " , No of lines = " << m_rawData.length();
|
||||
|
||||
if (m_rawData.length() == m_maxNoOfLines)
|
||||
m_rawData.removeFirst();
|
||||
m_rawData.append(line);
|
||||
model->setStringList(m_rawData);
|
||||
|
||||
}
|
||||
|
||||
void RawDataModel::clear()
|
||||
{
|
||||
|
||||
QLOG_TRACE() << "Raw Data Model cleared" ;
|
||||
|
||||
m_rawData.clear();
|
||||
model->setStringList(m_rawData);
|
||||
|
||||
}
|
||||
|
||||
void RawDataModel::setMaxNoOfLines(int noOfLines)
|
||||
{
|
||||
m_maxNoOfLines = noOfLines;
|
||||
}
|
||||
|
||||
void RawDataModel::enableAddLines(bool en)
|
||||
{
|
||||
m_addLinesEnabled = en;
|
||||
}
|
||||
31
Applications/qModMaster/src/rawdatamodel.h
Normal file
31
Applications/qModMaster/src/rawdatamodel.h
Normal file
@@ -0,0 +1,31 @@
|
||||
#ifndef RAWDATAMODEL_H
|
||||
#define RAWDATAMODEL_H
|
||||
|
||||
#include <QObject>
|
||||
#include <QStringListModel>
|
||||
|
||||
class RawDataModel : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit RawDataModel(QObject *parent = 0);
|
||||
|
||||
QStringListModel *model;
|
||||
void addLine(QString line);
|
||||
void enableAddLines(bool en);
|
||||
void clear();
|
||||
void setMaxNoOfLines(int noOfLines);
|
||||
int maxNoOfLines() { return m_maxNoOfLines; }
|
||||
|
||||
signals:
|
||||
|
||||
public slots:
|
||||
|
||||
private:
|
||||
QStringList m_rawData;
|
||||
int m_maxNoOfLines;
|
||||
bool m_addLinesEnabled;
|
||||
|
||||
};
|
||||
|
||||
#endif // RAWDATAMODEL_H
|
||||
158
Applications/qModMaster/src/registersdatadelegate.cpp
Normal file
158
Applications/qModMaster/src/registersdatadelegate.cpp
Normal file
@@ -0,0 +1,158 @@
|
||||
#include "registersdatadelegate.h"
|
||||
#include "mainwindow.h"
|
||||
#include "QsLog.h"
|
||||
#include <QtDebug>
|
||||
#include <QPainter>
|
||||
#include <QSpinBox>
|
||||
#include <QLineEdit>
|
||||
|
||||
#include "eutils.h"
|
||||
|
||||
void RegistersDataDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option,
|
||||
const QModelIndex &index) const
|
||||
{
|
||||
|
||||
QStyledItemDelegate::paint(painter, option, index);
|
||||
|
||||
}
|
||||
|
||||
QWidget *RegistersDataDelegate::createEditor(QWidget *parent,
|
||||
const QStyleOptionViewItem &/* option */,
|
||||
const QModelIndex &/* index */) const
|
||||
{
|
||||
|
||||
if (m_frmt == EUtils::Bin) {//Bin
|
||||
if (m_is16Bit) {
|
||||
QLineEdit *editor = new QLineEdit(parent);
|
||||
editor->setInputMask("bbbbbbbbbbbbbbbb");
|
||||
return editor;
|
||||
}
|
||||
else {
|
||||
QSpinBox *editor = new QSpinBox(parent);
|
||||
editor->setMinimum(0);
|
||||
editor->setMaximum(1);
|
||||
return editor;
|
||||
}
|
||||
}
|
||||
else if (m_frmt == EUtils::Dec) {//Dec
|
||||
QLineEdit *editor = new QLineEdit(parent);
|
||||
QRegularExpression rx("-{0,1}[0-9]{1,5}");
|
||||
QValidator *validator = new QRegularExpressionValidator(rx);
|
||||
editor->setValidator(validator);
|
||||
return editor;
|
||||
}
|
||||
else if (m_frmt == EUtils::Float) {//Float
|
||||
QLineEdit *editor = new QLineEdit(parent);
|
||||
QRegularExpression rx("^[-+]?[0-9]*\\.?[0-9]+([eE][-+]?[0-9]+)?$");
|
||||
QValidator *validator = new QRegularExpressionValidator(rx);
|
||||
editor->setValidator(validator);
|
||||
return editor;
|
||||
}
|
||||
else if (m_frmt == EUtils::Hex) {//Hex
|
||||
QLineEdit *editor = new QLineEdit(parent);
|
||||
editor->setInputMask("hhhh");
|
||||
return editor;
|
||||
}
|
||||
else {//Default = Dec
|
||||
QLineEdit *editor = new QLineEdit(parent);
|
||||
QRegularExpression rx("-{0,1}[0-9]{1,5}");
|
||||
QValidator *validator = new QRegularExpressionValidator(rx);
|
||||
editor->setValidator(validator);
|
||||
return editor;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void RegistersDataDelegate::setEditorData(QWidget *editor,
|
||||
const QModelIndex &index) const
|
||||
{
|
||||
|
||||
QString value = index.model()->data(index, Qt::EditRole).toString();
|
||||
|
||||
if (m_frmt == EUtils::Bin && !m_is16Bit) {//Bin
|
||||
QSpinBox *spinBox = static_cast<QSpinBox*>(editor);
|
||||
spinBox->setValue(value.toInt());
|
||||
}
|
||||
else { //Bin 16 Bit, Dec, Hex, Float?
|
||||
QLineEdit *lineEdit = static_cast<QLineEdit*>(editor);
|
||||
lineEdit->setText(value);
|
||||
}
|
||||
}
|
||||
|
||||
void RegistersDataDelegate::setModelData(QWidget *editor, QAbstractItemModel *model,
|
||||
const QModelIndex &index) const
|
||||
{
|
||||
|
||||
QString value;
|
||||
int intVal;
|
||||
float floatVal;
|
||||
bool ok;
|
||||
|
||||
if (m_frmt == EUtils::Bin && !m_is16Bit) {//Bin
|
||||
QSpinBox *spinBox = static_cast<QSpinBox*>(editor);
|
||||
intVal = (spinBox->text()).toInt(&ok,m_frmt);
|
||||
value = EUtils::formatValue(intVal, m_frmt, m_is16Bit, m_isSigned);
|
||||
}
|
||||
else if (m_frmt == EUtils::Float){ //Float
|
||||
QLineEdit *lineEdit = static_cast<QLineEdit*>(editor);
|
||||
floatVal = (lineEdit->text()).toFloat(&ok);
|
||||
value = EUtils::formatValue32(floatVal, m_floatPrecision);
|
||||
}
|
||||
else { //Bin 16 Bit, Dec, Hex
|
||||
QLineEdit *lineEdit = static_cast<QLineEdit*>(editor);
|
||||
intVal = (lineEdit->text()).toInt(&ok,m_frmt);
|
||||
if (intVal > 65535){
|
||||
mainWin->showUpInfoBar(tr("Set value failed\nValue is greater than 65535."), InfoBar::Error);
|
||||
QLOG_WARN() << "Set value failed. Value is greater than 65535";
|
||||
return;
|
||||
}
|
||||
else if (intVal < -32768){
|
||||
mainWin->showUpInfoBar(tr("Set value failed\nValue is smaller than -32768."), InfoBar::Error);
|
||||
QLOG_WARN() << "Set value failed. Value is smaller than -32768";
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
mainWin->hideInfoBar();
|
||||
}
|
||||
value = EUtils::formatValue(intVal, m_frmt, m_is16Bit, m_isSigned);
|
||||
}
|
||||
|
||||
QLOG_TRACE() << "Set model data value = " << value;
|
||||
|
||||
model->setData(index, value, Qt::EditRole);
|
||||
}
|
||||
|
||||
void RegistersDataDelegate::updateEditorGeometry(QWidget *editor,
|
||||
const QStyleOptionViewItem &option, const QModelIndex &/* index */) const
|
||||
{
|
||||
editor->setGeometry(option.rect);
|
||||
}
|
||||
|
||||
void RegistersDataDelegate::setFrmt(int frmt)
|
||||
{
|
||||
|
||||
m_frmt = frmt;
|
||||
|
||||
}
|
||||
|
||||
void RegistersDataDelegate::setIs16Bit(bool is16Bit)
|
||||
{
|
||||
|
||||
m_is16Bit = is16Bit;
|
||||
|
||||
}
|
||||
|
||||
void RegistersDataDelegate::setIsSigned(bool isSigned)
|
||||
{
|
||||
|
||||
m_isSigned = isSigned;
|
||||
|
||||
}
|
||||
|
||||
void RegistersDataDelegate::setFloatPrecision(int precision)
|
||||
{
|
||||
|
||||
m_floatPrecision = precision;
|
||||
|
||||
}
|
||||
39
Applications/qModMaster/src/registersdatadelegate.h
Normal file
39
Applications/qModMaster/src/registersdatadelegate.h
Normal file
@@ -0,0 +1,39 @@
|
||||
#ifndef REGISTERSDELEGATE_H
|
||||
#define REGISTERSDELEGATE_H
|
||||
|
||||
#include <QStyledItemDelegate>
|
||||
|
||||
class RegistersDataDelegate : public QStyledItemDelegate
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
private:
|
||||
int m_frmt;
|
||||
bool m_is16Bit;
|
||||
bool m_isSigned;
|
||||
int m_floatPrecision;
|
||||
|
||||
public:
|
||||
RegistersDataDelegate(QWidget *parent = 0) : QStyledItemDelegate(parent) { }
|
||||
|
||||
void paint(QPainter *painter, const QStyleOptionViewItem &option,
|
||||
const QModelIndex &index) const;
|
||||
|
||||
QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem &option,
|
||||
const QModelIndex &index) const;
|
||||
|
||||
void setEditorData(QWidget *editor, const QModelIndex &index) const;
|
||||
void setModelData(QWidget *editor, QAbstractItemModel *model,
|
||||
const QModelIndex &index) const;
|
||||
|
||||
void updateEditorGeometry(QWidget *editor,
|
||||
const QStyleOptionViewItem &option, const QModelIndex &index) const;
|
||||
|
||||
void setFrmt(int frmt);
|
||||
void setIs16Bit(bool is16Bit);
|
||||
void setIsSigned(bool isSigned);
|
||||
void setFloatPrecision(int precision);
|
||||
|
||||
};
|
||||
|
||||
#endif // REGISTERSDELEGATE_H
|
||||
383
Applications/qModMaster/src/registersmodel.cpp
Normal file
383
Applications/qModMaster/src/registersmodel.cpp
Normal file
@@ -0,0 +1,383 @@
|
||||
#include "registersmodel.h"
|
||||
#include "QsLog.h"
|
||||
#include <QStandardItem>
|
||||
#include <QtDebug>
|
||||
|
||||
#include "eutils.h"
|
||||
|
||||
RegistersModel::RegistersModel(QObject *parent) :
|
||||
QObject(parent)
|
||||
{
|
||||
model = new QStandardItemModel(0,0,this);
|
||||
m_regDataDelegate = new RegistersDataDelegate(0);
|
||||
m_noOfItems = 0;
|
||||
m_is16Bit = false;
|
||||
m_isSigned = false;
|
||||
m_startAddrBase = 10;
|
||||
clear();
|
||||
}
|
||||
|
||||
void RegistersModel::addItems(int startAddress, int noOfItems, bool valueIsEditable)
|
||||
{
|
||||
int row;
|
||||
int col;
|
||||
m_startAddress = startAddress;
|
||||
m_noOfItems = noOfItems;
|
||||
|
||||
QLOG_TRACE() << "Registers Model Address = " << startAddress << " , noOfItems = " << noOfItems
|
||||
<< " , first row = " << m_firstRow << " , last row = " << m_lastRow;
|
||||
|
||||
//Format Vertical - Horizontal Headers
|
||||
clear();
|
||||
if (noOfItems > 1) {
|
||||
if (m_frmt == EUtils::Float){
|
||||
m_firstRow = 0;
|
||||
m_lastRow = (noOfItems - 1) / 20;
|
||||
model->setHorizontalHeaderLabels(QStringList()<<RegModelFloatHeaderLabels[0]<<RegModelFloatHeaderLabels[1]
|
||||
<<RegModelFloatHeaderLabels[2]<<RegModelFloatHeaderLabels[3]
|
||||
<<RegModelFloatHeaderLabels[4]<<RegModelFloatHeaderLabels[5]
|
||||
<<RegModelFloatHeaderLabels[6]<<RegModelFloatHeaderLabels[7]
|
||||
<<RegModelFloatHeaderLabels[8]<<RegModelFloatHeaderLabels[9]);
|
||||
|
||||
|
||||
QStringList vertHeader;
|
||||
for (int i = m_firstRow; i <= m_lastRow; i++) {
|
||||
vertHeader<<QString("%1").arg(startAddress + i * 20, 2, 10, QLatin1Char('0'));
|
||||
}
|
||||
model->setVerticalHeaderLabels(vertHeader);
|
||||
}
|
||||
else {
|
||||
m_firstRow = 0;
|
||||
m_lastRow = (noOfItems - 1) / 10;
|
||||
model->setHorizontalHeaderLabels(QStringList()<<RegModelHeaderLabels[0]<<RegModelHeaderLabels[1]
|
||||
<<RegModelHeaderLabels[2]<<RegModelHeaderLabels[3]
|
||||
<<RegModelHeaderLabels[4]<<RegModelHeaderLabels[5]
|
||||
<<RegModelHeaderLabels[6]<<RegModelHeaderLabels[7]
|
||||
<<RegModelHeaderLabels[8]<<RegModelHeaderLabels[9]);
|
||||
|
||||
QStringList vertHeader;
|
||||
for (int i = m_firstRow; i <= m_lastRow; i++) {
|
||||
vertHeader<<QString("%1").arg(startAddress + i * 10, 2, 10, QLatin1Char('0'));
|
||||
}
|
||||
model->setVerticalHeaderLabels(vertHeader);
|
||||
}
|
||||
}
|
||||
else {
|
||||
model->setHorizontalHeaderLabels(QStringList()<<RegModelHeaderLabels[0]);
|
||||
model->setVerticalHeaderLabels(QStringList()<<QString("%1").arg(startAddress, 2, 10, QLatin1Char('0')));
|
||||
}
|
||||
|
||||
//Add data to model
|
||||
if (noOfItems == 1){
|
||||
QStandardItem *valueItem = new QStandardItem("-");model->setItem(0, 0, valueItem);
|
||||
valueItem->setEditable(valueIsEditable);
|
||||
}
|
||||
else {
|
||||
if (m_frmt == EUtils::Float){
|
||||
m_firstRow = 0;
|
||||
m_lastRow = (noOfItems - 1) / 20;
|
||||
for (int i = m_firstRow; i <= m_lastRow; i++) {
|
||||
row = i;
|
||||
for (int j = 0; j < 10; j++) {
|
||||
col = j;
|
||||
if ((row * 10 + col) >= (noOfItems / 2)){//not used cells
|
||||
QStandardItem *valueItem = new QStandardItem("x");model->setItem(row, col, valueItem);
|
||||
valueItem->setEditable(false);
|
||||
valueItem->setForeground(QBrush(Qt::red));
|
||||
valueItem->setBackground(QBrush(Qt::lightGray));
|
||||
}
|
||||
else {
|
||||
QStandardItem *valueItem = new QStandardItem("-");model->setItem(row, col, valueItem);
|
||||
valueItem->setEditable(valueIsEditable);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
m_firstRow = 0;
|
||||
m_lastRow = (noOfItems - 1) / 10;
|
||||
for (int i = m_firstRow; i <= m_lastRow; i++) {
|
||||
row = i;
|
||||
for (int j = 0; j < 10; j++) {
|
||||
col = j;
|
||||
if ((row * 10 + col) >= (noOfItems)){//not used cells
|
||||
QStandardItem *valueItem = new QStandardItem("x");model->setItem(row, col, valueItem);
|
||||
valueItem->setEditable(false);
|
||||
valueItem->setForeground(QBrush(Qt::red));
|
||||
valueItem->setBackground(QBrush(Qt::lightGray));
|
||||
}
|
||||
else {
|
||||
QStandardItem *valueItem = new QStandardItem("-");model->setItem(row, col, valueItem);
|
||||
valueItem->setEditable(valueIsEditable);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
emit(refreshView());
|
||||
|
||||
}
|
||||
|
||||
void RegistersModel::setNoValidValues()
|
||||
{
|
||||
|
||||
int row;
|
||||
int col;
|
||||
//if we have no valid values we set as value = '-/-'
|
||||
|
||||
if (m_frmt == EUtils::Float){
|
||||
for (int i = 0; i < (m_noOfItems / 2); i++){
|
||||
row = i / 10;
|
||||
col = i % 10;
|
||||
QModelIndex index = model->index(row, col, QModelIndex());
|
||||
model->setData(index,QBrush(Qt::red),Qt::ForegroundRole);
|
||||
model->setData(index,"-/-",Qt::DisplayRole);
|
||||
}
|
||||
}
|
||||
else {
|
||||
for (int i = 0; i < m_noOfItems; i++){
|
||||
row = i / 10;
|
||||
col = i % 10;
|
||||
QModelIndex index = model->index(row, col, QModelIndex());
|
||||
model->setData(index,QBrush(Qt::red),Qt::ForegroundRole);
|
||||
model->setData(index,"-/-",Qt::DisplayRole);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void RegistersModel::setValue(int idx, int value)
|
||||
{
|
||||
int row;
|
||||
int col;
|
||||
QString convertedValue;
|
||||
|
||||
convertedValue = EUtils::formatValue(value, m_frmt, m_is16Bit, m_isSigned);
|
||||
|
||||
//set model data
|
||||
if (m_noOfItems == 1){
|
||||
row = 0;
|
||||
col = 0;
|
||||
}
|
||||
else {
|
||||
row = (idx) / 10;
|
||||
col = (idx) % 10;
|
||||
}
|
||||
|
||||
QModelIndex index = model->index(row, col, QModelIndex());
|
||||
model->setData(index,QBrush(Qt::black),Qt::ForegroundRole);
|
||||
model->setData(index,convertedValue,Qt::DisplayRole);
|
||||
model->setData(index,QString("Address : %1").arg(m_startAddress + idx, 1, m_startAddrBase).toUpper(),Qt::ToolTipRole);
|
||||
}
|
||||
|
||||
void RegistersModel::setValue32(int idx, int valueHi, int valueLo)
|
||||
{//update model with float values
|
||||
int row;
|
||||
int col;
|
||||
QString convertedValue;
|
||||
|
||||
convertedValue = EUtils::formatValue32(valueHi, valueLo, m_endian, m_floatPrecision);
|
||||
|
||||
//set model data
|
||||
if (m_noOfItems == 1){
|
||||
row = 0;
|
||||
col = 0;
|
||||
}
|
||||
else {
|
||||
row = (idx) / 10;
|
||||
col = (idx) % 10;
|
||||
}
|
||||
|
||||
QModelIndex index = model->index(row, col, QModelIndex());
|
||||
model->setData(index,QBrush(Qt::black),Qt::ForegroundRole);
|
||||
model->setData(index,convertedValue,Qt::DisplayRole);
|
||||
model->setData(index,QString("Address : %1").arg(m_startAddress + 2*idx, 1, m_startAddrBase).toUpper(),Qt::ToolTipRole);
|
||||
}
|
||||
|
||||
int RegistersModel::value(int idx)
|
||||
{
|
||||
QString stringVal;
|
||||
int intVal;
|
||||
bool ok;
|
||||
|
||||
//Get Value
|
||||
stringVal = strValue(idx);
|
||||
intVal = stringVal.toInt(&ok,m_frmt);
|
||||
if (ok)
|
||||
return intVal;
|
||||
else
|
||||
return -1;
|
||||
|
||||
}
|
||||
|
||||
float RegistersModel::floatValue(int idx)
|
||||
{
|
||||
QString stringVal;
|
||||
float floatVal;
|
||||
bool ok;
|
||||
|
||||
//Get Value
|
||||
stringVal = strValue(idx);
|
||||
floatVal = stringVal.toFloat(&ok);
|
||||
if (ok)
|
||||
return floatVal;
|
||||
else
|
||||
return -1;
|
||||
|
||||
}
|
||||
|
||||
QString RegistersModel::strValue(int idx)
|
||||
{
|
||||
int row;
|
||||
int col;
|
||||
|
||||
//get model data
|
||||
if (m_noOfItems == 1){
|
||||
row = 0;
|
||||
col = 0;
|
||||
}
|
||||
else {
|
||||
row = (idx) / 10;
|
||||
col = (idx) % 10;
|
||||
}
|
||||
QModelIndex index = model->index(row, col, QModelIndex());
|
||||
QVariant value = model->data(index,Qt::DisplayRole);
|
||||
if (value.canConvert<QString>())
|
||||
return value.toString();
|
||||
else
|
||||
return "-/-";
|
||||
|
||||
}
|
||||
|
||||
void RegistersModel::changeFrmt(int frmt)
|
||||
{
|
||||
|
||||
QString stringVal;
|
||||
int intVal;
|
||||
int row;
|
||||
int col;
|
||||
bool ok;
|
||||
QString convertedVal;
|
||||
|
||||
QLOG_TRACE()<< "Registers Model changed format from " << m_frmt << " to " << frmt ;
|
||||
|
||||
//change base
|
||||
for (int idx = 0; idx < m_noOfItems ; idx++) {
|
||||
//Get Value
|
||||
stringVal = strValue(idx);
|
||||
intVal = stringVal.toInt(&ok,m_frmt);
|
||||
//Format Value
|
||||
if (ok)
|
||||
convertedVal = EUtils::formatValue(intVal, frmt, m_is16Bit, m_isSigned);
|
||||
else
|
||||
convertedVal = "-/-";
|
||||
//Update
|
||||
if (m_noOfItems == 1){
|
||||
row = 0;
|
||||
col = 0;
|
||||
}
|
||||
else {
|
||||
row = (idx) / 10;
|
||||
col = (idx) % 10;
|
||||
}
|
||||
QModelIndex index = model->index(row, col, QModelIndex());
|
||||
model->setData(index,convertedVal,Qt::DisplayRole);
|
||||
model->setData(index,QString("Address : %1").arg(m_startAddress + idx, m_startAddrBase).toUpper(),Qt::ToolTipRole);
|
||||
}
|
||||
|
||||
emit(refreshView());
|
||||
|
||||
}
|
||||
|
||||
void RegistersModel::clear()
|
||||
{
|
||||
|
||||
QLOG_TRACE()<< "Registers Model Cleared" ;
|
||||
|
||||
//Clear model
|
||||
model->clear();
|
||||
|
||||
}
|
||||
|
||||
void RegistersModel::setStartAddrBase(int base)
|
||||
{
|
||||
|
||||
QLOG_TRACE()<< "Registers Model start addr set base = " << base ;
|
||||
|
||||
m_startAddrBase = base;
|
||||
changeFrmt(m_frmt);
|
||||
|
||||
}
|
||||
|
||||
void RegistersModel::setFrmt(int frmt)
|
||||
{
|
||||
|
||||
QLOG_TRACE()<< "Registers Model set base = " << frmt ;
|
||||
|
||||
m_regDataDelegate->setFrmt(frmt);
|
||||
changeFrmt(frmt);
|
||||
m_frmt = frmt;
|
||||
|
||||
}
|
||||
|
||||
int RegistersModel::getFrmt()
|
||||
{
|
||||
|
||||
QLOG_TRACE()<< "Registers Model get format = " << m_frmt ;
|
||||
|
||||
return m_frmt;
|
||||
|
||||
}
|
||||
|
||||
void RegistersModel::setIs16Bit(bool is16Bit)
|
||||
{
|
||||
|
||||
QLOG_TRACE()<< "Registers Model Is16Bit = " << is16Bit ;
|
||||
m_is16Bit = is16Bit;
|
||||
m_regDataDelegate->setIs16Bit(is16Bit);
|
||||
|
||||
}
|
||||
|
||||
void RegistersModel::setIsSigned(bool isSigned)
|
||||
{
|
||||
|
||||
QLOG_TRACE()<< "Registers Model IsSigned = " << isSigned ;
|
||||
m_isSigned = isSigned;
|
||||
m_regDataDelegate->setIsSigned(isSigned);
|
||||
changeFrmt(m_frmt);
|
||||
|
||||
}
|
||||
|
||||
void RegistersModel::setEndian(int endian)
|
||||
{
|
||||
|
||||
QLOG_TRACE()<< "Registers Model endianness = " << endian ;
|
||||
m_endian = endian;
|
||||
|
||||
}
|
||||
|
||||
int RegistersModel::getEndian()
|
||||
{
|
||||
|
||||
QLOG_TRACE()<< "Registers Model endianness = " << m_endian ;
|
||||
return m_endian;
|
||||
|
||||
}
|
||||
|
||||
void RegistersModel::setFloatPrecision(int precision)
|
||||
{
|
||||
|
||||
QLOG_TRACE()<< "Registers Model float precision = " << precision ;
|
||||
m_floatPrecision = precision;
|
||||
m_regDataDelegate->setFloatPrecision(precision);
|
||||
|
||||
}
|
||||
|
||||
RegistersDataDelegate* RegistersModel::itemDelegate()
|
||||
{
|
||||
|
||||
return m_regDataDelegate;
|
||||
|
||||
}
|
||||
59
Applications/qModMaster/src/registersmodel.h
Normal file
59
Applications/qModMaster/src/registersmodel.h
Normal file
@@ -0,0 +1,59 @@
|
||||
#ifndef REGISTERSMODEL_H
|
||||
#define REGISTERSMODEL_H
|
||||
|
||||
#include <QObject>
|
||||
#include <QStandardItemModel>
|
||||
#include "registersdatadelegate.h"
|
||||
|
||||
static const QString RegModelHeaderLabels[]={"+00", "+01", "+02", "+03", "+04", "+05", "+06", "+07", "+08", "+09"};
|
||||
static const QString RegModelFloatHeaderLabels[]={"+00", "+02", "+04", "+06", "+08", "+10", "+12", "+14", "+16", "+18"};
|
||||
static const int AddressColumn=0;
|
||||
static const int ValueColumn=1;
|
||||
|
||||
class RegistersModel : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit RegistersModel(QObject *parent = 0);
|
||||
|
||||
void addItems(int startAddress, int noOfItems, bool valueIsEditable);
|
||||
void setValue(int idx, int value);
|
||||
void setValue32(int idx, int valueHi, int valueLo);
|
||||
void setFrmt(int frmt);
|
||||
int getFrmt();
|
||||
void setStartAddrBase(int base);
|
||||
void setIs16Bit(bool is16Bit);
|
||||
void setIsSigned(bool isSigned);
|
||||
void setEndian(int endian);
|
||||
int getEndian();
|
||||
void setFloatPrecision(int precision);
|
||||
QString strValue(int idx);
|
||||
int value(int idx);
|
||||
float floatValue(int idx);
|
||||
QStandardItemModel *model;
|
||||
void clear();
|
||||
void setNoValidValues();
|
||||
RegistersDataDelegate* itemDelegate();
|
||||
|
||||
private:
|
||||
void changeFrmt(int frmt);
|
||||
int m_startAddress;
|
||||
int m_noOfItems;
|
||||
int m_firstRow;
|
||||
int m_lastRow;
|
||||
bool m_is16Bit;
|
||||
bool m_isSigned;
|
||||
int m_startAddrBase;
|
||||
int m_frmt;
|
||||
int m_endian;
|
||||
int m_floatPrecision;
|
||||
RegistersDataDelegate *m_regDataDelegate;
|
||||
|
||||
signals:
|
||||
void refreshView();
|
||||
|
||||
public slots:
|
||||
|
||||
};
|
||||
|
||||
#endif // REGISTERSMODEL_H
|
||||
Reference in New Issue
Block a user