This is a server that implements a custom Ambient Light Sensor for adapting monitor brightness with the Lunar macOS app.
- Python 3.6+
- Access to binding port
80
# 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
The file lunarsensor.py
contains a server that reads lux values using the read_lux()
function at the bottom of the file.
Your actual sensor reading logic should be written in that function.
- Check if one-shot lux reading works
❯ 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
❯ curl lunarsensor.local/events
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}
event: state
data: {"id": "sensor-ambient_light", "state": "400.0 lx", "value": 400.0}
Reading from a BH1750 I²C sensor
pip3 install adafruit-circuitpython-bh1750
# Do the sensor reading logic below
import board
import adafruit_bh1750
i2c = 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.HIGH
async def read_lux():
lux = sensor.lux
dynamic_adjust_resolution(lux)
return lux
Reading from a VEML7700 I²C sensor
pip3 install adafruit-circuitpython-veml7700
# Do the sensor reading logic below
import board
import adafruit_veml7700
i2c = 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_2
async def read_lux():
lux = sensor.lux
dynamic_adjust_resolution(lux)
return lux
Reading from a HomeAssistant lux sensor
# Do the sensor reading logic below
HOME_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 id
async 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 None
return float(sensor["state"])
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 tolunarsensor.local
sensorPort
set by default to80
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:
defaults write fyi.lunar.Lunar sensorHostname homeassistant.local
defaults write fyi.lunar.Lunar sensorPort 8123
defaults write fyi.lunar.Lunar sensorPathPrefix /lunar
You can map the hostname to the sensor server IP using the /etc/hosts
file on the Mac device where Lunar is running.
##
# Host Database
#
# localhost is used to configure the loopback interface
# when the system is booting. Do not change this entry.
##
127.0.0.1 localhost
255.255.255.255 broadcasthost
::1 localhost
For example, if you would like to have Lunar listen for sensor events at `homeassistant.local:8123/lunar/events` you would run the follo wing commands:
+ # Added for Lunar sensor server
+ 192.168.0.203 lunarsensor.local