Russian Qt Forum
Ноябрь 23, 2024, 14:50 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

Войти
 
  Начало   Форум  WIKI (Вики)FAQ Помощь Поиск Войти Регистрация  

Страниц: 1 2 3 [4] 5 6   Вниз
  Печать  
Автор Тема: Система сбора и отображения данных  (Прочитано 40129 раз)
Bepec
Гость
« Ответ #45 : Март 11, 2014, 23:32 »

Вот так функции побеждают ООП Веселый
Записан
8Observer8
Гость
« Ответ #46 : Март 12, 2014, 14:24 »

Вот так функции побеждают ООП Веселый

Мне нужно было разобраться с такими техническими вопросами, как:
1) Обмен данными между Server'ом и Viewer'ом
2) Хранение данных

С первым вопросом вчера разобрался, а сегодня - со вторым. Решил хранить данные в базе данных SQLite, в виде: название датчика, значение, дата-врамя.

Кому интересно, вот видео, как работать с SQLite из Qt: http://www.youtube.com/watch?v=cc06D3wuTn4

Я добился того, чтобы Server сохранял текущие значения датчиков в базу данных (а так же дату-время). Теперь надо разобраться с SQL. А именно, как получить данные за период по столбцу дата-врамя. Как сделаю, то оформлю проект в виде ООП.

Отправлено: Март 11, 2014, 17:17

Написал пошаговую инструкцию, как работать с базой данных SQLite в Qt: http://www.prog.org.ru/topic_26665_0.html

Сделал вот такой GUI интерфейс, но пока не реализовал передачу данных из диапазона по времени съёма параметров:



« Последнее редактирование: Март 15, 2014, 08:06 от 8Observer8 » Записан
8Observer8
Гость
« Ответ #47 : Март 15, 2014, 08:24 »

Я уточнил ТЗ. Теперь сохраняю данные в базе данных SQLite.

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

Я заметил, что  у меня GUI клиента фризится (то есть замирает, притормаживает). Скорее всего это происходит в моменты записи в базу данных.

Вариант с базой данный считаю оправданным, так как в этом случае легко организовать доступ к данным и обработку их. К примеру, легко получить данные за период времени, так как в базу данных я сохраняю и время в формате: миллисекунды с начала эпохи (со времени рождения ОС Unix, то есть с 1970 года)



Почему ТЗ требует, чтобы получение данных с датчиков было отдельным тредом или процессом? Если это отдельный процесс, то получается, что это отдельное приложение, то есть Клиент и приложение датчика может быть на другой машине в сети. Правильно ли я понимаю?
Записан
Old
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 4350



Просмотр профиля
« Ответ #48 : Март 15, 2014, 08:37 »

Почему ТЗ требует, чтобы получение данных с датчиков было отдельным тредом или процессом?
Что бы этот прием шел параллельно с мониторингом данных. В случае с отдельным процессом - это еще и надежней, т.к. падение процесса получения данных не повлияет на процесс мониторинга и мы сможем отслеживать падения процессов и быстро их перезапускать.
И неплохое разделение функций получается: процесс приема просто складывает данные в БД - он знает и умеет получать данные, знает источники/протоколы и т.д., а процесс мониторинга берет данные исключительно из БД и ему не важно откуда и как эти данные получаются.

Если это отдельный процесс, то получается, что это отдельное приложение, то есть Клиент и приложение датчика может быть на другой машине в сети.
Тут зависит как эти два процесса будут взаимодействовать друг с другом.
Записан
Old
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 4350



Просмотр профиля
« Ответ #49 : Март 15, 2014, 08:47 »

Я заметил, что  у меня GUI клиента фризится (то есть замирает, притормаживает). Скорее всего это происходит в моменты записи в базу данных.
Да как бы не очень понятно с чего ему притормаживать. Отключите сохранение данных в БД и проверьте, пройдут ли фризы.
Записан
8Observer8
Гость
« Ответ #50 : Март 15, 2014, 09:27 »

Да как бы не очень понятно с чего ему притормаживать.

Я понял - это не фризы. У меня есть два текстовых поля LineEdit. В одном из них выводится время самого первого съёма, в другом - последнего. В моём приложении эти значения обновляются каждую секунду. Когда я пытаюсь выделить, к примеру, дату и время первого съёма, чтобы скопипастить, то выделение пропадает из-за обновления.

Но всё же, при наборе в полях: Требуемый диапазон - быстро набирать не получается. Есть небольшое притормаживание. Можете у себя просто запустить и попробовать набрать текст в поле "Введите начало диапазона". Только базу данных нужно расположить по этому пути:
Код
C++ (Qt)
QString path = QDir::currentPath()+QString("/database.sqlite");

Файл с базой данных можно найти в папке с исходниками Viewer'а.

Исходники:
https://github.com/8Observer8/IcebreakerServer/tree/dataFromRange
https://github.com/8Observer8/IcebreakerViewer/tree/dataFromRange

« Последнее редактирование: Март 15, 2014, 09:41 от 8Observer8 » Записан
8Observer8
Гость
« Ответ #51 : Март 23, 2014, 10:04 »

Помогите, пожалуйста, разобраться с таким вопросом. Хочу чтобы у каждого датчика был свой уникальный идентификатор. Поэтому я написал: static int mID; но компилятор ругается на эту строку:
Цитировать
Sensor.cpp:10: error: undefined reference to `Sensor::mID'

Sensor.h
Код
C++ (Qt)
#ifndef SENSOR_H
#define SENSOR_H
 
#include <QString>
 
class Sensor
{
public:
   Sensor(const QString &sensorName, const QString &portName);
 
   QString sensorName() const {
       return mSensorName;
   }
 
   QString portName() const {
       return mPortName;
   }
 
   int value() const;
 
   int id() const {
       return mID;
   }
 
private:
   QString mSensorName;
   QString mPortName;
   static int mID;
};
 
#endif // SENSOR_H
 

Sensor.cpp
Код
C++ (Qt)
#include "Sensor.h"
 
#include <QTime>
 
Sensor::Sensor(const QString &sensorName, const QString &portName) :
   mSensorName(sensorName),
   mPortName(portName)
{
   qsrand(QTime(0,0,0).secsTo(QTime::currentTime()));
   mID++;
}
 
int Sensor::value () const
{
   return qrand() % 10 + (mID * 10);
}
 
Записан
Old
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 4350



Просмотр профиля
« Ответ #52 : Март 23, 2014, 10:15 »

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

Для статических переменных нужно определить в cpp файле:
Код
C++ (Qt)
int Sensor::mID = 0;
 
Записан
8Observer8
Гость
« Ответ #53 : Март 23, 2014, 10:18 »

Огромное спасибо Улыбающийся

Посмотрите, пожалуйста, мой план-описание проекта. Всё ли здесь я правильно описал:

- пользователь запускает программу "Сервер Данных"

"Драйвер Датчика"
- пользователь запускает программу "Драйвер Датчика" (на том же, что и "Сервер Данных" или удалённом компьютере)
- добавляет датчики в таблицу, нажимая в меню "Добавить". В открывшимся диалоге указывает: имя датчика, номер COM-порта. В меню есть так же пункты: "Редактировать", "Удалить" запись из таблицы.
- вводит IP адрес (или имя компьютера) и порт "Сервера Данных"
- нажимает кнопку "Подсоединиться к серверу"
- пользователь может наблюдать текущие значения каждого датчика в приложении "Драйвер Датчика" в таблице

"Сервер Данных"
- после того, как пользователь нажал кнопку "Подсоединиться к серверу" в приложении "Драйвер Датчика", то "Сервер Данных" начинает принимать данные
- "Сервер Данных" сохраняет данные от датчиков в базу данных в таком виде: имя датчика, значение датчика, дата и время съёма

"Приложение Оператора"
- пользователь запускает "Приложение Оператора"
- вводит IP адрес (или имя компьютера) и порт сервера
- нажимает кнопку "Подсоединиться к серверу"
- "Приложение Оператора" начинает отправлять запросы приложению "Сервер Данных" каждую секунду
- в ответ приложение "Сервер Данных" присылает текущие значения датчиков
- "Приложение Оператора" отображает текущие значения датчиков
- пользователь вводит требуемый временной диапазон (дата-время) и получает от приложения "Сервер Данных" значения датчиков за указанный период
- пользователь так же может узнать значение указанного датчика в указанный момент времени, а так же значения указанного датчика в указанный период времени

Дополнительная функциональность. Пользователь может наблюдать текущие значения датчиков на графике в "Приложении Оператора" (графики рисуются в реальном времени)
Записан
Old
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 4350



Просмотр профиля
« Ответ #54 : Март 23, 2014, 10:19 »

Статический будет сам счетчик:

Sensor.h
Код
C++ (Qt)
#ifndef SENSOR_H
#define SENSOR_H
 
#include <QString>
 
class Sensor
{
public:
   Sensor(const QString &sensorName, const QString &portName);
 
   QString sensorName() const {
       return mSensorName;
   }
 
   QString portName() const {
       return mPortName;
   }
 
   int value() const;
 
   int id() const {
       return mID;
   }
 
private:
   QString mSensorName;
   QString mPortName;
   int        mID;
 
   static int mSeq;
};
 
#endif // SENSOR_H
 

Sensor.cpp
Код
C++ (Qt)
#include "Sensor.h"
 
#include <QTime>
 
int Sensor::mSeq = 0;
 
Sensor::Sensor(const QString &sensorName, const QString &portName) :
   mSensorName(sensorName),
   mPortName(portName),
   mID( mSeq++ )
{
   qsrand(QTime(0,0,0).secsTo(QTime::currentTime()));
}
 
int Sensor::value () const
{
   return qrand() % 10 + (mID * 10);
}
 
Записан
8Observer8
Гость
« Ответ #55 : Март 23, 2014, 10:20 »

Да, это то, что я хотел Улыбающийся Спасибо Улыбающийся
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #56 : Март 23, 2014, 11:10 »

Код
C++ (Qt)
int Sensor::value () const
{
   return qrand() % 10 + (mID * 10);
}
 
Возвращаемое значение зависит от порядка опроса датчиков
Записан
Old
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 4350



Просмотр профиля
« Ответ #57 : Март 23, 2014, 11:11 »

Возвращаемое значение зависит от порядка опроса датчиков
Ну rand так устроен. Улыбающийся
Записан
Johnik
Крякер
****
Offline Offline

Сообщений: 339


Просмотр профиля
« Ответ #58 : Март 23, 2014, 11:24 »

Помогите, пожалуйста, разобраться с таким вопросом. Хочу чтобы у каждого датчика был свой уникальный идентификатор. Поэтому я написал: static int mID; но компилятор ругается

можно еще так:
Код
C++ (Qt)
class Foo {
public:
   static int generateId()
   {
       static int id = 0;
       return id++;
   }
}
 
Записан
8Observer8
Гость
« Ответ #59 : Март 24, 2014, 14:40 »

Спасибо с генератором Улыбающийся

Сейчас 3 часа бился с проблемой и вроде подошёл к источнику. У меня Server отравляет QString Viewer'у. В строке содержатся данные по датчикам в формате: название, значение. Вот так: sensor1,18;sensor2,22;sensor3,28. Так вот. Когда это одно значение (sensor1,18), то Viewer нормально принимает. Если два и более, то Viewer перестаёт принимать.

Вот так Server отправляет строку:
Код
C++ (Qt)
void IcebreakerServer::sendToViewer(QTcpSocket *socket, const QString &str)
{
   QByteArray  arrBlock;
   QDataStream out(&arrBlock, QIODevice::WriteOnly);
   out.setVersion(QDataStream::Qt_4_7);
 
   out << quint16(0) << str;
 
   out.device()->seek(0);
   out << quint16(arrBlock.size() - sizeof(quint16));
 
   socket->write(arrBlock);
}
 

А вот так Viewer принимает:
Код
C++ (Qt)
void MainWindow::readyRead()
{
   QTcpSocket* clientSocket = (QTcpSocket*)sender();
   QDataStream in(clientSocket);
   in.setVersion(QDataStream::Qt_4_7);
   for (;;) {
       if (!m_nextBlockSize) {
           if (clientSocket->bytesAvailable() < (int)sizeof(quint16)) {
               break;
           }
           in >> m_nextBlockSize;
       }
 
       if (clientSocket->bytesAvailable() < m_nextBlockSize) {
           break;
       }
 
       QString inputData;
       in >> inputData;
       QStringList sensorsList = inputData.split(';');
 
       qDebug() << inputData;
 
       if ((sensorsList.size() == 3) && (sensorsList[0] == QString("alailableRange"))) {
           QDateTime time;
           // Begin of Range
           time.setMSecsSinceEpoch(sensorsList[1].toULongLong());
           ui->beginPossibleLineEdit->setText(time.toString());
 
           // End of Range
           time.setMSecsSinceEpoch(sensorsList[2].toULongLong());
           ui->endPossibleLineEdit->setText(time.toString());
       } else {
           qDebug() << "to table";
           if (sensorsList.size() != mModel->rowCount()) {
               mRows = sensorsList.size();
               delete mModel;
               mModel = new QStandardItemModel(mRows, mColumns, this);
               setHeaderData();
               ui->currentTable->setModel(mModel);
           }
 
           for (int i = 0; i < sensorsList.size(); ++i) {
               QStringList list = sensorsList[i].split(',');
               if (list.size() == mModel->columnCount()) {
                   QModelIndex index;
                   // Set data to the table
                   for (int j = 0; j < list.size(); ++j) {
                       index = mModel->index(i, j);
                       mModel->setData(index, list[j]);
                   }
               }
           }
       }
       m_nextBlockSize = 0;
   }
}
 
Записан
Страниц: 1 2 3 [4] 5 6   Вверх
  Печать  
 
Перейти в:  


Страница сгенерирована за 0.533 секунд. Запросов: 22.