|
|
|
# sonar
|
|
|
|
|
|
|
|
Sonar is an alarm clock server designed to run on a Raspberry Pi, but it could
|
|
|
|
just as well work anywhere.
|
|
|
|
|
|
|
|
For the alarm clock it plays a list of media files from the filesystem. By
|
|
|
|
default it will use the `mplayer` command.
|
|
|
|
|
|
|
|
# Usage
|
|
|
|
|
|
|
|
```
|
|
|
|
./sonar [-listen 127.0.0.1:8000]
|
|
|
|
```
|
|
|
|
|
|
|
|
Sonar has no authentication system. It listens on localhost by default and you
|
|
|
|
should put a proxy like nginx in front with HTTP Basic Auth or whatever.
|
|
|
|
|
|
|
|
It will create its config on first startup.
|
|
|
|
|
|
|
|
# Features
|
|
|
|
|
|
|
|
It listens on an HTTP service and shows a GUI on the homepage where you can
|
|
|
|
toggle the volume settings, start/stop the alarm clock playlist, and see/change
|
|
|
|
the scheduled alarm times.
|
|
|
|
|
|
|
|
The clock is controlled over simple RESTful API. You just post to these
|
|
|
|
endpoints:
|
|
|
|
|
|
|
|
* `/volume/higher`: increase volume by 5% (default)
|
|
|
|
* `/volume/lower`: lower volume by 5%
|
|
|
|
* `/volume/mute`: toggle mute status
|
|
|
|
* `/playlist/start`: start the playlist (doesn't stop automatically!)
|
|
|
|
* `/playlist/stop`: stop the playlist
|
|
|
|
|
|
|
|
Example to start the playlist via `curl`:
|
|
|
|
|
|
|
|
```bash
|
|
|
|
$ curl -X POST http://localhost:8000/playlist/start
|
|
|
|
```
|
|
|
|
|
|
|
|
# Screenshots
|
|
|
|
|
|
|
|

|
|
|
|
|
|
|
|
# How It Works
|
|
|
|
|
|
|
|
The config file specifies the shell commands to run to launch your media player,
|
|
|
|
volume changing commands, etc.
|
|
|
|
|
|
|
|
When the playlist starts, the Go app shuffles the files in your media folder
|
|
|
|
and feeds them one by one to your media player command (`mplayer` by default).
|
|
|
|
To stop the playlist, it kills the current mplayer task and stops.
|
|
|
|
|
|
|
|
When you save a schedule for the alarm clock, it will create and install a
|
|
|
|
crontab entry for the user running the app. The cron entry hits the API server
|
|
|
|
to start the playlist at the desired time, and then, an hour later, it stops
|
|
|
|
it the same way.
|
|
|
|
|
|
|
|
## Crontab
|
|
|
|
|
|
|
|
The schedule system installs into the user's local crontab. The cron entries
|
|
|
|
just post back to the API service, like:
|
|
|
|
|
|
|
|
```cron
|
|
|
|
30 5 * * * curl -X POST http://127.0.0.1:8000/playlist/start
|
|
|
|
30 6 * * * curl -X POST http://127.0.0.1:8000/playlist/stop
|
|
|
|
```
|
|
|
|
|
|
|
|
The stop command is installed one hour after the start.
|
|
|
|
|
|
|
|
The user's local crontab is **overwritten** by the one Sonar installs. To keep
|
|
|
|
custom crontab entries, place them into the `crontab.in/` directory.
|
|
|
|
|
|
|
|
All custom user crontabs are concatenated together ahead of Sonar's cron entries.
|
|
|
|
The `000-header.cron` is the standard Debian cron header and tends to be installed
|
|
|
|
on top.
|
|
|
|
|
|
|
|
# Installation
|
|
|
|
|
|
|
|
## Supervisor
|
|
|
|
|
|
|
|
There's an example supervisor config in the `etc/` folder.
|
|
|
|
|
|
|
|
Add it to supervisor and put nginx in front with Basic Auth.
|
|
|
|
|
|
|
|
# Makefile
|
|
|
|
|
|
|
|
* `make setup` to fetch dependencies.
|
|
|
|
* `make build` to build the binary to `bin/`
|
|
|
|
* `make dist` to build a distribution for your current setup
|
|
|
|
* `make run` to run it in debug mode
|
|
|
|
* `make watch` to run it in debug mode, auto-reloading (sometimes flaky control over mplayer tho!)
|
|
|
|
* `make pi` to build a zipped distribution for Raspberry Pi.
|
|
|
|
See [Cross Compile for Raspberry Pi](#cross-compile-for-raspberry-pi)
|
|
|
|
|
|
|
|
# Configuration
|
|
|
|
|
|
|
|
The config file will be in your system's native location, which is
|
|
|
|
`~/.config/sonar.json` on Linux environments.
|
|
|
|
|
|
|
|
After running the app once, it will save its default configuration to disk.
|
|
|
|
The defaults are fine for PulseAudio setups but you may want to revise it to
|
|
|
|
be sure.
|
|
|
|
|
|
|
|
A default config file looks like this, annotated:
|
|
|
|
|
|
|
|
```javascript
|
|
|
|
{
|
|
|
|
"cookieName": "session", // name of HTTP session cookie
|
|
|
|
"mediaPath": "./media", // path of media files (like .mp3) to shuffle and play
|
|
|
|
"mediaCommand": [
|
|
|
|
// The command to actually play the media. Use %s where the filename goes.
|
|
|
|
"mplayer",
|
|
|
|
"%s"
|
|
|
|
],
|
|
|
|
"volUpCommand": [
|
|
|
|
"pactl",
|
|
|
|
"set-sink-volume",
|
|
|
|
"0", // Sink number, from `pactl list-sinks`
|
|
|
|
"+5%" // 5% step
|
|
|
|
],
|
|
|
|
"volDnCommand": [
|
|
|
|
"pactl",
|
|
|
|
"set-sink-volume",
|
|
|
|
"0", // Sink number
|
|
|
|
"-5%"
|
|
|
|
],
|
|
|
|
"volMuteCommand": [
|
|
|
|
"pactl",
|
|
|
|
"set-sink-mute",
|
|
|
|
"0",
|
|
|
|
"toggle"
|
|
|
|
],
|
|
|
|
"volStatusCommand": [
|
|
|
|
// How to get the volume status. The command
|
|
|
|
// should output just a value like: 56%
|
|
|
|
"bash",
|
|
|
|
"-c",
|
|
|
|
"pacmd dump-volumes | grep \"Sink 0\" | egrep -o '([0-9]+)%' | head -1"
|
|
|
|
],
|
|
|
|
// scheduled alarm time by default
|
|
|
|
"hour": 6,
|
|
|
|
"minute": 30,
|
|
|
|
"days": [
|
|
|
|
"1", "2", "3", "4", "5"
|
|
|
|
]
|
|
|
|
}
|
|
|
|
```
|
|
|
|
|
|
|
|
## Cross Compile for Raspberry Pi
|
|
|
|
|
|
|
|
Use the `make pi` command to build a distribution for Raspberry Pi.
|
|
|
|
|
|
|
|
If you get permission errors when trying to download the standard library for
|
|
|
|
ARM64, make and chown the folders as a workaround:
|
|
|
|
|
|
|
|
```bash
|
|
|
|
sudo mkdir /usr/lib/golang/pkg/linux_arm
|
|
|
|
sudo chown kirsle:kirsle /usr/lib/golang/pkg/linux_arm
|
|
|
|
make pi
|
|
|
|
rsync -av sonar.pi 192.168.0.102:
|
|
|
|
```
|
|
|
|
|
|
|
|
It outputs a `sonar-pi.zip` that you can scp over and run.
|
|
|
|
|
|
|
|
# License
|
|
|
|
|
|
|
|
Noah Petherbridge © 2018
|
|
|
|
|
|
|
|
GPLv2.
|