Merge PR #289: Add an I2C hardware resource
This commit is contained in:
commit
917c58d145
278
libnymea-core/hardware/i2c/i2cmanagerimplementation.cpp
Normal file
278
libnymea-core/hardware/i2c/i2cmanagerimplementation.cpp
Normal 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()));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
95
libnymea-core/hardware/i2c/i2cmanagerimplementation.h
Normal file
95
libnymea-core/hardware/i2c/i2cmanagerimplementation.h
Normal 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
|
||||||
@ -41,6 +41,7 @@
|
|||||||
#include "hardware/radio433/radio433brennenstuhl.h"
|
#include "hardware/radio433/radio433brennenstuhl.h"
|
||||||
#include "hardware/bluetoothlowenergy/bluetoothlowenergymanagerimplementation.h"
|
#include "hardware/bluetoothlowenergy/bluetoothlowenergymanagerimplementation.h"
|
||||||
#include "hardware/network/mqtt/mqttproviderimplementation.h"
|
#include "hardware/network/mqtt/mqttproviderimplementation.h"
|
||||||
|
#include "hardware/i2c/i2cmanagerimplementation.h"
|
||||||
|
|
||||||
namespace nymeaserver {
|
namespace nymeaserver {
|
||||||
|
|
||||||
@ -67,8 +68,11 @@ HardwareManagerImplementation::HardwareManagerImplementation(Platform *platform,
|
|||||||
// Bluetooth LE
|
// Bluetooth LE
|
||||||
m_bluetoothLowEnergyManager = new BluetoothLowEnergyManagerImplementation(m_pluginTimerManager->registerTimer(10), this);
|
m_bluetoothLowEnergyManager = new BluetoothLowEnergyManagerImplementation(m_pluginTimerManager->registerTimer(10), this);
|
||||||
|
|
||||||
|
m_i2cManager = new I2CManagerImplementation(this);
|
||||||
|
|
||||||
qCDebug(dcHardware()) << "Hardware manager initialized successfully";
|
qCDebug(dcHardware()) << "Hardware manager initialized successfully";
|
||||||
|
|
||||||
|
|
||||||
// Enable all the resources
|
// Enable all the resources
|
||||||
setResourceEnabled(m_pluginTimerManager, true);
|
setResourceEnabled(m_pluginTimerManager, true);
|
||||||
setResourceEnabled(m_radio433, true);
|
setResourceEnabled(m_radio433, true);
|
||||||
@ -127,4 +131,9 @@ MqttProvider *HardwareManagerImplementation::mqttProvider()
|
|||||||
return m_mqttProvider;
|
return m_mqttProvider;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
I2CManager *HardwareManagerImplementation::i2cManager()
|
||||||
|
{
|
||||||
|
return m_i2cManager;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -37,14 +37,6 @@
|
|||||||
|
|
||||||
#include "hardwaremanager.h"
|
#include "hardwaremanager.h"
|
||||||
|
|
||||||
class Radio433;
|
|
||||||
class UpnpDiscovery;
|
|
||||||
class PluginTimerManager;
|
|
||||||
class NetworkAccessManager;
|
|
||||||
class UpnpDeviceDescriptor;
|
|
||||||
class PlatformZeroConfController;
|
|
||||||
class BluetoothLowEnergyManager;
|
|
||||||
|
|
||||||
namespace nymeaserver {
|
namespace nymeaserver {
|
||||||
|
|
||||||
class Platform;
|
class Platform;
|
||||||
@ -65,6 +57,7 @@ public:
|
|||||||
PlatformZeroConfController *zeroConfController() override;
|
PlatformZeroConfController *zeroConfController() override;
|
||||||
BluetoothLowEnergyManager *bluetoothLowEnergyManager() override;
|
BluetoothLowEnergyManager *bluetoothLowEnergyManager() override;
|
||||||
MqttProvider *mqttProvider() override;
|
MqttProvider *mqttProvider() override;
|
||||||
|
I2CManager * i2cManager() override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QNetworkAccessManager *m_networkAccessManager = nullptr;
|
QNetworkAccessManager *m_networkAccessManager = nullptr;
|
||||||
@ -78,6 +71,7 @@ private:
|
|||||||
UpnpDiscovery *m_upnpDiscovery = nullptr;
|
UpnpDiscovery *m_upnpDiscovery = nullptr;
|
||||||
BluetoothLowEnergyManager *m_bluetoothLowEnergyManager = nullptr;
|
BluetoothLowEnergyManager *m_bluetoothLowEnergyManager = nullptr;
|
||||||
MqttProvider *m_mqttProvider = nullptr;
|
MqttProvider *m_mqttProvider = nullptr;
|
||||||
|
I2CManager *m_i2cManager = nullptr;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -88,6 +88,7 @@ HEADERS += nymeacore.h \
|
|||||||
hardware/network/upnp/upnpdiscoveryreplyimplementation.h \
|
hardware/network/upnp/upnpdiscoveryreplyimplementation.h \
|
||||||
hardware/network/mqtt/mqttproviderimplementation.h \
|
hardware/network/mqtt/mqttproviderimplementation.h \
|
||||||
hardware/network/mqtt/mqttchannelimplementation.h \
|
hardware/network/mqtt/mqttchannelimplementation.h \
|
||||||
|
hardware/i2c/i2cmanagerimplementation.h \
|
||||||
debugserverhandler.h \
|
debugserverhandler.h \
|
||||||
tagging/tagsstorage.h \
|
tagging/tagsstorage.h \
|
||||||
tagging/tag.h \
|
tagging/tag.h \
|
||||||
@ -165,6 +166,7 @@ SOURCES += nymeacore.cpp \
|
|||||||
hardware/network/upnp/upnpdiscoveryreplyimplementation.cpp \
|
hardware/network/upnp/upnpdiscoveryreplyimplementation.cpp \
|
||||||
hardware/network/mqtt/mqttproviderimplementation.cpp \
|
hardware/network/mqtt/mqttproviderimplementation.cpp \
|
||||||
hardware/network/mqtt/mqttchannelimplementation.cpp \
|
hardware/network/mqtt/mqttchannelimplementation.cpp \
|
||||||
|
hardware/i2c/i2cmanagerimplementation.cpp \
|
||||||
debugserverhandler.cpp \
|
debugserverhandler.cpp \
|
||||||
tagging/tagsstorage.cpp \
|
tagging/tagsstorage.cpp \
|
||||||
tagging/tag.cpp \
|
tagging/tag.cpp \
|
||||||
|
|||||||
118
libnymea/hardware/i2c/i2cdevice.cpp
Normal file
118
libnymea/hardware/i2c/i2cdevice.cpp
Normal 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();
|
||||||
|
}
|
||||||
61
libnymea/hardware/i2c/i2cdevice.h
Normal file
61
libnymea/hardware/i2c/i2cdevice.h
Normal 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
|
||||||
78
libnymea/hardware/i2c/i2cmanager.cpp
Normal file
78
libnymea/hardware/i2c/i2cmanager.cpp
Normal 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)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
60
libnymea/hardware/i2c/i2cmanager.h
Normal file
60
libnymea/hardware/i2c/i2cmanager.h
Normal 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
|
||||||
@ -41,6 +41,7 @@ class UpnpDeviceDescriptor;
|
|||||||
class PlatformZeroConfController;
|
class PlatformZeroConfController;
|
||||||
class BluetoothLowEnergyManager;
|
class BluetoothLowEnergyManager;
|
||||||
class MqttProvider;
|
class MqttProvider;
|
||||||
|
class I2CManager;
|
||||||
class HardwareResource;
|
class HardwareResource;
|
||||||
|
|
||||||
class HardwareManager : public QObject
|
class HardwareManager : public QObject
|
||||||
@ -59,6 +60,7 @@ public:
|
|||||||
virtual PlatformZeroConfController *zeroConfController() = 0;
|
virtual PlatformZeroConfController *zeroConfController() = 0;
|
||||||
virtual BluetoothLowEnergyManager *bluetoothLowEnergyManager() = 0;
|
virtual BluetoothLowEnergyManager *bluetoothLowEnergyManager() = 0;
|
||||||
virtual MqttProvider *mqttProvider() = 0;
|
virtual MqttProvider *mqttProvider() = 0;
|
||||||
|
virtual I2CManager *i2cManager() = 0;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void setResourceEnabled(HardwareResource* resource, bool enabled);
|
void setResourceEnabled(HardwareResource* resource, bool enabled);
|
||||||
|
|||||||
@ -56,6 +56,8 @@ HEADERS += \
|
|||||||
hardware/bluetoothlowenergy/bluetoothlowenergydevice.h \
|
hardware/bluetoothlowenergy/bluetoothlowenergydevice.h \
|
||||||
hardware/bluetoothlowenergy/bluetoothdiscoveryreply.h \
|
hardware/bluetoothlowenergy/bluetoothdiscoveryreply.h \
|
||||||
hardware/bluetoothlowenergy/bluetoothlowenergymanager.h \
|
hardware/bluetoothlowenergy/bluetoothlowenergymanager.h \
|
||||||
|
hardware/i2c/i2cmanager.h \
|
||||||
|
hardware/i2c/i2cdevice.h \
|
||||||
coap/coap.h \
|
coap/coap.h \
|
||||||
coap/coappdu.h \
|
coap/coappdu.h \
|
||||||
coap/coapoption.h \
|
coap/coapoption.h \
|
||||||
@ -133,6 +135,8 @@ SOURCES += \
|
|||||||
hardware/bluetoothlowenergy/bluetoothlowenergymanager.cpp \
|
hardware/bluetoothlowenergy/bluetoothlowenergymanager.cpp \
|
||||||
hardware/bluetoothlowenergy/bluetoothlowenergydevice.cpp \
|
hardware/bluetoothlowenergy/bluetoothlowenergydevice.cpp \
|
||||||
hardware/bluetoothlowenergy/bluetoothdiscoveryreply.cpp \
|
hardware/bluetoothlowenergy/bluetoothdiscoveryreply.cpp \
|
||||||
|
hardware/i2c/i2cmanager.cpp \
|
||||||
|
hardware/i2c/i2cdevice.cpp \
|
||||||
coap/coap.cpp \
|
coap/coap.cpp \
|
||||||
coap/coappdu.cpp \
|
coap/coappdu.cpp \
|
||||||
coap/coapoption.cpp \
|
coap/coapoption.cpp \
|
||||||
|
|||||||
@ -72,6 +72,7 @@ Q_LOGGING_CATEGORY(dcBluetoothServer, "BluetoothServer")
|
|||||||
Q_LOGGING_CATEGORY(dcBluetoothServerTraffic, "BluetoothServerTraffic")
|
Q_LOGGING_CATEGORY(dcBluetoothServerTraffic, "BluetoothServerTraffic")
|
||||||
Q_LOGGING_CATEGORY(dcMqtt, "Mqtt")
|
Q_LOGGING_CATEGORY(dcMqtt, "Mqtt")
|
||||||
Q_LOGGING_CATEGORY(dcTranslations, "Translations")
|
Q_LOGGING_CATEGORY(dcTranslations, "Translations")
|
||||||
|
Q_LOGGING_CATEGORY(dcI2C, "I2C")
|
||||||
|
|
||||||
|
|
||||||
static QFile s_logFile;
|
static QFile s_logFile;
|
||||||
|
|||||||
@ -75,6 +75,7 @@ Q_DECLARE_LOGGING_CATEGORY(dcBluetoothServerTraffic)
|
|||||||
Q_DECLARE_LOGGING_CATEGORY(dcMqtt)
|
Q_DECLARE_LOGGING_CATEGORY(dcMqtt)
|
||||||
Q_DECLARE_LOGGING_CATEGORY(dcTranslations)
|
Q_DECLARE_LOGGING_CATEGORY(dcTranslations)
|
||||||
Q_DECLARE_LOGGING_CATEGORY(dcCoap)
|
Q_DECLARE_LOGGING_CATEGORY(dcCoap)
|
||||||
|
Q_DECLARE_LOGGING_CATEGORY(dcI2C)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Installs a nymea log message handler in the system.
|
Installs a nymea log message handler in the system.
|
||||||
|
|||||||
Reference in New Issue
Block a user