u
This commit is contained in:
@@ -179,113 +179,131 @@ discover_and_report_controls() {
|
||||
|
||||
log "Discovering available camera controls..."
|
||||
|
||||
# Helper function to escape strings for JSON
|
||||
json_escape() {
|
||||
local str="$1"
|
||||
# Escape backslashes first, then quotes
|
||||
str="${str//\\/\\\\}"
|
||||
str="${str//\"/\\\"}"
|
||||
# Remove any control characters
|
||||
str=$(echo "$str" | tr -d '\n\r\t')
|
||||
echo "$str"
|
||||
}
|
||||
# Get v4l2-ctl output
|
||||
local v4l2_output
|
||||
v4l2_output=$(v4l2-ctl -d "$VIDEO_DEVICE" -L 2>/dev/null) || true
|
||||
|
||||
# Parse v4l2-ctl -L output into JSON
|
||||
# Example lines:
|
||||
# brightness 0x00980900 (int) : min=-64 max=64 step=1 default=0 value=0
|
||||
# exposure_auto 0x009a0901 (menu) : min=0 max=3 default=3 value=3
|
||||
# 1: Manual Mode
|
||||
# 3: Aperture Priority Mode
|
||||
if [[ -z "$v4l2_output" ]]; then
|
||||
log "No v4l2 controls found"
|
||||
return
|
||||
fi
|
||||
|
||||
local controls_json="["
|
||||
local current_values_json="{"
|
||||
local first_control=true
|
||||
local first_value=true
|
||||
local payload
|
||||
|
||||
if command -v jq &>/dev/null; then
|
||||
# Use jq for proper JSON generation
|
||||
local controls_array="[]"
|
||||
local values_obj="{}"
|
||||
local current_ctrl=""
|
||||
local ctrl_json=""
|
||||
local menu_options=""
|
||||
local in_menu=false
|
||||
local current_type=""
|
||||
local current_min=""
|
||||
local current_max=""
|
||||
local current_step=""
|
||||
local current_default=""
|
||||
local current_value=""
|
||||
local menu_opts="{}"
|
||||
|
||||
while IFS= read -r line || [[ -n "$line" ]]; do
|
||||
# Check if this is a control line (starts with control name)
|
||||
while IFS= read -r line; do
|
||||
# Control line pattern: name 0xhex (type) : params
|
||||
if [[ "$line" =~ ^[[:space:]]*([a-z_][a-z0-9_]*)[[:space:]]+0x[0-9a-f]+[[:space:]]+\(([a-z]+)\)[[:space:]]*:[[:space:]]*(.*) ]]; then
|
||||
# Save previous control if exists
|
||||
# Save previous control
|
||||
if [[ -n "$current_ctrl" ]]; then
|
||||
if [[ "$in_menu" == "true" && -n "$menu_options" ]]; then
|
||||
ctrl_json="${ctrl_json%, }, \"options\": {${menu_options%,}}}"
|
||||
else
|
||||
ctrl_json="${ctrl_json%,}}"
|
||||
local ctrl_obj
|
||||
ctrl_obj=$(jq -n \
|
||||
--arg name "$current_ctrl" \
|
||||
--arg type "$current_type" \
|
||||
--argjson min "${current_min:-null}" \
|
||||
--argjson max "${current_max:-null}" \
|
||||
--argjson step "${current_step:-null}" \
|
||||
--argjson default "${current_default:-null}" \
|
||||
--argjson opts "$menu_opts" \
|
||||
'{name: $name, type: $type} +
|
||||
(if $min != null then {min: $min} else {} end) +
|
||||
(if $max != null then {max: $max} else {} end) +
|
||||
(if $step != null then {step: $step} else {} end) +
|
||||
(if $default != null then {default: $default} else {} end) +
|
||||
(if ($opts | length) > 0 then {options: $opts} else {} end)')
|
||||
controls_array=$(echo "$controls_array" | jq --argjson ctrl "$ctrl_obj" '. + [$ctrl]')
|
||||
|
||||
if [[ -n "$current_value" ]]; then
|
||||
values_obj=$(echo "$values_obj" | jq --arg k "$current_ctrl" --argjson v "$current_value" '. + {($k): $v}')
|
||||
fi
|
||||
if [[ "$first_control" == "true" ]]; then
|
||||
first_control=false
|
||||
else
|
||||
controls_json+=","
|
||||
fi
|
||||
controls_json+="$ctrl_json"
|
||||
fi
|
||||
|
||||
current_ctrl="${BASH_REMATCH[1]}"
|
||||
local ctrl_type="${BASH_REMATCH[2]}"
|
||||
current_type="${BASH_REMATCH[2]}"
|
||||
local params="${BASH_REMATCH[3]}"
|
||||
menu_opts="{}"
|
||||
current_min="" current_max="" current_step="" current_default="" current_value=""
|
||||
|
||||
ctrl_json="{\"name\": \"$current_ctrl\", \"type\": \"$ctrl_type\","
|
||||
menu_options=""
|
||||
in_menu=false
|
||||
[[ "$params" =~ min=(-?[0-9]+) ]] && current_min="${BASH_REMATCH[1]}"
|
||||
[[ "$params" =~ max=(-?[0-9]+) ]] && current_max="${BASH_REMATCH[1]}"
|
||||
[[ "$params" =~ step=([0-9]+) ]] && current_step="${BASH_REMATCH[1]}"
|
||||
[[ "$params" =~ default=(-?[0-9]+) ]] && current_default="${BASH_REMATCH[1]}"
|
||||
[[ "$params" =~ value=(-?[0-9]+) ]] && current_value="${BASH_REMATCH[1]}"
|
||||
|
||||
# Parse parameters
|
||||
if [[ "$params" =~ min=(-?[0-9]+) ]]; then
|
||||
ctrl_json+=" \"min\": ${BASH_REMATCH[1]},"
|
||||
# Menu option line
|
||||
elif [[ "$current_type" == "menu" && "$line" =~ ^[[:space:]]+([0-9]+):[[:space:]]+(.+)$ ]]; then
|
||||
local opt_key="${BASH_REMATCH[1]}"
|
||||
local opt_val="${BASH_REMATCH[2]}"
|
||||
menu_opts=$(echo "$menu_opts" | jq --arg k "$opt_key" --arg v "$opt_val" '. + {($k): $v}')
|
||||
fi
|
||||
if [[ "$params" =~ max=(-?[0-9]+) ]]; then
|
||||
ctrl_json+=" \"max\": ${BASH_REMATCH[1]},"
|
||||
fi
|
||||
if [[ "$params" =~ step=([0-9]+) ]]; then
|
||||
ctrl_json+=" \"step\": ${BASH_REMATCH[1]},"
|
||||
fi
|
||||
if [[ "$params" =~ default=(-?[0-9]+) ]]; then
|
||||
ctrl_json+=" \"default\": ${BASH_REMATCH[1]},"
|
||||
fi
|
||||
if [[ "$params" =~ value=(-?[0-9]+) ]]; then
|
||||
local current_value="${BASH_REMATCH[1]}"
|
||||
if [[ "$first_value" == "true" ]]; then
|
||||
first_value=false
|
||||
else
|
||||
current_values_json+=","
|
||||
fi
|
||||
current_values_json+="\"$current_ctrl\": $current_value"
|
||||
fi
|
||||
|
||||
if [[ "$ctrl_type" == "menu" ]]; then
|
||||
in_menu=true
|
||||
fi
|
||||
# Check if this is a menu option line (indented with number: description)
|
||||
elif [[ "$in_menu" == "true" && "$line" =~ ^[[:space:]]+([0-9]+):[[:space:]]+(.+)$ ]]; then
|
||||
local opt_val="${BASH_REMATCH[1]}"
|
||||
local opt_name
|
||||
opt_name=$(json_escape "${BASH_REMATCH[2]}")
|
||||
menu_options+="\"$opt_val\": \"$opt_name\","
|
||||
fi
|
||||
done < <(v4l2-ctl -d "$VIDEO_DEVICE" -L 2>/dev/null)
|
||||
done <<< "$v4l2_output"
|
||||
|
||||
# Save last control
|
||||
if [[ -n "$current_ctrl" ]]; then
|
||||
if [[ "$in_menu" == "true" && -n "$menu_options" ]]; then
|
||||
ctrl_json="${ctrl_json%, }, \"options\": {${menu_options%,}}}"
|
||||
else
|
||||
ctrl_json="${ctrl_json%,}}"
|
||||
local ctrl_obj
|
||||
ctrl_obj=$(jq -n \
|
||||
--arg name "$current_ctrl" \
|
||||
--arg type "$current_type" \
|
||||
--argjson min "${current_min:-null}" \
|
||||
--argjson max "${current_max:-null}" \
|
||||
--argjson step "${current_step:-null}" \
|
||||
--argjson default "${current_default:-null}" \
|
||||
--argjson opts "$menu_opts" \
|
||||
'{name: $name, type: $type} +
|
||||
(if $min != null then {min: $min} else {} end) +
|
||||
(if $max != null then {max: $max} else {} end) +
|
||||
(if $step != null then {step: $step} else {} end) +
|
||||
(if $default != null then {default: $default} else {} end) +
|
||||
(if ($opts | length) > 0 then {options: $opts} else {} end)')
|
||||
controls_array=$(echo "$controls_array" | jq --argjson ctrl "$ctrl_obj" '. + [$ctrl]')
|
||||
|
||||
if [[ -n "$current_value" ]]; then
|
||||
values_obj=$(echo "$values_obj" | jq --arg k "$current_ctrl" --argjson v "$current_value" '. + {($k): $v}')
|
||||
fi
|
||||
if [[ "$first_control" != "true" ]]; then
|
||||
controls_json+=","
|
||||
fi
|
||||
controls_json+="$ctrl_json"
|
||||
fi
|
||||
|
||||
controls_json+="]"
|
||||
current_values_json+="}"
|
||||
payload=$(jq -n --argjson controls "$controls_array" --argjson values "$values_obj" \
|
||||
'{controls: $controls, currentValues: $values}')
|
||||
else
|
||||
# Fallback: simple approach without jq (no menu options, basic controls only)
|
||||
log "jq not available, using simple control discovery"
|
||||
local controls="["
|
||||
local values="{"
|
||||
local first_ctrl=true
|
||||
local first_val=true
|
||||
|
||||
while IFS= read -r line; do
|
||||
if [[ "$line" =~ ^[[:space:]]*([a-z_][a-z0-9_]*)[[:space:]]+0x[0-9a-f]+[[:space:]]+\(([a-z]+)\)[[:space:]]*:.*value=(-?[0-9]+) ]]; then
|
||||
local name="${BASH_REMATCH[1]}"
|
||||
local type="${BASH_REMATCH[2]}"
|
||||
local value="${BASH_REMATCH[3]}"
|
||||
|
||||
[[ "$first_ctrl" == "true" ]] && first_ctrl=false || controls+=","
|
||||
controls+="{\"name\":\"$name\",\"type\":\"$type\"}"
|
||||
|
||||
[[ "$first_val" == "true" ]] && first_val=false || values+=","
|
||||
values+="\"$name\":$value"
|
||||
fi
|
||||
done <<< "$v4l2_output"
|
||||
|
||||
controls+="]"
|
||||
values+="}"
|
||||
payload="{\"controls\":$controls,\"currentValues\":$values}"
|
||||
fi
|
||||
|
||||
# POST to server
|
||||
local payload="{\"controls\": $controls_json, \"currentValues\": $current_values_json}"
|
||||
|
||||
local response
|
||||
response=$(curl -s --max-time 10 \
|
||||
-X POST \
|
||||
@@ -296,7 +314,11 @@ discover_and_report_controls() {
|
||||
|
||||
if echo "$response" | grep -q '"success"'; then
|
||||
local count
|
||||
if command -v jq &>/dev/null; then
|
||||
count=$(echo "$response" | jq -r '.controlsRegistered // "?"')
|
||||
else
|
||||
count=$(echo "$response" | grep -o '"controlsRegistered":[0-9]*' | cut -d: -f2)
|
||||
fi
|
||||
log "Reported $count available controls to server"
|
||||
else
|
||||
log "Failed to report available controls: $response"
|
||||
|
||||
Reference in New Issue
Block a user