Merge PR #289: Add an I2C hardware resource

modbusclient
Jenkins nymea 2020-06-07 19:16:23 +02:00
commit 917c58d145
13 changed files with 711 additions and 8 deletions

View File

@ -0,0 +1,278 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
*
* Copyright 2013 - 2020, nymea GmbH
* Contact: contact@nymea.io
*
* This file is part of nymea.
* This project including source code and documentation is protected by
* copyright law, and remains the property of nymea GmbH. All rights, including
* reproduction, publication, editing and translation, are reserved. The use of
* this project is subject to the terms of a license agreement to be concluded
* with nymea GmbH in accordance with the terms of use of nymea GmbH, available
* under https://nymea.io/license
*
* GNU Lesser General Public License Usage
* Alternatively, this project may be redistributed and/or modified under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation; version 3. This project is distributed in the hope that
* it will be useful, but WITHOUT ANY WARRANTY; without even the implied
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this project. If not, see <https://www.gnu.org/licenses/>.
*
* For any further details and any questions please contact us under
* contact@nymea.io or see our FAQ/Licensing Information on
* https://nymea.io/license/faq
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#include "i2cmanagerimplementation.h"
#include "hardware/i2c/i2cdevice.h"
#include "loggingcategories.h"
#include <QDir>
#include <QtConcurrent/QtConcurrentRun>
#include <sys/ioctl.h>
#include <unistd.h>
#include <linux/i2c-dev.h>
namespace nymeaserver {
I2CManagerImplementation::I2CManagerImplementation(QObject *parent) : I2CManager(parent)
{
m_pollTimer.setInterval(200);
m_pollTimer.setSingleShot(true);
connect(&m_pollTimer, &QTimer::timeout, this, &I2CManagerImplementation::nextCycle);
}
I2CManagerImplementation::~I2CManagerImplementation()
{
m_watcher.waitForFinished();
}
QStringList nymeaserver::I2CManagerImplementation::availablePorts() const
{
return QDir("/sys/class/i2c-adapter/").entryList(QDir::Dirs | QDir::NoDotAndDotDot, QDir::Name);
}
QList<I2CScanResult> nymeaserver::I2CManagerImplementation::scanRegisters(const QString &portName)
{
QList<I2CScanResult> ret;
QList<QString> portsToBeScanned = {portName};
if (portName.isEmpty()) {
portsToBeScanned = availablePorts();
}
m_mutex.lock();
foreach (const QString &p, portsToBeScanned) {
QFile f("/dev/" + p);
if (!f.open(QFile::ReadWrite)) {
qCWarning(dcI2C()) << "Failed to open I2C port" << p << "for scanning";
continue;
}
for (int address = 0x03; address <= 0x77; address++) {
// First check if selecting the slave address is possible at all
if (ioctl(f.handle(), I2C_SLAVE, address) >= 0) {
char probe = 0x00;
long res = 0;
// This is how the kernels i2cdetect scans:
// Try to read from address 0x30 - 0x35 and 0x50 to 0x5F and write to the others.
if ((address >= 0x30 && address <= 0x37)
|| (address >= 0x50 && address <= 0x5F)) {
res = read(f.handle(), &probe, 1);
} else {
res = write(f.handle(), &probe, 1);
}
if (res == 1) {
qCDebug(dcI2C()) << QString("Found slave device at address 0x%1").arg(address, 0, 16);
I2CScanResult result;
result.portName = p;
result.address = address;
ret.append(result);
}
}
}
}
m_mutex.unlock();
return ret;
}
bool I2CManagerImplementation::open(I2CDevice *i2cDevice)
{
if (m_openFiles.contains(i2cDevice)) {
qCWarning(dcI2C()) << "I2C device" << i2cDevice << "already opened.";
return false;
}
QString fileName = "/dev/" + i2cDevice->portName();
foreach (I2CDevice *d, m_openFiles.keys()) {
if (d->portName() == i2cDevice->portName()) {
// Another I2CDevice opened this file already. We'll hook into that.
m_mutex.lock();
m_openFiles.insert(i2cDevice, m_openFiles.value(d));
m_mutex.unlock();
return true;
}
}
if (!QFile::exists(fileName)) {
qCWarning(dcI2C()) << "The I2C port does not exist:" << i2cDevice->portName();
return false;
}
QFile *file = new QFile("/dev/" + i2cDevice->portName(), this);
if (!file->open(QFile::ReadWrite)) {
qCWarning(dcI2C()) << "Error opening I2C port" << i2cDevice << "Error:" << file->errorString();
delete file;
return false;
}
m_mutex.lock();
m_openFiles.insert(i2cDevice, file);
m_mutex.unlock();
return true;
}
bool I2CManagerImplementation::startReading(I2CDevice *i2cDevice, int interval)
{
QMutexLocker locker(&m_mutex);
if (!m_openFiles.contains(i2cDevice)) {
qCWarning(dcI2C()) << "I2CDevice not open. Cannot start reading.";
return false;
}
qCDebug(dcI2C()) << "Starting to poll I2C device" << i2cDevice;
ReadingInfo readingInfo;
readingInfo.interval = interval;
m_readers.insert(i2cDevice, readingInfo);
if (!m_pollTimer.isActive()) {
m_pollTimer.start();
}
return true;
}
void I2CManagerImplementation::stopReading(I2CDevice *i2cDevice)
{
QMutexLocker locker(&m_mutex);
m_readers.remove(i2cDevice);
if (m_readers.count() == 0) {
m_pollTimer.stop();
}
}
bool I2CManagerImplementation::writeData(I2CDevice *i2cDevice, const QByteArray &data)
{
m_writeQueueMutex.lock();
WritingInfo info;
info.device = i2cDevice;
info.data = data;
m_writeQueue.append(info);
m_writeQueueMutex.unlock();
return true;
}
void I2CManagerImplementation::close(I2CDevice *i2cDevice)
{
bool isInUse = false;
m_mutex.lock();
if (m_readers.contains(i2cDevice)) {
isInUse = true;
}
m_mutex.unlock();
if (isInUse) {
stopReading(i2cDevice);
}
int refCount = 0;
foreach (I2CDevice* d, m_openFiles.keys()) {
if (d->portName() == i2cDevice->portName()) {
refCount++;
}
}
if (refCount == 0) {
m_mutex.lock();
QFile *f = m_openFiles.take(i2cDevice);
m_mutex.unlock();
f->close();
f->deleteLater();
}
}
void I2CManagerImplementation::nextCycle()
{
QFuture<void> future = QtConcurrent::run([this](){
// Copy the write queue to open it up as fast as possible for others to append new entries
m_writeQueueMutex.lock();
QList<WritingInfo> writeQueue = m_writeQueue;
m_writeQueue.clear();
m_writeQueueMutex.unlock();
m_mutex.lock();
foreach (const WritingInfo &info, writeQueue) {
I2CDevice *i2cDevice = info.device;
int fd = m_openFiles.value(i2cDevice)->handle();
if (fd == -1) {
qCWarning(dcI2C()) << "I2C device" << i2cDevice << "not opened. Cannot write to it.";
continue;
}
if (ioctl(fd, I2C_SLAVE, i2cDevice->address()) < 0) {
qCWarning(dcI2C()) << "Cannot select I2C slave address for I2C device" << i2cDevice;
continue;
}
qCDebug(dcI2C()) << "Writing to I2C device" << i2cDevice;
bool success = i2cDevice->writeData(fd, info.data);
QMetaObject::invokeMethod(i2cDevice, "dataWritten", Qt::QueuedConnection, Q_ARG(bool, success));
}
foreach (I2CDevice *i2cDevice, m_readers.keys()) {
ReadingInfo readingInfo = m_readers.value(i2cDevice);
if (readingInfo.lastReading.addMSecs(readingInfo.interval) > QDateTime::currentDateTime()) {
continue;
}
int fd = m_openFiles.value(i2cDevice)->handle();
if (fd == -1) {
qCWarning(dcI2C()) << "I2C device" << i2cDevice << "not opened. Cannot read.";
continue;
}
if (ioctl(fd, I2C_SLAVE, i2cDevice->address()) < 0) {
qCWarning(dcI2C()) << "Cannot select I2C slave address for I2C device" << i2cDevice;
continue;
}
qCDebug(dcI2C()) << "Reading I2C device" << i2cDevice;
QByteArray data = i2cDevice->readData(fd);
m_readers[i2cDevice].lastReading = QDateTime::currentDateTime();
QMetaObject::invokeMethod(i2cDevice, "readingAvailable", Qt::QueuedConnection, Q_ARG(QByteArray, data));
}
m_mutex.unlock();
});
m_watcher.setFuture(future);
connect(&m_watcher, SIGNAL(finished()), &m_pollTimer, SLOT(start()));
}
}

View File

@ -0,0 +1,95 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
*
* Copyright 2013 - 2020, nymea GmbH
* Contact: contact@nymea.io
*
* This file is part of nymea.
* This project including source code and documentation is protected by
* copyright law, and remains the property of nymea GmbH. All rights, including
* reproduction, publication, editing and translation, are reserved. The use of
* this project is subject to the terms of a license agreement to be concluded
* with nymea GmbH in accordance with the terms of use of nymea GmbH, available
* under https://nymea.io/license
*
* GNU Lesser General Public License Usage
* Alternatively, this project may be redistributed and/or modified under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation; version 3. This project is distributed in the hope that
* it will be useful, but WITHOUT ANY WARRANTY; without even the implied
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this project. If not, see <https://www.gnu.org/licenses/>.
*
* For any further details and any questions please contact us under
* contact@nymea.io or see our FAQ/Licensing Information on
* https://nymea.io/license/faq
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#ifndef I2CMANAGERIMPLEMENTATION_H
#define I2CMANAGERIMPLEMENTATION_H
#include "hardware/i2c/i2cmanager.h"
#include <QObject>
#include <QMutex>
#include <QTimer>
#include <QHash>
#include <QFuture>
#include <QFutureWatcher>
#include <QDateTime>
class QFile;
namespace nymeaserver {
class I2CManagerImplementation : public I2CManager
{
Q_OBJECT
public:
explicit I2CManagerImplementation(QObject *parent = nullptr);
~I2CManagerImplementation();
QStringList availablePorts() const override;
QList<I2CScanResult> scanRegisters(const QString &portName) override;
bool open(I2CDevice *i2cDevice) override;
bool startReading(I2CDevice *i2cDevice, int interval = 1000) override;
void stopReading(I2CDevice *i2cDevice) override;
bool writeData(I2CDevice *i2cDevice, const QByteArray &data) override;
void close(I2CDevice *i2cDevice) override;
private slots:
void nextCycle();
private:
class ReadingInfo {
public:
int interval;
QDateTime lastReading;
};
class WritingInfo {
public:
QByteArray data;
I2CDevice *device;
};
QMutex m_mutex;
QHash<I2CDevice*, ReadingInfo> m_readers;
QHash<I2CDevice*, QFile*> m_openFiles;
QMutex m_writeQueueMutex;
QList<WritingInfo> m_writeQueue;
QFutureWatcher<void> m_watcher;
QTimer m_pollTimer;
};
}
#endif // I2CMANAGERIMPLEMENTATION_H

View File

@ -41,6 +41,7 @@
#include "hardware/radio433/radio433brennenstuhl.h"
#include "hardware/bluetoothlowenergy/bluetoothlowenergymanagerimplementation.h"
#include "hardware/network/mqtt/mqttproviderimplementation.h"
#include "hardware/i2c/i2cmanagerimplementation.h"
namespace nymeaserver {
@ -67,8 +68,11 @@ HardwareManagerImplementation::HardwareManagerImplementation(Platform *platform,
// Bluetooth LE
m_bluetoothLowEnergyManager = new BluetoothLowEnergyManagerImplementation(m_pluginTimerManager->registerTimer(10), this);
m_i2cManager = new I2CManagerImplementation(this);
qCDebug(dcHardware()) << "Hardware manager initialized successfully";
// Enable all the resources
setResourceEnabled(m_pluginTimerManager, true);
setResourceEnabled(m_radio433, true);
@ -127,4 +131,9 @@ MqttProvider *HardwareManagerImplementation::mqttProvider()
return m_mqttProvider;
}
I2CManager *HardwareManagerImplementation::i2cManager()
{
return m_i2cManager;
}
}

View File

@ -37,14 +37,6 @@
#include "hardwaremanager.h"
class Radio433;
class UpnpDiscovery;
class PluginTimerManager;
class NetworkAccessManager;
class UpnpDeviceDescriptor;
class PlatformZeroConfController;
class BluetoothLowEnergyManager;
namespace nymeaserver {
class Platform;
@ -65,6 +57,7 @@ public:
PlatformZeroConfController *zeroConfController() override;
BluetoothLowEnergyManager *bluetoothLowEnergyManager() override;
MqttProvider *mqttProvider() override;
I2CManager * i2cManager() override;
private:
QNetworkAccessManager *m_networkAccessManager = nullptr;
@ -78,6 +71,7 @@ private:
UpnpDiscovery *m_upnpDiscovery = nullptr;
BluetoothLowEnergyManager *m_bluetoothLowEnergyManager = nullptr;
MqttProvider *m_mqttProvider = nullptr;
I2CManager *m_i2cManager = nullptr;
};
}

View File

@ -88,6 +88,7 @@ HEADERS += nymeacore.h \
hardware/network/upnp/upnpdiscoveryreplyimplementation.h \
hardware/network/mqtt/mqttproviderimplementation.h \
hardware/network/mqtt/mqttchannelimplementation.h \
hardware/i2c/i2cmanagerimplementation.h \
debugserverhandler.h \
tagging/tagsstorage.h \
tagging/tag.h \
@ -165,6 +166,7 @@ SOURCES += nymeacore.cpp \
hardware/network/upnp/upnpdiscoveryreplyimplementation.cpp \
hardware/network/mqtt/mqttproviderimplementation.cpp \
hardware/network/mqtt/mqttchannelimplementation.cpp \
hardware/i2c/i2cmanagerimplementation.cpp \
debugserverhandler.cpp \
tagging/tagsstorage.cpp \
tagging/tag.cpp \

View File

@ -0,0 +1,118 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
*
* Copyright 2013 - 2020, nymea GmbH
* Contact: contact@nymea.io
*
* This file is part of nymea.
* This project including source code and documentation is protected by
* copyright law, and remains the property of nymea GmbH. All rights, including
* reproduction, publication, editing and translation, are reserved. The use of
* this project is subject to the terms of a license agreement to be concluded
* with nymea GmbH in accordance with the terms of use of nymea GmbH, available
* under https://nymea.io/license
*
* GNU Lesser General Public License Usage
* Alternatively, this project may be redistributed and/or modified under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation; version 3. This project is distributed in the hope that
* it will be useful, but WITHOUT ANY WARRANTY; without even the implied
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this project. If not, see <https://www.gnu.org/licenses/>.
*
* For any further details and any questions please contact us under
* contact@nymea.io or see our FAQ/Licensing Information on
* https://nymea.io/license/faq
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#include "i2cdevice.h"
#include "i2cmanager.h"
#include <QDebug>
/*! \fn QByteArray I2CDevice::readData(int fileDescriptor);
Reimplement this when implementing reading communication with an I2C device.
This method will be called repeatedly as soon as the I2CManager is instructed to start
reading from this device. Read the current value from the device, e.g. a sensor reading
and return the value.
The given file descriptor will already be opened, the I2C slave address already be
selected. The only task is to read the current value. Often that consists of a
write operation to configure registers on the device followed by a read operation.
IMPORTANT: This method will be called from a different thread. This means that you
are free to perform blocking operations, including calling QThread::msleep() but it
also implies that you must not access other members of the class if they may be
accessed from code outside of this method. If you absolutely must do so, make sure
to use mutexes (e.g. QMutex) accordingly.
*/
/*! \fn bool I2CDevice::writeData(int fileDescriptor, const QByteArray &data);
Reimplement this when implementing writing communication with an I2C device.
This method will be called when I2CManager::writeData(I2CDevice *device, const QByteArray &data)
is called. The data to be written is copied and passed on to this method.
The given file descriptor will already be opened, the I2C slave address already be
selected. The only task is to write the data to it. Often that consists of a
write operation to configure registers on the device followed by another write operation
to write the actual data.
IMPORTANT: This method will be called from a different thread. This means that you
are free to perform blocking operations, including calling QThread::msleep() but it
also implies that you must not access other members of the class if they may be
accessed from code outside of this method. If you absolutely must do so, make sure
to use mutexes (e.g. QMutex) accordingly.
*/
/*! Constructs an I2CDevice with the given portName and address. The \a portName
must match the file name of /dev, for example "i2c-0" for /dev/i2c-0. The
\a address describes the I2C slave address for this device.
I2CManager::scanRegisters() can be used to scan for available I2C devices connected
to the system.
*/
I2CDevice::I2CDevice(const QString &portName, int address, QObject *parent):
QObject(parent),
m_portName(portName),
m_address(address)
{
}
I2CDevice::~I2CDevice()
{
}
/*! Returns the port name of this I2C device. */
QString I2CDevice::portName() const
{
return m_portName;
}
/*! Returns the address of this I2C device. */
int I2CDevice::address() const
{
return m_address;
}
QByteArray I2CDevice::readData(int fileDescriptor)
{
Q_UNUSED(fileDescriptor)
return QByteArray();
}
bool I2CDevice::writeData(int fileDescriptor, const QByteArray &data)
{
Q_UNUSED(fileDescriptor)
Q_UNUSED(data)
return false;
}
QDebug operator<<(QDebug debug, const I2CDevice *i2cDevice)
{
debug.nospace() << "I2CDevice(Port: " << i2cDevice->portName() << ", Address: 0x" << QString::number(i2cDevice->address(), 16) << ")";
return debug.space();
}

View File

@ -0,0 +1,61 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
*
* Copyright 2013 - 2020, nymea GmbH
* Contact: contact@nymea.io
*
* This file is part of nymea.
* This project including source code and documentation is protected by
* copyright law, and remains the property of nymea GmbH. All rights, including
* reproduction, publication, editing and translation, are reserved. The use of
* this project is subject to the terms of a license agreement to be concluded
* with nymea GmbH in accordance with the terms of use of nymea GmbH, available
* under https://nymea.io/license
*
* GNU Lesser General Public License Usage
* Alternatively, this project may be redistributed and/or modified under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation; version 3. This project is distributed in the hope that
* it will be useful, but WITHOUT ANY WARRANTY; without even the implied
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this project. If not, see <https://www.gnu.org/licenses/>.
*
* For any further details and any questions please contact us under
* contact@nymea.io or see our FAQ/Licensing Information on
* https://nymea.io/license/faq
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#ifndef I2CDEVICE_H
#define I2CDEVICE_H
#include <QObject>
class I2CDevice : public QObject
{
Q_OBJECT
public:
explicit I2CDevice(const QString &portName, int address, QObject *parent = nullptr);
virtual ~I2CDevice();
QString portName() const;
int address() const;
virtual QByteArray readData(int fileDescriptor);
virtual bool writeData(int fileDescriptor, const QByteArray &data);
signals:
void readingAvailable(const QByteArray &data);
void dataWritten(bool success);
private:
QString m_portName;
int m_address;
};
QDebug operator<<(QDebug debug, const I2CDevice *i2cDevice);
#endif // I2CDEVICE_H

View File

@ -0,0 +1,78 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
*
* Copyright 2013 - 2020, nymea GmbH
* Contact: contact@nymea.io
*
* This file is part of nymea.
* This project including source code and documentation is protected by
* copyright law, and remains the property of nymea GmbH. All rights, including
* reproduction, publication, editing and translation, are reserved. The use of
* this project is subject to the terms of a license agreement to be concluded
* with nymea GmbH in accordance with the terms of use of nymea GmbH, available
* under https://nymea.io/license
*
* GNU Lesser General Public License Usage
* Alternatively, this project may be redistributed and/or modified under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation; version 3. This project is distributed in the hope that
* it will be useful, but WITHOUT ANY WARRANTY; without even the implied
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this project. If not, see <https://www.gnu.org/licenses/>.
*
* For any further details and any questions please contact us under
* contact@nymea.io or see our FAQ/Licensing Information on
* https://nymea.io/license/faq
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#include "i2cmanager.h"
/*! \fn QStringList I2CManager::availablePorts() const
Lists the available I2C ports in the system.
*/
/*! \fn QList<I2CScanResult> I2CManager::scanRegisters(const QString &portName = QString())
Scans the I2C systems for connected devices. If \a portName is given, only this port
will be scanned. If \a portName is empty, all available ports in the system will be
scanned.
*/
/*! \fn bool I2CManager::open(I2CDevice *i2cDevice)
Open the given I2CDevice. After reimplementing an I2CDevice, this method can be used
to open the device. Returns false if opening fails, for example because of missing
permissions or if the given \ai2cDevice is not valid, for example because of a bad
port name or slave address.
*/
/*! \fn bool I2CManager::startReading(I2CDevice *i2cDevice, int interval = 1000)
Start reading from the given \a i2cDevice. When calling this, the I2CManager will start
polling the given \a i2cDevice. Optionally, the interface can be given.
Note that the interval might not be met, for example if the device is busy by other
readers.
The given \a i2cDevice is required to be opened first.
*/
/*! \fn void I2CManager::stopReading(I2CDevice *i2cDevice)
Stops reading from the given \a i2cDevice.
*/
/*! \fn bool I2CManager::writeData(I2CDevice *i2cDevice, const QByteArray &data)
Write the given \a data to the given \a i2cDevice.
The data will be put into a write buffer and will be written to the device
in a different thread when the i2c device is available.
The given \a i2cDevice is required to be opened first.
*/
/*! \fn void I2CManager::close(I2CDevice *i2cDevice)
Closes the giben \a i2cDevice. If reading are still active for this device,
stopReading() will be called implicitly.
*/
I2CManager::I2CManager(QObject *parent):
QObject(parent)
{
}

View File

@ -0,0 +1,60 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
*
* Copyright 2013 - 2020, nymea GmbH
* Contact: contact@nymea.io
*
* This file is part of nymea.
* This project including source code and documentation is protected by
* copyright law, and remains the property of nymea GmbH. All rights, including
* reproduction, publication, editing and translation, are reserved. The use of
* this project is subject to the terms of a license agreement to be concluded
* with nymea GmbH in accordance with the terms of use of nymea GmbH, available
* under https://nymea.io/license
*
* GNU Lesser General Public License Usage
* Alternatively, this project may be redistributed and/or modified under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation; version 3. This project is distributed in the hope that
* it will be useful, but WITHOUT ANY WARRANTY; without even the implied
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this project. If not, see <https://www.gnu.org/licenses/>.
*
* For any further details and any questions please contact us under
* contact@nymea.io or see our FAQ/Licensing Information on
* https://nymea.io/license/faq
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#ifndef I2CMANAGER_H
#define I2CMANAGER_H
#include <QObject>
class I2CDevice;
struct I2CScanResult {
QString portName;
int address;
};
class I2CManager : public QObject
{
Q_OBJECT
public:
I2CManager(QObject *parent = nullptr);
virtual ~I2CManager() = default;
virtual QStringList availablePorts() const = 0;
virtual QList<I2CScanResult> scanRegisters(const QString &portName = QString()) = 0;
virtual bool open(I2CDevice *i2cDevice) = 0;
virtual bool startReading(I2CDevice *i2cDevice, int interval = 1000) = 0;
virtual void stopReading(I2CDevice *i2cDevice) = 0;
virtual bool writeData(I2CDevice *i2cDevice, const QByteArray &data) = 0;
virtual void close(I2CDevice *i2cDevice) = 0;
};
#endif // I2CMANAGER_H

View File

@ -41,6 +41,7 @@ class UpnpDeviceDescriptor;
class PlatformZeroConfController;
class BluetoothLowEnergyManager;
class MqttProvider;
class I2CManager;
class HardwareResource;
class HardwareManager : public QObject
@ -59,6 +60,7 @@ public:
virtual PlatformZeroConfController *zeroConfController() = 0;
virtual BluetoothLowEnergyManager *bluetoothLowEnergyManager() = 0;
virtual MqttProvider *mqttProvider() = 0;
virtual I2CManager *i2cManager() = 0;
protected:
void setResourceEnabled(HardwareResource* resource, bool enabled);

View File

@ -56,6 +56,8 @@ HEADERS += \
hardware/bluetoothlowenergy/bluetoothlowenergydevice.h \
hardware/bluetoothlowenergy/bluetoothdiscoveryreply.h \
hardware/bluetoothlowenergy/bluetoothlowenergymanager.h \
hardware/i2c/i2cmanager.h \
hardware/i2c/i2cdevice.h \
coap/coap.h \
coap/coappdu.h \
coap/coapoption.h \
@ -133,6 +135,8 @@ SOURCES += \
hardware/bluetoothlowenergy/bluetoothlowenergymanager.cpp \
hardware/bluetoothlowenergy/bluetoothlowenergydevice.cpp \
hardware/bluetoothlowenergy/bluetoothdiscoveryreply.cpp \
hardware/i2c/i2cmanager.cpp \
hardware/i2c/i2cdevice.cpp \
coap/coap.cpp \
coap/coappdu.cpp \
coap/coapoption.cpp \

View File

@ -72,6 +72,7 @@ Q_LOGGING_CATEGORY(dcBluetoothServer, "BluetoothServer")
Q_LOGGING_CATEGORY(dcBluetoothServerTraffic, "BluetoothServerTraffic")
Q_LOGGING_CATEGORY(dcMqtt, "Mqtt")
Q_LOGGING_CATEGORY(dcTranslations, "Translations")
Q_LOGGING_CATEGORY(dcI2C, "I2C")
static QFile s_logFile;

View File

@ -75,6 +75,7 @@ Q_DECLARE_LOGGING_CATEGORY(dcBluetoothServerTraffic)
Q_DECLARE_LOGGING_CATEGORY(dcMqtt)
Q_DECLARE_LOGGING_CATEGORY(dcTranslations)
Q_DECLARE_LOGGING_CATEGORY(dcCoap)
Q_DECLARE_LOGGING_CATEGORY(dcI2C)
/*
Installs a nymea log message handler in the system.