|
@@ -17409,7 +17409,8 @@ class ModbusRTUDevice : public QObject
|
17409
|
17409
|
void svuResponse(QByteArray response);
|
17410
|
17410
|
void requestMeasurement();
|
17411
|
17411
|
void mResponse(QByteArray response);
|
17412
|
|
- void ignore(QByteArray response);@/
|
|
17412
|
+ void ignore(QByteArray response);
|
|
17413
|
+ void timeout();@/
|
17413
|
17414
|
private:@/
|
17414
|
17415
|
QextSerialPort *port;
|
17415
|
17416
|
QByteArray responseBuffer;
|
|
@@ -17418,6 +17419,7 @@ class ModbusRTUDevice : public QObject
|
17418
|
17419
|
QList<char *> callbackQueue;
|
17419
|
17420
|
quint16 calculateCRC(QByteArray data);
|
17420
|
17421
|
QTimer *messageDelayTimer;
|
|
17422
|
+ QTimer *commTimeout;
|
17421
|
17423
|
int delayTime;
|
17422
|
17424
|
char station;
|
17423
|
17425
|
int decimalPosition;
|
|
@@ -17449,9 +17451,10 @@ immediately upon construction.
|
17449
|
17451
|
|
17450
|
17452
|
@<ModbusRTUDevice implementation@>=
|
17451
|
17453
|
ModbusRTUDevice::ModbusRTUDevice(DeviceTreeModel *model,@| const QModelIndex &index)
|
17452
|
|
-: QObject(NULL), messageDelayTimer(new QTimer), unitIsF(@[true@]), readingsv(@[false@]),
|
|
17454
|
+: QObject(NULL), messageDelayTimer(new QTimer), commTimeout(new QTimer), unitIsF(@[true@]), readingsv(@[false@]),
|
17453
|
17455
|
waiting(@[false@])@/
|
17454
|
17456
|
{@/
|
|
17457
|
+qDebug() << "Initializing Modbus RTU Device";
|
17455
|
17458
|
QDomElement portReferenceElement = model->referenceElement(model->data(index,
|
17456
|
17459
|
Qt::UserRole).toString());
|
17457
|
17460
|
QDomNodeList portConfigData = portReferenceElement.elementsByTagName("attribute");
|
|
@@ -17469,7 +17472,9 @@ ModbusRTUDevice::ModbusRTUDevice(DeviceTreeModel *model,@| const QModelIndex &in
|
17469
|
17472
|
double temp = ((double)(1) / (double)(baudRate)) * 48;
|
17470
|
17473
|
delayTime = (int)(temp * 3000);
|
17471
|
17474
|
messageDelayTimer->setSingleShot(true);
|
|
17475
|
+ commTimeout->setSingleShot(true);
|
17472
|
17476
|
connect(messageDelayTimer, SIGNAL(timeout()), this, SLOT(sendNextMessage()));
|
|
17477
|
+ connect(commTimeout, SIGNAL(timeout()), this, SLOT(timeout()));
|
17473
|
17478
|
port->setDataBits(DATA_8);
|
17474
|
17479
|
port->setParity((ParityType)attributes.value("parity").toInt());
|
17475
|
17480
|
port->setStopBits((StopBitsType)attributes.value("stop").toInt());
|
|
@@ -17632,6 +17637,7 @@ void ModbusRTUDevice::unitResponse(QByteArray response)
|
17632
|
17637
|
{
|
17633
|
17638
|
unitIsF = @[false@];
|
17634
|
17639
|
}
|
|
17640
|
+ qDebug() << "Received unit response";
|
17635
|
17641
|
}
|
17636
|
17642
|
|
17637
|
17643
|
void ModbusRTUDevice::svlResponse(QByteArray response)
|
|
@@ -17646,6 +17652,7 @@ void ModbusRTUDevice::svlResponse(QByteArray response)
|
17646
|
17652
|
outputSVLower /= 10;
|
17647
|
17653
|
}
|
17648
|
17654
|
emit SVLowerChanged(outputSVLower);
|
|
17655
|
+ qDebug() << "Received set value lower bound response";
|
17649
|
17656
|
}
|
17650
|
17657
|
|
17651
|
17658
|
void ModbusRTUDevice::svuResponse(QByteArray response)
|
|
@@ -17660,6 +17667,7 @@ void ModbusRTUDevice::svuResponse(QByteArray response)
|
17660
|
17667
|
outputSVUpper /= 10;
|
17661
|
17668
|
}
|
17662
|
17669
|
emit SVUpperChanged(outputSVUpper);
|
|
17670
|
+ qDebug() << "Received set value upper bound response";
|
17663
|
17671
|
}
|
17664
|
17672
|
|
17665
|
17673
|
void ModbusRTUDevice::requestMeasurement()
|
|
@@ -17767,6 +17775,7 @@ else
|
17767
|
17775
|
@<ModbusRTUDevice implementation@>=
|
17768
|
17776
|
ModbusRTUDevice::~ModbusRTUDevice()
|
17769
|
17777
|
{
|
|
17778
|
+ commTimeout->stop();
|
17770
|
17779
|
messageDelayTimer->stop();
|
17771
|
17780
|
port->close();
|
17772
|
17781
|
}
|
|
@@ -17786,6 +17795,10 @@ remove the message and callback information from the message queue, and start
|
17786
|
17795
|
a timer which will trigger sending the next message after a safe amount of
|
17787
|
17796
|
time has passed.
|
17788
|
17797
|
|
|
17798
|
+If a response is received with an invalid CRC, we do not pass that message
|
|
17799
|
+out. Instead, the message handling queues are kept as they are and the previous
|
|
17800
|
+command will be sent again once the message delay timer is finished.
|
|
17801
|
+
|
17789
|
17802
|
@<ModbusRTUDevice implementation@>=
|
17790
|
17803
|
void ModbusRTUDevice::dataAvailable()
|
17791
|
17804
|
{
|
|
@@ -17795,6 +17808,7 @@ void ModbusRTUDevice::dataAvailable()
|
17795
|
17808
|
}
|
17796
|
17809
|
responseBuffer.append(port->readAll());
|
17797
|
17810
|
@<Check Modbus RTU message size@>@;
|
|
17811
|
+ commTimeout->stop();
|
17798
|
17812
|
if(calculateCRC(responseBuffer) == 0)
|
17799
|
17813
|
{
|
17800
|
17814
|
QObject *object = retObjQueue.at(0);
|
|
@@ -17807,12 +17821,12 @@ void ModbusRTUDevice::dataAvailable()
|
17807
|
17821
|
messageQueue.removeAt(0);
|
17808
|
17822
|
retObjQueue.removeAt(0);
|
17809
|
17823
|
callbackQueue.removeAt(0);
|
17810
|
|
- messageDelayTimer->start(delayTime);
|
17811
|
17824
|
}
|
17812
|
17825
|
else
|
17813
|
17826
|
{
|
17814
|
17827
|
qDebug() << "CRC failed";
|
17815
|
17828
|
}
|
|
17829
|
+ messageDelayTimer->start(delayTime);
|
17816
|
17830
|
waiting = @[false@];
|
17817
|
17831
|
responseBuffer.clear();
|
17818
|
17832
|
}
|
|
@@ -17927,6 +17941,7 @@ void ModbusRTUDevice::sendNextMessage()
|
17927
|
17941
|
message.append(check[0]);
|
17928
|
17942
|
message.append(check[1]);
|
17929
|
17943
|
port->write(message);
|
|
17944
|
+ commTimeout->start(2000);
|
17930
|
17945
|
messageDelayTimer->start(delayTime);
|
17931
|
17946
|
waiting = @[true@];
|
17932
|
17947
|
}
|
|
@@ -17958,6 +17973,22 @@ void ModbusRTUDevice::ignore(QByteArray)
|
17958
|
17973
|
return;
|
17959
|
17974
|
}
|
17960
|
17975
|
|
|
17976
|
+@ Sometimes a communications failure will occur in which a response to a
|
|
17977
|
+command is never received. To reset communications we set a timer whenever a
|
|
17978
|
+command is sent and stop that once a full response is received. If the timer
|
|
17979
|
+times out, we should clear the response buffer and attempt to re-establish
|
|
17980
|
+communications. Currently this timeout is hard coded at 2 seconds, however
|
|
17981
|
+this should be configurable and smaller values may well be acceptable.
|
|
17982
|
+
|
|
17983
|
+@<ModbusRTUDevice implementation@>=
|
|
17984
|
+void ModbusRTUDevice::timeout()
|
|
17985
|
+{
|
|
17986
|
+ qDebug() << "Communications timeout.";
|
|
17987
|
+ responseBuffer.clear();
|
|
17988
|
+ waiting = false;
|
|
17989
|
+ messageDelayTimer->start();
|
|
17990
|
+}
|
|
17991
|
+
|
17961
|
17992
|
@ This class must be exposed to the host environment.
|
17962
|
17993
|
|
17963
|
17994
|
@<Function prototypes for scripting@>=
|