Skip to content

ACN (Automatic Crash Notification) API Codelab

Overview

This codelab guides you through implementing the Automatic Crash Notification (ACN) API, which automatically detects vehicle accidents and coordinates emergency response. You'll learn how to handle emergency situations, manage incident data, and integrate with rescue services.

Prerequisites

  • Basic understanding of REST APIs
  • Familiarity with JavaScript/TypeScript
  • Node.js and npm installed
  • Understanding of emergency response workflows
  • Text editor or IDE

Learning Objectives

  • Implement ACN incident detection and management
  • Handle real-time emergency notifications via SSE
  • Manage agent workflows and incident assignment
  • Process accident data and coordinate rescue services
  • Implement emergency response best practices

Setup

1. Project Initialization

bash
mkdir acn-api-demo
cd acn-api-demo
npm init -y
npm install axios node-fetch moment

2. Configuration

Create a config.js file:

javascript
export const API_CONFIG = {
  baseURL: 'https://api.ecarus.run/api/v1/safety',
  authToken: 'sk_4f9c7b8e2d1a6c0f3e7a9b5d8c1e4f2a7c6d9e0b3f5a8c1d4e7f9b2c6a1e3d',
  sampleVIN: 'KMHSH81C7LU123456',
  sampleAgentId: 'AGENT_001',
  timeout: 10000 // 10 seconds for emergency services
};

Step 1: ACN System Status and Monitoring

Implement System Health Monitoring

Create acnSystem.js:

javascript
import axios from 'axios';
import { API_CONFIG } from './config.js';

class ACNSystem {
  constructor() {
    this.client = axios.create({
      baseURL: API_CONFIG.baseURL,
      headers: {
        'Authorization': `Bearer ${API_CONFIG.authToken}`,
        'Content-Type': 'application/json'
      },
      timeout: API_CONFIG.timeout
    });
  }

  async getSystemHealth() {
    try {
      const response = await this.client.get('/acn/system/health');
      console.log('ACN System Health:', response.data);
      return response.data;
    } catch (error) {
      console.error('Failed to get system health:', error.response?.data || error.message);
      throw error;
    }
  }

  async getStatistics() {
    try {
      const response = await this.client.get('/acn/stats');
      console.log('ACN Statistics:', response.data);
      return response.data;
    } catch (error) {
      console.error('Failed to get ACN statistics:', error.response?.data || error.message);
      throw error;
    }
  }

  isSystemHealthy(healthData) {
    return healthData.status === 'HEALTHY' && 
           Object.values(healthData.services).every(service => service === 'ACTIVE');
  }

  getServiceStatus(healthData) {
    return {
      overall: healthData.status,
      services: healthData.services,
      metrics: healthData.metrics,
      isHealthy: this.isSystemHealthy(healthData)
    };
  }
}

export default ACNSystem;

Test System Monitoring

Create test-system.js:

javascript
import ACNSystem from './acnSystem.js';

const acnSystem = new ACNSystem();

async function testSystemMonitoring() {
  try {
    console.log('🏥 Testing ACN System Monitoring...');
    
    // Check system health
    const health = await acnSystem.getSystemHealth();
    const status = acnSystem.getServiceStatus(health);
    
    console.log('📊 System Status:', status);
    
    if (status.isHealthy) {
      console.log('✅ ACN System is fully operational');
    } else {
      console.log('⚠️ ACN System has issues that need attention');
    }
    
    // Get statistics
    const stats = await acnSystem.getStatistics();
    console.log('📈 ACN Statistics:', stats);
    
  } catch (error) {
    console.error('❌ System monitoring test failed:', error.message);
  }
}

testSystemMonitoring();

Step 2: Incident Management

Implement Incident Control

Create incidentManager.js:

javascript
import axios from 'axios';
import { API_CONFIG } from './config.js';

class IncidentManager {
  constructor() {
    this.client = axios.create({
      baseURL: API_CONFIG.baseURL,
      headers: {
        'Authorization': `Bearer ${API_CONFIG.authToken}`,
        'Content-Type': 'application/json'
      },
      timeout: API_CONFIG.timeout
    });
  }

  async getIncidentStatus(vin, cid) {
    try {
      const response = await this.client.get(
        `/vehicles/${vin}/acn/status`,
        { params: { cid } }
      );

      console.log('Incident Status:', response.data);
      return response.data;
    } catch (error) {
      console.error('Failed to get incident status:', error.response?.data || error.message);
      throw error;
    }
  }

  async getIncidentHistory(vin, options = {}) {
    try {
      const params = {
        limit: options.limit || 50,
        offset: options.offset || 0,
        startDate: options.startDate,
        endDate: options.endDate
      };

      const response = await this.client.get(
        `/vehicles/${vin}/acn/history`,
        { params }
      );

      console.log('Incident History:', response.data);
      return response.data;
    } catch (error) {
      console.error('Failed to get incident history:', error.response?.data || error.message);
      throw error;
    }
  }

  async closeIncident(vin, incidentData) {
    try {
      const payload = {
        cid: incidentData.cid,
        closureReason: incidentData.closureReason || 'EMERGENCY_SERVICES_DISPATCHED',
        result: incidentData.result || 'SUCCESS',
        agentId: incidentData.agentId || API_CONFIG.sampleAgentId,
        notes: incidentData.notes || ''
      };

      const response = await this.client.post(
        `/vehicles/${vin}/acn/close`,
        payload
      );

      console.log('Incident Closed:', response.data);
      return response.data;
    } catch (error) {
      console.error('Failed to close incident:', error.response?.data || error.message);
      throw error;
    }
  }

  formatIncidentLocation(location) {
    return {
      latitude: location.latitude,
      longitude: location.longitude,
      accuracy: location.accuracy || 'Unknown',
      formatted: `${location.latitude.toFixed(4)}, ${location.longitude.toFixed(4)}`
    };
  }

  assessIncidentSeverity(severity, trigger) {
    const severityLevels = {
      'LOW': { priority: 3, responseTime: '15 min', color: '🟡' },
      'MEDIUM': { priority: 2, responseTime: '10 min', color: '🟠' },
      'HIGH': { priority: 1, responseTime: '5 min', color: '🔴' },
      'CRITICAL': { priority: 0, responseTime: 'Immediate', color: '🚨' }
    };

    const triggerSeverity = {
      'AIRBAG_DEPLOYMENT': 'HIGH',
      'ROLLOVER_DETECTED': 'CRITICAL',
      'IMPACT_DETECTED': 'MEDIUM',
      'MANUAL_SOS': 'HIGH',
      'SOS_BUTTON': 'HIGH'
    };

    const assessedSeverity = severity || triggerSeverity[trigger] || 'MEDIUM';
    return severityLevels[assessedSeverity] || severityLevels['MEDIUM'];
  }
}

export default IncidentManager;

Test Incident Management

Create test-incident.js:

javascript
import IncidentManager from './incidentManager.js';
import { API_CONFIG } from './config.js';

const incidentManager = new IncidentManager();

async function testIncidentManagement() {
  const vin = API_CONFIG.sampleVIN;
  const testCid = 'ACN_20260307_001';

  try {
    console.log('🚨 Testing Incident Management...');
    
    // Get incident status
    const status = await incidentManager.getIncidentStatus(vin, testCid);
    const severity = incidentManager.assessIncidentSeverity(status.severity, status.trigger);
    
    console.log('📊 Incident Assessment:', {
      cid: status.cid,
      severity: severity,
      location: incidentManager.formatIncidentLocation(status.location),
      rescueStatus: status.rescueStatus
    });
    
    // Get incident history
    const history = await incidentManager.getIncidentHistory(vin, { limit: 10 });
    console.log('📜 Incident History:', history.incidents.length, 'incidents found');
    
    // Close incident (if active)
    if (status.status === 'ACTIVE') {
      console.log('🔒 Closing incident...');
      await incidentManager.closeIncident(vin, {
        cid: testCid,
        closureReason: 'EMERGENCY_SERVICES_DISPATCHED',
        result: 'SUCCESS',
        notes: 'Test incident closure'
      });
    }
    
  } catch (error) {
    console.error('❌ Incident management test failed:', error.message);
  }
}

testIncidentManagement();

Step 3: Agent Workflow Management

Implement Agent Management

Create agentManager.js:

javascript
import axios from 'axios';
import { API_CONFIG } from './config.js';

class AgentManager {
  constructor() {
    this.client = axios.create({
      baseURL: API_CONFIG.baseURL,
      headers: {
        'Authorization': `Bearer ${API_CONFIG.authToken}`,
        'Content-Type': 'application/json'
      },
      timeout: API_CONFIG.timeout
    });
  }

  async getAgentStatus(agentId) {
    try {
      const response = await this.client.get(`/acn/agents/${agentId}/status`);
      console.log('Agent Status:', response.data);
      return response.data;
    } catch (error) {
      console.error('Failed to get agent status:', error.response?.data || error.message);
      throw error;
    }
  }

  async getAgentIncidents(agentId, options = {}) {
    try {
      const params = {
        status: options.status,
        limit: options.limit || 50,
        offset: options.offset || 0
      };

      const response = await this.client.get(
        `/acn/agents/${agentId}/incidents`,
        { params }
      );

      console.log('Agent Incidents:', response.data);
      return response.data;
    } catch (error) {
      console.error('Failed to get agent incidents:', error.response?.data || error.message);
      throw error;
    }
  }

  calculateAgentWorkload(agentStatus, agentIncidents) {
    const workload = {
      currentIncidents: agentStatus.currentIncidents,
      totalHandled: agentStatus.totalHandled,
      averageHandlingTime: agentStatus.averageHandlingTime,
      isActive: agentStatus.status === 'ACTIVE',
      capacity: this.calculateCapacity(agentStatus),
      efficiency: this.calculateEfficiency(agentStatus, agentIncidents)
    };

    return workload;
  }

  calculateCapacity(agentStatus) {
    // Simple capacity calculation based on current incidents and average handling time
    const maxConcurrentIncidents = 3;
    const currentLoad = agentStatus.currentIncidents / maxConcurrentIncidents;
    
    if (currentLoad >= 1) return 'FULL';
    if (currentLoad >= 0.7) return 'HIGH';
    if (currentLoad >= 0.4) return 'MEDIUM';
    return 'LOW';
  }

  calculateEfficiency(agentStatus, agentIncidents) {
    // Calculate efficiency based on handling time and success rate
    const avgTime = parseFloat(agentStatus.averageHandlingTime);
    const targetTime = 10; // 10 minutes target
    
    const timeEfficiency = Math.max(0, Math.min(100, (targetTime / avgTime) * 100));
    
    return {
      timeEfficiency: timeEfficiency.toFixed(1),
      grade: timeEfficiency >= 90 ? 'A' : timeEfficiency >= 75 ? 'B' : timeEfficiency >= 60 ? 'C' : 'D'
    };
  }

  async assignIncidentToAgent(agentId, incidentId) {
    try {
      // This would typically be an internal API call
      // For demo purposes, we'll simulate the assignment
      console.log(`Assigning incident ${incidentId} to agent ${agentId}`);
      
      const assignment = {
        agentId,
        incidentId,
        assignedTime: new Date().toISOString(),
        status: 'ASSIGNED'
      };

      console.log('Incident Assigned:', assignment);
      return assignment;
    } catch (error) {
      console.error('Failed to assign incident:', error.message);
      throw error;
    }
  }
}

export default AgentManager;

Test Agent Management

Create test-agent.js:

javascript
import AgentManager from './agentManager.js';
import { API_CONFIG } from './config.js';

const agentManager = new AgentManager();

async function testAgentManagement() {
  const agentId = API_CONFIG.sampleAgentId;

  try {
    console.log('👮 Testing Agent Management...');
    
    // Get agent status
    const status = await agentManager.getAgentStatus(agentId);
    
    // Get agent incidents
    const incidents = await agentManager.getAgentIncidents(agentId);
    
    // Calculate workload
    const workload = agentManager.calculateAgentWorkload(status, incidents);
    
    console.log('📊 Agent Workload Analysis:', {
      agentId: status.agentId,
      status: status.status,
      currentIncidents: workload.currentIncidents,
      capacity: workload.capacity,
      efficiency: workload.efficiency,
      totalHandled: workload.totalHandled
    });
    
    // Simulate incident assignment
    if (workload.capacity !== 'FULL' && incidents.activeCount < 3) {
      await agentManager.assignIncidentToAgent(agentId, 'ACN_TEST_001');
    }
    
  } catch (error) {
    console.error('❌ Agent management test failed:', error.message);
  }
}

testAgentManagement();

Step 4: Real-time Emergency Notifications

Implement SSE Client for ACN

Create acnSSEClient.js:

javascript
export class ACNSSEClient {
  constructor(url, authToken) {
    this.url = url;
    this.authToken = authToken;
    this.eventSource = null;
    this.listeners = new Map();
    this.incidentHandlers = new Map();
  }

  connect() {
    return new Promise((resolve, reject) => {
      try {
        this.eventSource = new EventSource(this.url, {
          headers: {
            'Authorization': `Bearer ${this.authToken}`
          }
        });

        this.eventSource.onopen = () => {
          console.log('🚨 ACN SSE connection opened');
          resolve();
        };

        this.eventSource.onerror = (error) => {
          console.error('ACN SSE connection error:', error);
          if (this.eventSource.readyState === EventSource.CLOSED) {
            reject(new Error('ACN SSE connection closed'));
          }
        };

        this.eventSource.onmessage = (event) => {
          try {
            const data = JSON.parse(event.data);
            this.handleEvent(data);
          } catch (error) {
            console.error('Failed to parse ACN SSE data:', error);
          }
        };

      } catch (error) {
        reject(error);
      }
    });
  }

  on(eventType, callback) {
    if (!this.listeners.has(eventType)) {
      this.listeners.set(eventType, []);
    }
    this.listeners.get(eventType).push(callback);
  }

  handleEvent(data) {
    const eventType = data.type || 'default';
    const callbacks = this.listeners.get(eventType) || [];
    
    callbacks.forEach(callback => {
      try {
        callback(data);
      } catch (error) {
        console.error('Error in ACN event callback:', error);
      }
    });

    // Handle specific incident events
    if (eventType === 'INCIDENT_CREATED') {
      this.handleIncidentCreated(data);
    } else if (eventType === 'INCIDENT_UPDATED') {
      this.handleIncidentUpdated(data);
    }
  }

  handleIncidentCreated(data) {
    console.log('🚨 NEW INCIDENT CREATED:', data.data.cid);
    
    const incident = data.data;
    const severity = this.assessIncidentSeverity(incident.severity, incident.trigger);
    
    console.log(`📍 Location: ${incident.location.latitude}, ${incident.location.longitude}`);
    console.log(`🔥 Severity: ${severity.color} ${incident.severity}`);
    console.log(`⚡ Trigger: ${incident.trigger}`);
    
    // Trigger emergency response workflow
    this.triggerEmergencyWorkflow(incident);
  }

  handleIncidentUpdated(data) {
    console.log('📝 INCIDENT UPDATED:', data.data.cid);
    console.log('Status:', data.data.status);
  }

  assessIncidentSeverity(severity, trigger) {
    const severityLevels = {
      'LOW': { priority: 3, responseTime: '15 min', color: '🟡' },
      'MEDIUM': { priority: 2, responseTime: '10 min', color: '🟠' },
      'HIGH': { priority: 1, responseTime: '5 min', color: '🔴' },
      'CRITICAL': { priority: 0, responseTime: 'Immediate', color: '🚨' }
    };

    const triggerSeverity = {
      'AIRBAG_DEPLOYMENT': 'HIGH',
      'ROLLOVER_DETECTED': 'CRITICAL',
      'IMPACT_DETECTED': 'MEDIUM',
      'MANUAL_SOS': 'HIGH',
      'SOS_BUTTON': 'HIGH'
    };

    const assessedSeverity = severity || triggerSeverity[trigger] || 'MEDIUM';
    return severityLevels[assessedSeverity] || severityLevels['MEDIUM'];
  }

  triggerEmergencyWorkflow(incident) {
    console.log('🚑 Triggering emergency response workflow...');
    
    // Simulate emergency response steps
    const workflow = [
      { step: 1, action: 'Verify incident details', delay: 1000 },
      { step: 2, action: 'Contact emergency services', delay: 2000 },
      { step: 3, action: 'Dispatch rescue team', delay: 1500 },
      { step: 4, action: 'Update incident status', delay: 1000 }
    ];

    workflow.forEach(({ step, action, delay }) => {
      setTimeout(() => {
        console.log(`  Step ${step}: ${action}`);
      }, delay);
    });
  }

  disconnect() {
    if (this.eventSource) {
      this.eventSource.close();
      this.eventSource = null;
      console.log('ACN SSE connection closed');
    }
  }
}

Test Real-time Notifications

Create test-sse.js:

javascript
import { ACNSSEClient } from './acnSSEClient.js';
import { API_CONFIG } from './config.js';

async function testRealTimeNotifications() {
  const sseUrl = `${API_CONFIG.baseURL}/acn/events`;
  
  const sseClient = new ACNSSEClient(sseUrl, API_CONFIG.authToken);

  try {
    await sseClient.connect();

    // Listen for incident events
    sseClient.on('INCIDENT_CREATED', (data) => {
      console.log('🚨 New incident detected:', data.data);
    });

    sseClient.on('INCIDENT_UPDATED', (data) => {
      console.log('📝 Incident updated:', data.data);
    });

    sseClient.on('RESCUE_DISPATCHED', (data) => {
      console.log('🚑 Rescue dispatched:', data.data);
    });

    console.log('👂 Listening for ACN events... Press Ctrl+C to stop');

    // Keep the connection alive
    process.on('SIGINT', () => {
      console.log('\nDisconnecting...');
      sseClient.disconnect();
      process.exit(0);
    });

  } catch (error) {
    console.error('Failed to connect to ACN SSE:', error.message);
  }
}

testRealTimeNotifications();

Step 5: Emergency Response Coordination

Implement Emergency Response System

Create emergencyResponse.js:

javascript
import IncidentManager from './incidentManager.js';
import AgentManager from './agentManager.js';

class EmergencyResponseSystem {
  constructor() {
    this.incidentManager = new IncidentManager();
    this.agentManager = new AgentManager();
    this.activeIncidents = new Map();
    this.agentAssignments = new Map();
  }

  async handleNewIncident(incidentData) {
    try {
      console.log('🚨 Handling new incident:', incidentData.cid);
      
      // Assess incident severity
      const severity = this.incidentManager.assessIncidentSeverity(
        incidentData.severity, 
        incidentData.trigger
      );
      
      // Find available agent
      const agentId = await this.findAvailableAgent(severity.priority);
      
      if (agentId) {
        // Assign incident to agent
        await this.assignIncidentToAgent(incidentData.cid, agentId);
        
        // Coordinate emergency services
        await this.coordinateEmergencyServices(incidentData, severity);
        
        // Track incident
        this.activeIncidents.set(incidentData.cid, {
          ...incidentData,
          assignedAgent: agentId,
          severity,
          status: 'ASSIGNED',
          timestamp: new Date().toISOString()
        });
        
        console.log(`✅ Incident ${incidentData.cid} assigned to agent ${agentId}`);
      } else {
        console.log(`⚠️ No available agents for incident ${incidentData.cid}`);
        await this.queueIncident(incidentData);
      }
      
    } catch (error) {
      console.error('Failed to handle new incident:', error.message);
    }
  }

  async findAvailableAgent(priority) {
    try {
      // Get list of available agents (simplified for demo)
      const agents = [API_CONFIG.sampleAgentId];
      
      for (const agentId of agents) {
        const status = await this.agentManager.getAgentStatus(agentId);
        const incidents = await this.agentManager.getAgentIncidents(agentId);
        const workload = this.agentManager.calculateAgentWorkload(status, incidents);
        
        if (workload.isActive && workload.capacity !== 'FULL') {
          return agentId;
        }
      }
      
      return null;
    } catch (error) {
      console.error('Failed to find available agent:', error.message);
      return null;
    }
  }

  async assignIncidentToAgent(incidentId, agentId) {
    try {
      await this.agentManager.assignIncidentToAgent(agentId, incidentId);
      this.agentAssignments.set(agentId, (this.agentAssignments.get(agentId) || 0) + 1);
    } catch (error) {
      console.error('Failed to assign incident to agent:', error.message);
    }
  }

  async coordinateEmergencyServices(incidentData, severity) {
    console.log('🚑 Coordinating emergency services...');
    
    const emergencySteps = [
      { service: 'Police', priority: severity.priority <= 1 },
      { service: 'Fire Department', priority: severity.priority <= 2 },
      { service: 'Medical Services', priority: true },
      { service: 'Towing Service', priority: severity.priority <= 2 }
    ];

    for (const { service, priority } of emergencySteps) {
      if (priority) {
        console.log(`📞 Contacting ${service} for incident ${incidentData.cid}`);
        
        // Simulate service dispatch
        setTimeout(() => {
          console.log(`✅ ${service} dispatched to location: ${incidentData.location.latitude}, ${incidentData.location.longitude}`);
        }, Math.random() * 2000 + 1000);
      }
    }
  }

  async queueIncident(incidentData) {
    console.log(`📋 Queuing incident ${incidentData.cid} for later assignment`);
    // Implementation would add to a priority queue
  }

  async updateIncidentStatus(incidentId, newStatus, details = {}) {
    try {
      const incident = this.activeIncidents.get(incidentId);
      if (incident) {
        incident.status = newStatus;
        incident.lastUpdate = new Date().toISOString();
        incident.updateDetails = details;
        
        console.log(`📝 Updated incident ${incidentId} status to ${newStatus}`);
        
        if (newStatus === 'RESOLVED') {
          await this.closeIncident(incidentId);
        }
      }
    } catch (error) {
      console.error('Failed to update incident status:', error.message);
    }
  }

  async closeIncident(incidentId) {
    try {
      const incident = this.activeIncidents.get(incidentId);
      if (incident) {
        await this.incidentManager.closeIncident(incident.vin, {
          cid: incidentId,
          closureReason: 'EMERGENCY_SERVICES_COMPLETED',
          result: 'SUCCESS',
          agentId: incident.assignedAgent,
          notes: 'Emergency response completed successfully'
        });
        
        // Clean up tracking
        this.activeIncidents.delete(incidentId);
        
        if (incident.assignedAgent) {
          const currentCount = this.agentAssignments.get(incident.assignedAgent) || 0;
          this.agentAssignments.set(incident.assignedAgent, Math.max(0, currentCount - 1));
        }
        
        console.log(`✅ Incident ${incidentId} closed successfully`);
      }
    } catch (error) {
      console.error('Failed to close incident:', error.message);
    }
  }

  getActiveIncidents() {
    return Array.from(this.activeIncidents.values());
  }

  getAgentWorkload() {
    const workload = {};
    for (const [agentId, count] of this.agentAssignments) {
      workload[agentId] = count;
    }
    return workload;
  }
}

export default EmergencyResponseSystem;

Step 6: Complete ACN Application

Create Complete ACN System

Create acnApp.js:

javascript
import ACNSystem from './acnSystem.js';
import IncidentManager from './incidentManager.js';
import AgentManager from './agentManager.js';
import { ACNSSEClient } from './acnSSEClient.js';
import EmergencyResponseSystem from './emergencyResponse.js';
import { API_CONFIG } from './config.js';

class ACNApplication {
  constructor() {
    this.acnSystem = new ACNSystem();
    this.incidentManager = new IncidentManager();
    this.agentManager = new AgentManager();
    this.emergencySystem = new EmergencyResponseSystem();
    this.sseClient = null;
  }

  async initialize() {
    try {
      console.log('🚨 Initializing ACN Application...');
      
      // Check system health
      await this.checkSystemHealth();
      
      // Connect to real-time events
      await this.connectRealTimeEvents();
      
      // Initialize agent monitoring
      await this.initializeAgentMonitoring();
      
      console.log('✅ ACN Application initialized successfully');
    } catch (error) {
      console.error('❌ Failed to initialize ACN Application:', error.message);
    }
  }

  async checkSystemHealth() {
    console.log('🏥 Checking ACN System Health...');
    
    const health = await this.acnSystem.getSystemHealth();
    const status = this.acnSystem.getServiceStatus(health);
    
    if (status.isHealthy) {
      console.log('✅ ACN System is operational');
    } else {
      console.log('⚠️ ACN System has issues:');
      Object.entries(status.services).forEach(([service, serviceStatus]) => {
        if (serviceStatus !== 'ACTIVE') {
          console.log(`  - ${service}: ${serviceStatus}`);
        }
      });
    }
    
    const stats = await this.acnSystem.getStatistics();
    console.log('📊 Current Statistics:', stats);
  }

  async connectRealTimeEvents() {
    console.log('👂 Connecting to real-time events...');
    
    const sseUrl = `${API_CONFIG.baseURL}/acn/events`;
    this.sseClient = new ACNSSEClient(sseUrl, API_CONFIG.authToken);
    
    await this.sseClient.connect();
    
    this.sseClient.on('INCIDENT_CREATED', (data) => {
      this.handleNewIncident(data.data);
    });
    
    this.sseClient.on('INCIDENT_UPDATED', (data) => {
      this.handleIncidentUpdate(data.data);
    });
  }

  async initializeAgentMonitoring() {
    console.log('👮 Initializing agent monitoring...');
    
    const agentId = API_CONFIG.sampleAgentId;
    const status = await this.agentManager.getAgentStatus(agentId);
    const incidents = await this.agentManager.getAgentIncidents(agentId);
    const workload = this.agentManager.calculateAgentWorkload(status, incidents);
    
    console.log('📊 Agent Status:', {
      agentId: status.agentId,
      status: status.status,
      currentIncidents: workload.currentIncidents,
      capacity: workload.capacity,
      efficiency: workload.efficiency
    });
  }

  async handleNewIncident(incidentData) {
    console.log('🚨 Processing new incident:', incidentData.cid);
    
    try {
      // Get detailed incident information
      const vin = incidentData.vin || API_CONFIG.sampleVIN;
      const incidentStatus = await this.incidentManager.getIncidentStatus(vin, incidentData.cid);
      
      // Handle through emergency response system
      await this.emergencySystem.handleNewIncident(incidentStatus);
      
      // Display incident summary
      this.displayIncidentSummary(incidentStatus);
      
    } catch (error) {
      console.error('Failed to handle new incident:', error.message);
    }
  }

  async handleIncidentUpdate(incidentData) {
    console.log('📝 Processing incident update:', incidentData.cid);
    
    await this.emergencySystem.updateIncidentStatus(
      incidentData.cid,
      incidentData.status,
      incidentData
    );
  }

  displayIncidentSummary(incident) {
    const severity = this.incidentManager.assessIncidentSeverity(incident.severity, incident.trigger);
    const location = this.incidentManager.formatIncidentLocation(incident.location);
    
    console.log('\n🚨 INCIDENT SUMMARY');
    console.log('==================');
    console.log(`🆔 ID: ${incident.cid}`);
    console.log(`🚗 Vehicle: ${incident.vin}`);
    console.log(`🔥 Severity: ${severity.color} ${incident.severity}`);
    console.log(`⚡ Trigger: ${incident.trigger}`);
    console.log(`📍 Location: ${location.formatted}`);
    console.log(`🚑 Rescue Status: ${incident.rescueStatus}`);
    console.log(`⏰ Time: ${incident.timestamp}`);
    
    if (incident.estimatedArrival) {
      console.log(`🕐 ETA: ${incident.estimatedArrival}`);
    }
    
    console.log('==================\n');
  }

  async getSystemStatus() {
    console.log('\n📊 ACN SYSTEM STATUS');
    console.log('==================');
    
    const activeIncidents = this.emergencySystem.getActiveIncidents();
    const agentWorkload = this.emergencySystem.getAgentWorkload();
    
    console.log(`🚨 Active Incidents: ${activeIncidents.length}`);
    console.log(`👮 Agent Workload:`, agentWorkload);
    
    activeIncidents.forEach(incident => {
      console.log(`  - ${incident.cid}: ${incident.status} (Agent: ${incident.assignedAgent})`);
    });
    
    console.log('==================\n');
  }

  async shutdown() {
    console.log('🔄 Shutting down ACN Application...');
    
    if (this.sseClient) {
      this.sseClient.disconnect();
    }
    
    console.log('✅ ACN Application shutdown complete');
  }
}

// Example usage
async function main() {
  const app = new ACNApplication();
  
  try {
    await app.initialize();
    
    // Display system status periodically
    setInterval(async () => {
      await app.getSystemStatus();
    }, 30000); // Every 30 seconds
    
    // Handle graceful shutdown
    process.on('SIGINT', async () => {
      console.log('\n🔄 Received SIGINT, shutting down gracefully...');
      await app.shutdown();
      process.exit(0);
    });
    
    console.log('🚨 ACN Application is running... Press Ctrl+C to stop');
    
  } catch (error) {
    console.error('Application error:', error.message);
    process.exit(1);
  }
}

main();

Testing Your Implementation

Run the complete ACN application:

bash
node acnApp.js

Expected output:

🚨 Initializing ACN Application...
🏥 Checking ACN System Health...
✅ ACN System is operational
📊 Current Statistics: { totalIncidents: 1250, activeIncidents: 3, resolvedToday: 8, averageResponseTime: "4.5 min", successRate: 98.2 }
👂 Connecting to real-time events...
🚨 ACN SSE connection opened
👮 Initializing agent monitoring...
📊 Agent Status: { agentId: "AGENT_001", status: "ACTIVE", currentIncidents: 2, capacity: "MEDIUM", efficiency: { timeEfficiency: "85.0", grade: "B" } }
✅ ACN Application initialized successfully
🚨 ACN Application is running... Press Ctrl+C to stop

🚨 NEW INCIDENT CREATED: ACN_20260307_002
📍 Location: 37.4021, 127.1023
🔥 Severity: 🔴 HIGH
⚡ Trigger: AIRBAG_DEPLOYMENT
🚑 Triggering emergency response workflow...
  Step 1: Verify incident details
  Step 2: Contact emergency services
  Step 3: Dispatch rescue team
  Step 4: Update incident status
✅ Incident ACN_20260307_002 assigned to agent AGENT_001

🚨 INCIDENT SUMMARY
==================
🆔 ID: ACN_20260307_002
🚗 Vehicle: KMHSH81C7LU123456
🔥 Severity: 🔴 HIGH
⚡ Trigger: AIRBAG_DEPLOYMENT
📍 Location: 37.4021, 127.1023
🚑 Rescue Status: DISPATCHED
⏰ Time: 2026-03-07T14:30:00Z
🕐 ETA: 2026-03-07T14:45:00Z
==================

Challenge Exercises

  1. Multi-Agency Coordination: Implement coordination between multiple emergency agencies with different response protocols.

  2. Predictive Analytics: Add predictive analytics to estimate accident severity based on vehicle telemetry data.

  3. Mobile Integration: Create a mobile app interface for users to manually trigger SOS and receive updates.

  4. Incident Reporting: Generate detailed incident reports for insurance and legal purposes.

  5. Geospatial Analysis: Implement geospatial analysis to identify accident hotspots and optimize rescue resource placement.

Summary

In this codelab, you learned how to:

  • ✅ Implement ACN incident detection and management
  • ✅ Handle real-time emergency notifications via SSE
  • ✅ Manage agent workflows and incident assignment
  • ✅ Coordinate emergency response services
  • ✅ Build a complete emergency response system

The ACN API provides critical infrastructure for handling vehicle accidents and coordinating emergency response. The implementation patterns you learned here emphasize reliability, real-time processing, and life-saving coordination.

Additional Resources

Released under the MIT License.