The Swedish Police has an Open API where the latest public police notifications can be fetched. I have made a self-hosted system that regularly collects that data and stores it in a local database. A self-hosted REST API makes the harvested data searchable and I have an Angular application that displays the events on a map based on area and location words in the summary text. The code base can be downloaded from GitHub:
This blog post describes the design and implementation of this system.
I wanted to create an application where I can aggregate, search for and view public police events in Sweden. The Swedish Police has an Open Api where you can fetch the last 500 published events. The Api policy states that you are not allowed to make too frequent calls to the Api so I have made a service that makes a fetch every 10 minutes and stores the data locally. A benefit with this approach is that it will, over time, build up a history of all published data, and not be limited to the last 500 events.
Around 100 events are published daily. An event contains date/time, the name of the county or municipality where the event occurred, a short text summary, a type (e.g. accident, burglary) and a link to the event on the official web site (polisen.se) where updates and more details of the event can be viewed.
The event also contains a longitude/latitude position, but this is only the midpoint of the county or municipality, so it is not really useful. I want to decorate my map with more information so I make a look-up from public.opendatasoft.com/api for getting GeoJson boundary for the county or municipality and I show this as an overlay polygon on the map.
When the event is from a municipality, the summary text often contains some more useful location information in plain text (like an area name or a street name). I pick out the relevant words and use them for a query to nominatim.openstreetmap.org to search for the location. If a location match is found, this data is displayed as a bounding box for the likely area (this approach is not perfect but it works pretty well for most cases).
The system consists of these parts:
- A .NET Core/C# background service, CollectorService, that fetches the latest events, re-formats them and inserts/updates them into a MongoDB database
- A .NET Core/C# Web API service that provides look-up of the data via REST requests
- An Nginx web server that serves an Angular application to browsers
- An Angular application that runs in the browser. It lets you search and display events and show the information on a map with additional geo-information
I have packed the two services and the web server as Docker images that are instantiated as containers on a Linux machine at home.
The system uses these Open Data Api:s to gather information:
- polisen.se/api/events – Provides the event data
- tile.openstreetmap.org – Provides the tiles for the OpenStreetMap data (through OpenLayers in Angular)
- public.opendatasoft.com/api – Provides GeoJson polygons for boundaries of Swedish counties and municipalities
- nominatim.openstreetmap.org – Provides free text search for locations in OpenStreetMap
The Angular application
The PoliceEvent-application is developed with TypeScript using the Angular framework. PrimeNG is used a UI-library and OpenLayers is used for displaying OpenStreetMap maps with polygon overlays for the county/municipality and detailed area (when available). The application is very similar to the one described in my previous post, Traffic information with OpenLayers and Angular, but instead of using markers for displaying a set of positions I use polygons for displaying counties, municipalities and areas.
As the audience for this kind of data is Swedish, the UI i Swedish only. The main screen provides searching for events within different distances from the your position (your position is fetched from the browser). This distance calculation is based on the midpoint for the county/municipality that is provided with the events, so it is not perfect. You can also fetch events for the whole country and use a free-text filter for limiting the result list.
Each event has a map-button that opens a map that shows the county or municipality where the event occurred. If a more detailed area could be deduced from the summary text (with my super-simple algorithm described below), this area is displayed as an additional overlay.
As described earlier, I use nominatim.openstreetmap.org to search for likely areas based on information found in the summary text of the event. Preferably, I would like to have a lexical analysis of the text to pick out the perfect location words, but I tested a super-simple approach that actually worked quite well: Pick out all words that have a leading Uppercase letter and discard any words that are starting words for sentences. One-letter words and special police word combinations are also discarded. Combine the selected words into a free-text search for nominatim and for most cases you get a decent match. As streets and areas in openstreetmap can be divided into several parts with the same name (for example, a street can be divided into sections) you might get a a result with a bounding box for a section of a road. To overcome this I expand the returned bounding box area if the area is very small.
You can get the code from GitHub and experiment and improve it as you like: https://github.com/LarsBergqvist/police-events
The README-file contains information on how to build and run the system locally. There are Docker files included in the repository so you can use them to run the system with Docker containers.