Projekt

Obecné

Profil

Stáhnout (63.1 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, cdServer);
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, cdServer);
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
    cdServer->sendActualDirection(actualArrow.x(), actualArrow.y(), actualArrow.z());
1076
    cdServer->sendTargetDirection(dirArrow.x(), dirArrow.y(), dirArrow.z());
1077
    cdServer->processPings();
1078
}
1079

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

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

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

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

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

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

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

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

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

    
1390
    readRequest->deleteLater();
1391

    
1392
    pendingRead = false;
1393
}
1394

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

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

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

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

    
1430
        ui->resetPosBtn->setEnabled(false);
1431
        ui->curvePlayBtn->setEnabled(false);
1432
        ui->curveAssistPlayBtn->setEnabled(false);
1433
        ui->curveGenerateBtn->setEnabled(false);
1434
        ui->curveTeachBtn->setEnabled(false);
1435
        ui->curveLoadBtn->setEnabled(false);
1436
        ui->curveStoreBtn->setEnabled(false);
1437

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

    
1446
        bTeachStatus = bWriteEnable = bProcedureRunning = bPartState = bKeyState = bPlay = safetyBtnState = 0;
1447

    
1448
        ui->resetPosBtn->setEnabled(true);
1449
        ui->curvePlayBtn->setEnabled(true);
1450
        ui->curveGenerateBtn->setEnabled(true);
1451
        ui->curveTeachBtn->setEnabled(true);
1452
        ui->curveLoadBtn->setEnabled(true);
1453
        ui->curveStoreBtn->setEnabled(true);
1454

    
1455
        connectionGuard->restart();
1456
        connectionEstablished = true;
1457

    
1458
        //ziskat rovnou status tlacitek
1459
        readValue(BIT_BKEY, QModbusDataUnit::DiscreteInputs);
1460
        readValue(BIT_SAFETY_BTN, QModbusDataUnit::DiscreteInputs);
1461

    
1462
        setCurveData();  //nahrat do stroje rovnou krivku
1463
    }
1464
}
1465

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

    
1472
    QLOG_ERROR() <<  mbClient->errorString();
1473
}
1474

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

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

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

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

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

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

    
1528
    QFile file(fName);
1529
    if (!file.open(QIODevice::ReadOnly | QIODevice::Text))
1530
    {
1531
        return results;
1532
    }
1533

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

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

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

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

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

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

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

    
1641
    QLOG_DEBUG() << "prepare data";
1642
    QLOG_DEBUG() << QString("data count %1, packetNo %2").arg(calculatedCurve.size()).arg(packetNo);
1643

    
1644
    if (calculatedCurve.size() < packetNo*25)
1645
        return 0;
1646

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

    
1663
    return nLen;
1664
}
1665

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

    
1678
    if (dataType == GET_PART_CURVE)
1679
    {
1680
        nLen = (packetRemaining < 25) ? packetRemaining : 25;
1681

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

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

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

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

    
1719
    return nLen;
1720
}
(11-11/19)