diff --git a/CHANGELOG.txt b/CHANGELOG.txt index 5929a2e4..1ce2c11f 100644 --- a/CHANGELOG.txt +++ b/CHANGELOG.txt @@ -1,6 +1,15 @@ CHANGELOG - towerops-web ======================== +2026-02-11 - fix: live polling uses effective agent from site/org cascade + - File: lib/towerops_web/live/graph_live/show.ex + - Bug: Live poll mode used Agents.get_device_assignment/1 which only checks + direct device-level assignments. Devices with agent assigned at site or + org level fell through to direct Phoenix SNMP instead of routing to agent. + - Fix: Replaced with Agents.get_effective_agent_token/1 which walks the + device → site → org cascade, matching how regular polling resolves agents. + Also simplified request_agent_live_poll_and_wait to accept token_id directly. + 2026-02-11 - fix: round sensor values to 1 decimal place - Files: lib/towerops/workers/device_poller_worker.ex (poll_simple_sensor/2), lib/towerops_web/channels/agent_channel.ex (process_sensor_reading/3) diff --git a/lib/towerops_web/live/graph_live/show.ex b/lib/towerops_web/live/graph_live/show.ex index 7a4b66bd..7b6a43f6 100644 --- a/lib/towerops_web/live/graph_live/show.ex +++ b/lib/towerops_web/live/graph_live/show.ex @@ -686,16 +686,16 @@ defmodule ToweropsWeb.GraphLive.Show do now = DateTime.utc_now() timestamp_ms = DateTime.to_unix(now, :millisecond) - # Check if device has agent assignment (fresh check each poll to avoid stale data) - has_agent = Agents.get_device_assignment(device.id) != nil + # Check effective agent (device → site → org cascade) + agent_token_id = Agents.get_effective_agent_token(device) - Logger.info("Live poll for device #{device.name}: has_agent=#{has_agent}") + Logger.info("Live poll for device #{device.name}: agent_token_id=#{inspect(agent_token_id)}") new_points = - if has_agent do + if agent_token_id do # Request agent to poll NOW and wait for result Logger.info("Requesting live poll from agent") - request_agent_live_poll_and_wait(device.id, socket.assigns) + request_agent_live_poll_and_wait(device.id, agent_token_id, socket.assigns) else # Do direct SNMP polling for specific sensors only Logger.info("Using direct SNMP for live polling") @@ -724,39 +724,33 @@ defmodule ToweropsWeb.GraphLive.Show do end # Request live poll from agent and wait for response - defp request_agent_live_poll_and_wait(device_id, assigns) do - case Agents.get_device_assignment(device_id) do - nil -> + defp request_agent_live_poll_and_wait(device_id, agent_token_id, assigns) do + # Generate unique reply topic for this request + reply_topic = "live_poll_reply:#{:erlang.unique_integer([:positive])}" + + # Subscribe to reply topic + :ok = Phoenix.PubSub.subscribe(Towerops.PubSub, reply_topic) + + # Get sensors we're interested in + sensors = get_sensors_for_live_mode(assigns) + sensor_oids = Enum.map(sensors, & &1.sensor_oid) + + # Broadcast live poll request with reply topic and sensor OIDs + Phoenix.PubSub.broadcast( + Towerops.PubSub, + "agent:#{agent_token_id}:live_poll", + {:live_poll_requested, device_id, sensor_oids, reply_topic} + ) + + # Wait for response with timeout + receive do + {:live_poll_result, oid_values} -> + # Process the OID values into data points + process_live_poll_oids(sensors, oid_values) + after + 3000 -> + Logger.warning("Live poll timeout waiting for agent response") [] - - assignment -> - # Generate unique reply topic for this request - reply_topic = "live_poll_reply:#{:erlang.unique_integer([:positive])}" - - # Subscribe to reply topic - :ok = Phoenix.PubSub.subscribe(Towerops.PubSub, reply_topic) - - # Get sensors we're interested in - sensors = get_sensors_for_live_mode(assigns) - sensor_oids = Enum.map(sensors, & &1.sensor_oid) - - # Broadcast live poll request with reply topic and sensor OIDs - Phoenix.PubSub.broadcast( - Towerops.PubSub, - "agent:#{assignment.agent_token_id}:live_poll", - {:live_poll_requested, device_id, sensor_oids, reply_topic} - ) - - # Wait for response with timeout - receive do - {:live_poll_result, oid_values} -> - # Process the OID values into data points - process_live_poll_oids(sensors, oid_values) - after - 3000 -> - Logger.warning("Live poll timeout waiting for agent response") - [] - end end end