Update IRRemote ESP8266 to 2.6.2 and add ESP32 support

This commit is contained in:
Florian committed 2019-07-08 22:21:02 +02:00
1 parent 2ee18320be
commit 24bcdbc97c
195 files changed
+22963 -4737

No files matched your search

+46 -25
View File
@@ -14,13 +14,14 @@ USER_DIR = ../src
# Where to find test code.
TEST_DIR = ../test
INCLUDES = -I$(USER_DIR) -I$(TEST_DIR)
# Flags passed to the preprocessor.
# Set Google Test's header directory as a system directory, such that
# the compiler doesn't generate warnings in Google Test headers.
CPPFLAGS += -DUNIT_TEST
# Flags passed to the C++ compiler.
CXXFLAGS += -g -Wall -Wextra -pthread
CXXFLAGS += -g -Wall -Wextra -pthread -std=gnu++11
all : gc_decode mode2_decode
@@ -28,7 +29,7 @@ run_tests : all
failed=""; \
for py_unittest in *_test.py; do \
echo "RUNNING: $${py_unittest}"; \
python ./$${py_unittest} || failed="$${failed} $${py_unittest}"; \
python3 ./$${py_unittest} || failed="$${failed} $${py_unittest}"; \
done; \
if [ -n "$${failed}" ]; then \
echo "FAIL: :-( :-( Unit test(s)$${failed} failed! :-( :-("; exit 1; \
@@ -48,25 +49,28 @@ PROTOCOLS = ir_NEC.o ir_Sony.o ir_Samsung.o ir_JVC.o ir_RCMM.o ir_RC5_RC6.o \
ir_Pronto.o ir_GlobalCache.o ir_Nikai.o ir_Toshiba.o ir_Midea.o \
ir_Magiquest.o ir_Lasertag.o ir_Carrier.o ir_Haier.o ir_Hitachi.o \
ir_GICable.o ir_Whirlpool.o ir_Lutron.o ir_Electra.o ir_Pioneer.o \
ir_MWM.o ir_Vestel.o ir_Teco.o ir_Tcl.o
ir_MWM.o ir_Vestel.o ir_Teco.o ir_Tcl.o ir_Lego.o \
ir_MitsubishiHeavy.o ir_Goodweather.o ir_Inax.o ir_Argo.o \
ir_Trotec.o
# Common object files
COMMON_OBJ = IRutils.o IRtimer.o IRsend.o IRrecv.o $(PROTOCOLS)
# Common dependencies
COMMON_DEPS = $(USER_DIR)/IRrecv.h $(USER_DIR)/IRsend.h $(USER_DIR)/IRtimer.h \
$(USER_DIR)/IRutils.h $(USER_DIR)/IRremoteESP8266.h
$(USER_DIR)/IRutils.h $(USER_DIR)/IRremoteESP8266.h \
$(TEST_DIR)/IRsend_test.h
# Common test dependencies
COMMON_TEST_DEPS = $(COMMON_DEPS) $(TEST_DIR)/IRsend_test.h
gc_decode.o : gc_decode.cpp $(COMMON_TEST_DEPS) $(GTEST_HEADERS)
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -I$(USER_DIR) -I$(TEST_DIR) -c gc_decode.cpp
$(CXX) $(CPPFLAGS) $(CXXFLAGS) $(INCLUDES) -c gc_decode.cpp
gc_decode : $(COMMON_OBJ) gc_decode.o
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -lpthread $^ -o $@
mode2_decode.o : mode2_decode.cpp $(COMMON_TEST_DEPS) $(GTEST_HEADERS)
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -I$(USER_DIR) -I$(TEST_DIR) -c mode2_decode.cpp
$(CXX) $(CPPFLAGS) $(CXXFLAGS) $(INCLUDES) -c mode2_decode.cpp
mode2_decode : $(COMMON_OBJ) mode2_decode.o
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -lpthread $^ -o $@
@@ -83,7 +87,6 @@ IRsend.o : $(USER_DIR)/IRsend.cpp $(USER_DIR)/IRsend.h $(USER_DIR)/IRremoteESP82
IRrecv.o : $(USER_DIR)/IRrecv.cpp $(USER_DIR)/IRrecv.h $(USER_DIR)/IRremoteESP8266.h $(GTEST_HEADERS)
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/IRrecv.cpp
ir_NEC.o : $(USER_DIR)/ir_NEC.cpp $(COMMON_DEPS)
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/ir_NEC.cpp
@@ -97,10 +100,13 @@ ir_Sony.o : $(USER_DIR)/ir_Sony.cpp $(COMMON_DEPS)
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/ir_Sony.cpp
ir_Samsung.o : $(USER_DIR)/ir_Samsung.cpp $(USER_DIR)/ir_Samsung.h $(COMMON_DEPS)
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/ir_Samsung.cpp
$(CXX) $(CPPFLAGS) $(CXXFLAGS) $(INCLUDES) -c $(USER_DIR)/ir_Samsung.cpp
ir_Kelvinator.o : $(USER_DIR)/ir_Kelvinator.cpp $(USER_DIR)/ir_Kelvinator.h $(COMMON_DEPS)
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/ir_Kelvinator.cpp
$(CXX) $(CPPFLAGS) $(CXXFLAGS) $(INCLUDES) -c $(USER_DIR)/ir_Kelvinator.cpp
ir_Inax.o : $(USER_DIR)/ir_Inax.cpp $(COMMON_DEPS)
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/ir_Inax.cpp
ir_JVC.o : $(USER_DIR)/ir_JVC.cpp $(COMMON_DEPS)
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/ir_JVC.cpp
@@ -112,19 +118,22 @@ ir_LG.o : $(USER_DIR)/ir_LG.h $(USER_DIR)/ir_LG.cpp $(COMMON_DEPS)
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/ir_LG.cpp
ir_Mitsubishi.o : $(USER_DIR)/ir_Mitsubishi.h $(USER_DIR)/ir_Mitsubishi.cpp $(COMMON_DEPS)
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/ir_Mitsubishi.cpp
$(CXX) $(CPPFLAGS) $(CXXFLAGS) $(INCLUDES) -c $(USER_DIR)/ir_Mitsubishi.cpp
ir_MitsubishiHeavy.o : $(USER_DIR)/ir_MitsubishiHeavy.h $(USER_DIR)/ir_MitsubishiHeavy.cpp $(COMMON_DEPS)
$(CXX) $(CPPFLAGS) $(CXXFLAGS) $(INCLUDES) -c $(USER_DIR)/ir_MitsubishiHeavy.cpp
ir_Fujitsu.o : $(USER_DIR)/ir_Fujitsu.h $(USER_DIR)/ir_Fujitsu.cpp $(COMMON_DEPS)
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/ir_Fujitsu.cpp
$(CXX) $(CPPFLAGS) $(CXXFLAGS) $(INCLUDES) -c $(USER_DIR)/ir_Fujitsu.cpp
ir_Sharp.o : $(USER_DIR)/ir_Sharp.cpp $(COMMON_DEPS)
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/ir_Sharp.cpp
ir_Sharp.o : $(USER_DIR)/ir_Sharp.h $(USER_DIR)/ir_Sharp.cpp $(COMMON_DEPS)
$(CXX) $(CPPFLAGS) $(CXXFLAGS) $(INCLUDES) -c $(USER_DIR)/ir_Sharp.cpp
ir_RC5_RC6.o : $(USER_DIR)/ir_RC5_RC6.cpp $(COMMON_DEPS)
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/ir_RC5_RC6.cpp
ir_Panasonic.o : $(USER_DIR)/ir_Panasonic.cpp $(COMMON_DEPS)
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/ir_Panasonic.cpp
$(CXX) $(CPPFLAGS) $(CXXFLAGS) $(INCLUDES) -c $(USER_DIR)/ir_Panasonic.cpp
ir_Dish.o : $(USER_DIR)/ir_Dish.cpp $(COMMON_DEPS)
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/ir_Dish.cpp
@@ -133,7 +142,7 @@ ir_Whynter.o : $(USER_DIR)/ir_Whynter.cpp $(COMMON_DEPS)
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/ir_Whynter.cpp
ir_Coolix.o : $(USER_DIR)/ir_Coolix.cpp $(COMMON_DEPS)
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/ir_Coolix.cpp
$(CXX) $(CPPFLAGS) $(CXXFLAGS) $(INCLUDES) -c $(USER_DIR)/ir_Coolix.cpp
ir_Aiwa.o : $(USER_DIR)/ir_Aiwa.cpp $(COMMON_DEPS)
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/ir_Aiwa.cpp
@@ -145,10 +154,10 @@ ir_Sanyo.o : $(USER_DIR)/ir_Sanyo.cpp $(COMMON_DEPS)
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/ir_Sanyo.cpp
ir_Daikin.o : $(USER_DIR)/ir_Daikin.cpp $(USER_DIR)/ir_Daikin.h $(COMMON_DEPS)
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/ir_Daikin.cpp
$(CXX) $(CPPFLAGS) $(CXXFLAGS) $(INCLUDES) -c $(USER_DIR)/ir_Daikin.cpp
ir_Gree.o : $(USER_DIR)/ir_Gree.cpp $(GTEST_HEADERS)
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/ir_Gree.cpp
$(CXX) $(CPPFLAGS) $(CXXFLAGS) $(INCLUDES) -c $(USER_DIR)/ir_Gree.cpp
ir_Pronto.o : $(USER_DIR)/ir_Pronto.cpp $(GTEST_HEADERS)
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/ir_Pronto.cpp
@@ -157,10 +166,10 @@ ir_Nikai.o : $(USER_DIR)/ir_Nikai.cpp $(GTEST_HEADERS)
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/ir_Nikai.cpp
ir_Toshiba.o : $(USER_DIR)/ir_Toshiba.h $(USER_DIR)/ir_Toshiba.cpp $(COMMON_DEPS)
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/ir_Toshiba.cpp
$(CXX) $(CPPFLAGS) $(CXXFLAGS) $(INCLUDES) -c $(USER_DIR)/ir_Toshiba.cpp
ir_Midea.o : $(USER_DIR)/ir_Midea.cpp $(COMMON_DEPS)
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/ir_Midea.cpp
$(CXX) $(CPPFLAGS) $(CXXFLAGS) $(INCLUDES) -c $(USER_DIR)/ir_Midea.cpp
ir_Magiquest.o : $(USER_DIR)/ir_Magiquest.cpp $(GTEST_HEADERS)
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/ir_Magiquest.cpp
@@ -172,16 +181,16 @@ ir_Carrier.o : $(USER_DIR)/ir_Carrier.cpp $(GTEST_HEADERS)
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/ir_Carrier.cpp
ir_Haier.o : $(USER_DIR)/ir_Haier.cpp $(USER_DIR)/ir_Haier.h $(GTEST_HEADERS)
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/ir_Haier.cpp
$(CXX) $(CPPFLAGS) $(CXXFLAGS) $(INCLUDES) -c $(USER_DIR)/ir_Haier.cpp
ir_Hitachi.o : $(USER_DIR)/ir_Hitachi.cpp $(GTEST_HEADERS)
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/ir_Hitachi.cpp
$(CXX) $(CPPFLAGS) $(CXXFLAGS) $(INCLUDES) -c $(USER_DIR)/ir_Hitachi.cpp
ir_GICable.o : $(USER_DIR)/ir_GICable.cpp $(GTEST_HEADERS)
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/ir_GICable.cpp
ir_Whirlpool.o : $(USER_DIR)/ir_Whirlpool.cpp $(GTEST_HEADERS)
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/ir_Whirlpool.cpp
$(CXX) $(CPPFLAGS) $(CXXFLAGS) $(INCLUDES) -c $(USER_DIR)/ir_Whirlpool.cpp
ir_Lutron.o : $(USER_DIR)/ir_Lutron.cpp $(GTEST_HEADERS)
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/ir_Lutron.cpp
@@ -196,10 +205,22 @@ ir_MWM.o : $(USER_DIR)/ir_MWM.cpp $(USER_DIR)/ir_RC5_RC6.cpp $(COMMON_DEPS)
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/ir_MWM.cpp
ir_Vestel.o : $(USER_DIR)/ir_Vestel.cpp $(GTEST_HEADERS)
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/ir_Vestel.cpp
$(CXX) $(CPPFLAGS) $(CXXFLAGS) $(INCLUDES) -c $(USER_DIR)/ir_Vestel.cpp
ir_Teco.o : $(USER_DIR)/ir_Teco.cpp $(GTEST_HEADERS)
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/ir_Teco.cpp
$(CXX) $(CPPFLAGS) $(CXXFLAGS) $(INCLUDES) -c $(USER_DIR)/ir_Teco.cpp
ir_Tcl.o : $(USER_DIR)/ir_Tcl.cpp $(USER_DIR)/ir_Tcl.h $(GTEST_HEADERS)
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/ir_Tcl.cpp
$(CXX) $(CPPFLAGS) $(CXXFLAGS) $(INCLUDES) -c $(USER_DIR)/ir_Tcl.cpp
ir_Trotec.o : $(USER_DIR)/ir_Trotec.cpp $(USER_DIR)/ir_Trotec.h $(GTEST_HEADERS)
$(CXX) $(CPPFLAGS) $(CXXFLAGS) $(INCLUDES) -c $(USER_DIR)/ir_Trotec.cpp
ir_Lego.o : $(USER_DIR)/ir_Lego.cpp $(GTEST_HEADERS)
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/ir_Lego.cpp
ir_Argo.o : $(USER_DIR)/ir_Argo.cpp $(USER_DIR)/ir_Argo.h $(GTEST_HEADERS)
$(CXX) $(CPPFLAGS) $(CXXFLAGS) $(INCLUDES) -c $(USER_DIR)/ir_Argo.cpp
ir_Goodweather.o : $(USER_DIR)/ir_Goodweather.cpp $(USER_DIR)/ir_Goodweather.h $(GTEST_HEADERS)
$(CXX) $(CPPFLAGS) $(CXXFLAGS) $(INCLUDES) -c $(USER_DIR)/ir_Goodweather.cpp
@@ -8,7 +8,7 @@ import argparse
import sys
class RawIRMessage(object):
class RawIRMessage():
"""Basic analyse functions & structure for raw IR messages."""
# pylint: disable=too-many-instance-attributes
@@ -62,7 +62,7 @@ class RawIRMessage(object):
def _usec_compare(self, seen, expected):
"""Compare two usec values and see if they match within a
subtractive margin."""
return seen <= expected and seen > expected - self.margin
return expected - self.margin < seen <= expected
def _usec_compares(self, usecs, expecteds):
"""Compare a usec value to a list of values and return True
@@ -160,7 +160,7 @@ class RawIRMessage(object):
def avg_list(items):
"""Return the average of a list of numbers."""
if items:
return sum(items) / len(items)
return int(sum(items) / len(items))
return 0
@@ -293,7 +293,7 @@ def decode_data(message, defines, function_code, output=sys.stdout):
output.write("kHdrSpace+")
function_code.append(" space(kHdrSpace);")
elif message.is_bit_mark(usec) and count % 2:
if state != "HS" and state != "BS":
if state not in ("HS", "BS"):
output.write("kBitMark(UNEXPECTED)")
state = "BM"
elif message.is_zero_space(usec):
@@ -1,6 +1,6 @@
#!/usr/bin/python
#!/usr/bin/python3
"""Unit tests for auto_analyse_raw_data.py"""
import StringIO
from io import StringIO
import unittest
import auto_analyse_raw_data as analyse
@@ -12,7 +12,7 @@ class TestRawIRMessage(unittest.TestCase):
def test_display_binary(self):
"""Test the display_binary() method."""
output = StringIO.StringIO()
output = StringIO()
message = analyse.RawIRMessage(100, [8000, 4000, 500, 500, 500], output,
False)
self.assertEqual(output.getvalue(), '')
@@ -52,8 +52,8 @@ class TestAutoAnalyseRawData(unittest.TestCase):
def test_dump_constants_simple(self):
"""Simple tests for the dump_constants() function."""
ignore = StringIO.StringIO()
output = StringIO.StringIO()
ignore = StringIO()
output = StringIO()
defs = []
message = analyse.RawIRMessage(200, [
7930, 3952, 494, 1482, 520, 1482, 494, 1508, 494, 520, 494, 1482, 494,
@@ -75,8 +75,8 @@ class TestAutoAnalyseRawData(unittest.TestCase):
def test_dump_constants_aircon(self):
"""More complex tests for the dump_constants() function."""
ignore = StringIO.StringIO()
output = StringIO.StringIO()
ignore = StringIO()
output = StringIO()
defs = []
message = analyse.RawIRMessage(200, [
9008, 4496, 644, 1660, 676, 530, 648, 558, 672, 1636, 646, 1660, 644,
@@ -111,7 +111,7 @@ class TestAutoAnalyseRawData(unittest.TestCase):
self.assertEqual(analyse.convert_rawdata("0"), [0])
with self.assertRaises(ValueError) as context:
analyse.convert_rawdata("")
self.assertEqual(context.exception.message,
self.assertEqual(str(context.exception),
"Raw Data contains a non-numeric value of ''.")
# Single parenthesis
@@ -132,13 +132,13 @@ class TestAutoAnalyseRawData(unittest.TestCase):
# Bad parentheses
with self.assertRaises(ValueError) as context:
analyse.convert_rawdata("}10{")
self.assertEqual(context.exception.message,
self.assertEqual(str(context.exception),
"Raw Data not parsible due to parentheses placement.")
# Non base-10 values
with self.assertRaises(ValueError) as context:
analyse.convert_rawdata("10, 20, foo, bar, 30")
self.assertEqual(context.exception.message,
self.assertEqual(str(context.exception),
"Raw Data contains a non-numeric value of 'foo'.")
# A messy usual "good" case.
@@ -155,7 +155,7 @@ class TestAutoAnalyseRawData(unittest.TestCase):
"""Tests for the parse_and_report() function."""
# Without code generation.
output = StringIO.StringIO()
output = StringIO()
input_str = """
uint16_t rawbuf[139] = {9008, 4496, 644, 1660, 676, 530, 648, 558, 672,
1636, 646, 1660, 644, 556, 650, 584, 626, 560, 644, 580, 628, 1680,
@@ -210,7 +210,7 @@ class TestAutoAnalyseRawData(unittest.TestCase):
'Total Nr. of suspected bits: 67\n')
# With code generation.
output = StringIO.StringIO()
output = StringIO()
input_str = """
uint16_t rawbuf[37] = {7930, 3952, 494, 1482, 520, 1482, 494,
1508, 494, 520, 494, 1482, 494, 520, 494, 1482, 494, 1482, 494,
@@ -294,7 +294,7 @@ class TestAutoAnalyseRawData(unittest.TestCase):
"""Tests for unusual Space Gaps in parse_and_report() function."""
# Tests for unusual Gaps. (Issue #482)
output = StringIO.StringIO()
output = StringIO()
input_str = """
uint16_t rawbuf[272] = {3485, 3512, 864, 864, 864, 2620, 864, 864,
864, 2620, 864, 2620, 864, 2620, 864, 2620, 864, 2620, 864, 864,
@@ -466,7 +466,7 @@ class TestAutoAnalyseRawData(unittest.TestCase):
def test_reduce_list(self):
"""Tests for the reduce_list method."""
ignore = StringIO.StringIO()
ignore = StringIO()
message = analyse.RawIRMessage(200, [
7930, 3952, 494, 1482, 520, 1482, 494, 1508, 494, 520, 494, 1482, 494,
520, 494, 1482, 494, 1482, 494, 3978, 494, 520, 494, 520, 494, 520, 494,
@@ -0,0 +1,255 @@
#!/usr/bin/env python3
"""Generate SupportedProtocols.md by scraping source code files"""
import pathlib
import argparse
import sys
import re
import time
CODE_URL = "https://github.com/markszabo/IRremoteESP8266/blob/master/src/ir_"
BRAND_MODEL = re.compile(r"Brand: *(?P<brand>.+), *Model: *(?P<model>.+)")
ENUMS = re.compile(r"enum \w+ {(.+?)};", re.DOTALL)
ENUM_ENTRY = re.compile(r"^\s+(\w+)", re.MULTILINE)
DECODED_PROTOCOLS = re.compile(r".*results->decode_type *=.*?(\w+);")
AC_FN = re.compile(r"ir_(.+).h")
ALL_FN = re.compile(r"ir_(.+).(h|cpp)")
EXCLUDED_PROTOCOLS = ["UNKNOWN", "UNUSED", "kLastDecodeType"]
MARKDOWN_HEADER = """<!--- WARNING: Do NOT edit this file directly.
It is generated by './tools/scrape_supported_devices.py'.
Last generated: {} --->""".format(time.asctime())
def getallprotocols():
"""Return all protocls configured in IRremoteESP8266.h
"""
irremote = ARGS.directory / "IRremoteESP8266.h"
enums = getenums(irremote)
if not enums:
errorexit("Error getting ENUMS from IRremoteESP8266.h")
return enums
def getdecodedprotocols():
"""All protocols that include decoding support"""
ret = set()
for path in ARGS.directory.iterdir():
if path.suffix != ".cpp":
continue
matches = DECODED_PROTOCOLS.finditer(path.open().read())
for match in matches:
protocol = match.group(1)
if protocol not in EXCLUDED_PROTOCOLS:
ret.add(protocol)
return ret
def getallacs():
"""All supported A/C codes"""
ret = {}
for path in ARGS.directory.iterdir():
match = AC_FN.match(path.name)
if not match:
continue
acprotocol = match.group(1)
rawmodels = getenums(path)
models = set()
for model in rawmodels:
model = model.upper()
model = model.replace("K{}".format(acprotocol.upper()), "")
if model and model not in EXCLUDED_PROTOCOLS:
models.add(model)
ret[acprotocol] = models
return ret
def getalldevices():
"""All devices and associated branding and model information (if available)
"""
allcodes = {}
fnnomatch = set()
fnmatch = set()
for path in ARGS.directory.iterdir():
match = ALL_FN.match(path.name)
if not match:
continue
supports = extractsupports(path)
if supports:
fnmatch.add(path.stem)
else:
fnnomatch.add(path.stem)
protocol = match.group(1)
for brand, model in supports:
protocolbrand = (protocol, brand)
allcodes[protocolbrand] = allcodes.get(protocolbrand, list()) + [model]
nosupports = fnnomatch - fnmatch
for fnprotocol in nosupports:
allcodes[(fnprotocol[3:], "Unknown")] = []
return allcodes, nosupports
def getenums(path):
"""Returns the keys for the first enum type in path
"""
enums = ENUMS.search(path.open().read())
ret = set()
if not enums:
return ret
for enum in ENUM_ENTRY.finditer(enums.group(1)):
enum = enum.group(1)
if enum in EXCLUDED_PROTOCOLS:
continue
ret.add(enum)
return ret
ARGS = None
def initargs():
"""Init the command line arguments"""
global ARGS # pylint: disable=global-statement
parser = argparse.ArgumentParser()
parser.add_argument(
"-s",
"--stdout",
help="output to stdout rather than SupportedProtocols.md",
action="store_true",
)
parser.add_argument("-v",
"--verbose",
help="increase output verbosity",
action="store_true")
parser.add_argument(
"-a",
"--alert",
help="alert if a file does not have a supports section",
action="store_true",
)
parser.add_argument(
"directory",
nargs="?",
help="directory of the source git checkout",
default=None,
)
ARGS = parser.parse_args()
if ARGS.directory is None:
src = pathlib.Path("../src")
if not src.is_dir():
src = pathlib.Path("./src")
else:
src = pathlib.Path(ARGS.directory) / "src"
if not src.is_dir():
errorexit("Directory not valid: {}".format(str(src)))
ARGS.directory = src
return ARGS
def errorexit(msg):
"""Print an error and exit on critical error"""
sys.stderr.write("{}\n".format(msg))
sys.exit(1)
def extractsupports(path):
"""Extract all of the Supports: sections and associated brands and models
"""
supports = []
insupports = False
for line in path.open():
if not line.startswith("//"):
continue
line = line[2:].strip()
if line == "Supports:":
insupports = True
continue
if insupports:
match = BRAND_MODEL.match(line)
if match:
supports.append((match.group("brand"), match.group("model")))
else:
insupports = False
continue
return supports
def makeurl(txt, path):
"""Make a Markup URL from given filename"""
return "[{}]({})".format(txt, CODE_URL + path)
def outputprotocols(fout, protocols):
"""For a given protocol set, sort and output the markdown"""
protocols = list(protocols)
protocols.sort()
for protocol in protocols:
fout.write("- {}\n".format(protocol))
def main():
"""Standard boiler plate"""
initargs()
if ARGS.verbose:
print("Looking for files in: {}".format(str(ARGS.directory.resolve())))
if ARGS.stdout:
fout = sys.stdout
else:
foutpath = ARGS.directory / "../SupportedProtocols.md"
foutpath = foutpath.resolve()
if ARGS.verbose:
print("Output path: {}".format(str(foutpath)))
fout = foutpath.open("w")
decodedprotocols = getdecodedprotocols()
sendonly = getallprotocols() - decodedprotocols
allacs = getallacs()
allcodes, nosupports = getalldevices()
allbrands = list(allcodes.keys())
allbrands.sort()
fout.write(MARKDOWN_HEADER)
fout.write("\n# IR Protocols supported by this library\n\n")
fout.write(
"| Protocol | Brand | Model | A/C Model | Detailed A/C Support |\n")
fout.write("| --- | --- | --- | --- | --- |\n")
for protocolbrand in allbrands:
protocol, brand = protocolbrand
codes = allcodes[protocolbrand]
codes.sort()
if protocol in allacs:
acmodels = list(allacs[protocol])
acmodels.sort()
acsupport = "Yes"
brand = makeurl(brand, protocol + ".h")
else:
acmodels = []
acsupport = "-"
fout.write("| {} | **{}** | {} | {} | {} |\n".format(
makeurl(protocol, protocol + ".cpp"),
brand,
"<BR>".join(codes),
"<BR>".join(acmodels),
acsupport,
))
fout.write("\n\n## Send only protocols:\n\n")
outputprotocols(fout, sendonly)
fout.write("\n\n## Send & decodable protocols:\n\n")
outputprotocols(fout, decodedprotocols)
if ARGS.alert:
nosupports = list(nosupports)
nosupports.sort()
print("The following files had no supports section:")
for path in nosupports:
print("\t{}".format(path))
if __name__ == "__main__":
main()