Newer
Older
#include <QTimer>
#include <QtGlobal>
int SHsensor::m_sensors = 0;
bool SHsensor::m_testing = false;
QDateTime * SHsensor::m_testTime = nullptr;
SHsensor * SHsensor::S[SHNodeIdSize * SHSensorIdSize] = {nullptr};
QNetworkAccessManager * SHsensor::m_tasmota = nullptr;
QString SHsensor::m_brutto = NOVALUE;
QString SHsensor::m_netto = NOVALUE;
QStringList SHsensor::m_info = {};
QString SHsensor::m_errcnt_total = NOVALUE;
QString SHsensor::m_errcnt_current = NOVALUE;
QString SHsensor::m_err_solar = NOVALUE;
SHsensor::SHsensor(/* QString name,*/ int nid, SHsensor::SensorType type, QString url) :
m_value(NOVALUE),
m_timestamp(SHsensor::currentTime())
{
if (nid < 0 or nid >= SHNodeIdSize)
throw std::invalid_argument("SHsensor::SHsensor: nid out of range");
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
case SHsensor::none:
m_unit = "?";
m_sensorID = SID_DUMMY;
break;
case SHsensor::tempSensor:
m_unit = "C";
m_sensorID = SID_TEMP;
break;
case SHsensor::powerSensor:
case SHsensor::lightSensor:
m_unit = "W";
m_sensorID = SID_POWER;
break;
case SHsensor::Switch:
m_unit = "";
m_sensorID = SID_RELAY;
break;
case SHsensor::Switch2:
m_unit = "";
m_sensorID = SID_RELAY2;
break;
default:
throw std::invalid_argument("SHsensor::SHsensor: type out of range");
}
// Kontrolle der Zeitstempel
// QTimer *timer = new QTimer(this);
// connect(timer, &QTimer::timeout, this, &SHsensor::checkTimeStamp);
// timer->start(CONTROL_INTERVALL * 1000); // ms
// Zähler für Konsistenz
m_sensors++;
// Hinzufügen:
m_pos = hash(m_nodeID, m_sensorID);
// qDebug() << m_name << pos;
if (S[m_pos] != nullptr)
throw std::invalid_argument("SHsensor::SHsensor: nid=" + QString::number(m_nodeID).toStdString() + "/ sid=" + QString::number(m_sensorID).toStdString() + " not unique");
}
/*
*
*/
SHsensor::~SHsensor()
{
S[m_pos] = nullptr;
m_sensors--;
}
/*
*
*/
bool SHsensor::tasmota() const
{
return (m_url != "");
}
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
/*
*
*/
int SHsensor::sensorID() const
{
return m_sensorID;
}
/*
*
*/
int SHsensor::nodeID() const
{
return m_nodeID;
}
/*
*
*/
QDateTime SHsensor::timestamp() const
{
return m_timestamp;
}
/*
*
*/
QString SHsensor::value() const
{
if (isError())
return ("F" + QString::number((int) m_error));
else
return m_value;
}
/*
*
*/
QString SHsensor::unit() const
{
return m_unit;
}
/*
*
*/
QString SHsensor::name() const
{
}
/*
*
*/
void SHsensor::checkTimeStamp()
{
// qDebug() << "SHsensorBase::checkTimeStamp()";
QDateTime time = m_timestamp.addSecs(CONTROL_INTERVALL);
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
/*
* Nur für Tasmota und Temp
*/
void SHsensor::setNervousTemp(const QString &payload)
{
const int noAvg = 30;
if (payload != NOVALUE) {
float temp = payload.toFloat();
if (T.size() >= noAvg) {
Tsum -= T[0];
T.pop_front();
}
T.push_back(temp);
Tsum += temp;
// Durchschnitt berechnen
int Tint = Tsum/T.size() * 10; // auf eine Nachkommastelle beschränken
m_value = QString::number(Tint / 10.0);
} else {
if (T.size() > 0) {
Tsum -= T[0];
T.pop_front();
}
m_value = NOVALUE;
}
}
/*
*
*/
int SHsensor::sensors()
{
return m_sensors;
}
/*
*
*/
static QString errorTxt(SHsensor::ErrorType error) {
switch (error) {
case SHsensor::ErrorType::noError:
return "";
break;
case SHsensor::ErrorType::noValueError:
return "Kein Wert";
break;
case SHsensor::ErrorType::stupidValueError:
return "Fehlerhafter Wert";
break;
case SHsensor::ErrorType::switchError:
return "Schalter reagiert nicht";
break;
}
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
}
/*
*
*/
QString SHsensor::errorTxt() const
{
return ::errorTxt(m_error);
}
/*
*
*/
QString SHsensor::prevErrorTxt() const
{
return ::errorTxt(m_previousError);
}
/*
*
*/
void SHsensor::poll() const
{
if (not tasmota())
return;
QString cmd = "cm?cmnd=Status0";
QString urlRequest = m_url + "/" + cmd;
QNetworkRequest request;
// qDebug() << "polling tasmota" << name();
request.setUrl(QUrl(urlRequest));
m_tasmota->get(request);
}
/*
*
*/
void SHsensor::setValue(const QString &payload)
{
// qDebug() << "setValue::setValue(nid=" << m_nodeID << "sid=" << m_sensorID << "payl=" << payload << ")";
// qDebug() << "-> 1 isError" << isError();
// qDebug() << m_errorIndicated << m_error << m_previousError;
if (payl != NOVALUE) {
m_timestamp = SHsensor::currentTime();
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
resetError(noValueError);
} else {
setError(noValueError);
}
// Konsistenz-Check für bestimmte Sensoren:
if (payl != NOVALUE) {
float fvalue;
switch (m_type) {
case SHsensor::tempSensor:
fvalue = payl.toFloat();
if (fvalue < 0.0 or fvalue > 45.0) {
setError(stupidValueError);
payl = NOVALUE;
} else {
resetError(stupidValueError);
}
break;
case SHsensor::powerSensor:
fvalue = payl.toFloat();
if (fvalue < 0.0) {
setError(stupidValueError);
payl = NOVALUE;
} else {
resetError(stupidValueError);
}
break;
case SHsensor::lightSensor:
case SHsensor::none:
case SHsensor::Switch:
case SHsensor::Switch2:
break;
default:
throw std::invalid_argument("SHsensor::SHsensor: type out of range");
}
// if (tasmota() and m_type == SHsensor::tempSensor) // wird nicht mehr gebraucht
// setNervousTemp(payl);
// else
m_value = payl;
}
/*
*
*/
bool SHsensor::isTesting()
{
return m_testing;
}
/*
*
*/
void SHsensor::setTesting()
{
m_testTime = new QDateTime;
void SHsensor::setTestTime(const QDateTime &time)
{
assert(m_testing);
*m_testTime = time;
}
/*
*
*/
QDateTime SHsensor::currentTime()
{
if (m_testing) {
assert(m_testTime != nullptr);
return *m_testTime;
} else {
return QDateTime::currentDateTime();
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
/*
*
*/
void SHsensor::displayMem(QString comment)
{
QString command = "top -b -o +%MEM | head -n 10 | grep SHserver";
// QString command = "ssh pi@192.168.178.23 \"top -b -o +%MEM | head -n 10 | grep SHserver\"";
FILE* fp;
char* result = NULL;
size_t len = 0;
fflush(NULL);
fp = popen(command.toStdString().c_str(), "r");
if (fp == NULL) {
qDebug() << "Cannot execute command:" << command;
return;
}
QString qs;
while(getline(&result, &len, fp) != -1) {
// fputs(result, stdout);
qs += result;
}
// qDebug() << "result=" << result;
// qDebug() << "qs=" << qs;
free(result);
fflush(fp);
if (pclose(fp) != 0) {
perror("Cannot close stream.\n");
}
QStringList qsl = qs.split(' '/* QT6, Qt::SkipEmptyParts*/);
// qDebug() << qsl;
static int index = 0;
static int cnt = 0;
while (qsl[index] == "" or cnt < 5) {
index++;
if (qsl[index] != "")
cnt++;
}
static int prevsize = 0;
int memsize = qsl[index].toInt();
if (memsize > prevsize)
qDebug() << "#" << comment << "memsize" << memsize << ">" << prevsize;
else
qDebug() << "#" << comment << "memsize" << memsize;
prevsize = memsize;
}
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
/*
*
*/
void SHsensor::checkTimeStampALL()
{
for (auto s : S)
if (s != nullptr)
s->checkTimeStamp();
}
/*
* static
*/
int SHsensor::hash(int nid, int sid)
{
if (nid < 0 or nid >= SHNodeIdSize or sid < 0 or sid >= SHSensorIdSize) {
qDebug() << "hash out of range" << nid << sid;
return -1;
}
// assert(nid >= 0);
// assert(nid < SHNodeIdSize);
// assert(sid >= 0);
// assert(sid < SHSensorIdSize);
return nid * SHSensorIdSize + sid;
}
/*
*
*/
void SHsensor::printALL() {
static int errcnt_total = 0;
int errcnt = 0;
bool errsolar = false;
// SHsensor::displayMem("SHsensor::printALL");
QString line = QDate::currentDate().toString("dd.MM.yyyy") + " " + QTime::currentTime().toString("hh:mm:ss");
line = line + " " + s->name() + ":" + s->value() + s->unit();
// qDebug() << s->name() << s->unit() << s->value() << s->timestamp();
if (s->isError()) {
errcnt++;
if (s->type() == SHsensor::SensorType::lightSensor)
errsolar = true;
}
// SHsensor::displayMem("SHsensor::printALL ENDE");
SHsensor::setErrorInfo(errcnt_total, errcnt, errsolar);
// SHsensor::displayMem("SHsensor::pollTasmota");
static QVector<SHsensor*> T; // nur Tasmota und keine doppelten Namen
static bool firstRun = true;
if (firstRun) { // T einmalig erstellen
for (auto s : S)
if (s != nullptr and s->tasmota()) {
bool found = false;
for (auto t : T)
if (t->name() == s->name())
found = true;
if (not found)
T.push_back(s);
}
firstRun = false;
}
for (auto s : T)
if (s != nullptr)
s->poll();
// SHsensor::displayMem("SHsensor::pollTasmota ENDE");
/*
*
*/
void SHsensor::setValue(int nid, int sid, const QString &payl)
{
// qDebug() << "static SHsensor::setValue(nid=" << nid << "sid=" << sid << "payl=" << payl << ")";
// qDebug() << "pos" << pos << "S[pos]" << S[pos];
if (pos != -1 and S[pos] != nullptr) {
// qDebug() << "call setValue" << nid << sid;
S[pos]->setValue(payl);
}
}
/*
*
*/
QString SHsensor::getValue(int nid, int sid)
{
int pos = hash(nid, sid);
if (pos == -1 or S[pos] == nullptr)
return "ERRnoValue";
else
return S[pos]->value();
}
/*
*
*/
QString SHsensor::name(int nid)
{
static QString N[SHNodeIdSize] = {
"Gateway",
"HW_40", // Heißwasser Stufe 1
"Kamin", // große Heizung im Wohnzimmer, Stufe 2 gibt es nicht mehr
"Sonne", // Lichtsensor
"HW_60", // Heißwasser Stufe 2
"Tür", // Fußboden-Heizung im Wohnzimmer
"Klima", // Klimaanlage
"Wasch", // Waschmaschine
"Wohn", // Thermometer im Wohnzimmer
"Repeater2", // Repeater
"eCar", // E-Auto
"T Bad unten", // Thermometer Bad unten
"T Bad oben", // Thermometer Bad oben
"WandLR", // Wohnzimmer-Wand links+rechts
"WandM", // Wohnzimmer-Wand mitte
"Strom", // Zentraler Strommesser
"Dummy" // zum Testen neuer Knoten -- immer ganz hinten
};
if (nid < 0 or nid >= SHNodeIdSize)
return "#ERR-NAME#";
return N[nid];
}
void SHsensor::initStatics(QNetworkAccessManager *tasmota)
for (int i=0; i < SHNodeIdSize; i++) {
if (NID.contains(name(i)))
throw std::invalid_argument("ERROR double use of " + name(i).toStdString());
NID[name(i)] = i;
}
}
/*
*
*/
int SHsensor::nid(QString name)
{
if (NID.contains(name))
return NID[name];
else
return -1;
}
SHsensor::ErrorType SHsensor::error() const
{
return m_error;
}
/*
*
*/
void SHsensor::setError(ErrorType newError)
{
if (not isError()) { // keine Aktion falls es bereits einen Fehler gibt
m_error = newError;
m_errorTime = m_timestamp;
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
}
}
/*
*
*/
void SHsensor::resetError(ErrorType oldError)
{
if (m_error == oldError) {
m_previousError = m_error;
m_previousErrorTime = m_errorTime;
m_error = noError;
}
}
/*
*
*/
bool SHsensor::isError() const
{
return (m_error != noError);
}
/*
*
*/
SHsensor::SensorType SHsensor::type() const
{
return m_type;
}
/*
*
*/
void SHsensor::setSolarInfo(int newBrutto, int newNetto, const QStringList &newInfo)
SHsensor::m_brutto = QString::number(newBrutto);
SHsensor::m_netto = QString::number(newNetto);
SHsensor::m_info = newInfo;
}
/*
*
*/
void SHsensor::setErrorInfo(int errcnt_total, int errcnt_current, bool err_solar)
SHsensor::m_errcnt_total = QString::number(errcnt_total);
SHsensor::m_errcnt_current = QString::number(errcnt_current);
if (err_solar)
SHsensor::m_err_solar = "ERROR";
else
SHsensor::m_err_solar = "OK";
}
/*
*
*/
QStringList SHsensor::getInfo() {
QStringList qsl = {
SHsensor::m_brutto, SHsensor::m_netto, SHsensor::m_info.join(";"), // solar
SHsensor::m_errcnt_total, SHsensor::m_errcnt_current, SHsensor::m_err_solar // errors
};
return qsl;
const QString &SHsensor::url() const
{
return m_url;
}