mirror of
https://github.com/mjg59/python-broadlink.git
synced 2024-11-10 18:00:12 +01:00
634370d878
* Add ability to RF scan a specific frequency This adds an optional parameter to find_rf_packet(), along with a corresponding --rflearn parameter (defaulting to 433.92) to broadlink_cli that specifies the frequency to tune to, rather than requiring the frequency be found via sweeping. This is almost mandatory for certain types of remotes that do not repeat their signals while the button is held, and saves significant time when the frequency is known in advance or when many buttons are to be captured in a row. Additionally: - A get_frequency() API is added to return the current frequency the device is tuned to. - A check_frequency_ex() API is added to perform functions of both check_frequency() and get_frequency() in a single call. - broadlink_cli --rfscanlearn will now report the current frequency at 1 second intervals during sweeping, and will report the frequency it finally locks on to. * Clean up remote.py * Clean up broadlink_cli * Update conditional * Fix message --------- Co-authored-by: Felipe Martins Diel <41558831+felipediel@users.noreply.github.com>
133 lines
3.6 KiB
Python
133 lines
3.6 KiB
Python
"""Support for universal remotes."""
|
|
import struct
|
|
import typing as t
|
|
|
|
from . import exceptions as e
|
|
from .device import Device
|
|
|
|
|
|
class rmmini(Device):
|
|
"""Controls a Broadlink RM mini 3."""
|
|
|
|
TYPE = "RMMINI"
|
|
|
|
def _send(self, command: int, data: bytes = b"") -> bytes:
|
|
"""Send a packet to the device."""
|
|
packet = struct.pack("<I", command) + data
|
|
resp = self.send_packet(0x6A, packet)
|
|
e.check_error(resp[0x22:0x24])
|
|
payload = self.decrypt(resp[0x38:])
|
|
return payload[0x4:]
|
|
|
|
def update(self) -> None:
|
|
"""Update device name and lock status."""
|
|
resp = self._send(0x1)
|
|
self.name = resp[0x48:].split(b"\x00")[0].decode()
|
|
self.is_locked = bool(resp[0x87])
|
|
|
|
def send_data(self, data: bytes) -> None:
|
|
"""Send a code to the device."""
|
|
self._send(0x2, data)
|
|
|
|
def enter_learning(self) -> None:
|
|
"""Enter infrared learning mode."""
|
|
self._send(0x3)
|
|
|
|
def check_data(self) -> bytes:
|
|
"""Return the last captured code."""
|
|
return self._send(0x4)
|
|
|
|
|
|
class rmpro(rmmini):
|
|
"""Controls a Broadlink RM pro."""
|
|
|
|
TYPE = "RMPRO"
|
|
|
|
def sweep_frequency(self) -> None:
|
|
"""Sweep frequency."""
|
|
self._send(0x19)
|
|
|
|
def check_frequency(self) -> t.Tuple[bool, float]:
|
|
"""Return True if the frequency was identified successfully."""
|
|
resp = self._send(0x1A)
|
|
is_found = bool(resp[0])
|
|
frequency = struct.unpack("<I", resp[1:5])[0] / 1000.0
|
|
return is_found, frequency
|
|
|
|
def find_rf_packet(self, frequency: float = None) -> None:
|
|
"""Enter radiofrequency learning mode."""
|
|
payload = bytearray()
|
|
if frequency:
|
|
payload += struct.pack("<I", int(frequency * 1000))
|
|
self._send(0x1B, payload)
|
|
|
|
def cancel_sweep_frequency(self) -> None:
|
|
"""Cancel sweep frequency."""
|
|
self._send(0x1E)
|
|
|
|
def check_sensors(self) -> dict:
|
|
"""Return the state of the sensors."""
|
|
resp = self._send(0x1)
|
|
temp = struct.unpack("<bb", resp[:0x2])
|
|
return {"temperature": temp[0x0] + temp[0x1] / 10.0}
|
|
|
|
def check_temperature(self) -> float:
|
|
"""Return the temperature."""
|
|
return self.check_sensors()["temperature"]
|
|
|
|
|
|
class rmminib(rmmini):
|
|
"""Controls a Broadlink RM mini 3 (new firmware)."""
|
|
|
|
TYPE = "RMMINIB"
|
|
|
|
def _send(self, command: int, data: bytes = b"") -> bytes:
|
|
"""Send a packet to the device."""
|
|
packet = struct.pack("<HI", len(data) + 4, command) + data
|
|
resp = self.send_packet(0x6A, packet)
|
|
e.check_error(resp[0x22:0x24])
|
|
payload = self.decrypt(resp[0x38:])
|
|
p_len = struct.unpack("<H", payload[:0x2])[0]
|
|
return payload[0x6 : p_len + 2]
|
|
|
|
|
|
class rm4mini(rmminib):
|
|
"""Controls a Broadlink RM4 mini."""
|
|
|
|
TYPE = "RM4MINI"
|
|
|
|
def check_sensors(self) -> dict:
|
|
"""Return the state of the sensors."""
|
|
resp = self._send(0x24)
|
|
temp = struct.unpack("<bb", resp[:0x2])
|
|
return {
|
|
"temperature": temp[0x0] + temp[0x1] / 100.0,
|
|
"humidity": resp[0x2] + resp[0x3] / 100.0,
|
|
}
|
|
|
|
def check_temperature(self) -> float:
|
|
"""Return the temperature."""
|
|
return self.check_sensors()["temperature"]
|
|
|
|
def check_humidity(self) -> float:
|
|
"""Return the humidity."""
|
|
return self.check_sensors()["humidity"]
|
|
|
|
|
|
class rm4pro(rm4mini, rmpro):
|
|
"""Controls a Broadlink RM4 pro."""
|
|
|
|
TYPE = "RM4PRO"
|
|
|
|
|
|
class rm(rmpro):
|
|
"""For backwards compatibility."""
|
|
|
|
TYPE = "RM2"
|
|
|
|
|
|
class rm4(rm4pro):
|
|
"""For backwards compatibility."""
|
|
|
|
TYPE = "RM4"
|