diff --git a/octoprint_octorelay/driver.py b/octoprint_octorelay/driver.py index e6b02d44..5c2a5b3c 100755 --- a/octoprint_octorelay/driver.py +++ b/octoprint_octorelay/driver.py @@ -10,14 +10,23 @@ class Driver(): def __init__(self, pin: int, inverted: bool, pin_factory=None): self.pin = pin # GPIO pin - self.inverted = inverted # marks the relay as normally closed - self.handle = LED(pin, pin_factory=pin_factory, initial_value=inverted) + self.handle = LED(pin, pin_factory=pin_factory, active_high=not inverted) # release immediately, avoid lock, allow physical buttons to operate same relays: self.handle.pin_factory.release_pins(self.handle, self.pin) def __repr__(self) -> str: return f"{type(self).__name__}(pin={self.pin},inverted={self.inverted},closed={self.is_closed()})" + @property + def inverted(self): + """Returns true if the relay is normally closed.""" + return not self.handle.active_high + + @inverted.setter + def inverted(self, value): + """Changing this will invert is_closed value without inverting the pin""" + self.handle.active_high = not value + def close(self): """Activates the current flow through the relay.""" self.toggle(True) @@ -28,7 +37,7 @@ def open(self): def is_closed(self) -> bool: """Returns the logical state of the relay.""" - return xor(self.inverted, self.handle.is_lit) + return self.handle.is_lit def toggle(self, desired_state: Optional[bool] = None) -> bool: """ @@ -38,7 +47,7 @@ def toggle(self, desired_state: Optional[bool] = None) -> bool: """ if desired_state is None: desired_state = not self.is_closed() - (self.handle.on if xor(self.inverted, desired_state) else self.handle.off)() + (self.handle.on if desired_state else self.handle.off)() return desired_state @classmethod diff --git a/tests/test_driver.py b/tests/test_driver.py index b2aeeb9e..142fe4e2 100644 --- a/tests/test_driver.py +++ b/tests/test_driver.py @@ -27,7 +27,7 @@ def test_serialization(self): def test_close(self): cases = [ { "relay": Driver(18, False, MockFactory()), "expected_pin_state": True }, - { "relay": Driver(18, True, MockFactory()), "expected_pin_state": False } + { "relay": Driver(18, True, MockFactory()), "expected_pin_state": True } ] for case in cases: case["relay"].close() @@ -36,7 +36,7 @@ def test_close(self): def test_open(self): cases = [ { "relay": Driver(18, False, MockFactory()), "expected_pin_state": False }, - { "relay": Driver(18, True, MockFactory()), "expected_pin_state": True } + { "relay": Driver(18, True, MockFactory()), "expected_pin_state": False } ] for case in cases: case["relay"].open() @@ -46,8 +46,8 @@ def test_is_closed(self): cases = [ { "mocked_state": 1, "inverted": False, "expected_relay_state": True }, { "mocked_state": 0, "inverted": False, "expected_relay_state": False }, - { "mocked_state": 1, "inverted": True, "expected_relay_state": False }, - { "mocked_state": 0, "inverted": True, "expected_relay_state": True }, + { "mocked_state": 1, "inverted": True, "expected_relay_state": True }, + { "mocked_state": 0, "inverted": True, "expected_relay_state": False }, ] for case in cases: relay = Driver(18, case["inverted"], MockFactory()) @@ -58,8 +58,8 @@ def test_toggle__no_argument(self): cases = [ { "mocked_state": 1, "inverted": False, "expected_pin_state": False, "expected_relay_state": False }, { "mocked_state": 0, "inverted": False, "expected_pin_state": True, "expected_relay_state": True }, - { "mocked_state": 1, "inverted": True, "expected_pin_state": False, "expected_relay_state": True }, - { "mocked_state": 0, "inverted": True, "expected_pin_state": True, "expected_relay_state": False }, + { "mocked_state": 1, "inverted": True, "expected_pin_state": False, "expected_relay_state": False }, + { "mocked_state": 0, "inverted": True, "expected_pin_state": True, "expected_relay_state": True }, ] for case in cases: relay = Driver(18, case["inverted"], MockFactory()) @@ -75,7 +75,7 @@ def test_ensure(self): self.assertFalse(relay1.inverted) # Test retrieving the existing relay with the same pin and inversion - relay2 = Driver.ensure(17, True, MockFactory()) + relay2 = Driver.ensure(17, False, MockFactory()) self.assertIs(relay1, relay2) self.assertEqual(len(Driver.cache), 1) # Should still be 1