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
{
99
    ui->setupUi(this);
100

    
101
    mbClient = new QModbusTcpClient(this);
102

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

    
113
    itemCount = cntr = 0;
114

    
115
    safetyBtnState = safetyBtnBlinkOn = keyAutoBtnBlinkOn = 0;
116

    
117
    receivedDataSize = 0;
118

    
119
    mbServerId = 1;
120

    
121
    pd = waitDlg = nullptr;
122

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

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

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

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

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

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

    
150

    
151
    currState = numPoints = 0;
152

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

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

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

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

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

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

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

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

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

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

    
207
    cdServer = new CurveDataServer(st.value("curveServerPort", "4242").toUInt());
208

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

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

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

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

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

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

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

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

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

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

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

    
296
        return;
297
#endif
298

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
535
    getCurveDataFromFile(fileName);
536
}
537

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

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

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

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

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

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

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

    
584
        tmpCurveMA.clear();
585

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
830
            infoDialog dlg;
831
            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.");
832
            dlg.exec();
833

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

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

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

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

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

    
986
        }
987
    }
988

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

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

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

    
1035

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

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

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

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

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

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

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

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

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

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

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

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

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

    
1391
    readRequest->deleteLater();
1392

    
1393
    pendingRead = false;
1394
}
1395

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
1664
    return nLen;
1665
}
1666

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

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

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

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

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

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

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