I am creating an application which prints text through a POS printer.
The prints works fine. But for POS printer there are control commands to do certain functions like : paper cut, cashdraw open etc.. For eg:
Function: Partial cut
Code:
ASCII———-> ESC i
Hex ————-> 1B 69
Decimal—-> 27 105
When I try to send command 27 105 it just prints on paper instead of performing action.. I’m not exactly sure how to send it… Can someone suggest how to write to the socket…
#include "lanprinterui.h"
#include "ui_lanprinterui.h"
LanPrinterUI::LanPrinterUI(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::LanPrinterUI)
{
ui->setupUi(this);
m_TextInput = ui->textEdit;
m_pSocket = new QTcpSocket();
m_pSocket->connectToHost("192.168.1.20", 9100);
m_ConnectStatus = true;
QObject::connect(ui->pushButton, SIGNAL(clicked()), this, SLOT(print()));
}
LanPrinterUI::~LanPrinterUI()
{
delete ui;
delete m_pSocket;
}
void LanPrinterUI::print()
{
const int Timeout = 5 * 1000;
if (!m_ConnectStatus)
{
m_pSocket->connectToHost("192.168.1.20", 9100);
}
if (!m_pSocket->waitForConnected(Timeout))
{
//sent error
qDebug ("error in waitForConnected()");
qDebug (qPrintable(m_pSocket->errorString()));
m_ConnectStatus = false;
return;
}
m_ConnectStatus = true;
QByteArray block;
QDataStream out(&block, QIODevice::WriteOnly);
out.setVersion(QDataStream::Qt_4_0);
out << m_TextInput->toPlainText();
out << '\n';
m_pSocket->write(block);
}
What you want is
out << "\n\x1Bi";
That is, you want, after the '\n' char, to send the '\x1B' char (also known as "escape") and the 'i' char. You could also have written this as:
out << '\n' << "\x1b\x69";
or:
out << '\n' << char(27) << char(105);
or:
out << '\n' << char(0x1b) << char(0x69);
(or any other valid combination)
Another, better idea, would be to put in your class:
class LanPrinterUI {
private:
static const QString PARTIAL_PAPER_CUT = "\x1bi";
static const QString CASHDRAWER_OPEN = "\x1b....";
//...
};
And then you would just:
out << '\n' << PARTIAL_PAPER_CUT;
(which would be much better than hardcoded constants)
Related
I wrote this code:
void StartToSendCommand(QString fileName, QPlainTextEdit *textEdit)
{
QFile file(fileName);
if (!file.open(QIODevice::ReadOnly | QIODevice::Text))
return;
QTimer * inputTimer=new QTimer(textEdit);
QTextStream in(&file);
QString line;
while (!in.atEnd()) {
line = in.readLine();
if (line==""||line[0]=="#")
continue;
qDebug()<<line;
//TO DO: make also a waiting time between letters.
inputTimer->start(GWaitingTimeBetweenCommand);
QApplication::processEvents();
QThread::sleep(2);`
}
inputTimer->deleteLater();
SendCommandByUsb(fileName, line);
}
and I want to do that when its read from the file its also make a wait for 1 second between any letter.
how can I make it?
If you want to wait for individual letters, you can also do this with a QTimer interval. Once the condition is met, you can submit the file.
Here would be a small example, oriented towards a typewriter but has the same effect:
.h
....
private slots:
void typeWriter();
private:
QString line;
QTimer *timer;
....
.cpp
//constructor
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
line = "C:/.../readme.txt";
timer = new QTimer(this);
connect(timer,&QTimer::timeout, this, &MainWindow::typeWriter);
timer->start(1000);
}
void MainWindow::typeWriter()
{
static int counter = 0;
if(counter < line.length())
{
counter ++;
ui->label->setText(line.mid(0, counter));
//SendCommandByUsb(fileName, line.mid(0, counter));
timer->setInterval(1000);
qDebug() << counter << " : " << line.length() << " : " << line.mid(0, counter);
}
if(counter == line.length())
{
qDebug() << "end";
timer->stop();
}
}
the length of the string is compared with the counter. it is counted until it reaches the length of the string. the string method QString::mid can be thought of as a slice. it is sliced from index 0 (i.e. the beginning of the string) to the end, the counter takes care of that.
The timer interval defines the interval between the next call.
Just for info (because that's how the question read):
If you want to open a file and always want to wait a second for a letter to be read, you have to consider that you don't have a valid file path. Well that wouldn't make sense because you have to commit the file before anything is read at all.
I'm trying to establish a live communication between a QT program and a VS C++ program. However, I can read anything unless I close the writechannel in which I can't write anything anymore. Furthermore, the code I have now reads a continuous stream of output when I write one line to the VS C++ program when it should be waiting for the next input. Is there a way to establish synchronous communication with the two? What is wrong with my current program?
I've read documentation and can't seem to get a clear answer.
My Qt code:
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
process = new QProcess(this);
connect(process, SIGNAL(readyReadStandardOutput()), this, SLOT(readOutput()));
//connect(process, SIGNAL(readyReadStandardError()),this,SLOT(readOutput()));
process->setArguments(args);
process->setProgram("C:\\Users\\chten\\OneDrive\\Desktop\\QProcess\\test\\Debug\\test.exe");
process->start();
process->waitForStarted();
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::readOutput() {
ui->input->append(process->readAllStandardOutput());
}
void MainWindow::on_pushButton_2_pressed()
{
process->write("left");
process->waitForBytesWritten();
process->closeWriteChannel();
}
My C++ code:
cout << "waiting for response..." << endl;
string input_line;
//getline(cin, input_line);
//cout << input_line << endl;
while (true) {
getline(cin, input_line);
cout << input_line << endl;
for(int i = 0; i<9999999; i++){}
}
return 0;
I think the problem is that you never write a line to the child process, you just have...
process->write("left");
No newline. In the meantime the child is executing...
getline(cin, input_line);
waiting for the newline delimiter.
The reason closing the write channel appears to work is that it will cause the getline call in the child to receive an end-of-file condition and return. However, it will also set the eofbit in the input stream's state causing further calls to getline to return immediately: hence the "continuous stream of output" you refer to.
Try changing the implementation of MainWindow::on_pushButton_2_pressed to...
void MainWindow::on_pushButton_2_pressed ()
{
process->write("left\n");
process->waitForBytesWritten();
}
and change the child's source code to...
std::cout << "waiting for response..." << endl;
std::string input_line;
while (std::getline(std::cin, input_line)) {
std::cout << input_line << std::endl;
for(int i = 0; i<9999999; i++) {
}
}
return 0;
(All untested.)
As an aside, using Qt functions such as waitFoStarted, waitForBytesWritten etc. can be convenient but should be avoided. Far better to connect to and handle the various signals available.
I'm trying to load and store a custom QMetaType using QDataStream object. Here is an example:
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QString test1("/test1/");
const QString path1(QDir::homePath()+test1);
qDebug() << "path1 variable is " << path1;
QDir apphome(path1);
qDebug() << "apphome path is " << apphome.absolutePath();
if (!apphome.mkdir(path1)) { qDebug() << "mkdir returned false. directory already exists?"; }
if(!apphome.setCurrent(path1)) { qDebug() << "did not set current directory"; }
qDebug() << "apphome path is " << apphome.absolutePath();
Basic basic1;
Basic basic2;
basic1.value = 14;
QFile file1("file1name");
if (!file1.open(QIODevice::WriteOnly)) { qDebug() << "file1 not open."; }
QDataStream dataStream1(&file1);
QVariant qvar1;
qvar1.setValue(basic1);
dataStream1 << (quint32)12345;
dataStream1 << qvar1;
file1.close();
file1.open(QIODevice::ReadOnly);
QDataStream dataStream2(&file1);
quint32 magic;
QVariant qvar2;
dataStream1 >> magic;
qDebug() << "magic number is " << magic;
dataStream2 >> qvar2;
file1.close();
basic2 = qvar2.value<Basic>();
qDebug() << "14 = " << basic1.value << " = " << basic2.value << ".";
//MainWindow w;
//w.show();
return a.exec();
}
The magic number comes back, but there is a message QVariant::save: unable to save type 'Basic' (type id: 1026). and then of course QVariant::load: unable to load type 1026. and then 14 = 14 = 0. The Basic class is just from the QMetaType documentation:
struct Basic
{
Basic();
Basic(const Basic &basic);
~Basic();
int value;
};
Q_DECLARE_METATYPE(Basic)
// basic.cpp
#include "basic.h"
Basic::Basic() {}
Basic::Basic(const Basic &basic)
{
value = basic.value;
}
Basic::~Basic(){}
I'm running out of ideas, does anyone know what is causing the problem? The version of Qt is 5.10.1.
Because compiler can't read your mind, you need describe how serialization is possible, e.g.
struct Basic
{
Basic();
Basic(const Basic &basic);
~Basic();
int value;
friend QDataStream & operator << (QDataStream &arch, const Basic& object)
{
arch << object.value;
return arch;
}
friend QDataStream & operator >> (QDataStream &arch, Basic& object)
{
arch >> object.value;
return arch;
}
};
Q_DECLARE_METATYPE(Basic);
in main()
qRegisterMetaType<Basic>("Basic");
qRegisterMetaTypeStreamOperators<Basic>("Basic");
before save\load operation would happen. Q_DECLARE_METATYPE is required to store type with QVariant, those two are required to register object's "big three" to manage it as resource and its serialization methods. Output:
path1 variable is "C:/Users/Yaroslav/test1/"
apphome path is "C:/Users/Yaroslav/test1"
mkdir returned false. directory already exists?
apphome path is "C:/Users/Yaroslav/test1"
magic number is 12345
14 = 14 = 14 .
P.S. Note, if you left return a.exec(); with no window present, you get program staying in memory forever until you stop it.
I am using Qt (5.5) and I want to exchange data in JSON format in a client-server application.
So the format is constant:
{
"ball":
{
"posx": 12,
"posy": 35
}
}
I would like to be able to define a ByteArray or string like so:
QByteArray data = "{\"ball\":{\"posx\":%s,\"posy\":%s}}"
and then just write whatever the values for that into the string.
How do I do that?
QtJson is baked into Qt 5. It is easy to use, and gets it all ready for you pretty easily.
#include <QCoreApplication>
#include <QDebug>
#include <QJsonObject>
#include <QJsonDocument>
void saveToJson(QJsonObject & json);
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
QJsonObject jsonObject;
saveToJson(jsonObject);
QJsonDocument jsonDoc(jsonObject);
qDebug() << "Example of QJsonDocument::toJson() >>>";
qDebug() << jsonDoc.toJson();
qDebug() << "<<<";
return a.exec();
}
void saveToJson(QJsonObject & json)
{
QJsonObject ball;
ball["posx"] = 12;
ball["posy"] = 35;
json["ball"] = ball;
}
output
Example of QJsonDocument::toJson() >>>
"{
"ball": {
"posx": 12,
"posy": 35
}
}
"
<<<
Note: qDebug() wraps QString objects in quotes when printing. To get rid of that, pass your QString into qPrintable(). And it puts endl in for you at the end of each line.
For a more complex example see the official:
JSON Save Game Example
http://doc.qt.io/qt-5/qtcore-json-savegame-example.html
Hope that helps.
And here are more examples of string manipulations, but for readability and maintainability, please use the QJson classes.
QString str;
str = QString("{\"ball\":{\"posx\":%1,\"posy\":%2}}").arg(12).arg(35);
qDebug() << qPrintable(str);
QByteArray ba = str.toLocal8Bit();
qDebug() << ba;
QString str2;
str2 = "{\"ball\":{\"posx\":"
+ QString::number(12)
+ ",\"posy\":"
+ QString::number(35)
+ "}}";
qDebug() << qPrintable(str2);
output
{"ball":{"posx":12,"posy":35}}
"{"ball":{"posx":12,"posy":35}}"
{"ball":{"posx":12,"posy":35}}
Note again that the quotes are added by qDebug() when printing a QByteArray object.
Hope that helps.
I tried to modify the Qt network tutorial, and implemented it like:
quint16 blockSize;
void Client::readData()
{
qDebug() << "Received Data!";
QByteArray data;
QDataStream in(tcpSocket);
in.setVersion(QDataStream::Qt_4_0);
if (blockSize == 0) {
if (tcpSocket->bytesAvailable() < (int)sizeof(quint16))
return;
in >> blockSize;
}
qDebug() << "Received DATA II with blocksize " << blockSize;
if (tcpSocket->bytesAvailable() < blockSize)
{
qDebug() << tcpSocket->bytesAvailable() << ' ' << blockSize;
return;
}
qDebug() << "Received DATA III";
in >> data;
qDebug() << data;
QByteArray dbg = data; // create a copy to not alter the buffer itself
dbg.replace('\\', "\\\\"); // escape the backslash itself
dbg.replace('\0', "\\0"); // get rid of 0 characters
dbg.replace('\n', "\\n");
//dbg.replace('"', "\\\""); // more special characters as you like
qDebug() << dbg;
QString data_string(data);
qDebug() << "Emitting Signal";
emit Client::gotData(data_string);
}
void Server::sendData(void)
{
QByteArray block;
QDataStream out(&block, QIODevice::WriteOnly);
out.setVersion(QDataStream::Qt_4_0);
out << (quint16)0;
out << "Hello World, this is a very long text!";
out.device()->seek(0);
out << (quint16)(block.size() - sizeof(quint16));
qDebug() << "First number is: " << (quint16)(block.size() - sizeof(quint16));
qDebug() << "Blocksize is: " << block.size() << "with quint size: " << sizeof(quint16);
qDebug() << "Sending data!";
//Debug
QByteArray dbg = block; // create a copy to not alter the buffer itself
dbg.replace('\\', "\\\\"); // escape the backslash itself
dbg.replace('\0', "\\0"); // get rid of 0 characters
dbg.replace('\n', "\\n");
//dbg.replace('"', "\\\""); // more special characters as you like
qDebug() << dbg;
connect(clientConnection, SIGNAL(disconnected()), clientConnection, SLOT(deleteLater()));
clientConnection->write(block);
//clientConnection->disconnectFromHost();
}
Connecting works fine, but when I call sendData(), I get (from the same function) the transmitted block:
First number is: 43
Blocksize is: 45 with quint size: 2
Sending data!
"\0+\0\0\0'Hello World, this is a very long text!\0"
My first problem is: Where do all the \0 come from? As far as I understand the code, first I'm creating a 0, then I write the text, and them I am going back to the front and write the full size of the block. Is it because of the size of the (quint16)? When entering nothing, I get \0\0 and a size of 0, which is correct. The size of the example above is 43, which corresponds to + in ascii (and this sign is in the block above, too).
My second problem is: My readData()-function does not recognize the block size, (it always returns 450 as block size, which is clearly wrong). Why? Did I miss something?
UPDATE: After changing QByteArray data; to QString data; my problems are gone, no more strange \0 in my code -> should have used the right data type -> Head->Desk