Introducing ScanEyes

What is ScanEyes?

ScanEyes is a PHP web front end for visualizing, listening to, and archiving trunked radio traffic.

It allows user registration, permissions, and playlist creation.

It is currently live at sdrscan.com

screen
sdrscan viewed from a mobile device

conbined pic
Talkgroup browse mode
Screen Shot 2014-05-21 at 1.03.16 AM
Number of calls in a 24 hour period chart
Screen Shot 2014-05-21 at 12.59.35 AM
Screen Shot 2014-05-21 at 12.54.13 AM Admin control panel, log section
Screen Shot 2014-05-21 at 12.54.38 AM
App config of AdminCP
fakescanner
Fake scanner interface

Problem, Objective and Solution

Problem
  • A new radio system is being deployed in my city. New talkgroups pop up every day, need a way of logging them for review later so I can identify the unknown ones and submit the info (X City Police Dept) into the RadioReference Database
  • A means to record police dispatch calls in my city, so I can recall them when my local news paper publishes their “police blotter” section.
Objective
  • Program a script that records the calls so I can listen them to later, a pretty web interface is optional
Solution

How it works

Two essential pieces of software were written by me. LogRecorder (Available here) and the main ScanEyes application

The ScanEyes application is run in Apache with PHP without the need for a SQL server.

LogRecorder is a PHP script that runs in php-cli.exe (no web server) It polls sdrsharptrunking.log for file changes every 150ms and spawns an audio recorder if an active talkgroup is picked up by Unitrunker.

LogRecorder tells sox.exe to write an mp3 file containing call audio to a specific folder ‘YYYY/MM/DD/UNIXTIMESTAMP_TGID_TGNAME_RID_RNAME.mp3’

EverythingSearch by Void Tools indexes these files and when a user queries ScanEyes, the query is sent to es.exe with the search term. The resulting data is manipulated into various tables and charts.

Here is a diagram of the entire setup, including extra features I’ve built into the server for, for example, streaming live audio with low latency. This entire setup runs at about 7% total CPU utilization for a Core i5 4670K during idle. Main culprits for CPU usage are SDRSharp, 5%; and Unitrunker, 2%.

SDR flow diagram

There are two pieces of hardware in this setup, two SDR dongles. One talks to Unitrunker, another talks to SDRSharp.

Beginners explanation of trunked radio

Unitrunker listens to the control channel and gives a birds eye view of the entire radio system. It shows all the talkgroups on the radio system (Talkgroups are like virtual channels, unlike traditional analog radio, talkgroups are not bound to a particular frequency, rather grouped into a pool with other channels, sharing or competing for a group of frequencies. When an officer keys up their trunked radio, the voice signal can be on any voice channel defined by the control channel. The control channel tells all the other radios what talkgroup to listen to)

Unitrunker has plugins that allow remote tuning of the active control channel. By default, every talkgroup has the same priority, so it’s first come first serve. Unitrunker has 2 features, priority, and lockout. Lockout mutes the talkgroup so it is never listened to, and priority gives a talkgroup more priority over others. Useful for example, when you want to hear SWAT traffic over FD traffic.

remote.dll is a plugin that writes the current listening talkgroup to a file. SDRSharp is a piece of software that acts as a virtual radio, you can tune it to what ever frequency you want, and it will communicate with the second SDR to receive radio signals.

SDRSharp has a plugin that listens to remote.dll. This way, unitrunker can tell SDRSharp what channel to listen to, to get voice out. SDRSharp will then output this sound to a virtual audio cable. Virtual audio cables act as pipelines for audio from one program to another. In this case, we are taking the audio from SDRSharp, and putting it into our digital voice program.

P25 is a radio communications protocol that usually carries voice traffic. If you were to listen to P25 straight from the speaker, you would not hear voice, but digital noises like this. These noises can be decoded into regular voice by a program called DSD. All DSD needs is an input and output audio device and you’ll get clean listenable audio.

Other info

Listenable talkgroups along with all data is set through unitrunker, locking out a talkgroup causes LogRecorder to not record the call in the first place.

User and talkgroup prototype feature in unitrunker allows a user to prioritize newly added talkgroups, or lock them out, if only known talkgroups want to be logged.

Features

Responsive design works on tablets, phones as well as desktop browsers
Playlist Creation
  • Users can create playlists to share via email, reddit, G+, or Facebook.
  • The playlist URL contains a gzipped encoded call ID (no DB required)
  • When playlists are called, every file is played back in chronological order
  • Example playlist from a May 12th storm in my city
User permission levels
  • 0: Peon – no browse access
  • 1: Regular user – Configured default user, can browse and create playlist
  • 2: Streamer – Can do all above and listen to live radio stream
  • 3: General Admin – Can delete calls, restart programs, delete/modify users and above
  • 4: Global Admin – All above and reconfigure program options
Access levels for guests
  • No access, browse or search (Admin access only)
  • Guest browse and search (default)
  • Guest browse, search and stream
Admin Control panel features
  • Full event log with file deletion logging, security breach logging, logins and logoffs
  • Restarting system services, DSD+, Unitrunker, SDR#, LogRecorder (planned)
  • File Deletion, and file not found handling for users trying to play back said file
  • File Renaming, updating all files to their latest definition (planned)
  • Configuration interface, skips the need to edit config.php manually
  • User modification, deletion, addition (planned)
User Control panel features
  • Change passwords (planned)
  • Notepad, for writing down useful call notes (planned)
  • Streaming (for privileged users)
Methods to access calls
  • Search (command based browsing planned TGID:1234 RID:1234 etc)
  • Day-by-day browse
Other misc features
  • salted, hashed passwords
  • Call timeline chart (shows number of calls per hour per talkgroup)
  • full context searching, click a radio ID or talkgroup ID to do an “all encompassing search” against it
  • fake scanner (skeuomorphic BCD536HP scanner)
Other Planned features
  • Problem alerting, no recorded calls in X amount of time
  • High traffic alerting, something important happening
  • HTTPS support

Limitations

  • ScanEyes uses files instead of a traditional database. This may cause issues with large amounts of user accounts (this is on the bug list)
  • Limitations provided by Unitrunker, SDR#, and remote.dll only allow LogRecorder to record 1 call at a time. There can’t be simultaneous recording of more than 2 talkgroups at once.
  • Playlist playback page load is slow, 100ms/call
  • EDACS support is untested

System Requirements

System requirements, a.k.a. everything needed to listen to and record trunked radio calls.

This system has been tested on an Intel Core i5 4670K and 2x Intel Xeon X5355. It is untested on AMD processors

  • CPU: 2nd Generation Intel Core i5 Desktop processor
  • Memory: 4GB DDR3
  • Disk: 500MB Disk (SSD recommended)

Licensing

I’ve decided not to open source my work until an experienced PHP developer can review my code from a security standpoint. I’ve taken all possible measures to deter hackers, focusing mainly on input sanitization. That said. If you find anything on sdrscan.com, I’ll pay you via paypal to report these vulnerabilities to me.

Until then, I will allow other users(persons) to run this software provided that they don’t share it, or use my code elsewhere without my permission. Also, I doubt this will ever happen, but if a company would like this software, you can contact me directly.

As it stands right now, this software uses licensing servers with key validation.

Final thoughts

This was my first large scale PHP project. I’ve learned a lot along the way, which has caused some code discrepancies. For example not having a database out of pure laziness to learn MySQL. As I learn new things, I will begin to incorporate or update those features.

4 thoughts on “Introducing ScanEyes”

  1. Very nice work. I spent this weekend brain storming how to do something similar.
    I think I have it working with multiple sdr#’s running trunker plugin with unitrunker, hope to finish it tonight. I will let you know.

    1. I was able to update the remote.dll.

      This version does not create a sdrsharptrunking.log it creates a remote_trunking.log.

      The new log file is created in the same folder as remote.dll. So you copy the remote.dll one level deeper into the receivers folders like R00000005.

      This should allow you to receive multiple voice channels, I’m working on the corresponding change to the sdrsharp trunking plugin.

      https://github.com/dreinhold/UniLogger/releases/tag/v0.0.1

      Hope you can use this,
      Dylan

        1. UniTunker will work with mutiple voice receivers. The limitation was the remote.dll was writing to the same sdrsharptunking.log for every one.
          By default you drop remote.dll into UniTrunker’s data folder (say %UNI_DATA% ) folder, and then it writes to sdrsharptunking.log. UniTrunker supports a sepratate remote.dll for each receiver. Lets say you voice receiver is #2 (you can figure it out by looking in the config.xml) there is a folder name R00000002 in %UNI_DATA% if you drop the remote.dll in there and remove it from the base data dir and restart unitrunler you will see if still logs to sdrsharptrunking.log in %UNI_DATA%.

          Now if you use my version (it’s inside the remote.zip in the guthub release page) and put it into R0000002 you will see it creates the same file but named remote_trunking.log in the R0000002 folder.
          You can then put that remote.dll into any other voice receivers folders.

          Unitrunker will put the next call on the second voice receiver and write to the log.

          You can test this by just creating a new Debug receiver and watch remote_trunking.log.

          Hope that helps,
          Dylan

Leave a Reply to Dylan Reinhold Cancel reply

Your email address will not be published. Required fields are marked *