How to make a network monitoring card


I have sensors upload/download. How create similar card?
Image taken from here Netdata - Home Assistant

Here is my network monitopring dashboard, that has charts simililar to what you want to achieve:

And here is the code for just the chart part of monitor card:

            - type: custom:apexcharts-card
              update_interval: 5s
              graph_span: 5m
              show:
                loading: false
              apex_config:
                chart:
                  height: 250px
                grid:
                  show: true
                  strokeDashArray: 0
                  borderColor: '#444444'
                  position: back
                  xaxis:
                    lines:
                      show: true
                  yaxis:
                    lines:
                      show: true
                yaxis:
                  forceNiceScale: true
                xaxis:
                  type: datetime
                  axisTicks:
                    show: true
                  tickAmount: 6
                  labels:
                    format: HH:mm
                  lines:
                    show: true
                fill:
                  type: gradient
                  gradient:
                    type: vertical
                    shade: dark
                    stops:
                      - 0
                      - 90
                    opacityFrom:
                      - 1
                      - 0.2
                    opacityTo:
                      - 0.2
                      - 1
              series:
                - entity: sensor.internet_speed_in1
                  color: var(--green1)
                  name: IN
                - entity: sensor.internet_speed_out1
                  color: var(--green4)
                  name: OUT
                  invert: true
                - entity: input_number.zero_value
                  color: var(--green4)
                  name: ' '
              all_series_config:
                stroke_width: 1
                type: area

Hope this helps to start…

8 Likes

This is a cool option ).
Sad that “mini-graph-card” does not have it & users have to use card-mod to achieve same.

Hi @mirekmal,

The information of the access point shown just above the Wifi throughput, is that a custom card or did you use cardmod?

All the cards are standard available cards (text-diver, markdown, apex chart) just put together into vertical stack. Here is full card code for one device:

type: custom:vertical-stack-in-card
cards:
  - type: custom:text-divider-row
    text: AP-GROUND
  - type: markdown
    content: >
      <ha-icon icon="mdi:information-variant"></ha-icon> Mesh Node: {{
      states('sensor.draytek_ap_g_model') }}

      <ha-icon icon="mdi:alert-outline"></ha-icon> FW Ver: {{
      states('sensor.draytek_ap_g_firmware') }}                  

      <ha-icon icon="mdi:clock-check-outline"></ha-icon> Uptime: {{
      states('sensor.draytek_ap_g_uptime') }}
  - type: custom:text-divider-row
    text: WI-FI Throughput
  - type: custom:apexcharts-card
    update_interval: 5s
    graph_span: 5m
    show:
      loading: false
    apex_config:
      chart:
        height: 250px
      grid:
        show: true
        strokeDashArray: 0
        borderColor: '#444444'
        position: back
        xaxis:
          lines:
            show: true
        yaxis:
          lines:
            show: true
      yaxis:
        forceNiceScale: true
      xaxis:
        type: datetime
        axisTicks:
          show: true
        tickAmount: 6
        labels:
          format: HH:mm
        lines:
          show: true
      fill:
        type: gradient
        gradient:
          type: vertical
          shade: dark
          stops:
            - 0
            - 90
          opacityFrom:
            - 1
            - 0.2
          opacityTo:
            - 0.2
            - 1
    series:
      - entity: sensor.lan_speed_ap_g_in
        color: var(--pink1)
        name: IN
      - entity: sensor.lan_speed_ap_g_out
        color: var(--pink3)
        name: OUT
        invert: true
      - entity: input_number.zero_value
        color: var(--pink3)
        name: ' '
    all_series_config:
      stroke_width: 1.5
      type: area

Tricky part are actual throughput sensors and device info - for all om my devices I use SNPM monitoring to get this data.

2 Likes

Thanks, this looks great!

I did not find some properties in the documentation, for example “xaxis”… when they are deleted, at first glance nothing changes…

type: custom:apexcharts-card
update_interval: 5s
header:
  show: true
  title: Synology Network
graph_span: 6h
show:
  loading: false
apex_config:
  chart:
    height: 250px
  grid:
    show: true
    strokeDashArray: 0
    borderColor: '#444444'
    position: back
    xaxis:
      lines:
        show: true
    yaxis:
      lines:
        show: true
  yaxis:
    forceNiceScale: true
series:
  - entity: sensor.synologynas_download_throughput
    color: '426F2A'
    name: Download
  - entity: sensor.synologynas_upload_throughput
    color: '892937'
    name: Upload
    invert: true
all_series_config:
  stroke_width: 2
  type: area
1 Like

apexchart-card implements full apex graphics library that is very extensive. Not everything is documented in card documentation. For more advanced functions you can refer to official apex documentation, where you can find tons of additional settings. In particular option you refers to is causing vertical lines (for xaxis) to be shown, but true is also default value. If you change this to false you will see the difference. So it here probably as remnant from the time I created this chart and was playinf with different settings.

I love your network monitoring dashboard cards!
I have something similar, just a little more basic (using snmp with mini chart cards and sensor groups) and would like to enhance mine with some of your design.
However, what is the purpose of the ‘- entity: input_number.zero_value’ and can I see your sensor and template config for this?

Well, I just use it to anchow y-scale to zero values. I noticed that if there is no zero value in the dataset, apex chart has tendency to shift the scale by fraction of unit. Also this gives a solid line at zero value for reference.

Nice design!
Would you please also share the code for the header card’s?
(WAN, Devices, ADGUARD)

Here it is
WAN:

type: custom:vertical-stack-in-card
cards:
  - type: custom:vertical-stack-in-card
    horizontal: false
    cards:
      - type: custom:text-divider-row
        text: WAN
      - type: custom:vertical-stack-in-card
        horizontal: true
        cards:
          - type: custom:button-card
            entity: sensor.bandwidth_utilization
            icon: mdi:web
            name: FiberX
            show_name: true
            size: 40%
            show_state: true
            state_display: |

              [[[
                if (states['sensor.snmp_wan1_status'].state == 1 )
                  return states['sensor.bandwidth_utilization'].state+"%";
                else
                  return "N/C";
              ]]]
            card_size: 7
            label: |
              [[[
                if (states['sensor.snmp_wan1_status'].state == 1 )
                  return states['sensor.myip'].state;
                else
                  return "DOWN";
              ]]]
            show_label: true
            styles:
              grid:
                - grid-template-areas: "\"i\" \"s\" \"l\" \"n\""
                - grid-template-columns: 1fr
                - grid-template-rows: 48px 48px 32px 48px
              name:
                - font-size: 13px
              state:
                - font-size: 28px
                - color: |
                    [[[
                      if (states['sensor.snmp_wan1_status'].state == 1 )
                        return "var(--ok-text)";
                      else
                        return "var(--alert-text)";
                    ]]]
              label:
                - font-size: 16px
                - color: |
                    [[[
                      if (states['sensor.myip'].state == states['sensor.mirekmal_com'].state & states['sensor.myip'].state == states['sensor.mirekmal_homeserver_com'].state & states['sensor.myip'].state == states['sensor.mirekmal_dyndns_org'].state)
                        return "var(--dimmed-text)";
                      return "var(--alert-text)";
                    ]]]
          - type: custom:button-card
            entity: sensor.mirekmal_dyndns_org
            icon: |
              [[[
                if (states['sensor.snmp_vpn_status'].state >= 1 )
                  return "mdi:shield-link-variant-outline";
                else
                  return "mdi:shield-off-outline";
              ]]]
            name: VPN
            show_name: true
            size: 40%
            show_state: true
            state_display: |
              [[[
                if (states['sensor.snmp_vpn_status'].state >= 1 )
                  return states['sensor.bandwidth_utilization_vpn'].state+"%";
                else
                  return "N/C";
              ]]]
            card_size: 7
            label: |
              [[[
                if (states['sensor.snmp_vpn_status'].state >= 1 )
                  return states['sensor.snmp_vpn_ip'].state;
                else
                  return "DOWN";
              ]]]                
            show_label: true
            styles:
              grid:
                - grid-template-areas: "\"i\" \"s\" \"l\" \"n\""
                - grid-template-columns: 1fr
                - grid-template-rows: 48px 48px 32px 48px
              name:
                - font-size: 13px
              state:
                - font-size: 28px
                - color: |
                    [[[
                      if (states['sensor.snmp_vpn_status'].state >= 1 )
                        return "var(--ok-text)";
                      else
                        return "var(--alert-text)";
                    ]]]
              label:
                - font-size: 16px
          - type: custom:button-card
            entity: sensor.mirekmal_vpn_ddns_net
            icon: |
              [[[
                if (states['sensor.snmp_lte_status'].state == 1 )
                  return "mdi:signal";
                else
                  return "mdi:signal-off";
              ]]]
            name: LTE
            show_name: true
            size: 40%
            show_state: true
            state_display: |
              [[[
                if (states['sensor.snmp_lte_status'].state == 1 )
                  return "OK";
                else
                  return "N/C";
              ]]]
            card_size: 7
            label: |
              [[[
                if (states['sensor.snmp_lte_status'].state == 1 )
                  return states['sensor.mirekmal_lte_dyndns_org'].state;
                else
                  return "DOWN";
              ]]] 
            show_label: true
            styles:
              grid:
                - grid-template-areas: "\"i\" \"s\" \"l\" \"n\""
                - grid-template-columns: 1fr
                - grid-template-rows: 48px 48px 32px 48px
              name:
                - font-size: 13px
              state:
                - font-size: 28px
                - color: |
                    [[[
                      if (states['sensor.snmp_lte_status'].state == 1 )
                        return "var(--ok-text)";
                      else
                        return "var(--warning-text)";
                    ]]]
              label:
                - font-size: 16px
                - color: |
                    [[[
                      if (states['sensor.snmp_lte_status'].state == 1 )
                        return "var(--ok-text)";
                      else
                        return "var(--warning-text)";
                    ]]]

DEVICES:

type: custom:vertical-stack-in-card
cards:
  - type: custom:text-divider-row
    text: DEVICES
  - type: custom:vertical-stack-in-card
    cards:
      - type: custom:button-card
        entity: sensor.devices_all_count
        icon: mdi:check-network-outline
        name: WIRED
        show_name: true
        size: 40%
        show_state: true
        state_display: |
          [[[ 
            return states['sensor.fing_count_wired_devices_up'].state
          ]]]
        card_size: 7
        label: |
          [[[
            return states['sensor.fing_count_wired_devices'].state
          ]]]
        show_label: true
        styles:
          grid:
            - grid-template-areas: "\"i\" \"s\" \"l\" \"n\""
            - grid-template-columns: 1fr
            - grid-template-rows: 48px 48px 32px 48px
          name:
            - font-size: 13px
          state:
            - font-size: 28px
            - color: var(--ok-text)
          label:
            - font-size: 16px
      - type: custom:button-card
        entity: sensor.devices_wifi_count
        icon: mdi:access-point-network
        name: WIFI
        show_name: true
        size: 40%
        show_state: true
        state_display: |
          [[[
            return states['sensor.fing_count_wireless_devices_up'].state
          ]]]
        card_size: 7
        label: |
          [[[
            return states['sensor.fing_count_wireless_devices'].state
          ]]]
        show_label: true
        styles:
          grid:
            - grid-template-areas: "\"i\" \"s\" \"l\" \"n\""
            - grid-template-columns: 1fr
            - grid-template-rows: 48px 48px 32px 48px
          name:
            - font-size: 13px
          state:
            - font-size: 28px
            - color: var(--ok-text)
          label:
            - font-size: 16px
      - type: custom:button-card
        entity: sensor.devices_guest_count
        icon: mdi:help-network-outline
        name: DHCP
        show_name: true
        size: 40%
        show_state: true
        state_display: |
          [[[
            return states['sensor.fing_count_guest_devices_up'].state
          ]]]
        card_size: 7
        label: |
          [[[
            return states['sensor.fing_count_guest_devices'].state
          ]]]
        show_label: true
        styles:
          grid:
            - grid-template-areas: "\"i\" \"s\" \"l\" \"n\""
            - grid-template-columns: 1fr
            - grid-template-rows: 48px 48px 32px 48px
          name:
            - font-size: 13px
          state:
            - font-size: 28px
            - color: var(--ok-text)
          label:
            - font-size: 16px

ADGUARD:

type: custom:vertical-stack-in-card
cards:
  - type: custom:vertical-stack-in-card
    cards:
      - text: ADGUARD
        type: custom:text-divider-row
      - cards:
          - entity: switch.adguard_home_filtering
            size: 30px
            type: custom:button-card
            name: Filtering
            icon: mdi:shield-check
          - entity: switch.adguard_home_parental_control
            size: 30px
            type: custom:button-card
            name: Parental
            icon: mdi:shield-account
          - entity: switch.adguard_home_protection
            size: 30px
            type: custom:button-card
            name: Protection
            icon: mdi:shield-bug
          - entity: switch.adguard_home_safe_browsing
            size: 30px
            type: custom:button-card
            name: Browsing
            icon: mdi:shield-star
          - entity: switch.adguard_home_safe_search
            size: 30px
            type: custom:button-card
            name: Searching
            icon: mdi:shield-search
        horizontal: true
        type: custom:vertical-stack-in-card
  - cards:
      - align_icon: left
        animate: false
        entities:
          - entity: sensor.adguard_home_dns_queries
            index: 0
        font_size: 50
        hour24: true
        hours_to_show: 24
        points_per_hour: 1
        smoothing: false
        line_color: var(--greenish)
        line_width: 3
        name: Queries
        height: 150
        show:
          extrema: false
          fill: fade
          icon: false
          name: false
        type: custom:mini-graph-card
      - align_icon: left
        animate: false
        entities:
          - entity: sensor.adguard_home_dns_queries_blocked
            index: 0
        font_size: 50
        hour24: true
        hours_to_show: 24
        points_per_hour: 1
        smoothing: false
        line_color: var(--cyanish)
        line_width: 3
        name: Blocked
        height: 150
        show:
          extrema: false
          fill: fade
          icon: false
          name: false
        type: custom:mini-graph-card
      - align_icon: left
        animate: false
        entities:
          - entity: sensor.adguard_home_average_processing_speed
            index: 0
        font_size: 50
        hour24: true
        hours_to_show: 24
        points_per_hour: 1
        smoothing: false
        line_color: var(--light-magenta)
        line_width: 3
        name: Processing
        height: 150
        show:
          extrema: false
          fill: fade
          icon: false
          name: false
        type: custom:mini-graph-card
    type: horizontal-stack
card_mod:
  style: |
    position: top

Bear in mind lots of custom sensors (SNMP, RESTfull,) to get required data from router or fingbox…

1 Like

Thank you man for sharing this.

Seriously, thank you bunches for sharing this. I absolutely love the layout you have. For now I’m looking to just pull the send/receive from my FIOS router, but am having one heck of a time getting the apexchart to go full width. Any thoughts? I’ve added my current dashboard code below.

views:
  - title: Home
    sections:
      - type: grid
        cards:
          - type: custom:apexcharts-card
            update_interval: 5s
            graph_span: 5m
            show:
              loading: false
            apex_config:
              chart:
                height: 250px
                redrawOnParentResize: true
                redrawOnWindowResize: true
              grid:
                show: true
                strokeDashArray: 0
                borderColor: '#444444'
                position: back
                xaxis:
                  lines:
                    show: true
                yaxis:
                  lines:
                    show: true
              yaxis:
                forceNiceScale: true
              xaxis:
                type: datetime
                axisTicks:
                  show: true
                tickAmount: 6
                labels:
                  format: HH:mm
                lines:
                  show: true
              fill:
                type: gradient
                gradient:
                  type: vertical
                  shade: dark
                  stops:
                    - 0
                    - 90
                  opacityFrom:
                    - 1
                    - 0.2
                  opacityTo:
                    - 0.2
                    - 1
            series:
              - entity: sensor.fios_router_kib_s_received
                color: var(--green1)
                name: IN
              - entity: sensor.fios_router_kib_s_sent
                color: var(--green4)
                name: OUT
                invert: true
              - entity: input_number.zero_value
                color: green
                name: ' '
            all_series_config:
              stroke_width: 1
              type: area
        column_span: 4

For those that need it or are having similar issues and feeling frustrated, after several hours I figured it out. I had to nest the card into a horizontal-stack card. Code below for reference.

views:
  - title: Network
    sections:
      - type: grid
        cards:
          - type: horizontal-stack
            cards:
              - type: custom:apexcharts-card
                update_interval: 5s
                graph_span: 1h
                show:
                  loading: false
                apex_config:
                  chart:
                    height: 250px
                    redrawOnParentResize: true
                    redrawOnWindowResize: true
                  grid:
                    show: true
                    strokeDashArray: 0
                    borderColor: '#444444'
                    position: back
                    xaxis:
                      lines:
                        show: true
                    yaxis:
                      lines:
                        show: true
                  yaxis:
                    forceNiceScale: true
                  xaxis:
                    type: datetime
                    axisTicks:
                      show: true
                    tickAmount: 15
                    labels:
                      format: HH:mm
                    lines:
                      show: true
                  fill:
                    type: gradient
                    gradient:
                      type: vertical
                      shade: dark
                      stops:
                        - 0
                        - 90
                      opacityFrom:
                        - 1
                        - 0.2
                      opacityTo:
                        - 0.2
                        - 1
                series:
                  - entity: sensor.fios_router_kib_s_received
                    color: green
                    name: IN
                  - entity: sensor.fios_router_kib_s_sent
                    color: green
                    name: OUT
                    invert: true
                  - entity: input_number.zero_value
                    color: darkgreen
                    name: ' '
                all_series_config:
                  stroke_width: 1
                  type: area
            grid_options:
              columns: full
              rows: auto
        column_span: 4
    type: sections
    max_columns: 4
    cards: []

Hello,

I try to get all the sensors form my Unifi components. But it’s hard because there are no documented MIBs for the Unifi components. Found only two files for the access points. Can you help me and post the sensor configuration?