From 364cef6a8f7640e225df452051d07abc9584cc15 Mon Sep 17 00:00:00 2001 From: Michael Zanetti Date: Wed, 16 Apr 2014 00:55:32 +0200 Subject: [PATCH] add a preliminary plugin for lirc --- plugins/deviceplugins/deviceplugins.pro | 1 + .../deviceplugins/lircd/devicepluginlircd.cpp | 137 ++++++++++++++++++ .../deviceplugins/lircd/devicepluginlircd.h | 38 +++++ .../lircd/devicepluginlircd.json | 1 + plugins/deviceplugins/lircd/lircd.pro | 19 +++ plugins/deviceplugins/lircd/lircdclient.cpp | 78 ++++++++++ plugins/deviceplugins/lircd/lircdclient.h | 31 ++++ run_on_device.sh | 7 +- server/main.cpp | 1 + server/server.pro | 1 + tests/scripts/addconfigureddevice.sh | 4 +- 11 files changed, 314 insertions(+), 4 deletions(-) create mode 100644 plugins/deviceplugins/lircd/devicepluginlircd.cpp create mode 100644 plugins/deviceplugins/lircd/devicepluginlircd.h create mode 100644 plugins/deviceplugins/lircd/devicepluginlircd.json create mode 100644 plugins/deviceplugins/lircd/lircd.pro create mode 100644 plugins/deviceplugins/lircd/lircdclient.cpp create mode 100644 plugins/deviceplugins/lircd/lircdclient.h diff --git a/plugins/deviceplugins/deviceplugins.pro b/plugins/deviceplugins/deviceplugins.pro index 192cc8d0..a7aefd93 100644 --- a/plugins/deviceplugins/deviceplugins.pro +++ b/plugins/deviceplugins/deviceplugins.pro @@ -7,6 +7,7 @@ SUBDIRS += elro \ mock \ # weatherground \ openweathermap \ + lircd \ boblight { SUBDIRS += boblight diff --git a/plugins/deviceplugins/lircd/devicepluginlircd.cpp b/plugins/deviceplugins/lircd/devicepluginlircd.cpp new file mode 100644 index 00000000..bd9aed6b --- /dev/null +++ b/plugins/deviceplugins/lircd/devicepluginlircd.cpp @@ -0,0 +1,137 @@ +#include "devicepluginlircd.h" + +#include "plugin/device.h" +#include "devicemanager.h" + +#include "lircdclient.h" + +#include +#include + +VendorId lircdVendorId = VendorId("9a53049c-8828-4b87-b3f6-7bc7708196cd"); + +PluginId lircdPluginUuid = PluginId("075f734f-4d76-4ce3-9ef8-34c212285676"); +DeviceClassId lircdDeviceClassId = DeviceClassId("5c2bc4cd-ba6c-4052-b6cd-1db83323ea22"); +EventTypeId LircKeypressEventTypeId = EventTypeId("8711471a-fa0e-410b-b174-dfc3d2aeffb1"); + +DevicePluginLircd::DevicePluginLircd() +{ + m_lircClient = new LircClient(this); + + m_lircClient->connect(); + connect(m_lircClient, &LircClient::buttonPressed, this, &DevicePluginLircd::buttonPressed); +} + +QList DevicePluginLircd::supportedVendors() const +{ + QList ret; + Vendor guh(lircdVendorId, "Lircd"); + ret.append(guh); + return ret; +} + +QList DevicePluginLircd::supportedDevices() const +{ + QList ret; + + DeviceClass deviceClassLircd(pluginId(), lircdVendorId, lircdDeviceClassId); + deviceClassLircd.setName("IR Receiver"); + + QVariantList params; + QVariantMap remoteNameParam; + remoteNameParam.insert("name", "remoteName"); + remoteNameParam.insert("type", "string"); + params.append(remoteNameParam); + deviceClassLircd.setParams(params); + + // TODO: find a way to load this stuff from a json file, really! + // Ideally that file can be generated from /usr/share/lirc/remotes/* + // Note that the IDs need to be kept static! + QVariantList repeatParam; + QVariantMap repeatParamMap; + repeatParamMap.insert("name", "repeat"); + repeatParamMap.insert("type", "int"); + repeatParam.append(repeatParamMap); + + QList events; + EventType powerButton(EventTypeId("d62d779f-e5c6-4767-98e6-efe9c062b662")); + powerButton.setName("Power"); + powerButton.setParameters(repeatParam); + events.append(powerButton); + EventType yellowButton(EventTypeId("3313f62e-ea20-47f5-85af-28897d6ac440")); + yellowButton.setName("Yellow"); + yellowButton.setParameters(repeatParam); + events.append(yellowButton); + EventType blueButton(EventTypeId("9a395d93-e482-4fa2-b4bc-e60bb4bf8652")); + blueButton.setName("Blue"); + blueButton.setParameters(repeatParam); + events.append(blueButton); + EventType greenButton(EventTypeId("e8aaf18e-dc11-40da-980d-4eec42c58267")); + greenButton.setName("Green"); + greenButton.setParameters(repeatParam); + events.append(greenButton); + EventType redButton(EventTypeId("b8518755-55a0-4cd4-8856-1680848edcb7")); + redButton.setName("Red"); + redButton.setParameters(repeatParam); + events.append(redButton); + + deviceClassLircd.setEvents(events); + + ret.append(deviceClassLircd); + + return ret; +} + +DeviceManager::HardwareResources DevicePluginLircd::requiredHardware() const +{ + return DeviceManager::HardwareResourceNone; +} + +QString DevicePluginLircd::pluginName() const +{ + return "Lircd receiver"; +} + +PluginId DevicePluginLircd::pluginId() const +{ + return lircdPluginUuid; +} + +void DevicePluginLircd::buttonPressed(const QString &remoteName, const QString &buttonName, int repeat) +{ + Device *remote = nullptr; + QList configuredRemotes = deviceManager()->findConfiguredDevices(lircdDeviceClassId); + foreach (Device *device, configuredRemotes) { + if (device->params().value("remoteName").toString() == remoteName) { + remote = device; + break; + } + } + if (!remote) { + qDebug() << "Unhandled remote" << remoteName << buttonName; + return; + } + + qDebug() << "found remote" << remoteName << supportedDevices().first().events().count(); + foreach (const EventType &eventType, supportedDevices().first().events()) { + qDebug() << "checking eventType" << eventType.name() << "with" << buttonName; + if (eventType.name() == buttonName) { + QVariantMap param; + param.insert("repeat", repeat); + Event event(eventType.id(), remote->id(), param); + qDebug() << "emitting event"; + emitEvent(event); + } + } + +} + +//QVariantMap DevicePluginLircd::configuration() const +//{ +// return m_config; +//} + +//void DevicePluginLircd::setConfiguration(const QVariantMap &configuration) +//{ +// m_config = configuration; +//} diff --git a/plugins/deviceplugins/lircd/devicepluginlircd.h b/plugins/deviceplugins/lircd/devicepluginlircd.h new file mode 100644 index 00000000..6b55e266 --- /dev/null +++ b/plugins/deviceplugins/lircd/devicepluginlircd.h @@ -0,0 +1,38 @@ +#ifndef DEVICEPLUGINLIRCD_H +#define DEVICEPLUGINLIRCD_H + +#include "plugin/deviceplugin.h" + +#include + +class LircClient; + +class DevicePluginLircd: public DevicePlugin +{ + Q_OBJECT + + Q_PLUGIN_METADATA(IID "org.hiveyourhome.DevicePlugin" FILE "devicepluginlircd.json") + Q_INTERFACES(DevicePlugin) + +public: + explicit DevicePluginLircd(); + + QList supportedVendors() const override; + QList supportedDevices() const override; + DeviceManager::HardwareResources requiredHardware() const override; + + QString pluginName() const override; + PluginId pluginId() const override; + +// QVariantMap configuration() const override; +// void setConfiguration(const QVariantMap &configuration) override; + +private slots: + void buttonPressed(const QString &remoteName, const QString &buttonName, int repeat); + +private: + LircClient *m_lircClient; +// QVariantMap m_config; +}; + +#endif // DEVICEPLUGINBOLIRCD_H diff --git a/plugins/deviceplugins/lircd/devicepluginlircd.json b/plugins/deviceplugins/lircd/devicepluginlircd.json new file mode 100644 index 00000000..0967ef42 --- /dev/null +++ b/plugins/deviceplugins/lircd/devicepluginlircd.json @@ -0,0 +1 @@ +{} diff --git a/plugins/deviceplugins/lircd/lircd.pro b/plugins/deviceplugins/lircd/lircd.pro new file mode 100644 index 00000000..293c24a6 --- /dev/null +++ b/plugins/deviceplugins/lircd/lircd.pro @@ -0,0 +1,19 @@ +include(../../plugins.pri) + +TARGET = $$qtLibraryTarget(guh_devicepluginlircd) + +QT += network + +#INCLUDEPATH += /usr/local/include/ +#LIBS += -L/usr/local/lib/libboblight.a + +SOURCES += \ + devicepluginlircd.cpp \ + lircdclient.cpp \ + +HEADERS += \ + devicepluginlircd.h \ + lircdclient.h \ + + + diff --git a/plugins/deviceplugins/lircd/lircdclient.cpp b/plugins/deviceplugins/lircd/lircdclient.cpp new file mode 100644 index 00000000..54db9694 --- /dev/null +++ b/plugins/deviceplugins/lircd/lircdclient.cpp @@ -0,0 +1,78 @@ +#include "lircdclient.h" + +#include +#include + +LircClient::LircClient(QObject *parent) : + QObject(parent) +{ + + m_socket = new QLocalSocket(this); + QObject::connect(m_socket, &QLocalSocket::readyRead, this, &LircClient::readyRead); +} + +bool LircClient::connect() +{ + m_socket->connectToServer("/var/run/lirc/lircd", QIODevice::ReadWrite); + if (!m_socket->isOpen()) { + qWarning() << "Error connecting to lircd socket. Is Lircd running?"; + return false; + } + + qDebug() << "connected to lircd!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!11111"; + + qDebug() << "wrote to lirc:" << m_socket->write("LIST\n"); + + return true; + + +} + +void LircClient::readyRead() +{ +// qDebug() << "got data" << m_socket->readAll(); + + bool inBlock = false; + while (m_socket->canReadLine()) { + QByteArray line = m_socket->readLine().trimmed(); + qDebug() << "got line:" << line; + if (line == "BEGIN") { + inBlock = true; + continue; + } + if (line == "LIST") { + if (m_socket->readLine().trimmed() == "SUCCESS") { + readRemotes(); + } else { + qWarning() << "Error reading remotes from Lircd"; + } + continue; + } + if ( line == "END") { + inBlock = false; + continue; + } + + if (!inBlock) { + QList parts = line.split(' '); + if (parts.count() != 4) { + qWarning() << "Don't understand IR command. ignoring..."; + continue; + } + qDebug() << "emitting buttonpress"; + emit buttonPressed(QString(parts.at(3)), QString(parts.at(2)), parts.at(1).toInt()); + } + } +} + +void LircClient::readRemotes() +{ + m_socket->readLine(); // IGNORE DATA + int remoteCount = m_socket->readLine().trimmed().toInt(); + qDebug() << "found" << remoteCount << "remotes"; + for (int i = 0; i < remoteCount; i++) { + QByteArray line = m_socket->readLine().trimmed(); + m_remotes.append(line); + } +} + diff --git a/plugins/deviceplugins/lircd/lircdclient.h b/plugins/deviceplugins/lircd/lircdclient.h new file mode 100644 index 00000000..ff640de2 --- /dev/null +++ b/plugins/deviceplugins/lircd/lircdclient.h @@ -0,0 +1,31 @@ +#ifndef LIRCCLIENT_H +#define LIRCCLIENT_H + +#include +#include +#include + +class LircClient : public QObject +{ + Q_OBJECT +public: + explicit LircClient(QObject *parent = 0); + + bool connect(); + +signals: + void buttonPressed(const QString &remoteName, const QString &buttonName, int repeat); + +private slots: + void readyRead(); + +private: + void readRemotes(); + +private: + QLocalSocket *m_socket; + + QStringList m_remotes; +}; + +#endif // LIRCCLIENT_H diff --git a/run_on_device.sh b/run_on_device.sh index 116682e1..0aa61f41 100755 --- a/run_on_device.sh +++ b/run_on_device.sh @@ -3,9 +3,9 @@ CODE_DIR=guh BUILD_DIR=builddir USER=root USER_ID=0 -PASSWORD=guh +PASSWORD=hive BINARY=guh -TARGET_IP=${TARGET_IP-10.10.10.125} +TARGET_IP=${TARGET_IP-10.10.10.108} TARGET_SSH_PORT=22 TARGET_DEBUG_PORT=3768 RUN_OPTIONS=-qmljsdebugger=port:$TARGET_DEBUG_PORT @@ -52,7 +52,8 @@ sync_code() { build() { exec_with_ssh mkdir -p $CODE_DIR/$BUILD_DIR - exec_with_ssh QT_SELECT=qt5 PATH=/usr/local/qt5/bin:/usr/lib/ccache:$PATH "cd $CODE_DIR/$BUILD_DIR && PATH=/usr/local/qt5/bin:/usr/lib/ccache:$PATH qmake .." + exec_with_ssh PATH="/usr/lib/ccache:$PATH" ccache -s + exec_with_ssh QT_SELECT=qt5 PATH=/usr/local/qt5/bin:/usr/lib/ccache:$PATH "cd $CODE_DIR/$BUILD_DIR && PATH=/usr/local/qt5/bin:/usr/lib/ccache:$PATH CC='ccache gcc' qmake .. CONFIG+=boblight" exec_with_ssh PATH=/usr/lib/ccache:$PATH "cd $CODE_DIR/$BUILD_DIR && PATH=/usr/lib/ccache:$PATH make -j2" } diff --git a/server/main.cpp b/server/main.cpp index bdfddeb4..ad968b61 100644 --- a/server/main.cpp +++ b/server/main.cpp @@ -29,6 +29,7 @@ Q_IMPORT_PLUGIN(DevicePluginWifiDetector) Q_IMPORT_PLUGIN(DevicePluginMock) //Q_IMPORT_PLUGIN(DevicePluginWeatherground) Q_IMPORT_PLUGIN(DevicePluginOpenweathermap) +Q_IMPORT_PLUGIN(DevicePluginLircd) #if USE_BOBLIGHT Q_IMPORT_PLUGIN(DevicePluginBoblight) diff --git a/server/server.pro b/server/server.pro index 798e7910..21d14f20 100644 --- a/server/server.pro +++ b/server/server.pro @@ -23,6 +23,7 @@ LIBS += -L../plugins/deviceplugins/wifidetector/ -lguh_devicepluginwifidetector LIBS += -L../plugins/deviceplugins/mock -lguh_devicepluginmock #LIBS += -L../plugins/deviceplugins/weatherground -lguh_devicepluginweatherground LIBS += -L../plugins/deviceplugins/openweathermap -lguh_devicepluginopenweathermap +LIBS += -L../plugins/deviceplugins/lircd -lguh_devicepluginlircd boblight { LIBS += -L../plugins/deviceplugins/boblight -lguh_devicepluginboblight -L/usr/local/lib/ -lboblight diff --git a/tests/scripts/addconfigureddevice.sh b/tests/scripts/addconfigureddevice.sh index 53eb8a05..d139582a 100755 --- a/tests/scripts/addconfigureddevice.sh +++ b/tests/scripts/addconfigureddevice.sh @@ -35,6 +35,8 @@ else elif [ $2 == "openweathermap" ]; then # Adds a openweathermap device (echo '{"id":1, "method":"Devices.AddConfiguredDevice", "params":{"deviceClassId": "{985195aa-17ad-4530-88a4-cdd753d747d7}","deviceParams":{"location":""}}}'; sleep 1) | nc $1 1234 + elif [ $2 == "lirc" ]; then + (echo '{"id":1, "method":"Devices.AddConfiguredDevice", "params":{"deviceClassId": "{5c2bc4cd-ba6c-4052-b6cd-1db83323ea22}","deviceParams":{"remoteName":"'$3'"}}}'; sleep 1) | nc $1 1234 elif [ $2 == "discovered" ]; then if [ -z $4]; then echo "usage $0 host device [deviceClassId descriptorId]. In case of a discovered device, deviceClassId and descriptorId are mandatory." @@ -42,6 +44,6 @@ else (echo '{"id":1, "method":"Devices.AddConfiguredDevice", "params":{"deviceClassId": "'$3'", "deviceDescriptorId": "'$4'"}}'; sleep 1) | nc $1 1234 fi else - echo "unknown type $2. Possible values are: elroremote, elroswitch, intertechnoremote, wifidetector, mock1, mock2, openweathermap, discovered. (In case of discovered, a deviceDescriptorId is required)" + echo "unknown type $2. Possible values are: elroremote, elroswitch, intertechnoremote, wifidetector, mock1, mock2, openweathermap, lirc, discovered. (In case of discovered, a deviceDescriptorId is required)" fi fi