Here’s the DSL working version using Grok to help me code/debug it.
Create an account with https://platform.openai.com/ and grab API key and fund it (low as $5/month)
Script (analyze_image.sh)
#!/usr/bin/env bash
# Usage:
# ./analyze_image.sh /path/to/your/image.jpg "Describe exactly what is happening in this image"
# ────────────────────────────────────────────────────────────────────────────────
# Configuration - CHANGE THESE
# ────────────────────────────────────────────────────────────────────────────────
OPENAI_API_KEY="<your API key>"
MODEL="gpt-4o-mini" # or gpt-4o, gpt-4-turbo
MAX_TOKENS=300
# ────────────────────────────────────────────────────────────────────────────────
# Check arguments
# ────────────────────────────────────────────────────────────────────────────────
if [ $# -lt 2 ]; then
echo "Usage: $0 <image_file> <prompt>"
echo "Example:"
echo " $0 ./snapshot.jpg 'Describe exactly what is happening. Be specific about people, objects and actions.'"
exit 1
fi
IMAGE_PATH="$1"
PROMPT="$2"
# Check if file exists and is readable
if [ ! -f "$IMAGE_PATH" ] || [ ! -r "$IMAGE_PATH" ]; then
echo "Error: File not found or not readable: $IMAGE_PATH"
exit 1
fi
# ────────────────────────────────────────────────────────────────────────────────
# Convert image to base64
# ────────────────────────────────────────────────────────────────────────────────
# Detect mime type (jpg, png, webp, etc.)
MIME_TYPE=$(file --mime-type -b "$IMAGE_PATH")
# Most common fallback
if [[ "$MIME_TYPE" == *"jpeg"* ]]; then
MIME="image/jpeg"
elif [[ "$MIME_TYPE" == *"png"* ]]; then
MIME="image/png"
elif [[ "$MIME_TYPE" == *"webp"* ]]; then
MIME="image/webp"
else
MIME="image/jpeg" # default - OpenAI is quite forgiving
fi
BASE64_IMAGE=$(base64 -w 0 "$IMAGE_PATH")
# ────────────────────────────────────────────────────────────────────────────────
# Build JSON payload
# ────────────────────────────────────────────────────────────────────────────────
JSON_PAYLOAD=$(cat <<EOF
{
"model": "$MODEL",
"messages": [
{
"role": "user",
"content": [
{
"type": "text",
"text": "$PROMPT"
},
{
"type": "image_url",
"image_url": {
"url": "data:$MIME;base64,$BASE64_IMAGE"
}
}
]
}
],
"max_tokens": $MAX_TOKENS
}
EOF
)
# ────────────────────────────────────────────────────────────────────────────────
# Send request to OpenAI
# ────────────────────────────────────────────────────────────────────────────────
echo "Sending request to OpenAI... (image size: $(($(stat -c%s "$IMAGE_PATH") / 1024)) KB)"
RESPONSE=$(curl -s -X POST https://api.openai.com/v1/chat/completions \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $OPENAI_API_KEY" \
-d "$JSON_PAYLOAD")
# ────────────────────────────────────────────────────────────────────────────────
# Pretty print the answer (requires jq installed)
# ────────────────────────────────────────────────────────────────────────────────
if command -v jq >/dev/null 2>&1; then
ANSWER=$(echo "$RESPONSE" | jq -r '.choices[0].message.content // .error.message // "No answer"')
echo -e "\nAnswer:\n"
echo "$ANSWER"
else
echo "Response (raw - install jq for pretty output):"
echo "$RESPONSE" | grep -A 10 '"content"' || echo "$RESPONSE"
fi
# Optional: save full response
# echo "$RESPONSE" > response_$(date +%Y%m%d_%H%M%S).json
Item:
Switch AI_Switch "AI Switch [%s]" (HomeState)
String AI_Results "AI Results [%s]" (HomeState)
Rule: (attachmentFront = full path of image including image name)
var String results51 = "NULL"
AI_Results.postUpdate('OpenAI returned NO results.')
if (AI_Switch.state == ON) {
try {
results51 = executeCommandLine(Duration.ofSeconds(10), "/bin/bash", "/etc/openhab/scripts/analyze_image.sh", attachmentFront, "Describe exactly what is happening in this image. Be very specific about people, clothing, objects and any unusual activity.")
if (results51 !== null && results51 != NULL && results51.toString() != '') {
AI_Results.postUpdate(results51)
logInfo("OPENAI",results51)
}
} catch (Exception u5) { logError("OPENAI","openAI picture analysis FAILED via CURL. Exception is " + u5.getMessage) }
}
Example of the results from it:
Sending request to OpenAI… (image size: 43 KB)
Answer:
In the image, it appears to show a residential area during the morning hours. There is a driveway leading to a house, with a front lawn that has sparse grass and some bushes.
A person is seen standing on the driveway, wearing a green long-sleeve shirt and beige shorts. The individual is facing away from the camera and appears to be looking towards the street.
There is a vehicle parked in the street, which is a blue car. The surroundings indicate it might be winter, as a few patches of snow are visible on the grass. Near the left side of the image, an American flag is positioned on a pole. The overall scene is quiet, with no other notable activity occurring.
Best, Jay