import redis import atexit from flask import Flask, jsonify from flask_apscheduler import APScheduler from datetime import datetime, timedelta from scanner import * from config import * import logging logging.getLogger('apscheduler').setLevel(logging.ERROR) app = Flask(__name__) scheduler = APScheduler() scheduler.init_app(app) scheduler.start() run_counter = 0 scan_macs() # --- Scheduler job ---------------------------------------------------- @scheduler.task( 'interval', id='ble_scan', minutes=SCAN_INTERVAL_MINUTES, misfire_grace_time=30 ) def ble_scan_job(): run_counter = run_counter + 1 """Runs in the background, calls the async scanner.""" update_cache() if run_counter > 9: run_counter = 0 # --- API ------------------------------------------------------------- @app.route('/macs', methods=['GET']) def list_macs(): """Return the current set of MACs as JSON.""" macs = sorted(get_cache_snapshot()) return jsonify({"count": len(macs), "macs": macs}) @app.route('/details', methods=['GET']) def sensor_detail(): """Return the current set of MACs as JSON.""" sensors = get_sensor_details() return jsonify(sensors) @app.route('/summary', methods=['GET']) def sensor_summary(): """Return the current set of MACs as JSON.""" sensors = get_sensor_summary() return jsonify(sensors) # --- Convenience route ----------------------------------------------- @app.route('/', methods=['GET']) def hello(): return "BLE Scanner API - see /macs for the list." # --- Run -------------------------------------------------------------- if __name__ == '__main__': # The scheduler runs in its own thread; the main thread serves Flask. app.run(host=bind_ip, port=api_port, debug=False) # Register a graceful shutdown hook so the scanner state is persisted atexit.register(save_state)