Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Latch sensor missed state changes #3

Open
jantman opened this issue Jul 31, 2023 · 0 comments
Open

Latch sensor missed state changes #3

jantman opened this issue Jul 31, 2023 · 0 comments

Comments

@jantman
Copy link
Contributor

jantman commented Jul 31, 2023

On the side door, I've noticed a number of times where the latch sensor detection logic misses state changes. I originally wasn't sure if this was a hardware or software issue, but I tested by running a second script that just reads the latch sensor pin in a tight loop [^1] while flipping the latch sensor by hand and watching the output from both this script and rfidclient. Sure enough, on a number of occasions, I noticed state changes that rfidclient missed, even when making sure to toggle the sensor at intervals longer than the current 100ms debounce time.

I'm pretty sure that this is being caused by the current ... sub-optimal... threading when a latch sensor is present, i.e. we're already running the wiegand-reading binary and reading its STDOUT and then using new scans to notify the scan_worker daemon thread, but when I added the latch sensor, I just put that in its own daemon thread. That's using .when_pressed and .when_released callbacks on gpiozero.Button(), but RPi doesn't support (?) hardware interrupts for GPIO; under the hood, when_pressed and when_released are just using their own worker thread to poll for state changes. The result of all this is that it really doesn't play well with Python's multithreading approach and the GIL, and especially when doing network IO for the fob scans, it feels likely that we're losing short state changes from the latch sensor.

The simple solution here, which I'm starting work on soon, is to just run a separate daemon for reading latch sensor state and exposing that to Prometheus. That should solve the two immediate problems, (1) ensuring we have accurate data on when the latch is opened and closed and what state it's currently in, and (2) giving us valid data to compare against to identify when rfidclient is missing events.

That being said, with the addition of the latch sensor support, the right answer here is probably to overhaul rfidclient and move to multiprocessing, or something else that's more suited to reacting to two external inputs (wiegand reader, and latch sensor) without losing any input or state changes (even if the state changes are short in duration, as the latch sensor can be).

[1]: Test script:

#!/usr/bin/env python3

import logging
import os
from dotenv import load_dotenv

AUTH_TIMEOUT = 2
DOOR_OPEN_SECONDS = 10

logging.basicConfig(
    level=logging.DEBUG,
    format='%(asctime)s %(levelname)s:%(name)s:%(message)s'
)

load_dotenv(dotenv_path="/etc/default/rfidclient")

CONTACT_PIN: int = int(os.getenv("CONTACT_PIN", "0"))


import gpiozero
door_contact = gpiozero.Button(
    CONTACT_PIN, pull_up=True, bounce_time=0.1
)
logging.debug('Reading door contact on pin %s', CONTACT_PIN)

contact_state = door_contact.is_pressed
logging.info('Contact state is: %s', contact_state)
while True:
    if (new_state := door_contact.is_pressed) != contact_state:
        logging.info('Contact state changed to %s', new_state)
        contact_state = new_state
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant