Publish LumaOps source

This commit is contained in:
LumaOps release export
2026-09-03 01:18:36 +02:00
commit 7f1c0e5f71
2363 changed files with 501543 additions and 0 deletions
+90
View File
@@ -0,0 +1,90 @@
# Build and install {#build}
[TOC]
# Basic installation {#basic-install}
## Clone from github {#clone}
To get the newest version of the hueplusplus library, clone it directly from [github](https://github.com/enwi/hueplusplus).
The master branch contains the latest tested and stable version, while the development branch is more unstable.
```{.sh}
~ $ git clone https://github.com/enwi/hueplusplus.git
```
This creates a folder hueplusplus with the library sources.
When you want to update the library for a new version, use pull with rebase.
```{.sh}
~/hueplusplus $ git pull --rebase
```
## Build with CMake {#build-cmake}
To build the library, you need to use [CMake](https://cmake.org) version 3.10 or higher.
It is easiest to create a separate build directory where the build files are stored.
```{.sh}
~/hueplusplus $ mkdir build
~/hueplusplus $ cd build
~/hueplusplus/build $ cmake ..
~/hueplusplus/build $ make
```
To install or uninstall the library use the make targets.
```{.sh}
~/hueplusplus/build $ make install
~/hueplusplus/build $ make uninstall
```
## Use in a CMake project {#import-cmake}
If you have a project that already uses CMake you probably want to add the hueplusplus library directly in your cmake file.
For that the best way is to use find_package().
```{.cmake}
find_package(hueplusplus REQUIRED)
```
But this will only work if the hueplusplus library is already installed.
Instead, if you have the hueplusplus repository included in your project repository (as a submodule) or know where the folder lives you can do the following:
```{.cmake}
find_package(hueplusplus QUIET)
if(NOT hueplusplus_FOUND)
message(STATUS "-- hueplusplus not found, building it")
add_subdirectory("${CMAKE_CURRENT_SOURCE_DIR}/<path to directory>/hueplusplus" "${CMAKE_CURRENT_BINARY_DIR}/hueplusplus")
endif()
```
This will check if the hueplusplus library was found by find_package() and if not it will use the specified path to the library source and compile it during the build process.
The cmake project defines two library targets: `hueplusplusstatic` to link as a static library and `hueplusplusshared` to link as a shared library.
```{.cmake}
target_link_libraries(<executable> PUBLIC hueplusplusstatic)
```
## Use in another project {#import-other}
When you are not using CMake, you have to install hueplusplus and change your build configuration to link to the compiled library.
The header files in the include directory need to be added to the include path.
How you do this depends on the build system.
## Building tests {#build-tests}
If you additionally want to run the tests use cmake with the option -Dhueplusplus_TESTS=ON. Testing is done with Google gtest and gmock. Note that you wont need to install gtest/gmock yourself, because cmake will automatically download them and include them during the build.
The custom target `unittest` compiles and executes all tests.
```bash
mkdir build
cd build
cmake .. -Dhueplusplus_TESTS=ON
make unittest
```
If you also want to execute coverage tests you will need to install gcov and lcov yourself. To run the coverage test use
```bash
make coveragetest
```
## Building examples {#build-examples}
There are some small [example programs](@ref examples) using this library in the examples folder. To build them,
set `hueplusplus_EXAMPLES=ON`. The target `hueplusplus_examples` builds all examples into build/examples.
```{.sh}
mkdir build
cd build
cmake .. -Dhueplusplus_EXAMPLES=ON
make hueplusplus_examples
```
## External libraries
Hueplusplus requires a few external libraries (e.g. Mbed TLS and GTest), which are included automatically. If these are pre-installed on your system, those versions will be used by default. This can potentially cause issues if your installed versions are incompatible.
In this case, set `hueplusplus_NO_EXTERNAL_LIBRARIES=ON` to force using the embedded versions instead of the installed libraries.
@@ -0,0 +1,39 @@
# Getting started {#getting-started}
## Creating the Hue bridge
To start searching for a Hue Bridge you will need to choose an IHttpHandler and create one.
The options are a [WinHttpHandler](@ref hueplusplus::WinHttpHandler) (for windows) or a [LinHttpHandler](@ref hueplusplus::LinHttpHandler) (for linux or linux-like).
Then create a [BridgeFinder](@ref hueplusplus::BridgeFinder) object with the handler.
The handler is needed, because it tells the finder which functions to use to communicate with a bridge or your local network.
After that you can call [findBridges()](@ref hueplusplus::BridgeFinder::findBridges), which will return a vector containing the ip and mac address of all found Bridges.
\snippet Snippets.cpp search-bridge
## Authenticate Bridges
If you have found the Bridge you were looking for, you can then move on with the authentication process.
To get a new username from the Bridge (for now) you simply call [getBridge(bridges[\<index\>])](@ref hueplusplus::BridgeFinder::getBridge),
where index is your preferred Bridge from the part [Searching for Bridges](#searchingBridges). This requires the user to press the link button.
\snippet Snippets.cpp get-bridge-1
If you on the other hand already have a username you can add your bridge like so
\snippet Snippets.cpp get-bridge-2
If you do not want to use the BridgeFinder or you already know the ip and username of your bridge you have the option to create your own Hue object.
Here you will need to provide the ip address, the port number, a username and an HttpHandler
\snippet Snippets.cpp get-bridge-3
At this point you may want to decide whether to use a [shared state](@ref shared-state) cache model or keep the default settings.
### Controlling lights
\snippet Snippets.cpp control-lights
Use [transactions](@ref transactions) to change multiple properties at once.
### Controlling groups
\snippet Snippets.cpp control-groups
## More information
- [Transactions](@ref transactions)
- [Shared state cache](@ref shared-state)
+139
View File
@@ -0,0 +1,139 @@
# Documentation for the hueplusplus library
A simple and easy to use library for Philips Hue Lights.
[TOC]
## Features
* find bridges with SSDP or set an ip manually
* all common light functions (brightness, color, temperature)
* extended alert() functions, which alert in a specific color (good for notifications)
* supports sensors, rules, groups, scenes and schedules
* streaming with entertainment mode
* documented with doxygen
* tested with google test, google mock and gcov/lcov
## Compatibility
* Linux
* Windows
* MacOS
* Espressif ESP32 SDK & Arduino
## How to use
[Getting started](@ref getting-started)
### Searching for Bridges
To start searching for a Hue Bridge you will need to choose an IHttpHandler and create one. The options are a [WinHttpHandler](@ref hueplusplus::WinHttpHandler) (for windows) or a [LinHttpHandler](@ref hueplusplus::LinHttpHandler) (for linux or linux-like).
Then create a [BridgeFinder](@ref hueplusplus::BridgeFinder) object with the handler.
The handler is needed, because it tells the finder which functions to use to communicate with a bridge or your local network.
After that you can call [findBridges()](@ref hueplusplus::BridgeFinder::findBridges), which will return a vector containing the ip and mac address of all found Bridges.
\snippet Snippets.cpp search-bridge
At this point you may want to decide whether to use a [shared state](@ref shared-state) cache model or keep the default settings.
### Authenticate Bridges
If you have found the Bridge you were looking for, you can then move on with the authentication process.
To get a new username from the Bridge (for now) you simply call [getBridge(bridges[\<index\>])](@ref hueplusplus::BridgeFinder::getBridge),
where index is your preferred Bridge from the part [Searching for Bridges](#searchingBridges). This requires the user to press the link button.
\snippet Snippets.cpp get-bridge-1
If you on the other hand already have a username you can add your bridge like so
\snippet Snippets.cpp get-bridge-2
If you do not want to use the BridgeFinder or you already know the ip and username of your bridge you have the option to create your own Bridge object.
Here you will need to provide the ip address, the port number, a username and an HttpHandler
\snippet Snippets.cpp get-bridge-3
### Controlling lights
If you have your Bridge all set up, you can now control its lights.
For that create a new Light object and call [lights().get(\<id\>)](@ref hueplusplus::ResourceList::get) on your bridge object to get a reference to a specific light, where id
is the id of the light set internally by the Hue Bridge.
\snippet Snippets.cpp light-1
If you don't know the id of a specific light or want to get an overview over all lights that are controlled by your bridge,
you can get a vector containing them by calling [getAll()](@ref hueplusplus::ResourceList::getAll) on your bridge object. If no lights are found the vector will be empty.
\snippet Snippets.cpp light-2
If you now want to control a light, call a specific function of it.
\snippet Snippets.cpp light-3
But keep in mind that some light types do not have all functions available. So you might call a
specific function, but nothing will happen. For that you might want to check what type
of a light you are controlling. For that you can call the function [getColorType()](@ref hueplusplus::Light::getColorType()), which will return
a ColorType.
\snippet Snippets.cpp light-4
There's also a new way to check whether specific functions of a light are available:
\snippet Snippets.cpp light-5
These will either return true(light has specified function) or false(light lacks specified function).
## Build and install
[Build and install guide](@ref build)
### Basic installation
If you want to build the library you can use cmake (at least version 3.8). First create a build folder and then execute cmake.
```bash
mkdir build
cd build
cmake ..
```
Then compile the code with make. If you are inpatient use the option -j\<number\>, where number specifies how many files are compiled at the same time. Note this number should not exceed the number of cores*2 of your machine.
```bash
make
```
```bash
make -j4
```
If you want to install the library use
```bash
make install
```
To remove it
```bash
make uninstall
```
### Advanced usage
If you have a project that already uses CMake you probably want to add the hueplusplus library directly in your cmake file.
For that the best way is to use find_package().
When cmake finds the hueplusplus library you can then link against either the shared or static version of the library.
```cmake
find_package(hueplusplus REQUIRED)
target_link_libraries(<executable> PUBLIC hueplusplusstatic)
```
But this will only work if the hueplusplus library is already installed.
To get around this problem there is a pretty awesome way.
If you have the hueplusplus repository included in your project repository (as a submodule) or know where the folder lives you can do the following:
```cmake
find_package(hueplusplus QUIET)
if(NOT hueplusplus_FOUND)
message(STATUS "-- hueplusplus not found, building it")
add_subdirectory("${CMAKE_CURRENT_SOURCE_DIR}/<path to directory>/hueplusplus" "${CMAKE_CURRENT_BINARY_DIR}/hueplusplus")
endif()
target_link_libraries(<executable> PUBLIC hueplusplusstatic)
```
This will check if the hueplusplus library was found by find_package() and if not it will use the specified path to the library source and compile it during the build process.
### Running tests
If you additionally want to run the tests use cmake with the option -Dhueplusplus_TESTS=ON. Testing is done with Google gtest and gmock. Note that you wont need to install gtest/gmock yourself, because cmake will automatically download them and include them during the build. Since I added a custom target you will only need to call "make unittest" and the tests are compiled and executed.
```bash
mkdir build
cd build
cmake .. -Dhueplusplus_TESTS=ON
make unittest
```
If you also want to execute coverage tests you will need to install gcov and lcov yourself. To run the coverage test use
```bash
make coveragetest
```
## Other pages
- [Getting started](@ref getting-started)
- [Build and install](@ref build)
- [Shared state cache](@ref shared-state)
- [Transactions](@ref transactions)
- [Sensors](@ref sensors)
+47
View File
@@ -0,0 +1,47 @@
# Sensors {#sensors}
[TOC]
## Sensor support
The library supports the sensor types listed on the Hue developer documentation.
Include `hueplusplus/ZLLSensors.h` for ZigBee sensors and `hueplusplus/CLIPSensors.h` for CLIP sensors.
Other sensors can be used with the generic [Sensor](@ref hueplusplus::Sensor) class.
### Working with a known sensor
In most cases, the type of the sensors is known in advance, such as a switch.
The classes in the [sensors](@ref hueplusplus::sensors) namespace provide the documented
functionality. The type can be specified when accessing the sensor. When it does not match,
an exception is thrown.
\snippet Snippets.cpp known-sensor-1
You can also get all sensors of a specified type by using [getAllByType<T>()](@ref hueplusplus::SensorList::getAllByType).
\snippet Snippets.cpp known-sensor-2
### Working with an unknown sensor
When the sensor type is not known, use the generic sensor class. In this case, some attributes might not
exist, so they have to be checked first. This applies to all attributes that have a `hasXXX` method.
\snippet Snippets.cpp generic-sensor-1
It is easiest to compare the sensor type to the existing ones (`typeStr` on the specific sensor classes)
and then convert the sensor to that type.
\snippet Snippets.cpp generic-sensor-2
## ZLL sensors vs. CLIP sensors
ZLL sensors (defined in `ZLLSensors.h`) are physical device sensors which send their data
to the bridge using ZigBee. They are added in the same way as lights are, using [search()](@ref hueplusplus::SearchableResourceList::search).
CLIP sensors (in `CLIPSensors.h`) are added using [create()](@ref hueplusplus::CreateableResourceList::create) with [CreateSensor](@ref hueplusplus::CreateSensor)
for parameters. In general, which config and state attributes exist is specified when the sensor is created.
The values of CLIP sensors can be changed using requests, unlike ZLL sensors. They can also have a URL to query from.
## Creating conditions
The most important use for sensors is in [Rules](@ref hueplusplus::Rule), to trigger changes.
Conditions can be created from the specific sensor types using `makeCondition()`.
These functions return a helper class with methods for the [possible operators](@ref hueplusplus::Condition::Operator) valid for the state.
For some sensors, which have multiple possible states, there exist multiple variations of makeCondition.
\snippet Snippets.cpp sensor-conditions
For generic sensors, the conditions must be created manually using the [Condition](@ref hueplusplus::Condition::Condition)
constructor with a proper address to the sensor state.
@@ -0,0 +1,46 @@
# Shared state cache {#shared-state}
[TOC]
## What shared state means
There are two ways in which the API state (internally JSON) can be handled:
1. Every resource instance holds its own cache of the state (default).
2. All instances share the cache of the entire bridge.
### Advantages of shared state
* Different resources are always consistent on the library level.
If one part of the code uses the light with id 1 and turns it off,
light 1 is also off when using a different variable to access it.
* The number of requests can be reduced, because they can be bundled together on a higher cache level.
### Disadvantages of shared state
* Different objects are no longer thread safe, you cannot use **any** parts of the library
from multiple threads (without locking).
* Changes are not transparent. For example, a `const Light` can suddenly change its name, because the
name was changed somewhere else in the code.
Because of these considerations, shared state is disabled by default.
## Enabling shared state
Shared state can be configured when the bridge is first constructed, either in [getBridge()](@ref hueplusplus::BridgeFinder::getBridge)
or in the [constructor](@ref hueplusplus::Bridge::Bridge). Set `sharedState` to `true` to keep all resources
connected to the bridge cache.
\snippet Snippets.cpp shared-bridge-1
\snippet Snippets.cpp shared-bridge-2
## Shared state and refreshing
When shared cache is used, refreshes use a hierarchichal structure to determine how much should be requested from the bridge.
Every level has its own last update time and refresh duration.
First, it is checked whether the higher level is up to date and refresh everything if not.
Otherwise, only the lowest necessary level is requested from the bridge to be more efficient.
### Example:
\snippet Snippets.cpp refresh-example
[isOn()](@ref hueplusplus::Light::isOn) is a non-const method (in this case). That means it will refresh the
state if it is outdated. The default refresh time is inherited from `bridge.lights()`, so it is 30 seconds.
After 30 seconds, the state of `light` *and* `bridge.lights()` is outdated. Therefore, the entire list of lights is
updated at this point.
After more than one minute, the bridge state is considered outdated. This means that `isOn()` causes an update of
the entire bridge.
@@ -0,0 +1,38 @@
# Transactions {#transactions}
[TOC]
## Using a transaction for lights
Often, you want to change more than one property on a light at the same time,
for example brightness and color. This is done using transactions ([StateTransaction](@ref hueplusplus::StateTransaction)).
\snippet Snippets.cpp transaction-lights
The request is reduced to only the variables that need to be changed based on the current state.
For example, if the light is already on, that part of the transaction is ignored.
__Important:__ The transaction has an internal reference to the light state.
You must not cause a refresh of the state between creating and committing the transaction (e.g. non-const getters/setters),
because that invalidates the reference.
### Advanced usage
Another way to use the transaction is by storing it and building up the calls separately.
\snippet Snippets.cpp transaction-advanced
In this case, it is especially important that the light and the state of the light __MUST NOT__ invalidate. That means
* the light variable has to live longer than the transaction
* especially no non-const method calls on the light while the transaction is open, or committing other transactions
In general, this method is easier to screw up and should only be used when really necessary.
## Using a transaction for groups
The same principles of transactions for lights also apply for groups. The main difference is that
for groups, there are no checks of the current state. Even if all lights in the group are already on,
the request to turn on all lights on the group is still sent.
\snippet Snippets.cpp transaction-groups
## Creating Actions
In a [Schedule](@ref hueplusplus::Schedule) or [Rule](@ref hueplusplus::Rule),
the bridge can set the state of lights and groups. To configure this, a transaction
can be saved for later instead of committing it directly.
\snippet Snippets.cpp transaction-action