First time on the forum so hope you’ll forgive any newbie errors. Also my coding knowledge is limited.
I have been aiming to introduce some network information within HA. I tried the very good home assistant network scanner but this relies on information supplied by the router. I am using Sky and the router they provided allows for very limited configuration. So the output from Network Scanner is based on poor info in this case. The router and mesh are on my list for replacing with a ‘proper’ router/mesh system but not sure when it will rise up my priority list…
Network scanner has an example using flex-table-card and that lead me to this post and the info here and elsewhere in the community got me to the point where I have a working system based around Fing and their API. I have the premium version which gives you everything they have but the API does come with the basic free version although I think this will only update manually and a max of 3 times a day - so maybe of limited use.
So this is my experience of how to do this - which I am sure could be streamlined/simplified or approached in other ways. I couldn’t find any examples for Fing so this may give some people a starting point.
Obviously you need to install flex-table-card to use and enable the Fing API from within Fing.
There are three elements:
A sensor to retrieve the data from the API
sensor:
- platform: rest
name: fing_api_data
resource: http://192.168.1.xxx:49090/1/devices?auth=authorisationkeyfromapp # Replace with actual API endpoint
json_attributes:
- devices
value_template: "OK"
A template sensor to transform the JSON into something flex understands:
template:
- sensor:
- name: "Fing Devices Table"
state: "Device Data"
attributes:
devices: >
{% set devices = state_attr('sensor.fing_api_data', 'devices') %}
{% if devices %}
{{ devices }}
{% else %}
"error": "No devices found or invalid data"
{% endif %}
And finally the config file for the flex-card-table
type: custom:flex-table-card
title: Fing Devices
entities:
- sensor.fing_devices_table
sort_by: x.name+
columns:
- name: Name
data: devices
modify: >-
if (x.name && x.name.length > 0) {'<div style="font-weight: bold;">' +
x.name +'</div>'} else {'-'}
fallback: N/A
- name: MAC Address
data: devices
modify: if (x.mac && x.mac.length > 0) {x.mac} else {'-'}
fallback: N/A
- name: IP Address
data: devices
modify: if (x.ip[0] && x.ip[0].length > 0) {x.ip[0]} else {'-'}
fallback: N/A
- data: devices
name: " "
icon: mdi:arrow-up-drop-circle-outline
align: center
modify: |-
var ICON = 'mdi:arrow-up-drop-circle-outline';
var ICONCOLOR = 'color:green';
if (x.state =='UP')
ICON = 'mdi:arrow-up-drop-circle-outline';
if (x.state =='UP')
ICONCOLOR = 'color:green';
if (x.state =='DOWN')
ICON = 'mdi:arrow-down-drop-circle-outline';
if (x.state =='DOWN')
ICONCOLOR = 'color:red';
'<ha-icon icon="' + ICON + '" style="' + ICONCOLOR + '">'
fallback: Unknown
- name: Type
data: devices
modify: |-
if(x.type == undefined)
{"-"}
else {
switch(x.type){
case 'DESKTOP':
'<ha-icon icon="mdi:monitor">';
break;
case 'GATEWAY':
'<ha-icon icon="mdi:hub-outline">';
break;
case 'LAPTOP':
'<ha-icon icon="mdi:laptop">';
break;
case 'LIGHT':
'<ha-icon icon="mdi:lightbulb-outline">';
break;
case 'LOUDSPEAKER':
'<ha-icon icon="mdi:speaker-wireless">';
break;
case 'MEDIA_PLAYER':
'<ha-icon icon="mdi:play-network-outline">';
break;
case 'MOBILE':
'<ha-icon icon="mdi:cellphone">';
break;
case 'NAS_STORAGE':
'<ha-icon icon="mdi:nas">';
break;
case 'PRINTER':
'<ha-icon icon="mdi:printer">';
break;
case 'RADIO':
'<ha-icon icon="mdi:radio">';
break;
case 'RASPBERRY':
'<ha-icon icon="mdi:raspberry-pi">';
break;
case 'ROUTER':
'<ha-icon icon="mdi:router">';
break;
case 'SMART_CONTROLLER':
'<ha-icon icon="mdi:hub">';
break;
case 'SMART_HOME':
'<ha-icon icon="mdi:home-outline">';
break;
case 'SMART_PLUG':
'<ha-icon icon="mdi:power-plug-outline">';
break;
case 'STB':
'<ha-icon icon="mdi:set-top-box">';
break;
case 'SURVEILLANCE_CAMERA':
'<ha-icon icon="mdi:cctv">';
break;
case 'TABLET':
'<ha-icon icon="mdi:tablet">';
break;
case 'TELEVISION':
'<ha-icon icon="mdi:television">';
break;
case 'VOICE_CONTROL':
'<ha-icon icon="mdi:account-voice">';
break;
case 'WIFI':
'<ha-icon icon="mdi:wifi">';
break;
case 'WIFI_EXTENDER':
'<ha-icon icon="mdi:wifi-sync">';
break;
default:
'<ha-icon icon="mdi:help-circle-outline">';
}
}
sort_unmodified: true
align: center
fallback: N/A
- name: Make
data: devices
modify: if (x.make && x.make.length > 0) {x.make} else {'-'}
fallback: N/A
- name: Model
data: devices
modify: if (x.model && x.model.length > 0) {x.model} else {'-'}
fallback: N/A
- name: First Seen
data: devices
modify: |-
if(x.first_seen == undefined)
{"-"}
else {
var date = new Date(x.first_seen);
String(date.getDate()).padStart(2,'0')+"/"+
(String(date.getMonth()+ 1).padStart(2,'0'))+"/"+
date.getFullYear()+
" "+
String(date.getHours()).padStart(2,'0')+":"+
String(date.getMinutes()).padStart(2,'0')+":"+
String(date.getSeconds()).padStart(2,'0')
}
- name: Last Changed
data: devices
modify: |-
if(x.last_changed == undefined)
{"-"}
else {
var date = new Date(x.last_changed);
String(date.getDate()).padStart(2,'0')+"/"+
(String(date.getMonth()+ 1).padStart(2,'0'))+"/"+
date.getFullYear()+
" "+
String(date.getHours()).padStart(2,'0')+":"+
String(date.getMinutes()).padStart(2,'0')+":"+
String(date.getSeconds()).padStart(2,'0')
}
This gives example output like this:
Very happy that thanks to the contributions in these posts I found ways to substitute icons and format dates etc.
Issues?
I can’t get the initial sort to work. I assumed the x.name would give me that as the default but no joy. The sort on column feature works perfectly though.
I would also love to. able to filter within the table output amd/or search for a record but I believe neither of these is not a feature as yet. In the absence of this I thought I would just add another sensor/template sensor/table config with a value template on the sensor like this:
- platform: rest
name: fing_api_data_down
resource: http://192.168.1.xxx:49090/1/devices?auth=fingapiauthorisationcode # Replace with actual API endpoint
json_attributes:
- devices
value_template: "{{ value_json.devices | selectattr('state', 'eq', 'DOWN') | list | first }}"
But that still shows all records. I suspect I just don’t understand the formatting of value templates sufficiently.
Any ideas on a good way to achieve this would be greatly appreciated.
Anyway many thanks for all the ideas from all of you in this post and thanks to @Ildar_Gabdullin for setting it up and all the people who have contributed to this card