1
0
mirror of https://github.com/mjg59/python-broadlink.git synced 2024-11-21 22:51:41 +01:00

Add ability to RF scan a specific frequency (#613)

* 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>
This commit is contained in:
Ian Munsie 2024-04-10 04:40:00 +10:00 committed by GitHub
parent abcc9aaeed
commit 634370d878
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 36 additions and 24 deletions

View File

@ -1,5 +1,6 @@
"""Support for universal remotes.""" """Support for universal remotes."""
import struct import struct
import typing as t
from . import exceptions as e from . import exceptions as e
from .device import Device from .device import Device
@ -46,14 +47,19 @@ class rmpro(rmmini):
"""Sweep frequency.""" """Sweep frequency."""
self._send(0x19) self._send(0x19)
def check_frequency(self) -> bool: def check_frequency(self) -> t.Tuple[bool, float]:
"""Return True if the frequency was identified successfully.""" """Return True if the frequency was identified successfully."""
resp = self._send(0x1A) resp = self._send(0x1A)
return resp[0] == 1 is_found = bool(resp[0])
frequency = struct.unpack("<I", resp[1:5])[0] / 1000.0
return is_found, frequency
def find_rf_packet(self) -> None: def find_rf_packet(self, frequency: float = None) -> None:
"""Enter radiofrequency learning mode.""" """Enter radiofrequency learning mode."""
self._send(0x1B) payload = bytearray()
if frequency:
payload += struct.pack("<I", int(frequency * 1000))
self._send(0x1B, payload)
def cancel_sweep_frequency(self) -> None: def cancel_sweep_frequency(self) -> None:
"""Cancel sweep frequency.""" """Cancel sweep frequency."""

View File

@ -83,7 +83,8 @@ parser.add_argument("--switch", action="store_true", help="switch state from on
parser.add_argument("--send", action="store_true", help="send command") parser.add_argument("--send", action="store_true", help="send command")
parser.add_argument("--sensors", action="store_true", help="check all sensors") parser.add_argument("--sensors", action="store_true", help="check all sensors")
parser.add_argument("--learn", action="store_true", help="learn command") parser.add_argument("--learn", action="store_true", help="learn command")
parser.add_argument("--rfscanlearn", action="store_true", help="rf scan learning") parser.add_argument("--rflearn", action="store_true", help="rf scan learning")
parser.add_argument("--frequency", type=float, help="specify radiofrequency for learning")
parser.add_argument("--learnfile", help="save learned command to a specified file") parser.add_argument("--learnfile", help="save learned command to a specified file")
parser.add_argument("--durations", action="store_true", parser.add_argument("--durations", action="store_true",
help="use durations in micro seconds instead of the Broadlink format") help="use durations in micro seconds instead of the Broadlink format")
@ -127,7 +128,7 @@ if args.send:
data = durations_to_broadlink(parse_durations(' '.join(args.data))) \ data = durations_to_broadlink(parse_durations(' '.join(args.data))) \
if args.durations else bytearray.fromhex(''.join(args.data)) if args.durations else bytearray.fromhex(''.join(args.data))
dev.send_data(data) dev.send_data(data)
if args.learn or (args.learnfile and not args.rfscanlearn): if args.learn or (args.learnfile and not args.rflearn):
dev.enter_learning() dev.enter_learning()
print("Learning...") print("Learning...")
start = time.time() start = time.time()
@ -195,28 +196,33 @@ if args.switch:
else: else:
dev.set_power(True) dev.set_power(True)
print('* Switch to ON *') print('* Switch to ON *')
if args.rfscanlearn: if args.rflearn:
dev.sweep_frequency() if args.frequency:
print("Learning RF Frequency, press and hold the button to learn...") frequency = args.frequency
print("Press the button you want to learn, a short press...")
start = time.time()
while time.time() - start < TIMEOUT:
time.sleep(1)
if dev.check_frequency():
break
else: else:
print("RF Frequency not found") dev.sweep_frequency()
dev.cancel_sweep_frequency() print("Detecting radiofrequency, press and hold the button to learn...")
exit(1)
print("Found RF Frequency - 1 of 2!") start = time.time()
print("You can now let go of the button") while time.time() - start < TIMEOUT:
time.sleep(1)
locked, frequency = dev.check_frequency()
if locked:
break
else:
print("Radiofrequency not found")
dev.cancel_sweep_frequency()
exit(1)
input("Press enter to continue...") print("Radiofrequency detected: {}MHz".format(frequency))
print("You can now let go of the button")
print("To complete learning, single press the button you want to learn") input("Press enter to continue...")
dev.find_rf_packet() print("Press the button again, now a short press.")
dev.find_rf_packet(frequency)
start = time.time() start = time.time()
while time.time() - start < TIMEOUT: while time.time() - start < TIMEOUT:
@ -231,7 +237,7 @@ if args.rfscanlearn:
print("No data received...") print("No data received...")
exit(1) exit(1)
print("Found RF Frequency - 2 of 2!") print("Packet found!")
learned = format_durations(to_microseconds(bytearray(data))) \ learned = format_durations(to_microseconds(bytearray(data))) \
if args.durations \ if args.durations \
else ''.join(format(x, '02x') for x in bytearray(data)) else ''.join(format(x, '02x') for x in bytearray(data))