Fix excessive use of italics in README.md

This commit is contained in:
Alex Jordan
2016-08-17 12:41:14 -04:00
parent 57da88d9ca
commit 4cf32905c3

View File

@@ -8,7 +8,7 @@ The _OwnTracks Recorder_ is a lightweight program for storing and accessing loca
![Architecture of the Recorder](assets/ot-recorder.png)
There are two main components: the _Recorder_ obtains data via MQTT subscribes or HTTP POST, stores the data in plain files and serve it via its built-in REST API, and the _ocat_ command-line utility reads stored data in a variety of formats.
There are two main components: the _Recorder_ obtains data via MQTT subscribes or HTTP POST, stores the data in plain files and serve it via its built-in REST API, and the `ocat` command-line utility reads stored data in a variety of formats.
We developed the Recorder as a one-stop solution to storing location data published by our OwnTracks apps (iOS and Android) and retrieving this data. Our previous offerings (`m2s`, `o2s`/`Pista`) also work of course, but we believe the Recorder is best suited to most environments.
@@ -69,7 +69,7 @@ We developed the Recorder as a one-stop solution to storing location data publis
The Recorder serves two purposes:
1. It subscribes to an MQTT broker and reads messages published from the OwnTracks apps, storing these in a particular fashion into what we call the _store_ which is basically a bunch of plain files on the file system. Alternatively the Recorder can listen on HTTP for OwnTracks-type JSON messages POSTed to its HTTP server.
2. It provides a Web server which serves static pages, a REST API you use to request data from the _store_, and a WebSocket server. The distribution comes with a few examples of how to access the data through its HTTP interface (REST API). In particular a _table_ of last locations has been made available as well as a _live map_ which updates via the Recorder's WebSocket interface when location publishes are received. In addition we provide maps with last points or tracks using the GeoJSON produced by the Recorder.
2. It provides a Web server which serves static pages, a REST API you use to request data from the store, and a WebSocket server. The distribution comes with a few examples of how to access the data through its HTTP interface (REST API). In particular a table of last locations has been made available as well as a live map which updates via the Recorder's WebSocket interface when location publishes are received. In addition we provide maps with last points or tracks using the GeoJSON produced by the Recorder.
## Installing
@@ -167,10 +167,10 @@ sudo apt-get install libmosquitto-dev libcurl3 libcurl4-openssl-dev libconfig-de
#### Building
1. Obtain and download the software, via [our Homebrew Tap](https://github.com/owntracks/homebrew-recorder) on Mac OS X, directly as a clone of the repository, or as a [tar ball](https://github.com/owntracks/recorder/releases) which you unpack.
2. Copy the included `config.mk.in` file to `config.mk` and edit that. You specify the features or tweaks you need. (The file is commented.) Pay particular attention to the installation directory and the value of the _store_ (`STORAGEDEFAULT`): that is where the Recorder will store its files. `DOCROOT` is the root of the directory from which the Recorder's HTTP server will serve files.
2. Copy the included `config.mk.in` file to `config.mk` and edit that. You specify the features or tweaks you need. (The file is commented.) Pay particular attention to the installation directory and the value of the store (`STORAGEDEFAULT`): that is where the Recorder will store its files. `DOCROOT` is the root of the directory from which the Recorder's HTTP server will serve files.
3. Type `make` and watch the fun.
When _make_ finishes, you should have at least two executable programs called `ot-recorder` which is the Recorder proper, and `ocat`. If you want you can install these using `make install`, but this is not necessary: the programs will run from whichever directory you like if you add `--doc-root ./docroot` to the Recorder options.
When `make` finishes, you should have at least two executable programs called `ot-recorder` which is the Recorder proper, and `ocat`. If you want you can install these using `make install`, but this is not necessary: the programs will run from whichever directory you like if you add `--doc-root ./docroot` to the Recorder options.
Ensure the LMDB databases are initialized by running the following command which is safe to do, also after an upgrade. (This initialization is non-destructive -- it will not delete any data.)
@@ -180,7 +180,7 @@ ot-recorder --initialize
## Getting started
The Recorder has, like _ocat_, a daunting number of options, most of which you will not require. Running either utility with the `-h` or `--help` switch will summarize their meanings. You can, for example launch with a specific storage directory, disable the HTTP server, change its port, etc.
The Recorder has, like `ocat`, a daunting number of options, most of which you will not require. Running either utility with the `-h` or `--help` switch will summarize their meanings. You can, for example launch with a specific storage directory, disable the HTTP server, change its port, etc.
If you require authentication or TLS to connect to your MQTT broker, pay attention to the `$OTR_` environment variables listed in the help.
@@ -194,7 +194,7 @@ $ ./ot-recorder 'owntracks/#'
Publish a location from your OwnTracks app and you should see the Recorder receive that on the console. If you haven't disabled Geo-lookups, you'll also see the address from which the publish originated.
The location message received by the Recorder will be written to storage. In particular you should verify that your _storage_ directory contains:
The location message received by the Recorder will be written to storage. In particular you should verify that your storage directory contains:
1. a directory called `ghash/`
2. a directory called `rec/` with several subdirectories and a `.rec` file therein.
@@ -229,11 +229,11 @@ This section lists the most important options of the Recorder with their long na
`--norec` disables writing of REC files, so no location history or other similar publishes are stored, and the Lua `otr_putrec()` function is not invoked even if it exists. What is stored are CARDS and PHOTOS, as well as the LAST location of a device. As such, the API's `/locations` endpoint becomes useless.
`--norevgeo` suppresses reverse geo lookups, but this means that historic data will not show addresses (e.g. with the API or with _ocat_). See below for information on Reverse Geo lookups.
`--norevgeo` suppresses reverse geo lookups, but this means that historic data will not show addresses (e.g. with the API or with `ocat`). See below for information on Reverse Geo lookups.
`--logfacility` is the syslog facility to use (default is `LOCAL0`).
`--quiet` disables printing of messages to _stdout_.
`--quiet` disables printing of messages to stdout.
`--initialize` creates the a structure within the storage directory and initializes the LMDB database. It is safe to use this even if such a database exists -- the database is not wiped. After initialization, Recorder exits.
@@ -253,7 +253,7 @@ This section lists the most important options of the Recorder with their long na
## Configuration file
The Recorder attempts to read its startup configuration from a configuration file; the path to this is compiled into the Recorder (typically `/etc/defaults/ot-recorder`, and `ocat -v` will display the compiled-in default). The format of this file approximates that of a shell script with variables to be exported (the intention is so that it can be sourced by a shell script). Lines beginning with an octothorp (`#`) are ignored as are blank lines. Configuration settings proper are set as follows (note that some older versions of _libconfig_ require a trailing semicolon (`;`) at the end of a variable assignment):
The Recorder attempts to read its startup configuration from a configuration file; the path to this is compiled into the Recorder (typically `/etc/defaults/ot-recorder`, and `ocat -v` will display the compiled-in default). The format of this file approximates that of a shell script with variables to be exported (the intention is so that it can be sourced by a shell script). Lines beginning with an octothorp (`#`) are ignored as are blank lines. Configuration settings proper are set as follows (note that some older versions of libconfig require a trailing semicolon (`;`) at the end of a variable assignment):
```
OTR_STORAGEDIR="/var/spool/owntracks/recorder/store"
@@ -284,7 +284,7 @@ Note that options passed to `ot-recorder` override both configuration file setti
## Reverse proxy
Running the Recorder protected by an _nginx_ or _Apache_ server is possible and is the only recommended method if you want to server data behind _localhost_. The snippets below show how to do it, but you would also add authentication to them - or at least, to everything but the views. The snippet for HTTP mode shows an example of how to do this.
Running the Recorder protected by an Nginx or Apache server is possible and is the only recommended method if you want to serve data behind localhost. The snippets below show how to do it, but you would also add authentication to them - or at least, to everything but the views. The snippet for HTTP mode shows an example of how to do this.
### nginx
@@ -375,7 +375,7 @@ ProxyPassReverse /owntracks http://127.0.0.1:8083/
The Recorder has a built-in HTTP server with which it servers static files from either the compiled-in default `DOCROOT` directory or that specified at run-time with the `--doc-root` option. Furthermore, it serves JSON data from the API end-point at `/api/0/` and it has a built-in WebSocket server for the live map.
The API basically serves the same data as _ocat_ is able to produce - see [API.md](https://github.com/owntracks/recorder/blob/master/API.md). The server also accepts OwnTracks app data via HTTP POST to the `/pub` endpoint.
The API basically serves the same data as `ocat` is able to produce - see [API.md](https://github.com/owntracks/recorder/blob/master/API.md). The server also accepts OwnTracks app data via HTTP POST to the `/pub` endpoint.
### Example functionality
@@ -453,7 +453,7 @@ The Recorder's built-in WebSocket server updates a map as it receives publishes
## `ocat`
_ocat_ is a CLI query program for data stored by Recorder: it prints data from storage in a variety of output formats:
`ocat` is a CLI query program for data stored by Recorder: it prints data from storage in a variety of output formats:
* JSON
* GeoJSON (points)
@@ -464,12 +464,12 @@ _ocat_ is a CLI query program for data stored by Recorder: it prints data from s
* raw (the lines contained in the REC file with ISO timestamp)
* payload (basically just the payload part from RAW)
The _ocat_ utility accesses _storage_ directly — it doesnt use the Recorders REST interface. _ocat_ has a daunting number of options, some combinations of which make no sense at all.
The `ocat` utility accesses the store directly — it doesnt use the Recorders REST interface. `ocat` has a daunting number of options, some combinations of which make no sense at all.
Some example uses we consider useful:
* `ocat --list`
show which uers are in _storage_.
show which uers are in the store.
* `ocat --list --user jjolie`
show devices for the specified user
* `ocat --user jjolie --device ipad`
@@ -510,9 +510,9 @@ Some example uses we consider useful:
* `ocat ... --limit 10`
prints data for the current month, starting now and going backwards; only 10 locations will be printed. Generally, the `--limit` option reads the storage back to front which makes no sense in some combinations.
Specifying `--fields lat,tid,lon` will request just those JSON elements from _storage_. (Note that doing so with output GPX or GEOJSON could render those formats useless if, say, `lat` is missing in the list of fields.)
Specifying `--fields lat,tid,lon` will request just those JSON elements from the store. (Note that doing so with output GPX or GEOJSON could render those formats useless if, say, `lat` is missing in the list of fields.)
The `--from` and `--to` options allow you to specify a UTC date and/or timestamp from which respectively until which data will be read. By default, the last 6 hours of data are produced. If `--from` is not specified, it therefore defaults to _now minus 6 hours_. If `--to` is not specified it defaults to _now_. Dates and times must be specified as strings, and the following formats are recognized:
The `--from` and `--to` options allow you to specify a UTC date and/or timestamp from which respectively until which data will be read. By default, the last 6 hours of data are produced. If `--from` is not specified, it therefore defaults to "now minus 6 hours". If `--to` is not specified it defaults to "now". Dates and times must be specified as strings, and the following formats are recognized:
```
%Y-%m-%dT%H:%M:%S
@@ -526,7 +526,7 @@ The `--limit` option limits the output to the last specified number of records.
### Environment
The following environment variables control _ocat_'s behaviour:
The following environment variables control `ocat`'s behaviour:
* `OCAT_FORMAT` can be set to the preferred output format. If unset, JSON is used. The `--format` option overrides this setting.
* `OCAT_USERNAME` can be set to the preferred username. The `--user` option overrides this environment variable.
@@ -538,7 +538,7 @@ The Recorder has been running for a while, and the OwnTracks apps have published
#### List users and devices
We obtain a list of users from the _store_:
We obtain a list of users from the store:
```
$ ocat --list
@@ -549,7 +549,7 @@ $ ocat --list
}
```
From which devices has user _demo_ published data?
From which devices has user `demo` published data?
```
$ ocat --list --user demo
@@ -562,7 +562,7 @@ $ ocat --list --user demo
#### Show the last position reported by a user
Where was _demo_'s _iphone_ last seen? (Omit `--user` and `--device` to get LAST for all users and devices.)
Where was `demo`'s iPhone last seen? (Omit `--user` and `--device` to get LAST for all users and devices.)
```
$ ocat --last --user demo --device iphone
@@ -594,7 +594,7 @@ $ ocat --last --user demo --device iphone
Several things worth mentioning:
* The returned data structure is an array of JSON objects; had we omitted specifying a particular device or even a particular user we would have obtained the last position of all this user's devices or all users' devices respectively.
* If you are familiar with the [JSON data reported by the OwnTracks apps](http://owntracks.org/booklet/tech/json/) you'll notice that this JSON contains more information: this is provided on the fly by _ocat_ and the REST API, e.g. from the reverse-geo cache the Recorder maintains.
* If you are familiar with the [JSON data reported by the OwnTracks apps](http://owntracks.org/booklet/tech/json/) you'll notice that this JSON contains more information: this is provided on the fly by `ocat` and the REST API, e.g. from the reverse-geo cache the Recorder maintains.
#### What were the last 4 positions reported?
@@ -619,20 +619,20 @@ We took a number of decisions when designing the Recorder and its utilities:
* File names are lower case. A user called `JaNe` with a device named `myPHONe` will be found in a file named `jane/myphone`.
* All times are UTC (a.k.a. Zulu or GMT). We got sick and tired of converting stuff back and forth. It is up to the consumer of the data to convert to localtime if need be.
* The Recorder does not provide authentication or authorization. Nothing at all. Zilch. Nada. Think about this before making it available on a publicly-accessible IP address. Or rather: don't think about it; just don't do it. You can of course place a HTTP proxy in front of the Recorder to control access to it. Or use views (see below).
* `ocat`, the _cat_ program for the Recorder uses the same back-end which is used by the API though it accesses it directly (i.e. without resorting to HTTP).
* `ocat`, the `cat` program for the Recorder, uses the same back-end which is used by the API though it accesses it directly (i.e. without resorting to HTTP).
* The Recorder supports 3-level MQTT topics only, in the typical OwnTracks format: `"owntracks/<username>/<devicename>"`, optionally with a leading slash. (The first part of the topic need not be "owntracks".) Publishes via HTTP POST construct a ficticious topic internally using the provided user (`u`) and device (`d`) parameters.
## Storage
As mentioned earlier, data is stored in files, and these files are relative to `STORAGEDIR` (compiled into the programs or specified as an option). In particular, the following directory structure can exist, whereby directories are created as needed by the Recorder:
* `cards/`, optional, may contains user cards. This card is then stored here and used with, e.g., `ocat --last` to show a user's name and optional avatar. User cards are typically stored in a subdirectory called _username_, and therein a JSON file _username_.json. When reading cards, the Recorder will first attempt to open _username_/_device_/_username_.json and then _username_/_username_.json.
* `cards/`, optional, may contains user cards. This card is then stored here and used with, e.g., `ocat --last` to show a user's name and optional avatar. User cards are typically stored in a subdirectory called `username`, and therein a JSON file `[username].json`. When reading cards, the Recorder will first attempt to open `[username]/[device]/[username].json` and then `[username]/[username].json`.
* `config/`, optional, contains the JSON of a [device configuration](http://owntracks.org/booklet/features/remoteconfig/) (`.otrc`) which was requested remotely via a [dump command](http://owntracks.org/booklet/tech/json/#_typecmd). Note that this will contain sensitive data. You can use this `.otrc` file to restore the OwnTracks configuration on your device by copying to the device and opening it in OwnTracks.
* `ghash/`, unless disabled, reverse Geo data (using a Google service) is collected into an LMDB database located in this directory. This LMDB database also contains named databases which are used by your optional Lua hooks, as well as a `topic2tid` database which can be used for TID re-mapping.
* `last/` contains the last location published by devices. E.g. Jane's last publish from her iPhone would be in `last/jjolie/iphone/jjolie-iphone.json`. The JSON payload contained therein is enhanced with the fields `user`, `device`, `topic`, and `ghash`. If a device's `last/` directory contains a file called `extra.json` (i.e. matching the example, this would be `last/jjolie/iphone/extra.json`), the content of this file is merged into the existing JSON for this user and returned by the API. Note, that you cannot overwrite existing values. So, an `extra.json` containing `{ "tst" : 11 }` will do nothing because the `tst` element we obtain from location data overrules, but adding `{ "beverage" : "water" }` will do what you want. If Recorder is built with support for our Greenwich firmware, this directory might contain `batt.json`, `ext.json`, and/or `status.json` each of which hold an array of the last 100 reports for internal battery voltage, external voltage, and status respectively. These values are returned via the API in the LAST object. A file `http.json` which should contain either a single JSON object or an array of JSON objects is returned to clients in HTTPmode.
* `monitor` a file which contains a timestamp and the last received topic (see Monitoring below).
* `msg/` contains messages received by the Messaging system.
* `photos/` optional; contains the binary photos from a _card_.
* `photos/` optional; contains the binary photos from a card.
* `rec/` the Recorder data proper. One subdirectory per user, one subdirectory therein per device. Data files are named `YYYY-MM.rec` (e.g. `2015-08.rec` for the data accumulated during the month of August 2015.
* `waypoints/` contains a directory per user and device. Therein are individual files named by a timestamp with the JSON payload of published (i.e. shared) waypoints. The file names are timestamps because the `tst` of a waypoint is its key. If a user publishes all waypoints from a device (Publish Waypoints), the payload is stored in this directory as `username-device.otrw`. (Note, that this is the JSON [waypoints import format](http://owntracks.org/booklet/tech/json/#_typewaypoints).) You can use this `.otrw` file to restore the waypoints on your device by copying to the device and opening it in OwnTracks.
@@ -651,11 +651,11 @@ u0m97hc 46.652733 7.868803
This can be used to subsequently obtain missed lookups.
We recommend you keep reverse-geo lookups enabled, this data (country code `cc`, and the locations address `addr`) is used by the example Web apps provided by the Recorder to show where a particular device is. In addition, this cached data is used the the API (also _ocat_) when printing location data.
We recommend you keep reverse-geo lookups enabled, this data (country code `cc`, and the locations address `addr`) is used by the example Web apps provided by the Recorder to show where a particular device is. In addition, this cached data is used the the API (also `ocat`) when printing location data.
### Precision
The precision with which reverse-geo lookups are performed is controlled with the `--precison` option to Recorder (and with the `--precision` option to _ocat_ when you query for data). The default precision is compiled into the code (from `config.mk`). The higher the number, the more frequently lookups are performed; conversely, the lower the number, the fewer lookups are performed. For example, a precision of 1 means that points within an area of approximately 5000 km^2 would resolve to a single address, whereas a precision of 7 means that points within an area of approximately 150 m^2 resolve to one address. The Recorder obtains a location publish, extracts the latitude and longitude, and then calculates the [geohash](https://en.wikipedia.org/wiki/Geohash) string and truncates it to _precision_. If the calculated geohash string can be found in our local LMDB cache, we consider the point cached; otherwise an actual reverse geo lookup (via HTTP) is performed and the result is cached in LMDB at the key of the geohash.
The precision with which reverse-geo lookups are performed is controlled with the `--precison` option to Recorder (and with the `--precision` option to `ocat` when you query for data). The default precision is compiled into the code (from `config.mk`). The higher the number, the more frequently lookups are performed; conversely, the lower the number, the fewer lookups are performed. For example, a precision of 1 means that points within an area of approximately 5000 km^2 would resolve to a single address, whereas a precision of 7 means that points within an area of approximately 150 m^2 resolve to one address. The Recorder obtains a location publish, extracts the latitude and longitude, and then calculates the [geohash](https://en.wikipedia.org/wiki/Geohash) string and truncates it to `precision`. If the calculated geohash string can be found in our local LMDB cache, we consider the point cached; otherwise an actual reverse geo lookup (via HTTP) is performed and the result is cached in LMDB at the key of the geohash.
As an example, let's assume Jane's device is at position (lat, lon) `48.879840, 2.323522`, which resolves to a geohash string of length 7 `u09whf7`. We can [visualize this](http://www.movable-type.co.uk/scripts/geohash.html) and show what this looks like. (See also: [visualizing geohash](http://www.bigdatamodeling.org/2013/01/intuitive-geohash.html).)
@@ -698,7 +698,7 @@ In order to monitor the Recorder, whenever an MQTT message is received, a `monit
If Recorder is built with `WITH_PING` (default), a location publish to `owntracks/ping/ping` (i.e. username is `ping` and device is `ping`) can be used to round-trip-test the Recorder. For this particular username/device combination, Recorder will store LAST position, but it will not keep a `.REC` file for it. This can be used to verify, say, via your favorite monitoring system, that the Recorder is still operational.
After sending a _pingping_, you can query the REST interface to determine the difference in time. The `contrib/` directory has an example Python program (`ot-ping.py`) which you can adapt as needed for use by Icinga or Nagios.
After sending a pingping, you can query the REST interface to determine the difference in time. The `contrib/` directory has an example Python program (`ot-ping.py`) which you can adapt as needed for use by Icinga or Nagios.
```
OK ot-recorder pingping at http://127.0.0.1:8085: 0 seconds difference
@@ -708,7 +708,7 @@ OK ot-recorder pingping at http://127.0.0.1:8085: 0 seconds difference
A view is a sort of sandboxed look at data provided by the Recorder. Assume you host several devices, be they your own or those of some of your friends, and assume you want to allow somebody else to see where you are or have been during a specific time frame: with the Recorder's default Web server you cannot limit a visitor to see specific data only; once they reach the Recorder's Web interface, they have access to all your data. (We warned you about that earlier.) Using a HTTP proxy, you can provide an insight into certain portions of your data only.
You configure a view by creating a small JSON file of an arbitrary name which defines which user / device combination of data the view should display. Say you are recording data for `owntracks/jjolie/phone`, the _user_ would be `jjolie` and the _device_ is `phone`. You can also create a specific HTML page for this view or just use the default `vmap.html` we provide.
You configure a view by creating a small JSON file of an arbitrary name which defines which user / device combination of data the view should display. Say you are recording data for `owntracks/jjolie/phone`, the user would be `jjolie` and the device is `phone`. You can also create a specific HTML page for this view or just use the default `vmap.html` we provide.
The view then provides three URLs:
@@ -728,7 +728,7 @@ Suppose Jane wishes to have her acqaintances see where she is whilst on vacation
}
```
Jane's friends can now visit the URL `/view/loire` (note the missing `.json` extension) to be served a map showing Jane's progress along the Loire valley (if that is where she's actually travelling through). Jane can keep that view up even after she returns because the view will not serve data after the 15th of July, in other words, her location at any other time before or after the _from_ / _to_ dates is hidden.
Jane's friends can now visit the URL `/view/loire` (note the missing `.json` extension) to be served a map showing Jane's progress along the Loire valley (if that is where she's actually travelling through). Jane can keep that view up even after she returns because the view will not serve data after the 15th of July, in other words, her location at any other time before or after the from/to dates is hidden.
![Jane's vacation](assets/view-map.png)
@@ -753,12 +753,12 @@ The JSON in the view file (called `view.json` here) contains mandatory and optio
The _page_ is a single HTML file which must be located in the `views/` directory of the Recorder's document root. Trivial (primitive actually) text substitution is done for the following two tokens:
The `page` is a single HTML file which must be located in the `views/` directory of the Recorder's document root. Trivial (primitive actually) text substitution is done for the following two tokens:
* `@@@LASTPOS@@@` is converted to a URI on which the Recorder will serve the last position data
* `@@@GEO@@@` is converted to a URI on which the Recorder will serve GeoJSON data from its storage.
The default _page_ we provide is called `vmap.html`; by default it refreshes the last position every 60 seconds, and clicking on _Load track_ loads the GeoJSON track for the time frame specified by `from` and `to`.
The default `page` we provide is called `vmap.html`; by default it refreshes the last position every 60 seconds, and clicking on "Load track" loads the GeoJSON track for the time frame specified by `from` and `to`.
![Jane's vacation track](assets/view-track.png)
@@ -780,7 +780,7 @@ A little bit more complex view would look like this:
}
```
All JSON elements are copied into the _lastpos_ data which is returned to the caller. Using the above view configuration, a user requesting `http://localhost:8083/view/loire?lastpos=1` would obtain
All JSON elements are copied into the `lastpos` data which is returned to the caller. Using the above view configuration, a user requesting `http://localhost:8083/view/loire?lastpos=1` would obtain
```json
{
@@ -816,7 +816,7 @@ All JSON elements are copied into the _lastpos_ data which is returned to the ca
}
```
Note how `pathname` and `port` have been copied into the object. These values can be used by the _page_ served in the view.
Note how `pathname` and `port` have been copied into the object. These values can be used by the `page` served in the view.
### Authentication
@@ -828,7 +828,7 @@ If `view.json` contains an element called `auth`, it is assumed to be an array o
Each user/password digest combination will be able to access the view.
You create these strings with, say, the _htdigest_ program or `contrib/new-view-auth.py`:
You create these strings with, say, the `htdigest` program or `contrib/new-view-auth.py`:
```bash
htdigest -c /tmp/dd owntracks-recorder jjolie
@@ -897,7 +897,7 @@ Note, that Jane's user/device tuple should also be returned in order to display
### Browser API keys
In order to use the Recorder's maps and views, you have to obtain a [Google API "Browser key"](https://developers.google.com/maps/documentation/javascript/get-api-key). You then add this key to your _docroot_ directory so that the Recorder can find it. (You should already have a file called `apikey.js.sample` in that directory; copy or rename the file to `apikey.js` and ensure its content is valid JavaScript:
In order to use the Recorder's maps and views, you have to obtain a [Google API "Browser key"](https://developers.google.com/maps/documentation/javascript/get-api-key). You then add this key to your docroot directory so that the Recorder can find it. (You should already have a file called `apikey.js.sample` in that directory; copy or rename the file to `apikey.js` and ensure its content is valid JavaScript:
```bash
$ cat .../static/apikey.js
@@ -907,7 +907,7 @@ var apiKey = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
### The LMDB database
`ocat --load` and `ocat --dump` can be use to load and dump the lmdb database respectively. There is some support for loading/dumping named databases using `--load=xx` or `--dump=xx` to specify the name. Use the mdb utilities to actually perform backups of these. _load_ expects key/value strings in pairs, separated by exactly one space. If the value is the string `DELETE`, the key is deleted from the database, which allows us to, say, remove a whole bunch of geohash prefixes in one go (but be careful doing this):
`ocat --load` and `ocat --dump` can be use to load and dump the lmdb database respectively. There is some support for loading/dumping named databases using `--load=xx` or `--dump=xx` to specify the name. Use the mdb utilities to actually perform backups of these. `--load` expects key/value strings in pairs, separated by exactly one space. If the value is the string `DELETE`, the key is deleted from the database, which allows us to, say, remove a whole bunch of geohash prefixes in one go (but be careful doing this):
```bash
ocat --dump |