mirror of
https://github.com/crankyoldgit/IRremoteESP8266.git
synced 2026-01-12 00:05:10 +08:00
Scrape Supported Protocols and generate SupportedProtocols.md (#755)
* Tool to build the document. * Add reference to new doc. * Other - Move existing python unit tests to Python3 - Use Python3's pylint - Fix pylint issues found after move. - Convince CI/Travis to install/use convince Python3 stuff. Fixes #743
This commit is contained in:
3
.gitignore
vendored
3
.gitignore
vendored
@@ -8,6 +8,9 @@
|
||||
# vi/vim
|
||||
**/*.swp
|
||||
|
||||
# vscode
|
||||
.vscode
|
||||
|
||||
## Build environments
|
||||
# Platformio
|
||||
**/.pio/
|
||||
|
||||
@@ -22,7 +22,7 @@ install:
|
||||
- arduino --pref "compiler.warning_level=all" --save-prefs
|
||||
- sudo apt-get install jq
|
||||
- sudo apt-get purge python-enum34
|
||||
- sudo pip install pylint
|
||||
- sudo apt-get install pylint3
|
||||
script:
|
||||
# Check that everything compiles.
|
||||
- arduino --verify --board $BD $PWD/examples/IRrecvDemo/IRrecvDemo.ino
|
||||
@@ -51,7 +51,7 @@ script:
|
||||
# Check for lint issues.
|
||||
- shopt -s nullglob
|
||||
- python cpplint.py --extensions=c,cc,cpp,ino --headers=h,hpp {src,test,tools}/*.{h,c,cc,cpp,hpp,ino} examples/*/*.{h,c,cc,cpp,hpp,ino}
|
||||
- pylint {src,test,tools}/*.py
|
||||
- pylint3 -d F0001 {src,test,tools}/*.py
|
||||
- shopt -u nullglob
|
||||
# Build and run the unit tests.
|
||||
- (cd test; make run)
|
||||
|
||||
5
.vscode/settings.json
vendored
Normal file
5
.vscode/settings.json
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"python.linting.pylintEnabled": true,
|
||||
"python.linting.flake8Enabled": false,
|
||||
"python.formatting.provider": "yapf"
|
||||
}
|
||||
@@ -29,6 +29,10 @@ something you likely should not have. You should be able to quickly determine
|
||||
the new name from the old. e.g. `CONSTANT_NAME` to `kConstantName`.
|
||||
Use common sense or examining the library's code if this does affect code.
|
||||
|
||||
## Supported protocols
|
||||
You can find the details of which protocols & devices are supported
|
||||
[here](https://github.com/markszabo/IRremoteESP8266/blob/master/SupportedProtocols.md).
|
||||
|
||||
## Troubleshooting
|
||||
Before reporting an issue or asking for help, please try to follow our [Troubleshooting Guide](https://github.com/markszabo/IRremoteESP8266/wiki/Troubleshooting-Guide) first.
|
||||
|
||||
|
||||
127
SupportedProtocols.md
Normal file
127
SupportedProtocols.md
Normal file
@@ -0,0 +1,127 @@
|
||||
<!--- WARNING: Do NOT edit this file directly.
|
||||
It is generated by './tools/scrape_supported_devices.py'.
|
||||
Last generated: Sat Jun 15 13:29:53 2019 --->
|
||||
# IR Protocols supported by this library
|
||||
|
||||
| Protocol | Brand | Model | A/C Model | Detailed A/C Support |
|
||||
| --- | --- | --- | --- | --- |
|
||||
| [Aiwa](https://github.com/markszabo/IRremoteESP8266/blob/master/src/ir_Aiwa.cpp) | **Aiwa** | RC-T501 RCU | | - |
|
||||
| [Argo](https://github.com/markszabo/IRremoteESP8266/blob/master/src/ir_Argo.cpp) | **[Argo](https://github.com/markszabo/IRremoteESP8266/blob/master/src/ir_Argo.h)** | Ulisse 13 DCI Mobile Split A/C | | Yes |
|
||||
| [Carrier](https://github.com/markszabo/IRremoteESP8266/blob/master/src/ir_Carrier.cpp) | **Carrier/Surrey** | 42QG5A55970 remote<BR>53NGK009/012 Inverter<BR>619EGX0090E0 A/C<BR>619EGX0120E0 A/C<BR>619EGX0180E0 A/C<BR>619EGX0220E0 A/C | | - |
|
||||
| [Coolix](https://github.com/markszabo/IRremoteESP8266/blob/master/src/ir_Coolix.cpp) | **[Unknown](https://github.com/markszabo/IRremoteESP8266/blob/master/src/ir_Coolix.h)** | | | Yes |
|
||||
| [Daikin](https://github.com/markszabo/IRremoteESP8266/blob/master/src/ir_Daikin.cpp) | **[Daikin](https://github.com/markszabo/IRremoteESP8266/blob/master/src/ir_Daikin.h)** | ARC433** remote<BR>ARC433B69 remote<BR>ARC477A1 remote<BR>FTXZ25NV1B A/C<BR>FTXZ35NV1B A/C<BR>FTXZ50NV1B A/C | | Yes |
|
||||
| [Denon](https://github.com/markszabo/IRremoteESP8266/blob/master/src/ir_Denon.cpp) | **Unknown** | | | - |
|
||||
| [Dish](https://github.com/markszabo/IRremoteESP8266/blob/master/src/ir_Dish.cpp) | **DISH NETWORK** | echostar 301 | | - |
|
||||
| [Electra](https://github.com/markszabo/IRremoteESP8266/blob/master/src/ir_Electra.cpp) | **Unknown** | | | - |
|
||||
| [Fujitsu](https://github.com/markszabo/IRremoteESP8266/blob/master/src/ir_Fujitsu.cpp) | **[Fujitsu](https://github.com/markszabo/IRremoteESP8266/blob/master/src/ir_Fujitsu.h)** | AR-DB1 remote<BR>AR-RAE1E remote<BR>AR-RAH2E remote<BR>AR-REB1E remote<BR>AST9RSGCW A/C<BR>ASYG30LFCA A/C<BR>ASYG7LMCA A/C | ARDB1<BR>ARJW2<BR>ARRAH2E<BR>ARREB1E | Yes |
|
||||
| [Fujitsu](https://github.com/markszabo/IRremoteESP8266/blob/master/src/ir_Fujitsu.cpp) | **[Fujitsu General](https://github.com/markszabo/IRremoteESP8266/blob/master/src/ir_Fujitsu.h)** | AR-JW2 remote | ARDB1<BR>ARJW2<BR>ARRAH2E<BR>ARREB1E | Yes |
|
||||
| [GICable](https://github.com/markszabo/IRremoteESP8266/blob/master/src/ir_GICable.cpp) | **Unknown** | | | - |
|
||||
| [GlobalCache](https://github.com/markszabo/IRremoteESP8266/blob/master/src/ir_GlobalCache.cpp) | **Unknown** | | | - |
|
||||
| [Goodweather](https://github.com/markszabo/IRremoteESP8266/blob/master/src/ir_Goodweather.cpp) | **[Goodweather](https://github.com/markszabo/IRremoteESP8266/blob/master/src/ir_Goodweather.h)** | ZH/JT-03 remote | | Yes |
|
||||
| [Gree](https://github.com/markszabo/IRremoteESP8266/blob/master/src/ir_Gree.cpp) | **[EKOKAI](https://github.com/markszabo/IRremoteESP8266/blob/master/src/ir_Gree.h)** | A/C | | Yes |
|
||||
| [Gree](https://github.com/markszabo/IRremoteESP8266/blob/master/src/ir_Gree.cpp) | **[Ultimate](https://github.com/markszabo/IRremoteESP8266/blob/master/src/ir_Gree.h)** | Heat Pump | | Yes |
|
||||
| [Haier](https://github.com/markszabo/IRremoteESP8266/blob/master/src/ir_Haier.cpp) | **[Haier](https://github.com/markszabo/IRremoteESP8266/blob/master/src/ir_Haier.h)** | HSU-09HMC203 A/C<BR>HSU07-HEA03 remote<BR>YR-W02 remote | | Yes |
|
||||
| [Hitachi](https://github.com/markszabo/IRremoteESP8266/blob/master/src/ir_Hitachi.cpp) | **[Hitachi](https://github.com/markszabo/IRremoteESP8266/blob/master/src/ir_Hitachi.h)** | LT0541-HTA remote<BR>RAS-35THA6 remote<BR>Series VI A/C (Circa 2007) | | Yes |
|
||||
| [Inax](https://github.com/markszabo/IRremoteESP8266/blob/master/src/ir_Inax.cpp) | **Lixil** | Inax DT-BA283 Toilet | | - |
|
||||
| [JVC](https://github.com/markszabo/IRremoteESP8266/blob/master/src/ir_JVC.cpp) | **Unknown** | | | - |
|
||||
| [Kelvinator](https://github.com/markszabo/IRremoteESP8266/blob/master/src/ir_Kelvinator.cpp) | **[Kelvinator](https://github.com/markszabo/IRremoteESP8266/blob/master/src/ir_Kelvinator.h)** | KSV26CRC A/C<BR>KSV26HRC A/C<BR>KSV35CRC A/C<BR>KSV35HRC A/C<BR>KSV53HRC A/C<BR>KSV62HRC A/C<BR>KSV70CRC A/C<BR>KSV70HRC A/C<BR>KSV80HRC A/C<BR>YALIF Remote | | Yes |
|
||||
| [LG](https://github.com/markszabo/IRremoteESP8266/blob/master/src/ir_LG.cpp) | **[LG](https://github.com/markszabo/IRremoteESP8266/blob/master/src/ir_LG.h)** | 6711A20083V remote<BR>6711A20083V remote<BR>AKB74395308 remote<BR>AKB74395308 remote | | Yes |
|
||||
| [Lasertag](https://github.com/markszabo/IRremoteESP8266/blob/master/src/ir_Lasertag.cpp) | **Unknown** | | | - |
|
||||
| [Lego](https://github.com/markszabo/IRremoteESP8266/blob/master/src/ir_Lego.cpp) | **LEGO Power Functions** | IR Receiver | | - |
|
||||
| [Lutron](https://github.com/markszabo/IRremoteESP8266/blob/master/src/ir_Lutron.cpp) | **Unknown** | | | - |
|
||||
| [MWM](https://github.com/markszabo/IRremoteESP8266/blob/master/src/ir_MWM.cpp) | **Unknown** | | | - |
|
||||
| [Magiquest](https://github.com/markszabo/IRremoteESP8266/blob/master/src/ir_Magiquest.cpp) | **[Unknown](https://github.com/markszabo/IRremoteESP8266/blob/master/src/ir_Magiquest.h)** | | | Yes |
|
||||
| [Midea](https://github.com/markszabo/IRremoteESP8266/blob/master/src/ir_Midea.cpp) | **[Pioneer System](https://github.com/markszabo/IRremoteESP8266/blob/master/src/ir_Midea.h)** | RUBO18GMFILCAD A/C (18K BTU)<BR>RYBO12GMFILCAD A/C (12K BTU) | | Yes |
|
||||
| [Mitsubishi](https://github.com/markszabo/IRremoteESP8266/blob/master/src/ir_Mitsubishi.cpp) | **[Mitsubishi](https://github.com/markszabo/IRremoteESP8266/blob/master/src/ir_Mitsubishi.h)** | HC3000 Projector<BR>TV | | Yes |
|
||||
| [MitsubishiHeavy](https://github.com/markszabo/IRremoteESP8266/blob/master/src/ir_MitsubishiHeavy.cpp) | **[Mitsubishi Heavy Industries](https://github.com/markszabo/IRremoteESP8266/blob/master/src/ir_MitsubishiHeavy.h)** | RKX502A001C remote<BR>RLA502A700B remote<BR>SRKxxZJ-S A/C<BR>SRKxxZM-S A/C<BR>SRKxxZMXA-S A/C | | Yes |
|
||||
| [NEC](https://github.com/markszabo/IRremoteESP8266/blob/master/src/ir_NEC.cpp) | **[Unknown](https://github.com/markszabo/IRremoteESP8266/blob/master/src/ir_NEC.h)** | | | Yes |
|
||||
| [Nikai](https://github.com/markszabo/IRremoteESP8266/blob/master/src/ir_Nikai.cpp) | **Unknown** | | | - |
|
||||
| [Panasonic](https://github.com/markszabo/IRremoteESP8266/blob/master/src/ir_Panasonic.cpp) | **[Panasonic](https://github.com/markszabo/IRremoteESP8266/blob/master/src/ir_Panasonic.h)** | A75C2311 remote (CKP)<BR>A75C3704 remote<BR>A75C3747 remote<BR>A75C3747 remote<BR>A75C3747 remote<BR>A75C3747 remote<BR>CKP series A/C<BR>CS-ME10CKPG A/C<BR>CS-ME12CKPG A/C<BR>CS-ME14CKPG A/C<BR>CS-YW9MKD A/C<BR>CS-Z9RKR A/C<BR>DKE series A/C<BR>JKE series A/C<BR>NKE series A/C<BR>RKR series A/C<BR>TV | CKP<BR>DKE<BR>JKE<BR>LKE<BR>NKE<BR>RKR | Yes |
|
||||
| [Pioneer](https://github.com/markszabo/IRremoteESP8266/blob/master/src/ir_Pioneer.cpp) | **Unknown** | | | - |
|
||||
| [Pronto](https://github.com/markszabo/IRremoteESP8266/blob/master/src/ir_Pronto.cpp) | **Unknown** | | | - |
|
||||
| [RC5_RC6](https://github.com/markszabo/IRremoteESP8266/blob/master/src/ir_RC5_RC6.cpp) | **Unknown** | | | - |
|
||||
| [RCMM](https://github.com/markszabo/IRremoteESP8266/blob/master/src/ir_RCMM.cpp) | **Microsoft** | XBOX 360 | | - |
|
||||
| [Samsung](https://github.com/markszabo/IRremoteESP8266/blob/master/src/ir_Samsung.cpp) | **[Samsung](https://github.com/markszabo/IRremoteESP8266/blob/master/src/ir_Samsung.h)** | AR12KSFPEWQNET A/C<BR>IEC-R03 remote<BR>UA55H6300 TV | | Yes |
|
||||
| [Sanyo](https://github.com/markszabo/IRremoteESP8266/blob/master/src/ir_Sanyo.cpp) | **Unknown** | | | - |
|
||||
| [Sharp](https://github.com/markszabo/IRremoteESP8266/blob/master/src/ir_Sharp.cpp) | **[Sharp](https://github.com/markszabo/IRremoteESP8266/blob/master/src/ir_Sharp.h)** | AY-ZP40KR A/C<BR>LC-52D62U TV | | Yes |
|
||||
| [Sherwood](https://github.com/markszabo/IRremoteESP8266/blob/master/src/ir_Sherwood.cpp) | **Sherwood** | RC-138 remote<BR>RD6505(B) Receiver | | - |
|
||||
| [Sony](https://github.com/markszabo/IRremoteESP8266/blob/master/src/ir_Sony.cpp) | **Unknown** | | | - |
|
||||
| [Tcl](https://github.com/markszabo/IRremoteESP8266/blob/master/src/ir_Tcl.cpp) | **[Unknown](https://github.com/markszabo/IRremoteESP8266/blob/master/src/ir_Tcl.h)** | | | Yes |
|
||||
| [Teco](https://github.com/markszabo/IRremoteESP8266/blob/master/src/ir_Teco.cpp) | **[Unknown](https://github.com/markszabo/IRremoteESP8266/blob/master/src/ir_Teco.h)** | | | Yes |
|
||||
| [Toshiba](https://github.com/markszabo/IRremoteESP8266/blob/master/src/ir_Toshiba.cpp) | **[Toshiba](https://github.com/markszabo/IRremoteESP8266/blob/master/src/ir_Toshiba.h)** | Akita EVO II<BR>RAS 18SKP-ES<BR>RAS-B13N3KV2<BR>RAS-B13N3KVP-E<BR>WC-L03SE<BR>WH-TA04NE | | Yes |
|
||||
| [Trotec](https://github.com/markszabo/IRremoteESP8266/blob/master/src/ir_Trotec.cpp) | **[Unknown](https://github.com/markszabo/IRremoteESP8266/blob/master/src/ir_Trotec.h)** | | | Yes |
|
||||
| [Vestel](https://github.com/markszabo/IRremoteESP8266/blob/master/src/ir_Vestel.cpp) | **[Vestel](https://github.com/markszabo/IRremoteESP8266/blob/master/src/ir_Vestel.h)** | BIOX CXP-9 A/C (9K BTU) | | Yes |
|
||||
| [Whirlpool](https://github.com/markszabo/IRremoteESP8266/blob/master/src/ir_Whirlpool.cpp) | **[Whirlpool](https://github.com/markszabo/IRremoteESP8266/blob/master/src/ir_Whirlpool.h)** | DG11J1-04 remote<BR>DG11J1-3A remote<BR>DG11J1-91 remote<BR>SPIS409L A/C<BR>SPIS412L A/C<BR>SPIW409L A/C<BR>SPIW412L A/C<BR>SPIW418L A/C | DG11J13A<BR>DG11J191 | Yes |
|
||||
| [Whynter](https://github.com/markszabo/IRremoteESP8266/blob/master/src/ir_Whynter.cpp) | **Whynter** | ARC-110WD A/C | | - |
|
||||
|
||||
|
||||
## Send only protocols:
|
||||
|
||||
- GLOBALCACHE
|
||||
- PRONTO
|
||||
- RAW
|
||||
- SHERWOOD
|
||||
|
||||
|
||||
## Send & decodable protocols:
|
||||
|
||||
- AIWA_RC_T501
|
||||
- ARGO
|
||||
- CARRIER_AC
|
||||
- COOLIX
|
||||
- DAIKIN
|
||||
- DAIKIN2
|
||||
- DAIKIN216
|
||||
- DENON
|
||||
- DISH
|
||||
- ELECTRA_AC
|
||||
- FUJITSU_AC
|
||||
- GICABLE
|
||||
- GOODWEATHER
|
||||
- GREE
|
||||
- HAIER_AC
|
||||
- HAIER_AC_YRW02
|
||||
- HITACHI_AC
|
||||
- HITACHI_AC1
|
||||
- HITACHI_AC2
|
||||
- INAX
|
||||
- JVC
|
||||
- KELVINATOR
|
||||
- LASERTAG
|
||||
- LEGOPF
|
||||
- LG
|
||||
- LG2
|
||||
- LUTRON
|
||||
- MAGIQUEST
|
||||
- MIDEA
|
||||
- MITSUBISHI
|
||||
- MITSUBISHI2
|
||||
- MITSUBISHI_AC
|
||||
- MITSUBISHI_HEAVY_152
|
||||
- MITSUBISHI_HEAVY_88
|
||||
- MWM
|
||||
- NEC
|
||||
- NEC_LIKE
|
||||
- NIKAI
|
||||
- PANASONIC
|
||||
- PANASONIC_AC
|
||||
- PIONEER
|
||||
- RC5
|
||||
- RC5X
|
||||
- RC6
|
||||
- RCMM
|
||||
- SAMSUNG
|
||||
- SAMSUNG36
|
||||
- SAMSUNG_AC
|
||||
- SANYO
|
||||
- SANYO_LC7461
|
||||
- SHARP
|
||||
- SHARP_AC
|
||||
- SONY
|
||||
- TCL112AC
|
||||
- TECO
|
||||
- TOSHIBA_AC
|
||||
- TROTEC
|
||||
- VESTEL_AC
|
||||
- WHIRLPOOL_AC
|
||||
- WHYNTER
|
||||
@@ -1,7 +1,7 @@
|
||||
// Copyright 2016 David Conran
|
||||
// Gree A/C
|
||||
//
|
||||
// Supported:
|
||||
// Supports:
|
||||
// Brand: Ultimate, Model: Heat Pump
|
||||
// Brand: EKOKAI, Model: A/C
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
// Copyright 2018 crankyoldgit
|
||||
// The specifics of reverse engineering the protocol details by kuzin2006
|
||||
|
||||
// Supported:
|
||||
// Supports:
|
||||
// Brand: Haier, Model: HSU07-HEA03 remote
|
||||
// Brand: Haier, Model: YR-W02 remote
|
||||
// Brand: Haier, Model: HSU-09HMC203 A/C
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
//
|
||||
// Copyright 2018 David Conran
|
||||
|
||||
// Supported:
|
||||
// Supports:
|
||||
// Brand: Hitachi, Model: RAS-35THA6 remote
|
||||
// Brand: Hitachi, Model: LT0541-HTA remote
|
||||
// Brand: Hitachi, Model: Series VI A/C (Circa 2007)
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
//
|
||||
// Copyright 2016 David Conran
|
||||
|
||||
// Supported:
|
||||
// Supports:
|
||||
// Brand: Kelvinator, Model: YALIF Remote
|
||||
// Brand: Kelvinator, Model: KSV26CRC A/C
|
||||
// Brand: Kelvinator, Model: KSV26HRC A/C
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
// Copyright 2015 cheaplin
|
||||
// Copyright 2017, 2018 David Conran
|
||||
|
||||
// Supported:
|
||||
// Supports:
|
||||
// Brand: LG, Model: 6711A20083V remote
|
||||
// Brand: LG, Model: AKB74395308 remote
|
||||
|
||||
|
||||
@@ -1,18 +1,12 @@
|
||||
// Copyright 2017 David Conran
|
||||
|
||||
// Supported:
|
||||
// Supports:
|
||||
// Brand: LG, Model: 6711A20083V remote
|
||||
// Brand: LG, Model: AKB74395308 remote
|
||||
|
||||
#ifndef IR_LG_H_
|
||||
#define IR_LG_H_
|
||||
|
||||
// L GGGG
|
||||
// L G
|
||||
// L G GG
|
||||
// L G G
|
||||
// LLLLL GGG
|
||||
|
||||
#define __STDC_LIMIT_MACROS
|
||||
#include <stdint.h>
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
// LEGO
|
||||
// (LEGO is a Registrated Trademark of the Lego Group.)
|
||||
//
|
||||
// Supported:
|
||||
// Supports:
|
||||
// Brand: LEGO Power Functions, Model: IR Receiver
|
||||
//
|
||||
// Ref:
|
||||
|
||||
@@ -29,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; \
|
||||
|
||||
@@ -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,
|
||||
|
||||
255
tools/scrape_supported_devices.py
Executable file
255
tools/scrape_supported_devices.py
Executable file
@@ -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()
|
||||
Reference in New Issue
Block a user