Publish LumaOps source
This commit is contained in:
@@ -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)
|
||||
@@ -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)
|
||||
@@ -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
|
||||
Reference in New Issue
Block a user