diff --git a/unipi/devicepluginunipi.cpp b/unipi/devicepluginunipi.cpp index f7df2449..e61358bd 100644 --- a/unipi/devicepluginunipi.cpp +++ b/unipi/devicepluginunipi.cpp @@ -104,6 +104,17 @@ DeviceManager::DeviceSetupStatus DevicePluginUniPi::setupDevice(Device *device) return DeviceManager::DeviceSetupStatusSuccess; } + if (device->deviceClassId() == dimmerSwitchDeviceClassId) { + m_usedDigitalInputs.insert(device->paramValue(dimmerSwitchInputNumberParamTypeId).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::DeviceSetupStatusFailure; } @@ -287,7 +298,7 @@ DeviceManager::DeviceError DevicePluginUniPi::discoverDevices(const DeviceClassI if (m_usedRelais.contains(circuit)){ continue; } - DeviceDescriptor descriptor(deviceClassId, QString("Relay %1").arg(circuit), circuit); + DeviceDescriptor descriptor(deviceClassId, "Light", QString("Relay %1").arg(circuit)); ParamList parameters; parameters.append(Param(lightOutputParamTypeId, circuit)); parameters.append(Param(lightOutputTypeParamTypeId, GPIOType::relay)); @@ -302,7 +313,7 @@ DeviceManager::DeviceError DevicePluginUniPi::discoverDevices(const DeviceClassI if (m_usedDigitalOutputs.contains(circuit)){ continue; } - DeviceDescriptor descriptor(deviceClassId, QString("Digital output %1").arg(circuit), circuit); + DeviceDescriptor descriptor(deviceClassId, "Light", QString("Digital output %1").arg(circuit)); ParamList parameters; parameters.append(Param(lightOutputParamTypeId, circuit)); parameters.append(Param(lightOutputTypeParamTypeId, GPIOType::digitalOutput)); @@ -312,6 +323,26 @@ DeviceManager::DeviceError DevicePluginUniPi::discoverDevices(const DeviceClassI emit devicesDiscovered(deviceClassId, deviceDescriptors); return DeviceManager::DeviceErrorAsync; } + + if (deviceClassId == dimmerSwitchDeviceClassId) { + // Create the list of available digital inputs + QList 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(digitalInputDigitalInputNumberParamTypeId, circuit)); + descriptor.setParams(parameters); + deviceDescriptors.append(descriptor); + } + emit devicesDiscovered(deviceClassId, deviceDescriptors); + return DeviceManager::DeviceErrorAsync; + } } return DeviceManager::DeviceErrorDeviceClassNotFound; } @@ -355,11 +386,11 @@ void DevicePluginUniPi::deviceRemoved(Device *device) } else if(device->deviceClassId() == digitalOutputDeviceClassId) { m_usedDigitalOutputs.remove(device->paramValue(digitalOutputDigitalOutputNumberParamTypeId).toString()); } else if(device->deviceClassId() == digitalInputDeviceClassId) { - m_usedDigitalOutputs.remove(device->paramValue(digitalInputDigitalInputNumberParamTypeId).toString()); + m_usedDigitalInputs.remove(device->paramValue(digitalInputDigitalInputNumberParamTypeId).toString()); } else if (device->deviceClassId() == analogOutputDeviceClassId) { - m_usedDigitalOutputs.remove(device->paramValue(analogOutputAnalogOutputNumberParamTypeId).toString()); + m_usedAnalogOutputs.remove(device->paramValue(analogOutputAnalogOutputNumberParamTypeId).toString()); } else if (device->deviceClassId() == analogInputDeviceClassId) { - m_usedDigitalOutputs.remove(device->paramValue(analogInputAnalogInputNumberParamTypeId).toString()); + m_usedAnalogInputs.remove(device->paramValue(analogInputAnalogInputNumberParamTypeId).toString()); } else if (device->deviceClassId() == shutterDeviceClassId) { if (device->paramValue(shutterOutputTypeOpenParamTypeId) == GPIOType::relay) { @@ -380,6 +411,9 @@ void DevicePluginUniPi::deviceRemoved(Device *device) } else if (device->paramValue(lightOutputParamTypeId) == GPIOType::digitalOutput) { m_usedDigitalOutputs.remove(device->paramValue(lightOutputParamTypeId).toString()); } + } else if (device->deviceClassId() == dimmerSwitchDeviceClassId) { + m_usedDigitalInputs.remove(device->paramValue(dimmerSwitchInputNumberParamTypeId).toString()); + m_dimmerSwitches.remove(m_dimmerSwitches.key(device)); } if (myDevices().isEmpty()) { @@ -393,9 +427,9 @@ DeviceManager::DeviceError DevicePluginUniPi::executeAction(Device *device, cons if (device->deviceClassId() == relayOutputDeviceClassId) { - if (action.actionTypeId() == relayOutputRelayStatusActionTypeId) { + if (action.actionTypeId() == relayOutputPowerActionTypeId) { QString relayNumber = device->paramValue(relayOutputRelayNumberParamTypeId).toString(); - int stateValue = action.param(relayOutputRelayStatusActionParamTypeId).value().toInt(); + int stateValue = action.param(relayOutputPowerActionParamTypeId).value().toInt(); setOutput(relayNumber, stateValue); return DeviceManager::DeviceErrorNoError; @@ -403,11 +437,10 @@ DeviceManager::DeviceError DevicePluginUniPi::executeAction(Device *device, cons return DeviceManager::DeviceErrorActionTypeNotFound; } - if (device->deviceClassId() == digitalOutputDeviceClassId) { - if (action.actionTypeId() == digitalOutputDigitalOutputStatusActionTypeId) { + if (action.actionTypeId() == digitalOutputPowerActionTypeId) { QString digitalOutputNumber = device->paramValue(digitalOutputDigitalOutputNumberParamTypeId).toString(); - bool stateValue = action.param(digitalOutputDigitalOutputStatusActionParamTypeId).value().toBool(); + bool stateValue = action.param(digitalOutputPowerActionParamTypeId).value().toBool(); setOutput(digitalOutputNumber, stateValue); return DeviceManager::DeviceErrorNoError; @@ -464,7 +497,7 @@ DeviceManager::DeviceError DevicePluginUniPi::executeAction(Device *device, cons if (device->deviceClassId() == lightDeviceClassId) { QString circuit = device->paramValue(lightOutputParamTypeId).toString(); - bool stateValue = action.param(digitalOutputDigitalOutputStatusActionParamTypeId).value().toBool(); + bool stateValue = action.param(digitalOutputPowerActionParamTypeId).value().toBool(); setOutput(circuit, stateValue); return DeviceManager::DeviceErrorNoError; @@ -535,13 +568,10 @@ void DevicePluginUniPi::onWebSocketTextMessageReceived(QString message) //New Device detected m_relais.append(circuit); } else { - - foreach (Device *device, myDevices()) { + if (m_usedRelais.contains(circuit)) { + Device *device = m_usedRelais.value(circuit); if (device->deviceClassId() == relayOutputDeviceClassId) { - if (circuit == device->paramValue(relayOutputRelayNumberParamTypeId).toString()) { - device->setStateValue(relayOutputRelayStatusStateTypeId, value); - break; - } + device->setStateValue(relayOutputPowerStateTypeId, value); } else if (device->deviceClassId() == shutterDeviceClassId) { if (circuit == device->paramValue(shutterOutputOpenParamTypeId).toString()) { if (value && device->stateValue(shutterStatusStateTypeId).toString().contains("stop")) { @@ -551,8 +581,6 @@ void DevicePluginUniPi::onWebSocketTextMessageReceived(QString message) } else { qWarning(dcUniPi()) << "shutter" << device << "Output open:" << value << "Status: " << device->stateValue(shutterStatusStateTypeId).toString(); } - - break; } if (circuit == device->paramValue(shutterOutputCloseParamTypeId).toString()) { if (value && device->stateValue(shutterStatusStateTypeId).toString().contains("stop")) { @@ -566,10 +594,7 @@ void DevicePluginUniPi::onWebSocketTextMessageReceived(QString message) } } else if (device->deviceClassId() == lightDeviceClassId) { - if (circuit == device->paramValue(lightOutputParamTypeId).toString()) { - device->setStateValue(lightPowerStateTypeId, value); - break; - } + device->setStateValue(lightPowerStateTypeId, value); } } } @@ -578,13 +603,32 @@ void DevicePluginUniPi::onWebSocketTextMessageReceived(QString message) //New Device detected m_digitalOutputs.append(obj["circuit"].toString()); } else { - - foreach (Device *device, myDevices()) { + if (m_usedDigitalOutputs.contains(obj["circuit"].toString())) { + Device *device = m_usedDigitalOutputs.value(obj["circuit"].toString()); if (device->deviceClassId() == digitalOutputDeviceClassId) { - if (obj["circuit"] == device->paramValue(digitalOutputDigitalOutputNumberParamTypeId).toString()) { - device->setStateValue(digitalOutputDigitalOutputStatusStateTypeId, QVariant(obj["value"].toInt()).toBool()); + device->setStateValue(digitalOutputPowerStateTypeId, QVariant(obj["value"].toInt()).toBool()); + } else if (device->deviceClassId() == shutterDeviceClassId) { + if (circuit == device->paramValue(shutterOutputOpenParamTypeId).toString()) { + if (value && device->stateValue(shutterStatusStateTypeId).toString().contains("stop")) { + device->setStateValue(shutterStatusStateTypeId, "close"); + } else if (!value && device->stateValue(shutterStatusStateTypeId).toString().contains("open")) { + device->setStateValue(shutterStatusStateTypeId, "stop"); + } else { + qWarning(dcUniPi()) << "shutter" << device << "Output open:" << value << "Status: " << device->stateValue(shutterStatusStateTypeId).toString(); + } + } + if (circuit == device->paramValue(shutterOutputCloseParamTypeId).toString()) { + if (value && device->stateValue(shutterStatusStateTypeId).toString().contains("stop")) { + device->setStateValue(shutterStatusStateTypeId, "close"); + } else if (!value && device->stateValue(shutterStatusStateTypeId).toString().contains("close")) { + device->setStateValue(shutterStatusStateTypeId, "stop"); + } else { + qWarning(dcUniPi()) << "shutter" << device << "Output close:" << value << "Status: " << device->stateValue(shutterStatusStateTypeId).toString(); + } break; } + } else if (device->deviceClassId() == lightDeviceClassId) { + device->setStateValue(lightPowerStateTypeId, QVariant(obj["value"].toInt()).toBool()); } } } @@ -598,13 +642,15 @@ void DevicePluginUniPi::onWebSocketTextMessageReceived(QString message) //New Device detected m_digitalInputs.append(obj["circuit"].toString()); } else { - - foreach (Device *device, myDevices()) { + if (m_usedDigitalInputs.contains(obj["circuit"].toString())) { + bool value = QVariant(obj["value"].toInt()).toBool(); + Device *device = m_usedDigitalInputs.value(obj["circuit"].toString()); if (device->deviceClassId() == digitalInputDeviceClassId) { - if (obj["circuit"] == device->paramValue(digitalInputDigitalInputNumberParamTypeId).toString()) { - device->setStateValue(digitalInputDigitalInputStatusStateTypeId, QVariant(obj["value"].toInt()).toBool()); - break; - } + device->setStateValue(digitalInputDigitalInputStatusStateTypeId, value); + } else if (device->deviceClassId() == dimmerSwitchDeviceClassId) { + device->setStateValue(dimmerSwitchStatusStateTypeId, value); + DimmerSwitch *dimmerSwitch = m_dimmerSwitches.key(device); + dimmerSwitch->setPower(value); } } } @@ -648,7 +694,7 @@ void DevicePluginUniPi::onWebSocketTextMessageReceived(QString message) } } - if (obj["dev"] == "led") { + if (obj["dev"] == "led") { //TODO cant discover leds without toggling it from another client qCDebug(dcUniPi()) << "Led:" << obj["dev"] << "Circuit:" << obj["circuit"].toString() << "Value:" << obj["value"].toInt(); if (!m_leds.contains(obj["circuit"].toString())){ @@ -657,7 +703,7 @@ void DevicePluginUniPi::onWebSocketTextMessageReceived(QString message) } } - if (obj["dev"] == "sensor") { + if (obj["dev"] == "sensor") { //TODO not yet implemented qCDebug(dcUniPi()) << "Sensor:" << obj["dev"] << "Circuit:" << obj["circuit"].toString() << "Value:" << obj["value"].toInt(); if (!m_sensors.contains(obj["circuit"].toString())){ @@ -672,3 +718,31 @@ void DevicePluginUniPi::onRefreshTimer() { connectToEvok(); } + +void DevicePluginUniPi::onDimmerSwitchPressed() +{ + DimmerSwitch *dimmerSwitch = static_cast(sender()); + Device *device = m_dimmerSwitches.value(dimmerSwitch); + emit emitEvent(Event(dimmerSwitchPressedEventTypeId, device->id())); +} + +void DevicePluginUniPi::onDimmerSwitchLongPressed() +{ + DimmerSwitch *dimmerSwitch = static_cast(sender()); + Device *device = m_dimmerSwitches.value(dimmerSwitch); + emit emitEvent(Event(dimmerSwitchLongPressedEventTypeId, device->id())); +} + +void DevicePluginUniPi::onDimmerSwitchDoublePressed() +{ + DimmerSwitch *dimmerSwitch = static_cast(sender()); + Device *device = m_dimmerSwitches.value(dimmerSwitch); + emit emitEvent(Event(dimmerSwitchDoublePressedEventTypeId, device->id())); +} + +void DevicePluginUniPi::onDimmerSwitchDimValueChanged(int dimValue) +{ + DimmerSwitch *dimmerSwitch = static_cast(sender()); + Device *device = m_dimmerSwitches.value(dimmerSwitch); + device->setStateValue(dimmerSwitchDimValueStateTypeId, dimValue); +} diff --git a/unipi/devicepluginunipi.h b/unipi/devicepluginunipi.h index e5f66564..6e1ee629 100644 --- a/unipi/devicepluginunipi.h +++ b/unipi/devicepluginunipi.h @@ -28,6 +28,7 @@ #include "devicemanager.h" #include #include "plugintimer.h" +#include "dimmerswitch.h" class DevicePluginUniPi : public DevicePlugin { @@ -66,6 +67,8 @@ private: QHash m_usedSensors; QHash m_usedLeds; + QHash m_dimmerSwitches; + QList m_relais; QList m_digitalOutputs; QList m_digitalInputs; @@ -86,6 +89,11 @@ private slots: void onWebSocketDisconnected(); void onWebSocketTextMessageReceived(QString message); void onRefreshTimer(); + + void onDimmerSwitchPressed(); + void onDimmerSwitchLongPressed(); + void onDimmerSwitchDoublePressed(); + void onDimmerSwitchDimValueChanged(int dimValue); }; #endif // DEVICEPLUGINUNIPI_H diff --git a/unipi/devicepluginunipi.json b/unipi/devicepluginunipi.json index 5d0bd9f3..655bb873 100644 --- a/unipi/devicepluginunipi.json +++ b/unipi/devicepluginunipi.json @@ -23,7 +23,7 @@ "displayName": "Relay output", "deviceIcon": "Power", "createMethods": ["discovery"], - "interfaces": [ ], + "interfaces": ["power"], "basicTags": ["Device"], "paramTypes": [ { @@ -36,8 +36,8 @@ "stateTypes": [ { "id": "f9c01e7b-0523-4cac-905a-d5b20028e021", - "name": "relayStatus", - "displayName": "Relay", + "name": "power", + "displayName": "Power", "displayNameEvent": "Relay power changed", "displayNameAction": "Set relay power", "type": "bool", @@ -73,13 +73,66 @@ } ] }, + { + "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": [ ], + "interfaces": ["power"], "basicTags": ["Device"], "paramTypes": [ { @@ -92,8 +145,8 @@ "stateTypes": [ { "id": "470a0e30-a170-47ed-9ed3-c41db919555f", - "name": "digitalOutputStatus", - "displayName": "digital output", + "name": "power", + "displayName": "Power", "displayNameAction": "set digital output", "displayNameEvent": "digital output changed", "type": "bool", @@ -266,6 +319,30 @@ "writable": true } ] + }, + { + "id": "fe3d7d2f-3cee-4f2b-b6f8-4381ff1a2825", + "name": "temperatureSensor", + "displayName": "1-Wire Temperature Sensor", + "deviceIcon": "Thermometer", + "createMethods": ["discovery"], + "interfaces": ["temperaturesensor"], + "basicTags": ["Actuator"], + "paramTypes": [ + { + } + ], + "stateTypes":[ + { + "id": "a11e8108-d16e-4972-820a-f3611ba6fe24", + "name": "temperature", + "displayName": "Temperature", + "displayNameEvent": "Temperature changed", + "type": "double", + "defaultValue": 0, + "unit": "DegreeCelsius" + } + ] } ] } diff --git a/unipi/dimmerswitch.cpp b/unipi/dimmerswitch.cpp new file mode 100644 index 00000000..b2dd6354 --- /dev/null +++ b/unipi/dimmerswitch.cpp @@ -0,0 +1,87 @@ +#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(150); + 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_countingUp) { + m_dimValue += 3; + if(m_dimValue >= 100) { + m_dimValue = 100; + m_countingUp = false; + } + } else { + m_dimValue -= 3; + if(m_dimValue <= 0) { + m_dimValue = 0; + m_countingUp = true; + } + } + emit dimValueChanged(m_dimValue); +} + +void DimmerSwitch::onLongPressedTimeout() +{ + emit longPressed(); +} + + diff --git a/unipi/dimmerswitch.h b/unipi/dimmerswitch.h new file mode 100644 index 00000000..06c106bb --- /dev/null +++ b/unipi/dimmerswitch.h @@ -0,0 +1,42 @@ +#ifndef DIMMERSWITCH_H +#define DIMMERSWITCH_H + +#include +#include + +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 diff --git a/unipi/unipi.pro b/unipi/unipi.pro index b107daa1..60a45796 100644 --- a/unipi/unipi.pro +++ b/unipi/unipi.pro @@ -3,9 +3,11 @@ include(../plugins.pri) TARGET = $$qtLibraryTarget(nymea_devicepluginunipi) SOURCES += \ - devicepluginunipi.cpp + devicepluginunipi.cpp \ + dimmerswitch.cpp HEADERS += \ - devicepluginunipi.h + devicepluginunipi.h \ + dimmerswitch.h