Merge PR #114: New Plugin: WS2812FX
This commit is contained in:
commit
fc4f4cf3da
15
debian/control
vendored
15
debian/control
vendored
@ -550,6 +550,21 @@ Description: nymea.io plugin for wemo
|
||||
This package will install the nymea.io plugin for wemo
|
||||
|
||||
|
||||
Package: nymea-plugin-ws2812fx
|
||||
Architecture: any
|
||||
Depends: ${shlibs:Depends},
|
||||
${misc:Depends},
|
||||
nymea-plugins-translations,
|
||||
Description: nymea.io plugin for ws2812fx
|
||||
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 ws2812fx
|
||||
|
||||
|
||||
Package: nymea-plugin-tcpcommander
|
||||
Architecture: any
|
||||
Depends: ${shlibs:Depends},
|
||||
|
||||
1
debian/nymea-plugin-ws2812fx.install.in
vendored
Normal file
1
debian/nymea-plugin-ws2812fx.install.in
vendored
Normal file
@ -0,0 +1 @@
|
||||
usr/lib/@DEB_HOST_MULTIARCH@/nymea/plugins/libnymea_devicepluginws2812fx.so
|
||||
@ -44,6 +44,7 @@ PLUGIN_DIRS = \
|
||||
unitec \
|
||||
wakeonlan \
|
||||
wemo \
|
||||
ws2812fx \
|
||||
|
||||
|
||||
message(============================================)
|
||||
|
||||
7
ws2812fx/README.md
Normal file
7
ws2812fx/README.md
Normal file
@ -0,0 +1,7 @@
|
||||
# WS2812FX
|
||||
|
||||
Plug-In for the WS2812FX project, a WS2812 effect library for Arduino and ESP8266.
|
||||
Flash your microcontroller with the provided "serial_control" example. Connect the microcontroller
|
||||
over USB to the nymea device.
|
||||
|
||||
See also: https://github.com/kitesurfer1404/WS2812FX
|
||||
426
ws2812fx/devicepluginws2812fx.cpp
Normal file
426
ws2812fx/devicepluginws2812fx.cpp
Normal file
@ -0,0 +1,426 @@
|
||||
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||
* *
|
||||
* Copyright (C) 2019 Bernhard Trinnes <bernhard.trinnes@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/>. *
|
||||
* *
|
||||
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||||
|
||||
/*!
|
||||
\page ws2812fx.html
|
||||
\title WS2812FX Control
|
||||
\brief Plug-In to control WS2812FX over USB
|
||||
|
||||
\ingroup plugins
|
||||
\ingroup nymea-plugins
|
||||
|
||||
\chapter Plugin properties
|
||||
Following JSON file contains the definition and the description of all available \l{DeviceClass}{DeviceClasses}
|
||||
and \l{Vendor}{Vendors} of this \l{DevicePlugin}.
|
||||
|
||||
For more details how to read this JSON file please check out the documentation for \l{The plugin JSON File}.
|
||||
|
||||
\quotefile plugins/deviceplugins/ws2812fx/devicepluginws2812fx.json
|
||||
*/
|
||||
#include <QColor>
|
||||
#include "devicepluginws2812fx.h"
|
||||
#include "plugininfo.h"
|
||||
|
||||
DevicePluginWs2812fx ::DevicePluginWs2812fx ()
|
||||
{
|
||||
}
|
||||
|
||||
Device::DeviceSetupStatus DevicePluginWs2812fx::setupDevice(Device *device)
|
||||
{
|
||||
if (device->deviceClassId() == ws2812fxDeviceClassId) {
|
||||
QString interface = device->paramValue(ws2812fxDeviceSerialPortParamTypeId).toString();
|
||||
|
||||
if (!m_usedInterfaces.contains(interface)) {
|
||||
|
||||
QSerialPort *serialPort = new QSerialPort(interface, this);
|
||||
if(!serialPort)
|
||||
return Device::DeviceSetupStatusFailure;
|
||||
|
||||
serialPort->setBaudRate(115200);
|
||||
serialPort->setDataBits(QSerialPort::DataBits::Data8);
|
||||
serialPort->setParity(QSerialPort::Parity::NoParity);
|
||||
serialPort->setStopBits(QSerialPort::StopBits::OneStop);
|
||||
serialPort->setFlowControl(QSerialPort::FlowControl::NoFlowControl);
|
||||
|
||||
if (!serialPort->open(QIODevice::ReadWrite)) {
|
||||
qCWarning(dcWs2812fx()) << "Could not open serial port" << interface << serialPort->errorString();
|
||||
serialPort->deleteLater();
|
||||
return Device::DeviceSetupStatusFailure;
|
||||
}
|
||||
|
||||
connect(serialPort, SIGNAL(error(QSerialPort::SerialPortError)), this, SLOT(onSerialError(QSerialPort::SerialPortError)));
|
||||
connect(serialPort, SIGNAL(readyRead()), this, SLOT(onReadyRead()));
|
||||
|
||||
qCDebug(dcWs2812fx()) << "Setup successfully serial port" << interface;
|
||||
device->setStateValue(ws2812fxConnectedStateTypeId, true);
|
||||
m_usedInterfaces.append(interface);
|
||||
m_serialPorts.insert(device, serialPort);
|
||||
|
||||
if(!m_reconnectTimer) {
|
||||
m_reconnectTimer = new QTimer(this);
|
||||
m_reconnectTimer->setSingleShot(true);
|
||||
m_reconnectTimer->setInterval(5000);
|
||||
|
||||
connect(m_reconnectTimer, &QTimer::timeout, this, &DevicePluginWs2812fx::onReconnectTimer);
|
||||
}
|
||||
} else {
|
||||
return Device::DeviceSetupStatusFailure;
|
||||
}
|
||||
return Device::DeviceSetupStatusSuccess;
|
||||
}
|
||||
return Device::DeviceSetupStatusFailure;
|
||||
}
|
||||
|
||||
|
||||
Device::DeviceError DevicePluginWs2812fx::discoverDevices(const DeviceClassId &deviceClassId, const ParamList ¶ms)
|
||||
{
|
||||
Q_UNUSED(params)
|
||||
// Create the list of available serial interfaces
|
||||
QList<DeviceDescriptor> deviceDescriptors;
|
||||
|
||||
Q_FOREACH(QSerialPortInfo port, QSerialPortInfo::availablePorts()) {
|
||||
|
||||
qCDebug(dcWs2812fx()) << "Found serial port:" << port.portName();
|
||||
QString description = port.manufacturer() + " " + port.description();
|
||||
DeviceDescriptor descriptor(deviceClassId, port.portName(), description);
|
||||
foreach (Device *existingDevice, myDevices().filterByParam(ws2812fxDeviceSerialPortParamTypeId, port.portName())) {
|
||||
descriptor.setDeviceId(existingDevice->id());
|
||||
}
|
||||
ParamList parameters;
|
||||
parameters.append(Param(ws2812fxDeviceSerialPortParamTypeId, port.portName()));
|
||||
descriptor.setParams(parameters);
|
||||
deviceDescriptors.append(descriptor);
|
||||
}
|
||||
emit devicesDiscovered(deviceClassId, deviceDescriptors);
|
||||
return Device::DeviceErrorAsync;
|
||||
}
|
||||
|
||||
|
||||
Device::DeviceError DevicePluginWs2812fx::executeAction(Device *device, const Action &action)
|
||||
{
|
||||
if (device->deviceClassId() == ws2812fxDeviceClassId ) {
|
||||
|
||||
QByteArray command;
|
||||
if (action.actionTypeId() == ws2812fxPowerActionTypeId) {
|
||||
command.append("b ");
|
||||
if (action.param(ws2812fxPowerActionPowerParamTypeId).value().toBool()) {
|
||||
command.append("30");
|
||||
} else {
|
||||
command.append("0");
|
||||
}
|
||||
command.append("\r\n");
|
||||
return sendCommand(device, action.id(), command, CommandType::Brightness);
|
||||
}
|
||||
|
||||
if (action.actionTypeId() == ws2812fxBrightnessActionTypeId) {
|
||||
|
||||
command.append("b ");
|
||||
command.append(action.param(ws2812fxBrightnessActionBrightnessParamTypeId).value().toString());
|
||||
command.append("\r\n");
|
||||
return sendCommand(device, action.id(), command, CommandType::Brightness);
|
||||
}
|
||||
|
||||
if (action.actionTypeId() == ws2812fxSpeedActionTypeId) {
|
||||
|
||||
command.append("s ");
|
||||
command.append(action.param(ws2812fxSpeedActionSpeedParamTypeId).value().toString());
|
||||
command.append("\r\n");
|
||||
return sendCommand(device, action.id(), command, CommandType::Speed);
|
||||
}
|
||||
|
||||
if (action.actionTypeId() == ws2812fxColorActionTypeId) {
|
||||
|
||||
QColor color;
|
||||
color= action.param(ws2812fxColorActionColorParamTypeId).value().value<QColor>();
|
||||
command.append("c ");
|
||||
command.append(QString(color.name()).remove("#"));
|
||||
command.append("\r\n");
|
||||
return sendCommand(device, action.id(), command, CommandType::Color);
|
||||
}
|
||||
|
||||
if (action.actionTypeId() == ws2812fxColorTemperatureActionTypeId) {
|
||||
|
||||
// minValue 153, maxValue 500
|
||||
QColor color;
|
||||
color.setRgb(255, 255, static_cast<int>((255.00-(((action.param(ws2812fxColorTemperatureActionColorTemperatureParamTypeId).value().toDouble()-153.00)/347.00))*255.00)));
|
||||
device->setStateValue(ws2812fxColorTemperatureStateTypeId, action.param(ws2812fxColorTemperatureActionColorTemperatureParamTypeId).value());
|
||||
command.append("c ");
|
||||
command.append(QString(color.name()).remove("#"));
|
||||
command.append("\r\n");
|
||||
return sendCommand(device, action.id(), command, CommandType::Color);
|
||||
}
|
||||
|
||||
if (action.actionTypeId() == ws2812fxEffectModeActionTypeId) {
|
||||
|
||||
QString effectMode = action.param(ws2812fxEffectModeActionEffectModeParamTypeId).value().toString();
|
||||
command.append("m ");
|
||||
if (effectMode == "Static") {
|
||||
command.append(QString::number(FX_MODE_STATIC));
|
||||
} else if (effectMode == "Blink") {
|
||||
command.append(QString::number(FX_MODE_BLINK));
|
||||
} else if (effectMode == "Color Wipe") {
|
||||
command.append(QString::number(FX_MODE_COLOR_WIPE));
|
||||
} else if (effectMode == "Color Wipe Inverse") {
|
||||
command.append(QString::number(FX_MODE_COLOR_WIPE_INV));
|
||||
} else if (effectMode == "Color Wipe Reverse") {
|
||||
command.append(QString::number(FX_MODE_COLOR_WIPE_REV));
|
||||
} else if (effectMode == "Color Wipe Reverse Inverse") {
|
||||
command.append(QString::number(FX_MODE_COLOR_WIPE_REV_INV));
|
||||
} else if (effectMode == "Color Wipe Random") {
|
||||
command.append(QString::number(FX_MODE_COLOR_WIPE_RANDOM));
|
||||
} else if (effectMode == "Random Color") {
|
||||
command.append(QString::number(FX_MODE_RANDOM_COLOR));
|
||||
} else if (effectMode == "Single Dynamic") {
|
||||
command.append(QString::number(FX_MODE_SINGLE_DYNAMIC));
|
||||
} else if (effectMode == "Multi Dynamic") {
|
||||
command.append(QString::number(FX_MODE_MULTI_DYNAMIC));
|
||||
} else if (effectMode == "Rainbow") {
|
||||
command.append(QString::number(FX_MODE_RAINBOW));
|
||||
} else if (effectMode == "Rainbow Cycle") {
|
||||
command.append(QString::number(FX_MODE_RAINBOW_CYCLE));
|
||||
} else if (effectMode == "Scan") {
|
||||
command.append(QString::number(FX_MODE_SCAN));
|
||||
} else if (effectMode == "Dual Scan") {
|
||||
command.append(QString::number(FX_MODE_DUAL_SCAN));
|
||||
} else if (effectMode == "Fade") {
|
||||
command.append(QString::number(FX_MODE_FADE));
|
||||
} else if (effectMode == "Theater Chase") {
|
||||
command.append(QString::number(FX_MODE_THEATER_CHASE));
|
||||
} else if (effectMode == "Theater Chase Rainbow") {
|
||||
command.append(QString::number(FX_MODE_THEATER_CHASE_RAINBOW));
|
||||
} else if (effectMode == "Running Lights") {
|
||||
command.append(QString::number(FX_MODE_RUNNING_LIGHTS));
|
||||
} else if (effectMode == "Twinkle") {
|
||||
command.append(QString::number(FX_MODE_TWINKLE));
|
||||
} else if (effectMode == "Twinkle Random") {
|
||||
command.append(QString::number(FX_MODE_TWINKLE_RANDOM));
|
||||
} else if (effectMode == "Twinkle Fade") {
|
||||
command.append(QString::number(FX_MODE_TWINKLE_FADE));
|
||||
} else if (effectMode == "Twinkle Fade Random") {
|
||||
command.append(QString::number(FX_MODE_TWINKLE_FADE_RANDOM));
|
||||
} else if (effectMode == "Sparkle") {
|
||||
command.append(QString::number(FX_MODE_SPARKLE));
|
||||
} else if (effectMode == "Flash Sparkle") {
|
||||
command.append(QString::number(FX_MODE_FLASH_SPARKLE));
|
||||
} else if (effectMode == "Hyper Sparkle") {
|
||||
command.append(QString::number(FX_MODE_HYPER_SPARKLE));
|
||||
} else if (effectMode == "Strobe") {
|
||||
command.append(QString::number(FX_MODE_STROBE));
|
||||
} else if (effectMode == "Strobe Rainbow") {
|
||||
command.append(QString::number(FX_MODE_STROBE_RAINBOW));
|
||||
} else if (effectMode == "Multi Strobe") {
|
||||
command.append(QString::number(FX_MODE_MULTI_STROBE));
|
||||
} else if (effectMode == "Blink Rainbow") {
|
||||
command.append(QString::number(FX_MODE_BLINK_RAINBOW));
|
||||
} else if (effectMode == "Chase White") {
|
||||
command.append(QString::number(FX_MODE_CHASE_WHITE));
|
||||
} else if (effectMode == "Chase Color") {
|
||||
command.append(QString::number(FX_MODE_CHASE_COLOR));
|
||||
} else if (effectMode == "Chase Random") {
|
||||
command.append(QString::number(FX_MODE_CHASE_RANDOM));
|
||||
} else if (effectMode == "Chase Flash") {
|
||||
command.append(QString::number(FX_MODE_CHASE_FLASH));
|
||||
} else if (effectMode == "Chase Flash Random") {
|
||||
command.append(QString::number(FX_MODE_CHASE_FLASH_RANDOM));
|
||||
} else if (effectMode == "Chase Rainbow White") {
|
||||
command.append(QString::number(FX_MODE_CHASE_RAINBOW_WHITE));
|
||||
} else if (effectMode == "Chase Blackout") {
|
||||
command.append(QString::number(FX_MODE_CHASE_BLACKOUT));
|
||||
} else if (effectMode == "Chase Blackout Rainbow") {
|
||||
command.append(QString::number(FX_MODE_CHASE_BLACKOUT_RAINBOW));
|
||||
} else if (effectMode == "Color Sweep Random") {
|
||||
command.append(QString::number(FX_MODE_COLOR_SWEEP_RANDOM));
|
||||
} else if (effectMode == "Running Color") {
|
||||
command.append(QString::number(FX_MODE_RUNNING_COLOR));
|
||||
} else if (effectMode == "Running Red Blue") {
|
||||
command.append(QString::number(FX_MODE_RUNNING_RED_BLUE));
|
||||
} else if (effectMode == "Running Random") {
|
||||
command.append(QString::number(FX_MODE_RUNNING_RANDOM));
|
||||
}else if (effectMode == "Larson Scanner") {
|
||||
command.append(QString::number(FX_MODE_LARSON_SCANNER));
|
||||
}else if (effectMode == "Comet") {
|
||||
command.append(QString::number(FX_MODE_COMET));
|
||||
}else if (effectMode == "Fireworks") {
|
||||
command.append(QString::number(FX_MODE_FIREWORKS));
|
||||
}else if (effectMode == "Fireworks Random") {
|
||||
command.append(QString::number(FX_MODE_FIREWORKS_RANDOM));
|
||||
}else if (effectMode == "Merry Christmas") {
|
||||
command.append(QString::number(FX_MODE_MERRY_CHRISTMAS));
|
||||
}else if (effectMode == "Fire Flicker") {
|
||||
command.append(QString::number(FX_MODE_FIRE_FLICKER));
|
||||
}else if (effectMode == "Fire Flicker (soft)") {
|
||||
command.append(QString::number(FX_MODE_FIRE_FLICKER_SOFT));
|
||||
}else if (effectMode == "Fire Flicker (intense)") {
|
||||
command.append(QString::number(FX_MODE_FIRE_FLICKER_INTENSE));
|
||||
}else if (effectMode == "Circus Combustus") {
|
||||
command.append(QString::number(FX_MODE_CIRCUS_COMBUSTUS));
|
||||
}else if (effectMode == "Halloween") {
|
||||
command.append(QString::number(FX_MODE_HALLOWEEN));
|
||||
}else if (effectMode == "Bicolor Chase") {
|
||||
command.append(QString::number(FX_MODE_BICOLOR_CHASE));
|
||||
}else if (effectMode == "Tricolor Chase") {
|
||||
command.append(QString::number(FX_MODE_TRICOLOR_CHASE));
|
||||
}else if (effectMode == "ICU") {
|
||||
command.append(QString::number(FX_MODE_ICU));
|
||||
}else if (effectMode == "Custom 0") {
|
||||
command.append(QString::number(FX_MODE_CUSTOM_0));
|
||||
}else if (effectMode == "Custom 1") {
|
||||
command.append(QString::number(FX_MODE_CUSTOM_1));
|
||||
}else if (effectMode == "Custom 2") {
|
||||
command.append(QString::number(FX_MODE_CUSTOM_2));
|
||||
}else if (effectMode == "Custom 3") {
|
||||
command.append(QString::number(FX_MODE_CUSTOM_3));
|
||||
}
|
||||
command.append("\r\n");
|
||||
return sendCommand(device, action.id(), command, CommandType::Mode);
|
||||
}
|
||||
return Device::DeviceErrorActionTypeNotFound;
|
||||
}
|
||||
return Device::DeviceErrorDeviceClassNotFound;
|
||||
}
|
||||
|
||||
|
||||
void DevicePluginWs2812fx::deviceRemoved(Device *device)
|
||||
{
|
||||
if (device->deviceClassId() == ws2812fxDeviceClassId) {
|
||||
|
||||
m_usedInterfaces.removeAll(device->paramValue(ws2812fxDeviceSerialPortParamTypeId).toString());
|
||||
QSerialPort *serialPort = m_serialPorts.take(device);
|
||||
serialPort->flush();
|
||||
serialPort->close();
|
||||
serialPort->deleteLater();
|
||||
}
|
||||
|
||||
if (myDevices().empty()) {
|
||||
m_reconnectTimer->stop();
|
||||
m_reconnectTimer->deleteLater();
|
||||
}
|
||||
}
|
||||
|
||||
void DevicePluginWs2812fx::onReadyRead()
|
||||
{
|
||||
QSerialPort *serialPort = static_cast<QSerialPort*>(sender());
|
||||
Device *device = m_serialPorts.key(serialPort);
|
||||
|
||||
QByteArray data;
|
||||
while (serialPort->canReadLine()) {
|
||||
data = serialPort->readLine();
|
||||
qDebug(dcWs2812fx()) << "Message received" << data;
|
||||
|
||||
if (data.contains("mode")) {
|
||||
if (m_pendingActions.contains(CommandType::Mode)) {
|
||||
emit actionExecutionFinished(m_pendingActions.value(CommandType::Mode), Device::DeviceErrorNoError);
|
||||
}
|
||||
QString mode = data.split('-').at(1);
|
||||
mode.remove(0, 1);
|
||||
mode.remove("\r\n");
|
||||
qDebug(dcWs2812fx()) << "set mode to:" << mode;
|
||||
device->setStateValue(ws2812fxEffectModeStateTypeId, mode);
|
||||
}
|
||||
if (data.contains("brightness")) {
|
||||
if (m_pendingActions.contains(CommandType::Brightness)) {
|
||||
emit actionExecutionFinished(m_pendingActions.value(CommandType::Brightness), Device::DeviceErrorNoError);
|
||||
}
|
||||
QString rawBrightness = data.split(':').at(1);
|
||||
rawBrightness.remove(" ");
|
||||
rawBrightness.remove("\r\n");
|
||||
int brightness = rawBrightness.toInt();
|
||||
|
||||
qDebug(dcWs2812fx()) << "set brightness to:" << brightness;
|
||||
device->setStateValue(ws2812fxBrightnessStateTypeId, brightness);
|
||||
if (brightness == 0) {
|
||||
device->setStateValue(ws2812fxPowerStateTypeId, false);
|
||||
} else {
|
||||
device->setStateValue(ws2812fxPowerStateTypeId, true);
|
||||
}
|
||||
}
|
||||
if (data.contains("speed")) {
|
||||
if (m_pendingActions.contains(CommandType::Speed)) {
|
||||
emit actionExecutionFinished(m_pendingActions.value(CommandType::Speed), Device::DeviceErrorNoError);
|
||||
}
|
||||
QString rawSpeed = data.split(':').at(1);
|
||||
rawSpeed.remove(" ");
|
||||
rawSpeed.remove("\r\n");
|
||||
int speed = data.split(':').at(1).toInt();
|
||||
|
||||
qDebug(dcWs2812fx()) << "set speed to:" << speed;
|
||||
device->setStateValue(ws2812fxSpeedStateTypeId, speed);
|
||||
}
|
||||
if (data.contains("color")) {
|
||||
if (m_pendingActions.contains(CommandType::Color)) {
|
||||
emit actionExecutionFinished(m_pendingActions.value(CommandType::Color), Device::DeviceErrorNoError);
|
||||
}
|
||||
QString rawColor = data.split(':').at(1);
|
||||
rawColor.remove(" ");
|
||||
rawColor.remove("0x");
|
||||
rawColor.remove("\r\n");
|
||||
rawColor.prepend("#");
|
||||
qDebug(dcWs2812fx()) << "set color to:" << rawColor;
|
||||
device->setStateValue(ws2812fxColorStateTypeId, rawColor);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DevicePluginWs2812fx::onReconnectTimer()
|
||||
{
|
||||
foreach(Device *device, myDevices()) {
|
||||
if (!device->stateValue(ws2812fxConnectedStateTypeId).toBool()) {
|
||||
QSerialPort *serialPort = m_serialPorts.value(device);
|
||||
if (serialPort) {
|
||||
if (serialPort->open(QSerialPort::ReadWrite)) {
|
||||
device->setStateValue(ws2812fxConnectedStateTypeId, true);
|
||||
} else {
|
||||
device->setStateValue(ws2812fxConnectedStateTypeId, false);
|
||||
m_reconnectTimer->start();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void DevicePluginWs2812fx::onSerialError(QSerialPort::SerialPortError error)
|
||||
{
|
||||
QSerialPort *serialPort = static_cast<QSerialPort*>(sender());
|
||||
Device *device = m_serialPorts.key(serialPort);
|
||||
|
||||
if (error != QSerialPort::NoError && serialPort->isOpen()) {
|
||||
qCCritical(dcWs2812fx()) << "Serial port error:" << error << serialPort->errorString();
|
||||
m_reconnectTimer->start();
|
||||
serialPort->close();
|
||||
device->setStateValue(ws2812fxConnectedStateTypeId, false);
|
||||
}
|
||||
}
|
||||
|
||||
Device::DeviceError DevicePluginWs2812fx::sendCommand(Device* device, ActionId actionId, const QByteArray &command, CommandType commandType)
|
||||
{
|
||||
qDebug(dcWs2812fx()) << "Sending command" << command;
|
||||
QSerialPort *serialPort = m_serialPorts.value(device);
|
||||
if (!serialPort)
|
||||
return Device::DeviceErrorDeviceNotFound;
|
||||
if (serialPort->write(command) != command.length()) {
|
||||
qCWarning(dcWs2812fx) << "Error writing to serial port";
|
||||
return Device::DeviceErrorHardwareFailure;
|
||||
}
|
||||
m_pendingActions.insert(commandType, actionId);
|
||||
return Device::DeviceErrorAsync;
|
||||
}
|
||||
133
ws2812fx/devicepluginws2812fx.h
Normal file
133
ws2812fx/devicepluginws2812fx.h
Normal file
@ -0,0 +1,133 @@
|
||||
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||
* *
|
||||
* Copyright (C) 2019 Bernhard Trinnes <bernhard.trinnes@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 DEVICEPLUGINWS2812FX_H
|
||||
#define DEVICEPLUGINWS2812FX_H
|
||||
|
||||
#define FX_MODE_STATIC 0
|
||||
#define FX_MODE_BLINK 1
|
||||
#define FX_MODE_BREATH 2
|
||||
#define FX_MODE_COLOR_WIPE 3
|
||||
#define FX_MODE_COLOR_WIPE_INV 4
|
||||
#define FX_MODE_COLOR_WIPE_REV 5
|
||||
#define FX_MODE_COLOR_WIPE_REV_INV 6
|
||||
#define FX_MODE_COLOR_WIPE_RANDOM 7
|
||||
#define FX_MODE_RANDOM_COLOR 8
|
||||
#define FX_MODE_SINGLE_DYNAMIC 9
|
||||
#define FX_MODE_MULTI_DYNAMIC 10
|
||||
#define FX_MODE_RAINBOW 11
|
||||
#define FX_MODE_RAINBOW_CYCLE 12
|
||||
#define FX_MODE_SCAN 13
|
||||
#define FX_MODE_DUAL_SCAN 14
|
||||
#define FX_MODE_FADE 15
|
||||
#define FX_MODE_THEATER_CHASE 16
|
||||
#define FX_MODE_THEATER_CHASE_RAINBOW 17
|
||||
#define FX_MODE_RUNNING_LIGHTS 18
|
||||
#define FX_MODE_TWINKLE 19
|
||||
#define FX_MODE_TWINKLE_RANDOM 20
|
||||
#define FX_MODE_TWINKLE_FADE 21
|
||||
#define FX_MODE_TWINKLE_FADE_RANDOM 22
|
||||
#define FX_MODE_SPARKLE 23
|
||||
#define FX_MODE_FLASH_SPARKLE 24
|
||||
#define FX_MODE_HYPER_SPARKLE 25
|
||||
#define FX_MODE_STROBE 26
|
||||
#define FX_MODE_STROBE_RAINBOW 27
|
||||
#define FX_MODE_MULTI_STROBE 28
|
||||
#define FX_MODE_BLINK_RAINBOW 29
|
||||
#define FX_MODE_CHASE_WHITE 30
|
||||
#define FX_MODE_CHASE_COLOR 31
|
||||
#define FX_MODE_CHASE_RANDOM 32
|
||||
#define FX_MODE_CHASE_RAINBOW 33
|
||||
#define FX_MODE_CHASE_FLASH 34
|
||||
#define FX_MODE_CHASE_FLASH_RANDOM 35
|
||||
#define FX_MODE_CHASE_RAINBOW_WHITE 36
|
||||
#define FX_MODE_CHASE_BLACKOUT 37
|
||||
#define FX_MODE_CHASE_BLACKOUT_RAINBOW 38
|
||||
#define FX_MODE_COLOR_SWEEP_RANDOM 39
|
||||
#define FX_MODE_RUNNING_COLOR 40
|
||||
#define FX_MODE_RUNNING_RED_BLUE 41
|
||||
#define FX_MODE_RUNNING_RANDOM 42
|
||||
#define FX_MODE_LARSON_SCANNER 43
|
||||
#define FX_MODE_COMET 44
|
||||
#define FX_MODE_FIREWORKS 45
|
||||
#define FX_MODE_FIREWORKS_RANDOM 46
|
||||
#define FX_MODE_MERRY_CHRISTMAS 47
|
||||
#define FX_MODE_FIRE_FLICKER 48
|
||||
#define FX_MODE_FIRE_FLICKER_SOFT 49
|
||||
#define FX_MODE_FIRE_FLICKER_INTENSE 50
|
||||
#define FX_MODE_CIRCUS_COMBUSTUS 51
|
||||
#define FX_MODE_HALLOWEEN 52
|
||||
#define FX_MODE_BICOLOR_CHASE 53
|
||||
#define FX_MODE_TRICOLOR_CHASE 54
|
||||
#define FX_MODE_ICU 55
|
||||
#define FX_MODE_CUSTOM 56 // keep this for backward compatiblity
|
||||
#define FX_MODE_CUSTOM_0 56 // custom modes need to go at the end
|
||||
#define FX_MODE_CUSTOM_1 57
|
||||
#define FX_MODE_CUSTOM_2 58
|
||||
#define FX_MODE_CUSTOM_3 59
|
||||
|
||||
#include "devices/deviceplugin.h"
|
||||
|
||||
#include <QTimer>
|
||||
#include <QSerialPort>
|
||||
#include <QSerialPortInfo>
|
||||
|
||||
class DevicePluginWs2812fx : public DevicePlugin
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
Q_PLUGIN_METADATA(IID "io.nymea.DevicePlugin" FILE "devicepluginws2812fx.json")
|
||||
Q_INTERFACES(DevicePlugin)
|
||||
|
||||
public:
|
||||
explicit DevicePluginWs2812fx();
|
||||
|
||||
Device::DeviceSetupStatus setupDevice(Device *device) override;
|
||||
void deviceRemoved(Device *device) override;
|
||||
Device::DeviceError discoverDevices(const DeviceClassId &deviceClassId, const ParamList ¶ms) override;
|
||||
Device::DeviceError executeAction(Device *device, const Action &action) override;
|
||||
|
||||
private:
|
||||
enum CommandType {
|
||||
Color,
|
||||
Speed,
|
||||
Brightness,
|
||||
Mode
|
||||
};
|
||||
|
||||
QHash<Device *, QSerialPort *> m_serialPorts;
|
||||
QList<QString> m_usedInterfaces;
|
||||
QHash<CommandType, ActionId> m_pendingActions;
|
||||
|
||||
QTimer *m_reconnectTimer = nullptr;
|
||||
Device::DeviceError sendCommand(Device *device, ActionId actionId, const QByteArray &command, CommandType commandType);
|
||||
|
||||
private slots:
|
||||
void onReadyRead();
|
||||
void onReconnectTimer();
|
||||
void onSerialError(QSerialPort::SerialPortError error);
|
||||
|
||||
signals:
|
||||
|
||||
};
|
||||
|
||||
#endif // DEVICEPLUGINWS2812FX_H
|
||||
172
ws2812fx/devicepluginws2812fx.json
Normal file
172
ws2812fx/devicepluginws2812fx.json
Normal file
@ -0,0 +1,172 @@
|
||||
{
|
||||
"displayName": "WS2812FX",
|
||||
"name": "ws2812fx",
|
||||
"id": "5a3c8ca5-4ef7-47a3-bf3f-c257b9f11ef0",
|
||||
"vendors": [
|
||||
{
|
||||
"name": "nymea",
|
||||
"displayName": "nymea",
|
||||
"id": "2062d64d-3232-433c-88bc-0d33c0ba2ba6",
|
||||
"deviceClasses": [
|
||||
{
|
||||
"id": "24364e36-b199-4e35-b468-c44da58c009c",
|
||||
"name": "ws2812fx",
|
||||
"displayName": "WS2812FX",
|
||||
"createMethods": ["user", "discovery"],
|
||||
"interfaces": ["colorlight", "connectable"],
|
||||
"paramTypes": [
|
||||
{
|
||||
"id": "ed49f7d8-ab18-4c37-9b80-1004b75dcb91",
|
||||
"name": "serialPort",
|
||||
"displayName": "Serial port",
|
||||
"type": "QString",
|
||||
"inputType": "TextLine",
|
||||
"defaultValue": "ttyAMC0"
|
||||
}
|
||||
],
|
||||
"stateTypes": [
|
||||
{
|
||||
"id": "ee2c35ca-4236-43aa-aa7c-a5639c6dcf86",
|
||||
"name": "connected",
|
||||
"displayName": "reachable",
|
||||
"displayNameEvent": "reachable changed",
|
||||
"defaultValue": false,
|
||||
"type": "bool"
|
||||
},
|
||||
{
|
||||
"id": "00db76b4-86b3-4a3f-b4e8-ceded6891282",
|
||||
"name": "power",
|
||||
"displayName": "power",
|
||||
"displayNameEvent": "power changed",
|
||||
"displayNameAction": "Set power",
|
||||
"type": "bool",
|
||||
"defaultValue": false,
|
||||
"writable": true
|
||||
},
|
||||
{
|
||||
"id": "3de39d75-a775-43f1-b439-0fe326b4ba51",
|
||||
"name": "colorTemperature",
|
||||
"displayName": "color temperature",
|
||||
"displayNameEvent": "color temperature changed",
|
||||
"displayNameAction": "Set color temperature",
|
||||
"type": "int",
|
||||
"unit": "Mired",
|
||||
"defaultValue": 170,
|
||||
"minValue": 153,
|
||||
"maxValue": 500,
|
||||
"writable": true
|
||||
},
|
||||
{
|
||||
"id": "8490bab0-1fdc-4acc-81e4-e7cc91d9ce1d",
|
||||
"name": "color",
|
||||
"displayName": "color",
|
||||
"displayNameEvent": "color changed",
|
||||
"displayNameAction": "Set color",
|
||||
"type": "QColor",
|
||||
"defaultValue": "#000000",
|
||||
"writable": true
|
||||
},
|
||||
{
|
||||
"id": "05f2a002-6ce5-4811-bd79-44f15e981f5a",
|
||||
"name": "brightness",
|
||||
"displayName": "brightness",
|
||||
"displayNameEvent": "brightness changed",
|
||||
"displayNameAction": "Set brigtness",
|
||||
"type": "int",
|
||||
"unit": "Percentage",
|
||||
"defaultValue": 0,
|
||||
"minValue": 0,
|
||||
"maxValue": 100,
|
||||
"writable": true
|
||||
},
|
||||
{
|
||||
"id": "f1a37e73-1154-4f05-9444-d07566723c5a",
|
||||
"name": "speed",
|
||||
"displayName": "speed",
|
||||
"displayNameEvent": "speed changed",
|
||||
"displayNameAction": "Set speed",
|
||||
"type": "int",
|
||||
"unit": "Percentage",
|
||||
"defaultValue": 0,
|
||||
"minValue": 0,
|
||||
"maxValue": 100,
|
||||
"writable": true
|
||||
},
|
||||
{
|
||||
"id": "ebfb4bc6-b1dc-4a5c-a495-077cba4fec1a",
|
||||
"name": "effectMode",
|
||||
"displayName": "Effect mode",
|
||||
"displayNameEvent": "Effect mode changed",
|
||||
"displayNameAction": "Set effect mode",
|
||||
"type": "QString",
|
||||
"defaultValue": "Static",
|
||||
"possibleValues": [
|
||||
"Static",
|
||||
"Blink",
|
||||
"Breath",
|
||||
"Color Wipe",
|
||||
"Color Wipe Inverse",
|
||||
"Color Wipe Reverse",
|
||||
"Color Wipe Reverse Inverse",
|
||||
"Color Wipe Random ",
|
||||
"Random Color",
|
||||
"Single Dynamic",
|
||||
"Multi Dynamic",
|
||||
"Rainbow",
|
||||
"Rainbow Cycle",
|
||||
"Scan",
|
||||
"Dual Scan",
|
||||
"Fade",
|
||||
"Theater Chase",
|
||||
"Theater Chase Rainbow",
|
||||
"Running Lights",
|
||||
"Twinkle",
|
||||
"Twinkle Random",
|
||||
"Twinkle Fade",
|
||||
"Twinkle Fade Random",
|
||||
"Sparkle",
|
||||
"Flash Sparkle",
|
||||
"Hyper Sparkle",
|
||||
"Strobe",
|
||||
"Strobe Rainbow",
|
||||
"Multi Strobe",
|
||||
"Blink Rainbow",
|
||||
"Chase White",
|
||||
"Chase Color",
|
||||
"Chase Random",
|
||||
"Chase Rainbow",
|
||||
"Chase Flash",
|
||||
"Chase Flash Random",
|
||||
"Chase Rainbow White",
|
||||
"Chase Blackout",
|
||||
"Chase Blackout Rainbow",
|
||||
"Color Sweep Random",
|
||||
"Running Color",
|
||||
"Running Red Blue",
|
||||
"Running Random",
|
||||
"Larson Scanner",
|
||||
"Comet",
|
||||
"Fireworks",
|
||||
"Fireworks Random",
|
||||
"Merry Christmas",
|
||||
"Fire Flicker",
|
||||
"Fire Flicker (soft)",
|
||||
"Fire Flicker (intense)",
|
||||
"Circus Combustus",
|
||||
"Halloween",
|
||||
"Bicolor Chase",
|
||||
"Tricolor Chase",
|
||||
"ICU",
|
||||
"Custom 0",
|
||||
"Custom 1",
|
||||
"Custom 2",
|
||||
"Custom 3"
|
||||
],
|
||||
"writable": true
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
@ -0,0 +1 @@
|
||||
<?xml version="1.0" encoding="utf-8"?><!DOCTYPE TS><TS version="2.1"></TS>
|
||||
12
ws2812fx/ws2812fx.pro
Normal file
12
ws2812fx/ws2812fx.pro
Normal file
@ -0,0 +1,12 @@
|
||||
include(../plugins.pri)
|
||||
|
||||
QT += serialport
|
||||
|
||||
TARGET = $$qtLibraryTarget(nymea_devicepluginws2812fx)
|
||||
|
||||
SOURCES += \
|
||||
devicepluginws2812fx.cpp \
|
||||
|
||||
|
||||
HEADERS += \
|
||||
devicepluginws2812fx.h \
|
||||
Loading…
x
Reference in New Issue
Block a user