Merge PR #219: New plugin: USB relay
This commit is contained in:
commit
01adff2cd9
20
debian/control
vendored
20
debian/control
vendored
@ -15,6 +15,8 @@ Build-depends: libboblight-dev,
|
||||
qtconnectivity5-dev,
|
||||
libow-dev,
|
||||
libsodium-dev,
|
||||
libudev-dev,
|
||||
libhidapi-dev,
|
||||
Standards-Version: 3.9.3
|
||||
|
||||
|
||||
@ -687,6 +689,23 @@ Description: nymea.io plugin for unitec
|
||||
This package will install the nymea.io plugin for unitec
|
||||
|
||||
|
||||
Package: nymea-plugin-usbrelay
|
||||
Architecture: any
|
||||
Multi-Arch: same
|
||||
Section: libs
|
||||
Depends: ${shlibs:Depends},
|
||||
${misc:Depends},
|
||||
libudev1,
|
||||
libhidapi-hidraw0,
|
||||
Description: nymea.io plugin for USB relay
|
||||
The nymea daemon is a plugin based IoT (Internet of Things) server. The
|
||||
server works like a translator for devices, things and services and
|
||||
allows them to interact.
|
||||
With the powerful rule engine you are able to connect any device available
|
||||
in the system and create individual scenes and behaviors for your environment.
|
||||
.
|
||||
This package will install the nymea.io plugin for USB relay
|
||||
|
||||
|
||||
Package: nymea-plugin-wakeonlan
|
||||
Architecture: any
|
||||
@ -970,6 +989,7 @@ Depends: nymea-plugin-anel,
|
||||
nymea-plugin-tado,
|
||||
nymea-plugin-keba,
|
||||
nymea-plugin-unifi,
|
||||
nymea-plugin-usbrelay,
|
||||
Replaces: guh-plugins
|
||||
Description: Plugins for nymea IoT server - the default plugin collection
|
||||
The nymea daemon is a plugin based IoT (Internet of Things) server. The
|
||||
|
||||
1
debian/copyright
vendored
1
debian/copyright
vendored
@ -59,6 +59,7 @@ Files: avahimonitor/*
|
||||
senic/*
|
||||
udpcommander/*
|
||||
unitec/*
|
||||
usbrelay/*
|
||||
wemo/*
|
||||
License: LGPL-2.1
|
||||
Copyright: 2014-2017, Simon Stürz <simon.stuerz@guh.io>
|
||||
|
||||
1
debian/nymea-plugin-usbrelay.install.in
vendored
Normal file
1
debian/nymea-plugin-usbrelay.install.in
vendored
Normal file
@ -0,0 +1 @@
|
||||
usr/lib/@DEB_HOST_MULTIARCH@/nymea/plugins/libnymea_devicepluginusbrelay.so
|
||||
@ -55,6 +55,7 @@ PLUGIN_DIRS = \
|
||||
udpcommander \
|
||||
unifi \
|
||||
unitec \
|
||||
usbrelay \
|
||||
wakeonlan \
|
||||
wemo \
|
||||
ws2812fx \
|
||||
|
||||
5
usbrelay/README.md
Normal file
5
usbrelay/README.md
Normal file
@ -0,0 +1,5 @@
|
||||
# usbrelay
|
||||
--------------------------------
|
||||
|
||||
This plugin eneblas you to control low-cost USB HID relays. The plugin creates a power device for each relay and can be controlled using the `power?? interface.
|
||||
Examples of USB relay hardware can be found [here](http://vusb.wikidot.com/project:driver-less-usb-relays-hid-interface).
|
||||
298
usbrelay/devicepluginusbrelay.cpp
Normal file
298
usbrelay/devicepluginusbrelay.cpp
Normal file
@ -0,0 +1,298 @@
|
||||
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||
* *
|
||||
* Copyright (C) 2019 Simon Stürz <simon.stuerz@nymea.io> *
|
||||
* *
|
||||
* This file is part of nymea. *
|
||||
* *
|
||||
* This library is free software; you can redistribute it and/or *
|
||||
* modify it under the terms of the GNU Lesser General Public *
|
||||
* License as published by the Free Software Foundation; either *
|
||||
* version 2.1 of the License, or (at your option) any later version. *
|
||||
* *
|
||||
* This library 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 library; If not, see *
|
||||
* <http://www.gnu.org/licenses/>. *
|
||||
* *
|
||||
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||||
|
||||
#include "plugininfo.h"
|
||||
#include "devicepluginusbrelay.h"
|
||||
|
||||
#include <QTimer>
|
||||
#include <hidapi/hidapi.h>
|
||||
|
||||
DevicePluginUsbRelay::DevicePluginUsbRelay()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void DevicePluginUsbRelay::init()
|
||||
{
|
||||
// Initialize/create objects
|
||||
}
|
||||
|
||||
void DevicePluginUsbRelay::startMonitoringAutoDevices()
|
||||
{
|
||||
// Start seaching for devices which can be discovered and added automatically
|
||||
}
|
||||
|
||||
void DevicePluginUsbRelay::postSetupDevice(Device *device)
|
||||
{
|
||||
qCDebug(dcUsbRelay()) << "Post setup device" << device;
|
||||
|
||||
if (device->deviceClassId() == usbRelayConnectorDeviceClassId) {
|
||||
|
||||
// Initialize the states
|
||||
UsbRelay *relay = m_relayDevices.key(device);
|
||||
if (!relay) {
|
||||
qCWarning(dcUsbRelay()) << "Could not find relay in post setup.";
|
||||
return;
|
||||
}
|
||||
|
||||
device->setStateValue(usbRelayConnectorConnectedStateTypeId, relay->connected());
|
||||
|
||||
// Check if we have to create child devices (relays)
|
||||
if (myDevices().filterByParentDeviceId(device->id()).isEmpty()) {
|
||||
|
||||
DeviceDescriptors descriptors;
|
||||
for (int i = 0; i < relay->relayCount(); i++) {
|
||||
int relayNumber = i + 1;
|
||||
DeviceDescriptor descriptor(usbRelayDeviceClassId, QString("Relay %1").arg(relayNumber), QString(), device->id());
|
||||
ParamList params;
|
||||
params.append(Param(usbRelayDeviceRelayNumberParamTypeId, relayNumber));
|
||||
descriptor.setParams(params);
|
||||
descriptors.append(descriptor);
|
||||
}
|
||||
|
||||
emit autoDevicesAppeared(descriptors);
|
||||
}
|
||||
} else if (device->deviceClassId() == usbRelayDeviceClassId) {
|
||||
|
||||
UsbRelay *relay = getRelayForDevice(device);
|
||||
if (!relay) return;
|
||||
|
||||
// Set the current states
|
||||
int relayNumber = device->paramValue(usbRelayDeviceRelayNumberParamTypeId).toInt();
|
||||
device->setStateValue(usbRelayConnectedStateTypeId, relay->connected());
|
||||
device->setStateValue(usbRelayPowerStateTypeId, relay->relayPower(relayNumber));
|
||||
}
|
||||
}
|
||||
|
||||
void DevicePluginUsbRelay::deviceRemoved(Device *device)
|
||||
{
|
||||
qCDebug(dcUsbRelay()) << "Remove device" << device;
|
||||
if (device->deviceClassId() == usbRelayConnectorDeviceClassId) {
|
||||
UsbRelay *relay = m_relayDevices.key(device);
|
||||
if (!relay) return;
|
||||
m_relayDevices.remove(relay);
|
||||
delete relay;
|
||||
}
|
||||
}
|
||||
|
||||
void DevicePluginUsbRelay::discoverDevices(DeviceDiscoveryInfo *info)
|
||||
{
|
||||
// Init
|
||||
if (hid_init() < 0) {
|
||||
qCWarning(dcUsbRelay()) << "Could not initialize HID.";
|
||||
info->finish(Device::DeviceErrorHardwareFailure, QT_TR_NOOP("Cannot discover USB devices. HID initialisation failed on this system."));
|
||||
return;
|
||||
}
|
||||
|
||||
// Enumerate hid devices
|
||||
struct hid_device_info *devices = nullptr;
|
||||
struct hid_device_info *currentDevice = nullptr;
|
||||
devices = hid_enumerate(0x16c0, 0x05df);
|
||||
int relayCount = 0;
|
||||
currentDevice = devices;
|
||||
|
||||
for (relayCount = 0; currentDevice != nullptr; relayCount++) {
|
||||
currentDevice = currentDevice->next;
|
||||
}
|
||||
|
||||
qCDebug(dcUsbRelay()) << "Found" << relayCount << "usb relay devices";
|
||||
currentDevice = devices;
|
||||
for (int i = 0; i < relayCount; i++) {
|
||||
QString path = QString::fromLatin1(currentDevice->path);
|
||||
QString manufacturer = QString::fromWCharArray(currentDevice->manufacturer_string);
|
||||
QString product = QString::fromWCharArray(currentDevice->product_string);
|
||||
QString serialnumber = QString::fromWCharArray(currentDevice->serial_number);
|
||||
quint16 releaseNumber = static_cast<quint16>(currentDevice->release_number);
|
||||
quint16 productId = static_cast<quint16>(currentDevice->product_id);
|
||||
quint16 vendorId = static_cast<quint16>(currentDevice->vendor_id);
|
||||
int relayCount = QString(product.at(product.count() -1)).toInt();
|
||||
|
||||
qCDebug(dcUsbRelay()) << path << manufacturer << product << serialnumber << "Relay count" << relayCount << QString("%1:%2").arg(QString::number(vendorId, 16)).arg(QString::number(productId, 16)) << releaseNumber;
|
||||
|
||||
// Open it to get more details
|
||||
hid_device *hidDevice = nullptr;
|
||||
hidDevice = hid_open_path(currentDevice->path);
|
||||
if (!hidDevice) {
|
||||
qCWarning(dcUsbRelay()) << "Could not create HID device for" << path;
|
||||
continue;
|
||||
}
|
||||
|
||||
unsigned char buf[9];
|
||||
buf[0] = 0x01;
|
||||
int ret = hid_get_feature_report(hidDevice, buf, sizeof(buf));
|
||||
if (ret < 0) {
|
||||
qCWarning(dcUsbRelay()) << "Could not create HID device hidDevice for" << path;
|
||||
continue;
|
||||
}
|
||||
|
||||
quint8 relayStatus = static_cast<quint8>(buf[7]);
|
||||
for (int i = 0; i < relayCount; i++) {
|
||||
int relayNumber = i + 1;
|
||||
bool power = static_cast<bool>(relayStatus & 1 << i);
|
||||
qCDebug(dcUsbRelay()) << "--> Relay" << relayNumber << ":" << power;
|
||||
}
|
||||
|
||||
hid_close(hidDevice);
|
||||
|
||||
DeviceDescriptor descriptor(usbRelayConnectorDeviceClassId, "USB Relay Connector", QString("%1 (%2)").arg(product).arg(path));
|
||||
ParamList params;
|
||||
params.append(Param(usbRelayConnectorDevicePathParamTypeId, path));
|
||||
params.append(Param(usbRelayConnectorDeviceRelayCountParamTypeId, relayCount));
|
||||
descriptor.setParams(params);
|
||||
|
||||
// Set the current device id if we already have a device on this path
|
||||
foreach (Device *existingDevice, myDevices()) {
|
||||
if (existingDevice->paramValue(usbRelayConnectorDevicePathParamTypeId).toString() == path &&
|
||||
existingDevice->paramValue(usbRelayConnectorDeviceRelayCountParamTypeId).toInt() == relayCount) {
|
||||
descriptor.setDeviceId(existingDevice->id());
|
||||
break;
|
||||
}
|
||||
}
|
||||
info->addDeviceDescriptor(descriptor);
|
||||
}
|
||||
|
||||
hid_free_enumeration(devices);
|
||||
hid_exit();
|
||||
|
||||
info->finish(Device::DeviceErrorNoError);
|
||||
}
|
||||
|
||||
void DevicePluginUsbRelay::setupDevice(DeviceSetupInfo *info)
|
||||
{
|
||||
qCDebug(dcUsbRelay()) << "Setup device" << info->device();
|
||||
|
||||
// Relay connector
|
||||
if (info->device()->deviceClassId() == usbRelayConnectorDeviceClassId) {
|
||||
Device *device = info->device();
|
||||
QString path = device->paramValue(usbRelayConnectorDevicePathParamTypeId).toString();
|
||||
int relayCount = device->paramValue(usbRelayConnectorDeviceRelayCountParamTypeId).toInt();
|
||||
|
||||
UsbRelay *relay = new UsbRelay(path, relayCount, this);
|
||||
m_relayDevices.insert(relay, device);
|
||||
|
||||
connect(relay, &UsbRelay::connectedChanged, this, [this, device, relay](bool connected) {
|
||||
qCDebug(dcUsbRelay()) << "Device" << device->name() << (connected ? "connected" : "disconnected");
|
||||
device->setStateValue(usbRelayConnectorConnectedStateTypeId, connected);
|
||||
|
||||
// Set the connected state of all child devices
|
||||
foreach (Device *childDevice, myDevices().filterByParentDeviceId(device->id())) {
|
||||
if (childDevice->deviceClassId() == usbRelayDeviceClassId && childDevice->setupComplete()) {
|
||||
childDevice->setStateValue(usbRelayConnectedStateTypeId, connected);
|
||||
if (connected) {
|
||||
childDevice->setStateValue(usbRelayPowerStateTypeId, relay->relayPower(childDevice->paramValue(usbRelayDeviceRelayNumberParamTypeId).toInt()));
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
connect(relay, &UsbRelay::relayPowerChanged, this, [this, device](int relayNumber, bool power) {
|
||||
Device *relayDevice = getRelayDevice(device, relayNumber);
|
||||
if (!relayDevice) {
|
||||
// Note: probably not set up yet
|
||||
qCWarning(dcUsbRelay()) << "Could not find USB relay child device for" << device << relayNumber;
|
||||
return;
|
||||
}
|
||||
|
||||
relayDevice->setStateValue(usbRelayPowerStateTypeId, power);
|
||||
});
|
||||
|
||||
info->finish(Device::DeviceErrorNoError);
|
||||
return;
|
||||
}
|
||||
|
||||
// Relay
|
||||
if (info->device()->deviceClassId() == usbRelayDeviceClassId) {
|
||||
info->finish(Device::DeviceErrorNoError);
|
||||
return;
|
||||
}
|
||||
|
||||
info->finish(Device::DeviceErrorSetupFailed);
|
||||
}
|
||||
|
||||
void DevicePluginUsbRelay::executeAction(DeviceActionInfo *info)
|
||||
{
|
||||
qCDebug(dcUsbRelay()) << "Executing action for device" << info->device() << info->action().actionTypeId().toString() << info->action().params();
|
||||
|
||||
if (info->device()->deviceClassId() == usbRelayDeviceClassId) {
|
||||
|
||||
Device *device = info->device();
|
||||
UsbRelay *relay = getRelayForDevice(device);
|
||||
|
||||
if (!relay) {
|
||||
qCWarning(dcUsbRelay()) << "Could execute action because could not find USB relay for" << device;
|
||||
info->finish(Device::DeviceErrorHardwareNotAvailable);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!relay->connected()) {
|
||||
qCWarning(dcUsbRelay()) << "Relay is not connected";
|
||||
info->finish(Device::DeviceErrorHardwareNotAvailable);
|
||||
return;
|
||||
}
|
||||
|
||||
int relayNumber = device->paramValue(usbRelayDeviceRelayNumberParamTypeId).toInt();
|
||||
|
||||
if (info->action().actionTypeId() == usbRelayPowerActionTypeId) {
|
||||
bool power = info->action().param(usbRelayPowerActionPowerParamTypeId).value().toBool();
|
||||
if (!relay->setRelayPower(relayNumber, power)) {
|
||||
info->finish(Device::DeviceErrorHardwareFailure);
|
||||
return;
|
||||
}
|
||||
info->finish(Device::DeviceErrorNoError);
|
||||
return;
|
||||
}
|
||||
|
||||
info->finish(Device::DeviceErrorActionTypeNotFound);
|
||||
}
|
||||
|
||||
info->finish(Device::DeviceErrorDeviceClassNotFound);
|
||||
}
|
||||
|
||||
Device *DevicePluginUsbRelay::getRelayDevice(Device *parentDevice, int relayNumber)
|
||||
{
|
||||
foreach (Device *childDevice, myDevices().filterByParentDeviceId(parentDevice->id())) {
|
||||
if (childDevice->deviceClassId() == usbRelayDeviceClassId) {
|
||||
if (childDevice->paramValue(usbRelayDeviceRelayNumberParamTypeId).toInt() == relayNumber) {
|
||||
return childDevice;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
UsbRelay *DevicePluginUsbRelay::getRelayForDevice(Device *relayDevice)
|
||||
{
|
||||
Device *parentDevice = myDevices().findById(relayDevice->parentId());
|
||||
if (!parentDevice) {
|
||||
qCWarning(dcUsbRelay()) << "Could not find the parent device for" << relayDevice;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
UsbRelay *relay = m_relayDevices.key(parentDevice);
|
||||
if (!relay) {
|
||||
qCWarning(dcUsbRelay()) << "Could not find USB relay for" << relayDevice;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return relay;
|
||||
}
|
||||
58
usbrelay/devicepluginusbrelay.h
Normal file
58
usbrelay/devicepluginusbrelay.h
Normal file
@ -0,0 +1,58 @@
|
||||
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||
* *
|
||||
* Copyright (C) 2019 Simon Stürz <simon.stuerz@nymea.io> *
|
||||
* *
|
||||
* This file is part of nymea. *
|
||||
* *
|
||||
* This library is free software; you can redistribute it and/or *
|
||||
* modify it under the terms of the GNU Lesser General Public *
|
||||
* License as published by the Free Software Foundation; either *
|
||||
* version 2.1 of the License, or (at your option) any later version. *
|
||||
* *
|
||||
* This library 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 library; If not, see *
|
||||
* <http://www.gnu.org/licenses/>. *
|
||||
* *
|
||||
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||||
|
||||
#ifndef DEVICEPLUGINUSBRELAY_H
|
||||
#define DEVICEPLUGINUSBRELAY_H
|
||||
|
||||
#include "usbrelay.h"
|
||||
#include "devices/deviceplugin.h"
|
||||
|
||||
class DevicePluginUsbRelay: public DevicePlugin
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
Q_PLUGIN_METADATA(IID "io.nymea.DevicePlugin" FILE "devicepluginusbrelay.json")
|
||||
Q_INTERFACES(DevicePlugin)
|
||||
|
||||
|
||||
public:
|
||||
explicit DevicePluginUsbRelay();
|
||||
|
||||
void init() override;
|
||||
void startMonitoringAutoDevices() override;
|
||||
void postSetupDevice(Device *device) override;
|
||||
void deviceRemoved(Device *device) override;
|
||||
|
||||
void discoverDevices(DeviceDiscoveryInfo *info) override;
|
||||
void setupDevice(DeviceSetupInfo *info) override;
|
||||
void executeAction(DeviceActionInfo *info) override;
|
||||
|
||||
private:
|
||||
QHash<UsbRelay *, Device *> m_relayDevices;
|
||||
|
||||
Device *getRelayDevice(Device *parentDevice, int relayNumber);
|
||||
UsbRelay *getRelayForDevice(Device *relayDevice);
|
||||
private slots:
|
||||
|
||||
};
|
||||
|
||||
#endif // DEVICEPLUGINUSBRELAY_H
|
||||
88
usbrelay/devicepluginusbrelay.json
Normal file
88
usbrelay/devicepluginusbrelay.json
Normal file
@ -0,0 +1,88 @@
|
||||
{
|
||||
"name": "UsbRelay",
|
||||
"displayName": "USB relay",
|
||||
"id": "ed0035d3-561c-498e-bdb2-2b574cbd0a2f",
|
||||
"vendors": [
|
||||
{
|
||||
"displayName": "USB Relay",
|
||||
"name": "usbrelay",
|
||||
"id": "d699b81a-621a-4db6-a137-6adbb5c9c091",
|
||||
"deviceClasses": [
|
||||
{
|
||||
"name": "usbRelayConnector",
|
||||
"displayName": "USB Relay Connector",
|
||||
"id": "f48ff4db-d207-4221-963a-3fcb635102d8",
|
||||
"setupMethod": "JustAdd",
|
||||
"createMethods": ["Discovery"],
|
||||
"interfaces": [ "gateway" ],
|
||||
"paramTypes": [
|
||||
{
|
||||
"id": "a9fffbb9-f1c3-439c-9168-8c3fdfab29c8",
|
||||
"name": "path",
|
||||
"displayName": "System path",
|
||||
"type": "QString",
|
||||
"defaultValue": ""
|
||||
},
|
||||
{
|
||||
"id": "406e1396-e3a3-4200-9045-2146381041b3",
|
||||
"name": "relayCount",
|
||||
"displayName": "Relay count",
|
||||
"type": "uint",
|
||||
"defaultValue": 2
|
||||
}
|
||||
],
|
||||
"stateTypes": [
|
||||
{
|
||||
"id": "4cb1cf1f-76fd-4a9c-9397-b5f07b123050",
|
||||
"name": "connected",
|
||||
"displayName": "Connected",
|
||||
"displayNameEvent": "Connected changed",
|
||||
"type": "bool",
|
||||
"defaultValue": false
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "usbRelay",
|
||||
"displayName": "USB Relay",
|
||||
"id": "6e01190d-ed9e-4dab-97d1-dc357c740db8",
|
||||
"setupMethod": "JustAdd",
|
||||
"createMethods": ["Auto"],
|
||||
"interfaces": [ "power", "connectable" ],
|
||||
"paramTypes": [
|
||||
{
|
||||
"id": "48d6e667-643f-4f9f-ae12-5308d23a36d7",
|
||||
"name": "relayNumber",
|
||||
"displayName": "Relay number",
|
||||
"type": "uint",
|
||||
"defaultValue": 1
|
||||
}
|
||||
],
|
||||
"stateTypes": [
|
||||
{
|
||||
"id": "fd5338f8-f02b-4f99-8677-365cfc98221d",
|
||||
"name": "connected",
|
||||
"displayName": "Connected",
|
||||
"displayNameEvent": "Connected changed",
|
||||
"type": "bool",
|
||||
"defaultValue": false
|
||||
},
|
||||
{
|
||||
"id": "b22ec763-cb41-4d1b-846d-7b2cbe5e433d",
|
||||
"name": "power",
|
||||
"displayName": "Power",
|
||||
"displayNameEvent": "Power",
|
||||
"displayNameAction": "Set power",
|
||||
"type": "bool",
|
||||
"defaultValue": false,
|
||||
"writable": true
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
|
||||
163
usbrelay/rawhiddevicewatcher.cpp
Normal file
163
usbrelay/rawhiddevicewatcher.cpp
Normal file
@ -0,0 +1,163 @@
|
||||
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||
* *
|
||||
* Copyright (C) 2019 Simon Stürz <simon.stuerz@nymea.io> *
|
||||
* *
|
||||
* This file is part of nymea. *
|
||||
* *
|
||||
* This library is free software; you can redistribute it and/or *
|
||||
* modify it under the terms of the GNU Lesser General Public *
|
||||
* License as published by the Free Software Foundation; either *
|
||||
* version 2.1 of the License, or (at your option) any later version. *
|
||||
* *
|
||||
* This library 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 library; If not, see *
|
||||
* <http://www.gnu.org/licenses/>. *
|
||||
* *
|
||||
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||||
|
||||
#include "rawhiddevicewatcher.h"
|
||||
#include "extern-plugininfo.h"
|
||||
|
||||
RawHidDeviceWatcher::RawHidDeviceWatcher(QObject *parent) : QObject(parent)
|
||||
{
|
||||
m_udev = udev_new();
|
||||
if (!m_udev) {
|
||||
qCWarning(dcUsbRelay()) << "Could not initialize udev";
|
||||
return;
|
||||
}
|
||||
|
||||
// Create udev monitor
|
||||
m_monitor = udev_monitor_new_from_netlink(m_udev, "udev");
|
||||
if (!m_monitor) {
|
||||
qCWarning(dcUsbRelay()) << "Could not initialize udev monitor.";
|
||||
udev_unref(m_udev);
|
||||
m_udev = nullptr;
|
||||
return;
|
||||
}
|
||||
|
||||
// Set monitor filter to USB subsystem
|
||||
if (udev_monitor_filter_add_match_subsystem_devtype(m_monitor, "hidraw", nullptr) < 0) {
|
||||
qCWarning(dcUsbRelay()) << "Could not set seubsystem device type filter to usb_device.";
|
||||
udev_monitor_unref(m_monitor);
|
||||
m_monitor = nullptr;
|
||||
udev_unref(m_udev);
|
||||
m_udev = nullptr;
|
||||
return;
|
||||
}
|
||||
|
||||
// Enable the monitor
|
||||
if (udev_monitor_enable_receiving(m_monitor) < 0) {
|
||||
qCWarning(dcUsbRelay()) << "Could not enable udev monitor.";
|
||||
udev_monitor_unref(m_monitor);
|
||||
m_monitor = nullptr;
|
||||
udev_unref(m_udev);
|
||||
m_udev = nullptr;
|
||||
return;
|
||||
}
|
||||
|
||||
// Read initially all devices
|
||||
struct udev_enumerate *enumerate;
|
||||
struct udev_list_entry *devices, *dev_list_entry;
|
||||
enumerate = udev_enumerate_new(m_udev);
|
||||
if (!enumerate) {
|
||||
qCWarning(dcUsbRelay()) << "Could not create udev enumerate for initial device reading.";
|
||||
udev_monitor_unref(m_monitor);
|
||||
m_monitor = nullptr;
|
||||
udev_unref(m_udev);
|
||||
m_udev = nullptr;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
udev_enumerate_add_match_subsystem(enumerate, "hidraw");
|
||||
udev_enumerate_scan_devices(enumerate);
|
||||
|
||||
devices = udev_enumerate_get_list_entry(enumerate);
|
||||
if (!devices) {
|
||||
qCWarning(dcUsbRelay()) << "Failed to get hidraw devices from udev enumerate.";
|
||||
udev_monitor_unref(m_monitor);
|
||||
m_monitor = nullptr;
|
||||
udev_unref(m_udev);
|
||||
m_udev = nullptr;
|
||||
return;
|
||||
}
|
||||
|
||||
udev_list_entry_foreach(dev_list_entry, devices) {
|
||||
struct udev_device *device;
|
||||
const char *path;
|
||||
path = udev_list_entry_get_name(dev_list_entry);
|
||||
device = udev_device_new_from_syspath(m_udev, path);
|
||||
|
||||
QString devicePath = QString::fromLatin1(udev_device_get_property_value(device,"DEVNAME"));
|
||||
udev_device_unref(device);
|
||||
|
||||
qCDebug(dcUsbRelay()) << "[+]" << devicePath;
|
||||
m_devicePaths.append(devicePath);
|
||||
emit deviceAdded(devicePath);
|
||||
}
|
||||
|
||||
udev_enumerate_unref(enumerate);
|
||||
|
||||
// Create socket notifier for read
|
||||
m_notifier = new QSocketNotifier(udev_monitor_get_fd(m_monitor), QSocketNotifier::Read, this );
|
||||
connect(m_notifier, &QSocketNotifier::activated, this, [this](int socket){
|
||||
|
||||
Q_UNUSED(socket)
|
||||
|
||||
// Create udev device
|
||||
udev_device *device = udev_monitor_receive_device(m_monitor);
|
||||
if (!device) {
|
||||
qCWarning(dcUsbRelay()) << "Got socket sotification but could not read device information.";
|
||||
return;
|
||||
}
|
||||
|
||||
QString actionString = QString::fromLatin1(udev_device_get_action(device));
|
||||
QString devicePath = QString::fromLatin1(udev_device_get_property_value(device,"DEVNAME"));
|
||||
|
||||
// Clean udev device
|
||||
udev_device_unref(device);
|
||||
|
||||
if (actionString.isEmpty())
|
||||
return;
|
||||
|
||||
if (actionString == "add") {
|
||||
qCDebug(dcUsbRelay()) << "[+]" << devicePath;
|
||||
if (!m_devicePaths.contains(devicePath)) {
|
||||
m_devicePaths.append(devicePath);
|
||||
emit deviceAdded(devicePath);
|
||||
}
|
||||
}
|
||||
|
||||
if (actionString == "remove") {
|
||||
qCDebug(dcUsbRelay()) << "[-]" << devicePath;
|
||||
if (m_devicePaths.contains(devicePath)) {
|
||||
m_devicePaths.removeAll(devicePath);
|
||||
emit deviceRemoved(devicePath);
|
||||
}
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
m_notifier->setEnabled(true);
|
||||
qCDebug(dcUsbRelay()) << "Usb device watcher initialized successfully.";
|
||||
}
|
||||
|
||||
RawHidDeviceWatcher::~RawHidDeviceWatcher()
|
||||
{
|
||||
if (m_monitor)
|
||||
udev_monitor_unref(m_monitor);
|
||||
|
||||
if (m_udev)
|
||||
udev_unref(m_udev);
|
||||
}
|
||||
|
||||
QStringList RawHidDeviceWatcher::devicePaths() const
|
||||
{
|
||||
return m_devicePaths;
|
||||
}
|
||||
|
||||
53
usbrelay/rawhiddevicewatcher.h
Normal file
53
usbrelay/rawhiddevicewatcher.h
Normal file
@ -0,0 +1,53 @@
|
||||
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||
* *
|
||||
* Copyright (C) 2019 Simon Stürz <simon.stuerz@nymea.io> *
|
||||
* *
|
||||
* This file is part of nymea. *
|
||||
* *
|
||||
* This library is free software; you can redistribute it and/or *
|
||||
* modify it under the terms of the GNU Lesser General Public *
|
||||
* License as published by the Free Software Foundation; either *
|
||||
* version 2.1 of the License, or (at your option) any later version. *
|
||||
* *
|
||||
* This library 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 library; If not, see *
|
||||
* <http://www.gnu.org/licenses/>. *
|
||||
* *
|
||||
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||||
|
||||
#ifndef USBDEVICEWATCHER_H
|
||||
#define USBDEVICEWATCHER_H
|
||||
|
||||
#include <QDebug>
|
||||
#include <QObject>
|
||||
#include <QSocketNotifier>
|
||||
|
||||
#include <libudev.h>
|
||||
|
||||
class RawHidDeviceWatcher : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit RawHidDeviceWatcher(QObject *parent = nullptr);
|
||||
~RawHidDeviceWatcher();
|
||||
|
||||
QStringList devicePaths() const;
|
||||
|
||||
private:
|
||||
struct udev *m_udev = nullptr;
|
||||
struct udev_monitor *m_monitor = nullptr;
|
||||
QSocketNotifier *m_notifier = nullptr;
|
||||
QStringList m_devicePaths;
|
||||
|
||||
signals:
|
||||
void deviceAdded(const QString &devicePath);
|
||||
void deviceRemoved(const QString &devicePath);
|
||||
|
||||
};
|
||||
|
||||
#endif // USBDEVICEWATCHER_H
|
||||
@ -0,0 +1,100 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!DOCTYPE TS>
|
||||
<TS version="2.1">
|
||||
<context>
|
||||
<name>MaveoUsbRelay</name>
|
||||
<message>
|
||||
<location filename="../../build-maveousbrelay-Desktop-Debug/plugininfo.h" line="39"/>
|
||||
<location filename="../../build-maveousbrelay-Desktop-Debug/plugininfo.h" line="42"/>
|
||||
<source>Connected</source>
|
||||
<extracomment>The name of the ParamType (DeviceClass: usbRelay, EventType: connected, ID: {ccb0ab2e-5507-4742-b2e0-0cd2aec95df6})
|
||||
----------
|
||||
The name of the StateType ({ccb0ab2e-5507-4742-b2e0-0cd2aec95df6}) of DeviceClass usbRelay</extracomment>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../build-maveousbrelay-Desktop-Debug/plugininfo.h" line="45"/>
|
||||
<source>Connected changed</source>
|
||||
<extracomment>The name of the EventType ({ccb0ab2e-5507-4742-b2e0-0cd2aec95df6}) of DeviceClass usbRelay</extracomment>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../build-maveousbrelay-Desktop-Debug/plugininfo.h" line="48"/>
|
||||
<source>Impulse relay 1</source>
|
||||
<extracomment>The name of the ActionType ({35590728-12ff-4afe-a6be-7ba69ce81b63}) of DeviceClass usbRelay</extracomment>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../build-maveousbrelay-Desktop-Debug/plugininfo.h" line="51"/>
|
||||
<source>Impulse relay 2</source>
|
||||
<extracomment>The name of the ActionType ({63bfdae2-1c0f-4548-81cd-f64be5303f20}) of DeviceClass usbRelay</extracomment>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../build-maveousbrelay-Desktop-Debug/plugininfo.h" line="54"/>
|
||||
<source>Maveo USB Relay</source>
|
||||
<extracomment>The name of the DeviceClass ({942a187f-bdec-4527-8696-45d4891e7d6b})</extracomment>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../build-maveousbrelay-Desktop-Debug/plugininfo.h" line="57"/>
|
||||
<source>Maveo USB relay</source>
|
||||
<extracomment>The name of the plugin MaveoUsbRelay ({ddb4823d-0918-498e-87bc-6ae1a652538c})</extracomment>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../build-maveousbrelay-Desktop-Debug/plugininfo.h" line="60"/>
|
||||
<location filename="../../build-maveousbrelay-Desktop-Debug/plugininfo.h" line="63"/>
|
||||
<location filename="../../build-maveousbrelay-Desktop-Debug/plugininfo.h" line="66"/>
|
||||
<location filename="../../build-maveousbrelay-Desktop-Debug/plugininfo.h" line="69"/>
|
||||
<source>Power relay 1</source>
|
||||
<extracomment>The name of the ParamType (DeviceClass: usbRelay, ActionType: powerOne, ID: {39d85190-739f-474f-b04c-e0627d681bb2})
|
||||
----------
|
||||
The name of the ParamType (DeviceClass: usbRelay, EventType: powerOne, ID: {39d85190-739f-474f-b04c-e0627d681bb2})
|
||||
----------
|
||||
The name of the EventType ({39d85190-739f-474f-b04c-e0627d681bb2}) of DeviceClass usbRelay
|
||||
----------
|
||||
The name of the StateType ({39d85190-739f-474f-b04c-e0627d681bb2}) of DeviceClass usbRelay</extracomment>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../build-maveousbrelay-Desktop-Debug/plugininfo.h" line="72"/>
|
||||
<location filename="../../build-maveousbrelay-Desktop-Debug/plugininfo.h" line="75"/>
|
||||
<location filename="../../build-maveousbrelay-Desktop-Debug/plugininfo.h" line="78"/>
|
||||
<location filename="../../build-maveousbrelay-Desktop-Debug/plugininfo.h" line="81"/>
|
||||
<source>Power relay 2</source>
|
||||
<extracomment>The name of the ParamType (DeviceClass: usbRelay, ActionType: powerTwo, ID: {294376f7-7d21-4989-8803-ad5bffe08c48})
|
||||
----------
|
||||
The name of the ParamType (DeviceClass: usbRelay, EventType: powerTwo, ID: {294376f7-7d21-4989-8803-ad5bffe08c48})
|
||||
----------
|
||||
The name of the EventType ({294376f7-7d21-4989-8803-ad5bffe08c48}) of DeviceClass usbRelay
|
||||
----------
|
||||
The name of the StateType ({294376f7-7d21-4989-8803-ad5bffe08c48}) of DeviceClass usbRelay</extracomment>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../build-maveousbrelay-Desktop-Debug/plugininfo.h" line="84"/>
|
||||
<source>Set power relay 1</source>
|
||||
<extracomment>The name of the ActionType ({39d85190-739f-474f-b04c-e0627d681bb2}) of DeviceClass usbRelay</extracomment>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../build-maveousbrelay-Desktop-Debug/plugininfo.h" line="87"/>
|
||||
<source>Set power relay 2</source>
|
||||
<extracomment>The name of the ActionType ({294376f7-7d21-4989-8803-ad5bffe08c48}) of DeviceClass usbRelay</extracomment>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../build-maveousbrelay-Desktop-Debug/plugininfo.h" line="90"/>
|
||||
<source>System path</source>
|
||||
<extracomment>The name of the ParamType (DeviceClass: usbRelay, Type: device, ID: {a3644b93-1c37-472e-9303-a116feb33067})</extracomment>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../build-maveousbrelay-Desktop-Debug/plugininfo.h" line="93"/>
|
||||
<source>maveo</source>
|
||||
<extracomment>The name of the vendor ({e77e72ae-1228-42a3-85cd-34c6f3a8d494})</extracomment>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
</context>
|
||||
</TS>
|
||||
188
usbrelay/usbrelay.cpp
Normal file
188
usbrelay/usbrelay.cpp
Normal file
@ -0,0 +1,188 @@
|
||||
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||
* *
|
||||
* Copyright (C) 2019 Simon Stürz <simon.stuerz@nymea.io> *
|
||||
* *
|
||||
* This file is part of nymea. *
|
||||
* *
|
||||
* This library is free software; you can redistribute it and/or *
|
||||
* modify it under the terms of the GNU Lesser General Public *
|
||||
* License as published by the Free Software Foundation; either *
|
||||
* version 2.1 of the License, or (at your option) any later version. *
|
||||
* *
|
||||
* This library 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 library; If not, see *
|
||||
* <http://www.gnu.org/licenses/>. *
|
||||
* *
|
||||
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||||
|
||||
#include "usbrelay.h"
|
||||
#include "extern-plugininfo.h"
|
||||
|
||||
UsbRelay::UsbRelay(const QString &path, int relayCount, QObject *parent) :
|
||||
QObject(parent),
|
||||
m_path(path),
|
||||
m_relayCount(relayCount)
|
||||
{
|
||||
m_deviceWatcher = new RawHidDeviceWatcher(this);
|
||||
|
||||
connect(m_deviceWatcher, &RawHidDeviceWatcher::deviceAdded, this, &UsbRelay::onDeviceAdded);
|
||||
connect(m_deviceWatcher, &RawHidDeviceWatcher::deviceRemoved, this, &UsbRelay::onDeviceRemoved);
|
||||
|
||||
if (m_deviceWatcher->devicePaths().contains(m_path)) {
|
||||
setConnected(true);
|
||||
}
|
||||
|
||||
// Create initial relay map
|
||||
for (int i = 0; i < m_relayCount; i++) {
|
||||
m_relayMap.insert(i + 1, false);
|
||||
}
|
||||
}
|
||||
|
||||
UsbRelay::~UsbRelay()
|
||||
{
|
||||
if (m_hidDevice)
|
||||
hid_close(m_hidDevice);
|
||||
|
||||
hid_exit();
|
||||
}
|
||||
|
||||
QString UsbRelay::path() const
|
||||
{
|
||||
return m_path;
|
||||
}
|
||||
|
||||
int UsbRelay::relayCount() const
|
||||
{
|
||||
return m_relayCount;
|
||||
}
|
||||
|
||||
bool UsbRelay::connected() const
|
||||
{
|
||||
return m_connected;
|
||||
}
|
||||
|
||||
bool UsbRelay::relayPower(int relayNumber) const
|
||||
{
|
||||
return m_relayMap[relayNumber];
|
||||
}
|
||||
|
||||
bool UsbRelay::setRelayPower(int relayNumber, bool power)
|
||||
{
|
||||
if (!m_connected) {
|
||||
qCWarning(dcUsbRelay()) << "Could not set power of relay" << relayNumber << "because the device is not connected.";
|
||||
return false;
|
||||
}
|
||||
|
||||
if (relayNumber > m_relayCount) {
|
||||
qCWarning(dcUsbRelay()) << "Could not set power of relay power because the relay number is invalid" << relayNumber << ">" << m_relayCount;
|
||||
return false;
|
||||
}
|
||||
|
||||
return switchRelay(relayNumber, power);
|
||||
}
|
||||
|
||||
void UsbRelay::setConnected(bool connected)
|
||||
{
|
||||
if (m_connected == connected)
|
||||
return;
|
||||
|
||||
qCDebug(dcUsbRelay()) << m_path << (connected ? "connected" : "disconnected");
|
||||
if (connected) {
|
||||
// Initialize the device
|
||||
m_hidDevice = hid_open_path(m_path.toLatin1().data());
|
||||
if (!m_hidDevice) {
|
||||
qCWarning(dcUsbRelay()) << "Could nor open HID device for" << m_path;
|
||||
m_connected = false;
|
||||
emit connectedChanged(m_connected);
|
||||
}
|
||||
|
||||
readStatus();
|
||||
|
||||
} else {
|
||||
// Deinitialize
|
||||
if (m_hidDevice) {
|
||||
hid_close(m_hidDevice);
|
||||
m_hidDevice = nullptr;
|
||||
hid_exit();
|
||||
}
|
||||
}
|
||||
|
||||
m_connected = connected;
|
||||
emit connectedChanged(m_connected);
|
||||
}
|
||||
|
||||
void UsbRelay::setRelayPowerInternally(int relayNumber, bool power)
|
||||
{
|
||||
if (m_relayMap[relayNumber] == power)
|
||||
return;
|
||||
|
||||
qCDebug(dcUsbRelay()) << "Relay power changed" << relayNumber << power;
|
||||
m_relayMap[relayNumber] = power;
|
||||
emit relayPowerChanged(relayNumber, power);
|
||||
}
|
||||
|
||||
void UsbRelay::readStatus()
|
||||
{
|
||||
qCDebug(dcUsbRelay()) << "Read relay status of" << m_path;
|
||||
unsigned char buf[9];
|
||||
buf[0] = 0x01;
|
||||
int ret = hid_get_feature_report(m_hidDevice, buf, sizeof(buf));
|
||||
if (ret < 0) {
|
||||
qCWarning(dcUsbRelay()) << "Could not create HID device for reading" << m_path;
|
||||
hid_close(m_hidDevice);
|
||||
m_hidDevice = nullptr;
|
||||
|
||||
m_connected = false;
|
||||
emit connectedChanged(m_connected);
|
||||
return;
|
||||
}
|
||||
|
||||
quint8 relayStatus = static_cast<quint8>(buf[7]);
|
||||
|
||||
for (int i = 0; i < m_relayCount; i++) {
|
||||
int relayNumber = i + 1;
|
||||
bool power = static_cast<bool>(relayStatus & 1 << i);
|
||||
qCDebug(dcUsbRelay()) << "--> Relay" << relayNumber << power;
|
||||
setRelayPowerInternally(relayNumber, power);
|
||||
}
|
||||
}
|
||||
|
||||
bool UsbRelay::switchRelay(int relayNumber, bool power)
|
||||
{
|
||||
if (!m_hidDevice) {
|
||||
qCWarning(dcUsbRelay()) << "Cannot switch power for" << m_path << "because there is no HID device.";
|
||||
return false;
|
||||
}
|
||||
|
||||
unsigned char buf[9]; // 1 extra byte for the report ID
|
||||
memset(buf, 0x00, sizeof (buf));
|
||||
buf[1] = power ? 0xff : 0xfd;
|
||||
buf[2] = static_cast<unsigned char>(relayNumber); // Relay number
|
||||
|
||||
if (hid_write(m_hidDevice, buf, sizeof(buf)) <= 0) {
|
||||
qCWarning(dcUsbRelay()) << "Cannot switch power for" << m_path << "because could not write to HID device.";
|
||||
return false;
|
||||
}
|
||||
|
||||
readStatus();
|
||||
return true;
|
||||
}
|
||||
|
||||
void UsbRelay::onDeviceAdded(const QString &devicePath)
|
||||
{
|
||||
if (devicePath == m_path) {
|
||||
setConnected(true);
|
||||
}
|
||||
}
|
||||
|
||||
void UsbRelay::onDeviceRemoved(const QString &devicePath)
|
||||
{
|
||||
if (devicePath == m_path) {
|
||||
setConnected(false);
|
||||
}
|
||||
}
|
||||
77
usbrelay/usbrelay.h
Normal file
77
usbrelay/usbrelay.h
Normal file
@ -0,0 +1,77 @@
|
||||
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||
* *
|
||||
* Copyright (C) 2019 Simon Stürz <simon.stuerz@nymea.io> *
|
||||
* *
|
||||
* This file is part of nymea. *
|
||||
* *
|
||||
* This library is free software; you can redistribute it and/or *
|
||||
* modify it under the terms of the GNU Lesser General Public *
|
||||
* License as published by the Free Software Foundation; either *
|
||||
* version 2.1 of the License, or (at your option) any later version. *
|
||||
* *
|
||||
* This library 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 library; If not, see *
|
||||
* <http://www.gnu.org/licenses/>. *
|
||||
* *
|
||||
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||||
|
||||
#ifndef USBRELAY_H
|
||||
#define USBRELAY_H
|
||||
|
||||
#include <QObject>
|
||||
#include <hidapi/hidapi.h>
|
||||
|
||||
#include "rawhiddevicewatcher.h"
|
||||
|
||||
class UsbRelay : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit UsbRelay(const QString &path, int relayCount, QObject *parent = nullptr);
|
||||
~UsbRelay();
|
||||
|
||||
QString path() const;
|
||||
int relayCount() const;
|
||||
|
||||
bool connected() const;
|
||||
|
||||
bool relayPower(int relayNumber) const;
|
||||
bool setRelayPower(int relayNumber, bool power);
|
||||
|
||||
private:
|
||||
RawHidDeviceWatcher *m_deviceWatcher = nullptr;
|
||||
hid_device *m_hidDevice = nullptr;
|
||||
|
||||
QString m_path;
|
||||
int m_relayCount = 0;
|
||||
bool m_connected = false;
|
||||
bool m_relayOnePower = false;
|
||||
bool m_relayTwoPower = false;
|
||||
|
||||
void setConnected(bool connected);
|
||||
|
||||
// Relay map <relay number>, bool value
|
||||
QHash<int, bool> m_relayMap;
|
||||
|
||||
void setRelayPowerInternally(int relayNumber, bool power);
|
||||
|
||||
void readStatus();
|
||||
|
||||
bool switchRelay(int relayNumber, bool power);
|
||||
|
||||
signals:
|
||||
void connectedChanged(bool connected);
|
||||
void relayPowerChanged(int relayNumber, bool power);
|
||||
|
||||
private slots:
|
||||
void onDeviceAdded(const QString &devicePath);
|
||||
void onDeviceRemoved(const QString &devicePath);
|
||||
|
||||
};
|
||||
|
||||
#endif // USBRELAY_H
|
||||
14
usbrelay/usbrelay.pro
Normal file
14
usbrelay/usbrelay.pro
Normal file
@ -0,0 +1,14 @@
|
||||
include(../plugins.pri)
|
||||
|
||||
PKGCONFIG += hidapi-hidraw libudev
|
||||
|
||||
SOURCES += \
|
||||
devicepluginusbrelay.cpp \
|
||||
rawhiddevicewatcher.cpp \
|
||||
usbrelay.cpp
|
||||
|
||||
HEADERS += \
|
||||
devicepluginusbrelay.h \
|
||||
rawhiddevicewatcher.h \
|
||||
usbrelay.h
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user