Modbusclient as a console application, "Stuck in Connectingstate loop" - c++

I'm trying hardly to convert the Modbusmaster example (qt example) which is a widget application to a console application. I wanted to build a connection between a local slave and my master. The problem I'm facing is that my code is changing its state to “Connecting state” ,gets stuck and doesn't want to build a connection. That's why, I recon that the Modbus library is limited and it's only compatible with the widget form.
Could someone tell me if my guesses are right.
down below you will find my code:
#include <QCoreApplication>
#include <QDebug>
#include <QModbusDataUnit>
#include<iostream>
#include <QTimer>// this bib was add to the 50ms Loop check
#include <string>
#include <QString>
#include <QThread>
#include <QModbusTcpClient>
#include <QModbusDataUnit>
#include <QUrl>
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
Mainmodbus T ;
T.modbusDevice = new QModbusTcpClient();
if (!T.modbusDevice) qDebug()<<"error 1";
if (T.modbusDevice->state() != QModbusDevice::ConnectedState) {
T.modbusDevice->setConnectionParameter(QModbusDevice::NetworkAddressParameter, "127.0.0.1");
T.modbusDevice->setConnectionParameter(QModbusDevice::NetworkPortParameter, 502);
T.modbusDevice->connectDevice();
while(true){
qDebug()<<T.modbusDevice->state();}
}
return a.exec();
}

I can be wrong but I think the QModbusDevice::ConnectingState you see actually means your server is up and running and waiting for a connection.
I guess what you are missing is opening a connection from a Modbus client. You can do that with different tools, I guess running the client example
would be a good idea. Otherwise, you can use QModMaster or any other tool you like.
Once you open the connection from the client the state on your server should change to QModbusDevice::ConnectedState.
Be aware that the server you built is just an empty shell, there is no register map defined so if you query the contents of any register from the client you will get an error.
At the very minimum, you should at least define a map with some default values or get them from command-line options. To do that you need to look at the server example a bit more carefully.
First you need to define the register map with something like this:
QModbusDataUnitMap reg;
reg.insert(QModbusDataUnit::Coils, { QModbusDataUnit::Coils, 0, 10 });
reg.insert(QModbusDataUnit::DiscreteInputs, { QModbusDataUnit::DiscreteInputs, 0, 10 });
reg.insert(QModbusDataUnit::InputRegisters, { QModbusDataUnit::InputRegisters, 0, 10 });
reg.insert(QModbusDataUnit::HoldingRegisters, { QModbusDataUnit::HoldingRegisters, 0, 10 });
modbusDevice->setMap(reg);
setupDeviceData();
And then for the setupDeviceData(); you can copy the function in the example but instead of taking the data from the widget, you will have to load default values or something from the command line.
In answer to your question: no, there should be no limitation and you should be able to run the server from the command line. I wonder why somebody on his/her right mind would want to do that when you have excellent alternatives like libmodbus. But honestly, I won't miss much sleep wondering.

Related

Observe changes in QSharedMemory

I have a QSharedMemory to prevent that two processes of my application are running at the same time. Process A sets the QSharedMemory to "locked" when started. Now my process B sets a value like "please come back to foreground".
Is there an easy way for process A to observe changes in the QSharedMemory, i.e. avoids implementing a stupid pulling timer?
Here we are: QSystemSemaphore
Like its lighter counterpart QSemaphore, a QSystemSemaphore can be accessed from multiple threads. Unlike QSemaphore, a QSystemSemaphore can also be accessed from multiple processes.
Like QSharedMemory, QSystemSemaphore uses a key-based access method.
Instead of using shared memory, the process could open a QLocalSocket to a named local server, and when it fails, open a QLocalServer. All subsequent processes will success to open the socket to the server, and can communicate with it. That's probably the simplest, most portable way of accomplishing the job.
You can also use QtSingleApplication, iff it has been ported to Qt 5.
To answere your question: No, QSharedMemory does not have such a feature.
If you just want to have a "single instance" application, you can use https://github.com/Skycoder42/QSingleInstance.
It makes shure you have only 1 instance of you application at a time, can automatically bring the active window to the front and allows you to pass parameters from the new process to the running one.
Simple example:
#include "mainwindow.h"
#include <QApplication>
#include <QMessageBox>
#include <qsingleinstance.h>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QSingleInstance instance;
MainWindow *w = NULL;
instance.setStartupFunction([&]() -> int {
w = new MainWindow(NULL);
instance.setNotifyWindow(w);
w->show();
return 0;
});
QObject::connect(qApp, &QApplication::aboutToQuit, [&](){
delete w;
});
QObject::connect(&instance, &QSingleInstance::instanceMessage, [&](QStringList args){
QMessageBox::information(w, "Message", args.join('\n'));
});
return instance.singleExec();
}
This will show the mainwindow, just like you woudl expect. If the application is run a second time, the currently running mainwindow will be raised to the foreground and a messagebox with the arguments will be shown.
Note: This example uses the QWidgets, but the QSingleInstance can be used with a gui or core application, too.

Application freeze in 3rd party library call

I am working on a c++ measurement software which uses a 3rd party API for the interface all sensors are connected to. This API is not open source and no debug library is available.
In some occasions, the software freezes when starting to read a value from the interface. While I could not determine what criterions cause the problem and why it only happens sometimes so far, I'd like to intercept the freezing and implement some error handling, which would also allow me to better debug the issue.
In my code, I simply have a call
BOOL result = false;
result = pciadioAIStartConversion(board_index, channel_nr, range);
where, if the error occurs, pciadioAIStartConversion never returns. I am looking for some simple functionality to keep the software running and return if the call takes to long.
I am using the Qt framework (4.8.6) so a possible solution would be using the event system and a QTimer, but therefore the call would need its own thread if I'm not mistaken and that seems like overkill to me.
piezol is right You need a separate thread which can be quite a mess but the good news is that Qt thread framework (which is called QtConcurrent) is really helpful.
Here is an example for running a standard function in a separate thread mantaining control of it.
#include <QDebug>
#include <QThread>
#include <QString>
#include <qtconcurrentrun.h>
#include <QApplication>
using namespace QtConcurrent;
void hello(QString name)
{
qDebug() << "Hello" << name << "from" << QThread::currentThread();
}
int main(int argc, char **argv)
{
QApplication app(argc, argv);
QFuture<void> f1 = run(hello, QString("Alice"));
QFuture<void> f2 = run(hello, QString("Bob"));
f1.waitForFinished();
f2.waitForFinished();
}

Selecting from all available serial ports using Qt GUI

I could not find a conclusive answer to my issue so I decided to post my first question on this site. I'm fairly new to programming and have been using Qt for a couple of months now.
My code communicates with a microcontroller via serial ports, however the available port differs from pc to pc. I'm displaying the number of ports available with the code;
qDebug() << "Number of serial ports:" << QSerialPortInfo::availablePorts().count();
My question is: how can I display the name of all the available ports eg "COM 10, 17. 22, etc" and then show them in my GUI. What I eventually hope to do is have a combo box that can be dynamically populated with the available ports, I have one that switches between a couple ports at the moment but these are fixed ports corresponding to particular computers.
Try something like this:
#include <QApplication>
#include <QWindow>
#include <QSerialPortInfo>
#include <QComboBox>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QWidget w;
w.resize(200,200);
w.show();
QComboBox box(&w);
Q_FOREACH(QSerialPortInfo port, QSerialPortInfo::availablePorts()) {
box.addItem(port.portName());
}
box.move(100 - box.width() / 2,100 - box.height() / 2);
box.show();
return a.exec();
}
The code is pretty self-explanatory.
Found a relevant answer on qt centre, example code;
foreach (const QSerialPortInfo &serialPortInfo, QSerialPortInfo::availablePorts())
{
ui->comboBox->addItem(serialPortInfo.portName());
}

QtWebKit c++ connect: cannot convert QWebView to SOCKET

Recently started doing some programming for Windows and I simply can't get my program to work. I am trying to achieve an environment in which I mainly can use HTML for the frontend and control the backend with Javascript. On Linux I've managed to add functions and stuff to the "JavaScriptCore" but Windows haven't been to kind with me.
Currently I'm trying to catch the URL change event, allowing for special URLs to execute commands, however I get the following error:
error: C2664: 'connect' : cannot convert parameter 1 from 'QWebView *' to 'SOCKET'
There is no context in which this conversion is possible
I didn't manage to find a single search result concerning "QWebView to SOCKET" so I have no clue what to do but to ask you guys.
Here is my code. I'm not too good with programming to please be gentle ;)
#include <QtGui>
#include <QtWebKit>
#include <QApplication>
#include <QWebView>
#include <iostream>
using namespace std;
void test()
{
cout << "Hello world";
}
int main(int argc, char** argv) {
QApplication app(argc, argv);
QWebView view;
view.setWindowFlags(Qt::CustomizeWindowHint);
view.setWindowFlags(Qt::FramelessWindowHint);
view.setFixedSize(1000,600);
view.setStyleSheet("background:transparent;");
view.setAttribute(Qt::WA_TranslucentBackground);
view.setUrl(QUrl("http://google.com"));
view.setWindowTitle("test v0.1");
connect(view, SIGNAL(urlChanged(QUrl)), SLOT(test()));
view.show();
return app.exec();
}
Try this instead:
QObject::connect(&view, &QWebView::urlChanged, test);
You are using the old connection syntax which works only with QObjects and slots, test is not a slot and it is not a function of a QObject derived class, it is a free funciton, so you have to use the new syntax, available since Qt 5.
When you are not inside a QObject you don't have access to connect(), that is why my example uses the QObject namespace to invoke it in main(). In your case as DNT noted it is just some other function that happens to be named "connect".
Another mistake you made is you passed the view, but connect() works with pointers, so you have to use the & operator to get a pointer to the view.

parallely run an application while it starts another application in c++

I am trying to write an application program that can start another application using c++ in linux . Starting another application is not the problem . The problem I am facing is, that the parent application pauses till the child application is closed. I want the parent application to run along with the child application so that more functionalities of the parent application can be used. How do i go about it?
It would help me a lot if somebody could give me an idea on this.
The application consists of two files main.cpp and a virtualbotmain.cpp. The part of the
virtualbotmain.cpp: #include <iostream>
#include <stdlib.h>
VirtualBotMain::VirtualBotMain(QWidget *parent) :
QWidget(parent),
ui(new Ui::VirtualBotMain)
{
ui->setupUi(this);
}
void VirtualBotMain::on_enterButton_clicked()
{
QString enterString = ui->enterEdit->text();
ui->convoText->append("User: " + enterString);
ui->enterEdit->setText("");
if(enterString=="word")
{
ui->convoText->append("Joe: done..!!");
system("gedit");
}
}
The main.cpp is :
#include <QtGui/QApplication>
#include "virtualbotmain.h"
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
VirtualBotMain w;
w.show();
return a.exec();
}
This is a GUI application that can be used to just type in the application i am trying to open and the application will do it for me. So trying to open many applications one after the other is becoming a problem as the GUI application won't work untill i close the previously opened application.
If you're using a system call (or a similar way to invoke the shell), you can apply the same logic you'd apply in your terminal to start a process "in the background":
system("./myProgram &");
// ^
// run in background
Better alternatives include forking, though it really depends on your specific requirements, which we do not know.
#include <stddef.h>
#include <process.h>
int status = spawnl( P_NOWAIT, "myprog", "myprog", "ARG1", "ARG2", NULL );