panasonic-ac-models 1.0.0b7__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- panasonic_ac_models-1.0.0b7/PKG-INFO +110 -0
- panasonic_ac_models-1.0.0b7/README.md +95 -0
- panasonic_ac_models-1.0.0b7/panasonic_ac_models/__init__.py +3 -0
- panasonic_ac_models-1.0.0b7/panasonic_ac_models/decoder.py +59 -0
- panasonic_ac_models-1.0.0b7/panasonic_ac_models/lookup.py +62 -0
- panasonic_ac_models-1.0.0b7/panasonic_ac_models/models.json +3512 -0
- panasonic_ac_models-1.0.0b7/panasonic_ac_models.egg-info/PKG-INFO +110 -0
- panasonic_ac_models-1.0.0b7/panasonic_ac_models.egg-info/SOURCES.txt +10 -0
- panasonic_ac_models-1.0.0b7/panasonic_ac_models.egg-info/dependency_links.txt +1 -0
- panasonic_ac_models-1.0.0b7/panasonic_ac_models.egg-info/top_level.txt +1 -0
- panasonic_ac_models-1.0.0b7/pyproject.toml +31 -0
- panasonic_ac_models-1.0.0b7/setup.cfg +4 -0
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: panasonic_ac_models
|
|
3
|
+
Version: 1.0.0b7
|
|
4
|
+
Summary: Hardware database and feature gating lookup engine for Panasonic Smart ACs (Indian Market / MirAIe IoT)
|
|
5
|
+
Author-email: selvakk2k <selvakk2k@users.noreply.github.com>
|
|
6
|
+
License: MIT
|
|
7
|
+
Project-URL: Homepage, https://github.com/selvakk2k/panasonic-ac-models
|
|
8
|
+
Project-URL: Documentation, https://github.com/selvakk2k/panasonic-ac-models#readme
|
|
9
|
+
Project-URL: Repository, https://github.com/selvakk2k/panasonic-ac-models.git
|
|
10
|
+
Classifier: Programming Language :: Python :: 3
|
|
11
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
12
|
+
Classifier: Operating System :: OS Independent
|
|
13
|
+
Requires-Python: >=3.9
|
|
14
|
+
Description-Content-Type: text/markdown
|
|
15
|
+
|
|
16
|
+
# panasonic-ac-models
|
|
17
|
+
|
|
18
|
+
A model capability database and lookup engine for Panasonic Smart Air Conditioners (Indian Market / MirAIe platform). Designed for Home Assistant custom integrations, companion libraries, and custom dashboard cards to dynamically determine supported AC features (HVAC modes, Nanoe ionizer, Converti presets).
|
|
19
|
+
|
|
20
|
+
---
|
|
21
|
+
|
|
22
|
+
## Installation & Usage
|
|
23
|
+
|
|
24
|
+
### Python Library (Backend / Home Assistant Integrations)
|
|
25
|
+
|
|
26
|
+
Install via `pip`:
|
|
27
|
+
|
|
28
|
+
```bash
|
|
29
|
+
pip install git+https://github.com/selvakk2k/panasonic-ac-models.git
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
Query AC capabilities using the normalized lookup engine:
|
|
33
|
+
|
|
34
|
+
```python
|
|
35
|
+
from panasonic_ac_models import ACModelLookup
|
|
36
|
+
|
|
37
|
+
lookup = ACModelLookup()
|
|
38
|
+
|
|
39
|
+
# Query any indoor unit SKU (handles 'CS/CU-', casing, and spaces automatically)
|
|
40
|
+
caps = lookup.get_capabilities("CS/CU-EZ18BKYD")
|
|
41
|
+
|
|
42
|
+
print(caps["series"]) # "EZ"
|
|
43
|
+
print(caps["has_heat_mode"]) # 1 (Dual Heat Pump)
|
|
44
|
+
print(caps["converti_type"]) # "7-in-1"
|
|
45
|
+
|
|
46
|
+
# Dynamic feature gating
|
|
47
|
+
hvac_modes = ["cool", "heat", "off"] if caps["has_heat_mode"] == 1 else ["cool", "off"]
|
|
48
|
+
show_nanoe = (caps["has_nanoe"] == 1)
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
---
|
|
52
|
+
|
|
53
|
+
### Direct CDN (JavaScript / Frontend Cards)
|
|
54
|
+
|
|
55
|
+
Fetch `models.json` directly via jsDelivr CDN:
|
|
56
|
+
|
|
57
|
+
```
|
|
58
|
+
https://cdn.jsdelivr.net/gh/selvakk2k/panasonic-ac-models@main/models.json
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
```javascript
|
|
62
|
+
fetch("https://cdn.jsdelivr.net/gh/selvakk2k/panasonic-ac-models@main/models.json")
|
|
63
|
+
.then(res => res.json())
|
|
64
|
+
.then(data => {
|
|
65
|
+
const rawModel = "CS/CU-NU18AKY4WXD";
|
|
66
|
+
const cleanModel = rawModel.replace(/^(CS\/CU|CU)[-_\s]?/i, 'CS-').trim().toUpperCase();
|
|
67
|
+
|
|
68
|
+
const family = data.families.find(f => f.indoor_units.includes(cleanModel));
|
|
69
|
+
console.log("Heat Mode:", family?.has_heat_mode);
|
|
70
|
+
console.log("Converti Mode:", family?.converti_type);
|
|
71
|
+
});
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
---
|
|
75
|
+
|
|
76
|
+
## Feature Gating Rules
|
|
77
|
+
|
|
78
|
+
| Feature | Condition | Series / Generations |
|
|
79
|
+
|---|---|---|
|
|
80
|
+
| Wi-Fi / MirAIe | All Inverter Splits | NU, SU, EU, AU, HU, XU, EZ, KZ, WU, QU, YU, RU, TU, VU, ZU, LU, S-##PUY |
|
|
81
|
+
| Non-Smart | Fixed Speed / Window | KN, KU, CW-, PUB, PD |
|
|
82
|
+
| Heat Mode | Dual Heat Pump | EZ, KZ only |
|
|
83
|
+
| Nanoe Ionizer | Purification Models | HU, XU only |
|
|
84
|
+
| Converti 8-in-1 | 2026+ Models | NU/SU (Gen ≥ B) & EZ/HU/EU (Gen ≥ C) |
|
|
85
|
+
| Converti 7-in-1 | 2023–2025 Models | All other 2023–2025 inverter splits |
|
|
86
|
+
| Auto-Convertible (none) | Pre-2023 Models | 2020–2022 models (Gen W, X - sensor auto-scaling, no manual percentage buttons) |
|
|
87
|
+
|
|
88
|
+
---
|
|
89
|
+
|
|
90
|
+
## Database Summary
|
|
91
|
+
|
|
92
|
+
- **Models Tracked**: 403 verified Wi-Fi models across 116 hardware families.
|
|
93
|
+
- **Data Sources**: Bureau of Energy Efficiency (BEE) certified labels, Panasonic India catalogs, empirical MirAIe telemetry.
|
|
94
|
+
|
|
95
|
+
---
|
|
96
|
+
|
|
97
|
+
## Contributing
|
|
98
|
+
|
|
99
|
+
Pull requests are welcome! To add or correct a model:
|
|
100
|
+
|
|
101
|
+
1. Edit `models.json`.
|
|
102
|
+
2. Add the indoor SKU to the appropriate `indoor_units` array under `families`.
|
|
103
|
+
3. Submit a PR. Continuous Integration (`check-jsonschema`) will validate changes against `schema.json`.
|
|
104
|
+
|
|
105
|
+
---
|
|
106
|
+
|
|
107
|
+
## Authors & Credits
|
|
108
|
+
|
|
109
|
+
- **Lead Maintainer**: [@selvakk2k](https://github.com/selvakk2k)
|
|
110
|
+
- **AI Pair Programming & Architecture**: Antigravity (Google DeepMind Team)
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
# panasonic-ac-models
|
|
2
|
+
|
|
3
|
+
A model capability database and lookup engine for Panasonic Smart Air Conditioners (Indian Market / MirAIe platform). Designed for Home Assistant custom integrations, companion libraries, and custom dashboard cards to dynamically determine supported AC features (HVAC modes, Nanoe ionizer, Converti presets).
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## Installation & Usage
|
|
8
|
+
|
|
9
|
+
### Python Library (Backend / Home Assistant Integrations)
|
|
10
|
+
|
|
11
|
+
Install via `pip`:
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
pip install git+https://github.com/selvakk2k/panasonic-ac-models.git
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
Query AC capabilities using the normalized lookup engine:
|
|
18
|
+
|
|
19
|
+
```python
|
|
20
|
+
from panasonic_ac_models import ACModelLookup
|
|
21
|
+
|
|
22
|
+
lookup = ACModelLookup()
|
|
23
|
+
|
|
24
|
+
# Query any indoor unit SKU (handles 'CS/CU-', casing, and spaces automatically)
|
|
25
|
+
caps = lookup.get_capabilities("CS/CU-EZ18BKYD")
|
|
26
|
+
|
|
27
|
+
print(caps["series"]) # "EZ"
|
|
28
|
+
print(caps["has_heat_mode"]) # 1 (Dual Heat Pump)
|
|
29
|
+
print(caps["converti_type"]) # "7-in-1"
|
|
30
|
+
|
|
31
|
+
# Dynamic feature gating
|
|
32
|
+
hvac_modes = ["cool", "heat", "off"] if caps["has_heat_mode"] == 1 else ["cool", "off"]
|
|
33
|
+
show_nanoe = (caps["has_nanoe"] == 1)
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
---
|
|
37
|
+
|
|
38
|
+
### Direct CDN (JavaScript / Frontend Cards)
|
|
39
|
+
|
|
40
|
+
Fetch `models.json` directly via jsDelivr CDN:
|
|
41
|
+
|
|
42
|
+
```
|
|
43
|
+
https://cdn.jsdelivr.net/gh/selvakk2k/panasonic-ac-models@main/models.json
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
```javascript
|
|
47
|
+
fetch("https://cdn.jsdelivr.net/gh/selvakk2k/panasonic-ac-models@main/models.json")
|
|
48
|
+
.then(res => res.json())
|
|
49
|
+
.then(data => {
|
|
50
|
+
const rawModel = "CS/CU-NU18AKY4WXD";
|
|
51
|
+
const cleanModel = rawModel.replace(/^(CS\/CU|CU)[-_\s]?/i, 'CS-').trim().toUpperCase();
|
|
52
|
+
|
|
53
|
+
const family = data.families.find(f => f.indoor_units.includes(cleanModel));
|
|
54
|
+
console.log("Heat Mode:", family?.has_heat_mode);
|
|
55
|
+
console.log("Converti Mode:", family?.converti_type);
|
|
56
|
+
});
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
---
|
|
60
|
+
|
|
61
|
+
## Feature Gating Rules
|
|
62
|
+
|
|
63
|
+
| Feature | Condition | Series / Generations |
|
|
64
|
+
|---|---|---|
|
|
65
|
+
| Wi-Fi / MirAIe | All Inverter Splits | NU, SU, EU, AU, HU, XU, EZ, KZ, WU, QU, YU, RU, TU, VU, ZU, LU, S-##PUY |
|
|
66
|
+
| Non-Smart | Fixed Speed / Window | KN, KU, CW-, PUB, PD |
|
|
67
|
+
| Heat Mode | Dual Heat Pump | EZ, KZ only |
|
|
68
|
+
| Nanoe Ionizer | Purification Models | HU, XU only |
|
|
69
|
+
| Converti 8-in-1 | 2026+ Models | NU/SU (Gen ≥ B) & EZ/HU/EU (Gen ≥ C) |
|
|
70
|
+
| Converti 7-in-1 | 2023–2025 Models | All other 2023–2025 inverter splits |
|
|
71
|
+
| Auto-Convertible (none) | Pre-2023 Models | 2020–2022 models (Gen W, X - sensor auto-scaling, no manual percentage buttons) |
|
|
72
|
+
|
|
73
|
+
---
|
|
74
|
+
|
|
75
|
+
## Database Summary
|
|
76
|
+
|
|
77
|
+
- **Models Tracked**: 403 verified Wi-Fi models across 116 hardware families.
|
|
78
|
+
- **Data Sources**: Bureau of Energy Efficiency (BEE) certified labels, Panasonic India catalogs, empirical MirAIe telemetry.
|
|
79
|
+
|
|
80
|
+
---
|
|
81
|
+
|
|
82
|
+
## Contributing
|
|
83
|
+
|
|
84
|
+
Pull requests are welcome! To add or correct a model:
|
|
85
|
+
|
|
86
|
+
1. Edit `models.json`.
|
|
87
|
+
2. Add the indoor SKU to the appropriate `indoor_units` array under `families`.
|
|
88
|
+
3. Submit a PR. Continuous Integration (`check-jsonschema`) will validate changes against `schema.json`.
|
|
89
|
+
|
|
90
|
+
---
|
|
91
|
+
|
|
92
|
+
## Authors & Credits
|
|
93
|
+
|
|
94
|
+
- **Lead Maintainer**: [@selvakk2k](https://github.com/selvakk2k)
|
|
95
|
+
- **AI Pair Programming & Architecture**: Antigravity (Google DeepMind Team)
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import re
|
|
2
|
+
from typing import Dict, Any, Optional
|
|
3
|
+
|
|
4
|
+
PANASONIC_MODEL_REGEX = re.compile(
|
|
5
|
+
r"^(?:CS/CU|CS|CU|S)?[-_\s]?"
|
|
6
|
+
r"(?P<series>[A-Z]{2})"
|
|
7
|
+
r"(?P<capacity>\d{2})"
|
|
8
|
+
r"(?P<gen>[A-Z])"
|
|
9
|
+
r"(?:KY)?"
|
|
10
|
+
r"(?P<rating>\d)?"
|
|
11
|
+
r"(?P<suffix>[A-Z0-9-]*)$",
|
|
12
|
+
re.IGNORECASE
|
|
13
|
+
)
|
|
14
|
+
|
|
15
|
+
CAPACITY_MAP = {
|
|
16
|
+
"09": "0.75T",
|
|
17
|
+
"11": "0.9T",
|
|
18
|
+
"12": "1T",
|
|
19
|
+
"17": "1.4T",
|
|
20
|
+
"18": "1.5T",
|
|
21
|
+
"24": "2T",
|
|
22
|
+
"26": "2.2T",
|
|
23
|
+
"30": "2.5T",
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
HEAT_MODE_SERIES = {"EZ", "KZ"}
|
|
27
|
+
NANOE_SERIES = {"HU", "XU"}
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
def decode_model_string(model_code: str) -> Optional[Dict[str, Any]]:
|
|
31
|
+
"""Parses capability flags from a Panasonic AC model code string via deterministic rules."""
|
|
32
|
+
match = PANASONIC_MODEL_REGEX.match(model_code.strip().upper())
|
|
33
|
+
if not match:
|
|
34
|
+
return None
|
|
35
|
+
|
|
36
|
+
data = match.groupdict()
|
|
37
|
+
series = data["series"]
|
|
38
|
+
gen = data["gen"]
|
|
39
|
+
|
|
40
|
+
# Converti Generation Logic: Gen >= B/C receives 8-in-1; Gen Y/Z/A receives 7-in-1; older -> none
|
|
41
|
+
if gen in {"B", "C"}:
|
|
42
|
+
converti = "8-in-1"
|
|
43
|
+
elif gen in {"Y", "Z", "A"}:
|
|
44
|
+
converti = "7-in-1"
|
|
45
|
+
else:
|
|
46
|
+
converti = "none"
|
|
47
|
+
|
|
48
|
+
return {
|
|
49
|
+
"family_key": f"{series}-{data['capacity']}-{gen}",
|
|
50
|
+
"series": series,
|
|
51
|
+
"generation": gen,
|
|
52
|
+
"capacity_class": CAPACITY_MAP.get(data["capacity"], f"{data['capacity']} Ton"),
|
|
53
|
+
"speed_type": "variable",
|
|
54
|
+
"has_wifi": 1,
|
|
55
|
+
"has_heat_mode": 1 if series in HEAT_MODE_SERIES else 0,
|
|
56
|
+
"has_nanoe": 1 if series in NANOE_SERIES else 0,
|
|
57
|
+
"converti_type": converti,
|
|
58
|
+
"resolved_via": "regex_decoder"
|
|
59
|
+
}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import json
|
|
2
|
+
import os
|
|
3
|
+
import re
|
|
4
|
+
from typing import Dict, Any, Optional
|
|
5
|
+
from .decoder import decode_model_string
|
|
6
|
+
|
|
7
|
+
PKG_DIR = os.path.dirname(__file__)
|
|
8
|
+
PARENT_DIR = os.path.dirname(PKG_DIR)
|
|
9
|
+
|
|
10
|
+
DEFAULT_JSON_PATH = os.path.join(PKG_DIR, "models.json")
|
|
11
|
+
if not os.path.exists(DEFAULT_JSON_PATH):
|
|
12
|
+
DEFAULT_JSON_PATH = os.path.join(PARENT_DIR, "models.json")
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
def normalize_code(raw_code: str) -> str:
|
|
16
|
+
"""Normalizes input model strings (e.g. 'cs/cu-su18aky3w' -> 'CS-SU18AKY3W')."""
|
|
17
|
+
cleaned = raw_code.strip().upper()
|
|
18
|
+
cleaned = re.sub(r'^(CS/CU|CU)[-_\s]?', 'CS-', cleaned)
|
|
19
|
+
if not cleaned.startswith('CS-') and not cleaned.startswith('S-'):
|
|
20
|
+
cleaned = f"CS-{cleaned}"
|
|
21
|
+
return cleaned
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
class ACModelLookup:
|
|
25
|
+
"""O(1) normalized lookup engine for Panasonic AC models."""
|
|
26
|
+
|
|
27
|
+
def __init__(self, json_path: Optional[str] = None):
|
|
28
|
+
path = json_path or DEFAULT_JSON_PATH
|
|
29
|
+
with open(path, "r", encoding="utf-8") as f:
|
|
30
|
+
self.db = json.load(f)
|
|
31
|
+
|
|
32
|
+
# O(1) Normalized Lookup Index
|
|
33
|
+
self._index: Dict[str, Dict[str, Any]] = {}
|
|
34
|
+
for family in self.db.get("families", []):
|
|
35
|
+
for unit in family.get("indoor_units", []):
|
|
36
|
+
norm = normalize_code(unit)
|
|
37
|
+
self._index[norm] = family
|
|
38
|
+
|
|
39
|
+
def get_capabilities(self, model_code: str) -> Dict[str, Any]:
|
|
40
|
+
"""Resolves capability flags using exact index matching or regex decoding."""
|
|
41
|
+
norm = normalize_code(model_code)
|
|
42
|
+
|
|
43
|
+
# 1. Exact Match from Index
|
|
44
|
+
if norm in self._index:
|
|
45
|
+
result = dict(self._index[norm])
|
|
46
|
+
result["resolved_via"] = "database"
|
|
47
|
+
return result
|
|
48
|
+
|
|
49
|
+
# 2. Dynamic Fallback
|
|
50
|
+
dynamic = decode_model_string(model_code)
|
|
51
|
+
if dynamic:
|
|
52
|
+
return dynamic
|
|
53
|
+
|
|
54
|
+
# 3. Default Safe Fallback
|
|
55
|
+
return {
|
|
56
|
+
"family_key": "UNKNOWN",
|
|
57
|
+
"has_wifi": 1,
|
|
58
|
+
"has_heat_mode": 0,
|
|
59
|
+
"has_nanoe": 0,
|
|
60
|
+
"converti_type": "7-in-1",
|
|
61
|
+
"resolved_via": "safe_default"
|
|
62
|
+
}
|