This directory provides an example of how to integrate Firebase Cloud Messaging (FCM) into your FastAPI application for sending push notifications to client devices (e.g., Android, iOS, web). It demonstrates:
- How to initialise and use the Firebase Admin SDK to send FCM messages.
- How to store and manage device tokens in Redis (organised by user or site).
- How to design FastAPI endpoints for storing tokens, deleting tokens, and sending notifications.
- How to translate notification messages to multiple languages before dispatch (via a simple translation dictionary).
- Overview
- Prerequisites
- Setting Up a Firebase Project
- Generating the Service Account Credential File
- Directory Structure
- Installation
- Configuration
- Running the Example
- Using the API
- Additional Notes
This local notification server listens for requests to send push notifications to client devices via FCM. It:
- Stores FCM device tokens in Redis, keyed by user ID.
- Translates violation/warning messages into the recipient’s language using a simple dictionary-based approach.
- Dispatches notifications in bulk, grouping by language.
When a violation event is detected (e.g., “no hardhat,” “too close to machinery,” etc.), the server can push customised notifications with relevant content and optional images.
- Redis – the application depends on storing device tokens in Redis.
- A working FastAPI application – see the main
examples/authexample in this repository for authentication and general scaffolding. - Firebase Project – you must have a Firebase project with Cloud Messaging enabled.
- Python 3.9+ (recommended) – for running the code.
- Go to the Firebase Console.
- Create a new project (or select an existing one).
- Once created, go to Project Settings -> General to see your Project ID (e.g.,
construction-harzard-detection). - Under the Cloud Messaging section, ensure that FCM is enabled by default.
- In your Firebase project, navigate to Project Settings -> Service Accounts (under the Build or Settings section).
- Click Generate new private key under the Firebase Admin SDK section.
- This will download a
.jsonfile containing the service account credentials (private key, client email, etc.).
- This will download a
- Rename (or keep) the
.jsonfile name as you see fit. In this example, we have used:construction-harzard-detection-firebase-adminsdk-fbsvc-ca9d30aff7.json - Place this file in the
examples/local_notification_server/directory (or somewhere secure).- For production, you should keep this file outside the repository and manage secrets carefully.
Below is an overview of the files in examples/local_notification_server:
examples/local_notification_server/
├── app.py
├── fcm_service.py
├── lang_config.py
├── routers.py
├── schemas.py
├── construction-harzard-detection-firebase-adminsdk-fbsvc-ca9d30aff7.json (Your Firebase credentials)
└── README.md <- You are here
-
app.pyThe main FastAPI application that starts up withglobal_lifespan(from the parent auth example) and includes the notification router. -
fcm_service.pyResponsible for sending push notifications via the Firebase Admin SDK. It handles batch dispatch and error logging. -
lang_config.pyContains translation dictionaries for multiple languages and a simpleTranslatorclass that translates violation messages based on keys and placeholders. -
routers.pyProvides FastAPI routes for managing tokens (/store_token,/delete_token) and sending notifications (/send_fcm_notification). -
schemas.pyContains Pydantic models for request bodies (e.g.,TokenRequest,SiteNotifyRequest). -
construction-harzard-detection-firebase-adminsdk-fbsvc-ca9d30aff7.jsonAn example Firebase service account JSON file (rename and replace with your real one).
- Clone this repository (or copy the
examples/local_notification_serverfolder into your project). - Create and activate a virtual environment (optional but recommended):
python3 -m venv venv source venv/bin/activate # On macOS/Linux venv\Scripts\activate # On Windows
- Install the dependencies (in addition to those from the parent
examples/auth):(Or manually installpip install -r requirements.txt
firebase-adminand any other needed packages if they’re not already in your environment.)
-
Firebase credential file path Make sure the file path in
fcm_service.py(or wherever you initialise Firebase) matches your.jsonfile name and path. For example:cred_path = ( "examples/local_notification_server/" "construction-harzard-detection-firebase-adminsdk-fbsvc-ca9d30aff7.json" )
If you rename or relocate the file, update this path accordingly.
-
Redis The Redis connection is managed by the parent
examples/authmodules (redis_pool.py, etc.). Ensure your.envor environment variables are set for Redis (REDIS_HOST,REDIS_PORT,REDIS_PASSWORDif any). -
Database Similarly, ensure your
.env(or environment variables) is configured for the SQLAlchemy database, as some endpoints (like token storage) may query for user existence.
Below is an example command to start this local notification server (based on the app.py content):
python examples/local_notification_server/app.pyAlternatively, if you have a main.py in your root project that imports and runs this module, adapt accordingly. By default, it will run on 127.0.0.1:8003.
You can then test it using tools like HTTPie or cURL.
The main endpoints exposed by routers.py are:
POST /store_token
Body (TokenRequest):
{
"user_id": 1,
"device_token": "AAAA-VVVV-1234-XYZ",
"device_lang": "en-GB"
}- Stores the device token in Redis under
fcm_tokens:{user_id}, with the field as the token and value as the language code.
DELETE /delete_token
Body (TokenRequest):
{
"user_id": 1,
"device_token": "AAAA-VVVV-1234-XYZ"
}- Deletes the specified token from the user’s Redis hash.
POST /send_fcm_notification
Body (SiteNotifyRequest):
{
"site": "siteA",
"stream_name": "Camera-01",
"body": {
"warning_no_hardhat": {"count": 2},
"warning_close_to_machinery": {"count": 1}
},
"image_path": "https://example.com/image.jpg",
"violation_id": 123
}- Retrieves the site in the database, fetches associated users, and gathers all their device tokens from Redis.
- Groups tokens by language and uses the
Translator.translate_from_dict()to translate the warnings. - Sends out notifications with the relevant text and optional image.
- Returns a JSON response indicating success/failure.
-
Device Tokens
- For Android, you can retrieve the FCM token via the Firebase SDK in your app.
- For iOS, remember to enable push notifications and retrieve the APNs token, which the Firebase SDK will exchange for an FCM token.
-
Security
- In production, ensure your endpoints (e.g.,
/store_token) are protected. We rely on the parent JWT-based auth system (viajwt_access) for the/send_fcm_notificationendpoint. - Consider adding rate limiting and/or user-based checks for storing tokens.
- In production, ensure your endpoints (e.g.,
-
Multi-tenant or Per-Site
- This example groups users by site. You could adapt it to other grouping logic if desired (e.g., roles or certain user IDs).
-
Translations
- The
lang_config.pysimply uses a dictionary approach. For large-scale i18n, consider a more sophisticated library or a translation management system.
- The
-
Logging & Error Handling
fcm_service.pylogs unsuccessful sends usinglogging.error. In a production system, you should have robust error-handling and retry logic.