Implemented generic setup file and VL53L3CX Sensor
This commit is contained in:
parent
b85ee8ab25
commit
16ebe4a670
7 changed files with 105 additions and 55 deletions
|
@ -1,12 +1,10 @@
|
||||||
from sensors.people_counter import PeopleCounter
|
from sensors.people_counter import PeopleCounter
|
||||||
from sensors.vl53l1x_sensor import VL53L1XSensor
|
|
||||||
import logging
|
import logging
|
||||||
|
from setup import sensor
|
||||||
|
|
||||||
counter = PeopleCounter(VL53L1XSensor())
|
counter = PeopleCounter(sensor)
|
||||||
peopleCount = 0
|
peopleCount = 0
|
||||||
|
|
||||||
logging.getLogger().setLevel(logging.INFO)
|
|
||||||
|
|
||||||
|
|
||||||
def countChange(change: int) -> None:
|
def countChange(change: int) -> None:
|
||||||
global peopleCount
|
global peopleCount
|
||||||
|
|
|
@ -1,30 +1,26 @@
|
||||||
from sensors import Directions, VL53L1XSensor
|
from sensors import Directions
|
||||||
from time import sleep
|
from time import sleep
|
||||||
|
from setup import sensor
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
|
|
||||||
DELAY_SECONDS = 1
|
DELAY_SECONDS = 1
|
||||||
|
|
||||||
logging.getLogger().setLevel(logging.INFO)
|
|
||||||
|
|
||||||
|
|
||||||
sensor = VL53L1XSensor()
|
|
||||||
sensor.open()
|
sensor.open()
|
||||||
|
|
||||||
try:
|
try:
|
||||||
while True:
|
while True:
|
||||||
sensor.setDirection(Directions.INSIDE)
|
sensor.setDirection(Directions.INSIDE)
|
||||||
distance_inside = sensor.getDistance()
|
distance_inside = sensor.getDistance()
|
||||||
|
|
||||||
sensor.setDirection(Directions.OUTSIDE)
|
sensor.setDirection(Directions.OUTSIDE)
|
||||||
distance_outside = sensor.getDistance()
|
distance_outside = sensor.getDistance()
|
||||||
|
|
||||||
logging.info("----------")
|
logging.info("----------")
|
||||||
logging.info(f"Inside: {distance_inside} cm")
|
logging.info(f"Inside: {distance_inside} cm")
|
||||||
logging.info(f"Outside: {distance_outside} cm")
|
logging.info(f"Outside: {distance_outside} cm")
|
||||||
|
|
||||||
sleep(DELAY_SECONDS)
|
sleep(DELAY_SECONDS)
|
||||||
|
|
||||||
finally:
|
finally:
|
||||||
sensor.close()
|
sensor.close()
|
||||||
|
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
from sensors.vl53l1x_sensor import VL53L1XSensor
|
from sensors.vl53l1x_sensor import VL53L1XSensor
|
||||||
|
from sensors.vl53l3cx_sensor import VL53L3CXSensor
|
||||||
from sensors.people_counter import PeopleCounter
|
from sensors.people_counter import PeopleCounter
|
||||||
from sensors.tof_sensor import Directions
|
from sensors.tof_sensor import Directions
|
||||||
|
|
61
src/sensors/vl53l3cx_sensor.py
Normal file
61
src/sensors/vl53l3cx_sensor.py
Normal file
|
@ -0,0 +1,61 @@
|
||||||
|
from sensors.tof_sensor import Directions, ToFSensor
|
||||||
|
import VL53L1X
|
||||||
|
|
||||||
|
# Reference: https://github.com/pimoroni/vl53l1x-python
|
||||||
|
#
|
||||||
|
# Left, right, top and bottom are relative to the SPAD matrix coordinates,
|
||||||
|
# which will be mirrored in real scene coordinates.
|
||||||
|
# (or even rotated, depending on the VM53L1X element alignment on the board and on the board position)
|
||||||
|
#
|
||||||
|
# ROI in SPAD matrix coords:
|
||||||
|
#
|
||||||
|
# 15 top-left
|
||||||
|
# | X____
|
||||||
|
# | | |
|
||||||
|
# | |____X
|
||||||
|
# | bottom-right
|
||||||
|
# 0__________15
|
||||||
|
#
|
||||||
|
|
||||||
|
|
||||||
|
class VL53L3CXSensor(ToFSensor):
|
||||||
|
def __init__(self) -> None:
|
||||||
|
super().__init__()
|
||||||
|
|
||||||
|
def open(self, ranging_mode: int = 3) -> None:
|
||||||
|
self.sensor = VL53L1X.VL53L1X(i2c_bus=1, i2c_address=0x52)
|
||||||
|
self.sensor.open()
|
||||||
|
self.roi = VL53L1X.VL53L1xUserRoi()
|
||||||
|
|
||||||
|
# Optionally set an explicit timing budget
|
||||||
|
# These values are measurement time in microseconds,
|
||||||
|
# and inter-measurement time in milliseconds.
|
||||||
|
# If you uncomment the line below to set a budget you
|
||||||
|
# should use `tof.start_ranging(0)`
|
||||||
|
# tof.set_timing(66000, 70)
|
||||||
|
self.ranging = ranging_mode
|
||||||
|
# 0 = Unchanged
|
||||||
|
# 1 = Short Range
|
||||||
|
# 2 = Medium Range
|
||||||
|
# 3 = Long Range
|
||||||
|
|
||||||
|
def setDirection(self, direction: Directions) -> None:
|
||||||
|
"""Configure sensor to pick up the distance in a specific direction."""
|
||||||
|
direction_roi = {
|
||||||
|
Directions.INSIDE: VL53L1X.VL53L1xUserRoi(6, 3, 9, 0),
|
||||||
|
Directions.OUTSIDE: VL53L1X.VL53L1xUserRoi(6, 15, 9, 12),
|
||||||
|
}
|
||||||
|
|
||||||
|
self.roi = direction_roi[direction]
|
||||||
|
|
||||||
|
def getDistance(self) -> float:
|
||||||
|
"""Returns new distance in cm."""
|
||||||
|
self.sensor.set_user_roi(self.roi)
|
||||||
|
self.sensor.start_ranging(self.ranging)
|
||||||
|
distance = self.sensor.get_distance()
|
||||||
|
self.sensor.stop_ranging()
|
||||||
|
|
||||||
|
return distance / 10
|
||||||
|
|
||||||
|
def close(self) -> None:
|
||||||
|
self.sensor.close()
|
28
src/setup.py
Normal file
28
src/setup.py
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
from sensors import VL53L1XSensor, VL53L3CXSensor
|
||||||
|
from datetime import time
|
||||||
|
import logging
|
||||||
|
|
||||||
|
LOG_FILE_PATH = "log.txt" # Path for logs
|
||||||
|
logging.getLogger().setLevel(logging.INFO)
|
||||||
|
sensor = VL53L3CXSensor()
|
||||||
|
|
||||||
|
# Should lights already turn on where there is any kind of motion in the sensor
|
||||||
|
ENABLE_MOTION_TRIGGERED_LIGHT = True
|
||||||
|
|
||||||
|
# Should lights change when a certain time in the schedule is reached
|
||||||
|
ENABLE_SCHEDULE_TRIGGERS = (
|
||||||
|
False # Not working correctly at the moment, so turned off by default
|
||||||
|
)
|
||||||
|
|
||||||
|
# Schedule (Key is time after scene should be used. Value is scene name to be used.)
|
||||||
|
# Needs to be sorted chronologically
|
||||||
|
SCHEDULE: dict[time, str] = {}
|
||||||
|
|
||||||
|
# Philips Hue configuration
|
||||||
|
hue_conf = {
|
||||||
|
"bridge_ip": "",
|
||||||
|
"transition_time": 10, # seconds
|
||||||
|
"light_group": "",
|
||||||
|
# If file exists, application is considered 'registered' at the bridge
|
||||||
|
"registered_file": "smart_light_registered.bridge",
|
||||||
|
} # Custom configuration for philips hue
|
|
@ -1,28 +1,15 @@
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
from services.philips_hue import PhilipsHue
|
from services.philips_hue import PhilipsHue
|
||||||
from sensors.people_counter import PeopleCounter
|
from sensors.people_counter import PeopleCounter
|
||||||
from sensors.vl53l1x_sensor import VL53L1XSensor
|
|
||||||
import logging
|
import logging
|
||||||
import json
|
import json
|
||||||
|
from setup import sensor, hue_conf, LOG_FILE_PATH
|
||||||
|
|
||||||
LOG_FILE_PATH = "log.txt" # Path for logs
|
|
||||||
hue_conf = {
|
|
||||||
"bridge_ip": "",
|
|
||||||
"transition_time": 10, # seconds
|
|
||||||
# Light group to control
|
|
||||||
"light_group": "",
|
|
||||||
# If file exists, application is considered 'registered' at the bridge
|
|
||||||
"registered_file": "smart_light_registered.bridge",
|
|
||||||
} # Custom configuration for philips hue
|
|
||||||
|
|
||||||
|
|
||||||
hue: PhilipsHue = PhilipsHue(hue_conf) # Light interface
|
hue: PhilipsHue = PhilipsHue(hue_conf) # Light interface
|
||||||
counter: PeopleCounter = PeopleCounter(VL53L1XSensor()) # Sensor object
|
counter: PeopleCounter = PeopleCounter(sensor) # Sensor object
|
||||||
peopleCount: int = 0 # Global count of people on the inside
|
peopleCount: int = 0 # Global count of people on the inside
|
||||||
|
|
||||||
logging.getLogger().setLevel(logging.INFO)
|
|
||||||
|
|
||||||
|
|
||||||
def change_cb(countChange: int, directionState: dict):
|
def change_cb(countChange: int, directionState: dict):
|
||||||
"""Handles basic logging of event data for later analysis.
|
"""Handles basic logging of event data for later analysis.
|
||||||
|
|
|
@ -1,36 +1,15 @@
|
||||||
from datetime import datetime, time, timedelta
|
from datetime import datetime, time, timedelta
|
||||||
|
from typing import Optional
|
||||||
from services.philips_hue import PhilipsHue
|
from services.philips_hue import PhilipsHue
|
||||||
from sensors import PeopleCounter, Directions, VL53L1XSensor
|
from sensors import PeopleCounter, Directions, VL53L1XSensor
|
||||||
import logging
|
import logging
|
||||||
import json
|
import json
|
||||||
from timeloop import Timeloop
|
from timeloop import Timeloop
|
||||||
|
from setup import sensor, hue_conf, LOG_FILE_PATH, SCHEDULE, ENABLE_SCHEDULE_TRIGGERS
|
||||||
|
|
||||||
# Should lights already turn on where there is any kind of motion in the sensor
|
|
||||||
ENABLE_MOTION_TRIGGERED_LIGHT = True
|
|
||||||
|
|
||||||
# Should lights change when a certain time in the schedule is reached
|
|
||||||
ENABLE_SCHEDULE_TRIGGERS = (
|
|
||||||
False # Not working correctly at the moment, so turned off by default
|
|
||||||
)
|
|
||||||
|
|
||||||
# Schedule (Key is time after scene should be used. Value is scene name to be used.)
|
|
||||||
# Needs to be sorted chronologically
|
|
||||||
SCHEDULE: dict[time, str] = {}
|
|
||||||
|
|
||||||
|
|
||||||
LOG_FILE_PATH = "log.txt" # Path for logs
|
|
||||||
hue_conf = {
|
|
||||||
"bridge_ip": "",
|
|
||||||
"transition_time": 10, # seconds
|
|
||||||
"light_group": "",
|
|
||||||
# If file exists, application is considered 'registered' at the bridge
|
|
||||||
"registered_file": "smart_light_registered.bridge",
|
|
||||||
} # Custom configuration for philips hue
|
|
||||||
|
|
||||||
|
|
||||||
hue: PhilipsHue = PhilipsHue(hue_conf) # Light interface
|
hue: PhilipsHue = PhilipsHue(hue_conf) # Light interface
|
||||||
counter: PeopleCounter = PeopleCounter(VL53L1XSensor()) # Sensor object
|
counter: PeopleCounter = PeopleCounter(sensor) # Sensor object
|
||||||
peopleCount: int = 0 # Global count of people on the inside
|
peopleCount: int = 0 # Global count of people on the inside
|
||||||
motion_triggered_lights = False # Is light on because of any detected motion
|
motion_triggered_lights = False # Is light on because of any detected motion
|
||||||
timeloop: Timeloop = Timeloop() # Used for time triggered schedule
|
timeloop: Timeloop = Timeloop() # Used for time triggered schedule
|
||||||
|
@ -55,7 +34,7 @@ def time_minus_time(time_a: time, time_b: time) -> timedelta:
|
||||||
return dt_a - dt_b
|
return dt_a - dt_b
|
||||||
|
|
||||||
|
|
||||||
def get_scene_for_time(time: time) -> str:
|
def get_scene_for_time(time: time) -> Optional[str]:
|
||||||
"""Determines the correct scene to activate for a given time.
|
"""Determines the correct scene to activate for a given time.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
|
@ -185,7 +164,7 @@ def trigger_change(triggerState: dict):
|
||||||
motion_triggered_lights = target_light_state
|
motion_triggered_lights = target_light_state
|
||||||
|
|
||||||
|
|
||||||
def set_light_scene(target_scene: str) -> bool:
|
def set_light_scene(target_scene: str) -> None:
|
||||||
"""Sets the lights to the given scene, but only, if lights are already on. Does not correct count if lights are in an unexpected state.
|
"""Sets the lights to the given scene, but only, if lights are already on. Does not correct count if lights are in an unexpected state.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
|
|
Loading…
Reference in a new issue