Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/alin23/lunarsensor
Server that mimics a Lunar ambient light sensor, with support for multiple lux data sources
https://github.com/alin23/lunarsensor
iot monitor
Last synced: 3 months ago
JSON representation
Server that mimics a Lunar ambient light sensor, with support for multiple lux data sources
- Host: GitHub
- URL: https://github.com/alin23/lunarsensor
- Owner: alin23
- Created: 2022-03-02T11:55:02.000Z (almost 3 years ago)
- Default Branch: main
- Last Pushed: 2024-01-03T17:14:56.000Z (about 1 year ago)
- Last Synced: 2024-08-01T12:24:02.834Z (6 months ago)
- Topics: iot, monitor
- Language: Python
- Homepage:
- Size: 44.9 KB
- Stars: 36
- Watchers: 3
- Forks: 4
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
Awesome Lists containing this project
README
Lunar Sensor
Create a custom Ambient Light Sensor on any device
---
This is a server that implements a custom Ambient Light Sensor for adapting monitor brightness with the [Lunar macOS app](https://lunar.fyi/).
### Requirements
* Python 3.6+
### Running the server
```sh
# Installs dependencies and runs the server
make# Runs the server without installing dependencies
make run# If IPv6 is not available use HOST
make run HOST=0.0.0.0# Listen on another port using the PORT variable
make run PORT=8080
```---
### Implementing light sensor reading
The file `lunarsensor.py` contains a server that reads [lux](https://en.wikipedia.org/wiki/Lux) values using the [`read_lux()`](lunarsensor.py#L53-L57) function at the bottom of the file.
Your actual sensor reading logic should be written in that function.
#### Testing the server
* Check if one-shot lux reading works
```sh
❯ curl lunarsensor.local/sensor/ambient_light{"id":"sensor-ambient_light", "state":"0 lx", "value":0.000000}
```* Check if the EventSource is sending lux values every 2 seconds
```sh
❯ curl -N lunarsensor.local/eventsevent: state
data: {"id": "sensor-ambient_light", "state": "400.0 lx", "value": 400.0}event: state
data: {"id": "sensor-ambient_light", "state": "400.0 lx", "value": 400.0}event: state
data: {"id": "sensor-ambient_light", "state": "400.0 lx", "value": 400.0}
```---
### Implementation examples
#### 1. [HomeAssistant addon](homeassistant_addon)
An easily installable addon that runs the server on port 8899 and polls a sensor entity for lux values.
[![Open your Home Assistant instance and show the Supervisor add-on store.](https://my.home-assistant.io/badges/supervisor_store.svg)](https://my.home-assistant.io/redirect/supervisor_store/)
![adding the lunarsensor repo to HomeAssistant addons](https://files.lunar.fyi/ha-addon-lunar-repo-adding.png)
#### 2. Reading from a [BH1750](https://learn.adafruit.com/adafruit-bh1750-ambient-light-sensor) I²C sensor
```sh
pip3 install adafruit-circuitpython-bh1750
``````python
# Do the sensor reading logic belowimport board
import adafruit_bh1750i2c = board.I2C()
sensor = adafruit_bh1750.BH1750(i2c)def dynamic_adjust_resolution(lux):
if lux > 300:
sensor.resolution = adafruit_bh1750.Resolution.LOW
elif lux > 20:
sensor.resolution = adafruit_bh1750.Resolution.MEDIUM
else:
sensor.resolution = adafruit_bh1750.Resolution.HIGHasync def read_lux():
lux = sensor.lux
dynamic_adjust_resolution(lux)return lux
```#### 3. Reading from a [VEML7700](https://learn.adafruit.com/adafruit-veml7700) I²C sensor
```sh
pip3 install adafruit-circuitpython-veml7700
``````python
# Do the sensor reading logic belowimport board
import adafruit_veml7700i2c = board.I2C()
sensor = adafruit_veml7700.VEML7700(i2c)def dynamic_adjust_resolution(lux):
if lux > 300:
sensor.light_integration_time = adafruit_veml7700.ALS_25MS
sensor.light_gain = adafruit_veml7700.ALS_GAIN_1_8
elif lux > 100:
sensor.light_integration_time = adafruit_veml7700.ALS_50MS
sensor.light_gain = adafruit_veml7700.ALS_GAIN_1_4
elif lux > 20:
sensor.light_integration_time = adafruit_veml7700.ALS_100MS
sensor.light_gain = adafruit_veml7700.ALS_GAIN_1
elif lux > 10:
sensor.light_integration_time = adafruit_veml7700.ALS_200MS
sensor.light_gain = adafruit_veml7700.ALS_GAIN_1
else:
sensor.light_integration_time = adafruit_veml7700.ALS_400MS
sensor.light_gain = adafruit_veml7700.ALS_GAIN_2async def read_lux():
lux = sensor.lux
dynamic_adjust_resolution(lux)return lux
```#### 4. Reading from a [HomeAssistant](https://developers.home-assistant.io/docs/api/rest/) lux sensor
```python
# Do the sensor reading logic belowHOME_ASSISTANT_URL = "http://homeassistant.local:8123" # Replace with your HomeAssistant server URL
TOKEN = "your.jwt.token" # Replace with your long-lived HomeAssistant API token
SENSOR_ENTITY_ID = "sensor.living_room_ambient_light" # Replace with your sensor entity idasync def read_lux():
async with CLIENT.get(f"{HOME_ASSISTANT_URL}/api/states/{SENSOR_ENTITY_ID}", headers={"Authorization": f"Bearer {TOKEN}"}) as response:
sensor = await response.json()
if not json:
return Nonereturn float(sensor["state"])
```#### 5. Reading from a [Phillips Hue API](https://developers.meethue.com/develop/get-started-2/) motion sensor
```python
import math# Do the sensor reading logic below
HUE_API_URL = os.getenv("HUE_API_URL") # set env variable to: http:///api/
HUE_SENSOR_ID = os.getenv("HUE_SENSOR_ID") # send GET request to $HUE_API_URL/sensors and search for "Hue ambient light sensor"async def read_lux():
async with CLIENT.get(f"{HUE_API_URL}/sensors/{HUE_SENSOR_ID}") as response:
sensor = await response.json()
if not json:
return None
# Converting light level measured by sensor: 10000*log10(lux)+1
lightlevel = sensor['state']['lightlevel']
lux = lightlevel - 1
lux = lux / 10000
lux = math.pow(10, lux)return float(lux)
```### Running in Docker
Example for starting on `localhost:8080`
```shell
docker build -t lunarsensor .
docker run -p 127.0.0.1:8080:80 -d lunarsensor
```
---### Pointing Lunar to the sensor server
Lunar expects to find the sensor at the `lunarsensor.local` address by default.
This can be changed using the `defaults` command on the Mac where Lunar is running.
There are three settings that affect where Lunar looks for the sensor:
- `sensorHostname` set by default to `lunarsensor.local`
- `sensorPort` set by default to `80`
- `sensorPathPrefix` set by default to `/`For example, if you would like to have Lunar listen for sensor events at `homeassistant.local:8123/lunar/events` you would run the following commands:
```sh
defaults write fyi.lunar.Lunar sensorHostname homeassistant.local
defaults write fyi.lunar.Lunar sensorPort 8123
defaults write fyi.lunar.Lunar sensorPathPrefix /lunar
```