Raspberry Pi Weighting Control System
This project serves as a simple weighting control system, that was realized as a Bachelor Thesis
user_workspace.cpp
Go to the documentation of this file.
1 #include "user_workspace.h"
2 
3 #include <memory.h>
4 #include <spdlog/spdlog.h>
5 #include "localisation.h"
6 
7 
8 #define X_SAMPLES 5
9 
10 /*********************************************************************************************************************/
11 /* Measurements function definitions */
12 /*********************************************************************************************************************/
13 
15  char buf[64] = {0};
16  strftime(buf, 64, "%Y-%m-%d %H:%M:%S", &(this->measuring_start));
17  this->label = std::to_string(this->measurement_number) + " - " + std::string(buf);
18 
19  return this->label.c_str();
20 }
21 
23  spdlog::debug("measurement - ID: {0}", this->id);
24  // spdlog::debug("measurement - status: {0}", this->status);
25  spdlog::debug("measurement - measurement_number: {0}", this->measurement_number);
26  spdlog::debug("measurement - measuree_id: {0}", this->measuree_id);
27  spdlog::debug("measurement - measurer_id: {0}", this->measurer_id);
28  spdlog::debug("measurement - measuring_length: {0}", this->measuring_length);
29  char buf[64] = {0};
30  strftime(buf, 64, "%Y-%m-%d %H:%M:%S", &(this->measuring_start));
31  spdlog::debug("measurement - measuring start: {0}", buf);
32  memset(buf, 0, 64);
33  strftime(buf, 64, "%Y-%m-%d %H:%M:%S", &(this->measuring_end));
34  spdlog::debug("measurement - measuring end: {0}", buf);
35  spdlog::debug("measurement - description: {0}", this->description.c_str());
36  spdlog::debug("measurement - value_length: {0}", this->value_length);
37  spdlog::debug("measurement - value_count: {0}", this->value_count);
38  spdlog::debug("measurement - raw_values size: {0}", this->values.size());
39  spdlog::debug("measurement - x_val_med: {0}", this->x_val_med);
40  spdlog::debug("measurement - x_val_avg: {0}", this->x_val_avg);
41  spdlog::debug("measurement - all_val_med: {0}", this->all_val_med);
42  spdlog::debug("measurement - all_val_avg: {0}", this->all_val_avg);
43  memset(buf, 0, 64);
44  strftime(buf, 64, "%Y-%m-%d %H:%M:%S", &(this->created_at));
45  spdlog::debug("measurement - created at: {0}", buf);
46 }
47 
49  // Mass must be created as G. The hx sensor library atually returns measured double in Grams!
50  HX711::Mass x_med(x_val_med, HX711::Mass::Unit::G);
51  HX711::Mass x_avg(x_val_avg, HX711::Mass::Unit::G);
52  HX711::Mass all_med(all_val_med, HX711::Mass::Unit::G);
53  HX711::Mass all_avg(all_val_avg, HX711::Mass::Unit::G);
54 
55  /*
56  spdlog::info("Measured value no par: {0}", x_med.toString().c_str());
57  spdlog::info("Measured value MG: {0}", x_med.toString(HX711::Mass::Unit::MG).c_str());
58  spdlog::info("Measured value G: {0}", x_med.toString(HX711::Mass::Unit::G).c_str());
59  spdlog::info("Measured value KG: {0}", x_med.toString(HX711::Mass::Unit::KG).c_str());
60  */
61 
62  this->x_val_med_str = x_med.toString(current_unit);
63  this->x_val_avg_str = x_avg.toString(current_unit);
64  this->all_val_med_str = all_med.toString(current_unit);
65  this->all_val_avg_str = all_avg.toString(current_unit);
66 }
67 
69  char buf[64] = {0};
70  strftime(buf, 64, "%Y-%m-%d %H:%M:%S", &(this->measuring_start));
71  // FIXME - is first or second version better?
72  // this->start_str = buf;
73  this->start_str = std::string(buf);
74 
75  memset(buf, 0, 64);
76  strftime(buf, 64, "%Y-%m-%d %H:%M:%S", &(this->measuring_end));
77  // this->end_str = buf;
78  this->end_str = std::string(buf);
79 
80  memset(buf, 0, 64);
81  if (this->continuous) {
82  // continuous measuring is minute at least, up to days, so length is in s
83  sprintf(buf, "%ld s", std::chrono::seconds(this->measuring_length).count());
84  } else {
85  // regular measuring is expected to take around a minute max
86  sprintf(buf, "%ld ms", std::chrono::duration_cast<std::chrono::milliseconds>
87  (std::chrono::microseconds(this->measuring_length)).count());
88  }
89  // this->length_str = buf;
90  this->length_str = std::string(buf);
91 }
92 
93 void measurement::init_convinience_vars(const char* measurer_uname, const char* measuree_uname) {
94  this->init_value_strings();
95  this->init_start_end_strings();
96  this->measuree_uname = measuree_uname;
97  this->measurer_uname = measurer_uname;
98 }
99 
101  spdlog::debug("Comparing:");
102  this->log_measurement_to_debug();
103  spdlog::debug("to:");
105  spdlog::info("Comparing start");
106 
107  if (this->measurement_number != m->measurement_number) {
108  spdlog::debug("measurement_number diff: {0} - {1}", this->measurement_number, m->measurement_number);
109  }
110  if (this->measuree_id != m->measuree_id) {
111  spdlog::debug("measuree_id diff: {0} - {1}", this->measuree_id, m->measuree_id);
112  }
113  if (this->measurer_id != m->measurer_id) {
114  spdlog::debug("measurer_id diff: {0} - {1}", this->measurer_id, m->measurer_id);
115  }
116  if (this->measuring_length != m->measuring_length) {
117  spdlog::debug("measuring_length diff: {0} - {1}", this->measuring_length, m->measuring_length);
118  }
119  if (this->x_val_med != m->x_val_med) {
120  spdlog::debug("x_val_med diff: {0} - {1}", this->x_val_med, m->x_val_med);
121  }
122  if (this->x_val_avg != m->x_val_avg) {
123  spdlog::debug("x_val_avg diff: {0} - {1}", this->x_val_avg, m->x_val_avg);
124  }
125  if (this->all_val_med != m->all_val_med) {
126  spdlog::debug("all_val_med diff: {0} - {1}", this->all_val_med, m->all_val_med);
127  }
128  if (this->all_val_avg != m->all_val_avg) {
129  spdlog::debug("all_val_avg diff: {0} - {1}", this->all_val_avg, m->all_val_avg);
130  }
131  if (this->values.size() != m->values.size()) {
132  spdlog::debug("values.size() diff: {0} - {1}", this->values.size(), m->values.size());
133  }
134 
135  size_t len = this->values.size() > m->values.size() ? m->values.size() : this->values.size();
136  for (size_t i = 0; i < len; i++) {
137  if (this->values[i] != m->values[i]) {
138  spdlog::error("values (binary) start to differ at index {0}", i);
139  break;
140  }
141  }
142 
143  spdlog::info("Comparing end");
144  return 0;
145 }
146 
147 void measurement::init_simple_measuring(measurement *m, std::vector<double> &values) {
148  // this is called on every update - not logging even to debug
149  // spdlog::debug("user_workspace.cpp - Initing simple measurements");
150  m->values = values;
151  m->value_count = values.size();
152  m->value_length = sizeof(double);
153 
155  m->init_value_strings();
156 }
157 
158 void measurement::init_measuring(measurement *m, user_workspace *uspace, std::vector<double> &values,
159  std::tm *start_tm, std::tm *end_tm, unsigned long m_length)
160 {
161  spdlog::debug("user_workspace.cpp - Initing basic measuring parameters");
162 
163  m->values = values;
164  m->measuree_id = uspace->has_subuser() ? uspace->subuser->id : uspace->get_user_id();
165  m->measurer_id = uspace->get_user_id();
166  m->measurement_number = uspace->has_subuser() ? uspace->subuser->measure_count + 1 :
167  uspace->get_user()->measure_count + 1;
168 
169  // dereferencing like this should copy
170  m->measuring_start = *start_tm;
171  m->measuring_end = *end_tm;
172  m->measuring_length = m_length;
173  m->value_count = values.size();
174  m->value_length = sizeof(double);
175 
177 }
178 
180  // called often by init_simple_measuring(...); disabling debug
181  // spdlog::debug("user_workspace.cpp - Initing calculated measuring parameters");
182  std::pair<double, double> x_vals = measurement::calc_every_x_values_stats(m);
183  m->x_val_med = x_vals.first;
184  m->x_val_avg = x_vals.second;
185 
186  std::pair<double, double> all_vals = measurement::calc_all_values_stats(m);
187  m->all_val_med = all_vals.first;
188  m->all_val_avg = all_vals.second;
189 }
190 
191 void measurement::prepare_continuous_to_picked(std::vector<measurement> &ms, measurement* picked) {
192  if (ms.size() <= 0) return; // this shouldn't occure, but just to be safe
193 
194  *picked = ms[0]; // copy first element to picked
195 
196  picked->measuring_end = ms[ms.size() - 1].measuring_end;
197  picked->cont_measurements = ms.size();
198  picked->continuous = true;
199 
200  unsigned long total_length = 0;
201  double xm_sum = 0.0, xa_sum = 0.0, am_sum = 0.0, aa_sum = 0.0;
202 
203  for (size_t i = 0; i < ms.size(); i++) {
204  // measuring length is in us, continuous length is assumed to be minutes, hours or even days -> stored in seconds
205  total_length += ms[i].measuring_length / 1000000;
206  xm_sum += ms[i].x_val_med;
207  xa_sum += ms[i].x_val_avg;
208  am_sum += ms[i].all_val_med;
209  aa_sum += ms[i].all_val_avg;
210  }
211 
212  picked->measuring_length = total_length;
213  // use avarages of all stats as result to show
214  picked->x_val_med = xm_sum / ms.size();
215  picked->x_val_avg = xa_sum / ms.size();
216  picked->all_val_med = am_sum / ms.size();
217  picked->all_val_avg = aa_sum / ms.size();
218 }
219 
221  size_t it = 0, inc = 0;
222  std::vector<double> vect = m->values; // copy to not modify original vector order
223  std::vector<double> meds;
224  std::vector<double> avgs;
225 
226  while (it < vect.size()) {
227  if ((it + X_SAMPLES) < vect.size())
228  inc = X_SAMPLES;
229  else
230  inc = vect.size() - it;
231 
232  auto it_start = vect.begin() + it;
233  auto it_end = vect.begin() + it + inc;
234 
235  std::vector<double> tmp(it_start, it_end);
236 
237  meds.push_back(HX711::Utility::median(&tmp));
238  avgs.push_back(HX711::Utility::average(&tmp));
239 
240  it += inc;
241  }
242 
243  return std::pair<double, double>(HX711::Utility::median(&meds), HX711::Utility::average(&avgs));
244 }
245 
246 std::pair<double, double> measurement::calc_all_values_stats(measurement *m) {
247  std::vector<double> vect = m->values; // copy to not modify original vector order
248  return std::pair<double, double>(HX711::Utility::median(&vect), HX711::Utility::average(&vect));
249 }
250 
251 
252 /*********************************************************************************************************************/
253 /* User container function definitions */
254 /*********************************************************************************************************************/
255 
256 user_cont::user_cont(unsigned long id, uint8_t *rfid_ser_bin, uint8_t rfid_ser_len, std::string username,
257  std::string name, std::string lastname, std::string description, uint8_t role, std::tm reg_date,
258  std::tm last_login_date, std::tm created_at_date, std::tm date_of_birth)
259 {
260  this->id = id;
261  this->username = username;
262  this->rfid_ser_len = rfid_ser_len < 10 ? rfid_ser_len : 10;
263  memcpy(this->rfid_serial_bin, rfid_ser_bin, this->rfid_ser_len);
264  this->name = name;
265  this->lastname = lastname;
266  this->description = description;
267  this->role = role;
268  this->reg_date = reg_date;
269  this->last_login_date = last_login_date;
270  this->created_at_date = created_at_date;
271  this->date_of_birth = date_of_birth;
272 }
273 
275  spdlog::debug("user_cont - User ID: {0}", this->id);
276  spdlog::debug("user_cont - User RFID: {0:x} {1:x} {2:x} {3:x} {4:x} {5:x} {6:x} {7:x} {8:x} {9:x}",
277  this->rfid_serial_bin[0], this->rfid_serial_bin[1], this->rfid_serial_bin[2], this->rfid_serial_bin[3],
278  this->rfid_serial_bin[4], this->rfid_serial_bin[5], this->rfid_serial_bin[6], this->rfid_serial_bin[7],
279  this->rfid_serial_bin[8], this->rfid_serial_bin[9]);
280  spdlog::debug("user_cont - User rfid_ser_len: {0}", this->rfid_ser_len);
281  spdlog::debug("user_cont - User username: {0}", this->username);
282  spdlog::debug("user_cont - User name: {0}", this->name);
283  spdlog::debug("user_cont - User lastname: {0}", this->lastname);
284  spdlog::debug("user_cont - User description: {0}", this->description);
285  spdlog::debug("user_cont - User role: {0}", this->role);
286 
287  char buf[64] = {0};
288  strftime(buf, 64, "%Y-%m-%d %H:%M:%S", &(this->reg_date));
289  spdlog::debug("user_cont - User reg_date: {0}", buf);
290  memset(buf, 0, 64);
291  strftime(buf, 64, "%Y-%m-%d %H:%M:%S", &(this->last_login_date));
292  spdlog::debug("user_cont - User last_login_date: {0}", buf);
293  memset(buf, 0, 64);
294  strftime(buf, 64, "%Y-%m-%d %H:%M:%S", &(this->created_at_date));
295  spdlog::debug("user_cont - User created_at_date: {0}", buf);
296  memset(buf, 0, 64);
297  strftime(buf, 64, "%Y-%m-%d %H:%M:%S", &(this->date_of_birth));
298  spdlog::debug("user_cont - User date_of_birth: {0}", buf);
299 }
300 
301 
302 /*********************************************************************************************************************/
303 /* User_workspace function definitions */
304 /*********************************************************************************************************************/
305 
307  this->user.reset(user);
308  this->measured.reset(new measurement());
309  this->picked.reset(new measurement());
310 }
311 
313  return this->measured.get();
314 }
315 
317  return this->picked.get();
318 }
319 
321  if (tag->serial_size != this->user->rfid_ser_len)
322  return 1;
323 
324  for (int i = 0; i < tag->serial_size; i++) {
325  if (this->user->rfid_serial_bin[i] != tag->serial[i])
326  return 1;
327  }
328 
329  return 0;
330 }
331 
332 
334  return this->user.get() != nullptr;
335 }
336 
338  return this->subuser.get() != nullptr;
339 }
340 
341 std::pair<uint8_t*, uint8_t> user_workspace::get_rfid_serial() {
342  return std::pair<uint8_t*, uint8_t>(this->user->rfid_serial_bin, this->user->rfid_ser_len);
343 }
344 
346  return this->user->id;
347 }
348 
350  return this->user.get();
351 }
352 
354  return this->user->username;
355 }
356 
357 std::string& user_workspace::get_name() {
358  return this->user->name;
359 }
360 
362  return this->user->lastname;
363 }
365  return this->user->description;
366 }
367 
369  return this->user->role;
370 }
371 
373  switch (this->user->role) {
374  case 0:
375  return get_localized_text("GT_USER_ROLE_PAC");
376  case 1:
377  return get_localized_text("GT_USER_ROLE_EMP");
378  case 2:
379  return get_localized_text("GT_USER_ROLE_ADM");
380 
381  default:
382  return get_localized_text("GT_USER_ROLE_ERR");
383  }
384 }
385 
386 std::vector<std::unique_ptr<measurement_header>>& user_workspace::get_user_measur_headers() {
387  if (this->subuser.get() != nullptr) {
388  return this->subuser->measur_headers;
389  } else {
390  return this->user->measur_headers;
391  }
392 }
393 
395  if (this->subuser.get() != nullptr) {
396  return this->subuser.get();
397  } else {
398  return this->user.get();
399  }
400 }
401 
403  if (this->subuser.get() != nullptr) {
404  return this->subuser->id;
405  } else {
406  return this->user->id;
407  }
408 }
409 
411  if (this->subuser.get() != nullptr) {
412  return this->subuser->username;
413  } else {
414  return this->user->username;
415  }
416 }
417 
418 void user_workspace::init_measured(std::vector<double> values, std::tm *start_tm, std::tm *end_tm, unsigned long m_length) {
419  spdlog::debug("user_workspace.cpp - Initing basic measuring parameters");
420  this->measured.reset(new measurement());
421 
422  measurement::init_measuring(this->measured.get(), this, values, start_tm, end_tm, m_length);
423 }
unsigned long measurement_number
const char * get_header_label()
Container for measurement data and (convenience) variables, that are used to show measurement in GUI.
unsigned long measuring_length
static std::pair< double, double > calc_every_x_values_stats(measurement *m)
Calculates the median of medians and avarages of avarages of every X values (X is a defined constant ...
uint8_t value_length
std::string all_val_avg_str
std::string length_str
int compare(measurement *m)
std::vector< double > values
static void prepare_continuous_to_picked(std::vector< measurement > &ms, measurement *picked)
unsigned long value_count
std::tm created_at
HX711::Mass::Unit current_unit
void log_measurement_to_debug()
std::string end_str
void init_convinience_vars(const char *measurer_uname, const char *measuree_uname)
std::string all_val_med_str
std::tm measuring_end
double all_val_med
double all_val_avg
void init_start_end_strings()
static void init_simple_measuring(measurement *m, std::vector< double > &values)
std::string x_val_med_str
unsigned long measuree_id
std::string description
int cont_measurements
static std::pair< double, double > calc_all_values_stats(measurement *m)
Calculates the median and avarage of all values.
unsigned long measurer_id
std::tm measuring_start
std::string start_str
double x_val_avg
double x_val_med
static void init_measuring(measurement *m, user_workspace *uspace, std::vector< double > &values, std::tm *start_tm, std::tm *end_tm, unsigned long m_length)
static void calc_measuring_results(measurement *m)
std::string x_val_avg_str
std::string measurer_uname
void init_value_strings()
std::string measuree_uname
unsigned long measurement_number
Class used as a container for user data, that are selected from database. (and also for insert,...
std::string lastname
uint8_t role
user_cont(unsigned long, uint8_t *, uint8_t, std::string, std::string, std::string, std::string, uint8_t, std::tm, std::tm, std::tm, std::tm)
Construct a new user cont object through value parameters, but this isn't used. Originally inteded fo...
std::string username
void log_user_to_debug()
unsigned long id
std::tm last_login_date
std::tm reg_date
std::tm date_of_birth
unsigned long measure_count
std::tm created_at_date
std::string description
uint8_t rfid_serial_bin[10]
std::string name
uint8_t rfid_ser_len
Container that servers for storing users data and manipulating them.
unsigned long get_user_id()
void init_measured(std::vector< double > values, std::tm *start_tm, std::tm *end_tm, unsigned long m_length)
std::string & get_username()
std::string & get_lastname()
int compare_rfid_serials(rfid_reader::rfid_tag *tag)
std::unique_ptr< user_cont > subuser
user_cont * get_user()
unsigned long get_measured_id()
std::unique_ptr< measurement > measured
std::string & get_description()
measurement * get_last_hx_measuring()
std::vector< std::unique_ptr< measurement_header > > & get_user_measur_headers()
std::string & get_measured_username()
std::unique_ptr< measurement > picked
user_cont * get_measured_user()
const char * get_role_string()
measurement * get_picked_hx_measuring()
std::string & get_name()
std::pair< uint8_t *, uint8_t > get_rfid_serial()
user_workspace(user_cont *user)
Construct a new user workspace object. This can only be done with a user that is logged in.
const char * get_localized_text(const char *key)
Get the localized text object.
RFID tag structure. Stores data read from SPI.
Definition: rfid_reader.h:12
uint8_t serial[10]
Definition: rfid_reader.h:14
#define X_SAMPLES