Skip to content

Commit

Permalink
Update documentation pages.
Browse files Browse the repository at this point in the history
- use snippets to verify that the code actually compiles
- travis compiles examples and snippets
- update Doxyfile
  • Loading branch information
Jojo-1000 authored and enwi committed Mar 24, 2021
1 parent 5818606 commit efd1ed5
Show file tree
Hide file tree
Showing 14 changed files with 589 additions and 336 deletions.
5 changes: 3 additions & 2 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -49,11 +49,12 @@ install:

script:
############################################################################
# Build main and tests
# Build main, tests and examples
############################################################################
- mkdir -p build
- cd build
- cmake .. -Dhueplusplus_TESTS=ON -DCMAKE_BUILD_TYPE=Debug
- cmake .. -Dhueplusplus_TESTS=ON -DCMAKE_BUILD_TYPE=Debug -Dhueplusplus_EXAMPLES=ON
- make hueplusplus_examples hueplusplus_snippets
- make coveragetest
- cd ..
- doxygen Doxyfile
Expand Down
4 changes: 2 additions & 2 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ endif()

# options to set
option(hueplusplus_TESTS "Build tests" OFF)
option(hueplusplus_SAMPLES "Build examples" OFF)
option(hueplusplus_EXAMPLES "Build examples" OFF)

option(CLANG_TIDY_FIX "Perform fixes for Clang-Tidy" OFF)
find_program(CLANG_TIDY_EXE NAMES "clang-tidy" DOC "Path to clang-tidy executable")
Expand Down Expand Up @@ -100,6 +100,6 @@ if(hueplusplus_TESTS)
add_subdirectory("test")
endif()

if(hueplusplus_SAMPLES)
if(hueplusplus_EXAMPLES)
add_subdirectory("examples")
endif()
426 changes: 279 additions & 147 deletions Doxyfile

Large diffs are not rendered by default.

8 changes: 5 additions & 3 deletions doc/markdown/Build.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
# Build and install {#build}

[TOC]

# Basic installation {#basic-install}

## Clone from github {#clone}
Expand Down Expand Up @@ -74,11 +76,11 @@ make coveragetest
```

## Building examples {#build-examples}
There are some small example programs using this library in the examples folder. To build them,
set `hueplusplus_SAMPLES=ON`. The target `hueplusplus_examples` builds all examples into 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_SAMPLES=ON
cmake .. -Dhueplusplus_EXAMPLES=ON
make hueplusplus_examples
```
50 changes: 15 additions & 35 deletions doc/markdown/Getting_Started.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,54 +6,34 @@ The options are a [WinHttpHandler](@ref hueplusplus::WinHttpHandler) (for window

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::HueFinder::findBridges), which will return a vector containing the ip and mac address of all found Bridges.
```{.cpp}
// For windows use std::make_shared<hueplusplus::WinHttpHandler>();
auto handler = std::make_shared<hueplusplus::LinHttpHandler>();
hueplusplus::BridgeFinder finder(handler);
std::vector<hueplusplus::BridgeFinder::BridgeIdentification> bridges = finder.findBridges();
if (bridges.empty())
{
std::cerr << "No bridges found\n";
return;
}
```
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.
```{.cpp}
hueplusplus::Bridge bridge = finder.getBridge(bridges[0]);
```
\snippet Snippets.cpp get-bridge-1

If you on the other hand already have a username you can add your bridge like so
```{.cpp}
finder.addUsername(bridges[0].mac, "<username>");
hueplusplus::Bridge bridge = finder.getBridge(bridges[0]);
```
If you do not want to use the HueFinder or you already know the ip and username of your bridge you have the option to create your own Hue object.
\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
```{.cpp}
// For windows use std::make_shared<hueplusplus::WinHttpHandler>();
auto handler = std::make_shared<hueplusplus::LinHttpHandler>();
hueplusplus::Bridge bridge("192.168.2.102", 80, "<username>", handler);
```
\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

```{.cpp}
hueplusplus::Light light = bridge.getLight(1);
light1.On();
light1.Off();
```
\snippet Snippets.cpp control-lights

Use [transactions](@ref transactions) to change multiple properties at once.

### Controlling groups

```{.cpp}
hueplusplus::Group group = bridge.getGroup(1);
group.setOn(true);
```
\snippet Snippets.cpp control-groups

## More information
- [Transactions](@ref transactions)
- [Transactions](@ref transactions)
- [Shared state cache](@ref shared-state)
78 changes: 30 additions & 48 deletions doc/markdown/Mainpage.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
# 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)
Expand All @@ -17,85 +19,57 @@ A simple and easy to use library for Philips Hue Lights.
* Espressif ESP32 SDK & Arduino

## How to use
- [Getting Started](@ref getting-started)
[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.
```{.cpp}
// For windows use std::make_shared<hueplusplus::WinHttpHandler>();
handler = std::make_shared<hueplusplus::LinHttpHandler>();
hueplusplus::BridgeFinder finder(handler);
std::vector<hueplusplus::BridgeFinder::BridgeIdentification> bridges = finder.findBridges();
if (bridges.empty())
{
std::cerr << "No bridges found\n";
return;
}
\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.
```{.cpp}
hueplusplus::Bridge bridge = finder.getBridge(bridges[0]);
```
\snippet Snippets.cpp get-bridge-1

If you on the other hand already have a username you can add your bridge like so
```{.cpp}
finder.addUsername(bridges[0].mac, "<username>");
hueplusplus::Bridge bridge = finder.getBridge(bridges[0]);
```
\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
```{.cpp}
// For windows use std::make_shared<hueplusplus::WinHttpHandler>();
handler = std::make_shared<hueplusplus::LinHttpHandler>();
hueplusplus::Bridge bridge("192.168.2.102", 80, "<username>", handler);
```
\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.
```{.cpp}
hueplusplus::Light light1 = bridge.lights().get(1);
```
\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.
```{.cpp}
std::vector<hueplusplus::Light> lights = bridge.lights().getAll();
```
\snippet Snippets.cpp light-2

If you now want to control a light, call a specific function of it.
```{.cpp}
light1.on();
light1.setBrightness(120);
light1.alertHueSaturation(25500, 255);
light1.setColorLoop(true);
light1.setColorRGB(255, 128, 0);
lights[1].off();
lights.at(1).setColorHue(4562);
```
\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.
```{.cpp}
hueplusplus::ColorType type1 = light1.getColorType();
```
\snippet Snippets.cpp light-4

There's also a new way to check whether specific functions of a light are available:
```{.cpp}
light1.hasBrightnessControl();
light1.hasTemperatureControl();
light1.hasColorControl();
```
\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)
[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.
Expand Down Expand Up @@ -155,3 +129,11 @@ If you also want to execute coverage tests you will need to install gcov and lco
```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)
49 changes: 9 additions & 40 deletions doc/markdown/Sensors.md
Original file line number Diff line number Diff line change
@@ -1,49 +1,30 @@
# 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.
```{.cpp}
hueplusplus::sensors::ZLLSwitch switchSensor = bridge.sensors().getAsType<hueplusplus::sensors::ZLLSwitch>(2);
```
\snippet Snippets.cpp known-sensor-1

You can also get all sensors of a specified type by using [getAllByType<T>()](@ref hueplusplus::SensorList::getAllByType).
```{.cpp}
std::vector<hueplusplus::sensors::ZLLSwitch> allSwitches = bridge.sensors().getAllByType<hueplusplus::sensors::ZLLSwitch>();
```
\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.

```{.cpp}
hueplusplus::Sensor genericSensor = bridge.sensors().get(1);
if(genericSensor.hasOn())
{
// Now can check whether it is on
if(genericSensor.isOn())
{
// ...
}
}
```
\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.
```{.cpp}
hueplusplus::Sensor genericSensor = bridge.sensors().get(1);
if(genericSensor.getType() == hueplusplus::sensors::ZLLSwitch::typeStr)
{
hueplusplus::sensors::ZLLSwitch switchSensor = genericSensor.asSensorType<hueplusplus::sensors::ZLLSwitch>();
// ...
}
```
\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
Expand All @@ -60,19 +41,7 @@ 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.

```{.cpp}
hueplusplus::sensors::ZLLSwitch switchSensor = ...;
// ZLLSwitch conditions operate on `buttonEvent`, use makeConditionLastUpdate()
// to trigger on the last update time.
// Some examples:
hueplusplus::Condition upPressed = makeCondition(switchSensor).eq(hueplusplus::sensors::ZLLSwitch::c_UP_INITIAL_PRESS);
hueplusplus::Condition buttonChanged = makeCondition(switchSensor).dx();
hueplusplus::time::TimeInterval interval(std::chrono::hours(12), std::chrono::hours(13));
hueplusplus::Condition updatedAtNoon = makeConditionLastUpdate(switchSensor).in(interval);
```
\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.
constructor with a proper address to the sensor state.
20 changes: 6 additions & 14 deletions doc/markdown/Shared_State.md
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
# 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 for the entire bridge.
2. All instances share the cache of the entire bridge.

### Advantages of shared state
* Different resources are always consistent on the library level.
Expand All @@ -23,12 +25,8 @@ Because of these considerations, shared state is disabled by default.
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.
```{.cpp}
hueplusplus::Bridge bridge = finder.getBridge(bridges[0], true);
```
```{.cpp}
hueplusplus::Bridge bridge("192.168.2.102", 80, "<username>", handler, std::chrono::seconds(10), true);
```
\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.
Expand All @@ -38,13 +36,7 @@ Otherwise, only the lowest necessary level is requested from the bridge to be mo

### Example:

```{.cpp}
bridge.setRefreshDuration(std::chrono::minutes(1));
bridge.lights().setRefreshDuration(std::chrono::seconds(30));
hueplusplus::Light light = bridge.lights().get(1);
// ... wait some time
bool on = light.isOn();
```
\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
Expand Down
Loading

0 comments on commit efd1ed5

Please sign in to comment.