cctv 1.0.0

Terminal interface for CoolerControl
<div align="center">
  <h1>
  <img alt="cctv_logo" src="https://gitlab.com/coolercontrol/cctv/-/raw/master/assets/cctv.png" width="200">
  <br>
  cctv
  <br>
  </h1>

A terminal client for [CoolerControl](https://gitlab.com/coolercontrol/coolercontrol).

![](assets/demo.webm)
:warning: Requires the CoolerControl service daemon to be running either locally or remotely, [see Configuration](#configuration).

</div>

[[_TOC_]]

## Building

Clone the git repo and build with cargo. Requires a working [Rust installation](https://www.rust-lang.org/tools/install).

```bash
git clone https://gitlab.com/coolercontrol/cctv.git
cd cctv
cargo build --release
cargo run --release
```

## Installing/Upgrading

There are no packages for distributions yet but you can download and install the
latest binary artifact built from master or build from source yourself.

### Latest release

```bash
curl -LOJ --clobber --output-dir "/tmp" \
    https://gitlab.com/api/v4/projects/69657520/packages/generic/master/latest/cctv
sudo install -Dm 755 /tmp/cctv -t /usr/bin
```

### From source

Install with cargo. Requires a working [Rust installation](https://www.rust-lang.org/tools/install).

```bash
cargo install --git https://gitlab.com/coolercontrol/cctv.git
```

### From crates.io

`cctv` is also published to crates.io. Note that the version there may be slightly outdated.

```bash
cargo install cctv
```

Make sure `$HOME/.cargo/bin` is in your path:

```bash
# Bash users
echo 'export PATH="$HOME/.cargo/bin:$PATH"' >> ~/.bashrc
source ~/.bashrc

# zsh users
echo 'export PATH="$HOME/.cargo/bin:$PATH"' >> ~/.zshrc
source ~/.zshrc
```

## Usage

### CLI

```None
Usage: cctv [OPTIONS]
TUI client for CoolerControl

Options:
  --list-modes, -l                              Lists all available modes.
  --activate-mode <mode-name>, -a <mode-name>   Activates the specified mode.
  --daemonize                                   Do not launch the TUI and daemonize cctv.
  --activate-previous-mode, -p                  Activates the previously active mode. 
  --dump                                        Dump information about the system to stdout as json.
  --help, -h                                    Shows this help message.

If no options are passed, the application will launch into the TUI.
```

The `dump` command is meant to be used with [`jq`](https://jqlang.org). To get
the name of the currently active mode: 

```Bash
cctv --dump | jq -r '.state.current_mode_uid as $uid | .modes[] | select(.uid == $uid) | .name'
```

Feel free to reach out to request shortcuts for commonly used operations.

### TUI

#### Keybindings

For the differences between `working` and  `saved` changes or `edit` and `normal` modes,
refer to [editing profiles](#editing-profiles).

| Keys | Page | Mode | Action |
|---|---|---|---|
| Down, e, j | All | Normal | Select next item |
| Up, i, k | All | Normal | Select previous item |
| Right, o, l | All | Normal | Go to the next page |
| Left, n, h | All | Normal | Go to the previous page |
| R | All | Normal | Refresh app data |
| s | All | Normal | Toggle legend visibility |
| q | All | Normal | Quit |
| Ctrl+b | All | Normal | Toggle dock visibility. You can still use relevant keybindings when the dock is hidden. |
| a | Devices | Normal | Toggle between the default and the alternative chart |
| Enter | Modes | Normal | Activate currently highlighted mode |
| D | Profiles | All | Discard working changes |
| E | Profiles | Normal | Enter edit mode |
| A | Profiles | Normal | Apply saved changes to daemon |
| Esc | Profiles | Edit | Exit edit mode |
| Enter | Profiles | Edit | Save working changes |
| Right, o, l | Profiles | Edit | Move cursor right |
| Left, n, h | Profiles | Edit | Move cursor left |
| Backspace | Profiles | Edit | Delete one character |
| digits, space, dot, comma, [, ] | Profiles | Edit | Insert the character |

#### Editing profiles

Profile editing is a work-in-progress. There's experimental support for
manipulating graph and fixed profiles.

:warning: Take a backup of your config before editing - there may be breakages.

There are two input modes: edit and normal. Normal mode is the default.

When you enter edit mode you will see a popup populated with the current
settings.

Edits are in one of three states: working, saved, and applied.

| State | Description |
|---|---|
| Working | Changes made but not saved within `cctv`. Visible only in the text box. |
| Saved | Changes saved in `cctv` but not submitted to CoolerControl. Used for graph drawing, ineffective until applied. |
| Applied | Final changes successfully sent to the daemon. |

:light_bulb: Working changes are preserved (without being saved) when moving between
edit and normal modes.

Changes are validated when moving between stages.

| From | To | Validation |
|---|---|---|
| Working | Saved | All syntactically correct changes are accepted. |
| Saved | Applied | All changes deemed valid by the daemon are accepted. |

There are no guard rails beyond these. You will be notified of any errors. Lack
of a notification indicates success.

:light_bulb: To discard saved changes: press 'R' to sync `cctv` with the daemon.

:warning: Changes made in `cctv` require a page refresh to be reflected in the GUI.
The reverse is also true.

### Alerts

`cctv` will listen for server side events both when daemonized and in interactive mode.
It will send desktop notifications when it receives an alert.

## Configuration

Configuration is optional. `cctv` reads its from _one of_ these locations, in
order of precedence:
- `CCTV_CONFIG_FILEPATH` environment variable
- `$XDG_CONFIG_HOME/coolercontrol/cctv.json`
- `$HOME/.config/coolercontrol/cctv.json`

If a file is not found, `cctv` will use default values and create one for you.

If `daemon_address` or `port` are undefined, `cctv` will pull them from the
local `coolercontrold` config file located at `/etc/coolercontrol/config.toml`.

These are useful for connecting to remote daemons. Combined with
`CCTV_CONFIG_FILEPATH`, you can have multiple `cctv` instances on one machine
connecting to different `coolercontrold` instances.

Finally, for security, the password is read from the `CCTV_DAEMON_PASSWORD`
environment variable.

### Configuration Options

| Option | Description | Default |
|---|---|---|
| `daemon_address` | Address CoolerControl is listening on. | Value in the `coolercontrold` configuration file or internal default. |
| `port` | Port CoolerControl is listening on. | Value in the `coolercontrold` configuration file or internal default. |
| `time_range_s` | History in seconds for timeseries charts. | 60 |
| `username` | CoolerControl username. | *Internal default* |
| `skip_splash` | Skips the splash screen. | false |

### Environment variables

| Environment Variable | Description | Default |
|---|---|---|
| `CCTV_CONFIG_FILEPATH` | Absolute path to the CCTV configuration file. | See [above]#configuration. |
| `CCTV_DAEMON_PASSWORD` | CoolerControl password. | *Internal default* |

Note that there's currently no SSL or IPv6 support.