Files
StorageSecurity/Particle/docs/troubleshooting.md

30 KiB

Particle Boron Security Device Troubleshooting Guide

Comprehensive troubleshooting guide for diagnosing and resolving common issues with the ultra-low-power security device system.

🚨 Quick Diagnostic Checklist

Emergency Troubleshooting (Device Not Responding)

□ Check power LED on Boron (should be solid/breathing)
□ Verify battery voltage (>3.0V for operation)
□ Test microswitch manually (should trigger alarm)
□ Check cellular signal strength (>-85dBm preferred)
□ Verify SIM card seating and activation
□ Try safe mode recovery (SETUP+RESET procedure)

System Health Indicators

✅ HEALTHY SYSTEM:
- Status LED: Occasional brief flashes
- Battery reports: Daily via webhook
- Alarm response: <1 second trigger time
- Cellular connection: <60 seconds to connect
- Sleep current: 130μA ± 20μA

⚠️ WARNING SIGNS:
- No daily battery reports for >48 hours
- Alarm delay >5 seconds
- High power consumption (battery drain)
- Frequent connection failures
- Unexpected device resets

🚨 CRITICAL ISSUES:
- No response to manual testing
- Device constantly resetting
- Power consumption >1mA in sleep
- Complete loss of cellular connectivity
- Mechanical failure of sensors/alarm

🔋 Power and Battery Issues

Problem: High Power Consumption

Symptoms:

  • Battery draining faster than expected
  • Device feels warm to touch
  • Sleep current >200μA

Diagnostic Steps:

# 1. Measure sleep current
# Expected: 130μA ± 20μA
# Use μCurrent Gold or similar precision meter

# 2. Check for software issues
particle serial monitor
# Look for continuous output (should be silent in sleep)

# 3. Verify sleep mode entry
# Device should enter STOP mode within 10 seconds of last activity

Common Causes and Solutions:

Serial Interface Left Open:

// ❌ WRONG - Prevents sleep
void setup() {
    Serial.begin(9600);  // Remove this line!
    // rest of setup
}

// ✅ CORRECT - No serial in production
void setup() {
    // Serial.begin(9600);  // Commented out
    // rest of setup
}

Incorrect Pin Configuration:

// ✅ Add to setup() function
void configurePowerOptimalPins() {
    // Configure unused pins to prevent floating
    pinMode(A0, INPUT_PULLDOWN);
    pinMode(A1, INPUT_PULLDOWN);
    pinMode(A2, INPUT_PULLDOWN);
    pinMode(A3, INPUT_PULLDOWN);
    pinMode(A4, INPUT_PULLDOWN);
    pinMode(A5, INPUT_PULLDOWN);
    pinMode(D0, INPUT_PULLDOWN);
    pinMode(D1, INPUT_PULLDOWN);
    pinMode(D4, INPUT_PULLDOWN);
    pinMode(D5, INPUT_PULLDOWN);
    pinMode(D6, INPUT_PULLDOWN);
    pinMode(D8, INPUT_PULLDOWN);
    
    // Keep D2 (sensor), D3 (alarm), D7 (status) as configured
}

Stuck in Active Loop:

// ❌ WRONG - Prevents sleep
void loop() {
    while (someCondition) {
        // Infinite loop prevents sleep
    }
}

// ✅ CORRECT - Always allow sleep
void loop() {
    if (someCondition) {
        // Handle condition
    }
    // Loop exits, device can sleep
}

Problem: Battery Not Charging (Solar Setup)

Symptoms:

  • Battery level decreasing despite solar panel
  • Charge controller not showing charging status

Diagnostic Steps:

# 1. Check solar panel voltage
# Expected: 6V+ in direct sunlight
multimeter across panel terminals

# 2. Check charge controller input/output
# Input: Should match panel voltage
# Output: Should be 4.1-4.2V when charging

# 3. Check battery connection
# Ensure JST connector properly seated
# Verify polarity (red=+, black=-)

Solutions:

  • Clean solar panel surface
  • Check all connections for corrosion
  • Verify charge controller wiring
  • Test battery capacity with external charger

Problem: Inaccurate Battery Readings

Symptoms:

  • Battery percentage jumps unexpectedly
  • Reports 0% or >100% charge

Solution:

// Add battery reading validation
float getValidBatteryLevel() {
    float reading = System.batteryCharge();
    
    // Filter obviously invalid readings
    if (reading < 0 || reading > 100) {
        return lastValidReading;  // Use previous value
    }
    
    // Filter large jumps (>20% change)
    if (abs(reading - lastValidReading) > 20) {
        return lastValidReading;  // Reject sudden changes
    }
    
    lastValidReading = reading;
    return reading;
}

📡 Cellular and Connectivity Issues

Problem: Device Won't Connect to Cellular

Symptoms:

  • No daily battery reports received
  • Events show "Connection timeout" in logs
  • Cellular LED patterns indicate no connection

Diagnostic Steps:

Check Signal Strength:

# Use Particle CLI to check signal
particle get YOUR_DEVICE_ID signal

# Expected values:
# >-70dBm: Excellent
# -70 to -85dBm: Good  
# -85 to -100dBm: Fair
# <-100dBm: Poor (may not connect)

Check SIM Card Status:

# Verify SIM is active
particle sim list

# Check data usage
particle sim usage YOUR_SIM_ID

Test Manual Connection:

// Add to device code for testing
void testCellularConnection() {
    Serial.begin(9600);
    Serial.println("Testing cellular connection...");
    
    Cellular.on();
    Serial.println("Cellular radio on");
    
    waitFor(Cellular.ready, 60000);
    if (Cellular.ready()) {
        Serial.println("Cellular ready");
        
        CellularSignal signal = Cellular.RSSI();
        Serial.printf("Signal: %d dBm\n", signal.getStrength());
        Serial.printf("Quality: %d\n", signal.getQuality());
    } else {
        Serial.println("Cellular failed to connect");
    }
}

Common Solutions:

Poor Signal Strength:

  • Relocate device to higher position
  • Install external cellular antenna
  • Use cellular signal booster
  • Switch to different carrier if available

SIM Card Issues:

  • Reseat SIM card in holder
  • Check SIM activation status
  • Verify data plan is active
  • Replace SIM if damaged

Network Configuration:

// Force specific network settings if needed
void setNetworkParameters() {
    // Set APN if required by carrier
    Cellular.setActiveSim(EXTERNAL_SIM);
    
    // Set specific bands if needed
    // Cellular.setBandSelect("...");
}

Problem: Slow Cellular Connections

Symptoms:

  • Connection takes >2 minutes
  • High power consumption during connection
  • Timeouts during data transfer

Solutions:

Optimize Connection Sequence:

bool fastCellularConnect() {
    unsigned long start = millis();
    
    // Enable cellular with timeout
    Cellular.on();
    if (!waitFor(Cellular.ready, 30000)) {
        Serial.println("Cellular radio timeout");
        return false;
    }
    
    // Connect to Particle cloud with timeout
    Particle.connect();
    if (!waitFor(Particle.connected, 60000)) {
        Serial.println("Cloud connection timeout");
        return false;
    }
    
    Serial.printf("Connected in %lu seconds\n", (millis() - start) / 1000);
    return true;
}

Use Connection Keep-Alive:

void setup() {
    // Maintain network registration between sleeps
    Particle.keepAlive(120);  // 2 minutes
}

Problem: Data Usage Higher Than Expected

Symptoms:

  • Monthly data usage >10MB
  • Carrier data overage charges
  • Frequent connection events

Analysis:

# Check Particle data usage
particle sim usage YOUR_SIM_ID

# Review webhook frequency
# Should be 1-2 events per day normally

Solutions:

Reduce Message Size:

// Compact data format
String createCompactAlert() {
    // Before: "Type:SECURITY_BREACH|Description:Motion detected|Battery:85.2%|Signal:-45dBm"
    // After: "T:BREACH|D:Motion|B:85|S:-45"
    
    return String::format("T:%s|D:%s|B:%d|S:%d",
        getAlertTypeCode(),
        getShortDescription(), 
        (int)System.batteryCharge(),
        Cellular.RSSI().getStrength()
    );
}

Batch Multiple Events:

void batchEventReporting() {
    static String eventBuffer = "";
    
    eventBuffer += createEventData() + ";";
    
    // Send when buffer reaches size limit or time limit
    if (eventBuffer.length() > 200 || shouldSendBatch()) {
        Particle.publish("Batch_Events", eventBuffer, PRIVATE);
        eventBuffer = "";
    }
}

🔧 Hardware Issues

Problem: Microswitch Not Triggering

Symptoms:

  • No alarm when switch is manually opened
  • Security breaches not detected
  • Switch reads same value regardless of position

Diagnostic Steps:

Test Switch Continuity:

# Use multimeter to test switch
# Closed position: 0Ω resistance
# Open position: ∞Ω (no continuity)

Test Boron Input:

// Add diagnostic code
void testMicroswitchInput() {
    Serial.begin(9600);
    
    while (true) {
        bool switchState = digitalRead(MICROSWITCH_PIN);
        Serial.printf("Switch state: %s\n", switchState ? "CLOSED" : "OPEN");
        delay(500);
    }
}

Common Issues and Solutions:

Wiring Error:

✅ CORRECT NC WIRING:
Microswitch Common → D2 (Boron)
Microswitch NC → GND (Boron)

❌ INCORRECT (NO/Normal Open):
Microswitch Common → D2 (Boron)  
Microswitch NO → GND (Boron)

Mechanical Issues:

  • Check switch mounting alignment
  • Verify actuator travel distance
  • Lubricate switch if sticky
  • Replace switch if worn out

Electrical Issues:

  • Check for loose connections
  • Verify wire gauge (22-18 AWG recommended)
  • Test for electrical noise/interference
  • Add hardware debouncing if needed

Problem: Alarm Not Activating

Symptoms:

  • Switch triggers detected but no alarm sound
  • Alarm device doesn't activate
  • D3 pin voltage incorrect

Diagnostic Steps:

Test GPIO Output:

void testAlarmOutput() {
    Serial.begin(9600);
    
    Serial.println("Testing alarm output...");
    
    // Test D3 voltage
    digitalWrite(ALARM_PIN, HIGH);
    Serial.println("D3 should be 3.3V - measure with multimeter");
    delay(5000);
    
    digitalWrite(ALARM_PIN, LOW);
    Serial.println("D3 should be 0V - measure with multimeter");
    delay(5000);
}

Check Driver Circuit:

For transistor driver circuit:
1. Measure base voltage (should be 3.3V when D3=HIGH)
2. Check transistor collector voltage (should be ~0V when ON)
3. Verify alarm device voltage across terminals
4. Test transistor with known good component

Common Solutions:

Driver Circuit Issues:

Component Checklist:
□ 2N2222 transistor (or equivalent NPN)
□ 1kΩ base resistor
□ Proper ground connections
□ Adequate current rating for alarm device

Voltage Tests:
□ D3 output: 0V (LOW) / 3.3V (HIGH)
□ Base voltage: 0V (OFF) / 3.3V (ON)
□ Collector: VIN (OFF) / ~0V (ON)
□ Emitter: Always 0V (GND)

Alarm Device Issues:

  • Check power requirements vs available current
  • Verify voltage compatibility
  • Test alarm device independently
  • Check for blown fuse in alarm circuit

Problem: Status LED Behavior Issues

Symptoms:

  • LED constantly on/off
  • Unexpected flash patterns
  • LED not responding to events

Normal LED Patterns:

Startup:           3 slow blinks (500ms each)
Security Breach:   5 rapid blinks (100ms each)  
Daily Report:      2 medium blinks (200ms each)
Cellular Connect:  Alternating during connection
Success:           2 quick blinks (100ms each)
Error:             10 rapid blinks (50ms each)

Diagnostic Code:

void testStatusLED() {
    Serial.begin(9600);
    Serial.println("Testing status LED patterns...");
    
    // Test each pattern
    flashStatusLED(3, 500);   // Startup pattern
    delay(2000);
    flashStatusLED(5, 100);   // Breach pattern  
    delay(2000);
    flashStatusLED(2, 200);   // Report pattern
}

🌐 Webhook and Server Issues

Problem: Webhook Not Receiving Events

Symptoms:

  • Particle Console shows events published
  • No notifications received
  • Webhook service logs show no activity

Diagnostic Steps:

Test Particle Event Publishing:

# Check if device is publishing events
particle subscribe YOUR_DEVICE_ID

# Manually trigger test event
particle publish "Security Alert" "Type:TEST|Desc:Manual test" --private

Test Webhook Endpoint:

# Test webhook health
curl https://webhook.yourdomain.com/health

# Test webhook with manual POST
curl -X POST https://webhook.yourdomain.com/webhook \
  -H "Content-Type: application/json" \
  -H "User-Agent: ParticleBot/1.0" \
  -H "Authorization: Bearer YOUR_PARTICLE_SECRET" \
  -d '{"event":"Security Alert","data":"Type:TEST|Desc:Manual webhook test","published_at":"2024-01-07T12:00:00Z","coreid":"test","device_name":"Test Device"}'

Check Webhook Configuration:

Particle Console Webhook Settings:

{
  "event": "Security Alert",
  "url": "https://webhook.yourdomain.com/webhook",
  "headers": {
    "Authorization": "Bearer YOUR_SECRET_HERE",
    "Content-Type": "application/json",
    "User-Agent": "ParticleBot/1.0"
  }
}

Common Solutions:

Authentication Issues:

# Verify webhook secret matches
docker exec webhook-service env | grep PARTICLE_WEBHOOK_SECRET

# Check webhook service logs
docker compose logs webhook-service | grep -i auth

SSL/TLS Issues:

# Test SSL certificate
openssl s_client -connect webhook.yourdomain.com:443

# Check certificate expiration
curl -vI https://webhook.yourdomain.com/health

Network Connectivity:

# Test from external network
curl -I https://webhook.yourdomain.com/health

# Check DNS resolution
nslookup webhook.yourdomain.com

Problem: Notifications Not Being Sent

Symptoms:

  • Webhook receives events successfully
  • No email/SMS notifications received
  • Webhook logs show email errors

Diagnostic Steps:

Test SMTP Configuration:

# Test Gmail SMTP from webhook container
docker exec webhook-service python3 -c "
import smtplib
import os
try:
    with smtplib.SMTP_SSL('smtp.gmail.com', 465) as server:
        server.login(os.environ['SMTP_EMAIL'], os.environ['SMTP_PASSWORD'])
    print('SMTP connection successful')
except Exception as e:
    print(f'SMTP error: {e}')
"

Common Solutions:

Gmail Authentication Issues:

Common Problems:
□ Using regular password instead of app password
□ App password contains spaces (remove them)
□ 2FA not enabled on Google account
□ App password expired or revoked

Solution:
1. Enable 2FA on Google account
2. Generate new app password at https://myaccount.google.com/apppasswords
3. Use 16-character app password (no spaces)
4. Update .env file with new password

SMS Gateway Issues:

Common Carrier Gateways:
□ Verizon: number@vtext.com
□ AT&T: number@txt.att.net  
□ T-Mobile: number@tmomail.net
□ Sprint: number@messaging.sprintpcs.com

Test SMS Gateway:
1. Send test email to your SMS gateway address
2. Verify format: 10-digit number (no dashes/spaces)
3. Check carrier-specific limitations

🔄 Device Reset and Recovery

Safe Mode Recovery

When to Use:

  • Device constantly resetting
  • Firmware appears corrupted
  • Device not responding to OTA updates

Procedure:

# Enter safe mode
1. Hold SETUP button
2. Press and release RESET button (while holding SETUP)
3. Continue holding SETUP until LED breathes magenta
4. Release SETUP button

# Device is now in safe mode (breathing magenta)
# Flash firmware via CLI
particle flash YOUR_DEVICE_ID security_device.ino --target 5.8.0

DFU Mode Recovery

When to Use:

  • Safe mode doesn't work
  • Device completely unresponsive
  • Need to flash system firmware

Procedure:

# Enter DFU mode
1. Hold SETUP and RESET buttons
2. Release RESET while continuing to hold SETUP
3. Wait for LED to blink yellow rapidly
4. Release SETUP button

# Device is now in DFU mode (yellow blinking)
# Flash tinker firmware to reset
particle flash --usb tinker

# Then flash your application
particle flash YOUR_DEVICE_ID security_device.ino

Factory Reset

Complete Device Reset:

# Clear all user firmware and data
particle device doctor YOUR_DEVICE_ID

# This will:
# - Reset device keys
# - Clear user firmware  
# - Reset to factory state
# - Require device re-claiming

🔍 Advanced Diagnostics

Real-Time Monitoring Setup

Hardware Debug Setup:

Equipment Needed:
□ Logic analyzer or oscilloscope
□ μCurrent Gold (current measurement)
□ Multimeter
□ USB-to-serial adapter
□ Jumper wires and test probes

Monitoring Points:
□ VIN: Power supply voltage
□ D2: Microswitch state changes  
□ D3: Alarm output signal
□ D7: Status LED activity
□ TX/RX: Serial debug output (if enabled)

Software Debug Mode:

// Enable comprehensive debugging (REMOVE in production)
#define DEBUG_MODE
#ifdef DEBUG_MODE

void debugLog(String component, String message) {
    String timestamp = String(millis());
    Serial.println(timestamp + " [" + component + "] " + message);
}

void debugSystemState() {
    debugLog("POWER", "Battery: " + String(System.batteryCharge()) + "%");
    debugLog("NETWORK", "Signal: " + String(Cellular.RSSI().getStrength()) + "dBm");
    debugLog("GPIO", "D2: " + String(digitalRead(D2)) + ", D3: " + String(digitalRead(D3)));
    debugLog("MEMORY", "Free RAM: " + String(System.freeMemory()) + " bytes");
    debugLog("SYSTEM", "Uptime: " + String(millis() / 1000) + " seconds");
}

#else
#define debugLog(component, message)
#define debugSystemState()
#endif

Performance Profiling

Power Consumption Profiling:

void profilePowerConsumption() {
    unsigned long start, duration;
    
    // Profile cellular connection
    start = millis();
    Cellular.on();
    waitFor(Cellular.ready, 60000);
    duration = millis() - start;
    debugLog("PROFILE", "Cellular ready: " + String(duration) + "ms");
    
    // Profile cloud connection
    start = millis();
    Particle.connect();
    waitFor(Particle.connected, 60000);
    duration = millis() - start;
    debugLog("PROFILE", "Cloud connected: " + String(duration) + "ms");
    
    // Profile event publishing
    start = millis();
    Particle.publish("Test", "data", PRIVATE);
    duration = millis() - start;
    debugLog("PROFILE", "Event published: " + String(duration) + "ms");
}

Memory Usage Monitoring:

void monitorMemoryUsage() {
    static unsigned long lastCheck = 0;
    static int minFreeMemory = 999999;
    
    if (millis() - lastCheck > 10000) {  // Check every 10 seconds
        int freeMemory = System.freeMemory();
        if (freeMemory < minFreeMemory) {
            minFreeMemory = freeMemory;
        }
        
        debugLog("MEMORY", "Free: " + String(freeMemory) + 
                          ", Min: " + String(minFreeMemory) + " bytes");
        lastCheck = millis();
    }
}

Log Analysis and Pattern Detection

Event Pattern Analysis:

# Python script to analyze webhook logs
import re
import json
from datetime import datetime
from collections import defaultdict

def analyze_webhook_logs(log_file):
    events = defaultdict(list)
    power_data = []
    
    with open(log_file, 'r') as f:
        for line in f:
            # Parse timestamp and event type
            if 'Received webhook:' in line:
                timestamp = extract_timestamp(line)
                event_data = extract_event_data(line)
                events[event_data['type']].append(timestamp)
                
                if 'Batt:' in line:
                    battery = extract_battery_level(line)
                    power_data.append((timestamp, battery))
    
    # Analyze patterns
    print(f"Security breaches: {len(events['SECURITY_BREACH'])}")
    print(f"Daily reports: {len(events['DAILY_BATTERY_REPORT'])}")
    print(f"Average time between breaches: {calculate_average_interval(events['SECURITY_BREACH'])}")
    
    # Battery trend analysis
    if len(power_data) > 10:
        battery_trend = calculate_battery_trend(power_data)
        print(f"Battery drain rate: {battery_trend:.2f}% per day")

def extract_battery_level(line):
    match = re.search(r'Batt:(\d+\.?\d*)%', line)
    return float(match.group(1)) if match else None

# Usage: python analyze_logs.py webhook.log

Network Diagnostics

Cellular Network Analysis:

void analyzeCellularNetwork() {
    CellularSignal signal = Cellular.RSSI();
    CellularData data = Cellular.getDataUsage();
    
    debugLog("CELLULAR", "Provider: " + Cellular.getOperator());
    debugLog("CELLULAR", "Technology: " + String(Cellular.getTechnology()));
    debugLog("CELLULAR", "Signal Strength: " + String(signal.getStrength()) + " dBm");
    debugLog("CELLULAR", "Signal Quality: " + String(signal.getQuality()));
    debugLog("CELLULAR", "Data Used: " + String(data.tx_session + data.rx_session) + " bytes");
    
    // Test connection speed
    unsigned long start = millis();
    if (Particle.publish("Speed_Test", "test", PRIVATE)) {
        unsigned long latency = millis() - start;
        debugLog("CELLULAR", "Publish latency: " + String(latency) + "ms");
    }
}

DNS and Connectivity Testing:

void testConnectivity() {
    // Test different endpoints
    String endpoints[] = {
        "api.particle.io",
        "device.spark.io", 
        "google.com",
        "webhook.yourdomain.com"
    };
    
    for (String endpoint : endpoints) {
        unsigned long start = millis();
        TCPClient client;
        
        if (client.connect(endpoint, 80)) {
            unsigned long connectionTime = millis() - start;
            debugLog("CONNECTIVITY", endpoint + " connected in " + String(connectionTime) + "ms");
            client.stop();
        } else {
            debugLog("CONNECTIVITY", endpoint + " connection failed");
        }
    }
}

📊 Preventive Maintenance

Weekly Automated Checks

Device Self-Test Routine:

bool performWeeklyHealthCheck() {
    bool allTestsPassed = true;
    
    // Test 1: Battery level check
    float battery = System.batteryCharge();
    if (battery < 20.0) {
        publishAlert("MAINTENANCE", "Low battery: " + String(battery) + "%");
        allTestsPassed = false;
    }
    
    // Test 2: Cellular signal strength
    int signal = Cellular.RSSI().getStrength();
    if (signal < -90) {
        publishAlert("MAINTENANCE", "Weak signal: " + String(signal) + "dBm");
        allTestsPassed = false;
    }
    
    // Test 3: Memory usage check
    int freeMemory = System.freeMemory();
    if (freeMemory < 10000) {
        publishAlert("MAINTENANCE", "Low memory: " + String(freeMemory) + " bytes");
        allTestsPassed = false;
    }
    
    // Test 4: Switch operation test
    bool switchState = digitalRead(MICROSWITCH_PIN);
    // Record for trend analysis
    
    // Test 5: Alarm circuit test (brief pulse)
    digitalWrite(ALARM_PIN, HIGH);
    delay(100);
    digitalWrite(ALARM_PIN, LOW);
    
    if (allTestsPassed) {
        publishAlert("MAINTENANCE", "Weekly health check: PASS");
    }
    
    return allTestsPassed;
}

Monthly Maintenance Tasks

Automated Maintenance Reports:

# Server-side maintenance analysis
def generate_monthly_report(device_id, start_date, end_date):
    """Generate comprehensive device health report"""
    
    events = fetch_device_events(device_id, start_date, end_date)
    
    report = {
        'device_id': device_id,
        'period': f"{start_date} to {end_date}",
        'statistics': analyze_device_statistics(events),
        'battery_health': analyze_battery_trend(events),
        'connectivity': analyze_connectivity_stats(events),
        'security_events': count_security_events(events),
        'maintenance_needed': identify_maintenance_needs(events),
        'recommendations': generate_recommendations(events)
    }
    
    return report

def identify_maintenance_needs(events):
    """Identify potential maintenance requirements"""
    needs = []
    
    # Check battery degradation
    battery_trend = calculate_battery_trend(events)
    if battery_trend > 2.0:  # >2% per day indicates issues
        needs.append("Battery replacement recommended")
    
    # Check false alarm rate
    false_alarm_rate = calculate_false_alarm_rate(events)
    if false_alarm_rate > 0.1:  # >10% false alarms
        needs.append("Sensor calibration needed")
    
    # Check connectivity issues
    connection_success_rate = calculate_connection_success_rate(events)
    if connection_success_rate < 0.95:  # <95% success
        needs.append("Cellular antenna check recommended")
    
    return needs

Predictive Maintenance

Early Warning System:

void predictiveMaintenance() {
    static float batteryHistory[30];  // 30-day history
    static int historyIndex = 0;
    static bool historyFull = false;
    
    // Record daily battery level
    float currentBattery = System.batteryCharge();
    batteryHistory[historyIndex] = currentBattery;
    historyIndex = (historyIndex + 1) % 30;
    if (historyIndex == 0) historyFull = true;
    
    if (historyFull) {
        // Calculate battery drain trend
        float trend = calculateLinearTrend(batteryHistory, 30);
        
        // Predict battery life remaining
        float daysRemaining = currentBattery / abs(trend);
        
        if (daysRemaining < 90) {  // Less than 3 months
            publishAlert("PREDICTIVE", "Battery replacement needed in " + 
                        String((int)daysRemaining) + " days");
        }
    }
}

float calculateLinearTrend(float data[], int length) {
    // Simple linear regression to find trend
    float sumX = 0, sumY = 0, sumXY = 0, sumX2 = 0;
    
    for (int i = 0; i < length; i++) {
        sumX += i;
        sumY += data[i];
        sumXY += i * data[i];
        sumX2 += i * i;
    }
    
    float slope = (length * sumXY - sumX * sumY) / (length * sumX2 - sumX * sumX);
    return slope;  // % per day
}

🔧 Field Repair Procedures

Emergency Field Diagnostics

Minimal Equipment Diagnostics:

Required Tools:
□ Multimeter
□ Small screwdriver set
□ Spare battery (charged)
□ Mobile phone with Particle app

Quick Tests (5 minutes):
1. Check battery voltage (>3.0V)
2. Test microswitch continuity  
3. Verify alarm device operation
4. Check cellular signal strength via Particle app
5. Attempt manual event trigger

Field Diagnostic Checklist:

□ Visual inspection for physical damage
□ Check all wire connections for looseness
□ Verify enclosure seal integrity
□ Test battery voltage under load
□ Check for signs of water ingress
□ Verify antenna connections (if external)
□ Test switch mechanical operation
□ Check for insect/rodent interference

Remote Diagnostic Commands

Emergency Remote Access:

# Check device vitals
particle get YOUR_DEVICE_ID vitals

# Force connection test
particle function call YOUR_DEVICE_ID testConnection

# Get detailed diagnostics
particle function call YOUR_DEVICE_ID systemDiagnostics

# Force immediate battery report
particle function call YOUR_DEVICE_ID forceBatteryReport

Remote Recovery Commands:

# Safe restart
particle function call YOUR_DEVICE_ID safeRestart

# Force sleep mode
particle function call YOUR_DEVICE_ID forceSleep

# Emergency OTA update
particle flash YOUR_DEVICE_ID firmware_recovery.ino

# Factory reset (last resort)
particle device doctor YOUR_DEVICE_ID

📋 Troubleshooting Decision Tree

Device Issue Reported
        │
        ▼
   Is device responsive?
    ┌─NO─┐        ┌─YES─┐
    │    │        │     │
    ▼    │        ▼     │
Power Check    Check specific symptom
    │    │        │     │
    │    │        ▼     │
    │    │   Network Issue?
    │    │    ┌─YES─┐   ┌─NO─┐
    │    │    │     │   │    │
    │    │    ▼     │   ▼    │
    │    │ Cellular │Hardware│
    │    │Diagnostic│ Check  │
    │    │    │     │   │    │
    │    │    ▼     │   ▼    │
    │    │ Signal   │Sensor  │
    │    │  Test    │ Test   │
    │    │    │     │   │    │
    ▼    ▼    ▼     ▼   ▼    ▼
  Replace  Check   Fix  Test  Replace
  Battery  Power   Network Switch Component
     │    Supply     │    │      │
     ▼       │       ▼    ▼      ▼
   Test      │    Restart Reset  Test
   Device    ▼     Device System Function
     │    Replace      │    │      │
     ▼    Hardware     ▼    ▼      ▼
  Functional?       Works? Works? Works?
     │                │     │      │
     ▼                ▼     ▼      ▼
   SUCCESS         SUCCESS SUCCESS SUCCESS

📞 Support Escalation

When to Escalate

Level 1: Self-Service (User)

  • Basic connectivity issues
  • Simple configuration changes
  • Battery replacement
  • Environmental factors

Level 2: Technical Support

  • Persistent connectivity issues
  • Hardware component failures
  • Firmware corruption
  • Complex network problems

Level 3: Engineering Support

  • Design modifications needed
  • Systematic reliability issues
  • Performance optimization
  • Custom firmware requirements

Information to Gather Before Escalation

Device Information:

□ Device ID and name
□ Firmware version
□ Hardware revision
□ SIM card ID
□ Installation date
□ Last known working state
□ Environmental conditions

Issue Documentation:

□ Detailed symptom description
□ Frequency of occurrence
□ Steps already attempted
□ Error messages observed
□ Timeline of events
□ Impact on operations

Diagnostic Data:

□ Power consumption measurements
□ Signal strength readings
□ Event logs from webhook
□ Photos of hardware setup
□ Particle Console screenshots
□ Network configuration details

🔍 Quick Reference Summary:

Emergency Contacts:

  • Device Issues: Check Particle Community Forum
  • Server Issues: Check webhook service logs
  • Hardware Issues: Consult wiring diagrams
  • Network Issues: Test with Particle CLI

Most Common Issues:

  1. High power consumption → Check for Serial.begin() in code
  2. No cellular connection → Check signal strength and SIM status
  3. Switch not triggering → Verify NC wiring configuration
  4. No notifications → Check webhook authentication
  5. Device not sleeping → Remove debug code and configure pins

Recovery Procedures:

  1. Safe mode: SETUP+RESET → breathing magenta
  2. DFU mode: SETUP+RESET → yellow blinking
  3. Factory reset: particle device doctor
  4. OTA recovery: particle flash via CLI