Metadata-Version: 2.4
Name: lr-tls
Version: 0.5.0
Summary: A package for interfacing with TriLightSense by LumenRadio
Author-email: Jonas Estberger <jonas.estberger@lumenradio.com>
License: MIT
Keywords: TriLightSense,LED,serial,CLI
Classifier: Programming Language :: Python :: 3
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: OS Independent
Requires-Python: >=3.11
Description-Content-Type: text/markdown
Requires-Dist: pyserial>=3.5
Requires-Dist: typing_extensions>=4.0.0
Requires-Dist: typer>=0.12
Requires-Dist: rich>=13.7
Provides-Extra: dev
Requires-Dist: build>=1.2.1; extra == "dev"
Requires-Dist: twine>=5.1.1; extra == "dev"
Requires-Dist: wheel; extra == "dev"
Requires-Dist: pytest>=8; extra == "dev"
Requires-Dist: pytest-cov; extra == "dev"
Requires-Dist: pytest-html; extra == "dev"
Requires-Dist: black>=25; extra == "dev"
Requires-Dist: mypy; extra == "dev"
Requires-Dist: pylint; extra == "dev"
Requires-Dist: junit2html; extra == "dev"
Requires-Dist: types-pyserial; extra == "dev"

# lr-tls - TriLightSense API

A package for interfacing with [TriLightSense](https://gitlab.com/lumenradio/common/tri-light-sense) by LumenRadio.


## Installation


### Using pip

```bash
python3 -m pip install lr-tls
```

### Using a requirements.txt file

In your requirements.txt add
```
lr-tls
```


## Usage

### Calibration

Connect the TLS hardware and invoke the command line tool ```tls calibrate``` to initiate a calibration of the connected TLS board.

Example code:
```bash
$ tls calibrate --device /dev/ttyACM0 --config-file tls.json --channels 0,1,2
```

Both ```tls calibrate``` and ```tls sample``` support ```--format rich``` (default, human-readable) or ```--format json``` for machine-readable output.

### Sampling

Use ```tls sample``` to take a single color sample on a channel without going through the full calibration flow:

```bash
$ tls sample --device /dev/ttyACM0 --channel 0 --duration 0.1
```

Add ```--format json``` for machine-readable output.


### Configuration

Use ```tls config``` to read or change the board's persistent configuration
(settings are stored on the board and survive power cycles).

Read the current configuration:
```bash
$ tls config --device /dev/ttyUSB0
```

Change one or more settings (only the ones you pass are written):
```bash
$ tls config --device /dev/ttyUSB0 --sensitivity 8 --led-state 0
```

| Option | Values |
| --- | --- |
| ```--output-format``` | ```0``` = 8-bit RGB strings, ```1``` = 16-bit integer arrays |
| ```--sensitivity``` | ```0``` (low) .. ```8``` (high) |
| ```--led-state``` | ```0``` = off, ```1``` = on |
| ```--measuring-state``` | ```0``` = off, ```1``` = on |

Reset the board to factory defaults with ```--factory-reset```. Add
```--format json``` for machine-readable output.


### Pattern matching
lr-tls supports looking for blink patterns with different colors. The colors are specified in the configuration file. Use ```tls calibrate```
to generate such a file.


#### Example of measuring normalized color:

You may use ```config_from_string``` to configure the ```TriLightSense``` object with a json string.

example.py
```python
from lr_tls import TriLightSense

tls = TriLightSense()
tls.config_from_string("{\"SAMPLE_RATE\": 150}")

with tls.open("/dev/ttyACM0") as tls:
  color = tls.sample(channel = 0, duration_sec = 0.1)
  print(f"Color on channel 0 was {color}")
```


#### Example of looking for green blink and steady blue indication:

For more complex configuration with colors you can use ```config_from_file``` to configure the ```TriLightSense``` object.

config.json
```json
{
    "SAMPLE_RATE": 150,
    "off-0": "000000",
    "off-1": "000000",
    "green-0": "2D8132",
    "blue-1": "111379"
}
```

example.py
```python
from lr_tls import TriLightSense

tls = TriLightSense()
tls.config_from_file("config.json")

with tls.open("/dev/ttyACM0") as tls:
  green_blink = tls.create_pattern("500 off 500 green 500 off", 0)
  if tls.expect([green_blink, None, None], timeout_sec=10.0):
    print("Got green blink on channel 0!")

  blue_indication = tls.create_pattern("100 blue", 1)
  if tls.expect([None, blue_indication, None], timeout_sec=10.0):
    print("Detected blue light on channel 1!")

```

**_NOTE:_** When looking for a cyclic pattern - Start and end any blink pattern with the same color where the ending is the start of the new cycle.


## Considerations

When using this library there are four parameters to consider.

  - Interval range - In what ranges are the library and hardware guaranteed to detect a given pattern?
  - Detection timeout or ```timeout_sec``` - Given a pattern, how long do I need to look for it to be guaranteed to detect it?
  - Acception interval - How much can the expected and actual pattern differ and be guaranteed to be accepted?
  - Rejection interval - How much can the expected and actual pattern differ and be guaranteed to be rejected?


### Interval range

Pattern recognition is guaranteed for patterns with 50% duty cycle and repeat cycle of ```600ms``` to ```3000ms```. 


### Detection timeout for a specific frequency

If the blink is slow you'll need a longer timeout. Good rule of thumb is three times the pattern length.

I.e ```1500 off red 1500``` has a pattern repeat cycle of 3s and therefore require 9s timeout


### Guaranteeed Acception Interval

The pattern recognition is guaranteed when the expected and actual pattern differ less than ```50ms```.


### Guaranteed Rejection Interval

Pattern rejection is guaranteed when the expected and actual pattern differs more than ```400ms```.
