From dd6eb8767e7a7f1f54aa1e7a7b57309bc4fc5fba Mon Sep 17 00:00:00 2001 From: Matthew Garrett Date: Sat, 25 Nov 2017 12:38:57 -0800 Subject: [PATCH 1/3] Experimental RF code --- README.md | 39 ++++++++++++++++++++++++++++++++++++++- broadlink/__init__.py | 27 +++++++++++++++++++++++++++ 2 files changed, 65 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 1305ea0f5..48708827c 100644 --- a/README.md +++ b/README.md @@ -37,6 +37,23 @@ Enter learning mode: devices[0].enter_learning() ``` +Sweep RF frequencies: +``` +devices[0].sweep_frequency() +``` + +Check whether a frequency has been found: +``` +found = devices[0].check_frequency() +``` +(This will return True if the RM has locked onto a frequency, False otherwise) + +Attempt to learn an RF packet: +``` +found = devices[0].find_rf_packet() +``` +(This will return True if a packet has been found, False otherwise) + Obtain an IR or RF packet while in learning mode: ``` ir_packet = devices[0].check_data() @@ -76,4 +93,24 @@ devices[0].set_power(1, True) Check power state on a SmartPowerStrip: ``` state = devices[0].check_power() -``` \ No newline at end of file +``` + +Learning RF packets +------------------- + +timeout = 10 +devices[0].sweep_frequency() +# Hold down the rf button +for i in range(0, timeout): + found = devices[0].check_frequency() + if found == True: + break + time.sleep(1) +# Tap the rf button +for i in range(0, timeout): + found = devices[0].find_rf_packet() + if found == True: + break + time.sleep(1) +# Obtain the code +code = devices[0].check_data() diff --git a/broadlink/__init__.py b/broadlink/__init__.py index ea4cbc5fa..a4c8a4841 100644 --- a/broadlink/__init__.py +++ b/broadlink/__init__.py @@ -501,6 +501,33 @@ class rm(device): packet[0] = 3 self.send_packet(0x6a, packet) + def sweep_frequency(self): + packet = bytearray(16) + packet[0] = 0x19; + self.send_packet(0x6a, packet) + + def check_frequency(self): + packet = bytearray(16) + packet[0] = 0x1a + response = self.send_packet(0x6a, packet) + err = response[0x22] | (response[0x23] << 8) + if err == 0: + payload = self.decrypt(bytes(response[0x38:])) + if payload[0x04] == 1: + return True + return False + + def find_rf_packet(self): + packet = bytearray(16) + packet[0] = 0x1b + response = self.send_packet(0x6a, packet) + err = response[0x22] | (response[0x23] << 8) + if err == 0: + payload = self.decrypt(bytes(response[0x38:])) + if payload[0x04] == 1: + return True + return False + def check_temperature(self): packet = bytearray(16) packet[0] = 1 From 4e33ef446520275e0a9426dc8182dcc3af276da3 Mon Sep 17 00:00:00 2001 From: Brent Avery Date: Tue, 30 Jan 2018 07:45:21 +1100 Subject: [PATCH 2/3] Get rf scan learning working in CLI tool (#87) --- broadlink/__init__.py | 9 ++++-- cli/broadlink_cli | 70 +++++++++++++++++++++++++++++++++++-------- 2 files changed, 64 insertions(+), 15 deletions(-) diff --git a/broadlink/__init__.py b/broadlink/__init__.py index a4c8a4841..8a193d556 100644 --- a/broadlink/__init__.py +++ b/broadlink/__init__.py @@ -503,7 +503,12 @@ class rm(device): def sweep_frequency(self): packet = bytearray(16) - packet[0] = 0x19; + packet[0] = 0x19 + self.send_packet(0x6a, packet) + + def cancel_sweep_frequency(self): + packet = bytearray(16) + packet[0] = 0x1e self.send_packet(0x6a, packet) def check_frequency(self): @@ -541,7 +546,7 @@ class rm(device): temp = (ord(payload[0x4]) * 10 + ord(payload[0x5])) / 10.0 return temp -# For legay compatibility - don't use this +# For legacy compatibility - don't use this class rm2(rm): def __init__ (self): device.__init__(self, None, None) diff --git a/cli/broadlink_cli b/cli/broadlink_cli index 3acf168a9..dca0a3d6b 100755 --- a/cli/broadlink_cli +++ b/cli/broadlink_cli @@ -1,7 +1,6 @@ -#!/usr/bin/env python +#!/usr/bin/env python3 import broadlink -import sys import argparse import time @@ -71,6 +70,7 @@ parser.add_argument("--temperature",action="store_true", help="request temperatu 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("--learnfile", help="learn command and save to specified file") parser.add_argument("--durations", action="store_true", help="use durations in micro seconds instead of the Broadlink format") parser.add_argument("--convert", action="store_true", help="convert input data to durations") @@ -78,8 +78,8 @@ parser.add_argument("data", nargs='*', help="Data to send or convert") args = parser.parse_args() if args.device: - values = args.device.split(); - type = int(values[0],0) + values = args.device.split() + type = int(values[0], 0) host = values[1] mac = bytearray.fromhex(values[2]) elif args.mac: @@ -87,16 +87,16 @@ elif args.mac: host = args.host mac = bytearray.fromhex(args.mac) -if args.host: +if args.host or host is not None: dev = broadlink.gendevice(type, (host, 80), mac) dev.auth() if args.convert: data = bytearray.fromhex(''.join(args.data)) durations = to_microseconds(data) - print format_durations(durations) + print(format_durations(durations)) if args.temperature: - print dev.check_temperature() + print(dev.check_temperature()) if args.sensors: try: data = dev.check_sensors() @@ -104,7 +104,7 @@ if args.sensors: data = {} data['temperature'] = dev.check_temperature() for key in data: - print "{} {}".format(key, data[key]) + print("{} {}".format(key, data[key])) if args.send: data = durations_to_broadlink(parse_durations(' '.join(args.data))) \ if args.durations else bytearray.fromhex(''.join(args.data)) @@ -112,7 +112,7 @@ if args.send: if args.learn or args.learnfile: dev.enter_learning() data = None - print "Learning..." + print("Learning...") timeout = 30 while (data is None) and (timeout > 0): time.sleep(2) @@ -123,11 +123,55 @@ if args.learn or args.learnfile: if args.durations \ else ''.join(format(x, '02x') for x in bytearray(data)) if args.learn: - print learned + print(learned) if args.learnfile: - print "Saving to {}".format(args.learnfile) + print("Saving to {}".format(args.learnfile)) with open(args.learnfile, "w") as text_file: text_file.write(learned) else: - print "No data received..." - + print("No data received...") +if args.rfscanlearn: + dev.sweep_frequency() + print("Learning RF Frequency, press and hold the button to learn...") + + timeout = 20 + + while (not dev.check_frequency()) and (timeout > 0): + time.sleep(1) + timeout -= 1 + + if timeout <= 0: + print("RF Frequency not found") + dev.cancel_sweep_frequency() + exit(1) + + print("Found RF Frequency - 1 of 2!") + print("You can now let go of the button") + + input("Press any key to continue...") + + print("To complete learning, single press the button you want to learn") + + dev.find_rf_packet() + + data = None + timeout = 20 + + while (data is None) and (timeout > 0): + time.sleep(1) + timeout -= 1 + data = dev.check_data() + + if data: + 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)) + if args.learn | args.rfscanlearn: + print(learned) + if args.learnfile: + print("Saving to {}".format(args.learnfile)) + with open(args.learnfile, "w") as text_file: + text_file.write(learned) + else: + print("No data received...") \ No newline at end of file From 694b4423b50cc55f9a48d14a41f1615799342c43 Mon Sep 17 00:00:00 2001 From: Sergey Prilukin Date: Sun, 25 Nov 2018 23:58:33 +0200 Subject: [PATCH 3/3] fixed --learnfile argument usage, so it works for both IR and RF --- cli/broadlink_cli | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/cli/broadlink_cli b/cli/broadlink_cli index dca0a3d6b..1ff45f1d9 100755 --- a/cli/broadlink_cli +++ b/cli/broadlink_cli @@ -61,7 +61,7 @@ def parse_durations(str): return result -parser = argparse.ArgumentParser(fromfile_prefix_chars='@'); +parser = argparse.ArgumentParser(fromfile_prefix_chars='@') parser.add_argument("--device", help="device definition as 'type host mac'") parser.add_argument("--type", type=auto_int, default=0x2712, help="type of device") parser.add_argument("--host", help="host address") @@ -70,8 +70,8 @@ parser.add_argument("--temperature",action="store_true", help="request temperatu 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("--learnfile", help="save learned command to a specified file") parser.add_argument("--rfscanlearn", action="store_true", help="rf scan learning") -parser.add_argument("--learnfile", help="learn command and save to specified file") parser.add_argument("--durations", action="store_true", help="use durations in micro seconds instead of the Broadlink format") parser.add_argument("--convert", action="store_true", help="convert input data to durations") parser.add_argument("data", nargs='*', help="Data to send or convert") @@ -109,7 +109,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: +if args.learn: dev.enter_learning() data = None print("Learning...") @@ -122,9 +122,9 @@ if args.learn or args.learnfile: learned = format_durations(to_microseconds(bytearray(data))) \ if args.durations \ else ''.join(format(x, '02x') for x in bytearray(data)) - if args.learn: + if args.learnfile is None: print(learned) - if args.learnfile: + if args.learnfile is not None: print("Saving to {}".format(args.learnfile)) with open(args.learnfile, "w") as text_file: text_file.write(learned) @@ -148,7 +148,7 @@ if args.rfscanlearn: print("Found RF Frequency - 1 of 2!") print("You can now let go of the button") - input("Press any key to continue...") + input("Press enter to continue...") print("To complete learning, single press the button you want to learn") @@ -167,9 +167,9 @@ if args.rfscanlearn: learned = format_durations(to_microseconds(bytearray(data))) \ if args.durations \ else ''.join(format(x, '02x') for x in bytearray(data)) - if args.learn | args.rfscanlearn: + if args.learnfile is None: print(learned) - if args.learnfile: + if args.learnfile is not None: print("Saving to {}".format(args.learnfile)) with open(args.learnfile, "w") as text_file: text_file.write(learned)