Skip to content

Commit 598b6b8

Browse files
committed
update location logic and more test case and fix issue with parser
1 parent e262f36 commit 598b6b8

File tree

3 files changed

+361
-255
lines changed

3 files changed

+361
-255
lines changed

ap_monitor/app/main.py

Lines changed: 66 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import logging
22
from datetime import datetime, timedelta, timezone
3-
from typing import List, Optional
3+
from typing import List, Optional, Tuple
44
from fastapi import FastAPI, Depends, HTTPException, Query
55
from contextlib import asynccontextmanager
66
from sqlalchemy.orm import Session
@@ -161,6 +161,29 @@ async def lifespan(app: FastAPI):
161161
lifespan=lifespan,
162162
)
163163

164+
def parse_location(location: str) -> Tuple[Optional[str], Optional[str]]:
165+
"""
166+
Parse location string to extract building and floor names.
167+
Returns (building_name, floor_name) tuple.
168+
"""
169+
if not location or not isinstance(location, str):
170+
logger.warning(f"Skipping device with empty or invalid location: {location}")
171+
return None, None
172+
173+
parts = [p.strip() for p in location.split('/') if p.strip()]
174+
# Global/Keele Campus/<Building>/<Floor...>
175+
if len(parts) >= 4 and parts[0] == "Global" and parts[1] == "Keele Campus":
176+
building = parts[2]
177+
floor = parts[3]
178+
return building, floor
179+
# <Building>/<Floor...>
180+
if len(parts) >= 2:
181+
building = parts[0]
182+
floor = parts[1]
183+
return building, floor
184+
logger.warning(f"Skipping device with invalid location format: {location}")
185+
return None, None
186+
164187
def update_ap_data_task(db: Session = None, auth_manager_obj=None, fetch_ap_data_func=None):
165188
"""Background task to update AP data in the database."""
166189
auth_manager_obj = auth_manager_obj or auth_manager
@@ -180,23 +203,16 @@ def update_ap_data_task(db: Session = None, auth_manager_obj=None, fetch_ap_data
180203
# Process AP data
181204
for ap in aps:
182205
ap_name = ap.get('name')
183-
location = ap.get('location', '')
184-
location_parts = location.split('/') if location else []
185206

186-
# Handle location parsing based on real data format
187-
if not location_parts:
188-
logger.warning(f"Skipping device {ap_name} due to invalid location format: {location}")
189-
continue
190-
191-
# Extract building and floor from location
192-
if len(location_parts) >= 5:
193-
building_name = location_parts[2] # e.g., "Bethune Residence"
194-
floor_name = location_parts[3] # e.g., "Floor 5"
195-
elif len(location_parts) == 2:
196-
building_name = location_parts[0]
197-
floor_name = location_parts[1]
198-
else:
199-
logger.warning(f"Skipping device {ap_name} due to invalid location format: {location}")
207+
# Try different location fields in order of preference
208+
location = ap.get('location')
209+
if not location or len(location.split('/')) < 2:
210+
location = ap.get('snmpLocation')
211+
if not location or len(location.split('/')) < 2:
212+
location = ap.get('locationName')
213+
214+
building_name, floor_name = parse_location(location)
215+
if not building_name or not floor_name:
200216
continue
201217

202218
# Building
@@ -303,39 +319,32 @@ def update_client_count_task(db: Session = None, auth_manager_obj=None, fetch_cl
303319
# Process AP data for apclientcount DB
304320
for ap in ap_data:
305321
ap_name = ap.get('name')
306-
location = ap.get('location', '')
307-
location_parts = location.split('/') if location else []
308322

309-
# Handle location parsing based on real data format
310-
if not location_parts:
311-
logger.warning(f"Skipping device {ap_name} due to invalid location format: {location}")
312-
continue
313-
314-
# Extract building and floor from location
315-
if len(location_parts) >= 5:
316-
building_name = location_parts[3] # e.g., "Keele Campus"
317-
floor_name = location_parts[4] # e.g., "Floor 5"
318-
elif len(location_parts) == 2:
319-
building_name = location_parts[0]
320-
floor_name = location_parts[1]
321-
else:
322-
logger.warning(f"Skipping device {ap_name} due to invalid location format: {location}")
323+
# Try different location fields in order of preference
324+
location = ap.get('location')
325+
if not location or len(location.split('/')) < 2:
326+
location = ap.get('snmpLocation')
327+
if not location or len(location.split('/')) < 2:
328+
location = ap.get('locationName')
329+
330+
building_name, floor_name = parse_location(location)
331+
if not building_name or not floor_name:
323332
continue
324-
333+
325334
# Building
326-
building = db.query(ApBuilding).filter_by(building_name=building_name).first()
335+
building = db.query(ApBuilding).filter_by(buildingname=building_name).first()
327336
if not building:
328-
building = ApBuilding(building_name=building_name)
337+
building = ApBuilding(buildingname=building_name)
329338
db.add(building)
330339
db.flush()
331-
340+
332341
# Floor
333-
floor = db.query(Floor).filter_by(floorname=floor_name, building_id=building.building_id).first()
342+
floor = db.query(Floor).filter_by(floorname=floor_name, buildingid=building.buildingid).first()
334343
if not floor:
335-
floor = Floor(floorname=floor_name, building_id=building.building_id)
344+
floor = Floor(floorname=floor_name, buildingid=building.buildingid)
336345
db.add(floor)
337346
db.flush()
338-
347+
339348
# Access Point
340349
mac_address = ap.get('macAddress')
341350
ap_record = db.query(AccessPoint).filter_by(macaddress=mac_address).first()
@@ -350,15 +359,15 @@ def update_client_count_task(db: Session = None, auth_manager_obj=None, fetch_cl
350359
modelname=ap.get('model'),
351360
isactive=is_active,
352361
floorid=floor.floorid,
353-
building_id=building.building_id
362+
buildingid=building.buildingid
354363
)
355364
db.add(ap_record)
356365
db.flush()
357366
else:
358367
logger.debug(f"Updating existing AccessPoint: {ap.get('name')}")
359368
ap_record.isactive = is_active
360369
ap_record.floorid = floor.floorid
361-
ap_record.building_id = building.building_id
370+
ap_record.buildingid = building.buildingid
362371

363372
# Create client count records for each radio
364373
client_counts = ap.get('clientCount', {})
@@ -412,17 +421,17 @@ def insert_apclientcount_data(device_info_list, timestamp, session=None):
412421

413422
try:
414423
for device_info in device_info_list:
415-
# Parse location
416-
location = device_info.get("location", "")
417-
location_parts = location.split("/")
424+
ap_name = device_info.get('name')
418425

419-
# Determine building name based on location format
420-
if len(location_parts) >= 3:
421-
building_name = location_parts[2] # e.g., "Bethune Residence"
422-
elif len(location_parts) == 2:
423-
building_name = location_parts[0]
424-
else:
425-
logger.warning(f"Skipping device {device_info.get('name')} due to invalid location format: {location}")
426+
# Try different location fields in order of preference
427+
location = device_info.get('location')
428+
if not location or len(location.split('/')) < 2:
429+
location = device_info.get('snmpLocation')
430+
if not location or len(location.split('/')) < 2:
431+
location = device_info.get('locationName')
432+
433+
building_name, floor_name = parse_location(location)
434+
if not building_name or not floor_name:
426435
continue
427436

428437
# Get or create building
@@ -433,15 +442,17 @@ def insert_apclientcount_data(device_info_list, timestamp, session=None):
433442
session.commit()
434443

435444
# Get or create floor
436-
floor_name = location_parts[3] if len(location_parts) >= 4 else "Unknown Floor"
437445
floor = session.query(Floor).filter_by(buildingid=building.buildingid, floorname=floor_name).first()
438446
if not floor:
439447
floor = Floor(buildingid=building.buildingid, floorname=floor_name)
440448
session.add(floor)
441449
session.commit()
442450

443-
# Get or create room
444-
room_name = location_parts[4] if len(location_parts) >= 5 else "Unknown Room"
451+
# Get or create room (optional)
452+
room_name = "Unknown Room" # Default room name
453+
if location and len(location.split('/')) > 4:
454+
room_name = location.split('/')[4].strip()
455+
445456
room = session.query(Room).filter_by(floorid=floor.floorid, roomname=room_name).first()
446457
if not room:
447458
room = Room(floorid=floor.floorid, roomname=room_name)

0 commit comments

Comments
 (0)