LINUX.ORG.RU

Сообщения h0x0d9

 

Формат данных от термометра

Добрый день.

Помогите, пожалуйста, разобраться с форматом данных измеренной температуры. Есть в наличии пирометр, отсылающий измерения на виртуальный COM-порт. Из инструкции к устройству: «применить последовательность 0х10, 0х27, старший байт температуры, младший байт температуры». Прослушал трафик устройства. Далее привожу табличку, в которой первым столбцом измеренная температура (DEC) а вторым и третьим — старший и младший байт, соответственно. Вот эта часть мне понятна:

-0,10   FF  FF
18,40   00  b8
25,50   00  FF
25,90   01  03
26,40   01  08
28,00   01  18
28,60   01  1E
29,30   01  25
29,50   01  27
31,00   01  36
31,20   01  38
31,60   01  3C
41,80   01  A2
43,00   01  AE
45,90   01  CB
49,60   01  F0
31,70   01  3D
31,80   01  3E
31,90   01  3F
А вот с этой частью я не могу разобраться:
23,10   00  27
24,50   00  35
24,80   00  38
39,70   01  0D
33,20   01  0C  3F
34,20   01  16  3F
34,50   01  19  3F
34,60   01  1A  3F
34,80   01  1C  3F
34,90   01  1D  3F
35,30   01  21  3F
35,80   01  26  3F
36,50   01  2D  3F
36,90   01  31  3F
37,00   01  32  3F
37,30   01  35  3F
37,70   01  39  3F
37,80   01  3A  3F
38,30   01  3F  3F

Собственно, помогите, пожалуйста, разобрать этот формат температуры.

 ,

h0x0d9
()

Конвертация SFLOAT в double

Добрый вечер. Пишу кросс-клиент для BTLE железки. Впервые столкнулся с форматом поля SFLOAT.

Кусок из стандарта:

The following information is defined in ISO/IEEE Std. 
11073-2060™1-2008 [1]. The SFLOAT-Type data type is defined to
 represent numeric values that are not integer in type. The 
SFLOAT-Type is defined as a 16-bit value with 12-bit mantissa 
and 4-bit exponent. See Annex F.8 of [1] for a thorough 
definition of the SFLOAT-Type. This data type is defined as 
follows: Exponent Mantissa Size 4 bit 12 bit

16-bit float type; the integer type is a placeholder only

SFLOAT-Type ::= INT-U16 The 16–bit value contains a 4-bit 
exponent to base 10, followed by a 12-bit mantissa. 
Each is in twos-complement form. Special values are assigned to 
express the following: 
NaN [exponent 0, mantissa +(2^11 –1) → 0x07FF] 
NRes [exponent 0, mantissa –(2^11) → 0x0800] 
+ INFINITY [exponent 0, mantissa +(2^11 –2) → 0x07FE] 
– INFINITY [exponent 0, mantissa –(2^11 –2) → 0x0802] 
Reserved for future use [exponent 0, mantissa –(2^11 –1) → 0x0801]

На просторах сети был найден нужный код и немного обрезан под мои нужды:

typedef enum {
    MDER_S_POSITIVE_INFINITY = 0x07FE,
    MDER_S_NaN = 0x07FF,
    MDER_S_NRes = 0x0800,
    MDER_S_RESERVED_VALUE = 0x0801,
    MDER_S_NEGATIVE_INFINITY = 0x0802
} ReservedSFloatValues;
static const quint32 FIRST_S_RESERVED_VALUE = MDER_S_POSITIVE_INFINITY;

static const double reserved_float_values[5] = {INFINITY, NAN, NAN, NAN, -INFINITY};

double read_sfloat(quint16 int_data)
{
    quint16 mantissa = int_data & 0x0FFF;
    quint8 expoent = int_data >> 12;

    if (expoent >= 0x0008) {
        expoent = -((0x000F + 1) - expoent);
    }

    float output = 0;

    if (mantissa >= FIRST_S_RESERVED_VALUE && mantissa
            <= MDER_S_NEGATIVE_INFINITY) {
        output = reserved_float_values[mantissa - FIRST_S_RESERVED_VALUE];
    } else {
        if (mantissa >= 0x0800) {
            mantissa = -((0x0FFF + 1) - mantissa);
        }
        double magnitude = pow(10.0f, expoent);
        output = (mantissa * magnitude);
    }

    return output;
}

Есть контрольные данные из спека к прибору:

Byte:2 Format:SFLOAT,  LittleEndian
ex.1) 17.6Kpa -> 0xB0, 0xF0
ex.2) 128mmHg -> 0x80, 0x00 


Собственно, вопросы: не совсем понимаю, где ошибка.

Прогонка первого ex. через парсер — результат inf. Второго — 128 OK

 , ,

h0x0d9
()

Обертка на буфер данных

Здравствуйте, прокомментируйте, пожалуйста, решение и вопрос в самом конце.

Сырые данные из u_int8 *buffer оборачиваются классом Wrapper, который делит buffer на поля, каждому полю ставит в соответствие tag и размер поля. Структура данных для обертки задается списком объектов класса FieldDescription, которые содержат сведения о полях (tag, size), а порядок в списке определяет порядок в Wrapper.

class Wrapper
{
    Wrapper(char *);
    void setStructure(vector<const FieldDescription *> description);
    vector<string> getTagOrder() const;
    void *getValue(string tag) const;
    size_t getSize(string tag) const;
    void setValue(string tag, void * dataPtr);
    map<string, void *> getFieldTagToValue() const;
    map<string, size_t> getFieldTagToSizes() const;     
};

Для полноты картины приведу пример класса-пользователя. Для интерпретации полей Wrapper существует класс Interpreter, который в зависимости от значения интерпретируемого поля и других полей-условий ставит в соответствие строку текста.

class Interpreter
{
public:
    // интерпретация данных
    enum InterpretationType
    {
        PARAMLIST,
        NUMBER,
        STRING,
        IPv4,
        IPv6
    };
    void add(Tag_t tag, InterpretationType type);
    void add(Tag_t tag, map<ParamValue, ParamName_t> parmCode2Name);
    void add_if(Tag_t tag, map<ParamValue_t, ParamName_t> parmValue2Name, 
Tag_t conditionTag, ParamValue_t conditionValue);
    void add_if(Tag_t tag, map<ParamValue, ParamName_t> parmValue2Name, 
multiMap<Tag_t, ParamValue_t> conditionTags2Values);
    void add_if(Tag_t tag, InterpretationType type, multiMap<Tag_t, ParamValue_t> conditionTags2Values);
    map<Tag_t, string> convert(const Wrapper &prim) const;
};

Для чего это все нужно:

  • записывать в buffer данные из xml;
  • читать из буфера в тот же xml.

Вопрос:
Как быть, если некоторые поля Wrapper станут контейнерного типа — будут содержать список значений одного размера по одному тэгу?

 

h0x0d9
()

Хранилище данных и модель

«При реализации модели следует помнить, что QAbstractItemModel не хранит данных, он лишь предоставляет интерфейс, используемый представлениями для доступа к данным», — из тутора по QT-моделям.

Что представляет из себя хранилище? И как сие применять на практике?

Может быть, уважаемое сообщество, накидает годных примеров отношений «хранилище-модель», чтобы глубже понять проблему?

 ,

h0x0d9
()

О «серебрянной пуле» или создание универсальной модели

Здравствуйте.

По примерам MVC, у меня сложилось впечатление, что для каждого набора данных, разработчики делают новую модель, наследуемую от QAbstractItemoModel.

У меня в проекте имеется несколько независимых моделей, которые нужно отображать в виде дерева. Из общего у них только размерность дерева — два. Есть мысль сделать одну модель данных и инициализировать её мультимапом с ключом в качестве элемента верхнего уровня и его[ключа] значениями в качестве детей.

Что скажет уважаемое сообщество, стоит ли овчинка выделки? Какие подводные камни скрываются за этим решением.

 , ,

h0x0d9
()

В QSortFilterProxyModel не срабатывает фильтрация

Вводная: Есть две модели: исходная — дерево на QAbstractItemModel, прокси — таблица на QSortFilterProxyModel. Хочу при клике в исходной на элементе верхнего уровня, отобразить в прокси всех его детей в табличном виде.

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

Помогите, пожалуйста, разобраться, где я напортачил.

Исходники: https://bitbucket.org/h0x0d9/myfilterproxymodel

 ,

h0x0d9
()

Забавное поведение при отображении QAbstractItemModel на QSortFilterProxyModel

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

Есть модель дерева ListsRegisterModel, реализующая QAbstractItemModel. Есть QSortFilterProxyModel, к которой подключаю источником модель ListsRegisterModel. Вывожу ListsRegisterModel и прокси-модель в различные QTreeView.

И тут начинается странное. У меня пропали ветки второго уровня во втором отображении, хотя судя по виду, rowCount() отрабатывает правильно.

Скриншот

Код:

    ListsRegisterModel *model = new ListsRegisterModel(this);

    QSortFilterProxyModel *proxyModel = new QSortFilterProxyModel(this);
    proxyModel->setSourceModel(model);


    QTreeView *view = new QTreeView(this);
    view->setModel(model);

    QTreeView *view2 = new QTreeView(this);
    view2->setModel(proxyModel);

class ListsRegisterModel : public QAbstractItemModel
{
    Q_OBJECT
public:
    explicit ListsRegisterModel(QObject *parent = 0);
    ~ListsRegisterModel();

    QVariant data(const QModelIndex &index, int role) const;
    Qt::ItemFlags flags(const QModelIndex &index) const;
    QVariant headerData(int section, Qt::Orientation orientation,
                        int role = Qt::DisplayRole) const;
    QModelIndex index(int row, int column,
                      const QModelIndex &parent = QModelIndex()) const;
    QModelIndex parent(const QModelIndex &index) const;
    int rowCount(const QModelIndex &parent = QModelIndex()) const;
    int columnCount(const QModelIndex &parent = QModelIndex()) const;
    bool setData(const QModelIndex &index, const QVariant &value,
                 int role = Qt::CheckStateRole);

private:
    enum Columns
    {
        RamificationColumn,
        ListNameColumn = RamificationColumn,
        ListSubscriberColumn
    };

    TreeItem *rootItem;

    /**
     * @brief parseListsFile разбираем структуру файла с описаниями списков
     * @param path путь к файлу с регистром списков
     * @return QMultiMap<имя_списка, адрес получателя>
     */
    QMultiMap<QString, QString> parseListsFile(QString path);

    /**
     * @brief setupModelData первоначальная настройка модели
     * @param lists multiMap с регистром списков
     * @param parent корневой элемент дерева
     */
    void setupModelData(QMultiMap<QString, QString> lists, TreeItem *parent);
    TreeItem *getItem(const QModelIndex &index) const;
};

#include "listsregistermodel.h"
#include <QtCore>
#include "../treeItem/treeitem.h"

ListsRegisterModel::ListsRegisterModel(QObject *parent) :
    QAbstractItemModel(parent)
{
    QList<QVariant> rootData;
    rootData << tr("Имя") << tr("Абоненты");
    rootItem = new TreeItem(rootData);

    QMultiMap<QString, QString> listsReg = parseListsFile("etc/lists.reg");
    setupModelData(listsReg, rootItem);
}


void ListsRegisterModel::setupModelData(
        QMultiMap<QString, QString> lists, TreeItem *parent)
{
    TreeItem *root = parent;
    QList<TreeItem*> parents;
    parents << root;

    foreach (QString listName, lists.uniqueKeys()) {
        root->appendChild(new TreeItem(listName, root));
        if (root->childCount() > 0) {
            parents << root->child(root->childCount() - 1);
        }
        foreach (QString subscriber, lists.values(listName)) {
            parents.last()->appendChild(
                        new TreeItem(subscriber, parents.last()));
        }
    }
}


QMultiMap<QString, QString> ListsRegisterModel::parseListsFile(QString path)
{
    QMultiMap<QString, QString> listsRegister;
    QRegExp rx("^(\\d{4})\\s+\\{(.+)\\}$");

    QFile file(path);
    if (!file.exists()) {
        qWarning() << "Warning: file " << file.fileName() << " is not exist";
    }

    if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
        qWarning() << "Warning: file " << file.fileName() << " didn't' open";
    }

    while (!file.atEnd()) {
        // поиск регулярного выражения в следующей строке
        rx.indexIn(file.readLine().trimmed());
        // выбор абонентов выбранного списка
        QStringList subscribers =
                rx.cap(2).simplified().split(",", QString::KeepEmptyParts);
        // заполнение MultiMap контейнера значениями <имя списка, абонент>
        foreach (QString addr, subscribers) {
            listsRegister.insertMulti(rx.cap(1), addr);
        }
    }

    file.close();

    return listsRegister;
}


ListsRegisterModel::~ListsRegisterModel()
{
    delete rootItem;
}


QVariant ListsRegisterModel::data(const QModelIndex &index, int role) const
{
    if (!index.isValid())
        return QVariant();

    TreeItem *item = getItem(index);

    switch (role) {
    case Qt::DisplayRole:
        if (item->parent() == rootItem) {
            return item->data(index.column());
        }
        else {
            qDebug() << item->data(index.column() - 1);
            return item->data(index.column() - 1);
        }
        break;
    case Qt::CheckStateRole:
        if (index.column() == RamificationColumn
                && item->parent() == rootItem) {
            return QVariant(item->checkState());
        }
        break;
    default:
        return QVariant();
        break;
    }
    return QVariant();
}


TreeItem *ListsRegisterModel::getItem(const QModelIndex &index) const
{
    if (index.isValid()) {
        TreeItem *item = static_cast<TreeItem*>(index.internalPointer());
        if (item) return item;
    }
    return rootItem;
}


Qt::ItemFlags ListsRegisterModel::flags(const QModelIndex &index) const
{
    if (!index.isValid())
        return 0;

    const Qt::ItemFlags f = QAbstractItemModel::flags(index);

    TreeItem * item = getItem(index);

    if (index.column() == RamificationColumn && item->parent() == rootItem) {
        return  f | Qt::ItemIsUserCheckable;
    }
    return f;
}


QVariant ListsRegisterModel::headerData(int section, Qt::Orientation orientation, int role) const
{
    if (orientation == Qt::Horizontal && role == Qt::DisplayRole)
        return rootItem->data(section);

    return QVariant();
}


QModelIndex ListsRegisterModel::index(int row, int column, const QModelIndex &parent) const
{
    TreeItem * parentItem;

    if (row < 0 || column < 0)
        return QModelIndex();

    if (!parent.isValid())
        parentItem = rootItem;
    else
        parentItem = getItem(parent);

    TreeItem *childItem = parentItem->child(row);

    if (childItem)
        return createIndex(row, column, childItem);

    return QModelIndex();
}


QModelIndex ListsRegisterModel::parent(const QModelIndex &index) const
{
    if (!index.isValid())
        return QModelIndex();

    TreeItem *childItem = getItem(index);
    TreeItem *parentItem = childItem->parent();

    if (parentItem == rootItem)
        return QModelIndex();

    return createIndex(parentItem->row(), 0, parentItem);
}


int ListsRegisterModel::rowCount(const QModelIndex &parent) const
{
    TreeItem *parentItem;
    if (parent.column() > 0)
        return 0;

    if (!parent.isValid())
        parentItem = rootItem;
    else
        parentItem = static_cast<TreeItem*>(parent.internalPointer());

    return parentItem->childCount();
}


int ListsRegisterModel::columnCount(const QModelIndex &parent) const
{
    if (parent.isValid())
        return static_cast<TreeItem*>(parent.internalPointer())->columnCount();
    else
        return rootItem->columnCount();
}


bool ListsRegisterModel::setData(const QModelIndex &index, const QVariant &value, int role)
{
    if (role != Qt::CheckStateRole)
        return false;

    TreeItem *item = getItem(index);

    Qt::CheckState state
            = (value.toInt() == Qt::Checked) ? Qt::Checked : Qt::Unchecked;
    item->setCheckState(state);

    emit dataChanged(index, index);

    return true;
}

 , model-view,

h0x0d9
()

QTabWidget и динамически изменяющаяся страница

Здравствуйте. В классе AbstractManagerTab используется QTabWidget для отображения в его вкладках страниц IpTrafficPage и SpecTrafficPage — специализаций базового AbstractTrafficPage. Специализации базового класса AbstractManagerTab — StoredRecsTab — должны добавлять командные кнопки в AbstractTrafficPage на все страницы внутреннего QTabWidget.

Представленный подход не позволяет этого добиться, т.к. один и тот же объект QWidget не может одновременно отображаться в нескольких местах. Надеюсь, что посоветуете или наведете на правильную мысль.

class AbstractTrafficPage : public QWidget
{
    Q_OBJECT
public:
    explicit AbstractTrafficPage(QWidget *parent = 0);
    void addCommandButton(QWidget *btn);
private:
    QVBoxLayout *commBtnsLayout;
};

AbstractTrafficPage::AbstractTrafficPage(QWidget *parent) :
    QWidget(parent),
    commBtnsLayout(new QVBoxLayout)
{
    QVBoxLayout *mainLayout = new QVBoxLayout;
    mainLayout->addLayout(commBtnsLayout);
    mainLayout->addStretch();

    setLayout(mainLayout);
}

void AbstractTrafficPage::addCommandButton(QWidget *btn)
{
    commBtnsLayout->addWidget(btn);
}

class IpTrafficPage : public AbstractTrafficPage
{
    Q_OBJECT
public:
    explicit IpTrafficPage(QWidget *parent = 0) : AbstractTrafficPage(parent) {};
};

class SpecTrafficPage : public AbstractTrafficPage
{
    Q_OBJECT
public:
    explicit SpecTrafficPage(QWidget *parent = 0) : AbstractTrafficPage(parent) {};
};

class AbstractManagerTab : public QWidget {
public:
    AbstractManagerTab(QWidget *parent);
    ~AbstractManagerTab();
    void addCommandButton(QWidget *btn);
private:
    QTabWidget *hTab;
}

AbstractManagerTab::AbstractManagerTab(QWidget *parent) :
QWidget(parent),
hTab(new QTabWidget)
{
    IpTrafficPage *ipPage = new IpTrafficPage(this);
    hTab->addTab(ipPage, tr("IP);
    SpecTrafficPage *specPage = new SpecTrafficPage(this);
    hTab->addTab(specPage, tr("Spec"));

    QVBoxLayout *mainLayout = new QVBoxLayout;
    mainLayout->addWidget(hTab);
    setLayout(mainLayout);
}

AbstractManagerTab::~AbstractManagerTab()
{
    delete hTab;
}

AbstractManagerTab::addCommandButton(QWidget *btn) 
{
    for (int index = 0; index < hTab->count(); ++index) {
        AbstractTrafficPage *page = dynamic_cast<AbstractTrafficPage *>
                (hTab->widget(index));
        if (page)
            page->addCommandButton(btn);
    }
}

class StoredRecsTab : public AbstractManagerTab
{
    Q_OBJECT
public:
    explicit StoredRecsTab(QWidget *parent = 0);
};

StoredRecsTab::StoredRecsTab(QWidget *parent) :
    AbstractManagerTab(parent)
{
    QPushButton *createRecBtn = new QPushButton(tr("Create"), this);
    QPushButton *removeRecBtn = new QPushButton(tr("Remove"), this);

    addCommandButton(createRecBtn);
    addCommandButton(removeRecBtn);
}

 ,

h0x0d9
()

koi8-r-исходник > utf8-консоль

Предисловие.

Есть поделие, которое мне надо сопровождать и дорабатывать, писавшееся в koi8-r кодировке. Есть четырнадцатая слака с настроенной юникод-локалью, есть QtCreator в ней. Qt Creator поставил не позже, чем вчера, сижу второй день, разбираюсь.

Играюсь.

Создаю простой проект _без_использования_qt_. Выставляю файлам проекта кодировку KOI-8R. Проект делает только две следующие строчки:

setlocale(LC_ALL, "ru_RU.koi8r");
cout << "тест";
Если в консоли xterm, запускаемой из IDE, выводятся крякозябры, то во внутренней консоли криэйтера — вообще ничего.

Подскажите, пожалуйста, как настроить.

 , , ,

h0x0d9
()

RSS подписка на новые темы