mirror of
https://github.com/hanzoskill/device-assistant.git
synced 2026-10-30 21:03:55 +00:00
615 lines
26 KiB
Bash
615 lines
26 KiB
Bash
#!/usr/bin/env bash
|
|
# Device Assistant Handler
|
|
# Personal device manager with error lookup and troubleshooting
|
|
# Usage: handler.sh <command> [args...] <workspace>
|
|
|
|
set -euo pipefail
|
|
|
|
command -v jq >/dev/null 2>&1 || { echo '{"status":"error","message":"jq required"}'; exit 1; }
|
|
command -v curl >/dev/null 2>&1 || { echo '{"status":"error","message":"curl required"}'; exit 1; }
|
|
|
|
CMD="${1:-status}"
|
|
shift || true
|
|
|
|
# Get workspace (always last argument)
|
|
WORKSPACE="${!#:-$(pwd)}"
|
|
DATA_DIR="$WORKSPACE/memory/device-assistant"
|
|
CACHE_DIR="$DATA_DIR/cache"
|
|
|
|
mkdir -p "$DATA_DIR" "$CACHE_DIR"
|
|
|
|
# Files
|
|
DEVICES_FILE="$DATA_DIR/devices.json"
|
|
HISTORY_FILE="$DATA_DIR/error-history.json"
|
|
MAINTENANCE_FILE="$DATA_DIR/maintenance-log.json"
|
|
|
|
# Initialize files
|
|
[[ -f "$DEVICES_FILE" ]] || echo '{"devices":[]}' > "$DEVICES_FILE"
|
|
[[ -f "$HISTORY_FILE" ]] || echo '{"entries":[]}' > "$HISTORY_FILE"
|
|
[[ -f "$MAINTENANCE_FILE" ]] || echo '{"entries":[]}' > "$MAINTENANCE_FILE"
|
|
|
|
# ============================================
|
|
# Helper Functions
|
|
# ============================================
|
|
|
|
generate_id() {
|
|
local name="$1"
|
|
local base
|
|
base=$(echo "$name" | tr '[:upper:]' '[:lower:]' | tr ' äöü' '-aou' | tr -cd 'a-z0-9-')
|
|
local count
|
|
count=$(jq --arg base "$base" '[.devices[] | select(.id | startswith($base))] | length' "$DEVICES_FILE")
|
|
if [[ "$count" -gt 0 ]]; then
|
|
echo "${base}-$((count + 1))"
|
|
else
|
|
echo "$base"
|
|
fi
|
|
}
|
|
|
|
get_device() {
|
|
local identifier="$1"
|
|
# Search by id, name, or nickname (case-insensitive)
|
|
jq -c --arg id "$identifier" '[.devices[] | select(.id == $id or (.name | ascii_downcase) == ($id | ascii_downcase) or (.nickname // "" | ascii_downcase) == ($id | ascii_downcase))][0] // empty' "$DEVICES_FILE"
|
|
}
|
|
|
|
get_device_id() {
|
|
local identifier="$1"
|
|
local device
|
|
device=$(get_device "$identifier")
|
|
echo "$device" | jq -r '.id // empty'
|
|
}
|
|
|
|
# Search web for error code
|
|
search_error_code() {
|
|
local manufacturer="$1"
|
|
local model="$2"
|
|
local error_code="$3"
|
|
|
|
# Build search query
|
|
local query="${manufacturer} ${model} Fehler ${error_code} Lösung"
|
|
local encoded_query
|
|
encoded_query=$(echo -n "$query" | jq -sRr @uri)
|
|
|
|
# Check cache first
|
|
local cache_key
|
|
cache_key=$(echo -n "${manufacturer}-${model}-${error_code}" | tr ' ' '-' | tr '[:upper:]' '[:lower:]')
|
|
local cache_file="$CACHE_DIR/error-${cache_key}.json"
|
|
|
|
if [[ -f "$cache_file" ]]; then
|
|
local cache_age=$(($(date +%s) - $(stat -c %Y "$cache_file" 2>/dev/null || echo 0)))
|
|
if [[ $cache_age -lt 604800 ]]; then # 1 week cache
|
|
cat "$cache_file"
|
|
return 0
|
|
fi
|
|
fi
|
|
|
|
# Return structured response with search suggestion
|
|
local result
|
|
result=$(jq -n \
|
|
--arg manufacturer "$manufacturer" \
|
|
--arg model "$model" \
|
|
--arg code "$error_code" \
|
|
--arg query "$query" \
|
|
'{
|
|
manufacturer: $manufacturer,
|
|
model: $model,
|
|
errorCode: $code,
|
|
searchQuery: $query,
|
|
searchUrl: ("https://www.google.com/search?q=" + ($query | @uri))
|
|
}')
|
|
|
|
echo "$result" > "$cache_file"
|
|
echo "$result"
|
|
}
|
|
|
|
# Get known error codes for common manufacturers
|
|
get_known_error() {
|
|
local manufacturer="${1,,}"
|
|
local code="${2^^}"
|
|
|
|
case "$manufacturer" in
|
|
siemens|bosch|neff|constructa)
|
|
case "$code" in
|
|
E15) echo '{"meaning":"Wasserschutz aktiv","description":"Wasser in der Bodenwanne erkannt.","solution":["Gerät ausschalten","Wasser aus Bodenwanne entfernen","Auf Undichtigkeit prüfen","Gerät trocknen lassen"]}' ;;
|
|
E24) echo '{"meaning":"Abpumpproblem","description":"Wasser wird nicht richtig abgepumpt.","solution":["Sieb am Boden reinigen","Abflussschlauch prüfen","Siphon kontrollieren","Pumpe auf Fremdkörper prüfen"]}' ;;
|
|
E25) echo '{"meaning":"Ablaufpumpe blockiert","description":"Pumpe kann nicht arbeiten.","solution":["Pumpendeckel öffnen","Fremdkörper entfernen","Flügelrad prüfen"]}' ;;
|
|
E22) echo '{"meaning":"Filter verstopft","description":"Siebe sind verschmutzt.","solution":["Alle Siebe entnehmen","Unter Wasser reinigen","Siebe wieder einsetzen"]}' ;;
|
|
E01|E1) echo '{"meaning":"Heizungsfehler","description":"Wasser wird nicht erhitzt.","solution":["Service kontaktieren","Heizelement defekt"]}' ;;
|
|
E09) echo '{"meaning":"Heizfehler","description":"Problem mit der Heizung.","solution":["Service kontaktieren"]}' ;;
|
|
*) echo '{}' ;;
|
|
esac
|
|
;;
|
|
miele)
|
|
case "$code" in
|
|
F11) echo '{"meaning":"Abpumpfehler","description":"Wasser läuft nicht ab.","solution":["Ablauf prüfen","Filter reinigen","Pumpe prüfen"]}' ;;
|
|
F12|F13) echo '{"meaning":"Zulaufproblem","description":"Wasser läuft nicht zu.","solution":["Wasserhahn prüfen","Zulaufschlauch prüfen","Sieb im Zulauf reinigen"]}' ;;
|
|
F53) echo '{"meaning":"Motorfehler","description":"Motor funktioniert nicht korrekt.","solution":["Service kontaktieren"]}' ;;
|
|
*) echo '{}' ;;
|
|
esac
|
|
;;
|
|
samsung)
|
|
case "$code" in
|
|
UE|UB|E4) echo '{"meaning":"Unwucht","description":"Wäsche ungleichmäßig verteilt.","solution":["Wäsche gleichmäßiger verteilen","Nicht zu viel/wenig beladen","Gerät ausrichten"]}' ;;
|
|
OE|OF|E3) echo '{"meaning":"Überlauf","description":"Zu viel Wasser im Gerät.","solution":["Wasserzulauf schließen","Ablauf prüfen","Service kontaktieren"]}' ;;
|
|
LE|LE1|E9) echo '{"meaning":"Wasserleck","description":"Leck erkannt.","solution":["Gerät sofort ausschalten","Auf Undichtigkeit prüfen","Service kontaktieren"]}' ;;
|
|
HE|HE1|HE2) echo '{"meaning":"Heizungsfehler","description":"Wasser wird nicht erhitzt.","solution":["Service kontaktieren"]}' ;;
|
|
*) echo '{}' ;;
|
|
esac
|
|
;;
|
|
lg)
|
|
case "$code" in
|
|
OE) echo '{"meaning":"Abflussfehler","description":"Wasser läuft nicht ab.","solution":["Ablaufschlauch prüfen","Filter reinigen","Pumpe prüfen"]}' ;;
|
|
IE) echo '{"meaning":"Zulaufproblem","description":"Kein Wasserzulauf.","solution":["Wasserhahn öffnen","Zulaufschlauch prüfen"]}' ;;
|
|
UE) echo '{"meaning":"Unwucht","description":"Ungleichmäßige Beladung.","solution":["Wäsche verteilen","Gerät ausrichten"]}' ;;
|
|
PE) echo '{"meaning":"Drucksensorfehler","description":"Wasserstandssensor defekt.","solution":["Service kontaktieren"]}' ;;
|
|
*) echo '{}' ;;
|
|
esac
|
|
;;
|
|
aeg|electrolux)
|
|
case "$code" in
|
|
E10) echo '{"meaning":"Zulaufproblem","description":"Wasser läuft nicht zu.","solution":["Wasserhahn prüfen","Zulaufschlauch prüfen","Sieb reinigen"]}' ;;
|
|
E20) echo '{"meaning":"Abpumpfehler","description":"Wasser läuft nicht ab.","solution":["Filter reinigen","Ablauf prüfen","Pumpe prüfen"]}' ;;
|
|
E40) echo '{"meaning":"Türproblem","description":"Tür nicht richtig geschlossen.","solution":["Tür schließen","Türschloss prüfen"]}' ;;
|
|
*) echo '{}' ;;
|
|
esac
|
|
;;
|
|
*)
|
|
echo '{}'
|
|
;;
|
|
esac
|
|
}
|
|
|
|
# ============================================
|
|
# Commands
|
|
# ============================================
|
|
|
|
case "$CMD" in
|
|
# ----------------------------------------
|
|
# STATUS
|
|
# ----------------------------------------
|
|
status)
|
|
device_count=$(jq '.devices | length' "$DEVICES_FILE")
|
|
|
|
# Check for expiring warranties (next 90 days)
|
|
today=$(date +%s)
|
|
ninety_days=$((today + 7776000))
|
|
expiring=$(jq --argjson today "$today" --argjson future "$ninety_days" '[.devices[] | select(.warranty.expires != null) | select((.warranty.expires | strptime("%Y-%m-%d") | mktime) > $today and (.warranty.expires | strptime("%Y-%m-%d") | mktime) < $future)] | length' "$DEVICES_FILE" 2>/dev/null || echo "0")
|
|
|
|
# Check for due maintenance
|
|
maintenance_due=$(jq '[.devices[] | .maintenance[]? | select(.lastDone != null)] | length' "$DEVICES_FILE" 2>/dev/null || echo "0")
|
|
|
|
# Categories summary
|
|
categories=$(jq '[.devices[].category] | group_by(.) | map({category: .[0], count: length})' "$DEVICES_FILE")
|
|
|
|
jq -n \
|
|
--argjson count "$device_count" \
|
|
--argjson expiring "$expiring" \
|
|
--argjson maintenance "$maintenance_due" \
|
|
--argjson categories "$categories" \
|
|
'{
|
|
status: "ok",
|
|
deviceCount: $count,
|
|
warningWarrantyExpiring: $expiring,
|
|
maintenanceTracked: $maintenance,
|
|
byCategory: $categories,
|
|
commands: {
|
|
"/device list": "Alle Geräte anzeigen",
|
|
"/device add": "Neues Gerät hinzufügen",
|
|
"/device info <name>": "Geräte-Details",
|
|
"/device error <name> <code>": "Fehlercode nachschlagen",
|
|
"/device help <name> <problem>": "Problemlösung",
|
|
"/device warranty": "Garantie-Übersicht",
|
|
"/device maintenance": "Wartungsplan"
|
|
}
|
|
}'
|
|
;;
|
|
|
|
# ----------------------------------------
|
|
# LIST
|
|
# ----------------------------------------
|
|
list)
|
|
category="${1:-}"
|
|
|
|
if [[ -n "$category" && "$category" != "$WORKSPACE" ]]; then
|
|
devices=$(jq --arg cat "$category" '[.devices[] | select(.category == $cat)]' "$DEVICES_FILE")
|
|
else
|
|
devices=$(jq '.devices' "$DEVICES_FILE")
|
|
fi
|
|
|
|
echo "$devices" | jq '{
|
|
status: "ok",
|
|
count: length,
|
|
devices: [.[] | {
|
|
id: .id,
|
|
name: .name,
|
|
nickname: .nickname,
|
|
manufacturer: .manufacturer,
|
|
model: .model,
|
|
category: .category,
|
|
location: .location
|
|
}]
|
|
}'
|
|
;;
|
|
|
|
# ----------------------------------------
|
|
# ADD
|
|
# ----------------------------------------
|
|
add)
|
|
json_data="${1:-}"
|
|
|
|
if [[ -z "$json_data" || "$json_data" == "$WORKSPACE" ]]; then
|
|
# Interactive mode - return prompt
|
|
echo '{"status":"ok","action":"prompt","message":"Gerätedaten benötigt","required":["name","manufacturer","model"],"optional":["serialNumber","purchaseDate","purchasePrice","warranty","manualUrl","location","category","nickname"]}'
|
|
exit 0
|
|
fi
|
|
|
|
# Parse and validate JSON
|
|
if ! echo "$json_data" | jq -e . >/dev/null 2>&1; then
|
|
echo '{"status":"error","message":"Invalid JSON"}'
|
|
exit 1
|
|
fi
|
|
|
|
name=$(echo "$json_data" | jq -r '.name // empty')
|
|
[[ -z "$name" ]] && { echo '{"status":"error","message":"Name required"}'; exit 1; }
|
|
|
|
# Generate ID
|
|
device_id=$(generate_id "$name")
|
|
|
|
# Build device entry
|
|
device=$(echo "$json_data" | jq --arg id "$device_id" --arg added "$(date -Iseconds)" '
|
|
{
|
|
id: $id,
|
|
name: .name,
|
|
nickname: (.nickname // null),
|
|
category: (.category // "other"),
|
|
manufacturer: (.manufacturer // "Unknown"),
|
|
model: (.model // "Unknown"),
|
|
serialNumber: (.serialNumber // null),
|
|
purchaseDate: (.purchaseDate // null),
|
|
purchasePrice: (.purchasePrice // null),
|
|
warranty: (.warranty // null),
|
|
manualUrl: (.manualUrl // null),
|
|
supportUrl: (.supportUrl // null),
|
|
location: (.location // null),
|
|
notes: (.notes // null),
|
|
maintenance: (.maintenance // []),
|
|
errorHistory: [],
|
|
addedAt: $added
|
|
}
|
|
')
|
|
|
|
# Add to devices file
|
|
jq --argjson device "$device" '.devices += [$device]' "$DEVICES_FILE" > "$DEVICES_FILE.tmp"
|
|
mv "$DEVICES_FILE.tmp" "$DEVICES_FILE"
|
|
|
|
echo "$device" | jq '{status: "ok", message: "Gerät hinzugefügt", device: .}'
|
|
;;
|
|
|
|
# ----------------------------------------
|
|
# INFO
|
|
# ----------------------------------------
|
|
info)
|
|
identifier="${1:-}"
|
|
[[ -z "$identifier" || "$identifier" == "$WORKSPACE" ]] && { echo '{"status":"error","message":"Device name/id required"}'; exit 1; }
|
|
|
|
device=$(get_device "$identifier")
|
|
[[ -z "$device" || "$device" == "null" ]] && { echo '{"status":"error","message":"Device not found: '"$identifier"'"}'; exit 1; }
|
|
|
|
# Calculate warranty status
|
|
warranty_status="unknown"
|
|
warranty_expires=$(echo "$device" | jq -r '.warranty.expires // empty')
|
|
if [[ -n "$warranty_expires" && "$warranty_expires" != "null" ]]; then
|
|
expires_ts=$(date -d "$warranty_expires" +%s 2>/dev/null || echo 0)
|
|
today_ts=$(date +%s)
|
|
if [[ $expires_ts -gt 0 ]]; then
|
|
if [[ $expires_ts -gt $today_ts ]]; then
|
|
days_left=$(( (expires_ts - today_ts) / 86400 ))
|
|
warranty_status="aktiv (noch $days_left Tage)"
|
|
else
|
|
warranty_status="ABGELAUFEN"
|
|
fi
|
|
fi
|
|
fi
|
|
|
|
echo "$device" | jq --arg ws "$warranty_status" '. + {status: "ok", warrantyStatus: $ws}'
|
|
;;
|
|
|
|
# ----------------------------------------
|
|
# ERROR - Lookup error code
|
|
# ----------------------------------------
|
|
error)
|
|
identifier="${1:-}"
|
|
error_code="${2:-}"
|
|
|
|
[[ -z "$identifier" || "$identifier" == "$WORKSPACE" ]] && { echo '{"status":"error","message":"Device name required"}'; exit 1; }
|
|
[[ -z "$error_code" || "$error_code" == "$WORKSPACE" ]] && { echo '{"status":"error","message":"Error code required"}'; exit 1; }
|
|
|
|
device=$(get_device "$identifier")
|
|
[[ -z "$device" ]] && { echo '{"status":"error","message":"Device not found: '"$identifier"'"}'; exit 1; }
|
|
|
|
manufacturer=$(echo "$device" | jq -r '.manufacturer')
|
|
model=$(echo "$device" | jq -r '.model')
|
|
device_name=$(echo "$device" | jq -r '.name')
|
|
device_id=$(echo "$device" | jq -r '.id')
|
|
|
|
# Try built-in error codes first
|
|
known_error=$(get_known_error "$manufacturer" "$error_code")
|
|
|
|
if [[ "$known_error" != "{}" ]]; then
|
|
# Found in built-in database
|
|
result=$(echo "$known_error" | jq --arg mfr "$manufacturer" --arg mdl "$model" --arg code "$error_code" --arg name "$device_name" '
|
|
{
|
|
status: "ok",
|
|
source: "builtin",
|
|
device: $name,
|
|
manufacturer: $mfr,
|
|
model: $mdl,
|
|
errorCode: $code,
|
|
meaning: .meaning,
|
|
description: .description,
|
|
solution: .solution
|
|
}
|
|
')
|
|
else
|
|
# Search online
|
|
search_result=$(search_error_code "$manufacturer" "$model" "$error_code")
|
|
result=$(echo "$search_result" | jq --arg name "$device_name" '
|
|
{
|
|
status: "ok",
|
|
source: "search",
|
|
device: $name,
|
|
manufacturer: .manufacturer,
|
|
model: .model,
|
|
errorCode: .errorCode,
|
|
meaning: "Unbekannt",
|
|
description: "Fehlercode nicht in Datenbank",
|
|
searchUrl: .searchUrl,
|
|
suggestion: "Bitte online suchen oder Handbuch prüfen"
|
|
}
|
|
')
|
|
fi
|
|
|
|
# Log error to history
|
|
jq --arg device "$device_id" --arg code "$error_code" --arg ts "$(date -Iseconds)" \
|
|
'.entries = [{timestamp: $ts, deviceId: $device, errorCode: $code}] + .entries[:99]' \
|
|
"$HISTORY_FILE" > "$HISTORY_FILE.tmp"
|
|
mv "$HISTORY_FILE.tmp" "$HISTORY_FILE"
|
|
|
|
echo "$result"
|
|
;;
|
|
|
|
# ----------------------------------------
|
|
# TROUBLESHOOT - General problem help
|
|
# ----------------------------------------
|
|
troubleshoot)
|
|
identifier="${1:-}"
|
|
problem="${2:-}"
|
|
|
|
[[ -z "$identifier" ]] && { echo '{"status":"error","message":"Device name required"}'; exit 1; }
|
|
|
|
device=$(get_device "$identifier")
|
|
[[ -z "$device" ]] && { echo '{"status":"error","message":"Device not found"}'; exit 1; }
|
|
|
|
manufacturer=$(echo "$device" | jq -r '.manufacturer')
|
|
model=$(echo "$device" | jq -r '.model')
|
|
device_name=$(echo "$device" | jq -r '.name')
|
|
manual_url=$(echo "$device" | jq -r '.manualUrl // empty')
|
|
support_url=$(echo "$device" | jq -r '.supportUrl // empty')
|
|
|
|
# Build search query for the problem
|
|
query="${manufacturer} ${model} ${problem} Lösung"
|
|
search_url="https://www.google.com/search?q=$(echo -n "$query" | jq -sRr @uri)"
|
|
|
|
jq -n \
|
|
--arg device "$device_name" \
|
|
--arg mfr "$manufacturer" \
|
|
--arg mdl "$model" \
|
|
--arg problem "$problem" \
|
|
--arg searchUrl "$search_url" \
|
|
--arg manualUrl "$manual_url" \
|
|
--arg supportUrl "$support_url" \
|
|
'{
|
|
status: "ok",
|
|
device: $device,
|
|
manufacturer: $mfr,
|
|
model: $mdl,
|
|
problem: $problem,
|
|
resources: {
|
|
searchUrl: $searchUrl,
|
|
manualUrl: (if $manualUrl != "" then $manualUrl else null end),
|
|
supportUrl: (if $supportUrl != "" then $supportUrl else null end)
|
|
},
|
|
generalTips: [
|
|
"Gerät aus- und wieder einschalten",
|
|
"Bedienungsanleitung prüfen",
|
|
"Hersteller-Support kontaktieren"
|
|
]
|
|
}'
|
|
;;
|
|
|
|
# ----------------------------------------
|
|
# MANUAL
|
|
# ----------------------------------------
|
|
manual)
|
|
identifier="${1:-}"
|
|
[[ -z "$identifier" ]] && { echo '{"status":"error","message":"Device name required"}'; exit 1; }
|
|
|
|
device=$(get_device "$identifier")
|
|
[[ -z "$device" ]] && { echo '{"status":"error","message":"Device not found"}'; exit 1; }
|
|
|
|
manufacturer=$(echo "$device" | jq -r '.manufacturer')
|
|
model=$(echo "$device" | jq -r '.model')
|
|
manual_url=$(echo "$device" | jq -r '.manualUrl // empty')
|
|
|
|
# If no manual URL stored, provide search link
|
|
if [[ -z "$manual_url" ]]; then
|
|
query="${manufacturer} ${model} Bedienungsanleitung PDF"
|
|
search_url="https://www.google.com/search?q=$(echo -n "$query" | jq -sRr @uri)"
|
|
manual_url="$search_url"
|
|
stored=false
|
|
else
|
|
stored=true
|
|
fi
|
|
|
|
jq -n \
|
|
--arg device "$(echo "$device" | jq -r '.name')" \
|
|
--arg mfr "$manufacturer" \
|
|
--arg mdl "$model" \
|
|
--arg url "$manual_url" \
|
|
--argjson stored "$stored" \
|
|
'{
|
|
status: "ok",
|
|
device: $device,
|
|
manufacturer: $mfr,
|
|
model: $mdl,
|
|
manualUrl: $url,
|
|
isStored: $stored
|
|
}'
|
|
;;
|
|
|
|
# ----------------------------------------
|
|
# WARRANTY
|
|
# ----------------------------------------
|
|
warranty)
|
|
today=$(date +%s)
|
|
|
|
warranties=$(jq --argjson today "$today" '
|
|
[.devices[] | select(.warranty.expires != null) |
|
|
{
|
|
name: .name,
|
|
manufacturer: .manufacturer,
|
|
model: .model,
|
|
expires: .warranty.expires,
|
|
expiresTs: (.warranty.expires | strptime("%Y-%m-%d") | mktime),
|
|
daysLeft: (((.warranty.expires | strptime("%Y-%m-%d") | mktime) - $today) / 86400 | floor)
|
|
}
|
|
] | sort_by(.expiresTs)
|
|
' "$DEVICES_FILE" 2>/dev/null || echo "[]")
|
|
|
|
active=$(echo "$warranties" | jq '[.[] | select(.daysLeft > 0)]')
|
|
expired=$(echo "$warranties" | jq '[.[] | select(.daysLeft <= 0)]')
|
|
expiring_soon=$(echo "$warranties" | jq '[.[] | select(.daysLeft > 0 and .daysLeft <= 90)]')
|
|
|
|
jq -n \
|
|
--argjson active "$active" \
|
|
--argjson expired "$expired" \
|
|
--argjson soon "$expiring_soon" \
|
|
'{
|
|
status: "ok",
|
|
active: ($active | length),
|
|
expired: ($expired | length),
|
|
expiringSoon: $soon,
|
|
allWarranties: ($active + $expired)
|
|
}'
|
|
;;
|
|
|
|
# ----------------------------------------
|
|
# MAINTENANCE
|
|
# ----------------------------------------
|
|
maintenance)
|
|
# Get all devices with maintenance tasks
|
|
devices_with_maintenance=$(jq '[.devices[] | select(.maintenance | length > 0) | {
|
|
id: .id,
|
|
name: .name,
|
|
tasks: .maintenance
|
|
}]' "$DEVICES_FILE")
|
|
|
|
jq -n --argjson devices "$devices_with_maintenance" '{
|
|
status: "ok",
|
|
devicesWithMaintenance: ($devices | length),
|
|
devices: $devices
|
|
}'
|
|
;;
|
|
|
|
# ----------------------------------------
|
|
# UPDATE
|
|
# ----------------------------------------
|
|
update)
|
|
identifier="${1:-}"
|
|
json_data="${2:-}"
|
|
|
|
[[ -z "$identifier" ]] && { echo '{"status":"error","message":"Device name required"}'; exit 1; }
|
|
[[ -z "$json_data" || "$json_data" == "$WORKSPACE" ]] && { echo '{"status":"error","message":"Update data required"}'; exit 1; }
|
|
|
|
device_id=$(get_device_id "$identifier")
|
|
[[ -z "$device_id" ]] && { echo '{"status":"error","message":"Device not found"}'; exit 1; }
|
|
|
|
# Merge updates
|
|
jq --arg id "$device_id" --argjson updates "$json_data" '
|
|
.devices = [.devices[] | if .id == $id then . * $updates else . end]
|
|
' "$DEVICES_FILE" > "$DEVICES_FILE.tmp"
|
|
mv "$DEVICES_FILE.tmp" "$DEVICES_FILE"
|
|
|
|
echo '{"status":"ok","message":"Device updated","deviceId":"'"$device_id"'"}'
|
|
;;
|
|
|
|
# ----------------------------------------
|
|
# REMOVE
|
|
# ----------------------------------------
|
|
remove)
|
|
identifier="${1:-}"
|
|
[[ -z "$identifier" ]] && { echo '{"status":"error","message":"Device name required"}'; exit 1; }
|
|
|
|
device_id=$(get_device_id "$identifier")
|
|
[[ -z "$device_id" ]] && { echo '{"status":"error","message":"Device not found"}'; exit 1; }
|
|
|
|
jq --arg id "$device_id" '.devices = [.devices[] | select(.id != $id)]' "$DEVICES_FILE" > "$DEVICES_FILE.tmp"
|
|
mv "$DEVICES_FILE.tmp" "$DEVICES_FILE"
|
|
|
|
echo '{"status":"ok","message":"Device removed","deviceId":"'"$device_id"'"}'
|
|
;;
|
|
|
|
# ----------------------------------------
|
|
# SEARCH
|
|
# ----------------------------------------
|
|
search)
|
|
query="${1:-}"
|
|
[[ -z "$query" ]] && { echo '{"status":"error","message":"Search query required"}'; exit 1; }
|
|
|
|
results=$(jq --arg q "$query" '
|
|
[.devices[] | select(
|
|
(.name | ascii_downcase | contains($q | ascii_downcase)) or
|
|
(.manufacturer | ascii_downcase | contains($q | ascii_downcase)) or
|
|
(.model | ascii_downcase | contains($q | ascii_downcase)) or
|
|
((.nickname // "") | ascii_downcase | contains($q | ascii_downcase)) or
|
|
((.location // "") | ascii_downcase | contains($q | ascii_downcase))
|
|
)]
|
|
' "$DEVICES_FILE")
|
|
|
|
echo "$results" | jq '{status: "ok", query: "'"$query"'", results: ., count: length}'
|
|
;;
|
|
|
|
# ----------------------------------------
|
|
# LOG - Add maintenance log
|
|
# ----------------------------------------
|
|
log)
|
|
identifier="${1:-}"
|
|
note="${2:-}"
|
|
|
|
[[ -z "$identifier" ]] && { echo '{"status":"error","message":"Device name required"}'; exit 1; }
|
|
[[ -z "$note" || "$note" == "$WORKSPACE" ]] && { echo '{"status":"error","message":"Note required"}'; exit 1; }
|
|
|
|
device_id=$(get_device_id "$identifier")
|
|
[[ -z "$device_id" ]] && { echo '{"status":"error","message":"Device not found"}'; exit 1; }
|
|
|
|
# Add to maintenance log
|
|
jq --arg device "$device_id" --arg note "$note" --arg ts "$(date -Iseconds)" \
|
|
'.entries = [{timestamp: $ts, deviceId: $device, note: $note}] + .entries' \
|
|
"$MAINTENANCE_FILE" > "$MAINTENANCE_FILE.tmp"
|
|
mv "$MAINTENANCE_FILE.tmp" "$MAINTENANCE_FILE"
|
|
|
|
echo '{"status":"ok","message":"Maintenance logged","deviceId":"'"$device_id"'"}'
|
|
;;
|
|
|
|
# ----------------------------------------
|
|
# HELP
|
|
# ----------------------------------------
|
|
help)
|
|
echo '{"status":"ok","commands":["status","list","add","info","error","troubleshoot","manual","warranty","maintenance","update","remove","search","log"]}'
|
|
;;
|
|
|
|
*)
|
|
echo '{"status":"error","message":"Unknown command: '"$CMD"'"}'
|
|
exit 1
|
|
;;
|
|
esac
|