Torc  0.1
torc1wireds18b20.cpp
Go to the documentation of this file.
1 /* Class Torc1WireDS18B20
2 *
3 * This file is part of the Torc project.
4 *
5 * Copyright (C) Mark Kendall 2014-18
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
20 * USA.
21 */
22 
23 // Qt
24 #include <QtGlobal>
25 #include <QTextStream>
26 
27 // Torc
28 #include "torclogging.h"
29 #include "torccentral.h"
30 #include "torc1wirebus.h"
31 #include "torc1wireds18b20.h"
32 
33 #define MIN_READ_INTERVAL 10000
34 
35 Torc1WireReader::Torc1WireReader(const QString &DeviceName)
36  : m_timer(),
37  m_file(QStringLiteral("%1%2/w1_slave").arg(ONE_WIRE_DIRECTORY, DeviceName))
38 {
39  m_timer.setTimerType(Qt::CoarseTimer);
40  m_timer.setSingleShot(true);
41  connect(&m_timer, &QTimer::timeout, this, &Torc1WireReader::Read);
42  // randomise start time for each input
43  m_timer.start(qrand() % MIN_READ_INTERVAL);
44 }
45 
47 {
48  if (!m_file.open(QIODevice::ReadOnly))
49  {
50  LOG(VB_GENERAL, LOG_ERR, QStringLiteral("Failed to read device '%1' (Error #%2: '%3')")
51  .arg(m_file.fileName()).arg(m_file.error()).arg(m_file.errorString()));
52  emit NewTemperature(0.0, false);
53  m_timer.start(MIN_READ_INTERVAL);
54  return;
55  }
56 
57  // read
58  QTextStream text(&m_file);
59 
60  // check crc
61  QString line = text.readLine();
62  if (!line.contains(QStringLiteral("crc")) || !line.contains(QStringLiteral("YES")))
63  {
64  LOG(VB_GENERAL, LOG_ERR, QStringLiteral("CRC check failed for device %1").arg(m_file.fileName()));
65  emit NewTemperature(0.0, false);
66  }
67  else
68  {
69  // read temp
70  line = text.readLine().trimmed();
71  int index = line.lastIndexOf(QStringLiteral("t="));
72  if (index < 0)
73  {
74  LOG(VB_GENERAL, LOG_ERR, QStringLiteral("Failed to parse temperature for device %1").arg(m_file.fileName()));
75  emit NewTemperature(0.0, false);
76  }
77  else
78  {
79  line = line.mid(index + 2);
80  bool ok = false;
81  double temp = line.toDouble(&ok);
82  if (ok)
83  {
84  emit NewTemperature(temp / 1000.0, true);
85  }
86  else
87  {
88  LOG(VB_GENERAL, LOG_ERR, QStringLiteral("Failed to convert temperature for device %1").arg(m_file.fileName()));
89  emit NewTemperature(0.0, false);
90  }
91  }
92  }
93  m_file.close();
94  m_timer.start(MIN_READ_INTERVAL);
95 }
96 
98  : TorcQThread(QStringLiteral("1Wire")),
99  m_parent(Parent),
100  m_reader(nullptr),
101  m_deviceName(DeviceName)
102 {
103 }
104 
106 {
107  if (m_parent)
108  {
109  m_reader = new Torc1WireReader(m_deviceName);
110  connect(m_reader, &Torc1WireReader::NewTemperature, m_parent, &Torc1WireDS18B20::Read);
111  }
112 }
113 
115 {
116  if (m_reader)
117  delete m_reader;
118  m_reader = nullptr;
119  if (m_parent)
120  m_parent->Read(0.0, false);
121 }
122 
123 Torc1WireDS18B20::Torc1WireDS18B20(const QVariantMap &Details)
124  : TorcTemperatureInput(TorcCentral::GetGlobalTemperatureUnits() == TorcCentral::Celsius ? 0.0 : 32.0,
125  TorcCentral::GetGlobalTemperatureUnits() == TorcCentral::Celsius ? -55.0 : -67.0,
126  TorcCentral::GetGlobalTemperatureUnits() == TorcCentral::Celsius ? 125.0 : 257.0,
127  DS18B20NAME, Details),
128  m_deviceId(Details.value(QStringLiteral("wire1serial")).toString()),
129  m_readThread(this, Details.value(QStringLiteral("wire1serial")).toString())
130 {
131  m_readThread.start();
132 }
133 
135 {
136  m_readThread.quit();
137  m_readThread.wait();
138 }
139 
141 {
142  return QStringList() << tr("1Wire DS18B20 Temperature" ) << tr("Serial# %1").arg(m_deviceId);
143 }
144 
145 void Torc1WireDS18B20::Read(double Value, bool Valid)
146 {
147  if (Valid)
148  {
149  // readings are in celsius - convert if needed
150  double value = Value;
153  SetValue(value);
154  }
155  else
156  {
157  SetValid(false);
158  }
159 }
160 
162 {
163  TorcInput* Create(const QString &DeviceType, const QVariantMap &Details)
164  {
165  if (DeviceType == DS18B20NAME)
166  return new Torc1WireDS18B20(Details);
167  return nullptr;
168  }
170 
171 
Torc1WireReadThread(Torc1WireDS18B20 *Parent, const QString &DeviceName)
void SetValid(bool Valid) final
Definition: torcinput.cpp:143
static double CelsiusToFahrenheit(double Value)
QStringList GetDescription(void) override
static TemperatureUnits GetGlobalTemperatureUnits(void)
Definition: torccentral.cpp:58
#define MIN_READ_INTERVAL
void SetValue(double Value) override
Update the inputs value.
Definition: torcinput.cpp:90
void NewTemperature(double Value, double Valid)
void Read(double Value, bool Valid)
double value
Definition: torcdevice.h:60
#define LOG(_MASK_, _LEVEL_, _STRING_)
Definition: torclogging.h:20
void Start(void) override
Torc1WireDS18B20(const QVariantMap &Details)
Torc1WireDS18B20Factory Torc1WireDS18B20Factory
#define ONE_WIRE_DIRECTORY
Definition: torc1wirebus.h:12
A Torc specific wrapper around QThread.
Definition: torcqthread.h:7
Torc1WireReader(const QString &DeviceName)
#define DS18B20NAME
void Finish(void) override