## Local HTTP/HTTPS Setup with Custom CA

This project provides a dual-port Streamlit server setup for local networks:

- **HTTP** available on port **8502**
- **HTTPS** (trusted with custom CA) available on port **8503**

### How it works
- A custom Certificate Authority (CA) is generated for your organization.
- Each device/server is issued a certificate signed by this CA.
- Customers can import the CA certificate into their OS/browser trust store, so the device's HTTPS connection is fully trusted (no browser warnings).

### Usage

1. **Generate Certificates**
    - Run `generate_ca_cert.sh` in `src/auracast/server/`.
    - This creates:
        - `certs/ca/ca_cert.pem` / `ca_key.pem` (CA cert/key)
    - **Distribute `ca_cert.pem` or `ca_cert.crt` to customers** for installation in their trust store.
    - This is a one-time operation for your organization.

2. **Start the Server**
    - Run `run_http_and_https.sh` in `src/auracast/server/`.
    - This starts:
        - HTTP Streamlit on port 8500
        - HTTPS Streamlit on port 8501 (using the signed device cert)

3. **Client Trust Setup**
    - Customers should install `ca_cert.pem` in their operating system or browser trust store to trust the HTTPS connection.
    - After this, browsers will show a secure HTTPS connection to the device (no warnings).

### Why this setup?
- **WebRTC and other browser features require HTTPS for local devices.**
- Using a local CA allows trusted HTTPS without needing a public certificate or exposing devices to the internet.
- HTTP is also available for compatibility/testing.

### Advertise Hostname with mDNS
```bash
cd src/auracast/server
sudo ./provision_domain_hostname.sh <new_hostname> <new_domain>
```
- Example:
  ```bash
  sudo ./provision_domain_hostname.sh box1 auracast.local
  ```
- The script will:
  - Validate your input (no dots in hostname)
  - Set the system hostname
  - Update `/etc/hosts`
  - Set the Avahi domain in `/etc/avahi/avahi-daemon.conf`
  - Restart Avahi
  - Generate a unique per-device certificate and key signed by your CA, stored in `certs/per_device/<hostname>.<domain>/`.
  - The certificate will have a SAN matching the device's mDNS name (e.g., `box1-summitwave.local`).
---

### Troubleshooting & Tips
- **Use .local domain** (e.g., `box1-summitwave.local`) - most clients will not resolve multi-label domains.
- **Hostnames must not contain dots** (`.`). Only use single-label names for the system hostname.
- **Avahi domain** can be multi-label (e.g., `auracast.local`).
- **Clients may need** `libnss-mdns` installed and `/etc/nsswitch.conf` configured with `mdns4_minimal` and `mdns4` for multi-label mDNS names.
- If you have issues with mDNS name resolution, check for conflicting mDNS stacks (e.g., systemd-resolved, Bonjour, or other daemons).
- Some Linux clients may not resolve multi-label mDNS names via NSS—test with `avahi-resolve-host-name` and try from another device if needed.

# record audio and save to file for debugging
pw-record --target="AVIOUSB-8f6326 : 2:receive_Left" --rate=48000 --channels=1 --format=s24 /tmp/aes67_test.wav &
RECORD_PID=$!
sleep 30
kill $RECORD_PID

# uart reset over hci does not work:
stty -F /dev/ttyAMA3 -hupcl
stty -F /dev/ttyAMA3 -a | grep -o 'hupcl' || echo "-hupcl is set"


# Audio latency
if there is hearable audio error with aes67, tune sess.latency.msec in pipewire-aes67.conf

if latency is piling up something may be blocking the event loop in multicast_server.py - the event loop must never block at any time

---

After completing these steps, your device will be discoverable as `<hostname>.<domain>` (e.g., `box1.auracast.local`) on the local network via mDNS.

---

## Checking Advertised mDNS Services
Once your device is configured, you can verify that its mDNS advertisement is visible on the network:

- **List all mDNS services:**
  ```bash
  avahi-browse -a
  ```
  Look for your hostname and service (e.g., `box1.auracast.local`).
- **Check specific hostname resolution:**
  ```bash
  avahi-resolve-host-name box1.auracast.local
  avahi-resolve-host-name -4 box1.auracast.local  # IPv4 only
  avahi-resolve-host-name -6 box1.auracast.local  # IPv6 only
  ```

## Run the application with local webui
- for microphone streaming via the browser, https is required
- poetry run multicast_server.py
- sudo -E PATH="$PATH" bash ./start_frontend_https.sh
- bash start_mdns.sh


## Managing Auracast systemd Services

You can run the backend and frontend as systemd services for easier management and automatic startup on boot.

### 1. Install the service files
Copy the provided service files to your systemd directory (requires sudo):

```bash
sudo cp auracast-server.service /etc/systemd/system/
sudo cp auracast-frontend.service /etc/systemd/system/
```

### 2. Reload systemd
```bash
sudo systemctl daemon-reload
```

### 3. Enable services to start at boot
```bash
sudo systemctl enable auracast-server
sudo systemctl enable auracast-frontend
```

### 4. Start the services
```bash
sudo systemctl start auracast-server
sudo systemctl start auracast-frontend
```

### 5. Stop the services
```bash
sudo systemctl stop auracast-server
sudo systemctl stop auracast-frontend
```

### 6. Disable services to start at boot
```bash
sudo systemctl disable auracast-server
sudo systemctl disable auracast-frontend
```

### 7. Check service status
```bash
sudo systemctl status auracast-server
sudo systemctl status auracast-frontend
```

If you want to run the services as a specific user, edit the `User=` line in the service files accordingly.

# Setup the audio system
sudo apt update

sudo apt remove -y libportaudio2 portaudio19-dev libportaudiocpp0
echo "y" | rpi-update stable

sudo apt install -y pipewire wireplumber pipewire-audio-client-libraries rtkit cpufrequtils
cp src/service/pipewire/99-lowlatency.conf ~/.config/pipewire/pipewire.conf.d/
sudo cpufreq-set -g performance

/etc/modprobe.d/usb-audio-lowlatency.conf
option snd_usb_audio nrpacks=1

sudo apt install -y --no-install-recommends \
        git build-essential cmake pkg-config \
        libasound2-dev libpulse-dev pipewire ethtool linuxptp
sudo apt remove -y libportaudio2 portaudio19-dev libportaudiocpp0

git clone https://github.com/PortAudio/portaudio.git
cd portaudio 
git checkout 9abe5fe7db729280080a0bbc1397a528cd3ce658     
rm -rf build
cmake -S . -B build -G"Unix Makefiles" \
      -DBUILD_SHARED_LIBS=ON \
      -DPA_USE_ALSA=ON \
      -DPA_USE_PULSEAUDIO=ON \
      -DPA_USE_JACK=OFF
cmake --build build -j$(nproc)
sudo cmake --install build          # installs to /usr/local/lib
sudo ldconfig                        # refresh linker cache


# Device commisioning
- generate id_ed25519 keypair
- setup hostname
  - sudo bash src/auracast/server/provision_domain_hostname.sh box7-summitwave local
- activate aes67 service
  - install udev rule for ptp4l
    - sudo cp src/service/aes67/90-pipewire-aes67-ptp.rules /etc/udev/rules.d/
    - sudo udevadm control --log-priority=debug --reload-rules
    - sudo udevadm trigger
  - bash src/service/update_and_run_aes67.sh
  - poetry config virtualenvs.in-project true
  - poetry install
- activate server and frontend
  - bash srv/service/update_and_run_server_and_frontend.sh
- update to latest stable kernel
    - echo "y" | rpi-update stable
- place cert
- disable pw login
- loginctl enable-linger "$USER"
- reboot

# Use temperature sensor
- uncomment in config.txt: 
	- dtparam=i2c_arm=on
	- reboot
- load drivers
	- sudo modprobe i2c_bcm2835
	- sudo modprobe i2c-dev
	- echo i2c_bcm2835 | sudo tee -a /etc/modules
	- echo i2c-dev     | sudo tee -a /etc/modules
- read temp /src/scripts/temp 

# configure the pcm1862 i2s interface
bash misc/build_pcm1862_dts.sh
bash misc/install_asoundconf.sh

- configure differential inputs
sudo modprobe i2c-dev
i2cdetect -y 1 | grep -i 4a || true

i2cset -f -y 1 0x4a 0x00 0x00   # Page 0
i2cset -f -y 1 0x4a 0x06 0x10   # Left = VIN1P/M [DIFF]
i2cset -f -y 1 0x4a 0x07 0x10   # Right = VIN2P/M [DIFF]

# test recording
 arecord -f cd -c 1 -D record_left left.wav -r48000
 arecord -f cd -c 1 -D record_right right.wav -r48000

# Run with realtime priority
- for the feedback loop to work right realtime priority is absolutely nececcarry.
chrt -f 99 python src/auracast/multicast.py
- give the user realtime priority:
sudo tee /etc/security/limits.d/99-realtime.conf >/dev/null <<'EOF'
caster   -   rtprio   99
caster   -   memlock  unlimited
EOF

# Known issues:
- When running on a laptop there might be issues switching between usb and browser audio input since they use the same audio device

