Qt serial communication using UART RS232C - linux

I want to connect qt and a device using UART cable (RS232C) in linux.
I´m writing code, making ui and operating, but it does not work.
I want to connect when i click some button(ui) device turn on and connect.
Also i want to make a function that if i enter some command device will recognize and execute.
Below is my code , someone help me please.
<mainwindow.cpp>
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QtSerialPort/QSerialPort>
#include <QMessageBox>
#include <QObject>
#include <QIODevice>
#include <QDebug>
QSerialPort serial;
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
QSerialPort*port=new QSerialPort();
port->setPortName("/dev/ttyUSB0");
port->setBaudRate(QSerialPort::Baud19200);
port->setDataBits(QSerialPort::Data8);
port->setParity(QSerialPort::NoParity);
port->setStopBits(QSerialPort::OneStop);
port->setFlowControl(QSerialPort::NoFlowControl);
port->open(QIODevice::ReadWrite);
ui->setupUi(this);
serial = new QSerialPort(this);
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::on_pushButton_connect_clicked()
{
port=new QSerialPort();
QObject::connect(port,SIGNAL(readyRead()),this,
SLOT(on_pushButton_connect_clicked()));
if(!port->open(QIODevice::ReadWrite)){
QMessageBox::information(this, tr("connect"),
"serialcommunication start");
}
else
{
QMessageBox::critical(this, tr("fail"), serial-
>errorString());
}
}
void MainWindow::on_pushButton_disconnect_clicked()
{
port->close();
QMessageBox::information(this, tr("disconnect"), "serial
communication end");
}
<mainwindow.h>
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QtSerialPort/QSerialPort>
#include <QMessageBox>
#include <QIODevice>
#include <QDebug>
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
QSerialPort*serial; //plus
QSerialPort*port;
QWidget*main_widget;
void readData();
~MainWindow();
private slots:
void on_pushButton_connect_clicked();
void on_pushButton_disconnect_clicked();
private:
Ui::MainWindow *ui;
};
#endif // MAINWINDOW_H
<main.cpp>
#include "mainwindow.h"
#include <QApplication>
#include <QSerialPort>
#include <QSerialPortInfo>
#include <QDebug>
#include <QMessageBox>
#include <QIODevice>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
foreach(const QSerialPortInfo
&info,QSerialPortInfo::availablePorts()){
QSerialPort serial;
serial.setPort(info);
if (serial.open(QIODevice::ReadWrite))
serial.close();
}
MainWindow w;
w.show();
return a.exec();
}

First of all it is not guaranteed that your device will be always connected to /dev/ttyUSB0 so you'l better search for your device by QSerialPortInfo with parameter
QString manufacturer() const or quint16 productIdentifier() const or QString serialNumber() const.
Also you are creating too many QSerialPort and don't handle it. Create just one.
Here is sample code:
main.cpp
#include "mainwindow.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
w.show();
return a.exec();
}
mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
class QSerialPort;
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
private slots:
//! Receives all the data from serial port
void readSerialData();
void on_pushButton_connect_clicked();
void on_pushButton_disconnect_clicked();
private:
Ui::MainWindow *ui;
QSerialPort *mSerialPort;
};
#endif // MAINWINDOW_H
Next check your Your product manufacturer or serial number and set here.
Also you need separate handler for received data like I created readSerialData
mainwindows.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QSerialPort>
#include <QSerialPortInfo>
#include <QMessageBox>
#include <QDebug>
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow),
mSerialPort{new QSerialPort}
{
ui->setupUi(this);
mSerialPort->setBaudRate(QSerialPort::Baud19200);
mSerialPort->setDataBits(QSerialPort::Data8);
mSerialPort->setParity(QSerialPort::NoParity);
mSerialPort->setStopBits(QSerialPort::OneStop);
mSerialPort->setFlowControl(QSerialPort::NoFlowControl);
connect(mSerialPort, SIGNAL(readyRead()), this, SLOT(readSerialData()));
}
MainWindow::~MainWindow()
{
delete mSerialPort;
delete ui;
}
void MainWindow::readSerialData()
{
QByteArray lTmpBA;
lTmpBA = mSerialPort->readAll();
qDebug() << "Received data: " << lTmpBA;
}
void MainWindow::on_pushButton_connect_clicked()
{
foreach(QSerialPortInfo item, QSerialPortInfo::availablePorts()) {
if (item.manufacturer() == "Your product") { //past your manufacturer here
mSerialPort->setPort(item);
if(!mSerialPort->open(QIODevice::ReadWrite)){
QMessageBox::information(this, tr("connect"),
"serialcommunication start");
} else {
QMessageBox::critical(this, tr("fail"), mSerialPort->errorString());
}
} else {
qDebug() << "No connected device found";
}
}
}
void MainWindow::on_pushButton_disconnect_clicked()
{
mSerialPort->close();
}
latter if you want to send some data to your UART device just implemente slot and call method:
mSerialPort->write("Some command");

Related

Are the interrupts in Linux queued

I wrote a sample driver which disables keyboard interrupt for few seconds, and when i press keys at that duration, i get the pressed keys on the console when the interrupt is enabled?
#include <linux/module.h>
#include <linux/init.h>
#include <linux/delay.h>
#include <linux/irqflags.h>
#include <linux/interrupt.h>
unsigned int irq = 1;
module_param(irq, int, 0);
static int __init my_init(void)
{
pr_info("module is loaded on processor:%d\n", smp_processor_id());
pr_info("Disabling Interrupt:%u\n", irq);
disable_irq(irq);
pr_info("Disabled Interrupt:%u\n", irq);
mdelay(10000L);
pr_info("Enabling Interrupt:%u\n", irq);
enable_irq(irq);
pr_info("Enabled Interrupt:%u\n", irq);
return 0;
}
static void __exit my_exit(void)
{
}
MODULE_LICENSE("GPL");
module_init(my_init);
module_exit(my_exit);

connmanctl command(RegisterAgent) is not working via dbus

I can connect to open wifi via "connmanctl" using dbus via Qt,. I would like to connect secured wife using connmanctl via dbus. there is an API to regiser an agent( interactive mode, to enter passphrase) called "RegisterAgent(object path)"
, In this, I am not sure what is mean by object path. I have tried object path with ""/net/connman/technology/wifi", but it was not working. I think I am wrong on something. I have added Qt compiled code below. Can some one help me to connect to secured network through connmanctl via dbus ?
//------------tocker.h------------------
#ifndef TOCKER_H
#define TOCKER_H
#include <QObject>
#include <QDBusMessage>
#include <QDBusError>
class Tocker : public QObject
{
Q_OBJECT
public:
explicit Tocker(QObject *parent = 0);
signals:
public slots:
void onAgentRegisterRequested(QDBusMessage);
void onErrorResponse(QDBusError);
};
#endif // TOCKER_H
//----------------------
//talker.cpp................
#include <QDBusInterface>
#include <QDBusConnection>
#include <QList>
#include <QVariant>
#include <QtDebug>
#include "tocker.h"\
Tocker::Tocker(QObject *parent) : QObject(parent)
{
QDBusInterface interfaceObj("net.connman", "/", "net.connman.Manager", QDBusConnection::systemBus());
bool isScucess = false;
do
{
if(interfaceObj.isValid())
{
QList<QVariant> params;
params << "/net/connman/technology/wifi"; //I am not sure is this path is correct
if( interfaceObj.callWithCallback("RegisterAgent", params, this, SLOT(onAgentRegisterRequestedd(QDBusMessage)), SLOT(onErrorResponse(QDBusError)) ))
{
qDebug()<< Q_FUNC_INFO << "callWithCallback is success";
isScucess = true;
}
else
{
isScucess = false;
}
break;
}
}
while(false);
if( !isScucess )
{
qDebug()<< Q_FUNC_INFO << interfaceObj.lastError().message();
}
else
{
qDebug() << Q_FUNC_INFO << "Callback is success.";
}
}
void Tocker::onAgentRegisterRequested(QDBusMessage msg)
{
qDebug()<< Q_FUNC_INFO << msg;
}
void Tocker::onErrorResponse(QDBusError errorMsg )
{
qDebug()<< Q_FUNC_INFO << errorMsg;
}
-----------main.cpp........
#include <QCoreApplication>
#include "tocker.h"
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
Tocker tocker;
return a.exec();
}

Qt start an external program in Qt gridLayout

I was wondering, is it possible to start an external program via Qt and display the program in Qt gridLayout (or inside Qt window)?
At the moment, I'm able to start an external program via Qt, but I haven't find a way to display the program inside the QtWindow. In other words, the program just appear outside Qt window.
Qt Pro file
#-------------------------------------------------
#
# Project created by QtCreator 2016-09-21T16:31:30
#
#-------------------------------------------------
QT += core gui
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
TARGET = WifiProject
TEMPLATE = app
SOURCES += main.cpp\
mainwindow.cpp
HEADERS += mainwindow.h
FORMS += mainwindow.ui
Main window .h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QtNetwork/QNetworkConfigurationManager>
#include <QtNetwork/QNetworkSession>
#include <QtNetwork/QNetworkInterface>
#include <QDebug>
#include <QList>
#include <QProcess>
#include <QWidget>
#include <QBoxLayout>
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
private slots:
void on_StartWicd_clicked();
private:
Ui::MainWindow *ui;
void searchForNetwork();
QProcess *wicdProgram;
void addWicdProgram();
};
#endif // MAINWINDOW_H
mainwindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QWindow>
QString program = "/usr/bin/wicd-gtk";
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
searchForNetwork();
addWicdProgram();
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::searchForNetwork(){
}
void MainWindow::addWicdProgram(){
wicdProgram = new QProcess(this);
wicdProgram->setProgram(program);
WId winid = this->winId();
QWindow *container = QWindow::fromWinId(winid);
QWidget *program_start = createWindowContainer(container);
setCentralWidget(program_start);
ui->wifiGridLayout->addWidget(program_start);
wicdProgram->start();
qDebug()<<"wicd addded";
//ui->wifiGridLayout->addWidget(program_start);
}
void MainWindow::on_StartWicd_clicked()
{
//wicdProgram->start(program);
qDebug()<<"the wicd should have started";
wicdProgram->terminate();
}
A solution is to retrieve the window id of the application launch by qt and you can do like this :
QWindow *window = QWindow::fromWinId("Id of the application");
window->setFlags(Qt::FramelessWindowHint);
QWidget *widget = QWidget::createWindowContainer(window);

Sending structure through sockets in Qt

I am writing a client server application to transfer data in linux platform. I am developing a GUI application for client side in QT.I am just a beginner in QT and please help in transferring a structure from server side to client side.
The server side code written for non-GUI environment
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#pragma pack(1)
struct basestruct
{
int element1;
int element2;
};
#pragma pack(0)
struct basestruct newstruct;
int main(int argc, char *argv[])
{
int listenfd = 0, connfd = 0,n=0;
struct sockaddr_in serv_addr;
char sendBuff[1025];
listenfd = socket(AF_INET, SOCK_STREAM, 0);
memset(&serv_addr, '0', sizeof(serv_addr));
memset(sendBuff, '0', sizeof(sendBuff));
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
serv_addr.sin_port = htons(5000);
bind(listenfd, (struct sockaddr*)&serv_addr, sizeof(serv_addr));
listen(listenfd, 10);
while(1)
{
connfd = accept(listenfd, (struct sockaddr*)NULL, NULL);
newstruct.element1=1;
newstruct.element2=2;
if((n=send(connfd,(void *)&newstruct,sizeof(struct basestruct),0))<0)
perror("Write error");
printf("sent items :%d \n",n);
close(connfd);
sleep(1);
}}`
The client side code written in QT
#include "dialog.h"
#include "ui_dialog.h"
#include <QString>
#include <QDebug>
#include <QTextStream>
#include <QByteRef>
struct basestruct
{
int element1;
int element2;
};
basestruct newstruct;
Dialog::Dialog(QWidget *parent) :
QDialog(parent),
ui(new Ui::Dialog)
{
ui->setupUi(this);
ui->pushButton->setText("Connect");
ui->pushButton_2->setText("Ok");
ui->pushButton_3->setText("Close");
ui->pushButton_4->setText("Disconnect");
}
Dialog::~Dialog()
{
delete ui;
}
void Dialog::Read()
{
socket->waitForReadyRead(-1);
QByteArray byteArray;
byteArray=socket->readAll();
deserialize(byteArray);
qDebug()<<socket->readAll();
qDebug()<<"Read contents";
socket->flush();
}
void Dialog::on_pushButton_clicked()
{
socket=new QTcpSocket(this);
socket->connectToHost("127.0.0.1",5000);
qDebug()<<"Connected";
Read();
}
void Dialog::on_pushButton_4_clicked()
{
socket->close();
qDebug()<<"Disconnected";
}
void Dialog::deserialize(const QByteArray& byteArray)
{
QDataStream stream(byteArray);
stream.setVersion(QDataStream::Qt_4_0);
qDebug()<<"size received" <<byteArray.size();
stream >> newstruct.element1
>> newstruct.element2;
qDebug()<<"Element1"<<newstruct.element1<<"Element2"<<newstruct.element2;
}
When I receive the structure and print using qDebug() I am getting some garbage values. Kindly help me and point where I have gone wrong.Is there any easy alternative method to transfer structure in QT without serialising (similar to Non-GUI applications).
Thanks in advance
The Endianness problem can be overcome by specifying the Endianess as:
stream.setByteOrder(QDataStream::LittleEndian);
in the deserialise function after declaring Qdatastream.

C++ Windows Form Application: Attempted to read or write protected memory (unmanaged class)

I'm trying to use Boost library in my C++ Windows Form Application and I always get an exception:
Additional information: Attempted to read or write protected memory. This is often an indication that other memory is corrupt.
I'm using Visual Studio 2012 and Boost version 1.57.0. Previously I used Boost version 1.56.0 but upgrading didn't solve my issue.
Here are the code:
MyForm.cpp
#include "MyForm.h"
using namespace System;
using namespace System::Windows::Forms;
[STAThread]
void main(cli::array<String^>^ args) {
Application::EnableVisualStyles();
Application::SetCompatibleTextRenderingDefault(false);
TestUnmanaged::MyForm form;
Application::Run(%form);
}
MyForm.h
#pragma once
#include <iostream>
#include <map>
#include <sstream>
#include <cassert>
#include <stdio.h>
#include "ExternalProfileManager.h"
#define DEFAULT_PROFILE_NAME "profile.bin"
#pragma comment(lib, "Ws2_32.lib")
#pragma comment(lib, "lib/edk.lib")
namespace TestUnmanaged {
using namespace System;
using namespace System::ComponentModel;
using namespace System::Collections;
using namespace System::Windows::Forms;
using namespace System::Data;
using namespace System::Drawing;
ExternalProfileManager profileManager;
/// <summary>
/// Summary for MyForm
/// </summary>
public ref class MyForm : public System::Windows::Forms::Form
{
public:
MyForm(void)
{
InitializeComponent();
//
//TODO: Add the constructor code here
//
profileManager.load(DEFAULT_PROFILE_NAME);
std::vector<std::string> profileList;
profileManager.listProfile(profileList);
}
ExternalProfileManager.h
#ifndef EXTERNAL_PROFILE_MANAGER_H
#define EXTERNAL_PROFILE_MANAGER_H
#include <boost/serialization/string.hpp>
#include <boost/serialization/map.hpp>
#include <boost/serialization/vector.hpp>
#include <boost/serialization/export.hpp>
#include <boost/serialization/tracking.hpp>
#include <boost/serialization/base_object.hpp>
class ExternalProfileManager
{
ExternalProfileManager(const ExternalProfileManager&) {};
ExternalProfileManager& operator = (const ExternalProfileManager&) {};
protected:
std::map<std::string, std::string > _profiles;
typedef std::map<std::string, std::string >::iterator profileItr_t;
// Boost serialization support
friend class boost::serialization::access;
template <class Archive>
void serialize(Archive& ar, const unsigned int /*file version */)
{
ar & _profiles;
}
public:
ExternalProfileManager();
virtual ~ExternalProfileManager();
virtual bool save(const std::string& location);
virtual bool load(const std::string& location);
virtual bool insertProfile(const std::string& name, const unsigned char* profileBuf, unsigned int bufSize);
virtual bool listProfile(std::vector<std::string>& profiles);
};
//BOOST_CLASS_EXPORT(ExternalProfileManager);
//BOOST_CLASS_TRACKING(ExternalProfileManager, boost::serialization::track_never);
#endif // EXTERNAL_PROFILE_MANAGER_H
ExternalProfileManager.cpp
#include <fstream>
#include <boost/filesystem/operations.hpp>
#include <boost/filesystem/path.hpp>
#include <boost/regex.hpp>
#pragma warning(push)
#pragma warning(disable : 4267) // "conversion from size_t to unsigned int"
#pragma warning(disable : 4996)
#include <boost/archive/archive_exception.hpp>
#include <boost/archive/binary_oarchive.hpp>
#include <boost/archive/binary_iarchive.hpp>
#pragma warning(pop)
#include "ExternalProfileManager.h"
using namespace std;
namespace fs = boost::filesystem;
ExternalProfileManager::ExternalProfileManager()
{
}
ExternalProfileManager::~ExternalProfileManager()
{
}
bool ExternalProfileManager::save(const string& location)
{
ofstream ofs(location.c_str(), ios_base::binary);
if ( !ofs.is_open() ) return false;
try {
boost::archive::binary_oarchive oa(ofs);
oa << *this;
}
catch (boost::archive::archive_exception& )
{
return false;
}
return true;
}
bool ExternalProfileManager::load(const string& location)
{
ifstream ifs(location.c_str(), ios_base::binary);
if ( !ifs.is_open() ) return false;
try {
boost::archive::binary_iarchive ia(ifs);
ia >> *this;
}
catch (boost::archive::archive_exception& )
{
return false;
}
return true;
}
bool ExternalProfileManager::insertProfile(const string& name, const unsigned char* profileBuf, unsigned int bufSize)
{
assert(profileBuf);
// Replace our stored bytes with the contents of the buffer passed by the caller
string bytesIn(profileBuf, profileBuf+bufSize);
_profiles[name] = bytesIn;
return true;
}
bool ExternalProfileManager::listProfile(vector<string>& profiles)
{
profiles.clear();
for ( profileItr_t itr = _profiles.begin(); itr != _profiles.end(); ++itr ) {
profiles.push_back(itr->first);
}
return true;
}
The error occurred in ia >> *this; in ExternalProfileManager::load (thrown in file basic_archive.cpp). So calling profileManager.load(DEFAULT_PROFILE_NAME); from form constructor will trigger the exception.
Calling save will also trigger the same exception but other functions which have no this will work fine.
I tried creating a console application in VS 2012 and call ExternalProfileManager.h and it works perfectly (including save, load, and any other function). Here are the simple console application I created to test it:
Console.cpp
#include <iostream>
#include <map>
#include <sstream>
#include <cassert>
#include <stdio.h>
#include "ExternalProfileManager.h"
#define DEFAULT_PROFILE_NAME "profile.bin"
#pragma comment(lib, "Ws2_32.lib")
#pragma comment(lib, "lib/edk.lib")
ExternalProfileManager profileManager;
int main(int argc, char** argv) {
profileManager.load(DEFAULT_PROFILE_NAME);
std::vector<std::string> profileList;
profileManager.listProfile(profileList);
std::cout << "Available profiles:" << std::endl;
for (size_t i=0; i < profileList.size(); i++) {
std::cout << i+1 << ". " << profileList.at(i);
if (i+1 < profileList.size()) {
std::cout << std::endl;
}
}
return true;
}
profile.bin is generated from calling save function in console application and contain serialized data generated by boost. I can provide the file if it is needed to solve this issue.
I have also tried to create a simple class wrapper but the exception still occurred.
WrapperExternalProfileManager.h
#ifndef WRAPPER_EXTERNAL_PROFILE_MANAGER_H
#define WRAPPER_EXTERNAL_PROFILE_MANAGER_H
#include <string>
#include <vector>
class WrapperExternalProfileManager
{
WrapperExternalProfileManager(const WrapperExternalProfileManager&) {};
WrapperExternalProfileManager& operator = (const WrapperExternalProfileManager&) {};
public:
WrapperExternalProfileManager();
virtual ~WrapperExternalProfileManager();
virtual bool save(const std::string& location);
virtual bool load(const std::string& location);
virtual bool insertProfile(const std::string& name, const unsigned char* profileBuf, unsigned int bufSize);
virtual bool listProfile(std::vector<std::string>& profiles);
};
#endif
WrapperExternalProfileManager.cpp
#include "WrapperExternalProfileManager.h"
#include "ExternalProfileManager.h"
using namespace std;
ExternalProfileManager profileManager;
WrapperExternalProfileManager::WrapperExternalProfileManager()
{
std::cout<<"Constructor WrapperExternalProfileManager"<<std::endl;
}
WrapperExternalProfileManager::~WrapperExternalProfileManager()
{
}
bool WrapperExternalProfileManager::save(const string& location)
{
return profileManager.save(location);
}
bool WrapperExternalProfileManager::load(const string& location)
{
return profileManager.load(location);
}
bool WrapperExternalProfileManager::insertProfile(const string& name, const unsigned char* profileBuf, unsigned int bufSize)
{
return profileManager.insertProfile(name, profileBuf, bufSize);
}
bool WrapperExternalProfileManager::listProfile(vector<string>& profiles)
{
return profileManager.listProfile(profiles);
}
save and load still trigger the exception but other functions work perfectly.
Here are some property of the application which might be helpful:
Linker -> System -> SubSystem: Windows (/SUBSYSTEM:WINDOWS)
General -> Common Language Runtime Support: Common Language Runtime Support (/clr)
I know I have done something incorrectly but I don't know which part. Any suggestion to solve this issue would be appreciated.
Thanks in advance
You're going to have to find the source of your Undefined Behaviour (use static analysis tools, heap checking and divide and conquer).
I've just built your code on VS2013 RTM, using a ultra-simple C# console application as the driver:
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
var f = new TestUnmanaged.MyForm();
f.ShowDialog();
}
}
}
This JustWorks(TM).
I created a profile.bin with 100 random profiles of varying length:
#if 1
for (int i = 0; i < 100; ++i)
{
std::vector<uint8_t> buf;
std::generate_n(back_inserter(buf), rand() % 1024, rand);
insertProfile("profile" + std::to_string(i), buf.data(), buf.size());
}
save(location);
#endif
And they are deserialized just fine.
Good luck.
Download the full project here http://downloads.sehe.nl/stackoverflow/q27032092.zip in case you want to fiddle with it (compare the details?)

Resources