Skip to content

Commit 615d205

Browse files
committed
Removed Session-s from my.py
1 parent 23f94bd commit 615d205

File tree

3 files changed

+33
-122
lines changed

3 files changed

+33
-122
lines changed

custom_components/zte_router/manifest.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,5 +9,5 @@
99
"iot_class": "local_polling",
1010
"issue_tracker": "https://github.com/Kajkac/ZTE-MC-Home-assistant-repo/issues",
1111
"requirements": ["aiohttp"],
12-
"version": "1.0.49b11"
12+
"version": "1.0.49b12"
1313
}

custom_components/zte_router/mc.py

Lines changed: 17 additions & 115 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
import hashlib
22
from datetime import datetime, timedelta
3-
import binascii
43
import json
54
import sys
65
import os
@@ -15,7 +14,6 @@
1514
from cryptography import x509
1615
from cryptography.hazmat.backends import default_backend
1716
import re
18-
import atexit # <-- Added for auto cleanup
1917
from pygsm7 import encodeMessage, decodeMessage
2018
import traceback # <-- add this at the top if not already
2119
from logging.handlers import TimedRotatingFileHandler
@@ -129,98 +127,18 @@ def hex2utf(string):
129127
class zteRouter:
130128
def __init__(self, ip, username, password):
131129
self.ip = ip
132-
self.protocol = "http"
130+
self.protocol = "http" # default to http
133131
self.username = username
134132
self.password = password
135-
self.cookies = {}
133+
self.cookies = {} # Existing cookie management
136134
self.stok = None
137-
self.session_expiry = datetime.min
138-
self.uses_stok = False
135+
self.session_expiry = datetime.min # Initialize expiry in the past
139136
logger.info(f"Initializing ZTE Router with IP {ip}, Username: {username}, Password: {password}")
140-
141137
self.try_set_protocol()
142138
self.referer = f"{self.protocol}://{self.ip}/"
143139

144-
ld = self.get_LD()
145-
self.session_id = ld if ld else self.ip.replace(".", "_")
146-
147-
self.SESSION_FILE = os.path.join("/tmp", f"zte_session_{self.session_id}.json")
148-
logger.info(f"Using session ID: {self.session_id}")
149-
logger.info(f"Session file path: {self.SESSION_FILE}")
150-
151-
# Register cleanup function
152-
atexit.register(self.cleanup_files)
153-
154-
self.SESSION_FILE = os.path.join("/tmp", f"zte_session_{self.session_id}.json")
155140
CERT_FILE = "/tmp/zte_router_cert.pem"
156141

157-
def cleanup_files(self):
158-
if os.path.exists(self.SESSION_FILE):
159-
try:
160-
with open(self.SESSION_FILE, 'r') as f:
161-
session_data = json.load(f)
162-
expiry = datetime.fromisoformat(session_data.get("session_expiry"))
163-
if datetime.now() > expiry:
164-
os.remove(self.SESSION_FILE)
165-
logger.info(f"Cleaned up expired session file: {self.SESSION_FILE}")
166-
else:
167-
logger.info("Session still valid, skipping cleanup.")
168-
except Exception as e:
169-
logger.warning(f"Failed to evaluate or clean session file: {e}")
170-
171-
172-
def save_session(self):
173-
session_data = {
174-
'stok': self.stok,
175-
'session_expiry': self.session_expiry.isoformat(),
176-
'cookies': self.cookies,
177-
# Persist full session state
178-
'last_command': session.get("last_command"),
179-
'last_successful_cmd': session.get("last_successful_cmd"),
180-
'last_error': session.get("last_error"),
181-
'total_requests': session.get("total_requests"),
182-
'last_latency_ms': session.get("last_latency_ms"),
183-
'session_created': session.get("created"),
184-
'expires_in': session.get("expires_in"),
185-
'session_uses_stok': self.uses_stok,
186-
}
187-
with open(self.SESSION_FILE, 'w') as f:
188-
json.dump(session_data, f, indent=2)
189-
logger.info("📝 Session saved to disk:")
190-
logger.debug(json.dumps(session_data, indent=2))
191-
192-
193-
def load_session(self):
194-
if os.path.exists(self.SESSION_FILE):
195-
with open(self.SESSION_FILE, 'r') as f:
196-
session_data = json.load(f)
197-
self.stok = session_data.get('stok')
198-
self.cookies = session_data.get('cookies', {})
199-
self.session_expiry = datetime.fromisoformat(session_data['session_expiry'])
200-
self.uses_stok = session_data.get("session_uses_stok", False)
201-
202-
203-
# Restore extended session state
204-
session["last_command"] = session_data.get("last_command")
205-
session["last_successful_cmd"] = session_data.get("last_successful_cmd")
206-
session["last_error"] = session_data.get("last_error")
207-
session["total_requests"] = session_data.get("total_requests", 0)
208-
session["last_latency_ms"] = session_data.get("last_latency_ms", 0)
209-
session["created"] = session_data.get("session_created", datetime.now().isoformat())
210-
session["expires_in"] = session_data.get("expires_in", "N/A")
211-
212-
logger.info("📦 Session loaded from disk:")
213-
logger.debug(json.dumps(session_data, indent=2))
214-
215-
remaining = self.session_expiry - datetime.now()
216-
logger.info(f"⏳ Session expires in: {remaining.total_seconds() / 60:.2f} minutes")
217-
else:
218-
logger.info("⚠️ No existing session file found.")
219-
220-
221-
def is_session_valid(self):
222-
return datetime.now() < self.session_expiry and (not self.uses_stok or self.stok is not None)
223-
224142
def invalidate_session(self):
225143
logger.info("Invalidating session cookie")
226144
self.stok = None
@@ -438,16 +356,12 @@ def get_LD(self):
438356

439357
def getCookie(self, username, password, LD):
440358
logger.debug(f"Getting cookie for username: {username}, password: {password}, LD: {LD}")
441-
442-
self.load_session()
443-
if self.is_session_valid() and 'stok' in self.cookies:
444-
remaining = self.session_expiry - datetime.now()
445-
logger.info(f"🟢 Reusing session: stok={self.stok}")
446-
logger.info(f"Session valid for another {remaining.total_seconds() / 60:.1f} minutes")
447-
session["expires_in"] = f"{int(remaining.total_seconds() / 60)} min"
359+
if self.stok is not None and datetime.now() < self.session_expiry:
360+
logger.info(f"🟢 Reusing in-memory session: stok={self.stok}")
448361
return self.stok
449362
else:
450-
logger.warning("🔄 Session not valid or missing 'stok' — performing fresh login")
363+
logger.info("🔄 No valid session in memory, performing fresh login")
364+
451365

452366
header = {"Referer": self.referer}
453367
cookie_header = self.build_cookie_header()
@@ -486,20 +400,14 @@ def getCookie(self, username, password, LD):
486400
self.update_cookies(set_cookie_header)
487401

488402
stok = self.cookies.get('stok')
489-
if stok:
490-
self.uses_stok = True
491-
self.stok = stok
492-
logger.info(f"🔐 Router uses stok: {stok}")
493-
else:
494-
self.uses_stok = False
495-
self.stok = None
496-
logger.info("🔓 Router does NOT use stok (cookie-based only login)")
403+
if not stok:
404+
logger.error("Failed to obtain a valid cookie from the router")
405+
raise ValueError("Failed to obtain a valid cookie from the router")
497406

498407
# Set session expiry (e.g., valid for 60 minutes)
499408
self.session_expiry = datetime.now() + timedelta(minutes=1)
500409
session["expires_in"] = f"{int((self.session_expiry - datetime.now()).total_seconds() / 60)} min"
501410
self.stok = stok
502-
self.save_session()
503411
logger.info(f"Obtained new session cookie: stok={stok}")
504412
return stok
505413

@@ -1280,25 +1188,20 @@ def setdata_mode(self, BearerPreference):
12801188
result = zte.zteinfo4()
12811189
print(result)
12821190
elif command == 99:
1283-
# ✅ Explicitly load session before printing diagnostics
1284-
zte.load_session()
12851191
diagnostics = {
1286-
"session_created": session.get("created"),
1287-
"session_expires_in": session.get("expires_in"),
1288-
"last_command": session.get("last_command", "Unknown"),
1289-
"last_successful_cmd": session.get("last_successful_cmd", "Unknown"),
1290-
"last_error": session.get("last_error", "Unknown"),
1291-
"total_requests": session.get("total_requests", 0),
1292-
"fetch_latency_ms": session.get("last_latency_ms", 0),
1192+
"runtime_started": session.get("created"),
1193+
"last_latency_ms": session.get("last_latency_ms", 0),
1194+
"total_http_requests": session.get("total_requests", 0),
1195+
"last_error": session.get("last_error", "None"),
1196+
"command_success": session.get("last_successful_cmd", "None"),
1197+
"router_ip": ip,
12931198
}
12941199
print(json.dumps(diagnostics, indent=2))
12951200
sys.exit(0)
12961201

12971202
# ✅ Track last successful command if applicable
12981203
if command != 99 and result is not None:
12991204
session["last_successful_cmd"] = command
1300-
zte.save_session() # 💾 Save updated session to disk!
1301-
13021205
# ❌ Fallback if command is not recognized
13031206
if result is None:
13041207
print(f"Invalid command: {command}")
@@ -1307,5 +1210,4 @@ def setdata_mode(self, BearerPreference):
13071210
except Exception as e:
13081211
logger.error(f"An error occurred: {e}")
13091212
session["last_error"] = str(e)
1310-
zte.save_session()
1311-
sys.exit(1)
1213+
sys.exit(1)

custom_components/zte_router/sensor.py

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -79,10 +79,16 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry, async_add_e
7979
"station_list", "lan_station_list", "all_devices"
8080
])
8181

82+
# Create and store the SMS coordinator
83+
sms_coordinator = ZTERouterSMSUpdateCoordinator(hass, ip, pwd, user, sms_check_interval)
84+
await sms_coordinator.async_config_entry_first_refresh()
85+
hass.data[DOMAIN][entry.entry_id]["sms_coordinator"] = sms_coordinator
86+
87+
8288
# SMS Sensor
83-
sms_data = coordinator.data.get("sms_data", {})
84-
if "content" in sms_data:
85-
sensors.append(LastSMSSensor(coordinator, sms_data, disabled_sensors.get("last_sms", False)))
89+
sms_coordinator = hass.data[DOMAIN][entry.entry_id]["sms_coordinator"]
90+
sms_data = sms_coordinator.data.get("sms_data", {})
91+
sensors.append(LastSMSSensor(sms_coordinator, sms_data))
8692

8793
# FLUX Sensors
8894
registry = async_get(hass)
@@ -148,7 +154,7 @@ def __init__(self, hass, ip, pwd, user, interval, allow_stale_data=True):
148154

149155
async def _async_update_data(self):
150156
new_data = {}
151-
keys = {3: "dynamic_data", 6: "sms_data", 7: "status_data", 16: "client_data", 99: "diag_data"}
157+
keys = {3: "dynamic_data", 7: "status_data", 16: "client_data", 99: "diag_data"}
152158
for cmd, label in keys.items():
153159
try:
154160
raw = await self.hass.async_add_executor_job(
@@ -190,6 +196,8 @@ def run_mc_script(self, ip, pwd, user, cmd, retries=3, delay=2):
190196

191197
class ZTERouterSMSUpdateCoordinator(DataUpdateCoordinator):
192198
def __init__(self, hass, ip_entry, password_entry, username_entry, sms_check_interval):
199+
# In ZTERouterSMSUpdateCoordinator.__init__
200+
self._listeners = set()
193201
self.ip_entry = ip_entry
194202
self.password_entry = password_entry
195203
self.username_entry = username_entry if username_entry else ""
@@ -211,7 +219,8 @@ async def _async_update_data(self):
211219
)
212220
_LOGGER.debug(f"SMS data received from mc.py script: {data}")
213221
json_data = extract_json(data)
214-
self._data.update(json.loads(json_data))
222+
parsed = json.loads(json_data)
223+
self._data = {"sms_data": parsed}
215224
return self._data
216225
except Exception as err:
217226
_LOGGER.error(f"Error during _async_update_data (SMS): {err}")
@@ -1421,4 +1430,4 @@ def state(self):
14211430

14221431
@property
14231432
def unique_id(self):
1424-
return f"{DOMAIN}_{self.coordinator.ip_entry}_stat_flux_total_usage"
1433+
return f"{DOMAIN}_{self.coordinator.ip_entry}_stat_flux_total_usage"

0 commit comments

Comments
 (0)