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.
@@ -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,3 @@
1
+ from .lookup import ACModelLookup
2
+
3
+ __all__ = ["ACModelLookup"]
@@ -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
+ }