
Device Assistant
- 8 installs
- 33 repo stars
- Updated April 26, 2026
- bighardperson/computer-science-skills-collection
Device-assistant is a skill that tracks personal devices and appliances and looks up error codes with step-by-step troubleshooting.
About
This skill is a personal device and appliance manager. It tracks devices with model numbers, serial numbers, warranty and purchase details, and provides error-code lookups with step-by-step troubleshooting. It also surfaces manuals, warranty-expiry alerts, and maintenance reminders. It understands natural-language German queries and stores data as JSON files in the workspace.
- Tracks devices with model, serial, purchase, and warranty info
- Looks up appliance error codes and gives step-by-step fixes
- Reminds about warranty expiry and maintenance schedules
Device Assistant by the numbers
- 8 all-time installs (skills.sh)
- Ranked #2,242 of 3,280 Productivity & Planning skills by installs in the Skillselion catalog
- Data as of Jul 30, 2026 (Skillselion catalog sync)
device-assistant capabilities & compatibility
- Capabilities
- error lookup · troubleshooting · warranty tracking
- Use cases
- research · web search
- Platforms
- Linux · macOS · Windows
What device-assistant says it does
Personal device manager with error code lookup, troubleshooting, and maintenance tracking.
npx skills add https://github.com/bighardperson/computer-science-skills-collection --skill device-assistantAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 8 |
|---|---|
| repo stars | ★ 33 |
| Last updated | April 26, 2026 |
| Repository | bighardperson/computer-science-skills-collection ↗ |
What it does
Track home devices and look up appliance error codes for step-by-step troubleshooting.
Who is it for?
Managing home appliances and getting fixes when a device shows an error code.
When should I use this skill?
A device shows an error, you need a manual, or you want to check warranty or maintenance.
What you get
- devices.json registry
- error-history.json
- maintenance-log.json
By the numbers
- 11 handler commands
- 7 device categories
Files
Device Assistant 🔧
Personal device manager with error code lookup, troubleshooting, and maintenance tracking.
Features
- Device Registry: Track all devices with model, serial, purchase info
- Error Lookup: Instant error code explanations
- Troubleshooting: Step-by-step solutions
- Manual Links: Quick access to documentation
- Warranty Tracking: Know when warranties expire
- Maintenance Reminders: Filter changes, updates, etc.
Commands
| Command | Action |
|---|---|
/device | List all devices or show status |
/device add | Add a new device (interactive) |
/device list [category] | List devices by category |
/device info <name> | Show device details |
/device error <name> <code> | Lookup error code |
/device help <name> <problem> | Troubleshoot a problem |
/device manual <name> | Get manual/documentation |
/device warranty | Show warranty status |
/device maintenance | Show maintenance schedule |
/device remove <name> | Remove a device |
Natural Language
The skill understands natural queries:
- "Mein Geschirrspüler zeigt E24"
- "Waschmaschine macht komische Geräusche"
- "Wo ist die Anleitung für den Thermomix?"
- "Wann läuft die Garantie vom TV aus?"
Device Categories
| Category | Examples |
|---|---|
kitchen | Geschirrspüler, Kühlschrank, Backofen, Thermomix |
laundry | Waschmaschine, Trockner |
electronics | TV, Router, NAS, Computer |
climate | Heizung, Klimaanlage, Luftreiniger |
smart-home | Hue, Homematic, Sensoren |
software | Apps, Betriebssysteme, Lizenzen |
other | Alles andere |
Handler Commands
handler.sh status $WORKSPACE # Overview
handler.sh list [category] $WORKSPACE # List devices
handler.sh add <json> $WORKSPACE # Add device
handler.sh info <device-id> $WORKSPACE # Device details
handler.sh error <device-id> <code> $WORKSPACE # Error lookup
handler.sh troubleshoot <device-id> <problem> $WS # Get help
handler.sh manual <device-id> $WORKSPACE # Manual link
handler.sh warranty $WORKSPACE # Warranty overview
handler.sh maintenance $WORKSPACE # Maintenance due
handler.sh update <device-id> <json> $WORKSPACE # Update device
handler.sh remove <device-id> $WORKSPACE # Remove device
handler.sh search <query> $WORKSPACE # Search devices
handler.sh log <device-id> <note> $WORKSPACE # Add maintenance logData Structure
Device Entry
{
"id": "dishwasher-1",
"name": "Geschirrspüler",
"nickname": "Spüli",
"category": "kitchen",
"manufacturer": "Siemens",
"model": "SN658X06TE",
"serialNumber": "ABC123456",
"purchaseDate": "2022-03-15",
"purchasePrice": 899,
"warranty": {
"expires": "2025-03-15",
"type": "manufacturer",
"notes": "3 Jahre Siemens"
},
"manualUrl": "https://...",
"supportUrl": "https://...",
"location": "Küche",
"notes": "Salz alle 2 Monate nachfüllen",
"maintenance": [
{"task": "Filter reinigen", "interval": "monthly", "lastDone": "2026-01-01"}
],
"errorHistory": [],
"addedAt": "2024-01-01"
}Error Code Lookup
The skill searches for error codes using:
1. Built-in database for common manufacturers 2. Web search for specific model + error code 3. Manual extraction if manual URL is stored
Common Error Code Patterns
| Manufacturer | Pattern | Example |
|---|---|---|
| Siemens/Bosch | E + number | E24, E15 |
| Miele | F + number | F11, F53 |
| AEG | E + number | E10, E20 |
| Samsung | Letters + numbers | UE, OE, LE |
| LG | Letters | OE, IE, PE |
Example Session
User: Ich habe einen neuen Geschirrspüler
Bot: 🔧 Neues Gerät hinzufügen:
Welche Infos hast du?
• Hersteller?
• Modell?
• Seriennummer? (optional)
• Kaufdatum?
User: Siemens SN658X06TE, gekauft am 15.3.2022
Bot: ✅ Gespeichert!
📦 Geschirrspüler (Siemens SN658X06TE)
📅 Gekauft: 15.03.2022
🛡️ Garantie: bis 15.03.2025 (ABGELAUFEN)
📄 Anleitung: [Link gefunden]
Spitzname vergeben? (z.B. "Spüli")User: Mein Geschirrspüler zeigt E24
Bot: 🔧 Siemens SN658X06TE — Fehler E24
⚠️ Bedeutung: Abpumpproblem
Das Wasser wird nicht richtig abgepumpt.
🔨 Lösung:
1. Gerät ausschalten
2. Sieb am Boden prüfen und reinigen
3. Abflussschlauch auf Knicke prüfen
4. Siphon-Anschluss kontrollieren
5. Gerät neu starten
📄 Details: Anleitung S. 45
[Problem gelöst] [Weitere Hilfe]Data Files
Stored in $WORKSPACE/memory/device-assistant/:
| File | Purpose |
|---|---|
devices.json | All registered devices |
error-history.json | Past errors and solutions |
maintenance-log.json | Maintenance history |
error-codes/ | Cached error code info |
Warranty Alerts
The skill can remind you before warranties expire:
⚠️ Garantie-Warnung:
Diese Geräte laufen bald ab:
• TV Samsung (noch 30 Tage)
• Waschmaschine (noch 45 Tage)
Tipp: Jetzt prüfen ob alles funktioniert!Requirements
jq(JSON processing)curl(web lookups)- Internet for error code search
{
"ownerId": "kn77fv9851hjcqe52zqx0bhhbx7z680h",
"slug": "device-assistant",
"version": "1.0.0",
"publishedAt": 1769433983734
}{
"slug": "device-assistant",
"name": "Device Assistant",
"version": "1.0.0",
"installedAt": 1776152380982,
"source": "skillhub"
}#!/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