Merge PR #11: New plugin: UniPi

This commit is contained in:
Jenkins 2018-12-12 14:44:55 +01:00
commit be6eb24cc8
12 changed files with 1459 additions and 4 deletions

11
debian/changelog vendored
View File

@ -1,7 +1,14 @@
nymea-plugins (0.10.0) UNRELEASED; urgency=medium
nymea-plugins (0.10.0) xenial; urgency=medium
[ Michael Zanetti ]
* Elgato/Avea: Fix handling white channel in set color action
* New plugin: Generic MQTT client plugin (mqttclient)
* PhilipsHue: Improve naming of hue devices using nymea's system name
and syncing to bridge
* New plugin: Sonoff-Tasmota devices plugin (tasmota)
* Netatmo: fix after upstream API change, make use of new interfaces
-- Michael Zanetti <michael.zanetti@guh.io> Thu, 29 Nov 2018 12:48:11 +0100
-- Jenkins <jenkins@nymea.io> Sun, 09 Dec 2018 18:56:19 +0100
nymea-plugins (0.9.39) xenial; urgency=medium

16
debian/control vendored
View File

@ -681,6 +681,21 @@ Description: nymea.io plugin for remote ssh connection
This package will install the nymea.io plugin for remote ssh connection
Package: nymea-plugin-unipi
Architecture: any
Depends: ${shlibs:Depends},
${misc:Depends},
nymea-plugins-translations,
Description: nymea.io plugin for remote ssh connection
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 unipi devices
Package: nymea-plugins-translations
Section: misc
Architecture: all
@ -743,6 +758,7 @@ Depends: nymea-plugin-commandlauncher,
nymea-plugin-gpio,
nymea-plugin-mqttclient,
nymea-plugin-remotessh,
nymea-plugin-unipi,
Replaces: guh-plugins-maker
Description: Plugins for nymea IoT server - Meta package for makers, tinkers and hackers
The nymea daemon is a plugin based IoT (Internet of Things) server. The

5
debian/copyright vendored
View File

@ -36,9 +36,10 @@ License: LGPL-2.1
Copyright: 2016, Bernhard Trinnes <bernhard.trinnes@guh.io>
Files: plantcare/*
unipi/*
License: LGPL-2.1
Copyright: 2016-2017, Simon Stürz <simon.stuerz@guh.io>
2016, Bernhard Trinnes <bernhard.trinnes@guh.io>
Copyright: 2016-2018, Simon Stürz <simon.stuerz@guh.io>
2016-2018, Bernhard Trinnes <bernhard.trinnes@guh.io>
Files: pushbullet/*
usbwde/*

1
debian/nymea-plugin-unipi.install.in vendored Normal file
View File

@ -0,0 +1 @@
usr/lib/@DEB_HOST_MULTIARCH@/nymea/plugins/libnymea_devicepluginunipi.so

View File

@ -38,12 +38,14 @@ PLUGIN_DIRS = \
tasmota \
tcpcommander \
udpcommander \
unipi \
unitec \
usbwde \
wakeonlan \
wemo \
ws2812 \
CONFIG+=all
message(============================================)

819
unipi/devicepluginunipi.cpp Normal file
View File

@ -0,0 +1,819 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* *
* Copyright (C) 2017 Bernhard Trinnes <bernhard.trinnes@guh.io> *
* Copyright (C) 2018 Simon Stürz <simon.stuerz@guh.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 "devicepluginunipi.h"
#include "plugininfo.h"
#include <QJsonDocument>
DevicePluginUniPi::DevicePluginUniPi()
{
}
DevicePluginUniPi::~DevicePluginUniPi()
{
hardwareManager()->pluginTimerManager()->unregisterTimer(m_refreshTimer);
}
void DevicePluginUniPi::init()
{
}
DeviceManager::DeviceSetupStatus DevicePluginUniPi::setupDevice(Device *device)
{
connectToEvok();
if(myDevices().empty()) {
m_refreshTimer = hardwareManager()->pluginTimerManager()->registerTimer(60);
connect(m_refreshTimer, &PluginTimer::timeout, this, &DevicePluginUniPi::onRefreshTimer);
}
if (device->deviceClassId() == relayOutputDeviceClassId) {
m_usedRelais.insert(device->paramValue(relayOutputDeviceNumberParamTypeId).toString(), device);
return DeviceManager::DeviceSetupStatusSuccess;
}
if (device->deviceClassId() == digitalOutputDeviceClassId) {
m_usedDigitalOutputs.insert(device->paramValue(digitalOutputDeviceNumberParamTypeId).toString(), device);
return DeviceManager::DeviceSetupStatusSuccess;
}
if (device->deviceClassId() == digitalInputDeviceClassId) {
m_usedDigitalInputs.insert(device->paramValue(digitalInputDeviceNumberParamTypeId).toString(), device);
requestAllData();
return DeviceManager::DeviceSetupStatusSuccess;
}
if (device->deviceClassId() == analogInputDeviceClassId) {
m_usedAnalogInputs.insert(device->paramValue(analogInputDeviceInputNumberParamTypeId).toString(), device);
requestAllData();
return DeviceManager::DeviceSetupStatusSuccess;
}
if (device->deviceClassId() == analogOutputDeviceClassId) {
m_usedAnalogOutputs.insert(device->paramValue(analogOutputDeviceOutputNumberParamTypeId).toString(), device);
return DeviceManager::DeviceSetupStatusSuccess;
}
if (device->deviceClassId() == blindDeviceClassId) {
if (device->paramValue(blindDeviceOutputTypeOpenParamTypeId) == GpioType::Relay) {
m_usedRelais.insert(device->paramValue(blindDeviceOutputOpenParamTypeId).toString(), device);
} else if (device->paramValue(blindDeviceOutputTypeOpenParamTypeId) == GpioType::DigitalOutput) {
m_usedDigitalOutputs.insert(device->paramValue(blindDeviceOutputOpenParamTypeId).toString(), device);
}
if (device->paramValue(blindDeviceOutputTypeCloseParamTypeId) == GpioType::Relay) {
m_usedRelais.insert(device->paramValue(blindDeviceOutputCloseParamTypeId).toString(), device);
} else if (device->paramValue(blindDeviceOutputTypeOpenParamTypeId) == GpioType::DigitalOutput) {
m_usedDigitalOutputs.insert(device->paramValue(blindDeviceOutputCloseParamTypeId).toString(), device);
}
return DeviceManager::DeviceSetupStatusSuccess;
}
if (device->deviceClassId() == lightDeviceClassId) {
if (device->paramValue(lightDeviceOutputTypeParamTypeId) == GpioType::Relay) {
m_usedRelais.insert(device->paramValue(lightDeviceOutputParamTypeId).toString(), device);
} else if (device->paramValue(lightDeviceOutputParamTypeId) == GpioType::DigitalOutput) {
m_usedDigitalOutputs.insert(device->paramValue(lightDeviceOutputParamTypeId).toString(), device);
}
return DeviceManager::DeviceSetupStatusSuccess;
}
if (device->deviceClassId() == dimmerSwitchDeviceClassId) {
m_usedDigitalInputs.insert(device->paramValue(dimmerSwitchDeviceInputNumberParamTypeId).toString(), device);
DimmerSwitch* dimmerSwitch = new DimmerSwitch(this);
connect(dimmerSwitch, &DimmerSwitch::pressed, this, &DevicePluginUniPi::onDimmerSwitchPressed);
connect(dimmerSwitch, &DimmerSwitch::longPressed, this, &DevicePluginUniPi::onDimmerSwitchLongPressed);
connect(dimmerSwitch, &DimmerSwitch::doublePressed, this, &DevicePluginUniPi::onDimmerSwitchDoublePressed);
connect(dimmerSwitch, &DimmerSwitch::dimValueChanged, this, &DevicePluginUniPi::onDimmerSwitchDimValueChanged);
m_dimmerSwitches.insert(dimmerSwitch, device);
return DeviceManager::DeviceSetupStatusSuccess;
}
if (device->deviceClassId() == temperatureSensorDeviceClassId) {
m_usedTemperatureSensors.insert(device->paramValue(temperatureSensorDeviceAddressParamTypeId).toString(), device);
requestAllData();
return DeviceManager::DeviceSetupStatusSuccess;
}
return DeviceManager::DeviceSetupStatusFailure;
}
DeviceManager::DeviceError DevicePluginUniPi::discoverDevices(const DeviceClassId &deviceClassId, const ParamList &params)
{
Q_UNUSED(params);
qSort(m_relais);
qSort(m_digitalOutputs);
qSort(m_digitalInputs);
qSort(m_analogInputs);
qSort(m_analogOutputs);
const DeviceClass deviceClass = deviceManager()->findDeviceClass(deviceClassId);
if (deviceClass.vendorId() == unipiVendorId) {
if (deviceClassId == relayOutputDeviceClassId) {
// Create the list of available relais
QList<DeviceDescriptor> deviceDescriptors;
for (int i = 0; i < m_relais.count(); i++) {
const QString circuit = m_relais.at(i);
// Offer only gpios which arn't in use already
if (m_usedRelais.contains(circuit)){
continue;
}
DeviceDescriptor descriptor(deviceClassId, QString("Relay %1").arg(circuit), circuit);
ParamList parameters;
parameters.append(Param(relayOutputDeviceNumberParamTypeId, circuit));
descriptor.setParams(parameters);
deviceDescriptors.append(descriptor);
}
emit devicesDiscovered(deviceClassId, deviceDescriptors);
return DeviceManager::DeviceErrorAsync;
}
if (deviceClassId == digitalOutputDeviceClassId) {
// Create the list of available digital outputs
QList<DeviceDescriptor> deviceDescriptors;
for (int i = 0; i < m_digitalOutputs.count(); i++) {
const QString circuit = m_digitalOutputs.at(i);
// Offer only gpios which arn't in use already
if (m_usedDigitalOutputs.contains(circuit)){
continue;
}
DeviceDescriptor descriptor(deviceClassId, QString("Digital output %1").arg(circuit), circuit);
ParamList parameters;
parameters.append(Param(digitalOutputDeviceNumberParamTypeId, circuit));
descriptor.setParams(parameters);
deviceDescriptors.append(descriptor);
}
emit devicesDiscovered(deviceClassId, deviceDescriptors);
return DeviceManager::DeviceErrorAsync;
}
if (deviceClassId == digitalInputDeviceClassId) {
// Create the list of available digital inputs
QList<DeviceDescriptor> deviceDescriptors;
for (int i = 0; i < m_digitalInputs.count(); i++) {
const QString circuit = m_digitalInputs.at(i);
// Offer only digital inputs which arn't in use already
if (m_usedDigitalInputs.contains(circuit)){
continue;
}
DeviceDescriptor descriptor(deviceClassId, QString("Digital input %1").arg(circuit), circuit);
ParamList parameters;
parameters.append(Param(digitalInputDeviceNumberParamTypeId, circuit));
descriptor.setParams(parameters);
deviceDescriptors.append(descriptor);
}
emit devicesDiscovered(deviceClassId, deviceDescriptors);
return DeviceManager::DeviceErrorAsync;
}
if (deviceClassId == analogInputDeviceClassId) {
// Create the list of available digital inputs
QList<DeviceDescriptor> deviceDescriptors;
for (int i = 0; i < m_analogInputs.count(); i++) {
const QString circuit = m_analogInputs.at(i);
// Offer only analog inputs which aren't in use already
if (m_usedAnalogInputs.contains(circuit)){
continue;
}
DeviceDescriptor descriptor(deviceClassId, QString("Analog input %1").arg(circuit), circuit);
ParamList parameters;
parameters.append(Param(analogInputDeviceInputNumberParamTypeId, circuit));
descriptor.setParams(parameters);
deviceDescriptors.append(descriptor);
}
emit devicesDiscovered(deviceClassId, deviceDescriptors);
return DeviceManager::DeviceErrorAsync;
}
if (deviceClassId == analogOutputDeviceClassId) {
// Create the list of available digital inputs
QList<DeviceDescriptor> deviceDescriptors;
for (int i = 0; i < m_analogOutputs.count(); i++) {
const QString circuit = m_analogOutputs.at(i);
// Offer only digital inputs which arn't in use already
if (m_usedAnalogOutputs.contains(circuit)){
continue;
}
DeviceDescriptor descriptor(deviceClassId, QString("Analog Output %1").arg(circuit), circuit);
ParamList parameters;
parameters.append(Param(analogOutputDeviceOutputNumberParamTypeId, circuit));
descriptor.setParams(parameters);
deviceDescriptors.append(descriptor);
}
emit devicesDiscovered(deviceClassId, deviceDescriptors);
return DeviceManager::DeviceErrorAsync;
}
if (deviceClassId == blindDeviceClassId) {
// Create the list of available gpios
QList<DeviceDescriptor> deviceDescriptors;
for (int i = 0; i < (m_relais.count()-1); i++) {
const QString openingCircuit = m_relais.at(i);
// Offer only relais which aren't in use already
if (m_usedRelais.contains(openingCircuit)){
continue;
}
for (int a = (i+1); a < (m_relais.count()); a++) {
const QString closingCircuit = m_relais.at(a);
// Offer only relais which aren't in use already
if (!m_usedRelais.contains(closingCircuit)){
DeviceDescriptor descriptor(deviceClassId, "Blind", QString("Opening relay %1 | Closing relay %2").arg(openingCircuit, closingCircuit));
ParamList parameters;
parameters.append(Param(blindDeviceOutputOpenParamTypeId, openingCircuit));
parameters.append(Param(blindDeviceOutputCloseParamTypeId, closingCircuit));
parameters.append(Param(blindDeviceOutputTypeOpenParamTypeId, GpioType::Relay));
parameters.append(Param(blindDeviceOutputTypeCloseParamTypeId, GpioType::Relay));
descriptor.setParams(parameters);
deviceDescriptors.append(descriptor);
break;
}
}
}
for (int i = 0; i < (m_digitalOutputs.count()-1); i++) {
const QString openingCircuit = m_digitalOutputs.at(i);
// Offer only relais which aren't in use already
if (m_usedDigitalOutputs.contains(openingCircuit)){
continue;
}
for (int a = (i+1); a < (m_digitalOutputs.count()); a++) {
const QString closingCircuit = m_digitalOutputs.at(a);
// Offer only relais which aren't in use already
if (!m_usedDigitalOutputs.contains(closingCircuit)){
DeviceDescriptor descriptor(deviceClassId, "Blind", QString("Opening output %1 | Closing output %2").arg(openingCircuit, closingCircuit));
ParamList parameters;
parameters.append(Param(blindDeviceOutputOpenParamTypeId, openingCircuit));
parameters.append(Param(blindDeviceOutputCloseParamTypeId, closingCircuit));
parameters.append(Param(blindDeviceOutputTypeOpenParamTypeId, GpioType::DigitalOutput));
parameters.append(Param(blindDeviceOutputTypeCloseParamTypeId, GpioType::DigitalOutput));
descriptor.setParams(parameters);
deviceDescriptors.append(descriptor);
break;
}
}
}
emit devicesDiscovered(deviceClassId, deviceDescriptors);
return DeviceManager::DeviceErrorAsync;
}
if (deviceClassId == lightDeviceClassId) {
// Create the list of available gpios
QList<DeviceDescriptor> deviceDescriptors;
for (int i = 0; i < m_relais.count(); i++) {
const QString circuit = m_relais.at(i);
// Offer only gpios which arn't in use already
if (m_usedRelais.contains(circuit)){
continue;
}
DeviceDescriptor descriptor(deviceClassId, "Light", QString("Relay %1").arg(circuit));
ParamList parameters;
parameters.append(Param(lightDeviceOutputParamTypeId, circuit));
parameters.append(Param(lightDeviceOutputTypeParamTypeId, GpioType::Relay));
descriptor.setParams(parameters);
deviceDescriptors.append(descriptor);
}
for (int i = 0; i < m_digitalOutputs.count(); i++) {
const QString circuit = m_digitalOutputs.at(i);
// Offer only gpios which arn't in use already
if (m_usedDigitalOutputs.contains(circuit)){
continue;
}
DeviceDescriptor descriptor(deviceClassId, "Light", QString("Digital output %1").arg(circuit));
ParamList parameters;
parameters.append(Param(lightDeviceOutputParamTypeId, circuit));
parameters.append(Param(lightDeviceOutputTypeParamTypeId, GpioType::DigitalOutput));
descriptor.setParams(parameters);
deviceDescriptors.append(descriptor);
}
emit devicesDiscovered(deviceClassId, deviceDescriptors);
return DeviceManager::DeviceErrorAsync;
}
if (deviceClassId == dimmerSwitchDeviceClassId) {
// Create the list of available digital inputs
QList<DeviceDescriptor> deviceDescriptors;
for (int i = 0; i < m_digitalInputs.count(); i++) {
const QString circuit = m_digitalInputs.at(i);
// Offer only digital inputs which arn't in use already
if (m_usedDigitalInputs.contains(circuit)){
continue;
}
DeviceDescriptor descriptor(deviceClassId, "Dimmer switch", QString("Digital Input %1").arg(circuit));
ParamList parameters;
parameters.append(Param(dimmerSwitchDeviceInputNumberParamTypeId, circuit));
descriptor.setParams(parameters);
deviceDescriptors.append(descriptor);
}
emit devicesDiscovered(deviceClassId, deviceDescriptors);
return DeviceManager::DeviceErrorAsync;
}
if (deviceClassId == temperatureSensorDeviceClassId) {
// Create the list of available temperature sensor
QList<DeviceDescriptor> deviceDescriptors;
for (int i = 0; i < m_temperatureSensors.count(); i++) {
const QString circuit = m_temperatureSensors.at(i);
// Offer only temperature sensors which aren't in use already
if (m_usedTemperatureSensors.contains(circuit)){
continue;
}
DeviceDescriptor descriptor(deviceClassId, "Temperature Sensor", circuit);
ParamList parameters;
parameters.append(Param(temperatureSensorDeviceAddressParamTypeId, circuit));
descriptor.setParams(parameters);
deviceDescriptors.append(descriptor);
}
emit devicesDiscovered(deviceClassId, deviceDescriptors);
return DeviceManager::DeviceErrorAsync;
}
}
return DeviceManager::DeviceErrorDeviceClassNotFound;
}
void DevicePluginUniPi::setOutput(const QString &circuit, bool value)
{
QJsonObject json;
json["cmd"] = "set";
json["dev"] = "relay";
json["circuit"] = circuit;
json["value"] = value;
QJsonDocument doc(json);
QByteArray bytes = doc.toJson(QJsonDocument::Compact);
qCDebug(dcUniPi()) << "Send command" << bytes;
m_webSocket->sendBinaryMessage(bytes);
}
void DevicePluginUniPi::connectToEvok()
{
if ((m_webSocket == NULL) || !m_webSocket) {
int port = configValue(uniPiPluginPortParamTypeId).toInt();
m_webSocket = new QWebSocket();
connect(m_webSocket, &QWebSocket::connected, this, &DevicePluginUniPi::onWebSocketConnected);
connect(m_webSocket, &QWebSocket::disconnected, this, &DevicePluginUniPi::onWebSocketDisconnected);
QUrl url = QUrl("ws://localhost/ws");
url.setPort(port);
qCDebug(dcUniPi()) << "Conneting to:" << url.toString();
m_webSocket->open(url);
} else {
requestAllData();
}
}
void DevicePluginUniPi::deviceRemoved(Device *device)
{
if(device->deviceClassId() == relayOutputDeviceClassId) {
m_usedRelais.remove(device->paramValue(relayOutputDeviceNumberParamTypeId).toString());
} else if(device->deviceClassId() == digitalOutputDeviceClassId) {
m_usedDigitalOutputs.remove(device->paramValue(digitalOutputDeviceNumberParamTypeId).toString());
} else if(device->deviceClassId() == digitalInputDeviceClassId) {
m_usedDigitalInputs.remove(device->paramValue(digitalInputDeviceNumberParamTypeId).toString());
} else if (device->deviceClassId() == analogOutputDeviceClassId) {
m_usedAnalogOutputs.remove(device->paramValue(analogOutputDeviceOutputNumberParamTypeId).toString());
} else if (device->deviceClassId() == analogInputDeviceClassId) {
m_usedAnalogInputs.remove(device->paramValue(analogInputDeviceInputNumberParamTypeId).toString());
} else if (device->deviceClassId() == blindDeviceClassId) {
if (device->paramValue(blindDeviceOutputTypeOpenParamTypeId) == GpioType::Relay) {
m_usedRelais.remove(device->paramValue(blindDeviceOutputOpenParamTypeId).toString());
} else if (device->paramValue(blindDeviceOutputOpenParamTypeId) == GpioType::DigitalOutput) {
m_usedDigitalOutputs.remove(device->paramValue(blindDeviceOutputOpenParamTypeId).toString());
}
if (device->paramValue(blindDeviceOutputTypeCloseParamTypeId) == GpioType::Relay) {
m_usedRelais.remove(device->paramValue(blindDeviceOutputCloseParamTypeId).toString());
} else if (device->paramValue(blindDeviceOutputOpenParamTypeId) == GpioType::DigitalOutput) {
m_usedDigitalOutputs.remove(device->paramValue(blindDeviceOutputCloseParamTypeId).toString());
}
} else if (device->deviceClassId() == lightDeviceClassId) {
if (device->paramValue(lightDeviceOutputTypeParamTypeId) == GpioType::Relay) {
m_usedRelais.remove(device->paramValue(lightDeviceOutputParamTypeId).toString());
} else if (device->paramValue(lightDeviceOutputParamTypeId) == GpioType::DigitalOutput) {
m_usedDigitalOutputs.remove(device->paramValue(lightDeviceOutputParamTypeId).toString());
}
} else if (device->deviceClassId() == dimmerSwitchDeviceClassId) {
m_usedDigitalInputs.remove(device->paramValue(dimmerSwitchDeviceInputNumberParamTypeId).toString());
DimmerSwitch *dimmerSwitch = m_dimmerSwitches.key(device);
m_dimmerSwitches.remove(dimmerSwitch);
dimmerSwitch->deleteLater();
} else if (device->deviceClassId() == temperatureSensorDeviceClassId) {
m_usedTemperatureSensors.remove(device->paramValue(temperatureSensorDeviceAddressParamTypeId).toString());
}
if (myDevices().isEmpty()) {
m_webSocket->close();
m_webSocket->deleteLater();
}
}
DeviceManager::DeviceError DevicePluginUniPi::executeAction(Device *device, const Action &action)
{
if (m_webSocket->state() != QAbstractSocket::ConnectedState)
return DeviceManager::DeviceErrorHardwareNotAvailable;
if (device->deviceClassId() == relayOutputDeviceClassId) {
if (action.actionTypeId() == relayOutputPowerActionTypeId) {
QString relayNumber = device->paramValue(relayOutputDeviceNumberParamTypeId).toString();
int stateValue = action.param(relayOutputPowerActionPowerParamTypeId).value().toInt();
setOutput(relayNumber, stateValue);
return DeviceManager::DeviceErrorNoError;
}
return DeviceManager::DeviceErrorActionTypeNotFound;
}
if (device->deviceClassId() == digitalOutputDeviceClassId) {
if (action.actionTypeId() == digitalOutputPowerActionTypeId) {
QString digitalOutputNumber = device->paramValue(digitalOutputDeviceNumberParamTypeId).toString();
bool stateValue = action.param(digitalOutputPowerActionPowerParamTypeId).value().toBool();
setOutput(digitalOutputNumber, stateValue);
return DeviceManager::DeviceErrorNoError;
}
return DeviceManager::DeviceErrorActionTypeNotFound;
}
if (device->deviceClassId() == analogOutputDeviceClassId) {
if (action.actionTypeId() == analogOutputOutputValueActionTypeId) {
QString analogOutputNumber = device->paramValue(analogOutputDeviceOutputNumberParamTypeId).toString();
double analogValue = action.param(analogOutputOutputValueActionOutputValueParamTypeId).value().toDouble();
QJsonObject json;
json["cmd"] = "set";
json["dev"] = "ao";
json["circuit"] = analogOutputNumber;
json["value"] = analogValue;
QJsonDocument doc(json);
QByteArray bytes = doc.toJson(QJsonDocument::Compact);
qCDebug(dcUniPi()) << "Send command" << bytes;
m_webSocket->sendTextMessage(bytes);
return DeviceManager::DeviceErrorNoError;
}
return DeviceManager::DeviceErrorActionTypeNotFound;
}
if (device->deviceClassId() == blindDeviceClassId) {
QString circuitOpen = device->paramValue(blindDeviceOutputOpenParamTypeId).toString();
QString circuitClose = device->paramValue(blindDeviceOutputCloseParamTypeId).toString();
if (action.actionTypeId() == blindCloseActionTypeId) {
setOutput(circuitOpen, false);
setOutput(circuitClose, true);
return DeviceManager::DeviceErrorNoError;
}
if (action.actionTypeId() == blindOpenActionTypeId) {
setOutput(circuitClose, false);
setOutput(circuitOpen, true);
return DeviceManager::DeviceErrorNoError;
}
if (action.actionTypeId() == blindStopActionTypeId) {
setOutput(circuitOpen, false);
setOutput(circuitClose, false);
return DeviceManager::DeviceErrorNoError;
}
return DeviceManager::DeviceErrorActionTypeNotFound;
}
if (device->deviceClassId() == lightDeviceClassId) {
QString circuit = device->paramValue(lightDeviceOutputParamTypeId).toString();
bool stateValue = action.param(lightPowerActionPowerParamTypeId).value().toBool();
setOutput(circuit, stateValue);
return DeviceManager::DeviceErrorNoError;
}
return DeviceManager::DeviceErrorDeviceClassNotFound;
}
void DevicePluginUniPi::onWebSocketConnected()
{
qCDebug(dcUniPi()) << "WebSocket connected";
connect(m_webSocket, &QWebSocket::textMessageReceived,
this, &DevicePluginUniPi::onWebSocketTextMessageReceived);
requestAllData();
}
void DevicePluginUniPi::onWebSocketDisconnected()
{
qCDebug(dcUniPi()) << "WebSocket disconnected";
}
void DevicePluginUniPi::requestAllData()
{
QJsonObject json;
json["cmd"] = "all";
QJsonDocument doc(json);
QByteArray bytes = doc.toJson();
m_webSocket->sendTextMessage(bytes);
}
void DevicePluginUniPi::onWebSocketTextMessageReceived(const QString &message)
{
QJsonArray array;
QJsonParseError error;
QJsonDocument doc = QJsonDocument::fromJson(message.toUtf8(), &error);
if(error.error != QJsonParseError::NoError) {
qCWarning(dcUniPi) << "failed to parse data" << message << ":" << error.errorString();
return;
}
// check validity of the document
if(!doc.isNull()) {
if(doc.isObject()) {
array.append(doc.object());
} else if (doc.isArray()){
array = doc.array();;
}else {
qCDebug(dcUniPi()) << "Document is not an object nor an array";
}
} else {
qCDebug(dcUniPi()) << "Invalid JSON";
return;
}
for (int levelIndex = 0; levelIndex < array.size(); ++levelIndex) {
QJsonObject obj;
obj = array[levelIndex].toObject();
if (obj["dev"] == "relay") {
qCDebug(dcUniPi()) << "Relay:" << "Circuit:" << obj["circuit"].toString() << "Value:" << obj["value"].toInt() << "Relay Type:" << obj["relay_type"].toString() ;
QString circuit = obj["circuit"].toString();
bool value = obj["value"].toBool();
if ((obj["relay_type"].toString() == "physical") || (obj["relay_type"].toString() == "")) {
if (!m_relais.contains(circuit)) {
//New Device detected
m_relais.append(circuit);
} else {
if (m_usedRelais.contains(circuit)) {
Device *device = m_usedRelais.value(circuit);
if (device->deviceClassId() == relayOutputDeviceClassId) {
device->setStateValue(relayOutputPowerStateTypeId, value);
} else if (device->deviceClassId() == blindDeviceClassId) {
if (circuit == device->paramValue(blindDeviceOutputOpenParamTypeId).toString()) {
if (value) {
if (device->stateValue(blindStatusStateTypeId).toString().contains("stopped")) {
device->setStateValue(blindStatusStateTypeId, "opening");
} else if (device->stateValue(blindStatusStateTypeId).toString().contains("closing")) {
device->setStateValue(blindStatusStateTypeId, "opening");
} else if (device->stateValue(blindStatusStateTypeId).toString().contains("opening")) {
//state unchanged
}
} else {
if (device->stateValue(blindStatusStateTypeId).toString().contains("stopped")) {
// state unchanged
} else if (device->stateValue(blindStatusStateTypeId).toString().contains("closing")) {
// state unchanged
} else if (device->stateValue(blindStatusStateTypeId).toString().contains("opening")) {
device->setStateValue(blindStatusStateTypeId, "stopped");
}
}
}
if (circuit == device->paramValue(blindDeviceOutputCloseParamTypeId).toString()) {
if (value) {
if (device->stateValue(blindStatusStateTypeId).toString().contains("stopped")) {
device->setStateValue(blindStatusStateTypeId, "closing");
} else if (device->stateValue(blindStatusStateTypeId).toString().contains("closing")) {
//state unchanged
} else if (device->stateValue(blindStatusStateTypeId).toString().contains("opening")) {
device->setStateValue(blindStatusStateTypeId, "closing");
}
} else {
if (device->stateValue(blindStatusStateTypeId).toString().contains("stopped")) {
// state unchanged
} else if (device->stateValue(blindStatusStateTypeId).toString().contains("closing")) {
device->setStateValue(blindStatusStateTypeId, "stopped");
} else if (device->stateValue(blindStatusStateTypeId).toString().contains("opening")) {
// state unchanged
}
}
}
} else if (device->deviceClassId() == lightDeviceClassId) {
device->setStateValue(lightPowerStateTypeId, value);
}
}
}
} else if (obj["relay_type"].toString() == "digital") {
if (!m_digitalOutputs.contains(obj["circuit"].toString())){
//New Device detected
m_digitalOutputs.append(obj["circuit"].toString());
} else {
if (m_usedDigitalOutputs.contains(obj["circuit"].toString())) {
Device *device = m_usedDigitalOutputs.value(obj["circuit"].toString());
if (device->deviceClassId() == digitalOutputDeviceClassId) {
device->setStateValue(digitalOutputPowerStateTypeId, obj["value"].toBool());
} else if (device->deviceClassId() == blindDeviceClassId) {
if (circuit == device->paramValue(blindDeviceOutputOpenParamTypeId).toString()) {
if (value && device->stateValue(blindStatusStateTypeId).toString().contains("stopped")) {
device->setStateValue(blindStatusStateTypeId, "opening");
} else if (!value && device->stateValue(blindStatusStateTypeId).toString().contains("opening")) {
device->setStateValue(blindStatusStateTypeId, "stopped");
} else {
qCWarning(dcUniPi()) << "blind" << device << "Output open:" << value << "Status: " << device->stateValue(blindStatusStateTypeId).toString();
device->setStateValue(blindStatusStateTypeId, "stopped");
}
}
if (circuit == device->paramValue(blindDeviceOutputCloseParamTypeId).toString()) {
if (value && device->stateValue(blindStatusStateTypeId).toString().contains("stopped")) {
device->setStateValue(blindStatusStateTypeId, "closing");
} else if (!value && device->stateValue(blindStatusStateTypeId).toString().contains("closing")) {
device->setStateValue(blindStatusStateTypeId, "stopped");
} else {
qCWarning(dcUniPi()) << "blind" << device << "Output close:" << value << "Status: " << device->stateValue(blindStatusStateTypeId).toString();
device->setStateValue(blindStatusStateTypeId, "stopped");
}
}
} else if (device->deviceClassId() == lightDeviceClassId) {
device->setStateValue(lightPowerStateTypeId, obj["value"].toBool());
}
}
}
}
}
if (obj["dev"] == "input") {
qCDebug(dcUniPi()) << "Input:" << obj["dev"].toString() << "Circuit:" << obj["circuit"].toString() << "Value:" << obj["value"].toInt();
if (!m_digitalInputs.contains(obj["circuit"].toString())){
//New Device detected
m_digitalInputs.append(obj["circuit"].toString());
} else {
if (m_usedDigitalInputs.contains(obj["circuit"].toString())) {
bool value = obj["value"].toBool();
Device *device = m_usedDigitalInputs.value(obj["circuit"].toString());
if (device->deviceClassId() == digitalInputDeviceClassId) {
device->setStateValue(digitalInputInputStatusStateTypeId, value);
} else if (device->deviceClassId() == dimmerSwitchDeviceClassId) {
device->setStateValue(dimmerSwitchStatusStateTypeId, value);
DimmerSwitch *dimmerSwitch = m_dimmerSwitches.key(device);
dimmerSwitch->setPower(value);
}
}
}
}
if (obj["dev"] == "ao") {
qCDebug(dcUniPi()) << "Analog Output:" << obj["dev"] << "Circuit:" << obj["circuit"].toString() << "Value:" << obj["value"].toDouble();
if (!m_analogOutputs.contains(obj["circuit"].toString())){
//New Device detected
m_analogOutputs.append(obj["circuit"].toString());
} else {
if (m_usedAnalogOutputs.contains(obj["circuit"].toString())) {
double value = obj["value"].toDouble();
Device *device = m_usedAnalogOutputs.value(obj["circuit"].toString());
if (device->deviceClassId() == analogOutputDeviceClassId) {
device->setStateValue(analogOutputOutputValueStateTypeId, value);
}
}
}
}
if (obj["dev"] == "ai") {
qCDebug(dcUniPi()) << "Analog Input:" << obj["dev"] << "Circuit:" << obj["circuit"].toString() << "Value:" << obj["value"].toDouble();
if (!m_analogInputs.contains(obj["circuit"].toString())){
//New analog output detected
m_analogInputs.append(obj["circuit"].toString());
} else {
if (m_usedAnalogInputs.contains(obj["circuit"].toString())) {
double value = obj["value"].toDouble();
Device *device = m_usedAnalogInputs.value(obj["circuit"].toString());
if (device->deviceClassId() == analogInputDeviceClassId) {
device->setStateValue(analogInputInputValueStateTypeId, value);
}
}
}
}
if (obj["dev"] == "temp") {
qCDebug(dcUniPi()) << "Temperature Sensor:" << obj["typ"].toString() << "Address:" << obj["circuit"].toString() << "Value:" << obj["value"].toDouble() << "Connected:" << !(QVariant(obj["lost"]).toBool());
if (!m_temperatureSensors.contains(obj["circuit"].toString())){
//New temperature sensor detected
m_temperatureSensors.append(obj["circuit"].toString());
} else {
//Updating states of already added temperature sensor
if (m_usedTemperatureSensors.contains(obj["circuit"].toString())) {
double value = obj["value"].toDouble();
bool connected = !(obj["lost"]).toBool();
Device *device = m_usedTemperatureSensors.value(obj["circuit"].toString());
if (device->deviceClassId() == temperatureSensorDeviceClassId) {
device->setStateValue(temperatureSensorTemperatureStateTypeId, value);
device->setStateValue(temperatureSensorConnectedStateTypeId, connected);
}
}
}
}
}
}
void DevicePluginUniPi::onRefreshTimer()
{
connectToEvok();
}
void DevicePluginUniPi::onDimmerSwitchPressed()
{
DimmerSwitch *dimmerSwitch = static_cast<DimmerSwitch *>(sender());
Device *device = m_dimmerSwitches.value(dimmerSwitch);
emit emitEvent(Event(dimmerSwitchPressedEventTypeId, device->id()));
}
void DevicePluginUniPi::onDimmerSwitchLongPressed()
{
DimmerSwitch *dimmerSwitch = static_cast<DimmerSwitch *>(sender());
Device *device = m_dimmerSwitches.value(dimmerSwitch);
emit emitEvent(Event(dimmerSwitchLongPressedEventTypeId, device->id()));
}
void DevicePluginUniPi::onDimmerSwitchDoublePressed()
{
DimmerSwitch *dimmerSwitch = static_cast<DimmerSwitch *>(sender());
Device *device = m_dimmerSwitches.value(dimmerSwitch);
emit emitEvent(Event(dimmerSwitchDoublePressedEventTypeId, device->id()));
}
void DevicePluginUniPi::onDimmerSwitchDimValueChanged(int dimValue)
{
DimmerSwitch *dimmerSwitch = static_cast<DimmerSwitch *>(sender());
Device *device = m_dimmerSwitches.value(dimmerSwitch);
device->setStateValue(dimmerSwitchDimValueStateTypeId, dimValue);
}

100
unipi/devicepluginunipi.h Normal file
View File

@ -0,0 +1,100 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* *
* Copyright (C) 2017 Bernhard Trinnes <bernhard.trinnes@guh.io> *
* Copyright (C) 2018 Simon Stürz <simon.stuerz@guh.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 DEVICEPLUGINUNIPI_H
#define DEVICEPLUGINUNIPI_H
#include "plugin/deviceplugin.h"
#include "devicemanager.h"
#include <QtWebSockets/QtWebSockets>
#include "plugintimer.h"
#include "dimmerswitch.h"
class DevicePluginUniPi : public DevicePlugin
{
Q_OBJECT
Q_PLUGIN_METADATA(IID "io.nymea.DevicePlugin" FILE "devicepluginunipi.json")
Q_INTERFACES(DevicePlugin)
public:
explicit DevicePluginUniPi();
~DevicePluginUniPi();
void init() override;
DeviceManager::DeviceSetupStatus setupDevice(Device *device) override;
void deviceRemoved(Device *device) override;
DeviceManager::DeviceError executeAction(Device *device, const Action &action) override;
DeviceManager::DeviceError discoverDevices(const DeviceClassId &deviceClassId, const ParamList &params) override;
private:
enum GpioType {
Relay,
DigitalInput,
DigitalOutput,
AnalogInput,
AnalogOutput
};
QHash<QString, Device*> m_usedRelais;
QHash<QString, Device*> m_usedDigitalOutputs;
QHash<QString, Device*> m_usedDigitalInputs;
QHash<QString, Device*> m_usedAnalogOutputs;
QHash<QString, Device*> m_usedAnalogInputs;
QHash<QString, Device*> m_usedTemperatureSensors;
QHash<QString, Device*> m_usedLeds;
QHash<DimmerSwitch *, Device*> m_dimmerSwitches;
QList<QString> m_relais;
QList<QString> m_digitalOutputs;
QList<QString> m_digitalInputs;
QList<QString> m_analogOutputs;
QList<QString> m_analogInputs;
QList<QString> m_temperatureSensors;
QList<QString> m_leds;
QWebSocket *m_webSocket = nullptr;
PluginTimer *m_refreshTimer = nullptr;
void requestAllData();
void setOutput(const QString &circuit, bool value);
void connectToEvok();
private slots:
void onWebSocketConnected();
void onWebSocketDisconnected();
void onWebSocketTextMessageReceived(const QString &message);
void onRefreshTimer();
void onDimmerSwitchPressed();
void onDimmerSwitchLongPressed();
void onDimmerSwitchDoublePressed();
void onDimmerSwitchDimValueChanged(int dimValue);
};
#endif // DEVICEPLUGINUNIPI_H

View File

@ -0,0 +1,360 @@
{
"displayName": "UniPi",
"name": "UniPi",
"id": "26cba644-35ae-40a6-9c48-924198893a5f",
"paramTypes": [
{
"id": "5329655d-7e91-4b16-9abf-2abc82bf1b3c",
"name": "port",
"displayName": "Port",
"type": "int",
"defaultValue": "8080"
}
],
"vendors": [
{
"displayName": "UniPi",
"name": "unipi",
"id": "c82bfe27-d14d-40bd-b12f-ddba214b5fc5",
"deviceClasses": [
{
"id": "58f9db7f-fd33-45af-8c98-047b67ae5267",
"name": "relayOutput",
"displayName": "Relay output",
"deviceIcon": "Power",
"createMethods": ["discovery"],
"interfaces": ["power"],
"basicTags": ["Device"],
"paramTypes": [
{
"id": "7a09e3ad-452c-4bf4-a00c-f8114ed9a7a1",
"name": "number",
"displayName": "Relay number",
"type": "QString"
}
],
"stateTypes": [
{
"id": "f9c01e7b-0523-4cac-905a-d5b20028e021",
"name": "power",
"displayName": "Power",
"displayNameEvent": "Relay power changed",
"displayNameAction": "Set relay power",
"type": "bool",
"defaultValue": false,
"writable": true
}
]
},
{
"id": "0bec278a-98f1-416b-b496-6d00740f178a",
"name": "digitalInput",
"displayName": "Digital input",
"deviceIcon": "Switch",
"createMethods": ["discovery"],
"interfaces": [ ],
"basicTags": ["Sensor"],
"paramTypes": [
{
"id": "9c84d9b8-fdc7-41c1-9559-08f061ffc7a6",
"name": "number",
"displayName": "Input number",
"type": "QString"
}
],
"stateTypes": [
{
"id": "fa4f2764-b7ff-45e7-993b-b6af1840fd3d",
"name": "inputStatus",
"displayName": "Digital input",
"displayNameEvent": "Digital input changed",
"type": "bool",
"defaultValue": false
}
]
},
{
"id": "71e03d00-1b62-412b-b55d-ab90ad2eddff",
"name": "dimmerSwitch",
"displayName": "Dimmer switch",
"deviceIcon": "Switch",
"createMethods": ["discovery"],
"interfaces": ["longpressbutton"],
"basicTags": ["Sensor"],
"paramTypes": [
{
"id": "2344dedb-3e21-4f59-a016-0fc6233a38ac",
"name": "inputNumber",
"displayName": "Input number",
"type": "QString"
}
],
"stateTypes": [
{
"id": "b39a84ff-45c8-4ec1-b3a9-b99aeefc7221",
"name": "status",
"displayName": "Digital input",
"displayNameEvent": "Digital input changed",
"type": "bool",
"defaultValue": false
},
{
"id": "3e566b7c-11e6-4e97-9d9f-9636c465639e",
"name": "dimValue",
"displayName": "Dim value",
"displayNameEvent": "Dim value changed",
"type": "int",
"defaultValue": 0,
"unit": "Percentage"
}
],
"eventTypes": [
{
"id": "44be91cd-cbeb-477b-bb8c-6a6d4f9aaaf3",
"name": "pressed",
"displayName": "Pressed"
},
{
"id": "a4748afe-dcd6-45ea-8574-7b9c0e925f35",
"name": "longPressed",
"displayName": "Long pressed"
},
{
"id": "7e7b36f5-b871-43a3-a7f0-6cef1e550ad7",
"name": "doublePressed",
"displayName": "Double pressed"
}
]
},
{
"id": "f3a3c5ed-461a-4ca8-930b-df3af821b9e0",
"name": "digitalOutput",
"displayName": "Digital output",
"deviceIcon": "Power",
"createMethods": ["discovery"],
"interfaces": ["power"],
"basicTags": ["Device"],
"paramTypes": [
{
"id": "c01d5bde-de5d-42c5-b462-79745827875a",
"name": "number",
"displayName": "Output number",
"type": "QString"
}
],
"stateTypes": [
{
"id": "470a0e30-a170-47ed-9ed3-c41db919555f",
"name": "power",
"displayName": "Power",
"displayNameAction": "set digital output",
"displayNameEvent": "digital output changed",
"type": "bool",
"defaultValue": false,
"writable": true
}
]
},
{
"id": "9094a69f-f475-4050-a345-5ab52cb19774",
"name": "analogOutput",
"displayName": "Analog output",
"deviceIcon": "Power",
"createMethods": ["discovery"],
"interfaces": [ ],
"basicTags": ["Device"],
"paramTypes": [
{
"id": "46e606cc-67ee-4891-bc39-8fb0565c87da",
"name": "outputNumber",
"displayName": "Analog output number",
"type": "QString"
}
],
"stateTypes": [
{
"id": "6d825eb8-6d2a-4ac3-9125-9df8173116c9",
"name": "outputValue",
"displayName": "Analog output",
"displayNameEvent": "Analog output changed",
"displayNameAction": "Set analog output",
"type": "double",
"unit": "Volt",
"minValue": 0.00,
"maxValue": 10.00,
"defaultValue": 0.00,
"writable": true
}
]
},
{
"id": "06abd6a4-e655-4243-bc9c-9bd4ef5be2e6",
"name": "analogInput",
"displayName": "Analog Input",
"deviceIcon": "Power",
"createMethods": ["discovery"],
"interfaces": [ ],
"basicTags": ["Sensor"],
"paramTypes": [
{
"id": "cc6eb664-9fd2-457d-9d0d-0eb9703db4a2",
"name": "inputNumber",
"displayName": "Analog input number",
"type": "QString"
}
],
"stateTypes": [
{
"id": "2296f575-cc53-48ef-9086-6a412abfdde5",
"name": "inputValue",
"displayName": "Analog input",
"displayNameEvent": "Analog input changed",
"type": "double",
"unit": "Volt",
"defaultValue": 0.00
}
]
},
{
"id": "eadddc99-ce7d-4169-a2f9-a829fa105ad2",
"name": "blind",
"displayName": "Blind",
"deviceIcon": "Blinds",
"createMethods": ["discovery"],
"interfaces": ["blind"],
"basicTags": ["Actuator"],
"paramTypes": [
{
"id": "7878ef4b-2395-4995-b17d-b69cb7d280e1",
"name": "outputOpen",
"displayName": "Output open",
"type": "QString"
},
{
"id": "4aa113d0-294b-403d-9dd1-ad0abe833176",
"name": "outputClose",
"displayName": "Output close",
"type": "QString"
},
{
"id": "a030f030-4f26-4f33-aadf-ec3c3a5141a7",
"name": "outputTypeOpen",
"displayName": "Output type open",
"type": "QString",
"readOnly": true
},
{
"id": "fde509c5-8db1-411b-9e71-36997c39ee6b",
"name": "outputTypeClose",
"displayName": "Output type close",
"type": "QString",
"readOnly": true
}
],
"stateTypes":[
{
"id": "b8955f33-780a-48a5-9c50-c1bccf09918f",
"name": "status",
"displayName": "Status",
"displayNameEvent": "Status changed",
"type": "QString",
"possibleValues":[
"opening",
"stopped",
"closing"
],
"defaultValue": "stopped"
}
],
"actionTypes":[
{
"id": "cc8a13ae-2a3d-440a-a127-962fb912e511",
"name": "open",
"displayName": "Open"
},
{
"id": "19bda8bb-1a78-4f2f-9927-ff543012462e",
"name": "stop",
"displayName": "Stop"
},
{
"id": "7dc32e36-6a5c-46e1-8507-d9283067ac21",
"name": "close",
"displayName": "Close"
}
]
},
{
"id": "34fc941e-3465-4618-acf6-dda9c7242e27",
"name": "light",
"displayName": "Light",
"deviceIcon": "LightBulb",
"createMethods": ["discovery"],
"interfaces": ["light"],
"basicTags": ["Actuator"],
"paramTypes": [
{
"id": "e1375def-edd6-4886-8e87-73cf3ebc819d",
"name": "output",
"displayName": "Output",
"type": "QString"
},
{
"id": "5853de25-94c6-4f50-95cd-f1e3ef2ebc59",
"name": "outputType",
"displayName": "Output Type",
"type": "QString",
"readOnly": true
}
],
"stateTypes":[
{
"id": "3d0d6abc-87b9-42af-820e-e3bc7bde1743",
"name": "power",
"displayName": "Power",
"displayNameEvent": "Power changed",
"displayNameAction": "Set power",
"type": "bool",
"defaultValue": false,
"writable": true
}
]
},
{
"id": "4f0b3cfd-603a-47ec-9719-2db7eeae1143",
"name": "temperatureSensor",
"displayName": "Temperature sensor",
"deviceIcon": "Thermometer",
"createMethods": ["discovery"],
"interfaces": ["temperaturesensor", "connectable"],
"paramTypes": [
{
"id": "4684cee2-674e-4aa4-823d-096bd49f18ee",
"name": "address",
"displayName": "Address",
"type": "QString"
}
],
"stateTypes":[
{
"id": "7641d379-b832-40fc-a29b-7d32bba79236",
"name": "connected",
"displayName": "Connected",
"displayNameEvent": "Connection changed",
"type": "bool",
"defaultValue": false
},
{
"id": "7fd10e94-f11d-4084-8d03-414fd5592b6a",
"displayName": "Temperature",
"displayNameEvent": "Temperature changed",
"name": "temperature",
"type": "double",
"defaultValue": 0.00
}
]
}
]
}
]
}

90
unipi/dimmerswitch.cpp Normal file
View File

@ -0,0 +1,90 @@
#include "dimmerswitch.h"
DimmerSwitch::DimmerSwitch(QObject *parent) : QObject(parent)
{
m_longPressedTimer = new QTimer(this);
m_longPressedTimer->setSingleShot(true);
connect(m_longPressedTimer, SIGNAL(timeout()), this, SLOT(onLongPressedTimeout()));
m_doublePressedTimer = new QTimer(this);
m_doublePressedTimer->setSingleShot(true);
m_dimmerTimer = new QTimer(this);
connect(m_dimmerTimer, SIGNAL(timeout()), this, SLOT(onDimmerTimeout()));
}
DimmerSwitch::~DimmerSwitch()
{
m_longPressedTimer->deleteLater();
m_doublePressedTimer->deleteLater();
m_dimmerTimer->deleteLater();
}
void DimmerSwitch::setPower(const bool power)
{
if (m_power == power) {
return;
}
m_power = power;
if(power){
m_dimmerTimer->start(250);
m_longPressedTimer->start(2000);
if (m_doublePressedTimer->isActive()) {
m_doublePressedTimer->stop();
emit doublePressed();
} else {
m_doublePressedTimer->start(1000);
emit pressed();
}
} else {
m_dimmerTimer->stop();
m_longPressedTimer->stop();
}
}
bool DimmerSwitch::getPower()
{
return m_power;
}
void DimmerSwitch::setDimValue(const int dimValue)
{
m_dimValue = dimValue;
emit dimValueChanged(m_dimValue);
}
int DimmerSwitch::getDimValue()
{
return m_dimValue;
}
void DimmerSwitch::onDimmerTimeout()
{
if(!m_longPressedTimer->isActive()) {
if (m_countingUp) {
m_dimValue += 5;
if(m_dimValue >= 100) {
m_dimValue = 100;
m_countingUp = false;
}
} else {
m_dimValue -= 5;
if(m_dimValue <= 0) {
m_dimValue = 0;
m_countingUp = true;
}
}
emit dimValueChanged(m_dimValue);
}
}
void DimmerSwitch::onLongPressedTimeout()
{
emit longPressed();
}

42
unipi/dimmerswitch.h Normal file
View File

@ -0,0 +1,42 @@
#ifndef DIMMERSWITCH_H
#define DIMMERSWITCH_H
#include <QObject>
#include <QTimer>
class DimmerSwitch : public QObject
{
Q_OBJECT
public:
explicit DimmerSwitch(QObject *parent = 0);
~DimmerSwitch();
void setPower(const bool power);
bool getPower();
void setDimValue(const int dimValue);
int getDimValue();
QTimer *m_doublePressedTimer = nullptr;
QTimer *m_longPressedTimer = nullptr;
QTimer *m_dimmerTimer = nullptr;
private:
bool m_power;
int m_dimValue = 0;
bool m_countingUp = true;
bool m_powerWasLow = false; //flag to indicate the power was low within the double pressed time frame
signals:
void pressed();
void longPressed();
void doublePressed();
void dimValueChanged(int dimValue);
private slots:
void onLongPressedTimeout();
void onDimmerTimeout();
};
#endif // DIMMERSWITCH_H

View File

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE TS>
<TS version="2.1">
</TS>

13
unipi/unipi.pro Normal file
View File

@ -0,0 +1,13 @@
include(../plugins.pri)
TARGET = $$qtLibraryTarget(nymea_devicepluginunipi)
SOURCES += \
devicepluginunipi.cpp \
dimmerswitch.cpp
HEADERS += \
devicepluginunipi.h \
dimmerswitch.h