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
}
1078

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

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

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

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

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

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

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

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

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

    
1389
    readRequest->deleteLater();
1390

    
1391
    pendingRead = false;
1392
}
1393

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
1662
    return nLen;
1663
}
1664

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

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

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

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

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

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

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