Torc  0.1
torci2cbus.cpp
Go to the documentation of this file.
1 /* Class TorcI2CBus
2 *
3 * Copyright (C) Mark Kendall 2015-18
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 */
19 
20 // Torc
21 #include "torclogging.h"
22 #include "torccentral.h"
23 #include "torcinput.h"
24 #include "torcoutput.h"
25 #include "torci2cbus.h"
26 
28  : m_address(Address),
29  m_fd(-1)
30 {
31 }
32 
34 
36  : nextTorcI2CDeviceFactory(gTorcI2CDeviceFactory)
37 {
38  gTorcI2CDeviceFactory = this;
39 }
40 
42 {
43  return gTorcI2CDeviceFactory;
44 }
45 
47 {
49 }
50 
52 
55  m_devices()
56 {
57 }
58 
59 void TorcI2CBus::Create(const QVariantMap &Details)
60 {
61  QWriteLocker locker(&m_handlerLock);
62 
63  QVariantMap::const_iterator i = Details.constBegin();
64  for ( ; i != Details.constEnd(); ++i)
65  {
66  // I2C devices can be <sensors> or <outputs> (and both at the same time)
67  if (i.key() != INPUTS_DIRECTORY && i.key() != OUTPUTS_DIRECTORY)
68  continue;
69 
70  QVariantMap i2c = i.value().toMap();
71  QVariantMap::iterator it = i2c.begin();
72  for ( ; it != i2c.end(); ++it)
73  {
74  // look for <i2c>
75  if (it.key() != I2C)
76  continue;
77 
78  QVariantMap devices = it.value().toMap();
79  QVariantMap::iterator it2 = devices.begin();
80  for ( ; it2 != devices.end(); ++it2)
81  {
82  QVariantMap details = it2.value().toMap();
83 
84  // device needs an address
85  if (!details.contains(QStringLiteral("i2caddress")))
86  {
87  LOG(VB_GENERAL, LOG_ERR, QStringLiteral("I2C device '%1' needs <i2caddress>").arg(it2.key()));
88  continue;
89  }
90 
91  bool ok = false;
92  // N.B. assumes hexadecimal 0xXX
93  int address = details.value(QStringLiteral("i2caddress")).toString().toInt(&ok, 16);
94  if (!ok)
95  {
96  LOG(VB_GENERAL, LOG_ERR, QStringLiteral("Failed to parse I2C address from '%1' for device '%2'")
97  .arg(details.value(QStringLiteral("address")).toString(), it2.key()));
98  continue;
99  }
100 
101  // TODO - handle defining the same device in sensors and outputs
102  if (m_devices.contains(address))
103  {
104  LOG(VB_GENERAL, LOG_ERR, QStringLiteral("I2C bus already contains device at 0x%1 - ignoring").arg(address, 0, 16));
105  continue;
106  }
107 
108  TorcI2CDevice* device = nullptr;
110  for ( ; factory; factory = factory->NextFactory())
111  {
112  device = factory->Create(address, it2.key(), details);
113  if (device)
114  break;
115  }
116 
117  if (device)
118  m_devices.insert(address, device);
119  else
120  LOG(VB_GENERAL, LOG_ERR, QStringLiteral("Unable to find handler for I2C device '%1'").arg(it2.key()));
121  }
122  }
123  }
124 }
125 
127 {
128  QWriteLocker locker(&m_handlerLock);
129 
130  qDeleteAll(m_devices);
131  m_devices.clear();
132 }
133 static const QString i2cOutputTypes = QStringLiteral(
134 "<xs:simpleType name='pca9685ChannelNumberType'>\r\n"
135 " <xs:restriction base='xs:integer'>\r\n"
136 " <xs:minInclusive value='0'/>\r\n"
137 " <xs:maxInclusive value='15'/>\r\n"
138 " </xs:restriction>\r\n"
139 "</xs:simpleType>\r\n"
140 "\r\n"
141 "<xs:complexType name='pca9685ChannelType'>\r\n"
142 " <xs:all>\r\n"
143 " <xs:element name='name' type='deviceNameType'/>\r\n"
144 " <xs:element name='username' type='userNameType' minOccurs='0' maxOccurs='1'/>\r\n"
145 " <xs:element name='userdescription' type='userDescriptionType' minOccurs='0' maxOccurs='1'/>\r\n"
146 " <xs:element name='number' type='pca9685ChannelNumberType'/>\r\n"
147 " </xs:all>\r\n"
148 "</xs:complexType>\r\n"
149 "\r\n"
150 "<xs:complexType name='pca9685Type'>\r\n"
151 " <xs:sequence>\r\n"
152 " <!-- NB this enforces the address first -->\r\n"
153 " <xs:element name='i2caddress' type='hexType' minOccurs='1' maxOccurs='1'/>\r\n"
154 " <xs:element name='channel' type='pca9685ChannelType' minOccurs='1' maxOccurs='16'/>\r\n"
155 " </xs:sequence>\r\n"
156 "</xs:complexType>\r\n"
157 "\r\n"
158 "<xs:complexType name='i2cType'>\r\n"
159 " <xs:choice minOccurs='1' maxOccurs='unbounded'>\r\n"
160 " <xs:element name='pca9685' type='pca9685Type'/>\r\n"
161 " </xs:choice>\r\n"
162 "</xs:complexType>\r\n");
163 
164 static const QString i2cOutputs = QStringLiteral(
165 " <xs:element minOccurs='0' maxOccurs='1' name='i2c' type='i2cType'/>\r\n");
166 
167 static const QString i2cUnique = QStringLiteral(
168 " <!-- enforce unique i2c addresses -->\r\n"
169 " <xs:unique name='uniqueI2CAddress'>\r\n"
170 " <xs:selector xpath='.//i2caddress' />\r\n"
171 " <xs:field xpath='.' />\r\n"
172 " </xs:unique>\r\n");
173 
174 
176 {
177  public:
178  void GetXSD(QMultiMap<QString,QString> &XSD) {
179  XSD.insert(XSD_OUTPUTTYPES, i2cOutputTypes);
180  XSD.insert(XSD_OUTPUTS, i2cOutputs);
181  XSD.insert(XSD_UNIQUE, i2cUnique);
182  }
static TorcI2CDeviceFactory * gTorcI2CDeviceFactory
Definition: torci2cbus.h:39
#define XSD_UNIQUE
Definition: torccentral.h:64
static TorcI2CBus * gTorcI2CBus
Definition: torci2cbus.h:51
void Destroy(void)
Definition: torci2cbus.cpp:126
static const QString i2cOutputTypes
Definition: torci2cbus.cpp:133
#define I2C
Definition: torci2cbus.h:12
static const QString i2cOutputs
Definition: torci2cbus.cpp:164
static const QString i2cUnique
Definition: torci2cbus.cpp:167
#define OUTPUTS_DIRECTORY
Definition: torcoutput.h:13
virtual TorcI2CDevice * Create(int Address, const QString &Name, const QVariantMap &Details)=0
void Create(const QVariantMap &Details)
Definition: torci2cbus.cpp:59
TorcI2CXSDFactory TorcI2CXSDFactory
TorcI2CDevice(int Address)
Definition: torci2cbus.cpp:27
#define XSD_OUTPUTTYPES
Definition: torccentral.h:58
#define LOG(_MASK_, _LEVEL_, _STRING_)
Definition: torclogging.h:20
#define XSD_OUTPUTS
Definition: torccentral.h:59
QReadWriteLock m_handlerLock
#define INPUTS_DIRECTORY
Definition: torcinput.h:12
void GetXSD(QMultiMap< QString, QString > &XSD)
Definition: torci2cbus.cpp:178
TorcI2CDeviceFactory * NextFactory(void) const
Definition: torci2cbus.cpp:46
static TorcI2CDeviceFactory * GetTorcI2CDeviceFactory(void)
Definition: torci2cbus.cpp:41
TorcI2CDeviceFactory * nextTorcI2CDeviceFactory
Definition: torci2cbus.h:40