diff --git a/dream_cheeky/__init__.py b/dream_cheeky/__init__.py new file mode 100644 index 0000000..5f4c139 --- /dev/null +++ b/dream_cheeky/__init__.py @@ -0,0 +1,78 @@ +"""Simple interface for the Dream Cheeky Big Red Button.""" + + +import os +import time + + +def _run_callbacks(callbacks): + """Runs all the callbacks. + + :param callbacks: List of callable functions. + """ + for callback in callbacks: + callback() + + +class BigRedButton(object): + """Encapsulates the big red button.""" + + POLL_SIGNAL = b"\x08\x00\x00\x00\x00\x00\x00\x02" + LID_CLOSED = b"\x15\x00\x00\x00\x00\x00\x00\x00" + BUTTON_DOWN = b"\x16\x00\x00\x00\x00\x00\x00\x00" + LID_OPEN = b"\x17\x00\x00\x00\x00\x00\x00\x00" + + def __init__(self, device_fd): + """Initializes the BigRedButton. + + :param device_fd: File descriptor for the device + """ + self.device_fd = device_fd + self._prior = self.LID_CLOSED + self._button_press_callbacks = [] + self._lid_open_callbacks = [] + self._lid_close_callbacks = [] + + def on_button_press(self, callback): + """Registers callback for button press event. + + :param callback: Callback function to run on button press + """ + self._button_press_callbacks.append(callback) + + def on_lid_open(self, callback): + """Registers callback for lid open event. + + :param callback: Callback function to run on lid open + """ + self._lid_open_callbacks.append(callback) + + def on_lid_close(self, callback): + """Registers callback for lid close event. + + :param callback: Callback function to run on lid close + """ + self._lid_close_callbacks.append(callback) + + def _step(self): + """Executes one step of the event loop.""" + bytes_written = os.write(self.device_fd, self.POLL_SIGNAL) + if not bytes_written: + raise RuntimeError("Could not write to device file.") + bytes_read = os.read(self.device_fd, 8) + if not bytes_read: + raise RuntimeError("Could not read from device file.") + if bytes_read == self.LID_CLOSED and self._prior != self.LID_CLOSED: + _run_callbacks(self._lid_close_callbacks) + if bytes_read == self.BUTTON_DOWN and self._prior != self.BUTTON_DOWN: + _run_callbacks(self._button_press_callbacks) + if bytes_read == self.LID_OPEN and self._prior == self.LID_CLOSED: + _run_callbacks(self._lid_open_callbacks) + if bytes_read != self.POLL_SIGNAL: + self._prior = bytes_read + + def run(self): + """Executes the main event loop for the big red button.""" + while True: + self._step() + time.sleep(0.01) diff --git a/examples/print_on_button_press.py b/examples/print_on_button_press.py new file mode 100755 index 0000000..174e813 --- /dev/null +++ b/examples/print_on_button_press.py @@ -0,0 +1,23 @@ +#!/usr/bin/env python +"""Sample script for python-dream-cheeky.""" + +import os + +from dream_cheeky import BigRedButton + + +def handle_button_press(): + """Handles a button press.""" + print("Button pressed!") + + +def main(): + """Main function for the sync button.""" + device_file = os.open("/dev/big_red_button", os.O_RDWR) + button = BigRedButton(device_file) + button.on_button_press(handle_button_press) + button.run() + + +if __name__ == '__main__': + main() diff --git a/setup.py b/setup.py new file mode 100644 index 0000000..8666217 --- /dev/null +++ b/setup.py @@ -0,0 +1,18 @@ +from distutils.core import setup + +description = "Event-driven Python library for interacting with the Dream Cheeky big red button." + +setup( + name='python-dream-cheeky', + version='0.1.0', + author='Ian Adam Naval', + author_email='ianonavy@gmail.com', + packages=['dream_cheeky'], + scripts=[], + url='https://git.ianonavy.com/ianonavy/python-dream-cheeky/', + license='MIT', + description=description, + long_description=description, + install_requires=[], + +)