noisebell/pi/README.md

180 lines
6.4 KiB
Markdown

# <img src="media/noisebell%20logo.svg" width="100" alt="Noisebell Logo" style="vertical-align: middle; margin-right: 20px;"> Noisebell
A switch monitoring system that detects circuit state changes via GPIO and notifies configured HTTP endpoints via POST requests.
This is build by [Jet Pham][jetpham] to be used at Noisebridge to replace their old discord status bot
## Features
- GPIO circuit monitoring with configurable pin
- HTTP endpoint notifications via POST requests
- Daily rotating log files
- Cross-compilation support for Raspberry Pi deployment
- Software debouncing to prevent noisy switch detection
- Concurrent HTTP notifications for improved performance
- Comprehensive logging and error reporting
- Web-based monitor for testing (no physical hardware required)
- **Unified configuration system** with environment variable support
## Configuration
Noisebell uses environment variables for all configuration settings. Copy `env.example` to `.env` and modify the values as needed.
### Environment Variables
All configuration is handled through environment variables. Here are the available options:
#### GPIO Configuration
- `NOISEBELL_GPIO_PIN` (default: 17) - GPIO pin number for circuit monitoring
- `NOISEBELL_GPIO_DEBOUNCE_DELAY_SECS` (default: 5) - Debounce delay in seconds
#### Web Monitor Configuration
- `NOISEBELL_WEB_MONITOR_PORT` (default: 8080) - Port for web monitor server
- `NOISEBELL_WEB_MONITOR_ENABLED` (default: true) - Enable/disable web monitor
#### Logging Configuration
- `NOISEBELL_LOGGING_LEVEL` (default: info) - Log level (trace, debug, info, warn, error)
- `NOISEBELL_LOGGING_FILE_PATH` (default: logs/noisebell.log) - Log file path
- `NOISEBELL_LOGGING_MAX_BUFFERED_LINES` (default: 10000) - Maximum buffered log lines
#### Monitor Configuration
- `NOISEBELL_MONITOR_TYPE` (default: web) - Monitor type (gpio, web)
#### Endpoint Configuration
- `NOISEBELL_ENDPOINT_URL` (default: https://noisebell.jetpham.com/api/status) - HTTP endpoint URL
- `ENDPOINT_API_KEY` (optional) - API key for Authorization header
- `NOISEBELL_ENDPOINT_TIMEOUT_SECS` (default: 30) - Request timeout in seconds
- `NOISEBELL_ENDPOINT_RETRY_ATTEMPTS` (default: 3) - Number of retry attempts
### GPIO and Physical Tech
We interact directly over a [GPIO pin in a pull-up configuration][gpio-pullup] to read whether a circuit has been closed with a switch. This is an extremely simple circuit that will internally call a callback function when the state of the circuit changes.
When a state change is detected, the system:
1. Logs the circuit state change
2. Sends HTTP POST requests to all configured endpoints
3. Reports success/failure statistics in the logs
## Debouncing
When a switch changes state, it can bounce and create multiple rapid signals. Debouncing adds a delay to wait for the signal to settle, ensuring we only detect one clean state change instead of multiple false ones.
We do debouncing with software via [`set_async_interupt`][rppal-docs] which handles software debounce for us.
### Logging
Logs are stored in a single continuous log file in the `logs` directory
### Endpoint Notifications
When a circuit state change is detected, the system sends HTTP POST requests to the configured endpoint with the following JSON payload:
```json
{
"status": "open"
}
```
The status field will be either `"open"` or `"closed"` (lowercase).
#### Endpoint Configuration
The endpoint is configured using the environment variables listed above. If an API key is provided, it will be included in the `Authorization: Bearer <api_key>` header.
### Web Monitor
A web-based monitor is available for testing without physical hardware. When `NOISEBELL_WEB_MONITOR_ENABLED=true` (default), you can access the monitor at `http://localhost:8080` to manually trigger state changes and test the endpoint notification system.
### Images
<div align="center">
<img src="media/noisebell%20knifeswitch.jpg" width="400" alt="Knife Switch">
<br>
<em>The knife switch used to detect circuit state changes</em>
</div>
<br>
<div align="center">
<img src="media/noisebell%20raspberrypi%20closeup.jpg" width="400" alt="Raspberry Pi Closeup">
<br>
<em>Closeup view of the Raspberry Pi setup</em>
</div>
<br>
<div align="center">
<img src="media/noisebell%20raspberrypi%20with%20porthole.jpg" width="400" alt="Raspberry Pi with Porthole">
<br>
<em>The complete setup showing the Raspberry Pi mounted in a porthole</em>
</div>
## Development
### Requirements
- Rust toolchain (Install [Rust][rust-install])
- Raspberry Pi (tested on [RP02W][rp02w])
- `cross` for cross-compilation (Install [Cross][cross-install])
- Internet connectivity (wifi for the rp02w)
### Local Development (Web Monitor)
For local development and testing, you can run the web-based monitor using the following command:
```bash
# Copy the example environment file
cp env.example .env
# Run the application
cargo run
```
This will start a web server on port 8080. Open your browser and go to [http://localhost:8080](http://localhost:8080) to interact with the web monitor.
This is meant to replace the need for testing on an actual raspberry pi with gpio pins while keeping the terminal clean for logs.
### Deployment
The project includes a deployment script for Raspberry Pi. To deploy, run the deployment script:
```bash
./deploy.sh
```
### Configuration Validation
The application validates all configuration values on startup. If any configuration is invalid, the application will exit with a descriptive error message. Common validation checks include:
- GPIO pin must be between 1-40
- Debounce delay must be greater than 0
- Monitor type must be either "gpio" or "web"
- Port numbers must be valid
- Log levels must be valid (trace, debug, info, warn, error)
### Quick Start
1. **Clone the repository:**
```bash
git clone <repository-url>
cd noisebell
```
2. **Set up environment variables:**
```bash
cp env.example .env
# Edit .env with your configuration
```
3. **Run the application:**
```bash
cargo run
```
[jetpham]: https://jetpham.com/
[gpio-pullup]: https://raspberrypi.stackexchange.com/questions/4569/what-is-a-pull-up-resistor-what-does-it-do-and-why-is-it-needed
[rppal-docs]: https://docs.rs/rppal/latest/rppal/gpio/struct.InputPin.html#method.set_async_interrupt
[rust-install]: https://www.rust-lang.org/tools/install
[rp02w]: https://www.raspberrypi.com/products/raspberry-pi-zero-2-w/
[cross-install]: https://github.com/cross-rs/cross