AirScope — A Visual Frequency Analyzer for MikroTik (WISP-focused)

Hi everyone,

I’ve built a tool called AirScope, a visual frequency-scanning dashboard for MikroTik devices. It’s designed specifically for WISP operators who rely heavily on tools like Scan and Frequency Usage in Winbox but want something more visual, persistent, and insightful.

GitHub: GitHub - berksmbl/AirScope: MikroTik Frequency Analyzer · GitHub


:rocket: What is AirScope?

AirScope replaces the raw tables in Winbox with a modern, real-time dashboard that helps you see what’s happening across the spectrum.

It connects to your MikroTik via the RouterOS API and continuously collects scan + frequency usage data, then visualizes it in multiple ways — including a live spectrum graph, waterfall, and channel heatmap.


:key: Key Features

• Device Connection Panel

  • Connect via RouterOS API (port 8728)

  • Save device profiles (no passwords stored)

  • Supports both legacy wireless and RouterOS v7 wifi

• Dual Scan Modes (Continuous)

  • Networks Scan — detects and accumulates nearby APs (like Winbox scan, but persistent)

  • Frequency Usage — real airtime % + noise floor per frequency (~200 bins per sweep)

  • Max-hold logic ensures bursty/TDD signals are not missed

• Live Spectrum Graph

  • dBm vs MHz visualization

  • Signal + noise floor

  • Network overlays

  • Zoom + hover + PNG export

• Spectral Waterfall

  • Scrolling spectrogram of recent activity

• Channel Heatmap

  • One cell per 20 MHz channel

  • Combines:

    • Wi-Fi congestion

    • Raw spectrum energy

  • Clearly shows non-WiFi interference too

• Non-WiFi Interference Detection

  • Detects spectrum energy not explained by Wi-Fi networks

  • Flags things like:

    • Microwave interference

    • Radar

    • Proprietary links

  • Visualized as dashed bands + heatmap indicators

• Persistence (CDF) View

  • Mimosa-style frequency analysis

  • Shows how often airtime levels occur (not just averages)

  • Easily distinguish constant load vs burst interference

• Smart Channel Recommendation

  • Scores channels based on:

    • Overlapping signal strength

    • Spectrum usage

  • Suggests:

    • Best channel

    • Alternates

    • Cleanest 40/80 MHz blocks

• History & Compare

  • Save scans locally

  • Overlay past scans on live data

• Export Options

  • CSV (networks + usage)

  • PNG (spectrum graph)

• UI/UX

  • Dark mode (default) + light mode

  • Fully responsive

  • Real-time updates (SSE stream)


:gear: How It Works

  • The frontend (Next.js) opens a live stream (SSE over POST)

  • Backend maintains continuous RouterOS scan/usage streams

  • Data is accumulated server-side and pushed every second

  • Analysis (congestion, interference, recommendations) runs client-side


:test_tube: Getting Started

git clone https://github.com/BerkSMBL/AirScope.git
cd AirScope
npm install
npm run dev

Then open:
http://localhost:3000


:electric_plug: Connecting to MikroTik

  1. Enable API:
/ip service enable api

  1. Enter:
  • Router IP

  • Username / Password

  • Select wireless interface

Scanning starts automatically after connection.


:warning: Notes / Limitations

  • Background scanning is used when possible, but some modes require foreground scan → may interrupt traffic

  • One radio = one active tool (multiple sessions may conflict)

  • API (8728) is unencrypted → use only in trusted networks

  • Streams auto-stop after ~20s if UI disconnects


:bullseye: Why I Built This

As a WISP operator, I found Winbox tools:

  • Not visual enough

  • Not persistent

  • Hard to correlate spectrum vs detected networks

AirScope tries to combine:

  • MikroTik scan data

  • Real spectrum usage

  • Interference detection

  • Smart channel selection

…into a single, usable interface.


:speech_balloon: Feedback

I’d really appreciate feedback from other MikroTik / WISP users:

  • Feature ideas

  • Performance improvements

  • Compatibility issues (especially RouterOS v7 wifi)

Feel free to open issues or PRs on GitHub.

Thanks :raising_hands:

Moved to proper section

Hi,

Great idea, i'll try to run in docker soon because i've frequency problem.
I'll try my dockerfile when i'll do it. Deploy is planned on a swarm cluster, to keep it ready to use when needed.

In capsman/caps mode, will it work... ??

This looks really useful, especially the combination of the spectrum graph and channel heatmap. Being able to compare current interference with previous scans could save a lot of time when troubleshooting WISP networks.

I’m also curious about the CAPsMAN/CAP mode mentioned above. Does AirScope already support that setup, or is it planned for a future version?

It does look nice :slightly_smiling_face:.

JFYI, I would suggest to somehow show clearly how not all channels are the same in terms of:

  1. DFS/CAC (none vs. 1 min. vs. 10 min.)
  2. allowed radiation power

Compare with the graphics I posted here:

Nice job with the tool. I have been looking for more ways to make use of these wireless diagnostic functions within the MikroTik device and this provides some new ideas.

With a recent Debian install, I had to add some steps to run the tool but it was straightforward:

$ sudo apt install npm

$ npm install source-map-support

Note these are a little concerning:

npm WARN deprecated node-routeros@1.6.9: node-routeros has been discontinued

3 high severity vulnerabilities

Finally, add my local IP to AirScope/next.config.ts:

module.exports = {
allowedDevOrigins: ['local ip address'],
}

Thanks a lot for testing AirScope on Debian and for sharing the additional steps!

I wasn’t aware that node-routeros had been discontinued, so I really appreciate you pointing this out. I’ve looked into alternatives, but so far I haven’t found another Node.js RouterOS API library that provides the functionality I need and is actively maintained.

I’ll continue looking into this and see if I can find a better long-term solution. I also want to investigate the reported high-severity vulnerabilities and make sure they are not being introduced by dependencies that can be safely replaced or updated.

The allowedDevOrigins configuration is also useful feedback. I’ll look into making the development setup easier for LAN environments so users don’t have to manually modify next.config.ts.

Thanks again for taking the time to test it and for the detailed feedback! :+1:

Thanks for the suggestion! I completely agree that these factors are important, especially for 5 GHz deployments.

I’m planning to add this information in a future update so AirScope can clearly show the differences between channels, including DFS/CAC requirements and allowed transmit power.

My goal is not only to show which channel has less interference, but also to make it easier to understand which channel is actually the most practical choice for a real-world WISP deployment.

I’ll definitely take your suggestions into account when working on this part of the project. :+1:

Thanks! I’m planning to add a Dockerfile in the next update, so Docker/Swarm deployment should be easier.

Regarding CAPsMAN/CAP mode: I currently don’t have a CAPsMAN setup in my lab, and since I haven’t needed one myself, I haven’t specifically developed or tested AirScope for CAPsMAN yet.

However, AirScope currently discovers and lists the wireless interfaces exposed by the MikroTik device. So if the CAP exposes its wireless interfaces through the RouterOS API in the expected way, there is a good chance that connecting directly to the CAP will work with the current version.

If interface discovery or scanning doesn’t work properly in a CAP/CAPsMAN setup, I can look into adding specific support for it in a future update.

If you get a chance to test it with CAPsMAN, I’d be very interested in the results. That would also help me understand what needs to be improved. :+1:

Thanks for the feedback!

As I mentioned in my previous reply, I haven’t specifically developed or tested AirScope for CAPsMAN/CAP setups yet, mainly because I don’t currently have such a setup in my lab and haven’t had a personal need for it.

AirScope currently discovers and lists the wireless interfaces exposed by the MikroTik device, so I’m curious to see how well this works with CAPsMAN/CAP in a real-world setup.

If the current interface discovery or scanning doesn’t work properly in that environment, I can look into adding specific support for it in a future update.

I’d definitely like to make AirScope more useful for different MikroTik wireless deployments as the project evolves. :+1:

:satellite_antenna: AirScope Update — Spectrum Rules, a Rebuilt Scoring Engine & Docker

Quick recap: AirScope is a self-hosted web dashboard that talks to MikroTik over the RouterOS API and turns Winbox's Scanner and Freq. Usage tables into something you can actually plan a sector from. Open source, runs on your own box.

Here's what landed since the last post :backhand_index_pointing_down:


:vertical_traffic_light: Not all channels are equal — and now you can see it

Someone here pointed out that a congestion score alone hides what actually costs you: DFS, CAC time, and allowed EIRP. Fair point. It's in.

A regulatory ribbon now sits directly above the congestion strip, on the same frequency scale:

Meaning
:green_circle: free to use
:yellow_circle: DFS · 60 s CAC
:red_circle: DFS · 10 min CAC (weather radar)
:black_large_square: not allocated

…and the inline label carries the power ceiling (1 W, 4 W, 200 mW). ETSI / FCC, or off entirely.

The part I care about most: rules resolve worst-case across the channel's whole occupied width.

  • A 40 MHz channel clipping 5600–5650 → inherits the 10-minute CAC :stopwatch:
  • One straddling 5725 → takes the lower power limit
  • Running superchannel? 5350–5470 and 5000–5150 show up plainly as :no_entry: not allocated — the second one is aeronautical, including microwave landing systems

There's an opt-in "prefer channels without DFS" for the recommendation. Off by default — on 5 GHz that would exclude most of your usable spectrum, and that's your call, not the tool's.

:white_check_mark: Zero extra scanning for any of this. Static data, nobody's subscribers get dropped.


:brain: The scoring engine got rebuilt

The old version leaned on max-hold, and max-hold saturates: after ten minutes every bin approaches its all-time maximum and the ranking quietly collapses.

It now builds a per-bin occurrence histogram and scores from p50 (typical load) and p95 (near-worst case) — so longer observation makes the answer better instead of flatter. :chart_increasing:

Also in there:

  • :muted_speaker: Measured noise floor is part of the score, referenced against the quietest bin in the sweep
  • :antenna_bars: Adjacent-channel skirt — a strong carrier just outside your channel still desenses the front end
  • :collision: Burstiness penalty from the p95–p50 spread — TDMA links feel variance harder than steady load
  • :level_slider: Confidence levels, so you know when the recommendation is still guessing
  • :locked: Hysteresis, so the headline frequency stops flapping between near-equal candidates

:bullseye: Superchannel-aware throughout

The channel congestion view is no longer a 20 MHz grid. It's a sliding window stepped at the measurement resolution, with a 20 / 40 / 80 MHz selector — because a superchannel radio can sit anywhere, and the cleanest spot is often between grid channels.


:adhesive_bandage: RouterOS v7 fixed

v7 answers an empty query with an !empty sentence that the node-routeros client doesn't know — and it throws from inside the socket handler, where no try/catch can reach it. The whole connection died. :skull:

Patched. Tested against 7.21.5 (RB911G) and 6.49.20 (SXT 5 ac). Note that plenty of v7 boxes still run the legacy wireless package, so scan and frequency-monitor work there too.


:busts_in_silhouette: Sector view that costs you nothing

registration-table and monitor once are plain reads that never take the radio off channel, so they stream continuously whether or not you're scanning:

  • Per-client signal, SNR, CCQ, PHY rates, TDMA stats
  • One-line summary + sparklines :chart_decreasing:
  • Your active channel marked on every chart
  • The recommendation tells you what switching would actually gain

:spouting_whale: Docker

docker compose up -d --build

Multi-stage build, non-root, health check.

:warning: Run one instance per site — the server holds the RouterOS sessions and sweep state in memory, and two of them would fight over the same radio.


:prohibited: What it still won't do

No scheduled scanning. No automated DFS testing. Both mean taking the radio off channel on a timer and dropping subscribers — not a trade I'm willing to make.

Multi-point surveying (asking CPEs what they see) is the obvious next step, and the same objection applies. If it happens, it stays manual and opt-in.

:clipboard: The regulatory tables are a planning aid, not a compliance statement — national licensing varies, especially 5.7–5.9 GHz.


:link: Repo

GitHub - berksmbl/AirScope: MikroTik Frequency Analyzer · GitHub

Feedback welcome — the DFS suggestion was a good one and it made the tool better. :folded_hands: