From 168b9015ab37692e1d1164bfc4dd0282f16ab018 Mon Sep 17 00:00:00 2001 From: Ian Munsie Date: Sun, 15 Aug 2021 11:51:53 +1000 Subject: [PATCH 1/5] 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. --- broadlink/remote.py | 22 +++++++++++++++++++--- cli/broadlink_cli | 45 +++++++++++++++++++++++++++------------------ 2 files changed, 46 insertions(+), 21 deletions(-) diff --git a/broadlink/remote.py b/broadlink/remote.py index 017dac47..15a9a199 100644 --- a/broadlink/remote.py +++ b/broadlink/remote.py @@ -51,9 +51,25 @@ def check_frequency(self) -> bool: resp = self._send(0x1A) return resp[0] == 1 - def find_rf_packet(self) -> None: - """Enter radiofrequency learning mode.""" - self._send(0x1B) + def check_frequency_ex(self) -> (bool, float): + """Return (True if the frequency was identified successfully, Current frequency)""" + resp = self._send(0x1A) + return resp[0] == 1, struct.unpack(' float: + """Return frequency device is tuned to in MHz""" + resp = self._send(0x1A) + return struct.unpack(' None: + """Enter radiofrequency learning mode, optionally tuning the device to a specific frequency""" + payload = b'' + if frequency is not None: + payload = struct.pack(' None: """Cancel sweep frequency.""" diff --git a/cli/broadlink_cli b/cli/broadlink_cli index f7a24ade..594baff4 100755 --- a/cli/broadlink_cli +++ b/cli/broadlink_cli @@ -84,6 +84,7 @@ parser.add_argument("--send", action="store_true", help="send command") parser.add_argument("--sensors", action="store_true", help="check all sensors") 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", nargs="?", type=float, const=433.92, metavar="FREQUENCY", help="rf learning on specified FREQUENCY, default: 433.92") parser.add_argument("--learnfile", help="save learned command to a specified file") parser.add_argument("--durations", action="store_true", 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))) \ if args.durations else bytearray.fromhex(''.join(args.data)) dev.send_data(data) -if args.learn or (args.learnfile and not args.rfscanlearn): +if args.learn or (args.learnfile and not args.rfscanlearn and not args.rflearn): dev.enter_learning() print("Learning...") start = time.time() @@ -195,29 +196,36 @@ if args.switch: else: dev.set_power(True) print('* Switch to ON *') -if args.rfscanlearn: +if args.rfscanlearn or args.rflearn: dev.sweep_frequency() - print("Learning RF Frequency, press and hold the button to learn...") + if args.rfscanlearn: + print("Learning RF Frequency, press and hold the button to learn...") + + start = time.time() + while time.time() - start < TIMEOUT: + time.sleep(1) + locked, frequency = dev.check_frequency_ex() + if locked: + break + print("Sweeping {}MHz...".format(frequency)) + else: + print("RF Frequency not found") + dev.cancel_sweep_frequency() + exit(1) + frequency = dev.get_frequency() - start = time.time() - while time.time() - start < TIMEOUT: - time.sleep(1) - if dev.check_frequency(): - break - else: - print("RF Frequency not found") - dev.cancel_sweep_frequency() - exit(1) + print("Found RF Frequency {}MHz - 1 of 2!".format(frequency)) + print("You can now let go of the button") - print("Found RF Frequency - 1 of 2!") - print("You can now let go of the button") + input("Press enter to continue...") - input("Press enter to continue...") + dev.find_rf_packet() + else: + dev.find_rf_packet(args.rflearn) + print("Device tuned to {}MHz".format(dev.get_frequency())) print("To complete learning, single press the button you want to learn") - dev.find_rf_packet() - start = time.time() while time.time() - start < TIMEOUT: time.sleep(1) @@ -231,7 +239,8 @@ if args.rfscanlearn: print("No data received...") exit(1) - print("Found RF Frequency - 2 of 2!") + if args.rfscanlearn: + print("Found RF Frequency - 2 of 2!") learned = format_durations(to_microseconds(bytearray(data))) \ if args.durations \ else ''.join(format(x, '02x') for x in bytearray(data)) From b83826e8399e8eb75230f847d931d194f7c3bdb7 Mon Sep 17 00:00:00 2001 From: Felipe Martins Diel <41558831+felipediel@users.noreply.github.com> Date: Sun, 20 Mar 2022 21:33:44 -0300 Subject: [PATCH 2/5] Clean up remote.py --- broadlink/remote.py | 32 +++++++++++--------------------- 1 file changed, 11 insertions(+), 21 deletions(-) diff --git a/broadlink/remote.py b/broadlink/remote.py index 15a9a199..f4db3d2f 100644 --- a/broadlink/remote.py +++ b/broadlink/remote.py @@ -1,5 +1,6 @@ """Support for universal remotes.""" import struct +import typing as t from . import exceptions as e from .device import Device @@ -46,29 +47,18 @@ def sweep_frequency(self) -> None: """Sweep frequency.""" self._send(0x19) - def check_frequency(self) -> bool: + def check_frequency(self) -> t.Tuple[bool, float]: """Return True if the frequency was identified successfully.""" resp = self._send(0x1A) - return resp[0] == 1 - - def check_frequency_ex(self) -> (bool, float): - """Return (True if the frequency was identified successfully, Current frequency)""" - resp = self._send(0x1A) - return resp[0] == 1, struct.unpack(' float: - """Return frequency device is tuned to in MHz""" - resp = self._send(0x1A) - return struct.unpack(' None: - """Enter radiofrequency learning mode, optionally tuning the device to a specific frequency""" - payload = b'' - if frequency is not None: - payload = struct.pack(' None: + """Enter radiofrequency learning mode.""" + payload = bytearray() + if frequency: + payload += struct.pack(" None: From 274b31781d0a09e3d30a28f4e8c488f6fdce239d Mon Sep 17 00:00:00 2001 From: Felipe Martins Diel <41558831+felipediel@users.noreply.github.com> Date: Sun, 20 Mar 2022 21:35:26 -0300 Subject: [PATCH 3/5] Clean up broadlink_cli --- cli/broadlink_cli | 32 ++++++++++++++------------------ 1 file changed, 14 insertions(+), 18 deletions(-) diff --git a/cli/broadlink_cli b/cli/broadlink_cli index 594baff4..ec1216fc 100755 --- a/cli/broadlink_cli +++ b/cli/broadlink_cli @@ -83,8 +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("--sensors", action="store_true", help="check all sensors") 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", nargs="?", type=float, const=433.92, metavar="FREQUENCY", help="rf learning on specified FREQUENCY, default: 433.92") +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("--durations", action="store_true", help="use durations in micro seconds instead of the Broadlink format") @@ -196,35 +196,32 @@ if args.switch: else: dev.set_power(True) print('* Switch to ON *') -if args.rfscanlearn or args.rflearn: - dev.sweep_frequency() - if args.rfscanlearn: - print("Learning RF Frequency, press and hold the button to learn...") +if args.rflearn: + if args.frequency: + frequency = args.frequency + else: + dev.sweep_frequency() + print("Detecting radiofrequency, press and hold the button to learn...") start = time.time() while time.time() - start < TIMEOUT: time.sleep(1) - locked, frequency = dev.check_frequency_ex() + locked, frequency = dev.check_frequency() if locked: break - print("Sweeping {}MHz...".format(frequency)) else: - print("RF Frequency not found") + print("Radiofrequency not found") dev.cancel_sweep_frequency() exit(1) - frequency = dev.get_frequency() - print("Found RF Frequency {}MHz - 1 of 2!".format(frequency)) + print("Radiofrequency detected: {}MHz".format(frequency)) print("You can now let go of the button") input("Press enter to continue...") - dev.find_rf_packet() - else: - dev.find_rf_packet(args.rflearn) - print("Device tuned to {}MHz".format(dev.get_frequency())) + dev.find_rf_packet(frequency) - print("To complete learning, single press the button you want to learn") + print("Press the button again, now a short press.") start = time.time() while time.time() - start < TIMEOUT: @@ -239,8 +236,7 @@ if args.rfscanlearn or args.rflearn: print("No data received...") exit(1) - if args.rfscanlearn: - print("Found RF Frequency - 2 of 2!") + print("Packet found!") learned = format_durations(to_microseconds(bytearray(data))) \ if args.durations \ else ''.join(format(x, '02x') for x in bytearray(data)) From b90c6688dda33f9e558eadf38ae8c615a7f538a6 Mon Sep 17 00:00:00 2001 From: Felipe Martins Diel <41558831+felipediel@users.noreply.github.com> Date: Sun, 20 Mar 2022 21:50:00 -0300 Subject: [PATCH 4/5] Update conditional --- cli/broadlink_cli | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cli/broadlink_cli b/cli/broadlink_cli index ec1216fc..2679bc7e 100755 --- a/cli/broadlink_cli +++ b/cli/broadlink_cli @@ -128,7 +128,7 @@ if args.send: data = durations_to_broadlink(parse_durations(' '.join(args.data))) \ if args.durations else bytearray.fromhex(''.join(args.data)) dev.send_data(data) -if args.learn or (args.learnfile and not args.rfscanlearn and not args.rflearn): +if args.learn or (args.learnfile and not args.rflearn): dev.enter_learning() print("Learning...") start = time.time() From 81b9661f182cdc9415cefb84f184bd421f789a46 Mon Sep 17 00:00:00 2001 From: Felipe Martins Diel <41558831+felipediel@users.noreply.github.com> Date: Sun, 20 Mar 2022 22:12:19 -0300 Subject: [PATCH 5/5] Fix message --- cli/broadlink_cli | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/cli/broadlink_cli b/cli/broadlink_cli index 2679bc7e..1083e596 100755 --- a/cli/broadlink_cli +++ b/cli/broadlink_cli @@ -199,6 +199,7 @@ if args.switch: if args.rflearn: if args.frequency: frequency = args.frequency + print("Press the button you want to learn, a short press...") else: dev.sweep_frequency() print("Detecting radiofrequency, press and hold the button to learn...") @@ -219,9 +220,9 @@ if args.rflearn: input("Press enter to continue...") - dev.find_rf_packet(frequency) + print("Press the button again, now a short press.") - print("Press the button again, now a short press.") + dev.find_rf_packet(frequency) start = time.time() while time.time() - start < TIMEOUT: