Back to Blog
Mobile Development

Flutter IoT Alerts: Firebase Push Notifications for Device Events

When a sensor threshold is breached at 3am, your user needs an alert — not a dashboard to check. This guide builds the complete IoT alert pipeline: device event → cloud → Firebase Cloud Messaging → Flutter notification with actionable response.

September 2, 2024
10 min read
FlutterFCMPush NotificationsIoT

Flutter IoT Alerts: Firebase Push Notifications for Device Events

A monitoring dashboard is great when someone is watching it. But IoT systems operate 24/7 and humans don't. When a temperature sensor in a pharmaceutical cold chain spikes above threshold at 3am, your client needs to know immediately — not when they check the dashboard at 9am.

This guide builds the complete pipeline: embedded sensor → MQTT → cloud processing → Firebase Cloud Messaging → Flutter push notification with actionable response.

Architecture Overview

Sensor Event (threshold breach)
    ↓ MQTT
AWS IoT Core
    ↓ IoT Rule (SQL filter)
AWS Lambda (alert processor)
    ↓ FCM Admin SDK
Firebase Cloud Messaging
    ↓
Flutter App (foreground + background)
    ↓
User Action: Acknowledge / Snooze / View Details

Step 1: AWS Lambda Alert Processor

When a sensor publishes above threshold, IoT Core's rules engine triggers Lambda:

// lambda/alert-processor.js
import admin from 'firebase-admin'

admin.initializeApp({ credential: admin.credential.cert(JSON.parse(process.env.FIREBASE_SERVICE_ACCOUNT)), })

export const handler = async (event) => { const { deviceId, temperature, threshold, userId } = event

if (temperature <= threshold) return // IoT Rule should filter, but double-check

// Look up user's FCM token from DynamoDB const userRecord = await dynamoDB.get({ TableName: 'Users', Key: { userId }, }).promise()

const fcmToken = userRecord.Item?.fcmToken if (!fcmToken) return

const message = { token: fcmToken, notification: { title: '⚠️ Temperature Alert', body: Device ${deviceId}: ${temperature}°C (threshold: ${threshold}°C), }, data: { type: 'temperature_alert', deviceId, temperature: String(temperature), threshold: String(threshold), alertId: crypto.randomUUID(), timestamp: new Date().toISOString(), }, android: { priority: 'high', notification: { channelId: 'iot_alerts', priority: 'max', sound: 'alert_sound', }, }, apns: { payload: { aps: { sound: 'alert_sound.caf', 'content-available': 1, badge: 1, }, }, headers: { 'apns-priority': '10', 'apns-push-type': 'alert', }, }, }

await admin.messaging().send(message) console.log(Alert sent to ${userId} for device ${deviceId}) }

Step 2: Flutter FCM Setup

dependencies:
  firebase_core:     ^2.32.0
  firebase_messaging: ^14.9.0
  flutter_local_notifications: ^17.2.0

Initialize in main.dart:

Future main() async {
  WidgetsFlutterBinding.ensureInitialized()
  await Firebase.initializeApp(options: DefaultFirebaseOptions.currentPlatform)

// Handle background messages FirebaseMessaging.onBackgroundMessage(_firebaseMessagingBackgroundHandler)

// Android notification channel const channel = AndroidNotificationChannel( 'iot_alerts', 'IoT Alerts', importance: Importance.max, sound: RawResourceAndroidNotificationSound('alert_sound'), enableLights: true, ledColor: Colors.red, );

final localNotifications = FlutterLocalNotificationsPlugin() await localNotifications .resolvePlatformSpecificImplementation() ?.createNotificationChannel(channel)

runApp(const MyApp()) }

// Must be top-level function @pragma('vm:entry-point') Future _firebaseMessagingBackgroundHandler(RemoteMessage message) async { await Firebase.initializeApp(options: DefaultFirebaseOptions.currentPlatform) await AlertRepository.saveAlert(message.data) // Persist for next app open }

Step 3: Requesting Permissions and Getting FCM Token

class NotificationService {
  static Future initialize() async {
    final messaging = FirebaseMessaging.instance

final settings = await messaging.requestPermission( alert: true, badge: true, sound: true, criticalAlert: true, // iOS: bypasses Do Not Disturb for critical alerts )

if (settings.authorizationStatus == AuthorizationStatus.denied) return null

// Get FCM token and send to your backend final token = await messaging.getToken() if (token != null) { await ApiService.updateFCMToken(token) }

// Token refresh (happens after app restore, etc.) FirebaseMessaging.instance.onTokenRefresh.listen(ApiService.updateFCMToken)

return token } }

Step 4: Handling Notifications in All App States

class AlertHandler {
  static void initialize(BuildContext context) {
    // App in foreground
    FirebaseMessaging.onMessage.listen((message) {
      if (message.data['type'] == 'temperature_alert') {
        _showInAppAlert(context, message)
        _showLocalNotification(message)  // Show local notification even in foreground
      }
    })

// App in background, user tapped notification FirebaseMessaging.onMessageOpenedApp.listen((message) { _navigateToAlert(context, message.data['alertId']) })

// App terminated, user tapped notification FirebaseMessaging.instance.getInitialMessage().then((message) { if (message != null) { _navigateToAlert(context, message.data['alertId']) } }) }

static void _showInAppAlert(BuildContext context, RemoteMessage message) { ScaffoldMessenger.of(context).showMaterialBanner( MaterialBanner( backgroundColor: Colors.red[900], content: Text( message.notification?.body ?? 'Alert', style: const TextStyle(color: Colors.white), ), actions: [ TextButton( onPressed: () { ScaffoldMessenger.of(context).clearMaterialBanners() _acknowledgeAlert(message.data['alertId']) }, child: const Text('ACKNOWLEDGE', style: TextStyle(color: Colors.white)), ), TextButton( onPressed: () { ScaffoldMessenger.of(context).clearMaterialBanners() _navigateToAlert(context, message.data['alertId']) }, child: const Text('VIEW', style: TextStyle(color: Colors.orange)), ), ], ), ) } }

Step 5: Actionable Notifications (Android)

static Future _showLocalNotification(RemoteMessage message) async {
  const androidDetails = AndroidNotificationDetails(
    'iot_alerts',
    'IoT Alerts',
    importance: Importance.max,
    priority:   Priority.max,
    actions: [
      AndroidNotificationAction('acknowledge', 'Acknowledge', cancelNotification: true),
      AndroidNotificationAction('snooze',      'Snooze 15m',  cancelNotification: true),
      AndroidNotificationAction('view',        'View Details'),
    ],
  )

await FlutterLocalNotificationsPlugin().show( message.data['alertId'].hashCode, message.notification?.title, message.notification?.body, const NotificationDetails(android: androidDetails), payload: jsonEncode(message.data), ) }

Preventing Alert Fatigue

A threshold breach every 30 seconds will make users disable notifications entirely. Implement:

  • 1. Alert cooldown: Don't fire if same device alerted in last 15 minutes
  • 2. Severity levels: Critical (call), High (notification), Medium (dashboard badge only)
  • 3. Smart grouping: Bundle "5 temperature sensors above threshold" into one notification
  • 4. Scheduled silence: Respect user-defined maintenance windows
  • 5. Acknowledgement: Once acknowledged, suppress until condition clears and reoccurs
  • // Lambda: Cooldown check before sending FCM
    const lastAlert = await redis.get(alert:${deviceId}:last)
    if (lastAlert && Date.now() - parseInt(lastAlert) < 15 * 60 * 1000) {
      return  // Suppress — still within cooldown period
    }
    await redis.setex(alert:${deviceId}:last, 3600, Date.now())
    

    IoT alerting is a product feature, not just a technical checkbox — getting it wrong means ignored alerts or disabled notifications. If you need a production alert system built for your IoT product, [contact Code Caracal](/contact).

    Written by CodeCaracal Engineering

    We write from production experience — every technique in our articles has been deployed to real clients. No academic theory.

    More Articles

    Business · 12 min read

    IoT Device Compliance: FCC, CE, and Product Certification Guide for Hardware Startups

    Business · 11 min read

    What to Look for When Hiring an IoT Development Partner: 8 Critical Criteria

    Business · 11 min read

    IoT MVP to Production: Realistic Timeline and Budget for Hardware Startups

    Business · 11 min read

    IoT Development Agency vs Building In-House: A Decision Framework for Founders

    IoT Dashboard · 13 min read

    Next.js IoT Analytics Dashboard: From Sensor Data to Production App

    Business · 11 min read

    How Much Does It Cost to Build an IoT Product in 2024? A Realistic Breakdown

    IoT Dashboard · 11 min read

    IoT Dashboard UX: Design Principles for Industrial Monitoring Interfaces

    IoT Dashboard · 12 min read

    Node.js WebSocket Server: The Real-Time Backend for IoT Dashboards

    Cloud & DevOps · 12 min read

    Containerizing IoT Backend Services with Docker: From Dev to Production

    IoT Dashboard · 14 min read

    Grafana + InfluxDB IoT Monitoring: Complete Production Setup Guide

    IoT Dashboard · 12 min read

    Building Real-Time IoT Dashboards with React and Recharts

    Cloud & DevOps · 13 min read

    CI/CD for Embedded Firmware: Automated Build, Test, and OTA Release Pipeline

    Mobile Development · 12 min read

    Flutter Offline-First IoT Apps: Hive + Sync Architecture That Works in the Field

    Cloud & DevOps · 14 min read

    Terraform for IoT Infrastructure: Provisioning AWS IoT Core, Lambda, and InfluxDB as Code

    Cloud & DevOps · 12 min read

    Deploying IoT Backends on AWS: ECS Fargate vs Lambda vs EC2 Decision Guide

    Mobile Development · 11 min read

    Flutter + MQTT: Building Production IoT Mobile Apps That Scale

    Mobile Development · 13 min read

    Flutter BLE: Building a Bluetooth IoT Controller App from Scratch

    Cloud & DevOps · 13 min read

    AWS IoT Core vs Azure IoT Hub vs Google Cloud IoT: 2024 Honest Comparison

    IoT Engineering · 13 min read

    Kafka vs RabbitMQ for IoT: Choosing the Right Message Queue for High-Volume Telemetry

    IoT Engineering · 14 min read

    IoT System Testing: Unit, Integration, Hardware-in-the-Loop, and End-to-End

    IoT Engineering · 14 min read

    Predictive Maintenance with IoT Sensor Data: From Threshold to Machine Learning

    Embedded Systems · 14 min read

    IoT Bootloader Design: Secure Boot, A/B Partitions, and Reliable OTA Recovery

    IoT Engineering · 14 min read

    Multi-Tenant IoT Platform Architecture: Isolation, Scaling, and Data Partitioning

    Embedded Systems · 14 min read

    Memory Management in Embedded Firmware: Avoiding Heap Fragmentation and Stack Overflows

    IoT Engineering · 13 min read

    IoT Cost Optimization: How We Cut AWS IoT Bills by 60% Without Sacrificing Reliability

    IoT Engineering · 12 min read

    Edge Computing in IoT: When to Process On-Device vs In the Cloud

    IoT Engineering · 13 min read

    Digital Twins for IoT: Building a Virtual Mirror of Your Physical Devices

    Embedded Systems · 14 min read

    ESP32 Deep Sleep Mastery: Cutting Power Consumption from 240mA to 10µA

    IoT Engineering · 10 min read

    MQTT QoS 0, 1, and 2 Explained: Choosing the Right Level for IoT

    IoT Engineering · 14 min read

    IoT Monitoring and Observability: Metrics, Logs, and Distributed Tracing

    Embedded Systems · 14 min read

    Debugging Embedded Firmware: JTAG, GDB, Logic Analyzers, and Serial Tracing

    IoT Engineering · 12 min read

    WebSocket vs MQTT vs Server-Sent Events: Real-Time IoT Protocol Deep Dive

    Embedded Systems · 13 min read

    STM32 HAL vs Low-Level Drivers: When the Abstraction Costs You Too Much

    IoT Engineering · 13 min read

    IoT Data Pipeline: From Raw Sensor Reading to Live Dashboard in Under 100ms

    IoT Engineering · 13 min read

    Zero-Touch IoT Device Provisioning: Scaling from 10 to 100,000 Devices

    Embedded Systems · 13 min read

    UART vs SPI vs I2C: Choosing the Right Protocol for Sensor Integration

    IoT Engineering · 12 min read

    Real-Time IoT Alerting: From Simple Thresholds to ML Anomaly Detection

    Embedded Systems · 12 min read

    ESP32 Partition Table: Designing Flash Layout for Production Firmware

    IoT Engineering · 12 min read

    IoT Architecture Patterns: Hub-and-Spoke, Mesh, and Edge-Cloud Hybrid

    Embedded Systems · 13 min read

    IoT Battery Life Optimization: Engineering Devices That Last Years on a Single Charge

    IoT Engineering · 13 min read

    Time-Series Databases for IoT: InfluxDB vs TimescaleDB vs AWS Timestream

    Security · 14 min read

    Zero-Trust Security for Embedded IoT: Why Your Devices Are Probably Vulnerable

    Embedded Systems · 14 min read

    FreeRTOS on ESP32: Task Scheduling, Queues, and Resource Management for IoT

    IoT Engineering · 12 min read

    Building a Production IoT Gateway with Raspberry Pi and Node.js

    Embedded Systems · 13 min read

    ESP32 vs STM32: Choosing the Right Microcontroller for Your IoT Project

    Mobile Development · 10 min read

    Flutter + WebSocket: Building Real-Time IoT Dashboards That Don't Stutter

    IoT Engineering · 13 min read

    IoT Fleet Management at Scale: AWS IoT Core Device Registry and Provisioning

    IoT Engineering · 11 min read

    MQTT vs HTTP for IoT: Which Protocol Wins in Production?

    IoT Engineering · 12 min read

    ESP32 → MQTT → AWS IoT Core: The Production-Grade Architecture Guide

    Let's Build Together

    Got an IoT challenge?
    We've shipped it.

    Whether you need a fleet to track, a factory to monitor, or a farm to automate — our team has done it before and we'd love to build it with you. Typical response time: under 24 hours.

    No upfront commitment99.9% uptime SLANDA on requestFixed-price options