mirror of https://github.com/nymea/nymea.git
Merge PR #289: Add an I2C hardware resource
commit
917c58d145
|
|
@ -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()));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -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/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;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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 \
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
}
|
||||
|
|
@ -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
|
||||
|
|
@ -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)
|
||||
{
|
||||
|
||||
}
|
||||
|
|
@ -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 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);
|
||||
|
|
|
|||
|
|
@ -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 \
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
Loading…
Reference in New Issue