Projekt

Obecné

Profil

Stáhnout (62.9 KB) Statistiky
| Větev: | Tag: | Revize:
1
#include "mainwindow.h"
2
#include "curvedialog.h"
3
#include "infodialog.h"
4
#include "curvedataserver.h"
5
#include "selectpatientdlg.h"
6
#include "ui_mainwindow.h"
7
#include <QModbusTcpClient>
8
#include <QList>
9
#include <QVector3D>
10
#include <QVector>
11
#include <QTimer>
12
#include <QTime>
13
#include <QSettings>
14
#include <QFileDialog>
15
#include <QMessageBox>
16
#include <QSqlQueryModel>
17
#include <QScreen>
18

    
19
//prehravani naucene krivky
20
#define BIT_BPLAY           32772
21
//cviceni naucene kriky
22
#define BIT_BPLAY_ASSIST    32773
23

    
24
//povoleni tenzometru
25
#define BIT_BXYZ            32779
26
//uceni krivky
27
#define BIT_BTEACH          32780
28
//poloha klicku - je to discrete input
29
#define BIT_BKEY            32789
30
//bezpecnostni tlacitko
31
#define BIT_SAFETY_BTN      32785
32

    
33
//polohovaci motor
34
#define BIT_MOTOR_UP        32788
35
#define BIT_MOTOR_DOWN      32789
36

    
37
//reset pozice
38
#define BIT_RESET_POS       32769
39

    
40
#define BIT_WRITE_ENABLE    32868
41
#define BIT_DATA_TO_PLC     32869
42
#define BIT_DATA_TO_PC      32870
43
#define BIT_RDY             32871
44
#define BIT_PART_FINISHED   32873
45
#define BIT_MEASUREMENT_TO_PC 32874
46

    
47
//aktualni pozice
48
#define REG_X       32768
49
#define REG_Y       32769
50
#define REG_Z       32770
51
#define REG_A       32771
52

    
53
//pozice vektoru, kam se tlaci
54
#define REG_ACT_X   32772
55
#define REG_ACT_Y   32773
56
#define REG_ACT_Z   32774
57

    
58
//pozice vektoru, kam se ma tlacit
59
#define REG_DIR_X   32776
60
#define REG_DIR_Y   32777
61
#define REG_DIR_Z   32778
62

    
63
#define REG_LEN     32866
64
#define REG_INDEX   32867
65
#define REG_DATA    32868
66

    
67
#define REG_Q_1     32780
68
#define REG_Q_TOT   32781
69
#define REG_Q_PART  32782
70

    
71
//rychlost cviceni
72
#define REG_SPEED   32799
73

    
74
#define NO_STATE        0
75
#define SEND_CURVE      1
76
#define SEND_PREP_CURVE 2
77
#define SEND_WAIT_CURVE 3
78
#define SEND_LAST_CURVE 4
79
#define GET_CURVE       5
80
#define GET_WAIT_CURVE  6
81
#define GET_PART_CURVE  7
82
#define GET_NEXT_PART   8
83
#define GET_LAST_CURVE  9
84
#define GET_MEAS_START  10
85
#define GET_MEAS_WAIT   11
86
#define GET_MEAS_LEN    12
87
#define GET_MEAS_NEXT   13
88
#define GET_MEAS_LAST   14
89

    
90
//poloha aplikatoru v zakladnim stavu (tj. v reset pozici)
91
#define RES_X_POS       1000
92
#define RES_Y_POS       1000
93
#define RES_Z_POS       3000
94

    
95
MainWindow::MainWindow(QWidget *parent) :
96
    QMainWindow(parent),
97
    ui(new Ui::MainWindow),
98
    cdServer(new CurveDataServer)
99
{
100
    ui->setupUi(this);
101

    
102
    mbClient = new QModbusTcpClient(this);
103

    
104
    pendingRead = pendingWrite = lastPacket = initStep = bSpeedUpdated = false;
105
    calcCurvePoints[0] = calcCurvePoints[1] = staticSpherePos = spherePos = QVector3D(0,0,0);
106
    dirArrow = QVector3D(0,0,0);
107
    actualArrow = QVector3D(0,0,0);
108
    testSpherePos = QVector3D(0,0,0);
109
    overallQ = oneCycleQ = tempQ = 0;
110
    pId = indId = 0;
111
    pronSupVal = PRON_SUP_NOT;
112
    actSeries = 0;
113

    
114
    itemCount = cntr = 0;
115

    
116
    safetyBtnState = safetyBtnBlinkOn = keyAutoBtnBlinkOn = 0;
117

    
118
    receivedDataSize = 0;
119

    
120
    mbServerId = 1;
121

    
122
    pd = waitDlg = nullptr;
123

    
124
    checkTimer = new QTimer(this);
125
    procedureTimer = new QTimer(this);
126
    procedureTimeRemaining = 600;
127
    ui->procTimeDial->setValue(10);
128

    
129
    connect(mbClient, &QModbusClient::errorOccurred, this, &MainWindow::handleDeviceError);
130
    connect(mbClient, &QModbusClient::stateChanged, this, &MainWindow::onStateChanged);
131

    
132
    connect(ui->curveGenerateBtn, SIGNAL(clicked()), this, SLOT(curveGenerateClicked()));
133
    connect(ui->curvePlayBtn, SIGNAL(toggled(bool)), this, SLOT(curvePlayChanged(bool)));
134
    connect(ui->curveAssistPlayBtn, SIGNAL(toggled(bool)), this, SLOT(curveAssistChanged(bool)));
135
    connect(ui->curveTeachBtn, SIGNAL(toggled(bool)), this, SLOT(curveTeachChanged(bool)));
136
    connect(ui->curveStoreBtn, SIGNAL(clicked()), this, SLOT(curveStoreClicked()));
137
    connect(ui->curveLoadBtn, SIGNAL(clicked()), this, SLOT(curveLoadClicked()));
138
    connect(ui->measurementLoadBtn, SIGNAL(clicked()), this, SLOT(measurementLoadClicked()));
139
    connect(ui->resetPosBtn, SIGNAL(clicked()), this, SLOT(deviceResetClicked()));
140
    connect(ui->patientSelectBtn, SIGNAL(clicked()), this, SLOT(patientSelectClicked()));
141

    
142
    connect(ui->procTimeDial, SIGNAL(sliderMoved(int)), this, SLOT(timeDialMoved(int)));
143
    connect(ui->procTimeDial, SIGNAL(sliderReleased()), this, SLOT(timeDialReleased()));
144

    
145
    connect(ui->upDownSlider, SIGNAL(sliderMoved(int)), this, SLOT(upDownSliderMoved(int)));
146
    connect(ui->upDownSlider, SIGNAL(sliderReleased()), this, SLOT(movementSliderReleased()));
147

    
148
    connect(checkTimer, SIGNAL(timeout()), this, SLOT(mainCycle()));
149
    connect(procedureTimer, SIGNAL(timeout()), this, SLOT(updateAppTime()));
150

    
151

    
152
    currState = numPoints = 0;
153

    
154
    ui->connectionLabel->setStyleSheet("background-color: rgb(255,0,0)");
155
    ui->dbConnectionStatusLabel->setStyleSheet("background-color: rgb(255,0,0)");
156

    
157
    mbConnected = false;
158
    bTeachStatus = bWriteEnable = bProcedureRunning = bPartState = bKeyState = bPlay = 0;
159

    
160
    qualitySet = new QBarSet("Kvalita");
161
    qualityData = new QBarSeries();
162
    qualityData->append(qualitySet);
163

    
164
    QFont font;
165
    font.setPixelSize(18);
166

    
167
    chart = new QChart();
168
    chart->addSeries(qualityData);
169

    
170
    axisy = new QValueAxis();
171
    axisy->setRange(0.0, 100.0);
172
    axisy->setLabelsFont(font);
173

    
174
    //chart->createDefaultAxes(); // Preparing the axis
175
    chart->setAxisY(axisy, qualityData);
176
    //chart->axisX()->setRange(0,1);
177
    //chart->axisX()->setLabelsFont(font);
178
    //chart->axisY()->setLabelsFont(font);
179
    //chart->axisY()->setRange(0,100);
180
    chart->setTitle(tr("Graf kvality cvičení"));
181

    
182
    // Same formatting
183
    chart->setTitleFont(font);
184
    chart->setBackgroundVisible(false);
185
    chart->setMargins(QMargins(0,0,0,0));
186
    //chart->layout()->setContentsMargins(0,0,0,0);
187
    chart->legend()->hide();
188
    chart->setPlotAreaBackgroundBrush(QBrush(Qt::black));
189
    chart->setPlotAreaBackgroundVisible(true);
190
    graphView = new QChartView(chart);
191
    graphView->setMinimumSize(250,120);
192

    
193
    ui->verticalLayout->addWidget(graphView);
194
    ui->splitter->setStretchFactor(0,0);
195
    ui->splitter->setStretchFactor(1,1);
196

    
197
    QString stFname = qApp->applicationDirPath() + "/settings.ini";
198
    QSettings st(stFname, QSettings::IniFormat);
199
    serverIp = st.value("serverIP","127.0.0.1:1502").toString();
200
    actCurveType = st.value("curveType", CURVE_NONE).toInt();
201
    actCurveFileName = st.value("curveFileName","").toString();
202
    minDistanceFromTarget = st.value("minDistance", 400).toInt();
203
    ui->splitter->restoreState(st.value("splitterSizes").toByteArray());
204
    int cStep = st.value("curveStep", 1).toInt();
205
    //ui->glwidget->setConfig(cStep);
206
    calculatedCurve.clear();
207

    
208
    //inicializace databaze
209
    useDb = st.value("useDb", 0).toInt();
210
    auto dbAddr = st.value("dbAddress", "localhost").toString();
211
    auto dbUser = st.value("dbUser", "postgres").toString();
212
    auto dbPassword = st.value("dbPassword", "").toString();
213
    auto dbPort = st.value("dbPort", 5432).toInt();
214
    auto dbName = st.value("dbName","Cviceni").toString();
215

    
216
    db = new dbAccess();
217
    model = new QSqlQueryModel;
218

    
219
    if (useDb) {
220
        dbConnected = db->connect(dbAddr, dbUser, dbPassword, dbPort, dbName);
221
        if (dbConnected) {
222
            QLOG_INFO() << tr("OK< db connection established");
223
            ui->dbConnectionStatusLabel->setStyleSheet("background-color: rgb(0,255,0)");
224
            ui->dbConnectionStatusLabel->setText(tr("DB připojena"));
225
        }
226
    }
227

    
228
    //knofliky pro cviceni jsou pro zacatek disablovany
229
    ui->resetPosBtn->setEnabled(false);
230
    ui->curvePlayBtn->setEnabled(false);
231
    ui->curveAssistPlayBtn->setEnabled(false);
232
    ui->curveGenerateBtn->setEnabled(false);
233
    //ui->curveGenerateBtn->setEnabled(true);
234
    ui->curveTeachBtn->setEnabled(false);
235
    ui->curveLoadBtn->setEnabled(false);
236
    ui->curveStoreBtn->setEnabled(false);
237

    
238
    QScreen *screen = QGuiApplication::primaryScreen();
239
    QRect  screenGeometry = screen->geometry();
240
    this->setFixedSize(screenGeometry.width(),screenGeometry.height());
241
    //this->setFixedSize(1366,768);
242

    
243
    QTimer::singleShot(100, this, SLOT(display3DScene())); //kvuli nakresleni zakladni sceny
244

    
245
    connectionGuard = new QTime;
246
    connectionGuard->start();
247
    connectionEstablished = false;
248
    connectClicked();
249
        QLOG_DEBUG() << "Get part";
250
#ifdef PROCEDURE_TEST
251
    sphere.append(readPoints("kruh.txt"));
252
    act.append(readPoints("act.txt"));
253
    dir.append(readPoints("dir.txt"));
254
    cur.clear();
255
#endif
256
}
257

    
258
MainWindow::~MainWindow()
259
{
260
    QString stFname = qApp->applicationDirPath() + "/settings.ini";
261
    QSettings st(stFname, QSettings::IniFormat);
262
    st.setValue("splitterSizes",ui->splitter->saveState());
263
    st.setValue("curveType", actCurveType);
264
    st.setValue("curveFileName",actCurveFileName);
265

    
266
    if (mbConnected) {
267
        mbClient->disconnectDevice();
268
    }
269
    delete db;
270
    delete ui;
271
    delete cdServer;
272
}
273

    
274
//! Připojit/Odpojit modbus server
275
/*!
276
 * Funkce připojí, nebo odpojí modbus zařízení
277
 */
278
void MainWindow::connectClicked()
279
{
280
    const QUrl url = QUrl::fromUserInput(serverIp);
281

    
282
#ifdef PROCEDURE_TEST
283
        checkTimer->start(100);
284
        //ui->glwidget->procedureState(true);
285
        ui->curvePlayBtn->setEnabled(true);
286
        ui->curveAssistPlayBtn->setEnabled(true);
287
        ui->curveGenerateBtn->setEnabled(true);
288
        ui->curveTeachBtn->setEnabled(true);
289
        ui->curveLoadBtn->setEnabled(true);
290
        ui->curveStoreBtn->setEnabled(true);
291
        ui->safetyBtnLabel->setStyleSheet("background-color: rgb(0,255,0)");
292
        ui->connectionLabel->setStyleSheet("background-color: rgb(0,255,0)");
293
        ui->connectionLabel->setText(tr("Připojeno"));
294

    
295
        return;
296
#endif
297

    
298
    if (!mbConnected) {
299
        mbClient->setConnectionParameter(QModbusDevice::NetworkPortParameter, url.port());
300
        mbClient->setConnectionParameter(QModbusDevice::NetworkAddressParameter, url.host());
301
        mbClient->setTimeout(500);
302
        mbClient->setNumberOfRetries(3);
303
        if (!mbClient->connectDevice()) {
304
            QLOG_ERROR() << "Err connecting";
305
        }
306
        connectionGuard->start();
307
        checkTimer->start(500);
308
    } else {
309
        mbClient->disconnectDevice();
310
    }
311
}
312

    
313
//! Funkce volána po ukončení učení křivky
314
/*!
315
 * Funkce je volána poté, co je dokončeno učení nové křivky. Začne se stahování
316
 *  křivky do PC
317
 */
318
void MainWindow::changeClicked()
319
{
320
#ifndef FILE_TEST
321
    file.setFileName("data.txt");
322
    if (file.open(QIODevice::WriteOnly | QIODevice::Text)) {
323
         store.setDevice(&file);
324

    
325
         //QLOG_WARN() << "e";
326
         store << "x;y;z;r" << endl;
327
    }
328

    
329
    currState = GET_CURVE;
330
    calculatedCurve.clear();
331
#else
332
    QString line;
333
    QStringList list;
334
    int i = 0;
335
    qint16 x,y,z,a;
336
    file.setFileName("data.txt");
337
    calculatedCurve.clear();
338
    if (file.open(QIODevice::ReadOnly | QIODevice::Text)) {
339
         store.setDevice(&file);
340

    
341
         //QLOG_WARN() << "e";
342

    
343
         while(!store.atEnd()) {
344
             line = store.readLine();
345
             list = line.split(';');
346
             x = list.at(0).toShort();
347
             y = list.at(1).toShort();
348
             z = list.at(2).toShort();
349
             a = list.at(3).toShort();
350
             calculatedCurve.append(QVector3D(x,y,z,a));
351
         }
352
         file.close();
353
    }
354
    ui->glwidget->setCurve(calculatedCurve);
355
#endif
356
}
357

    
358
//! Výběr předpočítané křivky
359
/*!
360
 * Po stisknutí tlačítka na výběr křivky. Zavolá se odpovídající dialog a po
361
 *  úspěšném výběru parametrů křivky se tato předpočte a pošle do stroje
362
 */
363
void MainWindow::curveGenerateClicked()
364
{
365
    curveDialog dlg;
366

    
367
    if (dlg.exec() == QDialog::Accepted) {
368
        dlg.getCurve(&actCurveType, &actCurveAngle, &actCurveRot, &pronSupVal);
369
        ui->glwidget->setTubusColor(QVector4D(1, 0.737f, 0.231f, 0.7f));
370
        setCurveData();
371
#ifdef PROCEDURE_TEST
372
        itemCount = cntr = 0;
373
#endif
374
    }
375
 }
376

    
377
//! Připravení dat křivky
378
/*!
379
 * Připraví křivku, která pak bude poslána do stroje. Křika bude buďto předpočítaná na
380
 *  základě vybraných parametrů, anebo bude načtena ze souboru na disku.
381
 */
382
void MainWindow::setCurveData()
383
{
384
    int stepcount = 250,i, tmpI;
385
    double x, x1, y, y1, z, a, tmpdeg;
386

    
387
#ifdef FILE_TEST
388
    file.setFileName("data.txt");
389
    if (file.open(QIODevice::WriteOnly | QIODevice::Text)) {
390
         store.setDevice(&file);
391
    }
392
#endif
393

    
394
    if (actCurveType == CURVE_EXTERN) {
395
        if (!getCurveDataFromFile(actCurveFileName)) {
396
            QMessageBox::critical(this, tr("Cvičební stroj"),
397
                             tr("<font size=15>Nepodařilo se importovat křivku ze souboru.\nVyberte jiný soubor, nebo vygenerujte jinou křivku.</font>"),
398
                             QMessageBox::Ok);
399

    
400
            return;
401
        }
402
    } else {
403
        calculatedCurve.clear();
404

    
405
        //kdyz nebude pouzita zadna krivka - vymazat starou krivku
406
        if (actCurveType == CURVE_NONE)
407
            display3DScene();
408

    
409
        for (i=0; i < stepcount+1; i++) {
410
            if (actCurveRot == ROTATE_CLKWISE)
411
                tmpI = stepcount - i;
412
            else
413
                tmpI = i;
414
            tmpdeg = tmpI * (360.0/stepcount) * M_PI / 180.0;
415

    
416
            switch(actCurveType) {
417
            case CURVE_CIRCLE:
418
                x = 1600 * cos(tmpdeg);
419
                y = 1600 * sin(tmpdeg);
420
                break;
421
            case CURVE_ELLIPSE:
422
                x = 1200 * cos(tmpdeg);
423
                y = 1600 * sin(tmpdeg);
424
                break;
425
            case CURVE_LEMN:
426
                x = sqrt(2)*(1400)*cos(tmpdeg)/(1+sin(tmpdeg)*sin(tmpdeg));
427
                y = sqrt(2)*(3650)*sin(tmpdeg)*cos(tmpdeg)/(1+sin(tmpdeg)*sin(tmpdeg));
428
                break;
429
            case CURVE_KARD:
430
                x = (750)*2*cos(tmpdeg)-(750)*cos(2*tmpdeg);
431
                y = (750)*2*sin(tmpdeg)-(750)*sin(2*tmpdeg);
432
                break;
433
            case CURVE_LINE:
434
                if (i < stepcount/2)
435
                    tmpI = i * 2;
436
                else
437
                    tmpI = (stepcount - i) * 2;
438

    
439
                if (actCurveRot != ROTATE_CLKWISE)
440
                    tmpI = (stepcount - tmpI);
441

    
442
                //x = -2200 + tmpI * 4400.0 / stepcount;
443
                x = -2200 + tmpI * 4400.0 / stepcount;
444
                y = 0;// -2200 + tmpI * 4400.0 / stepcount;
445
                break;
446
            default:
447
                x = RES_X_POS;
448
                y = RES_Y_POS;
449
                z = RES_Z_POS;
450
            }
451

    
452
            x1 = x*cos(actCurveAngle*M_PI/4)-y*sin(actCurveAngle*M_PI/4);
453
            y1 = x*sin(actCurveAngle*M_PI/4)+y*cos(actCurveAngle*M_PI/4);
454

    
455
            if (actCurveType != CURVE_NONE)
456
                z = 6500.0 - y1*0.9;
457

    
458
            tmpdeg = 2 * M_PI * i / (double)stepcount;   //to same jako horni tmpdeg, jen s i
459
            switch(pronSupVal) {
460
            case PRON_SUP_1:
461
                a = sin(tmpdeg) * 15 + 45;
462
                break;
463
            case PRON_SUP_2:
464
                a = sin(tmpdeg) * 45 + 45;
465
                break;
466
            default:
467
                a = 0.0;
468
            }
469

    
470
            if (i == stepcount/2)
471
                calcCurvePoints[0] = QVector3D(x1,y1,z);
472
            else if (i == stepcount)
473
                calcCurvePoints[1] = QVector3D(x1,y1,z);
474

    
475
            calculatedCurve.append(QVector4D(x1,y1,z,a*10));
476
#ifdef FILE_TEST
477
            if (file.isOpen()) {
478
                store << (qint16)x1 << ";" << (qint16)y1 << ";" << (qint16)(7500.0+y/2.5) << ";" << (qint16)a << endl;
479
            }
480
#endif
481
        }
482
#ifdef FILE_TEST
483
        if (file.isOpen())
484
            file.close();
485
#endif
486
        ui->glwidget->setTubusColor(QVector4D(1, 0.737f, 0.231f, 0.7f));
487
        if (actCurveType != CURVE_NONE)
488
            ui->glwidget->setCurve(calculatedCurve);
489
        currState = SEND_CURVE;
490
    }
491
}
492

    
493
//! Učení křivky
494
/*!
495
 * V závislosti na vstupním parametru je zahájeno, nebo ukončeno učení křivky. Pokud je učení zahájeno, je nejprve zobrazen
496
 *  dialog s informací o tom, že je třeba počkat, než bude aplikátor v základní pozici. Pak je možno začít manuálně
497
 * projíždět křivku, která bude zaznamenána strojem.
498
 * Pokud je učení ukončeno, je do stroje poslán příkaz o ukončení učení
499
 * \param pressed Parametr, který obsahuje informaci o tom, jestli má být učení zahájeno, nebo ukončeno
500
 */
501
void MainWindow::curveTeachChanged(bool pressed)
502
{
503
    if (pressed) {
504
        deviceResetClicked();
505
        display3DScene();
506

    
507
        waitDlg = new QProgressDialog("<font size=15>Počkejte, než bude stroj v základní pozici</font>", "Zrušit", 0, 50);
508
        waitDlg->setModal(true);
509
        waitDlg->setValue(0);
510
        waitDlg->show();
511
        ui->curveTeachBtn->setStyleSheet("background-color: rgb(0, 85, 255)");
512
    } else {
513
        if (waitDlg != nullptr) {
514
            delete waitDlg;
515
            waitDlg = nullptr;
516
        }
517

    
518
        writeValue(BIT_BTEACH, QModbusDataUnit::Coils,0);
519
        writeValue(BIT_BXYZ, QModbusDataUnit::Coils,0);
520
        ui->curveTeachBtn->setStyleSheet("background-color: rgb(0, 222, 222)");
521
    }
522
}
523

    
524
//! Výběr uložené křivky
525
/*!
526
 * Po stisknutí tlačítka na načtení křivky z disku se objeví dialog pro výběr souboru. Pak
527
 * je křivka vyčtena z daného souboru.
528
 */
529
void MainWindow::curveLoadClicked()
530
{
531
    QString fileName = QFileDialog::getOpenFileName(this,
532
         tr("Načíst křivku"), "", tr("Souboru s křivkou (*.txt);;Vše (*.*)"));
533

    
534
    getCurveDataFromFile(fileName);
535
}
536

    
537
void MainWindow::measurementLoadClicked()
538
{
539
    openMeasurementFile();
540
    writeValue(BIT_MEASUREMENT_TO_PC, QModbusDataUnit::Coils, 1);
541
    currState = GET_MEAS_START;
542
}
543

    
544
QVector4D MainWindow::getDeltaMovingAverage(QVector4D point)
545
{
546
    tmpCurveMA.push_back(point);
547
    if (tmpCurveMA.size() > 10)
548
        tmpCurveMA.pop_front();
549
    qint32 sumx = 0, sumy = 0, sumz = 0;
550
    for (auto val: tmpCurveMA) {   //std::list<float>::iterator p = listDeltaMA.begin(); p != listDeltaMA.end(); ++p)
551
        sumx += val.x();
552
        sumy += val.y();
553
        sumz += val.z();
554
    }
555
    return QVector4D(sumx/tmpCurveMA.size(), sumy/tmpCurveMA.size(), sumz/tmpCurveMA.size(), point.w());
556
}
557

    
558
void MainWindow::openMeasurementFile()
559
{
560
    file.setFileName(QString("%1.csv").arg(QDateTime::currentDateTime().toString("yyyyMMdd-hhmmss")));
561
    if (file.open(QIODevice::WriteOnly | QIODevice::Text)) {
562
         store.setDevice(&file);
563

    
564
         store << "cas;x1;y1;z1;x2;y2;z2;x3;y3;z3" << endl;
565
    }
566
}
567

    
568
//!  Načtení uložené křivky ze souboru
569
int MainWindow::getCurveDataFromFile(QString fileName)
570
{
571
    int nRet = 0;
572
    QFile file(fileName);
573

    
574
    if (file.open(QIODevice::ReadOnly | QIODevice::Text)) {
575
        calculatedCurve.clear();
576

    
577
        QTextStream storeFile(&file);
578
        QVector4D point;
579
        QVector3D pointPrev;
580
        QStringList list;
581
        QString line;
582

    
583
        tmpCurveMA.clear();
584

    
585
        while(!storeFile.atEnd()) {
586
            line = storeFile.readLine();
587
            list = line.split(';');
588
            if (list.size() < 4)
589
                continue;
590
            point.setX(list.at(0).toShort());
591
            point.setY(list.at(1).toShort());
592
            point.setZ(list.at(2).toShort());
593
            point.setW(list.at(3).toShort());
594
            if (calculatedCurve.size() > 1) {
595
                pointPrev = calculatedCurve.last().toVector3D();
596
                if (pointPrev.distanceToPoint(point.toVector3D()) > 500.0)
597
                    calculatedCurve.append(getDeltaMovingAverage(point));
598
            } else
599
                calculatedCurve.append(getDeltaMovingAverage(point));
600
            /*pos++;
601
            if ((pos % 4) == 0)
602
                calculatedCurve.append(getDeltaMovingAverage(point));*/
603
        }
604
        if (calculatedCurve.size() > 2) {
605
            for (int i = 0; i<10; i++)
606
                calculatedCurve.append(getDeltaMovingAverage(calculatedCurve.first()));
607
        }
608

    
609
        file.close();
610
        if (calculatedCurve.size() > 0) {
611
            ui->glwidget->setTubusColor(QVector4D(1, 0.737f, 0.231f, 0.7f));
612
            ui->glwidget->setCurve(calculatedCurve);
613
        }
614
        actCurveFileName = fileName;
615
        actCurveType = CURVE_EXTERN;
616
        currState = SEND_CURVE;
617
        nRet = 1;
618
    }
619
    return nRet;
620
}
621

    
622
//! Uložení aktuální křivky
623
/*!
624
 * Po stisknutí tlačítka "Uložení křivky" se objeví dialog pro výběr souboru. Pak
625
 * je aktuální křivka uložena do daného souboru.
626
 */
627
void MainWindow::curveStoreClicked()
628
{
629
    if (calculatedCurve.size() > 0) {
630
        QString fileName = QFileDialog::getSaveFileName(this,
631
            tr("Uložit křivku"), "", tr("Souboru s křivkou (*.txt)"));
632

    
633
        QFile file(fileName);
634
        if (file.open(QIODevice::WriteOnly | QIODevice::Text)) {
635
            QTextStream storeFile(&file);
636

    
637
            for(auto &point: calculatedCurve) { //C++ 11 use
638
                storeFile << static_cast<qint16>(point.x()) << ";" << static_cast<qint16>(point.y())
639
                          << ";" << static_cast<qint16>(point.z()) << ";" << static_cast<qint16>(point.w()) << endl;
640
            }
641
            file.close();
642
        }
643

    
644
    } else {
645
        QMessageBox::warning(this, tr("Cvičební stroj"),
646
                             tr("<font size=15>V aplikaci není stažená žádná křivka\n</font>"),
647
                             QMessageBox::Ok);
648
    }
649
}
650

    
651
//! Přesun aktuatoru do defaultní pozice
652
void MainWindow::deviceResetClicked()
653
{
654
    writeValue(BIT_RESET_POS, QModbusDataUnit::Coils, 1);
655
}
656

    
657
//! Výběr pacienta
658
/*!
659
 * Po stisknutí tlačítka "Výběr pacienta" se objeví dialog pro výběr pacienta, který bude provádět procedury.
660
 * Konkrétní křivka a její provedení odpovídající proceduře je získána z databáze.
661
 */
662
void MainWindow::patientSelectClicked()
663
{
664
    if (!useDb) {
665
        infoDialog dlg;
666
        dlg.setInfoText(tr("Výběr pacienta/indikace"),tr("DB není použita, data nemohou být vybrána"));
667
        dlg.exec();
668
    } else {
669
        if (dbConnected) {
670
            selectPatientDlg dlg(db);
671
            QString cName;
672
            QStringList curveDataStr;
673
            dlg.exec();
674
            if (dlg.result() == QDialog::Accepted) {
675
                QString name, surname;
676
                dlg.getPatientInfo(&pId, &indId, &name, &surname, &actSeries, &procedureTimeRemaining, &cName);
677

    
678
                if (!cName.isEmpty()) {
679
                    curveDataStr = cName.split("_");
680
                    if (curveDataStr.size() == 4) {
681
                        actCurveType = curveDataStr.at(0).toInt();
682
                        actCurveAngle = curveDataStr.at(1).toInt();
683
                        actCurveRot = curveDataStr.at(2).toInt();
684
                        pronSupVal = curveDataStr.at(3).toInt();
685
                        ui->glwidget->setTubusColor(QVector4D(1, 0.737f, 0.231f, 0.7f));
686
                        setCurveData();
687
                    }
688
                }
689

    
690
                ui->patientNameLabel->setText(tr("Jméno: ") + name + " " + surname);
691
                ui->indicationLabel->setText(tr("Série: ") + QString::number(actSeries));
692
                ui->curveAssistPlayBtn->setText(tr("Spustit cvičení\n") + QString::number(procedureTimeRemaining/60)
693
                                                + ":" + QString("%1").arg(procedureTimeRemaining%60,2,10,QChar('0')) + "min");
694
                ui->procTimeDial->setValue(procedureTimeRemaining/60);
695
            }
696
        } else {
697
            infoDialog dlg;
698
            dlg.setInfoText(tr("Výběr pacienta/indikace"),tr("DB není připojena, data nemohou být vybrána"));
699
            dlg.exec();
700
        }
701
    }
702
}
703

    
704
//! Předvedení křivky strojem
705
/*!
706
 * Po stisknutí tlačítka "Provedení křivky" stroj začne opisovat křivku (bez asistence pacienta), která byla naposledy
707
 * do stroje poslána. Tento příkaz slouží k otestování, jak bude cvičení vypadat. Po dalším stisknutí tlačítka se
708
 * provádění křivky ukončí.
709
 * \param pressed Parametr, který obsahuje informaci o tom, jestli má být předvádění zahájeno, nebo ukončeno
710
 */
711
void MainWindow::curvePlayChanged(bool pressed)
712
{
713
    if (pressed)
714
        writeValue(BIT_BPLAY, QModbusDataUnit::Coils,1);
715
    else
716
        writeValue(BIT_BPLAY, QModbusDataUnit::Coils,0);
717
}
718

    
719
//! Start/stop procedury
720
/*!
721
 * Po stisknutí tlačítka "Spustit cvičení" stroj začne provádět cvičení (s asistencí pacienta) procedury. Provádí se
722
 * po křivce, která byla naposledy do stroje poslána. Procedura se zastaví buď po uplynutí nastaveného času a nebo po
723
 * dalším stisknutí téhož tlačítka, které bude po startu cvičení přejmenováno na "Ukončit cvičení"
724
 * \param pressed Parametr, který obsahuje informaci o tom, jestli má být procedura zahájena, nebo ukončena
725
 */
726
void MainWindow::curveAssistChanged(bool pressed)
727
{
728
#ifdef PROCEDURE_TEST
729
    if (pressed) {
730
        procedureTimer->start(1000);
731
        ui->curveAssistPlayBtn->setStyleSheet("background-color: rgb(255, 170, 0);");
732
    }
733
    else {
734
        procedureTimer->stop();
735

    
736
        procedureTimeRemaining = ui->procTimeDial->value()*60;
737
        ui->curveAssistPlayBtn->setText(tr("Spustit cvičení\n") + QString::number(procedureTimeRemaining/60)
738
                                        + ":" + QString("%1").arg(procedureTimeRemaining%60,2,10,QChar('0')) + "min");
739

    
740
        ui->curveAssistPlayBtn->setStyleSheet("background-color: rgb(0, 255, 0);");
741

    
742
        infoDialog dlg;
743
        dlg.setInfoText(tr("Cvičení"),tr("Cvičení je dokončeno"));
744
        dlg.exec();
745
    }
746
#else
747
    if (!bKeyState)
748
        return;
749

    
750
    if (pressed) {
751
        writeValue(BIT_BPLAY_ASSIST, QModbusDataUnit::Coils,1);
752
        ui->curveAssistPlayBtn->setStyleSheet("background-color: rgb(255, 170, 0);");
753
    } else {
754
        writeValue(BIT_BPLAY_ASSIST, QModbusDataUnit::Coils,0);
755
        ui->curveAssistPlayBtn->setStyleSheet("background-color: rgb(0, 255, 0);");
756
    }
757
#endif
758
}
759

    
760
//! Posun aktuátoru nahoru/dolu
761
/*!
762
 * Když je posuvník potažen směrem nahoru, stroj jede s aktuátorem nahoru. Dtto pro směr dolu
763
 * \param val Parametr, podle kterého se pozná, zda má stroj jet nahoru, nebo dolu
764
 */
765
void MainWindow::upDownSliderMoved(int val)
766
{
767
    QVector<quint16> vals;
768

    
769
    if (val > 50) { //motor nahoru
770
        vals.append(1);  //up
771
        vals.append(0);  //down
772
    } else if (val == 50) {  // motor zastavit
773
        vals.append(0);  //up
774
        vals.append(0);  //down
775
    } else { //motor dolu
776
        vals.append(0);  //up
777
        vals.append(1);  //down
778
    }
779
    writeValues(BIT_MOTOR_UP, QModbusDataUnit::Coils, vals);
780
}
781

    
782
//! Posun aktuátoru zastavit
783
/*!
784
 * Když je posuvník uvolněn, stroj zastaví pohyb nahoru/dolu.
785
 */
786
void MainWindow::movementSliderReleased()
787
{  //motor zastavit
788
    ui->upDownSlider->setValue(50);
789
    writeValue(BIT_MOTOR_UP, QModbusDataUnit::Coils,0);
790
    writeValue(BIT_MOTOR_DOWN, QModbusDataUnit::Coils,0);
791
}
792

    
793
//! Hlavní cyklus
794
/*!
795
 * Funkce je volána periodicky každých 100ms, když je modbus/tcp aktivní. Je zde řešena periodická kontrola spojení se strojem.
796
 * Pokud je modbus/tcp spojení ukončeno, zkusí se znovu připojit. V každém volání funkce se vytváří pořadavky na čtení dat ze stroje.
797
 * Dále se mění parametry stavového stroje na základě přijatých dat
798
 */
799
void MainWindow::mainCycle()
800
{
801
    if (connectionEstablished) {
802
        if (connectionGuard->elapsed() > 1000) {
803
            QLOG_ERROR() << tr("Od stroje nepřišla odpověď více, než 1 sekundu");
804
            connectionGuard->restart();
805
        }
806
    } else {
807
        if (connectionGuard->elapsed() > 20000) {
808
            QLOG_ERROR() << tr("Pokouším se znovu připojit");
809
            if (mbConnected) {
810
                mbClient->disconnectDevice();
811
                mbConnected = false;
812
            }
813
            connectClicked();
814
            connectionGuard->restart();
815
        }
816
    }
817

    
818
    if (waitDlg != nullptr) {
819
        int val = waitDlg->value();
820
        waitDlg->setValue(val+1);
821
#ifdef PROCEDURE_TEST
822
        itemCount = 0;
823
#endif
824
        if ((val > 48)|| (waitDlg->wasCanceled())) {
825
            delete waitDlg;
826
            waitDlg = nullptr;
827
            //stroj by mel byt v zakladni pozici
828

    
829
            infoDialog dlg;
830
            dlg.setInfoText("Učení", "Stroj je v základní pozici, stisknutím OK můžete začít učit pohyb\nPřipojte prosím pacienta ke stroji.");
831
            dlg.exec();
832

    
833
            writeValue(BIT_BTEACH, QModbusDataUnit::Coils,1);
834
            writeValue(BIT_BXYZ, QModbusDataUnit::Coils,1);
835
        }
836
    }
837

    
838
#if !defined(FILE_TEST) && !defined(PROCEDURE_TEST)
839
    if (!mbConnected)
840
        return;
841

    
842
    switch(currState) {
843
    case NO_STATE:
844
        if (!pendingRead) {
845
            //precteme vsechny vektory najednou - REG, REG_ACT,REG_DIR i REG_Q
846
            readValues(REG_X, QModbusDataUnit::HoldingRegisters, 15);
847
            //readValue(REG_SPEED, QModbusDataUnit::HoldingRegisters);
848
            readValue(BIT_WRITE_ENABLE, QModbusDataUnit::Coils);
849
            readValue(BIT_BTEACH, QModbusDataUnit::Coils);
850
            readValue(BIT_BPLAY_ASSIST, QModbusDataUnit::Coils);
851
            readValue(BIT_BPLAY, QModbusDataUnit::Coils);
852
            readValue(BIT_BKEY, QModbusDataUnit::DiscreteInputs);
853
            readValue(BIT_PART_FINISHED, QModbusDataUnit::Coils);
854
            readValue(BIT_SAFETY_BTN, QModbusDataUnit::DiscreteInputs);
855
            readValue(BIT_MEASUREMENT_TO_PC, QModbusDataUnit::Coils);
856
            pendingRead = true;
857
            if (!bProcedureRunning) {
858
                ui->glwidget->setSphereData(spherePos, QVector3D(0,0,0), QVector3D(0,0,0));
859
                ui->glwidget->setTestSphereData(spherePos);
860
            } else {
861
                ui->glwidget->setSphereData(spherePos,dirArrow*2,actualArrow*2); //pokusne prodlouzeni sipek - aby byly lepe videt
862
                if ((actCurveType == CURVE_CIRCLE) || (actCurveType == CURVE_ELLIPSE)
863
                        || (actCurveType == CURVE_KARD) || (actCurveType == CURVE_LEMN)
864
                        || (actCurveType == CURVE_LINE)) {
865
                    ui->glwidget->setTestSphereData(staticSpherePos);
866
                    if (staticSpherePos.distanceToPoint(spherePos) < minDistanceFromTarget) {
867
                        if (staticSpherePos == calcCurvePoints[0])
868
                            staticSpherePos = calcCurvePoints[1];
869
                        else
870
                            staticSpherePos = calcCurvePoints[0];
871
                    }
872
                } else {
873
                    ui->glwidget->setTestSphereData(spherePos);
874
                }
875
            }
876
            if (bTeachStatus) {
877
                ui->glwidget->addSphereData(spherePos, false, false);
878
                ui->glwidget->setTestSphereData(spherePos);
879
            }
880
        }
881
        break;
882
    case SEND_CURVE:
883
        curvePacket = 0;
884
        lastPacket = false;
885
        currState = SEND_PREP_CURVE;
886
        writeValue(BIT_DATA_TO_PLC, QModbusDataUnit::Coils,1);
887
        pd = new QProgressDialog("<font size=15>Křivka se odesílá do stroje</font>", "Zrušit", 0, calculatedCurve.size()/25+1);
888
        pd->setModal(true);
889
        pd->setValue(0);
890
        pd->show();
891
        break;
892
    case SEND_PREP_CURVE:
893
        int len;
894
        len = prepareCurveData(curvePacket);
895
        if (len < 25)
896
            lastPacket = true;
897

    
898
        currState = SEND_WAIT_CURVE;
899
        writeValue(BIT_RDY, QModbusDataUnit::Coils, 1);  //rdy
900
        QLOG_DEBUG() << "send packet";
901
        curvePacket++;
902
        break;
903
    case SEND_WAIT_CURVE:
904
        readValue(BIT_RDY, QModbusDataUnit::Coils);
905
        break;
906
    case SEND_LAST_CURVE:
907
        writeValue(BIT_DATA_TO_PLC, QModbusDataUnit::Coils,0);
908
        currState = NO_STATE;
909
        if (pd != nullptr) {
910
            delete pd;
911
            pd = nullptr;
912
        }
913
        break;
914
    case GET_CURVE:
915
        writeValue(BIT_DATA_TO_PC, QModbusDataUnit::Coils, 1); //ziskat krivku z PC
916
        curvePacket = 0;
917
        currState = GET_WAIT_CURVE;
918
        pd = new QProgressDialog("<font size=15>Křivka se čte ze stroje</font>", "Zrušit", 0, 100);
919
        pd->setModal(true);
920
        pd->setValue(0);
921
        pd->show();
922
        QLOG_DEBUG() << "Get new curve";
923
        receivedDataSize = 0;
924
        break;
925
    case GET_WAIT_CURVE:
926
        readValue(BIT_RDY, QModbusDataUnit::Coils);
927
        break;
928
    case GET_PART_CURVE:
929
        if (initStep) {
930
            readValues(REG_LEN, QModbusDataUnit::HoldingRegisters, 2);  //INDEX and LEN
931
            initStep = false;
932
        }
933
        break;
934
    case GET_NEXT_PART:
935
        QLOG_DEBUG() << "Get next part";
936
        currState = NO_STATE;
937
        break;
938
    case GET_MEAS_START:
939
        curvePacket = 0;
940
        receivedDataSize = 0;
941
        currState = GET_MEAS_WAIT;
942
        pd = new QProgressDialog("<font size=15>Měření se čte ze stroje</font>", "Zrušit", 0, 100);
943
        pd->setModal(true);
944
        pd->setValue(0);
945
        pd->show();
946
        QLOG_DEBUG() << "Get new measurement";
947
        break;
948
    case GET_MEAS_WAIT:
949
        readValue(BIT_RDY, QModbusDataUnit::Coils);
950
        break;
951
    case GET_MEAS_LEN:
952
        if (initStep) {
953
            readValues(REG_LEN, QModbusDataUnit::HoldingRegisters, 2);  //INDEX and LEN
954
            initStep = false;
955
        }
956
        break;
957
    case GET_MEAS_NEXT:
958
        QLOG_DEBUG() << "Get next part";
959
        currState = NO_STATE;
960
        break;
961
    default:
962
        ;
963
    }
964
#endif
965

    
966
    if (pd != nullptr) {
967
        if (pd->wasCanceled()) {
968
            QLOG_DEBUG() << "cancel dlg pressed";
969
            if (currState == SEND_WAIT_CURVE)
970
                currState = SEND_LAST_CURVE;
971
            else {
972
                if (file.isOpen()) {
973
                    file.close();
974
                }
975
                if (pd != nullptr) {
976
                    delete pd;
977
                    pd = nullptr;
978
                }
979
                writeValue(BIT_DATA_TO_PLC, QModbusDataUnit::Coils,0); //ukoncit krivku z PLC
980
                writeValue(BIT_DATA_TO_PC, QModbusDataUnit::Coils, 0); //ukoncit krivku z PC
981
                writeValue(BIT_MEASUREMENT_TO_PC, QModbusDataUnit::Coils, 0);
982
                currState = NO_STATE;
983
            }
984

    
985
        }
986
    }
987

    
988
    if ((safetyBtnState == 0)||(bKeyState == 0)) {  //neni stisknuto bezp. tlacitko, nebo nein nahozen klicek auto
989
        blinkCntr++;
990
        if (blinkCntr > 10) {
991
            if (safetyBtnState == 0) {
992
                if (safetyBtnBlinkOn)
993
                    ui->safetyBtnLabel->setStyleSheet("background-color: rgb(255,0,0)");
994
                else
995
                    ui->safetyBtnLabel->setStyleSheet("");
996
                safetyBtnBlinkOn = !safetyBtnBlinkOn;
997
            }
998
            if (bKeyState == 0) {
999
                if (keyAutoBtnBlinkOn)
1000
                    ui->autoKeyStatusLabel->setStyleSheet("background-color: #ffa500");  //oranzova
1001
                else
1002
                    ui->autoKeyStatusLabel->setStyleSheet("");
1003
                keyAutoBtnBlinkOn = !keyAutoBtnBlinkOn;
1004
            }
1005
            blinkCntr = 0;
1006
        }
1007
    }
1008
#ifdef GRAPH_TEST
1009
    cntr++;
1010
    if (cntr > 100) {
1011
        double r = ((double) rand() / (RAND_MAX))*100;
1012
        cntr = 0;
1013
        qualitySet->append(r);
1014
        chart->removeSeries(qualityData);
1015
        chart->addSeries(qualityData);
1016
        chart->setAxisY(axisy, qualityData);
1017

    
1018
        QLOG_DEBUG() << QString("Data %1, %2").arg(itemCount).arg(r);
1019
        itemCount++;
1020
    }
1021
#endif
1022

    
1023
#ifdef PROCEDURE_TEST
1024
    cntr++;
1025
    if (cntr > 1) {
1026
        QVector4D vec, vec1, vec2;
1027
        bool start = false, finish = false;
1028
        cntr = 0;
1029
        if (!calculatedCurve.isEmpty())
1030
            vec = calculatedCurve.at(itemCount);
1031
        else
1032
            vec = QVector4D(0,0,0,0);
1033

    
1034

    
1035
        //vec = sphere.at(itemCount);
1036
        cur.append(vec);
1037
        vec1 = dir.at(itemCount);
1038
        vec2 = act.at(itemCount);
1039
        vec1 = vec2 = QVector4D(0,0,0,0);
1040

    
1041
        if (itemCount == 0) {
1042
            start = true;
1043
        }
1044
        //itemCount += 10;
1045
        itemCount ++;
1046
        //if (itemCount > sphere.size()-1) {
1047
        if (itemCount > calculatedCurve.size()-1) {
1048
            itemCount = 0;
1049
            cur.clear();
1050
            finish = true;
1051
        }
1052

    
1053
        //ui->glwidget->setTubusColor(QVector4D(0, 0.87f, 0.87f, 1));
1054
        //ui->glwidget->addSphereData(vec, start, finish);
1055

    
1056
        /*if (itemCount > calculatedCurve.size()-1)
1057
            itemCount = 0;*/
1058
        /*if (!cur.isEmpty() && (cur.size() > 5)) {
1059
            const QList<QVector3D> *data;
1060
            data = &cur;
1061
            ui->glwidget->setCurve(*data);
1062
        }*/
1063
        //ui->glwidget->setSphereData(vec.toVector3D(), vec1.toVector3D(), vec2.toVector3D());
1064
        vec1 = QVector4D((float)rand()/(RAND_MAX)*2-1.0,(float)rand()/(RAND_MAX)*2-1.0,(float)rand()/(RAND_MAX)*2-1.0,0);
1065
        ui->glwidget->setSphereData(vec.toVector3D(),
1066
                                    QVector3D::crossProduct(vec.toVector3D()/5, vec1.toVector3D()),
1067
                                    QVector3D::crossProduct(vec.toVector3D()/5, QVector3D(0,1,0)));
1068
                                    /*QVector3D::crossProduct(vec.toVector3D()/5, QVector3D(-1,0,0)),
1069
                                    QVector3D::crossProduct(vec.toVector3D()/5, QVector3D(0,1,0)));*/
1070
        //ui->glwidget->setSphereData(vec, QVector3D(1000,-1000,0), QVector3D(-1200,1200,500));
1071
        connectionGuard->restart();
1072
    }
1073
#endif
1074
    cdServer->sendActuatorPosition(spherePos.x(), spherePos.y(), spherePos.z());
1075
}
1076

    
1077
//! Příjem dat ze stroje
1078
/*!
1079
 * Funkce je volána, jakmile přijdou jakákoliv data ze stroje po modbus/tcp. Data se zpracují a jsou připravena
1080
 * pro provádění akce v hlavním cyklu
1081
 */
1082
void MainWindow::readyRead()
1083
{
1084
    QModbusReply *readRequest = qobject_cast<QModbusReply *>(sender());
1085
    if (!readRequest)
1086
        return;
1087

    
1088
    if (readRequest->error() == QModbusDevice::NoError) {
1089
        const QModbusDataUnit unit = readRequest->result();
1090
        int value, address = unit.startAddress();
1091
        connectionGuard->restart();
1092

    
1093
        switch(unit.registerType()) {
1094
        case QModbusDataUnit::Coils:
1095
            for (uint i = 0; i < unit.valueCount(); i++) {
1096
                value = unit.value(i);
1097
                int addr = address+i;
1098
                /*if ((address+i) == BIT_DATA_TO_PLC) {
1099
                    if (value != 0) {
1100
                        if (currState != SEND_LAST_CURVE)
1101
                            currState = SEND_CURVE;
1102
                    } else {
1103
                        currState = NO_STATE;
1104
                        lastPacket = false;
1105
                    }
1106
                } else*/
1107
                switch(addr) {
1108
                case BIT_RDY:
1109
                {
1110
                    if ((currState == SEND_WAIT_CURVE) && (value == 0)) {
1111
                        if (lastPacket) {
1112
                            QLOG_DEBUG() << "Last packet sent";
1113
                            currState = SEND_LAST_CURVE;
1114
                        } else {
1115
                            QLOG_DEBUG() << "Send new data";
1116
                            currState = SEND_PREP_CURVE;
1117
                        }
1118
                        if (pd != nullptr) {
1119
                            pd->setValue(curvePacket);
1120
                        }
1121
                    } else if ((currState == GET_WAIT_CURVE) && (value == 1)) {
1122
                        initStep = true;
1123
                        currState = GET_PART_CURVE;
1124
                    } else if ((currState == GET_MEAS_WAIT) && (value == 1)) {
1125
                        initStep = true;
1126
                        currState = GET_MEAS_LEN;
1127
                    }
1128
                    break;
1129
                }
1130
                case BIT_WRITE_ENABLE:
1131
                {
1132
                    if (bWriteEnable != value) {
1133
                        /*if (value == 0)
1134
                            ui->curveBtn->setEnabled(false);
1135
                        else
1136
                            ui->curveBtn->setEnabled(true);*/
1137
                        bWriteEnable = value;
1138
                        QLOG_DEBUG() << "bWriteEnableChanged";
1139
                    }
1140
                    break;
1141
                }
1142
                case BIT_BTEACH:
1143
                {
1144
                    if (bTeachStatus != value) {
1145
                        if (value == 0) {
1146
                            changeClicked();//stahnout krivku
1147
                            actCurveType = CURVE_NONE; //neni vybrana zadna predpocitana krivka
1148
                            if (ui->curveTeachBtn->isChecked())
1149
                                ui->curveTeachBtn->toggle();
1150
                            ui->glwidget->addSphereData(spherePos, false, true);
1151
                        } else {
1152
                            if (!ui->curveTeachBtn->isChecked())
1153
                                ui->curveTeachBtn->toggle();
1154
                            ui->glwidget->setTubusColor(QVector4D(0, 0.87f, 0.87f, 0.7f));
1155
                            ui->glwidget->addSphereData(spherePos, true, false);
1156
                        }
1157
                        QLOG_DEBUG() << "bTeach changed";
1158
                        bTeachStatus = value;
1159
                    }
1160
                    break;
1161
                }
1162
                case BIT_BPLAY:
1163
                {
1164
                    if (bPlay != value) {
1165
                        if (value == 0) {
1166
                            if (ui->curvePlayBtn->isChecked())
1167
                                ui->curvePlayBtn->toggle();
1168
                        } else {
1169
                            if (!ui->curvePlayBtn->isChecked())
1170
                                ui->curvePlayBtn->toggle();
1171
                        }
1172
                        QLOG_DEBUG() << "bPlay changed";
1173
                        bPlay = value;
1174
                    }
1175
                    break;
1176
                }
1177
                case BIT_BPLAY_ASSIST:
1178
                {
1179
                    if (bProcedureRunning != value) {
1180
                        QLOG_DEBUG() << QString("bPlayAssist changed, val %1").arg(value);
1181
                        bProcedureRunning = value;
1182
                        //ui->glwidget->procedureState(value);
1183
                        if (value != 0) {
1184
                            overallQ = oneCycleQ = tempQ = 0;
1185
                            itemCount = 0;
1186
                            qualitySet->remove(0,qualitySet->count());
1187
                            ui->overallQualityEdit->setText("0");
1188
                            ui->oneCycleQualityEdit->setText("0");
1189
                            ui->actQualityEdit->setText("0");
1190
                            if (!ui->curveAssistPlayBtn->isChecked())
1191
                                ui->curveAssistPlayBtn->toggle();
1192
                            procedureQuality.clear();
1193
                            procedureTimer->start(1000);
1194
                            if (actCurveType != CURVE_NONE) {
1195
                                staticSpherePos = calcCurvePoints[0];
1196
                            }
1197
                        } else {
1198
                            ui->overallQualityEdit->setText(QString("%1").arg(overallQ));  //konec cviceni, zobrazit celkovy vysledek
1199
                            if (ui->curveAssistPlayBtn->isChecked())
1200
                                ui->curveAssistPlayBtn->toggle();
1201
                            procedureTimer->stop();
1202
                            if (dbConnected)
1203
                                db->addResult(pId, indId, actSeries, procedureQuality);
1204

    
1205
                            procedureTimeRemaining = ui->procTimeDial->value()*60;
1206
                            ui->curveAssistPlayBtn->setText(tr("Spustit cvičení\n") + QString::number(procedureTimeRemaining/60)
1207
                                                + ":" + QString("%1").arg(procedureTimeRemaining%60,2,10,QChar('0')) + "min");
1208
                        }
1209
                    }
1210
                    break;
1211
                }
1212
                case BIT_PART_FINISHED:
1213
                {
1214
                    if (bPartState != value) {
1215
                        if (value != 0) {
1216
                            QLOG_DEBUG() << "part finished";
1217
                            ui->oneCycleQualityEdit->setText(QString("%1").arg(oneCycleQ));
1218
                            writeValue(BIT_PART_FINISHED, QModbusDataUnit::Coils, 0); //vynulovat priznak konce jednoho cyklu
1219
                            if (oneCycleQ > 0)
1220
                                procedureQuality.append(oneCycleQ);
1221
                            qualitySet->append(oneCycleQ);
1222
                            chart->removeSeries(qualityData);
1223
                            chart->addSeries(qualityData);
1224
                            chart->setAxisY(axisy, qualityData);
1225
                            itemCount++;
1226
                        }
1227
                        bPartState = value;
1228
                    }
1229
                    break;
1230
                }
1231
                case BIT_MEASUREMENT_TO_PC:
1232
                {
1233
                    if (value && (currState < GET_MEAS_START)) {
1234
                        currState = GET_MEAS_START;
1235
                        openMeasurementFile();
1236
                    }
1237
                    if (!value && (currState > GET_MEAS_START )) {
1238
                        if (file.isOpen()) {
1239
                            file.close();
1240
                        }
1241
                        if (pd != nullptr) {
1242
                            delete pd;
1243
                            pd = nullptr;
1244
                        }
1245
                    }
1246
                    break;
1247
                }
1248
                default:
1249
                    ;
1250
                }
1251
            }
1252
            break;
1253
        case QModbusDataUnit::HoldingRegisters:
1254
            if ((unit.startAddress() == REG_X)&&(unit.valueCount() == 15)) {
1255
                spherePos = QVector3D((qint16)unit.value(0)/1.0,(qint16)unit.value(1)/1.0,(qint16)unit.value(2)/1.0);
1256
                //QLOG_DEBUG() << QString("sphere %1,%2,%3").arg((qint16)unit.value(0)/1.0).arg((qint16)unit.value(1)/1.0).arg((qint16)unit.value(2)/1.0);
1257
                //a = unit.value(3);
1258
                //REG_ACT_X
1259
                dirArrow = QVector3D((qint16)unit.value(4)/1.0,(qint16)unit.value(5)/1.0,(qint16)unit.value(6)/1.0);
1260
                //QLOG_DEBUG() << QString("dir %1,%2,%3").arg((qint16)unit.value(4)/1.0).arg((qint16)unit.value(5)/1.0).arg((qint16)unit.value(6)/1.0);
1261
                //REG_DIR_X
1262
                actualArrow = QVector3D((qint16)unit.value(8)*4.0,(qint16)unit.value(9)*4.0,(qint16)unit.value(10)*4.0);
1263
                //QLOG_DEBUG() << QString("act %1,%2,%3").arg((qint16)unit.value(8)/1.0).arg((qint16)unit.value(9)/1.0).arg((qint16)unit.value(10)/1.0);
1264
                //REG_Q
1265
                overallQ = unit.value(13);
1266
                value = unit.value(12);
1267
                /*if ((value != 0)&&(oneCycleQ != 0)) {
1268
                    QLOG_DEBUG() << "cycle finished - quality " << value;
1269
                    ui->oneCycleQualityEdit->setText(QString("%1").arg(value));
1270
                    procedureQuality.append(value);
1271
                    //end of cycle
1272
                }*/
1273
                oneCycleQ = value;
1274
                tempQ = unit.value(14);
1275
                ui->overallQualityEdit->setText(QString("%1").arg(overallQ));
1276
                ui->actQualityEdit->setText(QString("%1").arg(tempQ));
1277
            }
1278

    
1279
            if (unit.startAddress() == REG_DATA) {
1280
                QLOG_DEBUG() << QString("Mam %1 dat a %2 uz jich je stazeno").arg(unit.valueCount()/4).arg(calculatedCurve.size());
1281
                getCurveData(currState, nIndex, unit.values());
1282
                writeValue(BIT_RDY, QModbusDataUnit::Coils, 0); //ziskat krivku z PC
1283
                if (pd != nullptr)
1284
                    pd->setValue(receivedDataSize);
1285

    
1286
                /*if ((numPoints - nIndex) > 0) {
1287
                    if (currState == GET_PART_CURVE) {
1288
                        currState = GET_WAIT_CURVE;
1289
                        pd->setValue(calculatedCurve.size());
1290
                    }
1291
                    else {
1292
                        currState = GET_MEAS_WAIT;
1293
                        pd->setValue(numPoints - nIndex);
1294
                    }
1295
                    QLOG_DEBUG() << "Dalsi cast";
1296
                }*/
1297

    
1298
                if (receivedDataSize < numPoints) {
1299
                    if (currState == GET_PART_CURVE)
1300
                        currState = GET_WAIT_CURVE;
1301
                    else
1302
                        currState = GET_MEAS_WAIT;
1303
                    QLOG_DEBUG() << "Dalsi cast";
1304
                }
1305
                else {
1306
                    QLOG_DEBUG() << "OK mam krivku";
1307
                    currState = NO_STATE;
1308
                    if (currState == GET_PART_CURVE) {
1309
                        writeValue(BIT_DATA_TO_PC, QModbusDataUnit::Coils, 0); //ziskat krivku z PC
1310
                        ui->glwidget->setTubusColor(QVector4D(1, 0.737f, 0.231f, 0.7f));
1311
                        if (calculatedCurve.size() > MAX_CURVE_SIZE) {
1312
                            infoDialog dlg;
1313
                            dlg.setInfoText(tr("Velikost křivky"), tr("Předcvičená křivka je příliš dlouhá.\nBude zkrácena."));
1314
                            dlg.exec();
1315
                        }
1316
                        if (calculatedCurve.size() > 0) {
1317
                            ui->glwidget->setCurve(calculatedCurve);
1318
                        } else {
1319
                            infoDialog dlg;
1320
                            dlg.setInfoText(tr("Velikost křivky"), tr("Naučená křivka nelze použít. Neplatná data."));
1321
                            dlg.exec();
1322
                            display3DScene();
1323
                        }
1324
                    } else {
1325
                        writeValue(BIT_MEASUREMENT_TO_PC, QModbusDataUnit::Coils, 0);
1326
                    }
1327
                    if (file.isOpen()) {
1328
                        file.close();
1329
                    }
1330
                    if (pd != nullptr) {
1331
                        delete pd;
1332
                        pd = nullptr;
1333
                    }
1334
                    //ui->changeDataBtn->setEnabled(false);   //ok mam vsechny data, cekam na dalsi nauceni stroje
1335
                }
1336
                initStep = true;
1337
            } else if (unit.startAddress() == REG_LEN) {
1338
                numPoints = unit.value(0);  //pocet bodu
1339
                nIndex  = unit.value(1);    //index
1340
                QLOG_DEBUG() << QString("Mam len  %1, index %2").arg(numPoints).arg(nIndex);
1341
                readValues(REG_DATA, QModbusDataUnit::HoldingRegisters, 100); //precti data
1342
                if (pd != nullptr)
1343
                    pd->setMaximum(numPoints);
1344
            } else if (unit.startAddress() == REG_SPEED) {
1345
            }
1346

    
1347
            /*for (uint i = 0; i < unit.valueCount(); i++) {
1348
                const QString entry = tr("Address: %1, Value: %2").arg(unit.startAddress() + i)
1349
                        .arg(QString::number(unit.value(i)));
1350
                ui->textEdit->append(entry);
1351
            }*/
1352
            break;
1353
        case QModbusDataUnit::DiscreteInputs:
1354
            value = unit.value(0);
1355
            if  (address == BIT_BKEY) {
1356
                if (bKeyState != value) {
1357
                    QLOG_DEBUG() << "BKEY DI changed val = " << value;
1358
                    if (value == 0) {
1359
                        ui->curveAssistPlayBtn->setEnabled(false);
1360
                    }
1361
                    else {
1362
                        ui->curveAssistPlayBtn->setEnabled(true);
1363
                        ui->autoKeyStatusLabel->setStyleSheet("background-color: #00ff00");
1364
                    }
1365
                    bKeyState = value;
1366
                }
1367
            } else if  (address  == BIT_SAFETY_BTN) {
1368
                safetyBtnState = value;
1369
                if (value == 1)
1370
                    ui->safetyBtnLabel->setStyleSheet("background-color: rgb(0,255,0)");
1371
            }
1372
            break;
1373
        default:
1374
            break;
1375

    
1376
        }
1377
    } else if (readRequest->error() == QModbusDevice::ProtocolError) {
1378
        QLOG_ERROR() << QString(tr("Read response error: %1 (Modbus exception: 0x%2)").
1379
                                 arg(readRequest->errorString()).
1380
                                 arg(readRequest->rawResult().exceptionCode(), -1, 16));
1381
    } else {
1382
        QLOG_ERROR() << QString(tr("Read response error: %1 (code: 0x%2)").
1383
                                 arg(readRequest->errorString()).
1384
                                 arg(readRequest->error(), -1, 16));
1385
    }
1386

    
1387
    readRequest->deleteLater();
1388

    
1389
    pendingRead = false;
1390
}
1391

    
1392
//! Potvrzení zápisu dat na Modbus/TCP
1393
void MainWindow::writeFinished()
1394
{
1395
    QModbusReply *writeRequest = qobject_cast<QModbusReply *>(sender());
1396
    if (!writeRequest)
1397
        return;
1398

    
1399
    if (writeRequest->error() == QModbusDevice::ProtocolError) {
1400
        QLOG_ERROR() << QString(tr("Write response error: %1 (Modbus exception: 0x%2)")
1401
                                 .arg(writeRequest->errorString()).arg(writeRequest->rawResult().exceptionCode(), -1, 16));
1402
    } else if (writeRequest->error() != QModbusDevice::NoError) {
1403
        QLOG_ERROR() << QString(tr("Write response error: %1 (code: 0x%2)").
1404
                                 arg(writeRequest->errorString()).arg(writeRequest->error(), -1, 16));
1405
    }
1406
    writeRequest->deleteLater();
1407
}
1408

    
1409
//! Změna stavu spojení s modbus/tcp serverem
1410
/*!
1411
 * Funkce se volá, pokud se změní stav spojení modbus/tcp. Vzhled aplikace se upraví na základě stavu spojení.
1412
 * \param state Stav spojení - Connected, nebo Unconnected
1413
 */
1414
void MainWindow::onStateChanged(int state)
1415
{
1416
    bool connected = (state != QModbusDevice::UnconnectedState);
1417

    
1418
    if (state == QModbusDevice::UnconnectedState) {
1419
        ui->connectionLabel->setText(tr("Odpojeno"));
1420
        ui->connectionLabel->setStyleSheet("background-color: rgb(255,0,0)");
1421
        ui->safetyBtnLabel->setStyleSheet("");
1422
        ui->autoKeyStatusLabel->setStyleSheet("");
1423
        mbConnected = false;
1424
        //checkTimer->stop();
1425
        checkTimer->setInterval(500);
1426

    
1427
        ui->resetPosBtn->setEnabled(false);
1428
        ui->curvePlayBtn->setEnabled(false);
1429
        ui->curveAssistPlayBtn->setEnabled(false);
1430
        ui->curveGenerateBtn->setEnabled(false);
1431
        ui->curveTeachBtn->setEnabled(false);
1432
        ui->curveLoadBtn->setEnabled(false);
1433
        ui->curveStoreBtn->setEnabled(false);
1434

    
1435
        connectClicked();
1436
    } else if (state == QModbusDevice::ConnectedState) {
1437
        mbConnected = true;
1438
        ui->connectionLabel->setText(tr("Připojeno"));
1439
        ui->connectionLabel->setStyleSheet("background-color: rgb(0,255,0)");
1440
        //checkTimer->start(100);
1441
        checkTimer->setInterval(100);
1442

    
1443
        bTeachStatus = bWriteEnable = bProcedureRunning = bPartState = bKeyState = bPlay = safetyBtnState = 0;
1444

    
1445
        ui->resetPosBtn->setEnabled(true);
1446
        ui->curvePlayBtn->setEnabled(true);
1447
        ui->curveGenerateBtn->setEnabled(true);
1448
        ui->curveTeachBtn->setEnabled(true);
1449
        ui->curveLoadBtn->setEnabled(true);
1450
        ui->curveStoreBtn->setEnabled(true);
1451

    
1452
        connectionGuard->restart();
1453
        connectionEstablished = true;
1454

    
1455
        //ziskat rovnou status tlacitek
1456
        readValue(BIT_BKEY, QModbusDataUnit::DiscreteInputs);
1457
        readValue(BIT_SAFETY_BTN, QModbusDataUnit::DiscreteInputs);
1458

    
1459
        setCurveData();  //nahrat do stroje rovnou krivku
1460
    }
1461
}
1462

    
1463
//! Ošetření chyby při komunikaci
1464
void MainWindow::handleDeviceError(QModbusDevice::Error newError)
1465
{
1466
    if (newError == QModbusDevice::NoError || !mbClient)
1467
        return;
1468

    
1469
    QLOG_ERROR() <<  mbClient->errorString();
1470
}
1471

    
1472
//! Vytvoření úvodní 3D "křivky", pokud není ještě křivka ze stroje k dispozici
1473
void MainWindow::display3DScene()
1474
{
1475
    calculatedCurve.clear();
1476
    calculatedCurve.append(QVector4D(0,0,-4900,0.0));
1477
    calculatedCurve.append(QVector4D(0,0,-4900,0.0));
1478
    calculatedCurve.append(QVector4D(0,0,-4900,0.0));
1479
    calculatedCurve.append(QVector4D(0,0,-4000,0.0));
1480
    ui->glwidget->setCurve(calculatedCurve);
1481
}
1482

    
1483
//! Aktualizace času při asistovaném cvičení pacienta
1484
void MainWindow::updateAppTime()
1485
{
1486
    if (procedureTimeRemaining > 0) {
1487
        procedureTimeRemaining--;
1488
        ui->curveAssistPlayBtn->setText(tr("Ukončit cvičení\n") + QString::number(procedureTimeRemaining/60)
1489
                                                + ":" + QString("%1").arg(procedureTimeRemaining%60,2,10,QChar('0')) + "min");
1490
        if (procedureTimeRemaining == 0) {
1491
            procedureTimer->stop();
1492
            ui->curveAssistPlayBtn->toggle();
1493
        }
1494
    }
1495
}
1496

    
1497
//! Úprava doby asistovaného cvičení
1498
void MainWindow::timeDialMoved(int time)
1499
{
1500
    QString txt = tr("Ukončit cvičení\n");
1501
    if (!bProcedureRunning) {
1502
        txt = tr("Spustit cvičení\n");
1503
    }
1504
    ui->curveAssistPlayBtn->setText(txt + QString::number(time) + ":00 min");
1505
}
1506

    
1507
//! Úprava doby asistovaného cvičení
1508
void MainWindow::timeDialReleased()
1509
{
1510
    QString txt = tr("Ukončit cvičení\n");
1511

    
1512
    if (!bProcedureRunning) {
1513
        txt = tr("Spustit cvičení\n");
1514
    }
1515
    procedureTimeRemaining = ui->procTimeDial->value()*60;
1516
    ui->curveAssistPlayBtn->setText(txt + QString::number(procedureTimeRemaining/60) + ":00 min");
1517
}
1518

    
1519
#ifdef PROCEDURE_TEST
1520
QList<QVector4D> MainWindow::readPoints(QString fName)
1521
{
1522
    QList<QVector4D> results;
1523
    double a = 0.0;
1524

    
1525
    QFile file(fName);
1526
    if (!file.open(QIODevice::ReadOnly | QIODevice::Text))
1527
    {
1528
        return results;
1529
    }
1530

    
1531
    while (!file.atEnd())
1532
    {
1533
        QByteArray line = file.readLine();
1534
        QList<QByteArray> splitted = line.split(';');
1535
        if (splitted.size() < 3)
1536
            continue;
1537
        if (splitted.size() == 4)
1538
            a = splitted.at(3).trimmed().toFloat();
1539
        QVector4D point(QString(splitted.at(0)).trimmed().toFloat(), QString(splitted.at(1)).trimmed().toFloat(), QString(splitted.at(2)).trimmed().toFloat(),a);
1540
        results.append(point);
1541
    }
1542
    return results;
1543
}
1544
#endif
1545

    
1546
//! Vytvoření modbus/tcp požadavku na čtení jedné hodnoty
1547
/*!
1548
 * \param addr Modbus adresa
1549
 * \param table Typ registru
1550
 */
1551
void MainWindow::readValue(int addr, QModbusDataUnit::RegisterType table)
1552
{
1553
    QModbusDataUnit unit(table, addr, 1);
1554
    if (QModbusReply *readRequest = mbClient->sendReadRequest(unit, mbServerId)) {
1555
        if (!readRequest->isFinished())
1556
            connect(readRequest, SIGNAL(finished()), this, SLOT(readyRead()));
1557
        else
1558
            delete readRequest; // broadcast replies return immediately
1559
    } else {
1560
        QLOG_ERROR() << QString("Read error: %1").arg(mbClient->errorString());
1561
    }
1562
}
1563

    
1564
//! Vytvoření modbus/tcp požadavku na čtení více hodnot
1565
/*!
1566
 * \param addr Modbus adresa
1567
 * \param table Typ registrů
1568
 * \param regCount Počet čtených registrů
1569
 */
1570
void MainWindow::readValues(int addr, QModbusDataUnit::RegisterType table, qint16 regCount)
1571
{
1572
    QModbusDataUnit unit(table, addr, regCount);
1573
    if (QModbusReply *readRequest = mbClient->sendReadRequest(unit, mbServerId)) {
1574
        if (!readRequest->isFinished())
1575
            connect(readRequest, SIGNAL(finished()), this, SLOT(readyRead()));
1576
        else
1577
            delete readRequest; // broadcast replies return immediately
1578
    } else {
1579
        QLOG_ERROR() << QString("Read error: %1").arg(mbClient->errorString());
1580
    }
1581
}
1582

    
1583
//! Vytvoření modbus/tcp požadavku na zápis jedné hodnoty
1584
/*!
1585
 * \param addr Modbus adresa
1586
 * \param table Typ registru
1587
 * \param value Zapisovaná hodnota
1588
 */
1589
void MainWindow::writeValue(int addr, QModbusDataUnit::RegisterType table, qint16 value)
1590
{
1591
    QModbusDataUnit unit(table, addr, 1);
1592
    unit.setValue(0, value);
1593

    
1594
    if (QModbusReply *reply = mbClient->sendWriteRequest(unit, mbServerId)) {
1595
        if (!reply->isFinished()) {
1596
            connect(reply, SIGNAL(finished()), this, SLOT(writeFinished()));
1597
        } else {
1598
            // broadcast replies return immediately
1599
            reply->deleteLater();
1600
        }
1601
    } else {
1602
        QLOG_ERROR() << QString("Write error: %1").arg(mbClient->errorString());
1603
    }
1604
}
1605

    
1606
//! Vytvoření modbus/tcp požadavku na zápis více hodnot
1607
/*!
1608
 * \param addr Modbus adresa
1609
 * \param table Typ registru
1610
 * \param vals Zapisované hodnoty
1611
 */
1612
void MainWindow::writeValues(int addr, QModbusDataUnit::RegisterType table, QVector<quint16> vals)
1613
{
1614
    QModbusDataUnit unit(table, addr, vals);
1615
    if (QModbusReply *reply = mbClient->sendWriteRequest(unit, mbServerId)) {
1616
        if (!reply->isFinished()) {
1617
            connect(reply, SIGNAL(finished()), this, SLOT(writeFinished()));
1618
        } else {
1619
            // broadcast replies return immediately
1620
            reply->deleteLater();
1621
        }
1622
    } else {
1623
        QLOG_ERROR() << QString("Write error: %1").arg(mbClient->errorString());
1624
    }
1625
}
1626

    
1627
//! Příprava bloku dat pro stroj
1628
/*!
1629
 * Připraví požadovaný blok dat s křivkou pro poslání do stroje
1630
 * \param packetNo Pořadové číslo bloku
1631
 * \return Počet poslaných dat
1632
 */
1633
int MainWindow::prepareCurveData(int packetNo)
1634
{
1635
    int nLen = 0;
1636
    QVector<quint16> vals;
1637

    
1638
    QLOG_DEBUG() << "prepare data";
1639
    QLOG_DEBUG() << QString("data count %1, packetNo %2").arg(calculatedCurve.size()).arg(packetNo);
1640

    
1641
    if (calculatedCurve.size() < packetNo*25)
1642
        return 0;
1643

    
1644
    if (calculatedCurve.size() > 0) {
1645
        nLen = (calculatedCurve.size() - packetNo*25);
1646
        if (nLen > 25)
1647
            nLen = 25;
1648
        QLOG_DEBUG() << QString("Send data size %1, packetNo %2").arg(nLen).arg(packetNo);
1649
        for(int i = 0; i < nLen; i++) {
1650
            vals.append((qint16)(calculatedCurve.at(i+25*packetNo).x())); //x
1651
            vals.append((qint16)(calculatedCurve.at(i+25*packetNo).y())); //y
1652
            vals.append((qint16)(calculatedCurve.at(i+25*packetNo).z())); //z
1653
            vals.append((qint16)(calculatedCurve.at(i+25*packetNo).w())); //a
1654
        }
1655
        writeValues(REG_DATA, QModbusDataUnit::HoldingRegisters, vals);
1656
        writeValue(REG_INDEX, QModbusDataUnit::HoldingRegisters, packetNo*25); //index
1657
        writeValue(REG_LEN, QModbusDataUnit::HoldingRegisters, calculatedCurve.size()); //len
1658
    }
1659

    
1660
    return nLen;
1661
}
1662

    
1663
//! Získání bloku dat ze stroje
1664
/*!
1665
 * Přijme další blok dat s křivkou od stroje, přidá dané bodu do aktuální křivky, která se na konci vykreslí
1666
 * ve 3D okně
1667
 * \param packetNo Pořadové číslo bloku
1668
 * \param data Přijatá data
1669
 * \return Počet přijatých dat
1670
 */
1671
int MainWindow::getCurveData(int dataType, int packetNo, QVector<quint16> data)
1672
{
1673
    int nLen = 0, packetRemaining = numPoints - packetNo;
1674

    
1675
    if (dataType == GET_PART_CURVE)
1676
    {
1677
        nLen = (packetRemaining < 25) ? packetRemaining : 25;
1678

    
1679
        QLOG_DEBUG() <<  QString("nLen = %1, data size %2").arg(nLen).arg(data.size());
1680
        if ((nLen*4) > data.size()) {
1681
            QLOG_ERROR() << "Not enough data came - use only prersent data";
1682
            nLen = data.size()/4;
1683
        }
1684

    
1685
        for(int i = 0; i < nLen; i++) {
1686
            calculatedCurve.append(QVector4D((qint16)data.at(i*4), (qint16)data.at(i*4 + 1),
1687
                                         (qint16)data.at(i*4 + 2), (qint16)data.at(i*4 + 3)));
1688
            if (file.isOpen()) {
1689
                store << (qint16)data.at(i*4) << ";" << (qint16)data.at(i*4 + 1)
1690
                      << ";" << (qint16)data.at(i*4 + 2) << ";" << (qint16)data.at(i*4 + 3) << endl;
1691
            }
1692
        }
1693
    } else {
1694
        nLen = (packetRemaining < 10) ? packetRemaining : 10;
1695

    
1696
        QLOG_DEBUG() <<  QString("nLen = %1, data size %2").arg(nLen).arg(data.size());
1697
        if ((nLen*10) > data.size()) {
1698
            QLOG_ERROR() << "Not enough data came - use only present data";
1699
            nLen = data.size()/10;
1700
        }
1701

    
1702
        for(int i = 0; i < nLen; i++) {
1703
            if (file.isOpen()) {
1704
                store << (qint16)data.at(i*10) << ";" << (qint16)data.at(i*10 + 1)
1705
                      << ";" << (qint16)data.at(i*10 + 2) << ";" << (qint16)data.at(i*10 + 3)
1706
                      << ";" << (qint16)data.at(i*10 + 4) << ";" << (qint16)data.at(i*10 + 5)
1707
                      << ";" << (qint16)data.at(i*10 + 6) << ";" << (qint16)data.at(i*10 + 7)
1708
                      << ";" << (qint16)data.at(i*10 + 8) << ";" << (qint16)data.at(i*10 + 9)
1709
                      << endl;
1710
            }
1711
        }
1712
    }
1713
    receivedDataSize += nLen;
1714
    QLOG_DEBUG() << QString("get data packet No %1, received data count %2, packetRem %3").arg(packetNo).arg(receivedDataSize).arg(packetRemaining);
1715

    
1716
    return nLen;
1717
}
(11-11/19)