From 9b5fecd400c62c5f7461abb50a2442fc02357ee2 Mon Sep 17 00:00:00 2001 From: Nick Date: Mon, 27 Oct 2025 20:19:10 +0100 Subject: [PATCH] improved cache logic --- .tf5_mixer_cache/channels_cache.json | 66 +++++++++---------- __pycache__/mixer_controller.cpython-312.pyc | Bin 31355 -> 33041 bytes mixer_controller.py | 55 +++++++++++++--- 3 files changed, 79 insertions(+), 42 deletions(-) diff --git a/.tf5_mixer_cache/channels_cache.json b/.tf5_mixer_cache/channels_cache.json index be269e5..35d9786 100644 --- a/.tf5_mixer_cache/channels_cache.json +++ b/.tf5_mixer_cache/channels_cache.json @@ -11,21 +11,21 @@ "channel": 2, "name": "Gelato", "on": true, - "level_db": -6.25, + "level_db": -0.25, "pan": 0 }, "3": { "channel": 3, "name": "Talkback", "on": true, - "level_db": -Infinity, + "level_db": null, "pan": 0 }, "4": { "channel": 4, "name": "Sconosciuto", "on": false, - "level_db": -Infinity, + "level_db": null, "pan": 0 }, "5": { @@ -46,91 +46,91 @@ "channel": 7, "name": "Basso", "on": false, - "level_db": -Infinity, + "level_db": null, "pan": 0 }, "8": { "channel": 8, "name": "Sconosciuto", "on": false, - "level_db": -Infinity, + "level_db": null, "pan": 0 }, "9": { "channel": 9, "name": "Kick", "on": true, - "level_db": -Infinity, + "level_db": null, "pan": 0 }, "10": { "channel": 10, "name": "Snare", "on": true, - "level_db": -Infinity, + "level_db": null, "pan": 0 }, "11": { "channel": 11, "name": "Tom 1", "on": true, - "level_db": -Infinity, + "level_db": null, "pan": 0 }, "12": { "channel": 12, "name": "Tom 2", "on": true, - "level_db": -Infinity, + "level_db": null, "pan": 0 }, "13": { "channel": 13, "name": "Tom3", "on": true, - "level_db": -Infinity, + "level_db": null, "pan": 0 }, "14": { "channel": 14, "name": "Pan SX", "on": true, - "level_db": -Infinity, + "level_db": null, "pan": 0 }, "15": { "channel": 15, "name": "Pan dx", "on": true, - "level_db": -Infinity, + "level_db": null, "pan": 0 }, "16": { "channel": 16, "name": "Sconosciuto", "on": false, - "level_db": -Infinity, + "level_db": null, "pan": 0 }, "17": { "channel": 17, "name": "Sconosciuto", "on": false, - "level_db": -Infinity, + "level_db": null, "pan": 0 }, "18": { "channel": 18, "name": "Archetto", "on": false, - "level_db": -Infinity, + "level_db": null, "pan": 0 }, "19": { "channel": 19, "name": "Vox 5", "on": false, - "level_db": -Infinity, + "level_db": null, "pan": 0 }, "20": { @@ -144,14 +144,14 @@ "channel": 21, "name": "Sconosciuto", "on": false, - "level_db": -Infinity, + "level_db": null, "pan": 0 }, "22": { "channel": 22, "name": "Sconosciuto", "on": false, - "level_db": -Infinity, + "level_db": null, "pan": 0 }, "23": { @@ -179,7 +179,7 @@ "channel": 26, "name": "Sconosciuto", "on": false, - "level_db": -Infinity, + "level_db": null, "pan": 0 }, "27": { @@ -193,35 +193,35 @@ "channel": 28, "name": "Sconosciuto", "on": false, - "level_db": -Infinity, + "level_db": null, "pan": 0 }, "29": { "channel": 29, "name": "Pad", "on": true, - "level_db": -Infinity, + "level_db": null, "pan": 0 }, "30": { "channel": 30, "name": "Sconosciuto", "on": false, - "level_db": -Infinity, + "level_db": null, "pan": 0 }, "31": { "channel": 31, "name": "Sconosciuto", "on": false, - "level_db": -Infinity, + "level_db": null, "pan": 0 }, "32": { "channel": 32, "name": "Sconosciuto", "on": false, - "level_db": -Infinity, + "level_db": null, "pan": 0 }, "33": { @@ -242,42 +242,42 @@ "channel": 35, "name": "ch35", "on": true, - "level_db": -Infinity, + "level_db": null, "pan": 0 }, "36": { "channel": 36, "name": "ch36", "on": true, - "level_db": -Infinity, + "level_db": null, "pan": 0 }, "37": { "channel": 37, "name": "ch37", "on": true, - "level_db": -Infinity, + "level_db": null, "pan": 0 }, "38": { "channel": 38, "name": "ch38", "on": true, - "level_db": -Infinity, + "level_db": null, "pan": 0 }, "39": { "channel": 39, "name": "ch39", "on": true, - "level_db": -Infinity, + "level_db": null, "pan": 0 }, "40": { "channel": 40, "name": "ch40", "on": true, - "level_db": -Infinity, + "level_db": null, "pan": 0 } }, @@ -286,7 +286,7 @@ "mix": 1, "name": "Sinistro", "on": true, - "level_db": -Infinity + "level_db": null }, "2": { "mix": 2, @@ -310,7 +310,7 @@ "mix": 5, "name": "batteria", "on": true, - "level_db": 1.35 + "level_db": 1.1 }, "6": { "mix": 6, @@ -403,5 +403,5 @@ "level_db": 6.0 } }, - "timestamp": 1761592356.5132928 + "timestamp": 1761592662.917339 } \ No newline at end of file diff --git a/__pycache__/mixer_controller.cpython-312.pyc b/__pycache__/mixer_controller.cpython-312.pyc index 21741aba802e0706e769971ff02a8f4f0c36fae0..b886b948eb559113a78d5c8eee9c0ade79234569 100644 GIT binary patch delta 6285 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 K?r?}KHvbp&KMaBZ delta 4693 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 Jf`G_x?_V$JX*mD@ diff --git a/mixer_controller.py b/mixer_controller.py index 8c1b4b5..cc3e3df 100644 --- a/mixer_controller.py +++ b/mixer_controller.py @@ -63,7 +63,7 @@ class TF5MixerController: except socket.error as e: print(f'Errore di connessione dopo {max_retries} tentativi: {e}') - self._disconnect() # Forza riconnessione al prossimo tentativo + self._disconnect() if attempt < max_retries - 1: time.sleep(0.1) @@ -98,13 +98,30 @@ class TF5MixerController: return {"channels": {}, "mixes": {}, "timestamp": 0} def _save_cache(self): - """Salva la cache nel file.""" + """Salva la cache nel file, convertendo -inf in null.""" try: + # Crea una copia della cache per la serializzazione + cache_to_save = self._prepare_cache_for_json(self._cache) + with open(CACHE_FILE, 'w', encoding='utf-8') as f: - json.dump(self._cache, f, indent=2, ensure_ascii=False) + json.dump(cache_to_save, f, indent=2, ensure_ascii=False) except Exception as e: print(f"⚠️ Errore nel salvataggio della cache: {e}") + def _prepare_cache_for_json(self, obj): + """Converte ricorsivamente -inf in null per la serializzazione JSON.""" + if isinstance(obj, dict): + return {k: self._prepare_cache_for_json(v) for k, v in obj.items()} + elif isinstance(obj, list): + return [self._prepare_cache_for_json(item) for item in obj] + elif isinstance(obj, float): + # Converti -inf in null per JSON + if obj == float('-inf'): + return None + return obj + else: + return obj + def _is_cache_valid(self) -> bool: """Verifica se la cache è ancora valida.""" if not self._cache.get("channels"): @@ -112,6 +129,12 @@ class TF5MixerController: cache_age = time.time() - self._cache.get("timestamp", 0) return cache_age < CACHE_DURATION + def _normalize_level_from_cache(self, level_value): + """Normalizza il valore del livello dalla cache (gestisce None come -inf).""" + if level_value is None: + return float('-inf') + return level_value + def _update_channel_cache(self, channel: int): """Aggiorna la cache per un singolo canale leggendo dal mixer. @@ -555,10 +578,16 @@ class TF5MixerController: if not force_refresh and self._is_cache_valid(): cached_data = self._cache.get("channels", {}).get(str(channel)) if cached_data: + # Normalizza level_db (None -> -inf) + level_db = self._normalize_level_from_cache(cached_data.get("level_db")) return { "status": "success", "source": "cache", - **cached_data + "channel": cached_data["channel"], + "name": cached_data["name"], + "on": cached_data["on"], + "level_db": level_db, + "pan": cached_data.get("pan") } # Altrimenti leggi dal mixer @@ -613,10 +642,15 @@ class TF5MixerController: if not force_refresh and self._is_cache_valid(): cached_data = self._cache.get("mixes", {}).get(str(mix_number)) if cached_data: + # Normalizza level_db (None -> -inf) + level_db = self._normalize_level_from_cache(cached_data.get("level_db")) return { "status": "success", "source": "cache", - **cached_data + "mix": cached_data["mix"], + "name": cached_data["name"], + "on": cached_data["on"], + "level_db": level_db } # Altrimenti leggi dal mixer @@ -664,11 +698,13 @@ class TF5MixerController: for ch_str, info in self._cache.get("channels", {}).items(): if search_lower in info.get("name", "").lower(): + # Normalizza level_db quando restituisci i risultati + level_db = self._normalize_level_from_cache(info.get("level_db")) found_channels.append({ "channel": info["channel"], "name": info["name"], "on": info["on"], - "level_db": info["level_db"] + "level_db": level_db }) # Ordina per numero canale @@ -701,11 +737,13 @@ class TF5MixerController: for mix_str, info in self._cache.get("mixes", {}).items(): if search_lower in info.get("name", "").lower(): + # Normalizza level_db quando restituisci i risultati + level_db = self._normalize_level_from_cache(info.get("level_db")) found_mixes.append({ "mix": info["mix"], "name": info["name"], "on": info["on"], - "level_db": info["level_db"] + "level_db": level_db }) # Ordina per numero mix @@ -781,5 +819,4 @@ class TF5MixerController: "mixes": mixes, "cache_age_seconds": int(cache_age), "message": f"Riepilogo di {len(mixes)} mix (cache: {int(cache_age)}s fa)" - } - + } \ No newline at end of file