System: ARMAC Current Fire Threats Dashboard
Version: Based on scripts dated 2024-2026
Location: Fairhaven, Victoria, Australia

This is a summary almost entirely produced by AI Claude 4.5 based on the full set of scripts that currently produce the two dashboards Current Fire Threats and Current Fire Comparisons. I have added a post script on how it could be further developed.

by Claude 4.5


1. System Overview

The fire threat calculation system is a multi-layered analysis pipeline that integrates real-time fire event data, satellite thermal detections, burnt area mapping, and meteorological information to produce actionable threat assessments for property defense. The system runs within a Home Assistant automation platform and produces continuous updates on fire proximity, direction, and estimated time to impact.

Key Components

  1. VicEmergency Event Monitoring (vic_events_compact.py)
  2. DEA Satellite Hotspot Clustering (dea_hotspot_cluster_front.py)
  3. FFMVic Burnt Area Boundary Tracking (ffm_burnt_area_front.py)
  4. Fire Geometry Selection Logic (Home Assistant templates)
  5. Rate of Spread (ROS) Calculation (Home Assistant templates)
  6. Wind Alignment and Threat Assessment (Home Assistant templates)
  7. ETA Calculations (Home Assistant templates)

2. Data Sources and Inputs

2.1 VicEmergency Events (Primary Source)

Script: vic_events_compact.py

Data Source: https://emergency.vic.gov.au/public/events-geojson.json

Purpose: Identifies active fire incidents within a configurable radius of the home location.

Processing:

  1. Fetches GeoJSON data from VicEmergency API (5-minute polling interval with 2-minute cache)
  2. Filters incidents within jf_relevance_radius_km (default: 200 km) of home
  3. Excludes planned burns (identified by category or plannedBurn flag)
  4. Calculates minimum distance from home to fire geometry:
    • For Polygon/MultiPolygon geometries: Distance to nearest polygon edge (0 if inside polygon)
    • For Point geometries: Haversine distance from point to home
    • Uses equirectangular projection for local distance calculations (accurate within few hundred km)
  5. Identifies fires as BUSHFIRE (bushFire, grassFire, forestFire event codes) or OTHER
  6. Maintains burnt_edge_ok flag for fires within jf_burnt_edge_match_km (default: 10 km)
  7. Returns up to 120 nearest incidents sorted by distance

Distance Calculation Method:

For Polygons:
  - Projects polygon boundary into local km coordinates (equirectangular)
  - Computes minimum distance from home (0,0) to each polygon edge segment
  - Uses ray-casting algorithm to determine if home is inside polygon
  - Returns 0 if inside, otherwise minimum edge distance

For Points:
  - Uses haversine formula: d = 2R × arcsin(√(sin²(Δlat/2) + cos(lat1)×cos(lat2)×sin²(Δlon/2)))
  - R = 6371.0 km (Earth radius)

Key Outputs:

  • List of fire incidents with: id, lat, lon, distance_km, burnt_edge_ok, geometry_kind, headline, location, status

2.2 DEA Satellite Hotspots (Active Fire Front Detection)

Script: dea_hotspot_cluster_front.py

Data Source: https://hotspots.dea.ga.gov.au/data/recent-hotspots.json (Digital Earth Australia)

Purpose: Identifies the active fire boundary using recent satellite thermal detections, providing a more current fire position than official burnt area polygons.

Processing:

  1. Fetches recent hotspot detections (last ~72 hours) with 2-minute caching
  2. Filters hotspots within configurable radius of home (default: 200 km)
  3. Further filters to hotspots within time window (default: 8 hours) of current time
  4. Performs density-based spatial clustering:
    • Algorithm: Connected components using union-find data structure
    • Edge threshold: jf_hotspots_eps_km (default: 2.0 km) - two hotspots are connected if within this distance
    • Minimum cluster size: jf_hotspots_min_points (default: 10 detections)
  5. Ranks significant clusters by proximity to anchor point (selected fire incident)
  6. For the best cluster, identifies the hotspot point nearest to home as the "active fire boundary"

Clustering Logic:

@] Given N hotspot points:

  1. Initialize union-find structure with N components
  2. For each pair of points (i,j):
    • If haversine_distance(i,j) ≤ eps_km:
      • Union(i, j) // Merge into same cluster
  3. Collect clusters where size ≥ min_points
  4. Score clusters: closest-to-anchor → closest-to-home → newest

@]

Key Parameters:

  • jf_hotspots_query_radius_km: 200 km (search radius from home)
  • jf_hotspots_time_window_hr: 8 hours (only recent detections)
  • jf_hotspots_eps_km: 2.0 km (clustering distance threshold)
  • jf_hotspots_min_points: 10 detections (minimum cluster size)
  • jf_hotspots_anchor_match_km: 20 km (maximum distance from incident point to accept cluster)

Key Outputs:

  • Distance to nearest hotspot in best cluster
  • Coordinates of nearest hotspot point
  • Cluster statistics (size, anchor distance, newest detection time)

2.3 FFMVic Burnt Area Mapping (Official Fire Perimeter)

Script: ffm_burnt_area_front.py

Data Source: https://maps.ffm.vic.gov.au/arcgis/rest/services/Incidents_all/MapServer/20/query (FFMVic - Forest Fire Management Victoria)

Purpose: Provides official burnt area polygon boundaries for distance and bearing calculations to the confirmed fire edge.

Processing:

  1. Queries ArcGIS MapServer for SUBTYPE=2 (Current Burnt Area) polygons within radius of anchor point
  2. Performs two-stage query strategy:
    • Query 1: Around selected fire incident point (default radius: 80 km)
    • Query 2: Around home point (expanded radius: 120-250 km) if name match fails in Query 1
  3. Name-based matching:
    • Normalizes incident names from VicEmergency and FFMVic (removes stopwords, common prefixes)
    • Tokenizes names (e.g., "Grampians Bushfire" → ["grampians", "bushfire"])
    • Requires minimum 2-token prefix match for association
    • Strips generic terms: bushfire, grassfire, fire, warning, watch, advice, emergency, planned, burn
  4. Calculates nearest point on polygon boundary to home using segment-by-segment projection
  5. Selection logic (priority order):
    • NAME_PREFIX: Incident name matches ≥2 tokens with FFMVic polygon name, closest to home
    • NAME_PREFIX_HOME_FALLBACK: Name match found in expanded home-centric query
    • RADIUS: No name match, uses closest polygon within 10 km of anchor point

Boundary Distance Calculation:

@] For each polygon ring:

  1. Convert polygon coordinates to equirectangular projection (km) centered at home
  2. For each edge segment (A,B):
    • Compute closest point C on segment to origin (home at 0,0)
    • t = -((A·v)/(v·v)) where v = B-A [parameterized closest point]
    • t = clamp(t, 0, 1) [restrict to segment]
    • C = A + t×v
    • distance = |C|
  3. Return minimum distance across all segments

@]

Key Parameters:

  • jf_burnt_area_query_radius_km: 80 km (initial query radius from anchor)
  • jf_burnt_edge_match_km: 10 km (maximum distance from anchor to accept polygon by proximity)
  • NAME_MIN_PREFIX_TOKENS: 2 (minimum matching tokens for name association)
  • HOME_FALLBACK_MIN_RADIUS_KM: 120 km (expanded search if initial query finds no name match)

Key Outputs:

  • Distance to nearest burnt area edge
  • Coordinates of nearest point on burnt area boundary
  • Incident ID and name from FFMVic
  • Match method used (NAME_PREFIX, RADIUS, etc.)

2.4 Meteorological Data (Wind and Weather)

Data Source: Bureau of Meteorology (BOM) - Aireys Inlet weather station

Parameters Collected:

  • Wind speed (km/h)
  • Wind direction (degrees, 0° = North)
  • Wind gust speed (km/h)
  • Air temperature (°C)
  • Relative humidity (%)
  • Dew point (°C)

Processing:

  • REST API polling (5-minute intervals)
  • Direct integration into Home Assistant sensors
  • Used for: - Wind alignment calculations (downwind threat assessment) - Rate of spread (ROS) phase determination - Fire behavior modeling

3. Fire Geometry Selection Logic

Purpose: Determines which data source provides the most accurate and current fire position for threat calculations.

Selection Hierarchy (Priority Order):

3.1 HOTSPOT_CLUSTER_EDGE (Highest Priority)

Conditions:

  • DEA hotspot cluster exists with valid distance
  • Cluster's anchor point matches selected fire incident (within 0.001° ~111m)
  • Cluster anchor distance ≤ jf_hotspots_anchor_match_km (20 km)

Rationale: Satellite thermal detections provide the most current active fire boundary, updated multiple times per day. Preferred when available as it represents actual burning, not just reported perimeter.

3.2 BURNT_AREA_EDGE (Medium Priority)

Conditions:

  • FFMVic burnt area polygon exists with valid distance
  • Polygon's anchor point matches selected fire incident (within 0.001°)
  • Polygon anchor distance ≤ jf_burnt_edge_match_km (10 km)
  • No valid hotspot cluster available

Rationale: Official mapped burnt area provides accurate perimeter when hotspots are unavailable or cloud-obscured. Updated less frequently (hours to days) but represents confirmed fire boundary.

3.3 INCIDENT_POINT (Fallback)

Conditions:

  • Neither hotspot cluster nor burnt area polygon meets criteria
  • Uses VicEmergency incident point coordinates

Rationale: Least accurate but always available. Provides approximate fire location when dynamic boundaries unavailable.

Implementation: Template sensor JF Fire Geometry Source evaluates conditions and sets state to one of three values.


4. Fire Distance and Bearing Calculations

4.1 Fire Distance to Home

Sensor: sensor.jf_fire_distance_km

Calculation Logic:

@]python IF using HOTSPOT_CLUSTER_EDGE:

    distance = hotspot_cluster_home_distance_km
  \\ELIF using BURNT_AREA_EDGE:
    distance = burnt_area_home_distance_km
  \\ELSE (INCIDENT_POINT):
    distance = haversine(fire_lat, fire_lon, home_lat, home_lon)

@]

Output: Distance in kilometers (2 decimal precision)

4.2 Fire Bearing to Home

Sensor: sensor.jf_fire_bearing_to_home_deg

Purpose: Calculates the compass bearing from the fire position to home. This is the direction the fire would need to travel to reach the property.

Calculation Method:

@] Uses spherical trigonometry (forward azimuth calculation):

Given:

  fire_lat, fire_lon = Fire position
  home_lat, home_lon = Home position

Convert to radians:

  lat1 = fire_lat × π/180
  lat2 = home_lat × π/180
  dlon = (home_lon - fire_lon) × π/180

Calculate bearing:

  y = sin(dlon) × cos(lat2)
  x = cos(lat1) × sin(lat2) - sin(lat1) × cos(lat2) × cos(dlon)
  bearing_rad = atan2(y, x)
  bearing_deg = (bearing_rad × 180/π + 360) mod 360

Output: 0-360° where 0° = North, 90° = East, 180° = South, 270° = West @]

Coordinate Source by Geometry Type:

  • HOTSPOT_CLUSTER_EDGE: Uses home_near_lat, home_near_lon from hotspot cluster
  • BURNT_AREA_EDGE: Uses home_near_lat, home_near_lon from burnt area boundary
  • INCIDENT_POINT: Uses jf_fire_lat, jf_fire_lon from VicEmergency

5. Wind Alignment and Downwind Threat Assessment

5.1 Wind Direction Processing

Sensor: sensor.jf_wind_towards_deg

Purpose: Converts BOM wind "from" direction to "towards" direction (direction wind is blowing).

Calculation: @] wind_towards = (wind_from + 180) mod 360 @]

Example: Wind from 270° (West) → blowing towards 90° (East)

5.2 Downwind Offset Angle

Sensor: sensor.jf_downwind_offset_deg

Purpose: Calculates the angular difference between wind direction and fire-to-home bearing.

Calculation: @] diff = fire_bearing_to_home - wind_towards diff_normalized = ((diff + 180) mod 360) - 180 // Range: -180° to +180° downwind_offset = |diff_normalized| // Absolute angular separation @]

Interpretation:

  • 0°: Fire directly upwind, wind blowing straight toward home
  • 90°: Fire to the side, wind blowing perpendicular
  • 180°: Fire downwind, wind blowing away from home

5.3 Downwind Threat Zone

Sensor: sensor.jf_is_home_downwind

Purpose: Boolean determination if home is within the primary fire spread cone.

Logic: @] half_angle = jf_downwind_half_angle_deg // Default: 40°

IF downwind_offset ≤ half_angle:

    is_home_downwind = "YES"

ELSE:

    is_home_downwind = "NO"

@]

Configuration Parameter: jf_downwind_half_angle_deg = 40° (default)

This creates an 80° cone (±40° from wind direction) representing the primary threat zone where the fire is most likely to spread.


6. Rate of Spread (ROS) Calculation

6.1 Fire Spread Phase Determination

Sensor: sensor.jf_fire_spread_phase

Purpose: Classifies fire behavior into three phases based on wind speed, using empirically-derived thresholds.

Wind Speed Thresholds:

  • jf_phase2_wind_kmh = 15 km/h (default)
  • jf_phase3_wind_kmh = 25 km/h (default)

Phase Classification:

@] wind_speed = BOM Aireys wind speed (km/h)

IF wind_speed < 15 km/h:

    Phase = I (Low wind - smoldering/backing fire)
  \\ELIF wind_speed < 25 km/h:
    Phase = II (Moderate wind - steady head fire)
  \\ELSE:
    Phase = III (High wind - running crown fire)

@]

6.2 Fire Front Rate of Spread (ROS)

Sensor: sensor.jf_fire_front_ros_kmh

Purpose: Estimates head fire spread rate using a piecewise-linear wind-ROS model with phase-dependent slopes.

Model Parameters:

  • jf_ros_k1 = 0.02 (Phase I slope coefficient)
  • jf_ros_k2 = 0.06 (Phase II slope coefficient)
  • jf_ros_k3 = 0.08 (Phase III slope coefficient)
  • jf_ros_min_kmh = 0.3 km/h (minimum ROS)
  • jf_ros_phase1_max_kmh = 1.2 km/h (Phase I ceiling)

Calculation Algorithm:

@]python

Get wind speed and thresholds

w = wind_speed_kmh w2 = 15 # Phase II threshold w3 = 25 # Phase III threshold

Phase I: Linear with floor and ceiling

ros1 = k1 × w ros1 = max(ros1, ros_min) # Apply minimum ros1 = min(ros1, ros1_max) # Apply maximum clamp

Phase II: Ensure continuity at phase boundary

ros1_at_w2 = k1 × w2 ros1_at_w2 = max(ros1_at_w2, ros_min) ros1_at_w2 = min(ros1_at_w2, ros1_max)

ros2 = k2 × w ros2 = max(ros2, ros1_at_w2) # Enforce continuity

Phase III: Unrestricted linear growth

ros3 = k3 × w

Select ROS based on current wind speed

IF w < w2:

    ROS = ros1

ELIF w < w3:

    ROS = ros2

ELSE:

    ROS = ros3

@]

Example Outputs:

  • 10 km/h wind → Phase I → ~0.30 km/h (minimum)
  • 20 km/h wind → Phase II → ~1.20 km/h
  • 40 km/h wind → Phase III → ~3.20 km/h
  • 60 km/h wind → Phase III → ~4.80 km/h

Model Rationale:

  • Phase I represents backing/flanking fire with minimal wind influence
  • Phase II represents active head fire with increasing wind coupling
  • Phase III represents wind-driven crown fire with strong wind coupling
  • Continuity enforced at phase boundaries prevents discontinuous jumps in ROS

6.3 Ember Attack Speed

Sensor: sensor.jf_ember_attack_speed_kmh

Purpose: Estimates the effective advance rate of embers and spotting ahead of the main fire front.

Calculation: @] ember_speed = spot_multiplier × fire_front_ros

Default: spot_multiplier = 3.0 @]

Rationale: Embers can travel ahead of the fire front by 1-5+ km depending on wind speed and fuel characteristics. The multiplier represents the ratio of ember advance rate to fire front advance rate.

Example:

  • Fire front ROS: 2.0 km/h
  • Multiplier: 3.0
  • Ember attack speed: 6.0 km/h

7. Estimated Time of Arrival (ETA) Calculations

7.1 Preconditions for ETA Calculation

ETAs are only calculated when sensor.jf_is_home_downwind = "YES"

Logic: If home is not in the primary downwind cone, the fire is not expected to travel toward the property under current wind conditions.

7.2 ETA to Embers

Sensor: sensor.jf_eta_embers_hr

Purpose: Estimates time until ember attack begins at the property.

Calculation: @] IF is_home_downwind == "YES":

    eta_embers = fire_distance_km / ember_attack_speed_kmh
  \\ELSE:
    eta_embers = None

@]

Example:

  • Distance: 15 km
  • Ember speed: 6.0 km/h
  • ETA: 2.5 hours

7.3 ETA to Fire Front

Sensor: sensor.jf_eta_fire_front_hr

Purpose: Estimates time until main fire front reaches the property.

Calculation: @] IF is_home_downwind == "YES":

    eta_fire_front = fire_distance_km / fire_front_ros_kmh
  \\ELSE:
    eta_fire_front = None

@]

Example:

  • Distance: 15 km
  • Fire front ROS: 2.0 km/h
  • ETA: 7.5 hours

7.4 Rough ETA Range

Sensors:

  • sensor.jf_rough_eta_min_hr = sensor.jf_eta_embers_hr
  • sensor.jf_rough_eta_max_hr = sensor.jf_eta_fire_front_hr

Purpose: Provides a time window for fire impact.

Interpretation:

  • Min (Embers): Earliest likely impact - prepare defenses
  • Max (Fire Front): Latest expected impact - main fire arrival

8. Fire Event Selection and Tracking

8.1 Automated Fire Selection

Script: jf_autoselect_nearest_watch_bushfire.py

Purpose: Automatically selects the nearest WATCH-level or higher bushfire incident for monitoring.

Selection Criteria (Priority Order):

  1. Status = "WATCH" AND kind = "BUSHFIRE"
  2. Status = "EMERGENCY WARNING" OR "WATCH AND ACT" AND kind = "BUSHFIRE"
  3. Any BUSHFIRE within watch zone radius
  4. Nearest fire of any kind within relevance radius

Latch Behavior: Once a WATCH bushfire is selected, it remains selected until:

  • Fire is no longer present in VicEmergency feed
  • User manually changes selection
  • Fire status downgrades below ADVICE level

8.2 Manual Fire Selection

Interface: input_select.jf_vic_fire_event

Purpose: Allows manual override of automatic selection.

List Building: jf_vic_events_to_select.py

  • Formats fires as dropdown options: "BUSHFIRE | WATCH | 12.5km | Grampians"
  • Orders by: status severity → kind (bushfire first) → distance
  • Updates every 5 minutes or when VicEmergency data refreshes

8.3 Fire Event State Propagation

Automation: "JF Apply Selected VicEmergency Fire Event"

Triggered by: Change in input_select.jf_vic_fire_event

Action: @]python Parse selected fire event:

  - Extract: id, name, lat, lon, distance, status

Update input entities:

  - input_text.jf_fire_name = name
  - input_text.jf_fire_source_id = id
  - input_number.jf_fire_lat = lat
  - input_number.jf_fire_lon = lon

@]

These coordinates become the "anchor point" for:

  • DEA hotspot cluster queries
  • FFMVic burnt area queries
  • Distance and bearing calculations

9. MQTT Publishing for Remote Monitoring

9.1 Published Topics

The system publishes real-time threat data to MQTT broker for integration with remote monitoring systems, mobile apps, and alerting infrastructure.

Topic Structure: home/fire/[parameter]

Published Parameters:

TopicSensor SourceUnitsUpdate Rate
home/fire/distancejf_fire_distance_kmkm5 min
home/fire/bearingjf_fire_bearing_to_home_degdegrees5 min
home/fire/downwindjf_is_home_downwindYES/NO5 min
home/fire/rosjf_fire_front_ros_kmhkm/h5 min
home/fire/eta_minjf_rough_eta_min_hrhours5 min
home/fire/eta_maxjf_rough_eta_max_hrhours5 min
home/fire/phasejf_fire_spread_phaseI/II/III5 min
home/fire/geometry_sourcejf_fire_geometry_sourcetext5 min
home/fire/namejf_fire_nametexton change
home/wind/speedbom_aireys_wind_speedkm/h30 min
home/wind/directionbom_aireys_wind_directiondegrees30 min

9.2 Payload Format

All payloads are plain text (not JSON) for simplicity:

@] home/fire/distance → "15.23" home/fire/bearing → "087.5" home/fire/downwind → "YES" home/fire/ros → "2.10" home/fire/eta_min → "2.5" home/fire/eta_max → "7.3" @]


10. Caching and Performance Optimization

10.1 Cache Strategy

All three data-fetching scripts implement identical caching:

Cache Parameters:

  • Cache duration: 120 seconds (2 minutes)
  • Cache location: /config/[script_name]_cache.json
  • Cache key: Includes query parameters to prevent stale data on parameter changes

Cache Behavior: @]python IF cache exists AND cache_age < 120 seconds AND cache_key matches:

    RETURN cached_data
    SET cached=True, cache_age_sec=[age]

ELSE:

    FETCH fresh_data
    WRITE cache
    RETURN fresh_data
    SET cached=False, cache_age_sec=0

@]

Fallback on Error: @]python TRY:

    data = fetch_from_api()

EXCEPT Exception:

    IF cache exists:
        RETURN cached_data with error flag
    ELSE:
        RETURN empty result with error message

@]

10.2 Polling Intervals

ComponentIntervalRationale
VicEmergency events300 sec (5 min)Official updates every 5-15 min
DEA hotspots300 sec (5 min)Satellite passes every 1-4 hours, cache handles rapid polls
FFMVic burnt area300 sec (5 min)Updates hourly to daily
BOM wind data300-1800 secWeather station updates every 30 min
Template sensorsEvent-drivenRecalculate when dependencies change

10.3 Timeout Settings

  • Web fetch timeout: 10-25 seconds (script-dependent)
  • Command line sensor timeout: 10-20 seconds
  • Short timeouts prevent dashboard freezing during data loading

11. Error Handling and Resilience

11.1 Graceful Degradation

The system is designed to continue operating with partial data:

Scenario: VicEmergency API Down

  • Returns cached fire list (up to 2 min stale)
  • User can still manually select previously detected fires
  • Distance/bearing calculations continue if fire coordinates known

Scenario: DEA Hotspots Unavailable

  • Falls back to FFMVic burnt area if available
  • Falls back to incident point if neither boundary source works
  • System continues threat assessment with reduced accuracy

Scenario: FFMVic API Down

  • Uses DEA hotspots if available
  • Falls back to incident point
  • Distance calculations continue with alternate geometry

Scenario: BOM Wind API Down

  • ROS calculations halt (returns None)
  • ETAs become unavailable
  • Historical wind data may be used if configured

11.2 Data Validation

Each script performs defensive validation:

@]python

Coordinate validation

IF lat is None OR lon is None OR lat < -90 OR lat > 90 OR lon < -180 OR lon > 180:

    SKIP record / RETURN error

Distance validation

IF distance < 0 OR distance > max_reasonable_distance:

    SKIP record / FLAG warning

Timestamp validation

IF timestamp > now + 1hour OR timestamp < now - 72hours:

    SKIP record / Use fallback

@]

11.3 JSON Output Guarantees

All Python scripts guarantee valid JSON output even on catastrophic failure:

@]python TRY:

    result = process_data()
    print(json.dumps(result))

EXCEPT Exception as e:

    print(json.dumps({
        "ok": False,
        "error": str(e),
        "count": 0,
        "features": [],
        # ... other safe default fields
    }))

@]

This ensures Home Assistant command_line sensors never fail due to parse errors.


12. Coordinate Systems and Projections

12.1 Geographic Coordinate System

Standard: WGS84 (EPSG:4326)

  • All input coordinates in decimal degrees
  • Latitude: -90° to +90° (negative = South)
  • Longitude: -180° to +180° (negative = West)

12.2 Distance Calculation Methods

Haversine Formula (long-distance, point-to-point): @] R = 6371.0088 km (Earth mean radius) d = 2R × arcsin(√(sin²(Δlat/2) + cos(lat1)×cos(lat2)×sin²(Δlon/2))) @]

Accuracy: <0.5% error for distances <1000 km

Equirectangular Projection (local, for polygon operations): @] Centered at (lat0, lon0): x_km = (lon - lon0) × cos(lat0) × 111.32 y_km = (lat - lat0) × 110.574

Distance from origin: d = √(x² + y²) @]

Accuracy: <1% error for distances <200 km from origin Fast computation for polygon edge calculations

12.3 Bearing Calculation

Forward Azimuth (great circle initial bearing): @] y = sin(Δlon) × cos(lat2) x = cos(lat1) × sin(lat2) - sin(lat1) × cos(lat2) × cos(Δlon) bearing = atan2(y, x) bearing_deg = (bearing × 180/π + 360) mod 360 @]

Returns true bearing (0° = North, clockwise)


13. Configurable Parameters Reference

13.1 Spatial Parameters

ParameterDefaultRangeUnitPurpose
jf_relevance_radius_km2005-200kmMaximum distance to consider fires
jf_watch_zone_km201-50kmPriority zone for WATCH fires
jf_burnt_area_query_radius_km8010-200kmFFMVic query radius
jf_burnt_edge_match_km100-50kmMax distance to associate burnt area
jf_hotspots_query_radius_km20010-500kmDEA hotspot query radius
jf_hotspots_anchor_match_km200-100kmMax distance to associate hotspot cluster

13.2 Temporal Parameters

ParameterDefaultRangeUnitPurpose
jf_hotspots_time_window_hr81-72hoursHotspot recency filter

13.3 Clustering Parameters

ParameterDefaultRangeUnitPurpose
jf_hotspots_eps_km2.00.5-15kmHotspot clustering distance
jf_hotspots_min_points102-200countMinimum cluster size

13.4 Fire Spread Model Parameters

ParameterDefaultRangeUnitPurpose
jf_phase2_wind_kmh150-80km/hPhase I→II wind threshold
jf_phase3_wind_kmh250-120km/hPhase II→III wind threshold
jf_ros_k10.020-0.20-Phase I ROS slope
jf_ros_k20.060-0.30-Phase II ROS slope
jf_ros_k30.080-0.40-Phase III ROS slope
jf_ros_min_kmh0.30-10km/hMinimum ROS
jf_ros_phase1_max_kmh1.20-10km/hPhase I ROS ceiling
jf_spot_multiplier3.01-10-Ember speed multiplier
jf_downwind_half_angle_deg405-90degreesThreat cone half-angle

14. Calculation Flow Summary

@] ┌─────────────────────────────────────────────────────────────────┐ │ DATA ACQUISITION (Every 5 minutes) │ ├─────────────────────────────────────────────────────────────────┤ │ │ │ VicEmergency API DEA Hotspots API │ │ ├─ Fire incidents ├─ Thermal detections │ │ ├─ Filter by radius ├─ Filter by time window │ │ ├─ Exclude planned burns ├─ Cluster by density │ │ └─ Calculate distances └─ Rank by anchor proximity │ │ │ │ FFMVic ArcGIS API BOM Weather API │ │ ├─ Burnt area polygons ├─ Wind speed │ │ ├─ Name matching ├─ Wind direction │ │ ├─ Boundary calculations └─ Temperature, humidity │ │ └─ Incident association │ │ │ └─────────────────────────────────────────────────────────────────┘

┌─────────────────────────────────────────────────────────────────┐ │ FIRE SELECTION (Event-driven) │ ├─────────────────────────────────────────────────────────────────┤ │ │ │ 1. Build fire event list (sorted by priority) │ │ 2. Auto-select nearest WATCH bushfire (if enabled) │ │ 3. User can manually override selection │ │ 4. Set anchor coordinates (lat, lon) for selected fire │ │ │ └─────────────────────────────────────────────────────────────────┘

┌─────────────────────────────────────────────────────────────────┐ │ GEOMETRY SELECTION (Every calculation cycle) │ ├─────────────────────────────────────────────────────────────────┤ │ │ │ Priority 1: HOTSPOT_CLUSTER_EDGE │ │ ├─ IF: Hotspot cluster exists │ │ ├─ AND anchor matches selected fire │ │ ├─ AND anchor distance ≤ 20 km │ │ └─ USE: Nearest hotspot point to home │ │ │ │ Priority 2: BURNT_AREA_EDGE │ │ ├─ IF: Burnt area polygon exists │ │ ├─ AND anchor matches selected fire │ │ ├─ AND anchor distance ≤ 10 km │ │ └─ USE: Nearest polygon edge to home │ │ │ │ Priority 3: INCIDENT_POINT │ │ └─ USE: VicEmergency incident coordinates │ │ │ └─────────────────────────────────────────────────────────────────┘

┌─────────────────────────────────────────────────────────────────┐ │ SPATIAL CALCULATIONS (Real-time on data change) │ ├─────────────────────────────────────────────────────────────────┤ │ │ │ Fire Distance Fire Bearing to Home │ │ └─ Haversine / Edge distance └─ Forward azimuth calculation│ │ │ │ Wind Direction Conversion Downwind Offset │ │ └─ "From" → "Towards" └─ Angular diff (bearing-wind)│ │ │ │ Is Home Downwind? │ │ └─ IF offset ≤ 40° → YES, ELSE NO │ │ │ └─────────────────────────────────────────────────────────────────┘

┌─────────────────────────────────────────────────────────────────┐ │ FIRE BEHAVIOR MODELING (Real-time on wind change) │ ├─────────────────────────────────────────────────────────────────┤ │ │ │ Fire Spread Phase │ │ ├─ Phase I: wind < 15 km/h │ │ ├─ Phase II: 15 ≤ wind < 25 km/h │ │ └─ Phase III: wind ≥ 25 km/h │ │ │ │ Fire Front ROS (km/h) │ │ ├─ Phase I: ROS = k1 × wind (clamped 0.3-1.2 km/h) │ │ ├─ Phase II: ROS = k2 × wind (min continuity from Phase I) │ │ └─ Phase III: ROS = k3 × wind │ │ │ │ Ember Attack Speed (km/h) │ │ └─ speed = ROS × spot_multiplier (default: 3.0) │ │ │ └─────────────────────────────────────────────────────────────────┘

┌─────────────────────────────────────────────────────────────────┐ │ THREAT ASSESSMENT (Real-time on any input change) │ ├─────────────────────────────────────────────────────────────────┤ │ │ │ IF is_home_downwind == "YES": │ │ │ │ ETA Embers (hours) │ │ └─ distance_km / ember_speed_kmh │ │ │ │ ETA Fire Front (hours) │ │ └─ distance_km / fire_front_ros_kmh │ │ │ │ Impact Window │ │ └─ Min = ETA Embers, Max = ETA Fire Front │ │ │ │ ELSE: │ │ └─ No direct threat (fire not approaching) │ │ │ └─────────────────────────────────────────────────────────────────┘

┌─────────────────────────────────────────────────────────────────┐ │ OUTPUT & DISPLAY │ ├─────────────────────────────────────────────────────────────────┤ │ │ │ Home Assistant Dashboard MQTT Publishing │ │ ├─ Fire name & status ├─ Distance, bearing │ │ ├─ Distance & bearing ├─ Downwind status │ │ ├─ Geometry source ├─ ROS, phase │ │ ├─ Downwind status ├─ ETAs (min/max) │ │ ├─ ROS & spread phase └─ Wind data │ │ ├─ ETA range │ │ └─ Debug information │ │ │ │ Alerts & Notifications │ │ └─ Triggered by configurable thresholds │ │ │ └─────────────────────────────────────────────────────────────────┘ @]


15. Key Assumptions and Limitations

15.1 Model Assumptions

  1. Fire Spread is Wind-Driven: The model assumes head fire spread follows wind direction within a cone. Topographic effects, fuel discontinuities, and firebreaks are not modeled.
  2. Uniform Terrain: ROS calculations do not account for slope, which can significantly increase or decrease spread rates.
  3. Constant Conditions: ETAs assume current wind speed and direction persist. Actual fire behavior is highly variable.
  4. Linear Spread Model: The piecewise-linear ROS model is a simplified approximation. Real fires exhibit non-linear behavior, particularly during fire front intensification.
  5. Ember Transport: The spot multiplier is a rough empirical factor. Actual ember transport depends on fire intensity, fuel type, and atmospheric stability.

15.2 Data Limitations

  1. VicEmergency Update Latency: Official incident data updates every 5-15 minutes. Rapidly developing fires may not reflect current conditions.
  2. Satellite Overpass Frequency: DEA hotspots depend on satellite passes (1-4 hour intervals). Cloud cover prevents detection.
  3. Burnt Area Mapping Delay: FFMVic polygons are manually digitized and may lag actual fire progression by hours to days.
  4. Weather Station Representativeness: Single weather station (Aireys Inlet) may not capture local wind variations, particularly in complex terrain.
  5. Coordinate Accuracy: VicEmergency incident points are approximate (±1-5 km typical). Fire geometry sources provide more accurate positions.

15.3 Known Edge Cases

  1. Multiple Fires in Close Proximity: Name matching and proximity logic may incorrectly associate burnt areas or hotspots if multiple fires are within threshold distances.
  2. Erratic Fire Geometry Changes: Sudden jumps in reported fire position can cause temporary mismatches between data sources.
  3. Null/Missing Data: System designed to gracefully degrade but ETAs become unavailable if wind data is missing.
  4. Fire Behavior Changes: Model assumes relatively steady conditions. Sudden wind shifts, humidity changes, or fire-atmosphere coupling events are not predicted.

16. Validation and Calibration

16.1 Empirical Tuning

The ROS model parameters have been tuned based on:

  • Historical fire progression data from Victorian fires
  • Published fire behavior research (McArthur, CSIRO fire models)
  • Local fuel type characteristics (coastal eucalypt forest)
  • Observed fire runs during 2019-2020 fire season

16.2 Recommended Calibration Process

For site-specific tuning:

  1. Phase Thresholds: Observe local fire behavior transitions. Adjust jf_phase2_wind_kmh and jf_phase3_wind_kmh if spread regime changes occur at different wind speeds.
  2. ROS Slopes (k1, k2, k3): Compare predicted ETAs with actual fire progression. Increase/decrease slopes if model consistently under/over-predicts spread rates.
  3. Spot Multiplier: Observe ember attack timing relative to main fire front arrival. Adjust multiplier based on local fuel conditions and fire intensity.
  4. Downwind Cone Angle: If fire frequently spreads outside predicted threat zone, increase @@jf_downwind_half_angle_deg. Decrease if false alarms common.

16.3 Accuracy Assessment

Distance Calculations:

  • Expected accuracy: ±500m (Hotspot/Burnt Area Edge)
  • Expected accuracy: ±2-5 km (Incident Point fallback)

ROS Predictions:

  • Typical accuracy: ±50% under steady conditions
  • Accuracy degrades during rapid fire behavior changes

ETA Predictions:

  • Useful for order-of-magnitude estimates (hours vs. days)
  • NOT suitable for precise timing decisions
  • Recommend 50% safety margin on minimum ETA

17. Future Enhancement Opportunities

  1. Fuel Type Integration: Incorporate vegetation/fuel mapping to refine ROS by fuel class.
  2. Topographic Corrections: Add slope-dependent ROS adjustments using DEM data.
  3. Fire Danger Rating Integration: Use official AFDRS (Australian Fire Danger Rating System) inputs.
  4. Ensemble Forecasting: Generate multiple ETAs using weather forecast ensembles.
  5. Historical Fire Progression Tracking: Log fire position over time to detect acceleration/deceleration trends.
  6. Machine Learning ROS Model: Train on historical fire progression data for improved predictions.
  7. Integration with Fire Simulation Models: Interface with Phoenix RapidFire or similar simulation tools.
  8. Real-Time Weather Radar: Incorporate radar reflectivity for smoke plume tracking and fire front detection.
  9. JF - or integrate with Vesta Mk 2 perhaps by: Starting with the GitHub Python translation (fastest runnable baseline - https://github.com/m-gale/ROS_evaluation). Cross-check line-by-line against the CSIRO user guide equations and thresholds (chrome-extension://efaidnbmnnnibpcajpcglclefindmkaj/https://research.csiro.au/vestamk2/wp-content/uploads/sites/443/2021/12/Vesta-Mk-2-users-guide-2021_a.pdf?utm_source=chatgpt.com). Use the Spark model-library code listing (https://research.csiro.au/spark/resources/model-library/dry-eucalypt-forest-vesta-mk-2/) as a second independent reference for implementation details (especially wind/moisture handling).

Document Metadata

Author: Technical documentation generated from ARMAC fire threat system codebase\\Date: February 2026\\Version: 1.0\\System Version: Based on scripts last modified January 2025\\Location: Fairhaven, Victoria, Australia (-38.463445°, 144.085157°)


END OF TECHNICAL DESCRIPTION << Testing Infrastructure and System Validation cont | | Development Notes >>      |Table of Contents>


Page last modified on February 17, 2026, at 07:45 am