hyperion.ng/libsrc/leddevice/dev_net/LedDevicePhilipsHue.h
LordGrey ed5455458b
Disentangle LedDevice/LinearColorSmoothing, Bug Fixes & Test support (#654)
* Handle Exceptions in main & Pythoninit

* Have SSDPDiscover generic again

* Have SSDPDiscover generic again

* Change Info- to Debug logs as technical service messages

* Nanoleaf - When switched on, ensure UDP mode

* Include SQL Database in Cross-Compile instructions

* Fix Clazy (QT code checker) and clang Warnings

* Stop LedDevice:write for disabled device

* Nanoleaf: Fix uint printfs

* NanoLeaf: Fix indents to tabs

* NanoLeaf - Add debug verbosity switches

* Device switchability support, FileDevice with timestamp support

* Nanoleaf Light Panels now support External Control V2

* Enhance LedDeviceFile by Timestamp + fix readyness

* Stop color stream, if LedDevice disabled

* Nanoleaf - remove switchability

* Fix MultiColorAdjustment, if led-range is greater lednum

* Fix logging

* LedFileDevice/LedDevice - add testing support

* New "Led Test" effect

* LedDeviceFile - Add chrono include + Allow Led rewrites for testing

* Stabilize Effects for LedDevices where latchtime = 0

* Update LedDeviceFile, allow latchtime = 0

* Distangle LinearColorSmoothing and LEDDevice, Fix Effect configuration updates

* Updates LedDeviceFile - Initialize via Open

* Updates LedDeviceNanoleaf - Initialize via Open, Remove throwing exceptions

* Updates ProviderUDP - Remove throwing exceptions

* Framebuffer - Use precise timer

* TestSpi - Align to LedDevice updates

* Pretty Print CrossCompileHowTo as markdown-file

* Ensure that output is only written when LedDevice is ready

* Align APA102 Device to new device staging

* Logger - Remove clang warnings on extra semicolon

* Devices SPI - Align to Device stages and methods

* Fix cppcheck and clang findings

* Add Code-Template for new Devices

* Align devices to stages and methods, clean-up some code

* Allow to reopen LedDevice without restart

* Revert change "Remove Connect (PriorityMuxer::visiblePriorityChanged -> Hyperion::update) due to double writes"

* Remove visiblePriorityChanged from LedDevice to decouple LedDevice from hyperion logic

* Expose LedDevice getLedCount and align signedness
2020-02-10 15:21:58 +01:00

270 lines
6.1 KiB
C++

#pragma once
// STL includes
#include <set>
// Qt includes
#include <QNetworkAccessManager>
#include <QTimer>
// Leddevice includes
#include <leddevice/LedDevice.h>
// Forward declaration
struct CiColorTriangle;
/**
* A color point in the color space of the hue system.
*/
struct CiColor
{
/// X component.
float x;
/// Y component.
float y;
/// The brightness.
float bri;
///
/// Converts an RGB color to the Hue xy color space and brightness.
/// https://github.com/PhilipsHue/PhilipsHueSDK-iOS-OSX/blob/master/ApplicationDesignNotes/RGB%20to%20xy%20Color%20conversion.md
///
/// @param red the red component in [0, 1]
///
/// @param green the green component in [0, 1]
///
/// @param blue the blue component in [0, 1]
///
/// @return color point
///
static CiColor rgbToCiColor(float red, float green, float blue, CiColorTriangle colorSpace);
///
/// @param p the color point to check
///
/// @return true if the color point is covered by the lamp color space
///
static bool isPointInLampsReach(CiColor p, CiColorTriangle colorSpace);
///
/// @param p1 point one
///
/// @param p2 point tow
///
/// @return the cross product between p1 and p2
///
static float crossProduct(CiColor p1, CiColor p2);
///
/// @param a reference point one
///
/// @param b reference point two
///
/// @param p the point to which the closest point is to be found
///
/// @return the closest color point of p to a and b
///
static CiColor getClosestPointToPoint(CiColor a, CiColor b, CiColor p);
///
/// @param p1 point one
///
/// @param p2 point tow
///
/// @return the distance between the two points
///
static float getDistanceBetweenTwoPoints(CiColor p1, CiColor p2);
};
bool operator==(CiColor p1, CiColor p2);
bool operator!=(CiColor p1, CiColor p2);
/**
* Color triangle to define an available color space for the hue lamps.
*/
struct CiColorTriangle
{
CiColor red, green, blue;
};
class PhilipsHueBridge : public QObject
{
Q_OBJECT
private:
Logger* _log;
/// QNetworkAccessManager for sending requests.
QNetworkAccessManager manager;
/// Ip address of the bridge
QString host;
/// User name for the API ("newdeveloper")
QString username;
/// Timer for bridge reconnect interval
QTimer bTimer;
private slots:
///
/// Receive all replies and check for error, schedule reconnect on issues
/// Emits newLights() on success when triggered from connect()
///
void resolveReply(QNetworkReply* reply);
public slots:
///
/// Connect to bridge to check availbility and user
///
void bConnect(void);
signals:
///
/// Emits with a QMap of current bridge light/value pairs
///
void newLights(QMap<quint16,QJsonObject> map);
public:
PhilipsHueBridge(Logger* log, QString host, QString username);
///
/// @param route the route of the POST request.
///
/// @param content the content of the POST request.
///
void post(QString route, QString content);
};
/**
* Simple class to hold the id, the latest color, the color space and the original state.
*/
class PhilipsHueLight
{
private:
Logger* _log;
PhilipsHueBridge* bridge;
/// light id
unsigned int id;
bool on;
unsigned int transitionTime;
CiColor color;
/// The model id of the hue lamp which is used to determine the color space.
QString modelId;
CiColorTriangle colorSpace;
/// The json string of the original state.
QString originalState;
///
/// @param state the state as json object to set
///
void set(QString state);
public:
// Hue system model ids (http://www.developers.meethue.com/documentation/supported-lights).
// Light strips, color iris, ...
static const std::set<QString> GAMUT_A_MODEL_IDS;
// Hue bulbs, spots, ...
static const std::set<QString> GAMUT_B_MODEL_IDS;
// Hue Lightstrip plus, go ...
static const std::set<QString> GAMUT_C_MODEL_IDS;
///
/// Constructs the light.
///
/// @param log the logger
/// @param bridge the bridge
/// @param id the light id
///
PhilipsHueLight(Logger* log, PhilipsHueBridge* bridge, unsigned int id, QJsonObject values);
~PhilipsHueLight();
///
/// @param on
///
void setOn(bool on);
///
/// @param transitionTime the transition time between colors in multiples of 100 ms
///
void setTransitionTime(unsigned int transitionTime);
///
/// @param color the color to set
/// @param brightnessFactor the factor to apply to the CiColor#bri value
///
void setColor(CiColor color, float brightnessFactor = 1.0f);
CiColor getColor() const;
///
/// @return the color space of the light determined by the model id reported by the bridge.
CiColorTriangle getColorSpace() const;
};
/**
* Implementation for the Philips Hue system.
*
* To use set the device to "philipshue".
* Uses the official Philips Hue API (http://developers.meethue.com).
*
* @author ntim (github), bimsarck (github)
*/
class LedDevicePhilipsHue: public LedDevice
{
Q_OBJECT
public:
///
/// Constructs specific LedDevice
///
/// @param deviceConfig json device config
///
explicit LedDevicePhilipsHue(const QJsonObject &deviceConfig);
///
/// Destructor of this device
///
virtual ~LedDevicePhilipsHue();
/// constructs leddevice
static LedDevice* construct(const QJsonObject &deviceConfig);
public slots:
/// thread start
virtual void start() override;
private slots:
/// creates new PhilipsHueLight(s) based on user lightid with bridge feedback
///
/// @param map Map of lightid/value pairs of bridge
///
void newLights(QMap<quint16, QJsonObject> map);
void stateChanged(bool newState);
protected:
///
/// Writes the RGB-Color values to the leds.
///
/// @param[in] ledValues The RGB-color per led
///
/// @return Zero on success else negative
///
virtual int write(const std::vector<ColorRgb> & ledValues) override;
bool init(const QJsonObject &deviceConfig) override;
private:
/// bridge class
PhilipsHueBridge* _bridge;
///
bool switchOffOnBlack;
/// The brightness factor to multiply on color change.
float brightnessFactor;
/// Transition time in multiples of 100 ms.
/// The default of the Hue lights is 400 ms, but we may want it snapier.
int transitionTime;
/// Array of the light ids.
std::vector<unsigned int> lightIds;
/// Array to save the lamps.
std::vector<PhilipsHueLight> lights;
};