power: add RF transmitter support
Signed-off: Daniel Bauer <github@dbauer.me>
This commit is contained in:
parent
86764657cf
commit
c3f1b290f8
|
@ -190,7 +190,7 @@ gcode:
|
|||
```
|
||||
|
||||
## `[power]`
|
||||
Enables device power control. Currently GPIO (relays), TPLink Smartplug,
|
||||
Enables device power control. Currently GPIO (relays), RF transmitter, TPLink Smartplug,
|
||||
and Tasmota (via http) devices, HomeAssistant switch are supported.
|
||||
|
||||
```ini
|
||||
|
@ -198,7 +198,7 @@ and Tasmota (via http) devices, HomeAssistant switch are supported.
|
|||
|
||||
[power device_name]
|
||||
type: gpio
|
||||
# The type of device. Can be either gpio, tplink_smartplug, tasmota
|
||||
# The type of device. Can be either gpio, rf, tplink_smartplug, tasmota
|
||||
# shelly, homeseer, homeassistant, or loxonev1.
|
||||
# This parameter must be provided.
|
||||
off_when_shutdown: False
|
||||
|
@ -217,7 +217,7 @@ restart_delay: 1.
|
|||
# If "restart_klipper_when_powered" is set, this option specifies the amount
|
||||
# of time (in seconds) to delay the restart. Default is 1 second.
|
||||
pin: gpiochip0/gpio26
|
||||
# The pin to use for GPIO devices. The chip is optional, if left out
|
||||
# The pin to use for GPIO and RF devices. The chip is optional, if left out
|
||||
# then the module will default to gpiochip0. If one wishes to invert
|
||||
# the signal, a "!" may be prefixed to the pin. Valid examples:
|
||||
# gpiochip0/gpio26
|
||||
|
@ -297,6 +297,12 @@ output_id:
|
|||
# The output_id is the name of a programmed output, virtual input or virtual
|
||||
# output in the loxone config his output_id (name) may only be used once in
|
||||
# the loxone config
|
||||
on_code:
|
||||
off_code:
|
||||
# The above options are used for "rf" devices. The
|
||||
# codes should be valid binary codes that are send via the RF transmitter.
|
||||
# For example: 1011.
|
||||
|
||||
```
|
||||
Below are some potential examples:
|
||||
```ini
|
||||
|
@ -559,4 +565,4 @@ default_qos: 0
|
|||
api_qos:
|
||||
# The QOS level to use for the API topics. If not provided, the
|
||||
# value specified by "default_qos" will be used.
|
||||
```
|
||||
```
|
||||
|
|
|
@ -12,6 +12,7 @@ import json
|
|||
import struct
|
||||
import socket
|
||||
import asyncio
|
||||
import time
|
||||
from tornado.iostream import IOStream
|
||||
from tornado.httpclient import AsyncHTTPClient
|
||||
from tornado.escape import json_decode
|
||||
|
@ -68,7 +69,8 @@ class PrinterPower:
|
|||
"shelly": Shelly,
|
||||
"homeseer": HomeSeer,
|
||||
"homeassistant": HomeAssistant,
|
||||
"loxonev1": Loxonev1
|
||||
"loxonev1": Loxonev1,
|
||||
"rf": RFDevice
|
||||
}
|
||||
try:
|
||||
for section in prefix_sections:
|
||||
|
@ -79,7 +81,7 @@ class PrinterPower:
|
|||
if dev_class is None:
|
||||
raise config.error(f"Unsupported Device Type: {dev_type}")
|
||||
dev = dev_class(cfg)
|
||||
if isinstance(dev, GpioDevice):
|
||||
if isinstance(dev, GpioDevice) or isinstance(dev, RFDevice):
|
||||
if not HAS_GPIOD:
|
||||
continue
|
||||
dev.configure_line(cfg, self.chip_factory)
|
||||
|
@ -470,6 +472,53 @@ class GpioDevice(PowerDevice):
|
|||
def close(self) -> None:
|
||||
self.line.release()
|
||||
|
||||
class RFDevice(GpioDevice):
|
||||
|
||||
# Protocol definition
|
||||
# [1, 3] means HIGH is set for 1x pulse_len and LOW for 3x pulse_len
|
||||
ZERO_BIT = [1, 3] # zero bit
|
||||
ONE_BIT = [3, 1] # one bit
|
||||
SYNC_BIT = [1, 31] # sync between
|
||||
PULSE_LEN = 0.00035 # length of a single pulse
|
||||
RETRIES = 10 # send the code this many times
|
||||
|
||||
def __init__(self, config: ConfigHelper):
|
||||
super().__init__(config)
|
||||
self.on = config.get("on_code").zfill(24)
|
||||
self.off = config.get("off_code").zfill(24)
|
||||
|
||||
def initialize(self) -> None:
|
||||
self.set_power("on" if self.initial_state else "off")
|
||||
|
||||
def _transmit_digit(self, waveform) -> None:
|
||||
self.line.set_value(1)
|
||||
time.sleep(waveform[0]*RFDevice.PULSE_LEN)
|
||||
self.line.set_value(0)
|
||||
time.sleep(waveform[1]*RFDevice.PULSE_LEN)
|
||||
|
||||
def _transmit_code(self, code) -> None:
|
||||
for _ in range(RFDevice.RETRIES):
|
||||
for i in code:
|
||||
if i == "1":
|
||||
self._transmit_digit(RFDevice.ONE_BIT)
|
||||
elif i == "0":
|
||||
self._transmit_digit(RFDevice.ZERO_BIT)
|
||||
self._transmit_digit(RFDevice.SYNC_BIT)
|
||||
|
||||
def set_power(self, state) -> None:
|
||||
try:
|
||||
if state == "on":
|
||||
code = self.on
|
||||
else:
|
||||
code = self.off
|
||||
self._transmit_code(code)
|
||||
except Exception:
|
||||
self.state = "error"
|
||||
msg = f"Error Toggling Device Power: {self.name}"
|
||||
logging.exception(msg)
|
||||
raise self.server.error(msg) from None
|
||||
self.state = state
|
||||
|
||||
|
||||
# This implementation based off the work tplink_smartplug
|
||||
# script by Lubomir Stroetmann available at:
|
||||
|
|
Loading…
Reference in New Issue