Последнее обновление:
November 20, 2019

Есть мысль... Жми, напиши!
Что имеем: Постов : 166 Авторов: 1 Категорий: 27

Программирование и отладка STM32F3 Discovery в QtCreator под Windows

Впринципе, алгоритм действий точно такой же, как и в предыдущем посте под Ubuntu

Обновил ссылку на новый ARM GCC

Здесь приведу лишь отличия по пунктам

  1. Качаем  драйвер, распаковываем и ставим. Вместо ST-Link поставим OpenOCD  , скачиваем, распаковываем в любую папку.
  2. так же
  3. Качаем GCC ARM с https://developer.arm.com/open-source/gnu-toolchain/gnu-rm/downloads (справа в списке экзешник) и ставим.  отладчик qtcreator-gdb-7-7-mingw32_nt-6-1-i686 (т.к. для Qt Creator нужно, что бы он был с поддержкой питона), распаковываем в любую папку и прописываем полный путь, имя на ваше усмотрение.
  4. Путь компилятораC:\Program Files (x86)\GNU Tools ARM Embedded\6 2017-q1-update\bin\arm-none-eabi-gcc.exe (либо в ту папку, куда поставили)
  5. При добавлении выбираем OpenOCD, запуск в режиме pipe,
    исполняемый файл: прописываете полный путь до OpenOCD.exe,
    файл конфигурации ставите <full path>\openocd-0.9.0\scripts\board\stm32f3discovery.cfg  под свою плату.
  6. Также
  7. Также

Вот как -то так =)

Если вылетает при отладке, либо при её завершении, поставьте в Qt Creator -> Инструменты -> Параметры -> Отладчик -> GDB, расширенные
галку у «Использовать асинхронный режим для работы с программой»
Если будет ошибка «Unknown remote qXfer reply: OK», то см. пункт 5.1 из статьи для Ubuntu

P.S  Вместо OpenOCD можно использовать старую добрую st-link-utility под Windows, но она старовата и, как мне кажется, тормознута.

Views :

2314

Программирование и отладка STM32F3 Discovery в QtCreator под Ubuntu

Спустя три года опять решил поиграться с STM32F, но уже вплотную.

В этот раз в роли IDE и дебагера будет выступать QtCreator т.к. в новых версиях есть плагинчик для работы с голыми устройствами.

Ось — Ubuntu 16.04, под Windows тут недалеко.

1.  Поставим сам отладчик для STM т.е. gdb сервер

Устанавливаем всё необходимое для сборки:

sudo apt-get install libusb-1.0-0-dev

Надеюсь CMake и GCC уже стоят.

Для этого клонируем репозиторий и собираем ST-Link Utility

cd ~/Projects/ST-Link-Utility
git clone https://github.com/texane/stlink.git .
make release
cd build/Release
sudo make install
sudo ldconfig
sudo udevadm control --reload-rules
sudo  udevadm trigger

Вот впринципе сервер скомпиллен, запускать его для вывода справки:

st-util -h

2. Включаем в QtCreator плагин Help -> About Plugins -> галка напротив BareMetal и перезапускаем QtCreator

3. Дальше необходимо поставить компилятор и отладчик для архитектуры ARM

sudo add-apt-repository ppa:team-gcc-arm-embedded/ppa
sudo apt-get update
sudo apt-get install gcc-arm-embedded

4. Добавляем их в QtCreator

Preferences -> Build & Run -> Compillers -> Add -> GCC

Название на ваше усмотрение, у меня: arm-none-eabi-gcc

Путь прописываем такой: /usr/bin/arm-none-eabi-gcc

Preferences -> Build & Run -> Debuggers -> Add

Название на ваше усмотрение, у меня: arm-none-eabi-gdb 

Путь прописываем такой: /usr/bin/arm-none-eabi-gdb 

5. Создадим устройство, переходим в Preferences ->BareMetal -> Add ST-Link

название на ваше усмотрение, у меня ST-Link-Utility

режим запуска: TCP/IP

исполняемый файл: st-util

хост: localhost, порт: 4242

5.1 Нужно дать отладчику дополнительное время для ожидания подключения:

Options->Debugger->GDB->Additional Startup Commands и прописать

set remotetimeout 10

6. Теперь добавляем комплект сборки:

Preferences -> Build & Run -> Kits -> Add

Название на ваше усмотрение, у меня Qt for Bare Metal

Тип устройства: Bare Metal

Устройство: Нажимаете Manager -> Add -> Bare Metal

Название на ваше усмотрение, у меня ST-Link1

Тип сервера gdb:  ST-Link-Utility (из предыдущего шага)

Компилятор:  как задали в предыдущем шаге, у меня arm-none-eabi-gcc

Отладчик: как задали в предыдущем шаге, у меня arm-none-eabi-gdb

Профиль Qt: отсутствует

7. Так, с подготовкой закончили, создаём новый проект, импортировав его шаблон из Git репозитория File-> New -> Import -> Git.

Репозиторий с шаблоном: https://github.com/Riflio/STM32F3DiscoveryQtCreatorTemplate

Путь выбираете свой.

Смените комплект на Qt for Bare Metal и можно наконец то прожать Run, в окне вывод приложения должно появиться примерно это:

Отладка запущена
st-util 1.2.0-147-g3de5cf0
Flash page at addr: 0x08000000 erased
Flash page at addr: 0x08000800 erased
Flash page at addr: 0x08001000 erased

И светодиоды должны начать зажигаться по кругу.

Если вылетает при отладке, либо при её завершении, поставьте в Qt Creator -> Инструменты -> Параметры -> Отладчик -> GDB, расширенные
галку у «Использовать асинхронный режим для работы с программой»
Если будет ошибка «Unknown remote qXfer reply: OK«, то см. пункт 5.1

P.S. Как создавать шаблон под другие контроллеры?
Сделать его достаточно просто, потребуется CMSIS — в ней содержатся описания для доступа к регистрам периферии и STM32F30x_StdPeriph_Driver (в новых версиях переименован в HAL)
Всё это ищется в недрах сайта st.com    ldscripts были найдены в каком-то демо-проекте 😀

Вот как-то так =)

Views :

3063

Конвертация QVideoFrame to OpenCV Mat в Qt5.6 и OpenCV3.1

Потребовалось на днях обрабатывать кадры с камеры (Использовалась QCamera) через OpenCV.

Да,  OpenCV может сам захватывать фреймы, но в случае с Qt QCamera работает лучше и есть больше параметров (например выбо р формата YUV или MJPG).

Вот так выглядит конвертация:

QVideoFrame copy(frame);
if (frame.isValid() && copy.map(QAbstractVideoBuffer::ReadOnly)) {
    Mat frameYUV=Mat(copy.height() + copy.height()/2, copy.width(), CV_8UC1, (void*)copy.bits() );
    
    Mat frameRGB;
    cvtColor(frameYUV, frameRGB, CV_YUV2BGRA_I420);

    imshow("Video", frameRGB);
}

C камеры приходит QVideoFrame frame в формате YUV.

Вот и всё =)

 

 

Views :

333

Qt настраиваем логирование в проекте (формат лога)

Приветствую!

Отладочные сообщения в QtCreator достаточно не информативные, особенно в большом проекте, а каждый раз прописывать  что-то вроде:

qDebug()<<"MyClass::functionName params"<<p1<<p2;

что бы знать в каком хоть классе и функции идёт вывод достаточно долго.

Можно перехватить вывод qDebug, а заодно qInfo, qWarning и т.д. и выводить их в файл логов (либо писать в базу, либо отправлять на лог-сервер).

Делается это так:

в main.cpp  сразу после QApplication app(…); прописываем:

 qInstallMessageHandler(myMessageHandler);

В *.pro файле добавляем:

DEFINES += QT_MESSAGELOGCONTEXT

что бы обрабатывался контекст вызова, ну и делаем свой обработчик вывода:

#include <QDateTime>
void myMessageHandler(QtMsgType type, const QMessageLogContext& context, const QString &msg)
{
    QString txt;   
    static long long uid=0; //-- номеруем вывод
    //-- название функции с классом, берём только класс и саму функцию
    QRegExp rx("([\\w-]+::[\\w-]+)");
    if (rx.indexIn(context.function) ==-1) return;
    QString function = rx.cap(1);

    QString msgSep = (msg.length()>0)? ">> " : "";

    switch (type) {
        case QtInfoMsg:
            txt = QString("Info: %1%2%3").arg(function).arg(msgSep).arg(msg);
        break;
        case QtDebugMsg:
            txt = QString("Debug: %1%2%3").arg(function).arg(msgSep).arg(msg);
            break;
        case QtWarningMsg:
            txt = QString("Warning: %1%2%3").arg(function).arg(msgSep).arg(msg);
        break;
        case QtCriticalMsg:
            txt = QString("Critical: %1%2%3").arg(function).arg(msgSep).arg(msg);
        break;
        case QtFatalMsg:
            txt = QString("Fatal: %1%2%3").arg(function).arg(msgSep).arg(msg);
            abort();
        break;
    }

    QDateTime dateTime = QDateTime::currentDateTime();
    uid++;
    txt=QString("%1:%2 %3").arg(dateTime.toString(Qt::ISODate)).arg(uid).arg(txt);

    QFile outFile(QString("%1/log-%2.log").arg(".").arg(QDate::currentDate().toString("dd.MM.yy")));
    outFile.open(QIODevice::WriteOnly | QIODevice::Append);
    QTextStream ts(&outFile);
    ts << txt << endl;
    outFile.close();


}

Дальше, если у вас Линь, то достаточно просто в консольке прописать:

tail -f  log-18.09.16.log

и весь вывод будет идти в реал тайме.

Если разбор выражения на отдельные поля не требуется, то можно сразу задать шаблон вывода:

в main.cpp перед QApplication  прописать:

qSetMessagePattern("%{type} %{if-category}%{category}: %{endif}%{function}: %{message}");

Подробнее можно найти в офф. доках: http://doc.qt.io/qt-5/qtglobal.html#qSetMessagePattern

Вот как-то так =)

Views :

2038

Android MySql (QMysql) драйвер для Qt5.6 на Windows и Linux компиляция

В общем понадобилось портировать одну прогу под Андроид arm7, но она плотненько работает с базой данных, а так как я человек впринципе ленивый, то обёртку для REST API сервера было лень писать, решился на компилирование MySQL плагина, но если бы я знал тогда, что это займёт у меня 20 часов…
красноглазик

 

В общем вот вам готовый рецепт из 12 шагов для компиляции на Ubuntu и на Windows
То, что помечено windows16 -выполнять только на винде.
Установим инструменты:
1. Качаем и устанавливаем CMake https://cmake.org/download/ у меня 3.5.2
2. Разумеется Android NDK у вас уже должен быть установлен, но вдруг: https://developer.android.com/tools/sdk/ndk/index.html
windows163. Качаем и ставим MSYS https://sourceforge.net/projects/mingw/files/latest/download?source=files (отмечаем всё, что можно)
4. При установке Qt нужно было поставить и исходники (папка qt/5.6/src/qtbase), если нет её, то качаем и ставим
windows165. Открываем консольку MSYS (c:\mingw\msys\1.0\msys.bat), в дальнейшем все действия будут вестись в ней и для удобства выкачивания установим wget:

/c/mingw/bin/mingw-get install msys-wget-bin

1. Создадим отдельную директорию, где будем развлекаться и перейдём в неё:

mkdir /d/Projects/AndroidMySQL
 cd /d/Projects/AndroidMySQL

2. Выкачиваем саму MariaDB, а именно коннектор

wget https://downloads.mariadb.org/interstitial/connector-c-3.0.0/mariadb-connector-c-3.0.0-alpha-src.tar.gz
 tar -xzvf mariadb-connector-c-3.0.0-alpha-src.tar.gz

3. Выкачиваем и распаковываем исходники iconv http://ftp.gnu.org/pub/gnu/libiconv/libiconv-1.14.tar.gz

wget http://ftp.gnu.org/pub/gnu/libiconv/libiconv-1.14.tar.gz
 tar -xvzf libiconv-1.14.tar.gz

4. Выкачиваем и распаковываем OpenSSL

wget -c http://www.openssl.org/source/openssl-1.0.1h.tar.gz --no-check-certificate
 tar -xvzf openssl-1.0.1h.tar.gz

5. Задаём общие глобальные переменные
windows16

 export PATH="$PATH:/c/mingw/bin:/c/Program Files (x86)/CMake/bin"
 export ANDROID_NDK_ROOT=/d/Android/android-ndk-r10e
 export SR="$ANDROID_NDK_ROOT"/platforms/android-19/arch-arm/usr # Укажите платформу, под которую собираете ваши проекты (Лучше, 19)
 export BR="$ANDROID_NDK_ROOT"/toolchains/arm-linux-androideabi-4.9/prebuilt/windows-x86_64/bin/arm-linux-androideabi-
 export CPP="$BR"cpp
 export AR="$BR"ar
 export STRIP="$BR"strip
 export RANLIB="$BR"ranlib
 export LINKER="$BR"ld
 export OBJDUMP="$BR"objdump
 export CC="$BR"gcc
 export CFLAGS="--sysroot=$SR"
 export CPPFLAGS="$CFLAGS"
 export C_INCLUDE_PATH=$SR/include
 export ANDROID_DEV=$SR/usr
 export MAKEDEPPROG="$CC -M"

6. Собираем сначала iconv

cd libiconv-1.14
 ./configure --host=arm --prefix=$SR/usr --with-sysroot=$SR
 make
 make install

7. Собираем OpenSSL

cd ../openssl-1.0.1h
 CC="$CC -march=armv7-a -mfloat-abi=softfp"
 ./Configure android-armv7 --prefix=$SR/usr no-asm
 make
 make install
 make install_sw
Если заматериться error: undefined reference to ‘__ctype_get_mb_cur_max’,
то в файл libcharset/lib/localcharset.c после дефайнов добавляем

size_t __ctype_get_mb_cur_max(void){
 return 1;
 }

8. Нус, начинаем подготовку к сборке MariaDB

В файл include/my_global.h необходимо добавить определение типа ushort

#ifndef ushort
 #define ushort uint16
 #endif

9. Подготавливаем сборку

cd ../mariadb-connector-c-3.0.0-alpha-src
mkdir build
 cd build
cmake -G "Unix Makefiles"
 -DCMAKE_BUILD_TYPE=Release \
 -DCMAKE_AR="$BR"ar.exe \
 -DCMAKE_C_COMPILER="$BR"gcc.exe \
 -DCMAKE_C_FLAGS=--sysroot=$SR \
 -DCMAKE_LINKER="$BR"ld.exe \
 -DCMAKE_RANLIB="$BR"ranlib.exe \
 -DCMAKE_STRIP="$BR"strip.exe \
 -DCMAKE_SYSTEM_NAME=Linux \
 -DICONV_INCLUDE_DIR="$SR/usr/include" \
 -DICONV_LIBRARIES="$SR/usr/lib/libiconv.a" \
 -DOPENSSL_ROOT_DIR="$SR/usr/lib/" \
 ../

10. Зажмуриваемся и собираем

make
windows16 ага, фиг то там, failed to create symbolic link ‘libmysqlclient.a’: No error
внезапно… тут, похоже, баг самого CMake, поэтому в файле
\AndroidMySQL\mariadb-connector-c-3.0.0-alpha-src\build\libmariadb\CMakeFiles\SYM_libmysqlclient.a.dir\build.make
находим строки (их по две) c -E create_symlink libmariadbclient.a libmysqlclient.a, удаляем её полностью
а так же -E create_symlink libmariadb.so libmysqlclient_r.so аналогично
и вручную копируем и продолжаем сборку

cp libmariadb/libmariadbclient.a libmariadb/libmysqlclient.a
 cp libmariadb/libmariadbclient.a libmariadb/libmysqlclient_r.a
 cp libmariadb/libmariadb.so libmariadb/libmysqlclient.so
 cp libmariadb/libmariadb.so libmariadb/libmysqlclient_r.so
 make
и ещё раз фиг error: unknown type name ‘pthread_mutex_t’
в файле ../unittest/libmariadb/thread.c
находим pthread_t threads[THREAD_NUM]; заменяем на void * threads[THREAD_NUM];
и там же заменяем pthread_mutex_t LOCK_test; на void * LOCK_test;
и опять
make

На этот раз должно всё ок пройти, ну и устанавливаем и копируем к нашему ndk

make install
mkdir "$SR/usr/lib/mariadb"
 mkdir "$SR/usr/include/mariadb/"
 cp libmariadb/*.{a,so} "$SR/usr/lib/mariadb/"
 cp ../include/* "$SR/usr/include/mariadb/"

11. Собираем плагин QMySQL, открываем обычную консольку пути только на свои замените

cd /d/Qt/5.6/Src/qtbase/src/plugins/sqldrivers/mysql/
 /d/Qt/5.6/android_armv7/bin/qmake.exe \
 "INCLUDEPATH+=$SR/usr/include/mariadb" \
 "LIBS+=-L$SR/usr/lib/mariadb -lmariadbclient -lssl -lcrypto -liconv" \
 -o Makefile mysql.pro
make
 make install

12. Разрабатываем тестовый проект
Так как зависит от libmariadb.so, то его необходимо таскать с проектом, для этого в *.pro файле проекта добавить

contains(ANDROID_TARGET_ARCH,armeabi-v7a) {
 ANDROID_EXTRA_LIBS = \
 d:/Projects/AndroidMySQL/mariadb-connector-c-3.0.0-alpha-src/build/libmariadb/libmariadb.so
 }

Пересобираем проект, запускаем, и хуй то там =)
QMYSQL driver not loaded
яоминь
Посмотрим зависимости libqsqlmysql.so, которая в каталоге /home/pavelk/Qt/5.6/android_armv7/plugins/sqldrivers

ldd libqsqlmysql.so

и опять облом, нужна ldd для arm, ладно и с этим разберёмся, например так, тынц.

ldd-avr libqsqlmysql.so

Дело в том, что в зависимостях у libmysql.so есть libmariadb.so.3, а не libmariadb.so
почуяли разницу? =))

В общем, что бы побыстроляну пофиксить
в файле libmariadb/CMakeLists.txt
находим

SOVERSION ${CPACK_PACKAGE_VERSION_MAJOR})

и заменяем на

SOVERSION "so")

ну а дальше удалить полностью build и заново, начиная с 9 шага
troll

!пересобираем! проект, не забыть исправить в pro файле на libmariadb.so.so запускаем и радуемся =)

Итого: сэкономлено куча времени и нервов. Хоть спасибо скажите =))

Views :

1332

Qt Android JNI преобразование QByteArray в jbytearray и обратно, а так же получение и передача в jni функцию

Подребовалось мне из Java класса вызвать функцию, наподобии этой:

public int send(byte[] data)
{     
....
}

Ну а что бы её вызвать из C++ нужно было преобразовать QByteArray в jbytearray
делается это так:

    jbyteArray QByteArray2jbyteArray(QByteArray buf)
    {
     QAndroidJniEnvironment env;
     jbyteArray array = env->NewByteArray(buf.length());
     env->SetByteArrayRegion (array, 0, buf.length(), reinterpret_cast<jbyte*>(buf.data()));
     return array;
    }

если нужно обратное преобразование, то делается так:

QByteArray jbyteArray2QByteArray(jbyteArray buf)
    {
       QAndroidJniEnvironment env;
       int len = env->GetArrayLength(buf);
       QByteArray array;
       array.resize(len);
       env->GetByteArrayRegion (buf, 0, len, reinterpret_cast<jbyte*>(array.data()));
       return array;
    }

ну а саму функцию из Java класса с помощью JNI можно вызвать так:

QAndroidJniObject myActivity=  QtAndroid::androidActivity();
myActivity.callMethod<int>("send", "([B)I", QByteArray2jbytearray(myByteArray));

Если нужно наоборот вернуть из функции jbytearray, то тут немного по сложнее:

QAndroidJniObject myActivity=  QtAndroid::androidActivity();
QAndroidJniObject readData = myActivity.callObjectMethod("read", "(V)[B");
jbyteArray array =readData.object<jbyteArray>();

Кстати, не забываем подключать заголовочники:

#include <QtAndroid>
#include <QAndroidJniEnvironment>
#include <QAndroidJniObject>

И в *.pro файле добавлять

QT +=  androidextras

Вот как то так =)

Views :

993

Печатаем на фискальнике Custom VKP-80K из c++ на Qt

В общем задача была разобраться с печатью именно фискалки, благо с обычной печатью всё просто, попробуем теперь с ним.

Т.к. дела раньше с фискальниками почти не имел, ссался, что в нём уже стоит ЭКЛЗ и все мои тестовые продажи Нидерландов уйдут в память, а потом при проверке налоговая не досчитается несколько ВВП,

но всё оказалась проще, ЭКЛЗ нет, а в сервисе сказали, что даётся 1000 тестовых печатей, пока там какая-то память не включиться, чтож, ок.

 

Первым делом как обычно качаем драйвера OPOS. Почему OPOS ? Лично я уже просто привык. У меня через них работает и чекопечатник и сканер штрих-кодов и печатник штрих-кодов и карт ридер и по мелочи разные фентифлюшки и в случай их замены не придётся пол протокола переписывать.

Дальше ставим непосредственно драйвера фискальника. Скорее всего это будет АТОЛ в рот ему ноги (версия 4.18). Ставим как обычно.

Проверить фискальник можно зайдя в папку с дровами и запустив (C:\Program Files\АТОЛ\Drivers\Bin\FPRNM_T.exe)

справа внизу клацаете галку устройство включено, вверху справа выбираете режим «1 регистрация», жамкаете «Войти»,

затем непосредственно продаёте: переходите на таб  «Регистрация» жамкаете на   «Продажа» и затем «Закрыть чек без сдачи».

Должен вылезти чек. За ошибками смотреть внизу в поле «Результат»

Так, теперь пора бы и начать кодить, а фиг там.

Ещё нужно сгенерировать заголовочник и реализацию для OPOS, а если точнее для ActiveX компонента, т.к. работа идёт через него.

Запускаем консольку, вбиваем:

cd C:\Projects\VKP-80K\
C:\Qt\5.4\mingw491_32\bin\dumpcpp "C:\Program Files (x86)\OPOS\CommonCO\OPOSFiscalPrinter.ocx"

Ток пути на свои замените.

В папке C:\Projects\VKP-80K\  должны появится вожделенные заголовочник и реализация.

Так же в эту папку не помешает кинуть заголовочник с константами OposFptr.h и Opos.h (из папки с установленными OPOS)

А вот теперь можно и покодить.

Создаём новый проектик (у меня простой консольный) и сразу в .pro файл добавляем

CONFIG += qaxcontainer # Для работы с ActiveX

Дальше в main.cpp подключаем наш заголовочник, константы, и заодно пространство имён (откройте заголовочник, вверху увидите), в моём случае

#include "oposfiscalprinter_cco.h"
#include "OposFptr.h"
using namespace OposFiscalPrinter_CCO;

Ну и теперь печатаем нашу продажу, приведу код с комментами, там всё просто:

OPOSFiscalPrinter * ECR;

ECR = new OPOSFiscalPrinter();

ECR->Open(""); //-- Подключаемся. Стандартное имя для этой фискалки, ищите в инструкции
ECR->ClaimDevice(1000); //-- Захватываем
ECR->SetDeviceEnabled(true); //-- Включаем

ECR->ResetPrinter(); //-- сбрасываем состояние в дефолтное

ECR->SetFiscalReceiptType(FPTR_RT_SALES); //-- Говорим, что начинаем продажу

ECR->BeginFiscalReceipt(false); //-- Начинаем печатать фискальный чек

int summ = 123;
int count = 1;

ECR->PrintRecItem( "ТЕСТ ПРОДАЖИ" , summ ,  count*1000, 0 , summ , "psc" ); //-- Печатаем продажу. count*1000 не ошибка, так надо =) 

int salesSumm =123; //-- нам нужно при окончании указать точную сумму всех операций, иначе чек будет анулирован

ECR->PrintRecTotal(salesSumm,  salesSumm , "1"); //-- печатаем итоговую сумму, сколько внесено, валюту.

ECR->PrintRecMessage("Тест прошёл успешно"); //-- кастомные сообщений после основной части текста

ECR->EndFiscalReceipt(false); //-- завершаем фискальник и выплёвываем его

ECR->PrintZReport(); //-- по-приколу распечатаем z-отчёт. P.S. должны быть промежутки между печатью z-ки, у меня принтер раньше, чем каждые 2 часа не давал.

ECR->SetDeviceEnabled(false);
ECR->close();

Вот так вот =)  Надеюсь всё получилось.

 

И на десерт — в Qt 5.5 не печатает на фискалке копейки 😀 в чём проблема я разобрался, но на это ушла вся ночь, поэтому решение за отдельную плату,  сами разберётесь, там просто оказывается.

 

Views :

774

OpenCV 3.1 захват видео с камеры в Qt 5.6

Надеюсь, компиляция прошла успешно =)

Обновил на новый лад с использованием Mat

Создаём новый консольный проект, в .pro файле дописываем:

INCLUDEPATH += "/usr/local/opencv/3.1/include/"
LIBS += -L"/usr/local/opencv/3.1/lib/"
LIBS += -lopencv_core \
        -lopencv_features2d \
        -lopencv_highgui \
        -lopencv_imgcodecs \
        -lopencv_imgproc \
        -lopencv_video \
        -lopencv_videoio \
        -lopencv_videostab

Теперь основное main.cpp:

#include <QApplication>
#include <QDebug>

#include <opencv2/opencv.hpp>
#include <opencv2/highgui.hpp>

using namespace std;
using namespace cv;

int main(int argc, char *argv[])
{
    QApplication app(argc, argv);
    qDebug()<<"Hello world";

    //-- Выбираем первую попавшуюся камеру
    VideoCapture cap(0);

    //-- Проверяем, удалось ли подключиться
    if (!cap.isOpened()) {
        qDebug()<<"Camera not opened!";
        return 0;
    }

    //-- Выставляем параметры камеры ширину и высоту кадра в пикселях
    cap.set(CV_CAP_PROP_FRAME_WIDTH, 1280);
    cap.set(CV_CAP_PROP_FRAME_HEIGHT, 960);

    Mat frame;

    while (true) {
        cap >> frame; //-- захватываем очередной кадр

        imshow("Video", frame); //-- показываем его

        char c = cvWaitKey(33); //-- если была нажата клавиша, узнаём её код

        if (c==27) { //-- нажата ESC, прерываем цикл
            break;
        }

    }


    return app.exec();
}

Впринципе, ничего сложного.

Views :

5939

PoDoFo сборка для Qt на Ubuntu 14.10

PoDoFO

PoDoFo это библиотека для чтения и записи PDF файлов.

Для Windows мануал здесь.

Создаём папку, в которой будет идти вся сборка, у меня это ~/Projects/PoDoFO/

Скачиваем саму PoDoFO
Распаковываем файлы архива в папку  podofo-src

Ещё понадобиться LibJpeg
Распаковываем файлы в папку jpeg-9a
Компилируем LibJpeg.
В терминале:

cd ~/Projects/PoDoFo/jpeg-9a/
./configure
make
sudo make install

Так же потребуется LibPng, устанавливаем так:

sudo apt-get install libpng-dev

Теперь, наконец-то, собираем сам PoDoFo

cd  ~/Projects/PoDoFO/podofo-build/
cmake -G "Unix Makefiles" -DCMAKE_INSTALL_PREFIX="$HOME/Projects/PoDoFo/lib" ../podofo-src
make
sudo make install

Библиотека скомпилирована! Всё необходимое будет в папке ~/Projects/PoDoFo/lib

Документация по PoDoFo здесь.

Исходники тестового проекта Qt и PoDoFo.

Views :

716

Установка и печать на термопринтере VKP-80II из Qt 5

Прилетела на днях сия  игрушка.
Применений к ней куча — всё зависит от фантазии.

Сейчас расскажу как на нём печатать из Qt.

Первым делом идём на сайт производителя за дровами, да не простыми, а OPOS.

Вставим чековую ленту в принтер, теперь вынимаем питание, зажимаем верхнюю кнопку (Line feed), включаем питание, ждём пока зажужжит и отпускаем кнопку.

Напечатаются настройки и жмём снова верхнюю кнопку (Line feed) что бы принтер выплюнул ленту.

С ленты нас интересует только параметры RS232, они сейчас потребуются.

Запускаем установку дров, указываем способ соединения и параметры скорости (по умолчанию 19200) и прочие, при необходимости.

Для теста, запускаем OPOS POS Printer configurator и настраиваем параметры.

В нём мы настраиваем как связатсья с принтером через OPOS драйвер. Запомните device name — оно нам пригодится.

Потом запускаем OPOS POS Printer test и можно немного поиграться.

Если всё работает, то пора создавать новый Qt проект (тип — на ваш выбор).

Всё общение с термопринтером идёт через ActiveX компонент OPOSPOSPrinter.ocx, поэтому сейчас заодно покажу как работать с ActiveX в Qt.

Для работы нам нужно получить от библиотеки реализацию cpp и h файлов с помощью утилитки, входящую в состав Qt — dumpcpp.

Открываем виндузятную консольку, переходим в каталог, где будем создавать классы, и запускаем dumpcpp:

cd C:\Projects\1CTerminal\1CTerminal\opos
dumpcpp "C:\Program Files (x86)\OLEForRetail\ServiceOPOS\POSPrinter\CustomEngineering\OPOSPOSPrinter.ocx"

В каталоге должно появится два файла, открываем их на изучение, что бы примерно понять с чего начать.

Т.е. как минимум узнаём пространство имён (OposPOSPrinter_1_9_Lib) и название класса (OPOSPOSPrinter).

В *.pro файле проекта добавляем:

CONFIG += qaxcontainer # Для работы с ActiveX

Добавляем в проект сгенерированные файлы oposposprinter_1_9_lib.cpp и oposposprinter_1_9_lib.h

Заодно добавьте следующий заголовочный файл, в нём собрал все используемые статусные сообщения:

Заголовочник opos/oposprinter_consts.h

//-- Коды результата
namespace OposPOSPrinter_1_9_Lib {

    #define OPOS_SUCCESS            0
    #define OPOS_E_CLOSED           101
    #define OPOS_E_CLAIMED          102
    #define OPOS_E_NOTCLAIMED       103
    #define OPOS_E_NOSERVICE        104
    #define OPOS_E_DISABLED         105
    #define OPOS_E_ILLEGAL          106
    #define OPOS_E_NOHARDWARE       107
    #define OPOS_E_OFFLINE          108
    #define OPOS_E_NOEXIST          109
    #define OPOS_E_EXISTS           110
    #define OPOS_E_FAILURE          111
    #define OPOS_E_TIMEOUT          112
    #define OPOS_E_BUSY             113
    #define OPOS_E_EXTENDED         114

    #define strOPOS_SUCCESS         "OPOS_SUCCESS"
    #define strOPOS_E_CLOSED        "OPOS_E_CLOSED"
    #define strOPOS_E_CLAIMED       "OPOS_E_CLAIMED"
    #define strOPOS_E_NOTCLAIMED    "OPOS_E_NOTCLAIMED"
    #define strOPOS_E_NOSERVICE     "OPOS_E_NOSERVICE"
    #define strOPOS_E_DISABLED      "OPOS_E_DISABLED"
    #define strOPOS_E_ILLEGAL       "OPOS_E_ILLEGAL"
    #define strOPOS_E_NOHARDWARE    "OPOS_E_NOHARDWARE"
    #define strOPOS_E_OFFLINE       "OPOS_E_OFFLINE"
    #define strOPOS_E_NOEXIST       "OPOS_E_NOEXISTS"
    #define strOPOS_E_EXISTS        "OPOS_E_EXISTS"
    #define strOPOS_E_FAILURE       "OPOS_E_FAILURE"
    #define strOPOS_E_TIMEOUT       "OPOS_E_TIMEOUT"
    #define strOPOS_E_BUSY          "OPOS_E_BUSY"
    #define strOPOS_E_EXTENDED      "OPOS_E_EXTENDED"

    //-- Коды состояний
    #define PTR_S_RECEIPT           2

    //-- Коды параметров
    #define PTR_SUE_COVER_OPEN      11
    #define PTR_SUE_COVER_OK        12

    #define PTR_SUE_JRN_EMPTY       21
    #define PTR_SUE_JRN_NEAREMPTY   22
    #define PTR_SUE_JRN_PAPEROK     23

    #define PTR_SUE_REC_EMPTY       24
    #define PTR_SUE_REC_NEAREMPTY   25
    #define PTR_SUE_REC_PAPEROK     26

    #define PTR_SUE_SLP_EMPTY       27
    #define PTR_SUE_SLP_NEAREMPTY   28
    #define PTR_SUE_SLP_PAPEROK     29

    #define PTR_SUE_JRN_CARTRIDGE_EMPTY         41
    #define PTR_SUE_JRN_CARTRIDGE_NEAREMPTY     42
    #define PTR_SUE_JRN_HEAD_CLEANING           43
    #define PTR_SUE_JRN_CARTRIDGE_OK            44

    #define PTR_SUE_REC_CARTRIDGE_EMPTY         45
    #define PTR_SUE_REC_CARTRIDGE_NEAREMPTY     46
    #define PTR_SUE_REC_HEAD_CLEANING           47
    #define PTR_SUE_REC_CARTRIDGE_OK            48

    #define PTR_SUE_SLP_CARTRIDGE_EMPTY         49
    #define PTR_SUE_SLP_CARTRIDGE_NEAREMPTY     50
    #define PTR_SUE_SLP_HEAD_CLEANING           51
    #define PTR_SUE_SLP_CARTRIDGE_OK            52

    #define PTR_SUE_IDLE                        1001

    #define strPTR_SUE_COVER_OPEN               "PTR_SUE_COVER_OPEN"
    #define strPTR_SUE_COVER_OK                 "PTR_SUE_COVER_OK"
    #define strPTR_SUE_REC_EMPTY                "PTR_SUE_REC_EMPTY"
    #define strPTR_SUE_REC_NEAREMPTY            "PTR_SUE_REC_NEAREMPTY"
    #define strPTR_SUE_REC_PAPEROK              "PTR_SUE_REC_PAPEROK"
    #define strPTR_SUE_IDLE                     "PTR_SUE_IDLE"

    #define PTR_BM_ASIS                         -11
    #define PTR_BM_CENTER                       -2

    #define PTR_BCS_UPCA                        101
    #define PTR_BCS_UPCE                        102
    #define PTR_BCS_EAN128                      120
    #define PTR_BCS_Code128                     110


    #define PTR_BC_TEXT_ABOVE                   -12
    #define PTR_BC_TEXT_BELOW                   -13
    #define PTR_BC_CENTER                       -2

}

#endif // OPOSPRINTER_CONSTS_H

Так же создадим новый класс, например Printer, в котором будем осуществлять непосредственно печать.

Дальше я разбирался с помощью интуиции и примерного проекта (В основном: C:\Program Files (x86)\OLEForRetail\ServiceOPOS\POSPrinter\CustomEngineering\OPOSPOSPrinterTest_Src\FormMainApp.frm).

Printer.h:

#ifndef PRINTER_H
#define PRINTER_H

#include "opos/oposposprinter_1_9_lib.h"
#include "opos/oposprinter_consts.h"
using namespace OposPOSPrinter_1_9_Lib;

class Printer : public QObject
{
   Q_OBJECT
public:
   explicit Printer(QObject *parent = 0);

signals:
public slots:
private:
   IOPOSPOSPrinter * oposPrinter;
};
#endif // PRINTER_H

и printer.cpp

#include "printer.h"

Printer::Printer(QObject *parent) :
QObject(parent)
{
   oposPrinter = new IOPOSPOSPrinter();
   oposPrinter->setControl("{ccb90152-b81e-11d2-ab74-0040054c3719}");
   int res = oposPrinter->Open("Custom POS Printer");
   qDebug()<<"Open sataus: "<<res;
   oposPrinter->ClaimDevice(100);
   oposPrinter->SetDeviceEnabled(true);
   oposPrinter->PrintImmediate(2, "Hello, QT!, Привет, мир!" );
   oposPrinter->CutPaper(100);
   oposPrinter->Close();
}

Надеюсь, запечатает. На этом всё =)

Архивчик со вспомогательным классом: Printer

В printer.cpp заменить  AppSettings()->value(«com_printer»).toString()  на device name  из OPOS POS Printer configurator.

Навсякий случай дрова OPOS для Custom VKP-80II

Views :

2189