Projekt

Obecné

Profil

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

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

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

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

    
36
//reset pozice
37
#define BIT_RESET_POS       32769
38

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

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

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

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

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

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

    
70
//rychlost cviceni
71
#define REG_SPEED   32799
72

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

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

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

    
100
    mbClient = new QModbusTcpClient(this);
101
    pendingRead = pendingWrite = lastPacket = initStep = bSpeedUpdated = false;
102
    calcCurvePoints[0] = calcCurvePoints[1] = staticSpherePos = spherePos = QVector3D(0,0,0);
103
    dirArrow = QVector3D(0,0,0);
104
    actualArrow = QVector3D(0,0,0);
105
    testSpherePos = QVector3D(0,0,0);
106
    overallQ = oneCycleQ = tempQ = 0;
107
    pId = indId = 0;
108
    pronSupVal = PRON_SUP_NOT;
109
    actSeries = 0;
110

    
111
    itemCount = cntr = 0;
112

    
113
    safetyBtnState = safetyBtnBlinkOn = keyAutoBtnBlinkOn = 0;
114

    
115
    receivedDataSize = 0;
116

    
117
    mbServerId = 1;
118

    
119
    pd = waitDlg = nullptr;
120

    
121
    checkTimer = new QTimer(this);
122
    procedureTimer = new QTimer(this);
123
    procedureTimeRemaining = 600;
124
    ui->procTimeDial->setValue(10);
125

    
126
    connect(mbClient, &QModbusClient::errorOccurred, this, &MainWindow::handleDeviceError);
127
    connect(mbClient, &QModbusClient::stateChanged, this, &MainWindow::onStateChanged);
128

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

    
139
    connect(ui->procTimeDial, SIGNAL(sliderMoved(int)), this, SLOT(timeDialMoved(int)));
140
    connect(ui->procTimeDial, SIGNAL(sliderReleased()), this, SLOT(timeDialReleased()));
141

    
142
    connect(ui->upDownSlider, SIGNAL(sliderMoved(int)), this, SLOT(upDownSliderMoved(int)));
143
    connect(ui->upDownSlider, SIGNAL(sliderReleased()), this, SLOT(movementSliderReleased()));
144

    
145
    connect(checkTimer, SIGNAL(timeout()), this, SLOT(mainCycle()));
146
    connect(procedureTimer, SIGNAL(timeout()), this, SLOT(updateAppTime()));
147

    
148

    
149
    currState = numPoints = 0;
150

    
151
    ui->connectionLabel->setStyleSheet("background-color: rgb(255,0,0)");
152
    ui->dbConnectionStatusLabel->setStyleSheet("background-color: rgb(255,0,0)");
153

    
154
    mbConnected = false;
155
    bTeachStatus = bWriteEnable = bProcedureRunning = bPartState = bKeyState = bPlay = 0;
156

    
157
    qualitySet = new QBarSet("Kvalita");
158
    qualityData = new QBarSeries();
159
    qualityData->append(qualitySet);
160

    
161
    QFont font;
162
    font.setPixelSize(18);
163

    
164
    chart = new QChart();
165
    chart->addSeries(qualityData);
166

    
167
    axisy = new QValueAxis();
168
    axisy->setRange(0.0, 100.0);
169
    axisy->setLabelsFont(font);
170

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

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

    
190
    ui->verticalLayout->addWidget(graphView);
191
    ui->splitter->setStretchFactor(0,0);
192
    ui->splitter->setStretchFactor(1,1);
193

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

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

    
213
    db = new dbAccess();
214
    model = new QSqlQueryModel;
215

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

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

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

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

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

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

    
263
    if (mbConnected) {
264
        mbClient->disconnectDevice();
265
    }
266
    delete db;
267
    delete ui;
268
}
269

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

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

    
291
        return;
292
#endif
293

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

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

    
321
         //QLOG_WARN() << "e";
322
         store << "x;y;z;r" << endl;
323
    }
324

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

    
337
         //QLOG_WARN() << "e";
338

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

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

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

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

    
383
#ifdef FILE_TEST
384
    file.setFileName("data.txt");
385
    if (file.open(QIODevice::WriteOnly | QIODevice::Text)) {
386
         store.setDevice(&file);
387
    }
388
#endif
389

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

    
396
            return;
397
        }
398
    } else {
399
        calculatedCurve.clear();
400

    
401
        //kdyz nebude pouzita zadna krivka - vymazat starou krivku
402
        if (actCurveType == CURVE_NONE)
403
            display3DScene();
404

    
405
        for (i=0; i < stepcount+1; i++) {
406
            if (actCurveRot == ROTATE_CLKWISE)
407
                tmpI = stepcount - i;
408
            else
409
                tmpI = i;
410
            tmpdeg = tmpI * (360.0/stepcount) * M_PI / 180.0;
411

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

    
435
                if (actCurveRot != ROTATE_CLKWISE)
436
                    tmpI = (stepcount - tmpI);
437

    
438
                //x = -2200 + tmpI * 4400.0 / stepcount;
439
                x = -2200 + tmpI * 4400.0 / stepcount;
440
                y = 0;// -2200 + tmpI * 4400.0 / stepcount;
441
                break;
442
            default:
443
                x = RES_X_POS;
444
                y = RES_Y_POS;
445
                z = RES_Z_POS;
446
            }
447

    
448
            x1 = x*cos(actCurveAngle*M_PI/4)-y*sin(actCurveAngle*M_PI/4);
449
            y1 = x*sin(actCurveAngle*M_PI/4)+y*cos(actCurveAngle*M_PI/4);
450

    
451
            if (actCurveType != CURVE_NONE)
452
                z = 6500.0 - y1*0.9;
453

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

    
466
            if (i == stepcount/2)
467
                calcCurvePoints[0] = QVector3D(x1,y1,z);
468
            else if (i == stepcount)
469
                calcCurvePoints[1] = QVector3D(x1,y1,z);
470

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

    
489
//! Učení křivky
490
/*!
491
 * 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
492
 *  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ě
493
 * projíždět křivku, která bude zaznamenána strojem.
494
 * Pokud je učení ukončeno, je do stroje poslán příkaz o ukončení učení
495
 * \param pressed Parametr, který obsahuje informaci o tom, jestli má být učení zahájeno, nebo ukončeno
496
 */
497
void MainWindow::curveTeachChanged(bool pressed)
498
{
499
    if (pressed) {
500
        deviceResetClicked();
501
        display3DScene();
502

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

    
514
        writeValue(BIT_BTEACH, QModbusDataUnit::Coils,0);
515
        writeValue(BIT_BXYZ, QModbusDataUnit::Coils,0);
516
        ui->curveTeachBtn->setStyleSheet("background-color: rgb(0, 222, 222)");
517
    }
518
}
519

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

    
530
    getCurveDataFromFile(fileName);
531
}
532

    
533
void MainWindow::measurementLoadClicked()
534
{
535
    openMeasurementFile();
536
    writeValue(BIT_MEASUREMENT_TO_PC, QModbusDataUnit::Coils, 1);
537
    currState = GET_MEAS_START;
538
}
539

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

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

    
560
         store << "cas;x1;y1;z1;x2;y2;z2;x3;y3;z3" << endl;
561
    }
562
}
563

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

    
570
    if (file.open(QIODevice::ReadOnly | QIODevice::Text)) {
571
        calculatedCurve.clear();
572

    
573
        QTextStream storeFile(&file);
574
        QVector4D point;
575
        QVector3D pointPrev;
576
        QStringList list;
577
        QString line;
578

    
579
        tmpCurveMA.clear();
580

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

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

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

    
629
        QFile file(fileName);
630
        if (file.open(QIODevice::WriteOnly | QIODevice::Text)) {
631
            QTextStream storeFile(&file);
632

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

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

    
647
//! Přesun aktuatoru do defaultní pozice
648
void MainWindow::deviceResetClicked()
649
{
650
    writeValue(BIT_RESET_POS, QModbusDataUnit::Coils, 1);
651
}
652

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

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

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

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

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

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

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

    
738
        infoDialog dlg;
739
        dlg.setInfoText(tr("Cvičení"),tr("Cvičení je dokončeno"));
740
        dlg.exec();
741
    }
742
#else
743
    if (!bKeyState)
744
        return;
745

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

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

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

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

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

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

    
825
            infoDialog dlg;
826
            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.");
827
            dlg.exec();
828

    
829
            writeValue(BIT_BTEACH, QModbusDataUnit::Coils,1);
830
            writeValue(BIT_BXYZ, QModbusDataUnit::Coils,1);
831
        }
832
    }
833

    
834
#if !defined(FILE_TEST) && !defined(PROCEDURE_TEST)
835
    if (!mbConnected)
836
        return;
837

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

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

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

    
981
        }
982
    }
983

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

    
1014
        QLOG_DEBUG() << QString("Data %1, %2").arg(itemCount).arg(r);
1015
        itemCount++;
1016
    }
1017
#endif
1018

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

    
1030

    
1031
        //vec = sphere.at(itemCount);
1032
        cur.append(vec);
1033
        vec1 = dir.at(itemCount);
1034
        vec2 = act.at(itemCount);
1035
        vec1 = vec2 = QVector4D(0,0,0,0);
1036

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

    
1049
        //ui->glwidget->setTubusColor(QVector4D(0, 0.87f, 0.87f, 1));
1050
        //ui->glwidget->addSphereData(vec, start, finish);
1051

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

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

    
1083
    if (readRequest->error() == QModbusDevice::NoError) {
1084
        const QModbusDataUnit unit = readRequest->result();
1085
        int value, address = unit.startAddress();
1086
        connectionGuard->restart();
1087

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

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

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

    
1281
                /*if ((numPoints - nIndex) > 0) {
1282
                    if (currState == GET_PART_CURVE) {
1283
                        currState = GET_WAIT_CURVE;
1284
                        pd->setValue(calculatedCurve.size());
1285
                    }
1286
                    else {
1287
                        currState = GET_MEAS_WAIT;
1288
                        pd->setValue(numPoints - nIndex);
1289
                    }
1290
                    QLOG_DEBUG() << "Dalsi cast";
1291
                }*/
1292

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

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

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

    
1382
    readRequest->deleteLater();
1383

    
1384
    pendingRead = false;
1385
}
1386

    
1387
//! Potvrzení zápisu dat na Modbus/TCP
1388
void MainWindow::writeFinished()
1389
{
1390
    QModbusReply *writeRequest = qobject_cast<QModbusReply *>(sender());
1391
    if (!writeRequest)
1392
        return;
1393

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

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

    
1413
    if (state == QModbusDevice::UnconnectedState) {
1414
        ui->connectionLabel->setText(tr("Odpojeno"));
1415
        ui->connectionLabel->setStyleSheet("background-color: rgb(255,0,0)");
1416
        ui->safetyBtnLabel->setStyleSheet("");
1417
        ui->autoKeyStatusLabel->setStyleSheet("");
1418
        mbConnected = false;
1419
        //checkTimer->stop();
1420
        checkTimer->setInterval(500);
1421

    
1422
        ui->resetPosBtn->setEnabled(false);
1423
        ui->curvePlayBtn->setEnabled(false);
1424
        ui->curveAssistPlayBtn->setEnabled(false);
1425
        ui->curveGenerateBtn->setEnabled(false);
1426
        ui->curveTeachBtn->setEnabled(false);
1427
        ui->curveLoadBtn->setEnabled(false);
1428
        ui->curveStoreBtn->setEnabled(false);
1429

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

    
1438
        bTeachStatus = bWriteEnable = bProcedureRunning = bPartState = bKeyState = bPlay = safetyBtnState = 0;
1439

    
1440
        ui->resetPosBtn->setEnabled(true);
1441
        ui->curvePlayBtn->setEnabled(true);
1442
        ui->curveGenerateBtn->setEnabled(true);
1443
        ui->curveTeachBtn->setEnabled(true);
1444
        ui->curveLoadBtn->setEnabled(true);
1445
        ui->curveStoreBtn->setEnabled(true);
1446

    
1447
        connectionGuard->restart();
1448
        connectionEstablished = true;
1449

    
1450
        //ziskat rovnou status tlacitek
1451
        readValue(BIT_BKEY, QModbusDataUnit::DiscreteInputs);
1452
        readValue(BIT_SAFETY_BTN, QModbusDataUnit::DiscreteInputs);
1453

    
1454
        setCurveData();  //nahrat do stroje rovnou krivku
1455
    }
1456
}
1457

    
1458
//! Ošetření chyby při komunikaci
1459
void MainWindow::handleDeviceError(QModbusDevice::Error newError)
1460
{
1461
    if (newError == QModbusDevice::NoError || !mbClient)
1462
        return;
1463

    
1464
    QLOG_ERROR() <<  mbClient->errorString();
1465
}
1466

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

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

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

    
1502
//! Úprava doby asistovaného cvičení
1503
void MainWindow::timeDialReleased()
1504
{
1505
    QString txt = tr("Ukončit cvičení\n");
1506

    
1507
    if (!bProcedureRunning) {
1508
        txt = tr("Spustit cvičení\n");
1509
    }
1510
    procedureTimeRemaining = ui->procTimeDial->value()*60;
1511
    ui->curveAssistPlayBtn->setText(txt + QString::number(procedureTimeRemaining/60) + ":00 min");
1512
}
1513

    
1514
#ifdef PROCEDURE_TEST
1515
QList<QVector4D> MainWindow::readPoints(QString fName)
1516
{
1517
    QList<QVector4D> results;
1518
    double a = 0.0;
1519

    
1520
    QFile file(fName);
1521
    if (!file.open(QIODevice::ReadOnly | QIODevice::Text))
1522
    {
1523
        return results;
1524
    }
1525

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

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

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

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

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

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

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

    
1633
    QLOG_DEBUG() << "prepare data";
1634
    QLOG_DEBUG() << QString("data count %1, packetNo %2").arg(calculatedCurve.size()).arg(packetNo);
1635

    
1636
    if (calculatedCurve.size() < packetNo*25)
1637
        return 0;
1638

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

    
1655
    return nLen;
1656
}
1657

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

    
1670
    if (dataType == GET_PART_CURVE)
1671
    {
1672
        nLen = (packetRemaining < 25) ? packetRemaining : 25;
1673

    
1674
        QLOG_DEBUG() <<  QString("nLen = %1, data size %2").arg(nLen).arg(data.size());
1675
        if ((nLen*4) > data.size()) {
1676
            QLOG_ERROR() << "Not enough data came - use only prersent data";
1677
            nLen = data.size()/4;
1678
        }
1679

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

    
1691
        QLOG_DEBUG() <<  QString("nLen = %1, data size %2").arg(nLen).arg(data.size());
1692
        if ((nLen*10) > data.size()) {
1693
            QLOG_ERROR() << "Not enough data came - use only present data";
1694
            nLen = data.size()/10;
1695
        }
1696

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

    
1711
    return nLen;
1712
}
(9-9/17)