Monitoring Cisco Meraki Dashboard with NetCrunch

Discover how to extend Cisco Meraki monitoring with NetCrunch for detailed visibility into SSIDs, client usage, and rogue access points. Learn what wireless metrics you can track and how centralized reporting enables proactive network management. This guide explains how integrated monitoring enables you to anticipate and resolve network issues more quickly

Cisco Meraki provides effective built-in alerts through its Dashboard for immediate network issues. However, detailed monitoring of wireless infrastructure, client usage, and rogue access points often requires additional integration with advanced monitoring tools. This guide demonstrates how to extend Cisco Meraki monitoring capabilities by integrating with NetCrunch using a PowerShell script and JavaScript parser.

Prerequisites

To proceed, you'll need:

  • Cisco Meraki Dashboard API key (generate your API key)
  • NetCrunch installed and configured
  • Basic PowerShell knowledge

PowerShell Script for Data Collection

Create a script file on your NetCrunch Server machine— for example, at C:\Scripts\MerakiDashboardScript.ps1 - and populate it with the following content, making sure to include your API key:

$apiKey = "<your api key here>"
$baseUrl = "https://api.meraki.com/api/v1"
$outputPath = "C:\Scripts\meraki.json"
$headers = @{
    "X-Cisco-Meraki-API-Key" = $apiKey
    "Content-Type" = "application/json"
}

function Convert-IsoUtc {
    param([long]$unix)
    if ($unix -gt 1000000000) {
        return ([DateTimeOffset]::FromUnixTimeSeconds($unix).UtcDateTime.ToString("yyyy-MM-ddTHH:mm:ssZ"))
    } else {
        return $null
    }
}


$report = @{
    Organization = @{}
    Network      = @{}
    Devices      = @()
    Wireless     = @()
    Clients      = @()
    RogueSSIDs   = @()
    OtherSSIDs   = @()
}


try {
    $orgs = Invoke-RestMethod -Uri "$baseUrl/organizations" -Method Get -Headers $headers
    $org = $orgs[0]
    $report.Organization = $org
    Write-Host "`n== Meraki Organizations ==" -ForegroundColor Cyan
    Write-Host "ID: $($org.id)  Name: $($org.name)" -ForegroundColor Green
} catch {
    Write-Host "Error fetching organizations: $($_.Exception.Message)" -ForegroundColor Red
    return
}


try {
    $networks = Invoke-RestMethod -Uri "$baseUrl/organizations/$($org.id)/networks" -Method Get -Headers $headers
    $network = $networks[0]
    $report.Network = $network
    Write-Host "`n== Networks in Organization ==" -ForegroundColor Cyan
    Write-Host "ID: $($network.id)  Name: $($network.name)" -ForegroundColor Green
} catch {
    Write-Host "Error fetching networks: $($_.Exception.Message)" -ForegroundColor Red
    return
}


try {
    $devices = Invoke-RestMethod -Uri "$baseUrl/networks/$($network.id)/devices" -Method Get -Headers $headers
    $report.Devices = $devices
    Write-Host "`n== Devices in Network ==" -ForegroundColor Cyan
    $devices | ForEach-Object {
        Write-Host "Name: $($_.name) | Model: $($_.model) | Serial: $($_.serial)" -ForegroundColor Yellow
    }

    $apDevice = $devices | Where-Object { $_.model -like "MR*" } | Select-Object -First 1
    $serial = $apDevice.serial
    Write-Host "`nUsing device: $($apDevice.name) ($serial)" -ForegroundColor Magenta
} catch {
    Write-Host "Error fetching devices: $($_.Exception.Message)" -ForegroundColor Red
    return
}


try {
    $apStatus = Invoke-RestMethod -Uri "$baseUrl/devices/$serial/wireless/status" -Method Get -Headers $headers
    $report.Wireless = $apStatus.basicServiceSets
    Write-Host "`n== AP Wireless Status ==" -ForegroundColor Cyan
    $apStatus.basicServiceSets | ForEach-Object {
        Write-Host "SSID: $($_.ssidName) | Band: $($_.band) | Channel: $($_.channel) | Power: $($_.power) dBm" -ForegroundColor Blue
    }
} catch {
    Write-Host "Error fetching AP wireless status: $($_.Exception.Message)" -ForegroundColor Red
}


try {
    $clients = Invoke-RestMethod -Uri "$baseUrl/networks/$($network.id)/clients" -Method Get -Headers $headers
    $report.Clients = $clients
    Write-Host "`n== Clients ==" -ForegroundColor Cyan
    $clients | ForEach-Object {
        Write-Host "$($_.description) - $($_.mac) - Usage: $($_.usage.total) Bytes" -ForegroundColor DarkGreen
    }
} catch {
    Write-Host "Error fetching clients: $($_.Exception.Message)" -ForegroundColor Red
}


try {
    $airMarshal = Invoke-RestMethod -Uri "$baseUrl/networks/$($network.id)/wireless/airMarshal" -Method Get -Headers $headers
    if ($airMarshal) {
        $rogue = @()
        $other = @()

        foreach ($entry in $airMarshal) {
            $record = [PSCustomObject]@{
                SSID       = $entry.ssid
                BSSID      = $entry.bssid
                Signal     = $entry.signalStrength
                LastSeen   = Convert-IsoUtc $entry.lastSeen
                SeenOnLAN  = $entry.seenOnLan
            }
            if ($entry.seenOnLan -eq $true) {
                $rogue += $record
            } else {
                $other += $record
            }
        }

        $report.RogueSSIDs = $rogue
        $report.OtherSSIDs = $other

        Write-Host "`n== Air Marshal: Rogue SSIDs ==" -ForegroundColor Red
        $rogue | ForEach-Object {
            Write-Host "SSID: $($_.SSID) | MAC: $($_.BSSID) | Signal: $($_.Signal) dBm | Seen: $($_.LastSeen)" -ForegroundColor DarkRed
        }

        Write-Host "`n== Air Marshal: Other SSIDs ==" -ForegroundColor Cyan
        $other | ForEach-Object {
            Write-Host "SSID: $($_.SSID) | MAC: $($_.BSSID) | Signal: $($_.Signal) dBm | Seen: $($_.LastSeen)" -ForegroundColor DarkCyan
        }
    }
} catch {
    Write-Host "Error fetching Air Marshal data: $($_.Exception.Message)" -ForegroundColor Red
}

try {
    $json = $report | ConvertTo-Json -Depth 5
    [System.IO.File]::WriteAllText($outputPath, $json, [System.Text.UTF8Encoding]::new($false))
    Write-Host "`n== Report saved to $outputPath ==" -ForegroundColor Green
} catch {
    Write-Host "Error saving JSON file: $($_.Exception.Message)" -ForegroundColor Red
}

Data Parser JavaScript code

In NetCrunch’s Data Parsers, create a new parser: Settings -> Resources -> Data Parsers. With blue plus create new parser, select type JavaScript and name it. Paste code below. Remember to paste the contents of the output file c:\Scripts\meraki.json into the Test Data field.

const doc = typeof data === 'string' ? JSON.parse(data) : data;
result.status("Organization", {
value: "OK",
data: {
name: doc.Organization?.name,
networkName: doc.Network?.name
}
});
// Define counters
result.counters([
{ path: "Devices/Count", value: doc.Devices.length },
{ path: "Wireless/TotalSSIDs", value: doc.Wireless.length },
{ path: "Clients/Count", value: doc.Clients.length },
{ path: "RogueSSIDs/Count", value: doc.RogueSSIDs.length }
]);

Add Script Sensor in NetCrunch

Important File Location Note:

Make sure that the PowerShell script (MerakiDashboardScript.ps1) and the resulting JSON file (meraki.json) are placed on the same machine where the NetCrunch Server is installed. This ensures that the Script Sensor can access the script and read the JSON output directly. The file names used here are examples and can be changed to suit your environment.

  1. Select a Node for Monitoring Cisco Meraki Dashboard
  2. Add a new Script Sensor:
    • in Node Settings go to section Monitoring Sensors and use plus to add sensor. Search for Script and select it
    • Sensor Name: e.g., MerakiDashboard
    • Script Type: PowerShell
    • Specify the path and script name (e.g., c:\Scripts\MerakiDashboardScript.ps1)
    • Check Read result from file, specify the path to the JSON file (e.g., c:\Scripts\meraki.json)
    • Select the previously created data parser in Script Output Data Format

Configure Alerts

  1. Add a new Alert:
    - Event Trigger: New Event for Monitoring Sensor Counter

  2. Choose severity and description.
    - Select Counter set "average value" set "more than" and enter clients number (e.g., 20).

  3. Counter Selection:
    From the Script.Clients, select Clients . You can filter instances or simply select All instances and monitor clients regardless of, for example, organizations.
  4. Confirm your selection and create the Alert.
  5. Associate your preferred Alerting Script if needed.

Completion

NetCrunch now monitors detailed data from your Cisco Meraki Dashboard.

Conclusion

Integrating Cisco Meraki with NetCrunch significantly enhances network monitoring capabilities. This method provides comprehensive visibility into device health, client activities, and wireless environment, allowing proactive infrastructure management and troubleshooting.

clientsdasboardmerakinetworksorganizationsroguescriptsensorwifi

NetCrunch. Answers not just pictures

Maps → Alerts → Automation → Intelligence