phue2 0.0.1.dev279__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- phue2-0.0.1.dev279/.github/workflows/lint.yml +36 -0
- phue2-0.0.1.dev279/.github/workflows/publish.yml +26 -0
- phue2-0.0.1.dev279/.github/workflows/test.yml +55 -0
- phue2-0.0.1.dev279/.gitignore +11 -0
- phue2-0.0.1.dev279/.pre-commit-config.yaml +22 -0
- phue2-0.0.1.dev279/LICENSE +21 -0
- phue2-0.0.1.dev279/PKG-INFO +188 -0
- phue2-0.0.1.dev279/README.md +177 -0
- phue2-0.0.1.dev279/examples/connect_bridge.py +101 -0
- phue2-0.0.1.dev279/examples/flicker.py +54 -0
- phue2-0.0.1.dev279/examples/hue-rainbow.py +40 -0
- phue2-0.0.1.dev279/examples/random_colors.py +18 -0
- phue2-0.0.1.dev279/examples/rgb_colors.py +62 -0
- phue2-0.0.1.dev279/examples/sine_wave_lights.py +127 -0
- phue2-0.0.1.dev279/examples/tk_gui_complex.py +71 -0
- phue2-0.0.1.dev279/examples/tk_gui_hsb.py +119 -0
- phue2-0.0.1.dev279/examples/tk_gui_simple.py +33 -0
- phue2-0.0.1.dev279/justfile +9 -0
- phue2-0.0.1.dev279/pyproject.toml +75 -0
- phue2-0.0.1.dev279/src/phue2/__init__.py +37 -0
- phue2-0.0.1.dev279/src/phue2/__main__.py +408 -0
- phue2-0.0.1.dev279/src/phue2/_internal/__init__.py +1 -0
- phue2-0.0.1.dev279/src/phue2/_internal/console.py +175 -0
- phue2-0.0.1.dev279/src/phue2/bridge.py +1246 -0
- phue2-0.0.1.dev279/src/phue2/exceptions.py +22 -0
- phue2-0.0.1.dev279/src/phue2/group.py +118 -0
- phue2-0.0.1.dev279/src/phue2/light.py +301 -0
- phue2-0.0.1.dev279/src/phue2/scene.py +58 -0
- phue2-0.0.1.dev279/src/phue2/sensor.py +307 -0
- phue2-0.0.1.dev279/tests/__init__.py +0 -0
- phue2-0.0.1.dev279/tests/samples.py +268 -0
- phue2-0.0.1.dev279/tests/test_basic_import.py +7 -0
- phue2-0.0.1.dev279/tests/test_bridge.py +92 -0
- phue2-0.0.1.dev279/tests/test_cli.py +168 -0
- phue2-0.0.1.dev279/tests/test_request.py +103 -0
- phue2-0.0.1.dev279/uv.lock +1052 -0
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
name: Lint
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [ master ]
|
|
6
|
+
pull_request:
|
|
7
|
+
branches: [ master ]
|
|
8
|
+
|
|
9
|
+
jobs:
|
|
10
|
+
lint:
|
|
11
|
+
name: Lint
|
|
12
|
+
runs-on: ubuntu-latest
|
|
13
|
+
steps:
|
|
14
|
+
- uses: actions/checkout@v4
|
|
15
|
+
|
|
16
|
+
- name: Install uv
|
|
17
|
+
uses: astral-sh/setup-uv@v5
|
|
18
|
+
with:
|
|
19
|
+
enable-cache: true
|
|
20
|
+
version: "0.6.11"
|
|
21
|
+
|
|
22
|
+
- name: Install just
|
|
23
|
+
uses: extractions/setup-just@v2
|
|
24
|
+
|
|
25
|
+
- name: Set up Python
|
|
26
|
+
uses: actions/setup-python@v5
|
|
27
|
+
with:
|
|
28
|
+
python-version-file: "pyproject.toml"
|
|
29
|
+
|
|
30
|
+
- name: Install dependencies
|
|
31
|
+
run: uv sync
|
|
32
|
+
|
|
33
|
+
- name: Run pre-commit
|
|
34
|
+
uses: pre-commit/action@v3.0.1
|
|
35
|
+
with:
|
|
36
|
+
extra_args: --all-files
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
name: Publish phue2 to PyPI
|
|
2
|
+
on:
|
|
3
|
+
release:
|
|
4
|
+
types: [published]
|
|
5
|
+
workflow_dispatch:
|
|
6
|
+
|
|
7
|
+
jobs:
|
|
8
|
+
pypi-publish:
|
|
9
|
+
name: Upload to PyPI
|
|
10
|
+
runs-on: ubuntu-latest
|
|
11
|
+
permissions:
|
|
12
|
+
id-token: write
|
|
13
|
+
steps:
|
|
14
|
+
- name: Checkout
|
|
15
|
+
uses: actions/checkout@v4
|
|
16
|
+
with:
|
|
17
|
+
fetch-depth: 0
|
|
18
|
+
|
|
19
|
+
- name: "Install uv"
|
|
20
|
+
uses: astral-sh/setup-uv@v3
|
|
21
|
+
|
|
22
|
+
- name: Build
|
|
23
|
+
run: uv build --no-cache
|
|
24
|
+
|
|
25
|
+
- name: Publish to PyPi
|
|
26
|
+
run: uv publish -v dist/* --token ${{ secrets.UV_PUBLISH_TOKEN }}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
name: Tests
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [ master ]
|
|
6
|
+
paths:
|
|
7
|
+
- "src/**/*.py"
|
|
8
|
+
- "tests/**/*.py"
|
|
9
|
+
- "pyproject.toml"
|
|
10
|
+
- ".github/workflows/test.yml"
|
|
11
|
+
pull_request:
|
|
12
|
+
branches: [ master ]
|
|
13
|
+
paths:
|
|
14
|
+
- "src/**/*.py"
|
|
15
|
+
- "tests/**/*.py"
|
|
16
|
+
- "pyproject.toml"
|
|
17
|
+
- ".github/workflows/test.yml"
|
|
18
|
+
|
|
19
|
+
env:
|
|
20
|
+
# Enable colored output
|
|
21
|
+
PY_COLORS: 1
|
|
22
|
+
|
|
23
|
+
jobs:
|
|
24
|
+
test:
|
|
25
|
+
name: ${{ matrix.os }} - python:${{ matrix.python-version }}
|
|
26
|
+
runs-on: ${{ matrix.os }}
|
|
27
|
+
strategy:
|
|
28
|
+
fail-fast: false
|
|
29
|
+
matrix:
|
|
30
|
+
os: [ubuntu-latest, macos-latest]
|
|
31
|
+
python-version: ["3.10", "3.13"]
|
|
32
|
+
|
|
33
|
+
steps:
|
|
34
|
+
- uses: actions/checkout@v4
|
|
35
|
+
|
|
36
|
+
- name: Install uv
|
|
37
|
+
uses: astral-sh/setup-uv@v5
|
|
38
|
+
with:
|
|
39
|
+
enable-cache: true
|
|
40
|
+
version: "0.6.11"
|
|
41
|
+
python-version: ${{ matrix.python-version }}
|
|
42
|
+
|
|
43
|
+
- name: Install just
|
|
44
|
+
uses: extractions/setup-just@v2
|
|
45
|
+
with:
|
|
46
|
+
github-token: ${{ secrets.GITHUB_TOKEN }}
|
|
47
|
+
|
|
48
|
+
- name: Install dependencies
|
|
49
|
+
run: uv sync
|
|
50
|
+
|
|
51
|
+
- name: Build
|
|
52
|
+
run: just build
|
|
53
|
+
|
|
54
|
+
- name: Run tests
|
|
55
|
+
run: just test
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
repos:
|
|
2
|
+
- repo: https://github.com/astral-sh/uv-pre-commit
|
|
3
|
+
# uv version.
|
|
4
|
+
rev: 0.6.11
|
|
5
|
+
hooks:
|
|
6
|
+
- id: uv-lock
|
|
7
|
+
- repo: https://github.com/astral-sh/ruff-pre-commit
|
|
8
|
+
# Ruff version.
|
|
9
|
+
rev: v0.9.1
|
|
10
|
+
hooks:
|
|
11
|
+
# Run the linter.
|
|
12
|
+
- id: ruff
|
|
13
|
+
args: [--fix]
|
|
14
|
+
# Run the formatter.
|
|
15
|
+
- id: ruff-format
|
|
16
|
+
- repo: local
|
|
17
|
+
hooks:
|
|
18
|
+
- id: typecheck
|
|
19
|
+
name: typecheck
|
|
20
|
+
entry: just typecheck
|
|
21
|
+
language: system
|
|
22
|
+
pass_filenames: false
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
The MIT License (MIT)
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 Nathan Nowack
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in
|
|
13
|
+
all copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
21
|
+
THE SOFTWARE.
|
|
@@ -0,0 +1,188 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: phue2
|
|
3
|
+
Version: 0.0.1.dev279
|
|
4
|
+
Summary: A Philips Hue Python library
|
|
5
|
+
Author: Nathanaël Lécaudé, Nathan Nowack
|
|
6
|
+
License: MIT
|
|
7
|
+
License-File: LICENSE
|
|
8
|
+
Requires-Python: >=3.10
|
|
9
|
+
Requires-Dist: httpx
|
|
10
|
+
Description-Content-Type: text/markdown
|
|
11
|
+
|
|
12
|
+
# phue2
|
|
13
|
+
|
|
14
|
+
modern Python library to control the Philips Hue lighting system
|
|
15
|
+
|
|
16
|
+
This is a fork of the original [phue library](https://github.com/studioimaginaire/phue) by Nathanaël Lécaudé, modernized with type annotations, improved error handling, and a fully-featured CLI. The library remains MIT licensed.
|
|
17
|
+
|
|
18
|
+
> [!IMPORTANT]
|
|
19
|
+
|
|
20
|
+
> I appreciate the original authors work and if there's any interest in merging these (substantial) changes back into the original library, I'm happy to do so.
|
|
21
|
+
|
|
22
|
+
## Installation
|
|
23
|
+
|
|
24
|
+
### Using uv
|
|
25
|
+
|
|
26
|
+
```bash
|
|
27
|
+
uv add phue2
|
|
28
|
+
|
|
29
|
+
uv pip install phue2
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
### Using pip
|
|
33
|
+
|
|
34
|
+
```bash
|
|
35
|
+
pip install phue2
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
## Repository Structure
|
|
39
|
+
|
|
40
|
+
```
|
|
41
|
+
.
|
|
42
|
+
├── LICENSE
|
|
43
|
+
├── README.md
|
|
44
|
+
├── examples/
|
|
45
|
+
├── src/
|
|
46
|
+
│ └── phue/
|
|
47
|
+
│ ├── __init__.py
|
|
48
|
+
│ ├── __main__.py # CLI interface
|
|
49
|
+
│ ├── bridge.py # Bridge connection handling
|
|
50
|
+
│ ├── exceptions.py # Custom exceptions
|
|
51
|
+
│ ├── group.py # Group controls
|
|
52
|
+
│ ├── light.py # Light controls
|
|
53
|
+
│ ├── scene.py # Scene handling
|
|
54
|
+
│ └── sensor.py # Sensor controls
|
|
55
|
+
└── tests/ # Tests
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
## Requirements
|
|
59
|
+
|
|
60
|
+
- Python 3.10 or higher (not compatible with Python 2.x)
|
|
61
|
+
- httpx (for network requests)
|
|
62
|
+
|
|
63
|
+
## Features
|
|
64
|
+
|
|
65
|
+
- Fully typed with Python type annotations
|
|
66
|
+
- Robust error handling with custom exceptions
|
|
67
|
+
- Comprehensive test suite
|
|
68
|
+
- Colorful, user-friendly command-line interface
|
|
69
|
+
- Support for Lights, Groups, Scenes, and Sensors
|
|
70
|
+
- Auto-discovery of Hue bridges on the network
|
|
71
|
+
- Simple and intuitive API for controlling Hue devices
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
## Command Line Usage
|
|
76
|
+
|
|
77
|
+
The library includes a command-line interface for controlling your Hue lights:
|
|
78
|
+
|
|
79
|
+
```bash
|
|
80
|
+
# List all lights
|
|
81
|
+
phue ls
|
|
82
|
+
|
|
83
|
+
# Get details about a specific light
|
|
84
|
+
phue get light "Living Room"
|
|
85
|
+
|
|
86
|
+
# Turn on a light and set brightness
|
|
87
|
+
phue set light "Kitchen" --on --bri 200
|
|
88
|
+
|
|
89
|
+
# List all groups
|
|
90
|
+
phue ls groups
|
|
91
|
+
|
|
92
|
+
# Turn off lights in a group
|
|
93
|
+
phue set group "Downstairs" --off
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
## Basic Usage
|
|
97
|
+
|
|
98
|
+
Using the set_light and get_light methods you can control pretty much all the parameters:
|
|
99
|
+
|
|
100
|
+
```python
|
|
101
|
+
from phue2 import Bridge
|
|
102
|
+
|
|
103
|
+
# Connect to the bridge
|
|
104
|
+
b = Bridge('192.168.1.100')
|
|
105
|
+
|
|
106
|
+
# If the app is not registered and the button is not pressed, press the button and call connect()
|
|
107
|
+
# This only needs to be run a single time
|
|
108
|
+
b.connect()
|
|
109
|
+
|
|
110
|
+
# Get the bridge state (This returns the full dictionary that you can explore)
|
|
111
|
+
b.get_api()
|
|
112
|
+
|
|
113
|
+
# Prints if light 1 is on or not
|
|
114
|
+
b.get_light(1, 'on')
|
|
115
|
+
|
|
116
|
+
# Set brightness of lamp 1 to max
|
|
117
|
+
b.set_light(1, 'bri', 254)
|
|
118
|
+
|
|
119
|
+
# Turn lamp 2 on
|
|
120
|
+
b.set_light(2, 'on', True)
|
|
121
|
+
|
|
122
|
+
# You can also control multiple lamps by sending a list as lamp_id
|
|
123
|
+
b.set_light([1, 2], 'on', True)
|
|
124
|
+
|
|
125
|
+
# You can also use light names instead of the id
|
|
126
|
+
b.get_light('Kitchen')
|
|
127
|
+
b.set_light('Kitchen', 'bri', 254)
|
|
128
|
+
|
|
129
|
+
# Also works with lists
|
|
130
|
+
b.set_light(['Bathroom', 'Garage'], 'on', False)
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
### Light Objects
|
|
134
|
+
|
|
135
|
+
If you want to work in a more object-oriented way, you can get Light objects:
|
|
136
|
+
|
|
137
|
+
```python
|
|
138
|
+
# Get a flat list of light objects
|
|
139
|
+
lights = b.lights
|
|
140
|
+
|
|
141
|
+
# Print light names
|
|
142
|
+
for light in lights:
|
|
143
|
+
print(light.name)
|
|
144
|
+
|
|
145
|
+
# Set brightness of each light to 127
|
|
146
|
+
for light in lights:
|
|
147
|
+
light.brightness = 127
|
|
148
|
+
|
|
149
|
+
# Get a dictionary with the light name as the key
|
|
150
|
+
light_names = b.get_light_objects('name')
|
|
151
|
+
|
|
152
|
+
# Set lights using name as key
|
|
153
|
+
for light_name in ['Kitchen', 'Bedroom', 'Garage']:
|
|
154
|
+
light = light_names.get(light_name)
|
|
155
|
+
if light:
|
|
156
|
+
light.on = True
|
|
157
|
+
light.hue = 15000
|
|
158
|
+
light.saturation = 120
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
## Error Handling
|
|
162
|
+
|
|
163
|
+
The library provides custom exceptions for better error handling:
|
|
164
|
+
|
|
165
|
+
```python
|
|
166
|
+
from phue2 import Bridge, PhueRegistrationException, PhueRequestTimeout
|
|
167
|
+
|
|
168
|
+
try:
|
|
169
|
+
b = Bridge('192.168.1.100')
|
|
170
|
+
b.connect()
|
|
171
|
+
except PhueRegistrationException:
|
|
172
|
+
print("Press the button on the bridge and try again")
|
|
173
|
+
except PhueRequestTimeout:
|
|
174
|
+
print("Could not connect to the bridge - check your network")
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
## Acknowledgments
|
|
178
|
+
|
|
179
|
+
This project is a fork of the original [phue](https://github.com/studioimaginaire/phue) library created by Nathanaël Lécaudé.
|
|
180
|
+
|
|
181
|
+
The modernized version was created by [zzstoatzz](https://github.com/zzstoatzz) to add type annotations and a more opinionated CLI.
|
|
182
|
+
|
|
183
|
+
## License
|
|
184
|
+
|
|
185
|
+
MIT - http://opensource.org/licenses/MIT
|
|
186
|
+
|
|
187
|
+
"Hue Personal Wireless Lighting" is a trademark owned by Koninklijke Philips Electronics N.V., see www.meethue.com for more information.
|
|
188
|
+
I am in no way affiliated with the Philips organization.
|
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
# phue2
|
|
2
|
+
|
|
3
|
+
modern Python library to control the Philips Hue lighting system
|
|
4
|
+
|
|
5
|
+
This is a fork of the original [phue library](https://github.com/studioimaginaire/phue) by Nathanaël Lécaudé, modernized with type annotations, improved error handling, and a fully-featured CLI. The library remains MIT licensed.
|
|
6
|
+
|
|
7
|
+
> [!IMPORTANT]
|
|
8
|
+
|
|
9
|
+
> I appreciate the original authors work and if there's any interest in merging these (substantial) changes back into the original library, I'm happy to do so.
|
|
10
|
+
|
|
11
|
+
## Installation
|
|
12
|
+
|
|
13
|
+
### Using uv
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
uv add phue2
|
|
17
|
+
|
|
18
|
+
uv pip install phue2
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
### Using pip
|
|
22
|
+
|
|
23
|
+
```bash
|
|
24
|
+
pip install phue2
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
## Repository Structure
|
|
28
|
+
|
|
29
|
+
```
|
|
30
|
+
.
|
|
31
|
+
├── LICENSE
|
|
32
|
+
├── README.md
|
|
33
|
+
├── examples/
|
|
34
|
+
├── src/
|
|
35
|
+
│ └── phue/
|
|
36
|
+
│ ├── __init__.py
|
|
37
|
+
│ ├── __main__.py # CLI interface
|
|
38
|
+
│ ├── bridge.py # Bridge connection handling
|
|
39
|
+
│ ├── exceptions.py # Custom exceptions
|
|
40
|
+
│ ├── group.py # Group controls
|
|
41
|
+
│ ├── light.py # Light controls
|
|
42
|
+
│ ├── scene.py # Scene handling
|
|
43
|
+
│ └── sensor.py # Sensor controls
|
|
44
|
+
└── tests/ # Tests
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
## Requirements
|
|
48
|
+
|
|
49
|
+
- Python 3.10 or higher (not compatible with Python 2.x)
|
|
50
|
+
- httpx (for network requests)
|
|
51
|
+
|
|
52
|
+
## Features
|
|
53
|
+
|
|
54
|
+
- Fully typed with Python type annotations
|
|
55
|
+
- Robust error handling with custom exceptions
|
|
56
|
+
- Comprehensive test suite
|
|
57
|
+
- Colorful, user-friendly command-line interface
|
|
58
|
+
- Support for Lights, Groups, Scenes, and Sensors
|
|
59
|
+
- Auto-discovery of Hue bridges on the network
|
|
60
|
+
- Simple and intuitive API for controlling Hue devices
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
## Command Line Usage
|
|
65
|
+
|
|
66
|
+
The library includes a command-line interface for controlling your Hue lights:
|
|
67
|
+
|
|
68
|
+
```bash
|
|
69
|
+
# List all lights
|
|
70
|
+
phue ls
|
|
71
|
+
|
|
72
|
+
# Get details about a specific light
|
|
73
|
+
phue get light "Living Room"
|
|
74
|
+
|
|
75
|
+
# Turn on a light and set brightness
|
|
76
|
+
phue set light "Kitchen" --on --bri 200
|
|
77
|
+
|
|
78
|
+
# List all groups
|
|
79
|
+
phue ls groups
|
|
80
|
+
|
|
81
|
+
# Turn off lights in a group
|
|
82
|
+
phue set group "Downstairs" --off
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
## Basic Usage
|
|
86
|
+
|
|
87
|
+
Using the set_light and get_light methods you can control pretty much all the parameters:
|
|
88
|
+
|
|
89
|
+
```python
|
|
90
|
+
from phue2 import Bridge
|
|
91
|
+
|
|
92
|
+
# Connect to the bridge
|
|
93
|
+
b = Bridge('192.168.1.100')
|
|
94
|
+
|
|
95
|
+
# If the app is not registered and the button is not pressed, press the button and call connect()
|
|
96
|
+
# This only needs to be run a single time
|
|
97
|
+
b.connect()
|
|
98
|
+
|
|
99
|
+
# Get the bridge state (This returns the full dictionary that you can explore)
|
|
100
|
+
b.get_api()
|
|
101
|
+
|
|
102
|
+
# Prints if light 1 is on or not
|
|
103
|
+
b.get_light(1, 'on')
|
|
104
|
+
|
|
105
|
+
# Set brightness of lamp 1 to max
|
|
106
|
+
b.set_light(1, 'bri', 254)
|
|
107
|
+
|
|
108
|
+
# Turn lamp 2 on
|
|
109
|
+
b.set_light(2, 'on', True)
|
|
110
|
+
|
|
111
|
+
# You can also control multiple lamps by sending a list as lamp_id
|
|
112
|
+
b.set_light([1, 2], 'on', True)
|
|
113
|
+
|
|
114
|
+
# You can also use light names instead of the id
|
|
115
|
+
b.get_light('Kitchen')
|
|
116
|
+
b.set_light('Kitchen', 'bri', 254)
|
|
117
|
+
|
|
118
|
+
# Also works with lists
|
|
119
|
+
b.set_light(['Bathroom', 'Garage'], 'on', False)
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
### Light Objects
|
|
123
|
+
|
|
124
|
+
If you want to work in a more object-oriented way, you can get Light objects:
|
|
125
|
+
|
|
126
|
+
```python
|
|
127
|
+
# Get a flat list of light objects
|
|
128
|
+
lights = b.lights
|
|
129
|
+
|
|
130
|
+
# Print light names
|
|
131
|
+
for light in lights:
|
|
132
|
+
print(light.name)
|
|
133
|
+
|
|
134
|
+
# Set brightness of each light to 127
|
|
135
|
+
for light in lights:
|
|
136
|
+
light.brightness = 127
|
|
137
|
+
|
|
138
|
+
# Get a dictionary with the light name as the key
|
|
139
|
+
light_names = b.get_light_objects('name')
|
|
140
|
+
|
|
141
|
+
# Set lights using name as key
|
|
142
|
+
for light_name in ['Kitchen', 'Bedroom', 'Garage']:
|
|
143
|
+
light = light_names.get(light_name)
|
|
144
|
+
if light:
|
|
145
|
+
light.on = True
|
|
146
|
+
light.hue = 15000
|
|
147
|
+
light.saturation = 120
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
## Error Handling
|
|
151
|
+
|
|
152
|
+
The library provides custom exceptions for better error handling:
|
|
153
|
+
|
|
154
|
+
```python
|
|
155
|
+
from phue2 import Bridge, PhueRegistrationException, PhueRequestTimeout
|
|
156
|
+
|
|
157
|
+
try:
|
|
158
|
+
b = Bridge('192.168.1.100')
|
|
159
|
+
b.connect()
|
|
160
|
+
except PhueRegistrationException:
|
|
161
|
+
print("Press the button on the bridge and try again")
|
|
162
|
+
except PhueRequestTimeout:
|
|
163
|
+
print("Could not connect to the bridge - check your network")
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
## Acknowledgments
|
|
167
|
+
|
|
168
|
+
This project is a fork of the original [phue](https://github.com/studioimaginaire/phue) library created by Nathanaël Lécaudé.
|
|
169
|
+
|
|
170
|
+
The modernized version was created by [zzstoatzz](https://github.com/zzstoatzz) to add type annotations and a more opinionated CLI.
|
|
171
|
+
|
|
172
|
+
## License
|
|
173
|
+
|
|
174
|
+
MIT - http://opensource.org/licenses/MIT
|
|
175
|
+
|
|
176
|
+
"Hue Personal Wireless Lighting" is a trademark owned by Koninklijke Philips Electronics N.V., see www.meethue.com for more information.
|
|
177
|
+
I am in no way affiliated with the Philips organization.
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""
|
|
3
|
+
Example showing how to connect to a Philips Hue bridge.
|
|
4
|
+
This is a good first script to run when setting up phue.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
import json
|
|
8
|
+
import logging
|
|
9
|
+
import os
|
|
10
|
+
import sys
|
|
11
|
+
|
|
12
|
+
from phue2 import Bridge, Light, PhueRegistrationException, console
|
|
13
|
+
|
|
14
|
+
logging.basicConfig(level=logging.WARNING, format="%(levelname)s: %(message)s")
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
def light_formatter(light: Light) -> str:
|
|
18
|
+
"""Format a light for display in a table."""
|
|
19
|
+
status = "ON" if light.on else "OFF"
|
|
20
|
+
return f"{light.name:<25} - Status: {status}"
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
def main():
|
|
24
|
+
"""Connect to the Hue bridge and save credentials."""
|
|
25
|
+
console.header("Philips Hue Bridge Setup")
|
|
26
|
+
|
|
27
|
+
config_path = os.path.expanduser("~/.python_hue")
|
|
28
|
+
|
|
29
|
+
if os.path.exists(config_path):
|
|
30
|
+
try:
|
|
31
|
+
with open(config_path) as f:
|
|
32
|
+
config = json.loads(f.read())
|
|
33
|
+
if config:
|
|
34
|
+
console.info("Found existing Hue bridge configuration.")
|
|
35
|
+
|
|
36
|
+
for ip_address in config:
|
|
37
|
+
if "username" in config[ip_address]:
|
|
38
|
+
console.info(f"Trying saved bridge at {ip_address}...")
|
|
39
|
+
try:
|
|
40
|
+
bridge = Bridge(ip=ip_address)
|
|
41
|
+
lights = bridge.lights
|
|
42
|
+
console.success(f"Connected to bridge at {ip_address}")
|
|
43
|
+
console.table(lights, light_formatter)
|
|
44
|
+
return
|
|
45
|
+
except Exception as e:
|
|
46
|
+
console.error(f"Couldn't connect to {ip_address}")
|
|
47
|
+
console.info(f"Error details: {e}")
|
|
48
|
+
|
|
49
|
+
console.warning("Couldn't connect with any saved bridges.")
|
|
50
|
+
except (json.JSONDecodeError, FileNotFoundError):
|
|
51
|
+
console.error("Config file exists but is invalid.")
|
|
52
|
+
|
|
53
|
+
console.section("Bridge Connection Setup")
|
|
54
|
+
console.info("You'll need to provide your bridge IP address.")
|
|
55
|
+
console.info(
|
|
56
|
+
"You can find it in the Hue app (Settings > My Bridge) or your router."
|
|
57
|
+
)
|
|
58
|
+
|
|
59
|
+
ip_address = input("\nEnter your bridge IP address: ")
|
|
60
|
+
if not ip_address:
|
|
61
|
+
console.error("No IP address provided. Exiting.")
|
|
62
|
+
sys.exit(1)
|
|
63
|
+
|
|
64
|
+
while True:
|
|
65
|
+
console.section("Link Button Authentication")
|
|
66
|
+
console.warning("You need to press the link button on your Hue bridge.")
|
|
67
|
+
console.box(
|
|
68
|
+
"IMPORTANT",
|
|
69
|
+
[
|
|
70
|
+
"You only have 30 seconds to press the button!",
|
|
71
|
+
"Get ready to walk over to your bridge...",
|
|
72
|
+
],
|
|
73
|
+
)
|
|
74
|
+
|
|
75
|
+
input("\nPress Enter when you're ready to go press the button...")
|
|
76
|
+
|
|
77
|
+
try:
|
|
78
|
+
console.info("Attempting to register with the bridge...")
|
|
79
|
+
bridge = Bridge(ip=ip_address)
|
|
80
|
+
console.success("Connected and saved credentials!")
|
|
81
|
+
|
|
82
|
+
console.section("Your Hue Lights")
|
|
83
|
+
console.table(bridge.lights, light_formatter)
|
|
84
|
+
|
|
85
|
+
console.success("Setup complete! You can now control your Hue lights.")
|
|
86
|
+
break
|
|
87
|
+
|
|
88
|
+
except PhueRegistrationException:
|
|
89
|
+
console.error("Link button was not pressed in time.")
|
|
90
|
+
console.warning("Let's try again. Remember, you only have 30 seconds!")
|
|
91
|
+
|
|
92
|
+
except Exception as e:
|
|
93
|
+
console.error(f"Connection failed: {e}")
|
|
94
|
+
retry = input("\nTry again? (y/n): ")
|
|
95
|
+
if retry.lower() != "y":
|
|
96
|
+
console.error("Exiting. Please try again later.")
|
|
97
|
+
sys.exit(1)
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
if __name__ == "__main__":
|
|
101
|
+
main()
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
"""
|
|
2
|
+
This script will have all lights flicker randomly.
|
|
3
|
+
|
|
4
|
+
WARNING: If you have not previously connected to the bridge, run connect_bridge.py first.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
import random
|
|
8
|
+
from time import sleep
|
|
9
|
+
|
|
10
|
+
from phue2 import Bridge
|
|
11
|
+
|
|
12
|
+
b = Bridge()
|
|
13
|
+
b.connect()
|
|
14
|
+
lights = b.lights
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
def select_multiple_lights() -> list[int]:
|
|
18
|
+
"""
|
|
19
|
+
Selects a random number of lights from the list of lights every time, resulting in a 'flickering' look.
|
|
20
|
+
"""
|
|
21
|
+
return random.choices(range(1, len(lights) + 1), k=random.randint(1, len(lights)))
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
def multi_modal():
|
|
25
|
+
"""
|
|
26
|
+
Generates a random transition time between 0.2 and 0.7 seconds folowing a multi-modal distribution.
|
|
27
|
+
This results in really fast transitions, but also slow transitions.
|
|
28
|
+
"""
|
|
29
|
+
return [
|
|
30
|
+
2 + int(random.betavariate(1, 9) * 5),
|
|
31
|
+
2 + int(random.betavariate(9, 1) * 5),
|
|
32
|
+
][bool(random.getrandbits(1))]
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
def candle_flicker():
|
|
36
|
+
"""
|
|
37
|
+
Sends a command to change a certain number of lights a different color temperature every time. ct_inc was finicky, so I've used ct instead.
|
|
38
|
+
All inputs use a beta distribution, as it looked more natural. A similar look can be achieved using a triangular distribution as well.
|
|
39
|
+
"""
|
|
40
|
+
b.set_light(
|
|
41
|
+
select_multiple_lights(),
|
|
42
|
+
{
|
|
43
|
+
"transitiontime": multi_modal(),
|
|
44
|
+
"on": True,
|
|
45
|
+
"bri": 1 + int(random.betavariate(2, 5) * 253),
|
|
46
|
+
"ct": 153 + int(random.betavariate(9, 4) * 347),
|
|
47
|
+
},
|
|
48
|
+
)
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
if __name__ == "__main__":
|
|
52
|
+
while True:
|
|
53
|
+
candle_flicker()
|
|
54
|
+
sleep(random.random())
|