feat: Implement server-managed camera settings with new API endpoints, client-side application, and updated documentation.
This commit is contained in:
@@ -76,6 +76,58 @@ VIDEO_DEVICE="/dev/video0"
|
||||
./capture-upload.sh
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Camera Settings (Focus & Exposure)
|
||||
|
||||
Camera settings are stored on the PicUpper server and applied before each capture.
|
||||
|
||||
### Set camera settings via API
|
||||
|
||||
```bash
|
||||
# Set focus and exposure for your camera
|
||||
curl -X PUT \
|
||||
-H "X-API-Key: your-api-key" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"focus_automatic_continuous": 0,
|
||||
"focus_absolute": 30,
|
||||
"exposure_auto": 1,
|
||||
"exposure_absolute": 200,
|
||||
"brightness": 0,
|
||||
"contrast": 32
|
||||
}' \
|
||||
https://dev.seedheads.de/picUploadApi/settings/rpi-webcam-1
|
||||
```
|
||||
|
||||
### Get current settings
|
||||
|
||||
```bash
|
||||
curl -H "X-API-Key: your-api-key" \
|
||||
https://dev.seedheads.de/picUploadApi/settings/rpi-webcam-1
|
||||
```
|
||||
|
||||
### Available settings (for Logitech C922)
|
||||
|
||||
| Setting | Range | Description |
|
||||
|---------|-------|-------------|
|
||||
| `focus_automatic_continuous` | 0-1 | 0=manual, 1=auto |
|
||||
| `focus_absolute` | 0-255 | Lower=closer (manual mode) |
|
||||
| `exposure_auto` | 1-3 | 1=manual, 3=auto |
|
||||
| `exposure_absolute` | 3-2047 | Shutter speed (manual mode) |
|
||||
| `brightness` | -64 to 64 | Image brightness |
|
||||
| `contrast` | 0-64 | Image contrast |
|
||||
|
||||
### Find your camera's available controls
|
||||
|
||||
```bash
|
||||
v4l2-ctl -d /dev/video0 --list-ctrls
|
||||
```
|
||||
|
||||
**Note:** Install `v4l-utils` on the Pi: `sudo apt install v4l-utils`
|
||||
|
||||
---
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Check if webcam is detected
|
||||
|
||||
@@ -118,6 +118,125 @@ if [[ ! -e "$VIDEO_DEVICE" ]]; then
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Fetch and apply camera settings from server
|
||||
apply_camera_settings() {
|
||||
# Check if v4l2-ctl is available
|
||||
if ! command -v v4l2-ctl &>/dev/null; then
|
||||
log "v4l2-ctl not installed, skipping camera settings"
|
||||
return
|
||||
fi
|
||||
|
||||
# Derive settings URL from upload URL (replace /upload with /settings)
|
||||
local SETTINGS_URL="${API_URL%/upload}/settings/$CAMERA_ID"
|
||||
|
||||
log "Fetching camera settings from server..."
|
||||
local SETTINGS_RESPONSE
|
||||
SETTINGS_RESPONSE=$(curl -s --max-time 10 \
|
||||
-H "X-API-Key: $API_KEY" \
|
||||
"$SETTINGS_URL" 2>/dev/null) || true
|
||||
|
||||
if [[ -z "$SETTINGS_RESPONSE" ]]; then
|
||||
log "Could not fetch settings, using camera defaults"
|
||||
return
|
||||
fi
|
||||
|
||||
# Check if server has custom settings (look for updatedAt field)
|
||||
local has_custom_settings=false
|
||||
if command -v jq &>/dev/null; then
|
||||
local updated_at
|
||||
updated_at=$(echo "$SETTINGS_RESPONSE" | jq -r '.settings.updatedAt // empty')
|
||||
if [[ -n "$updated_at" && "$updated_at" != "null" ]]; then
|
||||
has_custom_settings=true
|
||||
fi
|
||||
else
|
||||
if echo "$SETTINGS_RESPONSE" | grep -q '"updatedAt"'; then
|
||||
has_custom_settings=true
|
||||
fi
|
||||
fi
|
||||
|
||||
if [[ "$has_custom_settings" == "false" ]]; then
|
||||
# No custom settings on server - upload current camera settings
|
||||
log "No settings on server, uploading current camera settings..."
|
||||
upload_current_settings
|
||||
return
|
||||
fi
|
||||
|
||||
# Apply settings from server
|
||||
if command -v jq &>/dev/null; then
|
||||
local settings
|
||||
settings=$(echo "$SETTINGS_RESPONSE" | jq -r '.settings // empty')
|
||||
if [[ -n "$settings" ]]; then
|
||||
for ctrl in focus_automatic_continuous focus_absolute exposure_auto exposure_absolute brightness contrast; do
|
||||
local value
|
||||
value=$(echo "$settings" | jq -r ".$ctrl // empty")
|
||||
if [[ -n "$value" && "$value" != "null" ]]; then
|
||||
v4l2-ctl -d "$VIDEO_DEVICE" --set-ctrl="${ctrl}=${value}" 2>/dev/null || true
|
||||
fi
|
||||
done
|
||||
log "Applied camera settings from server"
|
||||
fi
|
||||
else
|
||||
for ctrl in focus_automatic_continuous focus_absolute exposure_auto exposure_absolute brightness contrast; do
|
||||
local value
|
||||
value=$(echo "$SETTINGS_RESPONSE" | grep -o "\"${ctrl}\":[0-9-]*" | cut -d: -f2)
|
||||
if [[ -n "$value" ]]; then
|
||||
v4l2-ctl -d "$VIDEO_DEVICE" --set-ctrl="${ctrl}=${value}" 2>/dev/null || true
|
||||
fi
|
||||
done
|
||||
log "Applied camera settings from server"
|
||||
fi
|
||||
}
|
||||
|
||||
# Read current camera settings and upload to server
|
||||
upload_current_settings() {
|
||||
local SETTINGS_URL="${API_URL%/upload}/settings/$CAMERA_ID"
|
||||
|
||||
# Read current values from camera
|
||||
local focus_auto focus_abs exp_auto exp_abs brightness contrast
|
||||
focus_auto=$(v4l2-ctl -d "$VIDEO_DEVICE" --get-ctrl=focus_automatic_continuous 2>/dev/null | cut -d: -f2 | tr -d ' ') || focus_auto=""
|
||||
focus_abs=$(v4l2-ctl -d "$VIDEO_DEVICE" --get-ctrl=focus_absolute 2>/dev/null | cut -d: -f2 | tr -d ' ') || focus_abs=""
|
||||
exp_auto=$(v4l2-ctl -d "$VIDEO_DEVICE" --get-ctrl=exposure_auto 2>/dev/null | cut -d: -f2 | tr -d ' ') || exp_auto=""
|
||||
exp_abs=$(v4l2-ctl -d "$VIDEO_DEVICE" --get-ctrl=exposure_absolute 2>/dev/null | cut -d: -f2 | tr -d ' ') || exp_abs=""
|
||||
brightness=$(v4l2-ctl -d "$VIDEO_DEVICE" --get-ctrl=brightness 2>/dev/null | cut -d: -f2 | tr -d ' ') || brightness=""
|
||||
contrast=$(v4l2-ctl -d "$VIDEO_DEVICE" --get-ctrl=contrast 2>/dev/null | cut -d: -f2 | tr -d ' ') || contrast=""
|
||||
|
||||
# Build JSON payload
|
||||
local json_parts=()
|
||||
[[ -n "$focus_auto" ]] && json_parts+=("\"focus_automatic_continuous\": $focus_auto")
|
||||
[[ -n "$focus_abs" ]] && json_parts+=("\"focus_absolute\": $focus_abs")
|
||||
[[ -n "$exp_auto" ]] && json_parts+=("\"exposure_auto\": $exp_auto")
|
||||
[[ -n "$exp_abs" ]] && json_parts+=("\"exposure_absolute\": $exp_abs")
|
||||
[[ -n "$brightness" ]] && json_parts+=("\"brightness\": $brightness")
|
||||
[[ -n "$contrast" ]] && json_parts+=("\"contrast\": $contrast")
|
||||
|
||||
if [[ ${#json_parts[@]} -eq 0 ]]; then
|
||||
log "Could not read camera settings"
|
||||
return
|
||||
fi
|
||||
|
||||
# Join with commas
|
||||
local IFS=','
|
||||
local json_body="{${json_parts[*]}}"
|
||||
|
||||
# Upload to server
|
||||
local response
|
||||
response=$(curl -s --max-time 10 \
|
||||
-X PUT \
|
||||
-H "X-API-Key: $API_KEY" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d "$json_body" \
|
||||
"$SETTINGS_URL" 2>/dev/null) || true
|
||||
|
||||
if echo "$response" | grep -q '"success"'; then
|
||||
log "Uploaded current camera settings to server"
|
||||
else
|
||||
log "Failed to upload camera settings"
|
||||
fi
|
||||
}
|
||||
|
||||
apply_camera_settings
|
||||
|
||||
|
||||
# Capture image
|
||||
log "Capturing from $VIDEO_DEVICE ($RESOLUTION)"
|
||||
if ! fswebcam -d "$VIDEO_DEVICE" -r "$RESOLUTION" -S "$SKIP_FRAMES" --no-banner "$TEMP_FILE" 2>/dev/null; then
|
||||
|
||||
Reference in New Issue
Block a user