-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathgsmscale.cpp
More file actions
186 lines (148 loc) · 4.95 KB
/
Copy pathgsmscale.cpp
File metadata and controls
186 lines (148 loc) · 4.95 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
#include "gsmscale.h"
#include "ui_gsmscale.h"
#include "serial_comms.h"
#include <iostream>
#include <ctime>
/**
* @brief gsmscale::gsmscale
* @param parent
*
* Set up slots and initially create the threads that read and monitor
* the serial port. Also set default values for the user interface.
*/
gsmscale::gsmscale(QWidget *parent)
:
QMainWindow(parent),
ui(new Ui::gsmscale) {
ui->setupUi(this);
for(PAGE_SIZE &it : m_pageSizeLUT) {
ui->CB_PageSize->addItem(it.Name);
}
this->statusBar()->setSizeGripEnabled(false);
ui->SPIN_Length->setDisabled(true);
ui->SPIN_Width->setDisabled(true);
ui->SPIN_Length->setValue(m_pageSizeLUT[0].L);
ui->SPIN_Width->setValue(m_pageSizeLUT[0].W);
ui->TXT_CUR_Weight->insertPlainText("Error");
connect(ui->CB_PageSize, SIGNAL(currentIndexChanged(int)), this, SLOT(update_page_size(int)));
m_t1Done = false;
t1 = new std::thread([this] { this->monitor_measuring_device(); } );
t1_handle = t1->native_handle();
t1->detach();
t_Monitor = new std::thread([this] { this->monitor_threads(); } );
t_Monitor->detach();
/**
* @code startTimer() @endcode
* is used to trigger the timerEvent() method that is used to update the
* user interface. It served no other purpose; the threads have thier own
* timers.
* */
m_timerId = startTimer(300);
}
/**
* @brief gsmscale::~gsmscale
*/
gsmscale::~gsmscale() {
killTimer(m_timerId);
m_t1Done = true;
if(t1->joinable())
t1->join();
delete t1;
if(t_Monitor->joinable())
t_Monitor->join();
delete t_Monitor;
delete ui;
}
/**
* @brief gsmscale::monitor_measuring_device
*
* CALLED BY THREAD t1
*
* Create an instance of the serial_comms class, check that we can
* connect to the scale and if we can then try and read data from
* the scale.
*
* @note read_serial() may block, a second thread is created to
* kill off this thread (t1) if it blocks for too long.
*/
void gsmscale::monitor_measuring_device() {
serial_comms s;
while(!s.test_comms()) {
t1_serialReadTime = time(nullptr);
std::this_thread::sleep_for(std::chrono::milliseconds(1000));
m_deviceMeasurement_MUTEX.lock();
m_deviceMeasurement = "Error";
m_deviceMeasurement_MUTEX.unlock();
}
while(!m_t1Done) {
t1_serialReadTime = time(nullptr);
m_deviceMeasurement_MUTEX.lock();
m_deviceMeasurement = s.read_serial();
m_deviceMeasurement_MUTEX.unlock();
std::this_thread::sleep_for(std::chrono::milliseconds(300));
}
}
/**
* @brief gsmscale::monitor_threads
*
* CALLED BY t_Monitor
*
* This is used to kill thread "t1" if the scale becomes disconnected
* It will then attempt to recreated it to allow the applicatin to
* continue if the scale is reconnected.
*/
void gsmscale::monitor_threads() {
const int T1_TIMEOUT = 5;
while (!m_t1Done) {
if ((time(nullptr) - T1_TIMEOUT) > t1_serialReadTime ) {
pthread_cancel(t1_handle);
m_deviceMeasurement = "Timeout";
m_deviceMeasurement_MUTEX.unlock();
if(DEBUG_SERIAL) std::cout << "Thread killed due to being blocked by read()." << std::endl;
t1 = new std::thread([this] { this->monitor_measuring_device(); } );
t1_handle = t1->native_handle(); //USED SO WE CAN KILL THE THREAD.
t1->detach();
}
std::this_thread::sleep_for(std::chrono::milliseconds(1000));
}
}
/**
* @brief gsmscale::timerEvent
* @param event
*
* Update the user interface.
*
* @attention The lock guard will block this method if the
* m_deviceMeasurement_MUTEX is locked (see the monitor_measuring_device() method)
*/
void gsmscale::timerEvent(QTimerEvent *event) {
event->accept();
ui->TXT_CUR_Weight->clear();
//WAIT FOR THE m_deviceMeasurement VALE TO BECOME STABLE
std::lock_guard guard(m_deviceMeasurement_MUTEX);
if(DEBUG_SERIAL) std::cout << __PRETTY_FUNCTION__ <<": Value received: " << m_deviceMeasurement << std::endl;
ui->TXT_CUR_Weight->insertPlainText(QString::fromStdString(m_deviceMeasurement));
double widthM, lengthM, weightG;
widthM = ui->SPIN_Width->value() / 1000;
lengthM = ui->SPIN_Length->value() / 1000;
weightG = ui->TXT_CUR_Weight->toPlainText().toInt();
ui->LCD_GSM->display(round(weightG / (lengthM * widthM)));
}
/**
* @brief gsmscale::update_page_size
* @param index
*
* Update the user interface to reflect the selected page size based on the lookup
* table m_pageSizeLUT.
*/
void gsmscale::update_page_size(int index) {
ui->SPIN_Length->setValue(m_pageSizeLUT[index].L);
ui->SPIN_Width->setValue(m_pageSizeLUT[index].W);
if(m_pageSizeLUT[index].Name.compare("Custom") == 0) {
ui->SPIN_Length->setDisabled(false);
ui->SPIN_Width->setDisabled(false);
} else {
ui->SPIN_Length->setDisabled(true);
ui->SPIN_Width->setDisabled(true);
}
}