{@device.name}

"bg-green-100 text-green-800 dark:bg-green-950/50 dark:text-green-400 ring-1 ring-green-600/20 dark:ring-green-500/30" :down -> "bg-red-100 text-red-800 dark:bg-red-950/50 dark:text-red-400 ring-1 ring-red-600/20 dark:ring-red-500/30" :unknown -> "bg-gray-100 text-gray-800 dark:bg-gray-800/50 dark:text-gray-400 ring-1 ring-gray-600/20 dark:ring-gray-500/30" end ]}> "bg-green-600 dark:bg-green-500" :down -> "bg-red-600 dark:bg-red-500" :unknown -> "bg-gray-500 dark:bg-gray-400" end ]}> {case @device.status do :up -> "Online" :down -> "Offline" :unknown -> "Unknown" end}
{@device.ip_address} Polled by: <%= if @agent_info.type == :cloud do %> <.icon name="hero-cloud" class="h-3.5 w-3.5" /> <%= if @agent_info.agent_token_id do %> Cloud ({@agent_info.name}) <% else %> Cloud <% end %> <% else %> <.icon name="hero-server" class="h-3.5 w-3.5" /> {@agent_info.name} <%= if @agent_info.is_offline do %> <.icon name="hero-exclamation-triangle" class="h-3 w-3" /> Offline <% end %> <% end %>
<.button navigate={~p"/devices/#{@device.id}/edit"}> <.icon name="hero-pencil" class="h-4 w-4" /> Edit
<%= case @active_tab do %> <% "overview" -> %>

Device Information

<%= if @snmp_device do %>
System Name
{@snmp_device.sys_name || @device.name}
Resolved IP
{@device.ip_address}
Hardware
{@snmp_device.model || "N/A"}
Operating System
{cond do @snmp_device.manufacturer && @snmp_device.firmware_version -> "#{@snmp_device.manufacturer} #{@snmp_device.firmware_version}" @snmp_device.manufacturer -> @snmp_device.manufacturer true -> @snmp_device.sys_descr || "N/A" end} <%= if firmware_update_available?(@snmp_device, @available_firmware) do %>
<.icon name="hero-arrow-up-circle" class="h-5 w-5 text-blue-500 cursor-help dark:text-blue-400" />
<% end %>
Serial Number
{@snmp_device.serial_number}
Object ID
{@snmp_device.sys_object_id || "N/A"}
Contact
{@snmp_device.sys_contact || "N/A"}
Location
{@snmp_device.sys_location || "N/A"}
Uptime
{format_uptime(@snmp_device.sys_uptime)}
<% else %>
Name
{@device.name}
IP Address
{@device.ip_address}
<% end %>
Device Added
{format_device_age(@device.inserted_at)}
Last Discovered
{if @device.last_discovery_at do format_device_age(@device.last_discovery_at) else "Never" end}
Last Polled
{if @device.last_snmp_poll_at do format_device_age(@device.last_snmp_poll_at) else "Never" end}
<%= if @traffic_chart_data do %>
<.link navigate={~p"/devices/#{@device.id}/graph/traffic"} class="block px-4 py-3 border-b border-gray-200 dark:border-white/10 hover:bg-gray-50 dark:hover:bg-gray-800 transition-colors" >

Overall Traffic

<.icon name="hero-arrow-right" class="h-4 w-4 text-gray-400" />
<% end %> <%= if @latency_chart_data do %>
<.link navigate={~p"/devices/#{@device.id}/graph/latency"} class="block px-4 py-3 border-b border-gray-200 dark:border-white/10 hover:bg-gray-50 dark:hover:bg-gray-800 transition-colors" >

ICMP Latency

<.icon name="hero-arrow-right" class="h-4 w-4 text-gray-400" />
<% end %>
<%= if @processor_chart_data || (@processors && length(@processors) > 0) do %> <% processor_count = if @processors, do: length(@processors), else: 0 avg_load = if processor_count > 0 do loads = @processors |> Enum.map(& &1.load_percent) |> Enum.reject(&is_nil/1) if length(loads) > 0, do: Enum.sum(loads) / length(loads), else: nil else nil end %>
<.link navigate={~p"/devices/#{@device.id}/graph/processors"} class="block px-4 py-3 border-b border-gray-200 dark:border-white/10 hover:bg-gray-50 dark:hover:bg-gray-800 transition-colors" >

<%= if processor_count > 0 do %> {processor_count} {if processor_count == 1, do: "Processor", else: "Processors"} <% else %> Processors <% end %>

<.icon name="hero-arrow-right" class="h-4 w-4 text-gray-400" />
<%= if @processor_chart_data do %>
<% end %> <%= if avg_load do %>
Average Load
= 50 && avg_load < 80 && "bg-yellow-500", avg_load >= 80 && "bg-red-500" ]} style={"width: #{min(avg_load, 100)}%"} >
{Float.round(avg_load, 0)}%
<% end %>
<% end %> <%= if @memory_chart_data do %>
<.link navigate={~p"/devices/#{@device.id}/graph/memory"} class="block px-4 py-3 border-b border-gray-200 dark:border-white/10 hover:bg-gray-50 dark:hover:bg-gray-800 transition-colors" >

Memory Usage

<.icon name="hero-arrow-right" class="h-4 w-4 text-gray-400" />
<% end %> <%= if @storage_sensors && length(@storage_sensors) > 0 do %>

Storage Usage

<%= for sensor <- @storage_sensors do %>
<.link navigate={ ~p"/devices/#{@device.id}/graph/storage?sensor_id=#{sensor.id}" } class="hover:text-blue-600 dark:hover:text-blue-400 hover:underline" > {sensor.sensor_descr}
<%= if sensor.latest_reading do %> {format_sensor_value( sensor.latest_reading.value, sensor.sensor_divisor )} {sensor.sensor_unit} <% else %> N/A <% end %>
<% end %>
<% end %> <%= if @storage && length(@storage) > 0 do %>

Storage Volumes ({length(@storage)})

<%= if @storage_volume_chart_data do %>
<% end %>
<%= for storage <- @storage do %> <% usage_percent = if storage.total_bytes && storage.total_bytes > 0 do Float.round(storage.used_bytes / storage.total_bytes * 100, 1) else 0.0 end %> <.link navigate={ ~p"/devices/#{@device.id}/graph/storage_volume?storage_id=#{storage.id}" } class="block hover:bg-gray-50 dark:hover:bg-gray-700/50 -mx-2 px-2 py-1 rounded transition-colors" >
{storage.description || "Storage #{storage.storage_index}"} {format_bytes(storage.used_bytes)} / {format_bytes(storage.total_bytes)}
= 70 && usage_percent < 90 && "bg-yellow-500", usage_percent >= 90 && "bg-red-500" ]} style={"width: #{min(usage_percent, 100)}%"} >
{usage_percent}%
{String.replace(storage.storage_type || "other", "_", " ") |> String.capitalize()}
<% end %>
<% end %> <%= if @temperature_sensors && length(@temperature_sensors) > 0 do %>

Temperature

<%= for sensor <- @temperature_sensors do %>
<.link navigate={ ~p"/devices/#{@device.id}/graph/temperature?sensor_id=#{sensor.id}" } class="hover:text-blue-600 dark:hover:text-blue-400 hover:underline" > {sensor.sensor_descr}
<%= if sensor.latest_reading do %> {format_sensor_value( sensor.latest_reading.value, sensor.sensor_divisor )} {sensor.sensor_unit || "°C"} <% else %> N/A <% end %>
<% end %>
<% end %> <%= if @voltage_sensors && length(@voltage_sensors) > 0 do %>

Voltage

<%= for sensor <- @voltage_sensors do %>
<.link navigate={ ~p"/devices/#{@device.id}/graph/voltage?sensor_id=#{sensor.id}" } class="hover:text-blue-600 dark:hover:text-blue-400 hover:underline" > {sensor.sensor_descr}
<%= if sensor.latest_reading do %> {format_sensor_value( sensor.latest_reading.value, sensor.sensor_divisor )} {sensor.sensor_unit} <% else %> N/A <% end %>
<% end %>
<% end %> <%= if @grouped_transceivers && length(@grouped_transceivers) > 0 do %>

Transceivers

<%= for {_transceiver_name, sensors} <- @grouped_transceivers do %> <%= for sensor <- sensors do %>
<.link navigate={ ~p"/devices/#{@device.id}/graph/dbm?sensor_id=#{sensor.id}" } class="hover:text-blue-600 dark:hover:text-blue-400 hover:underline" > {sensor.sensor_descr}
<%= if sensor.latest_reading do %> {format_sensor_value( sensor.latest_reading.value, sensor.sensor_divisor )} {sensor.sensor_unit} <% else %> N/A <% end %>
<% end %> <% end %>
<% end %> <%= if (@general_counters && length(@general_counters) > 0) || (@firewall_counters && length(@firewall_counters) > 0) do %>

Counters

<%= if @general_counters && length(@general_counters) > 0 do %>
<%= for sensor <- @general_counters do %>
<.link navigate={ ~p"/devices/#{@device.id}/graph/#{sensor.sensor_type}?sensor_id=#{sensor.id}" } class="hover:text-blue-600 dark:hover:text-blue-400 hover:underline" > {sensor.sensor_descr}
<%= if sensor.latest_reading && sensor.latest_reading.value do %> {trunc(sensor.latest_reading.value)} <%= if sensor.sensor_unit && sensor.sensor_unit != "" do %> {sensor.sensor_unit} <% end %> <% else %> N/A <% end %>
<% end %>
<% end %> <%= if @firewall_counters && length(@firewall_counters) > 0 do %>

Firewall

<%= for sensor <- @firewall_counters do %>
<.link navigate={ ~p"/devices/#{@device.id}/graph/#{sensor.sensor_type}?sensor_id=#{sensor.id}" } class="hover:text-blue-600 dark:hover:text-blue-400 hover:underline" > {sensor.sensor_descr}
<%= if sensor.latest_reading && sensor.latest_reading.value do %> {trunc(sensor.latest_reading.value)} <%= if sensor.sensor_unit && sensor.sensor_unit != "" do %> {sensor.sensor_unit} <% end %> <% else %> N/A <% end %>
<% end %>
<% end %>
<% end %> <%= if @wireless_sensors && length(@wireless_sensors) > 0 do %>

Wireless

<%= for sensor <- @wireless_sensors do %>
<.link navigate={ ~p"/devices/#{@device.id}/graph/wireless?sensor_id=#{sensor.id}" } class="hover:text-blue-600 dark:hover:text-blue-400 hover:underline" > {sensor.sensor_descr}
<%= if sensor.latest_reading && sensor.latest_reading.value do %> <%= if sensor.sensor_type in ["clients", "ccq", "utilization"] do %> {trunc(sensor.latest_reading.value)} <% else %> {Float.round(sensor.latest_reading.value, 1)} <% end %> <%= if sensor.sensor_unit && sensor.sensor_unit != "" do %> {sensor.sensor_unit} <% end %> <% else %> N/A <% end %>
<% end %>
<% end %>
<%!-- Connected Devices --%> <%= if @connected_devices != [] do %>

Connected Devices ({length(@connected_devices)} links)

<%= for link <- @connected_devices do %> <% peer_device = cond do link.target_device && link.target_device.id != @device.id -> link.target_device link.source_device && link.source_device.id != @device.id -> link.source_device link.target_device -> link.target_device true -> nil end %> <% end %>
Device IP Address Interface Link Type Confidence Status
<%= if peer_device do %> <.link navigate={~p"/devices/#{peer_device.id}"} class="font-medium text-blue-600 hover:text-blue-800 dark:text-blue-400 dark:hover:text-blue-300" > {peer_device.name} <% else %>
{link.discovered_remote_name || link.discovered_remote_mac || "Unknown"}
<% end %>
<%= if peer_device do %> {peer_device.ip_address} <% else %> {link.discovered_remote_ip || "-"} <% end %> <%= if link.source_interface do %> {link.source_interface.if_name} <% else %> - <% end %> "bg-blue-100 text-blue-800 dark:bg-blue-900 dark:text-blue-200" link.link_type == "mac_match" -> "bg-yellow-100 text-yellow-800 dark:bg-yellow-900 dark:text-yellow-200" link.link_type == "arp_inference" -> "bg-orange-100 text-orange-800 dark:bg-orange-900 dark:text-orange-200" true -> "bg-gray-100 text-gray-800 dark:bg-gray-700 dark:text-gray-200" end ]}> {link.link_type}
= 0.9 -> "bg-green-500" link.confidence >= 0.7 -> "bg-blue-500" link.confidence >= 0.5 -> "bg-yellow-500" true -> "bg-red-500" end ]} style={"width: #{trunc(link.confidence * 100)}%"} >
{trunc(link.confidence * 100)}%
<%= if peer_device do %> Managed <% else %> Discovered <% end %>
<% end %> <% "ports" -> %> <%= if @snmp_interfaces && length(@snmp_interfaces) > 0 do %>
<%= for {category, interfaces} <- @interfaces_by_type do %>

{category} Interfaces ({length(interfaces)})

<%= for interface <- interfaces do %> <% end %>
# Name Status Speed IP Address MAC
{interface.if_index} <.link navigate={ ~p"/devices/#{@device.id}/graph/traffic?interface_id=#{interface.id}" } class="hover:text-blue-600 dark:hover:text-blue-400" >
{interface.if_name || interface.if_descr}
<%= if interface.if_alias do %>
{interface.if_alias}
<% end %>
{String.upcase(interface.if_oper_status || "unknown")} {format_speed(interface.if_speed)} <% interface_ips = Map.get(@ip_addresses_by_interface, interface.id, []) %> <%= if Enum.empty?(interface_ips) do %> - <% else %>
<%= for ip <- interface_ips do %>
{ip.ip_address} <%= if ip.prefix_length do %> /{ip.prefix_length} <% end %>
<% end %>
<% end %>
{interface.if_phys_address || "-"}
<% end %>
<% else %>

No interfaces discovered

<% end %> <% "neighbors" -> %> <%= if @neighbors && length(@neighbors) > 0 do %>

Discovered Neighbors

<%= for neighbor <- @neighbors do %> <% end %>
Protocol Local Port Remote Device Remote Port IP Address Platform Capabilities Last Seen
{neighbor.protocol} <.link navigate={ ~p"/devices/#{@device.id}/graph/traffic?interface_id=#{neighbor.interface.id}" } class="text-blue-600 hover:text-blue-800 dark:text-blue-400 dark:hover:text-blue-300" > {neighbor.interface.if_name || neighbor.interface.if_descr} <%= if neighbor.matched_device do %> <.link navigate={~p"/devices/#{neighbor.matched_device.id}"} class="font-medium text-blue-600 hover:text-blue-800 dark:text-blue-400 dark:hover:text-blue-300" > {neighbor.matched_device.name} <% else %>
<%= if neighbor.remote_system_name do %> {neighbor.remote_system_name |> String.split("/") |> List.first()} <% else %> Unknown <% end %>
<% end %>
{neighbor.remote_port_id || "-"}
<%= if !neighbor.matched_device && neighbor.remote_chassis_id do %>
{neighbor.remote_chassis_id}
<% end %>
{neighbor.remote_address || "-"} {neighbor.remote_platform || "-"} <%= if neighbor.remote_capabilities && length(neighbor.remote_capabilities) > 0 do %> {Enum.join(neighbor.remote_capabilities, ", ")} <% else %> - <% end %> {time_ago(neighbor.last_discovered_at)}
<% else %>
<.icon name="hero-server-stack" class="mx-auto h-12 w-12 text-gray-400" />

No neighbors discovered

This device doesn't have any LLDP or CDP neighbors, or neighbor discovery hasn't run yet.

<% end %> <% "arp" -> %> <%= if @arp_entries && length(@arp_entries) > 0 do %>

ARP Table ({length(@arp_entries)} entries)

<%= for arp <- @arp_entries do %> <% end %>
IP Address MAC Address Interface Type Last Seen
{arp.ip_address} {arp.mac_address} <%= if arp.interface do %> <.link navigate={ ~p"/devices/#{@device.id}/graph/traffic?interface_id=#{arp.interface.id}" } class="text-blue-600 hover:text-blue-800 dark:text-blue-400 dark:hover:text-blue-300" > {arp.interface.if_name || arp.interface.if_descr} <% else %> ifIndex {arp.if_index} <% end %> {arp.entry_type || "unknown"} {time_ago(arp.last_seen_at)}
<% else %>
<.icon name="hero-table-cells" class="mx-auto h-12 w-12 text-gray-400" />

No ARP entries discovered

This device doesn't have any ARP entries, or ARP discovery hasn't run yet.

<% end %> <% "mac" -> %> <%= if @mac_addresses && length(@mac_addresses) > 0 do %>

MAC Address Table ({length(@mac_addresses)} entries)

<%= for mac <- @mac_addresses do %> <% end %>
MAC Address VLAN Interface Status Last Seen
{mac.mac_address} <%= if mac.vlan_id do %> {mac.vlan_id} <% else %> - <% end %> <%= if mac.interface do %> <.link navigate={ ~p"/devices/#{@device.id}/graph/traffic?interface_id=#{mac.interface.id}" } class="text-blue-600 hover:text-blue-800 dark:text-blue-400 dark:hover:text-blue-300" > {mac.interface.if_name || mac.interface.if_descr} <% else %> Port {mac.port_index} <% end %> {mac.entry_status || "unknown"} {time_ago(mac.last_seen_at)}
<% else %>
<.icon name="hero-table-cells" class="mx-auto h-12 w-12 text-gray-400" />

No MAC addresses discovered

This device doesn't have any MAC forwarding entries, or MAC discovery hasn't run yet.

<% end %> <% "vlans" -> %> <%= if @vlans && length(@vlans) > 0 do %>

Configured VLANs ({length(@vlans)})

<%= for vlan <- @vlans do %> <% end %>
VLAN ID Name Type Status Last Checked
{vlan.vlan_id} {vlan.vlan_name || "-"} {vlan.vlan_type || "ethernet"} {String.upcase(vlan.status || "unknown")} {time_ago(vlan.last_checked_at)}
<% else %>
<.icon name="hero-square-3-stack-3d" class="mx-auto h-12 w-12 text-gray-400" />

No VLANs discovered

This device doesn't have any VLANs configured, or VLAN discovery hasn't run yet.

<% end %> <% "ip_addresses" -> %>
<%= if length(@ipv4_addresses) > 0 do %>

IPv4 Addresses ({length(@ipv4_addresses)})

<%= for ip <- @ipv4_addresses do %> <% end %>
IP Address Subnet Interface Primary
{ip.ip_address} <%= if ip.prefix_length do %> /{ip.prefix_length} <% else %> {ip.subnet_mask || "-"} <% end %> {(ip.snmp_interface && (ip.snmp_interface.if_name || ip.snmp_interface.if_descr)) || "-"} <%= if ip.is_primary do %> Primary <% else %> - <% end %>
<% end %> <%= if length(@ipv6_addresses) > 0 do %>

IPv6 Addresses ({length(@ipv6_addresses)})

<%= for ip <- @ipv6_addresses do %> <% end %>
IP Address Prefix Interface
{ip.ip_address} /{ip.prefix_length || "-"} {(ip.snmp_interface && (ip.snmp_interface.if_name || ip.snmp_interface.if_descr)) || "-"}
<% end %> <%= if length(@ipv4_addresses) == 0 && length(@ipv6_addresses) == 0 do %>
<.icon name="hero-globe-alt" class="mx-auto h-12 w-12 text-gray-400" />

No IP addresses discovered

This device doesn't have any IP addresses discovered, or IP discovery hasn't run yet.

<% end %>
<% "backups" -> %> <%= if @device.mikrotik_enabled do %>

Configuration Backups <%= if Enum.any?(@mikrotik_backups) do %> ({length(@mikrotik_backups)}) <% end %>

<.icon name="hero-beaker" class="h-3 w-3" /> Experimental
<%= if @agent_info.agent_token_id do %> <% else %>
Assign an agent to enable backups
<% end %>
<%= if Enum.any?(@mikrotik_backups) do %> <%!-- Instructions for comparing backups --%> <%= if length(@mikrotik_backups) > 1 do %>
<.icon name="hero-information-circle" class="h-5 w-5 text-blue-600 dark:text-blue-400 flex-shrink-0 mt-0.5" />
Compare configurations: Select any 2 backups using the checkboxes to compare their differences
<% end %>
<%= for backup <- @mikrotik_backups do %> <% compression_ratio = if backup.config_size_bytes && backup.config_size_bytes > 0 do Float.round( (1 - backup.compressed_size_bytes / backup.config_size_bytes) * 100, 1 ) else 0.0 end %> <% end %>
<.icon name="hero-check-circle" class="h-4 w-4 mx-auto" /> Date Original Size Compressed Size Ratio Source Actions
= 2 } title={ if MapSet.member?(@selected_backup_ids, backup.id), do: "Selected for comparison", else: if(MapSet.size(@selected_backup_ids) >= 2, do: "Maximum 2 backups can be selected", else: "Select to compare" ) } class="h-4 w-4 rounded border-gray-300 text-blue-600 focus:ring-blue-600 disabled:opacity-50 disabled:cursor-not-allowed dark:border-gray-600 dark:bg-gray-700" /> {ToweropsWeb.TimeHelpers.format_iso8601(backup.backed_up_at, @timezone)} {format_bytes(backup.config_size_bytes)} {format_bytes(backup.compressed_size_bytes)} {compression_ratio}% {String.replace(backup.trigger_source, "_", " ") |> String.capitalize()}
<%= if ToweropsWeb.Permissions.owner?(@current_scope) do %> <% end %>
<%!-- Pagination --%> <%= if assigns[:pagination] do %>
<.pagination meta={@pagination} path={~p"/devices/#{@device.id}"} params={%{"tab" => "backups"}} />
<% end %> <%!-- Floating Compare Button --%> <%= if MapSet.size(@selected_backup_ids) > 0 do %>
<%!-- Selection status --%>
<.icon name="hero-check-circle" class="h-5 w-5 text-blue-600 dark:text-blue-400" />
{MapSet.size(@selected_backup_ids)} of 2 backups selected
<%!-- Instructions when only 1 selected --%> <%= if MapSet.size(@selected_backup_ids) == 1 do %>
Select one more backup to compare
<% end %> <%!-- Action buttons --%>
<% end %> <% else %>
<.icon name="hero-document-text" class="mx-auto h-12 w-12 text-gray-400" />

No backups yet

<%= if @agent_info.agent_token_id do %>

Automatic backups run daily at {ToweropsWeb.TimeHelpers.format_utc_hour( 7, @timezone )}.

<% else %>

Assign an agent to enable automatic backups.

<% end %>
<% end %>
<% else %>
<.icon name="hero-server" class="mx-auto h-12 w-12 text-gray-400" />

MikroTik API not enabled

Enable MikroTik API in device settings to enable configuration backups.

<.button navigate={~p"/devices/#{@device.id}/edit"}> Edit Device Settings
<% end %> <% "logs" -> %>

Event Logs

Showing the most recent 100 events

<%= if Enum.any?(@events) do %>
<%= for event <- @events do %>
<%= if event.severity == "info" do %> <.icon name="hero-information-circle" class="w-5 h-5" /> <% end %> <%= if event.severity == "warning" do %> <.icon name="hero-exclamation-triangle" class="w-5 h-5" /> <% end %> <%= if event.severity == "critical" do %> <.icon name="hero-x-circle" class="w-5 h-5" /> <% end %>

{event.message}

{format_event_type(event.event_type)} {event.severity}
<% end %>
<% else %>
<.icon name="hero-document-text" class="mx-auto h-12 w-12 text-gray-400" />

No events yet

Events will appear here as interface states change, speeds change, or other monitored changes occur.

<% end %>
<% "debug" -> %>

Raw Discovery Data

Raw SNMP OID values collected during the last discovery run at <%= if @snmp_device.last_discovery_at do %> {ToweropsWeb.TimeHelpers.format_iso8601( @snmp_device.last_discovery_at, @timezone )} <% else %> unknown time <% end %>.

<%= if @snmp_device.raw_discovery_data do %>

System OIDs

<%= for {key, data} <- Map.get(@snmp_device.raw_discovery_data, "system_oids", %{}) do %> <% end %>
Field OID Value
{key} {data["oid"]} {inspect(data["value"])}
<%= if Map.get(@snmp_device.raw_discovery_data, "health_sensor_table") do %>

Health Sensor Table Walk

<%= for {oid, value} <- Map.get(@snmp_device.raw_discovery_data, "health_sensor_table", %{}) do %> <% end %>
OID Value
{oid} {inspect(value)}
<% end %> <%= if Map.get(@snmp_device.raw_discovery_data, "discovered_sensors") do %>

Discovered Sensors

<%= for sensor <- Map.get(@snmp_device.raw_discovery_data, "discovered_sensors", []) do %> <% end %>
Type Description OID Value State
{sensor["type"]} {sensor["descr"]} {sensor["oid"]} {sensor["value"]} <%= if sensor["unit"] && sensor["unit"] != "" do %> {sensor["unit"]} <% end %> <%= if sensor["state_descr"] do %> {sensor["state_descr"]} <% else %> - <% end %>
<% end %>

Copyable Raw Data

Click the text box to select all data, then copy with Cmd+C or Ctrl+C

<% else %>

No raw discovery data available. Run discovery again to collect debug data.

<% end %>
<% "checks" -> %>
<.icon name="hero-clipboard-document-check" class="mx-auto h-12 w-12 text-gray-400" />

No checks configured

Get started by creating a service check for this device.

<.button type="button"> <.icon name="hero-plus" class="h-4 w-4" /> Add Check
<% "preseem" -> %> <%= if @preseem_access_point do %>
<%!-- Score cards --%>
QoE Score
{if @preseem_access_point.qoe_score, do: Float.round(@preseem_access_point.qoe_score, 1), else: "---"}
Capacity Score
{if @preseem_access_point.capacity_score, do: Float.round(@preseem_access_point.capacity_score, 1), else: "---"}
RF Score
{if @preseem_access_point.rf_score, do: Float.round(@preseem_access_point.rf_score, 1), else: "---"}
<%!-- Details card --%>

Access Point Details

Name
{@preseem_access_point.name || "---"}
Preseem ID
{@preseem_access_point.preseem_id}
Subscribers
{@preseem_access_point.subscriber_count || "---"}
Busy Hours
<%= if @preseem_access_point.busy_hours do %> {@preseem_access_point.busy_hours} hrs/day <% else %> --- <% end %>
Airtime Utilization
<%= if @preseem_access_point.airtime_utilization do %> {Float.round(@preseem_access_point.airtime_utilization, 1)}% <% else %> --- <% end %>
Match Type
{@preseem_access_point.match_confidence}
<%!-- Recent metrics table --%> <%= if @preseem_metrics != [] do %>

Recent QoE Metrics

<%= for metric <- @preseem_metrics do %> <% end %>
Time Latency (ms) P95 Latency Jitter (ms) Loss (%) Throughput Subscribers
{Calendar.strftime(metric.recorded_at, "%Y-%m-%d %H:%M")} {if metric.avg_latency, do: Float.round(metric.avg_latency, 1), else: "---"} {if metric.p95_latency, do: Float.round(metric.p95_latency, 1), else: "---"} {if metric.avg_jitter, do: Float.round(metric.avg_jitter, 1), else: "---"} {if metric.avg_loss, do: Float.round(metric.avg_loss, 2), else: "---"} {if metric.avg_throughput, do: "#{Float.round(metric.avg_throughput, 1)} Mbps", else: "---"} {metric.subscriber_count || "---"}
<% end %>
<% else %>

No Preseem data linked to this device.

<% end %> <% _ -> %>

Tab not found

<% end %>