No description
  • PHP 66.7%
  • Shell 19.8%
  • JavaScript 13.5%
Find a file
Stefan Maier b713a995c2
All checks were successful
release / build_release (release) Successful in 1m19s
update to 1.0.4, adding auto reloader
2026-03-11 11:28:16 +01:00
.forgejo/workflows update CI/CD 2026-02-25 12:22:45 +01:00
assets docs update 2026-02-25 15:52:38 +01:00
wp-camera-snapshots update to 1.0.4, adding auto reloader 2026-03-11 11:28:16 +01:00
.gitignore expose only b64 images to rprevent 2026-02-25 15:03:07 +01:00
build-plugin.sh update to 1.0.4, adding auto reloader 2026-03-11 11:28:16 +01:00
BUILD.md update to release version 1.0.0 2026-02-25 12:00:16 +01:00
README.md update to 1.0.4, adding auto reloader 2026-03-11 11:28:16 +01:00
TEST.md update to release version 1.0.0 2026-02-25 12:00:16 +01:00
test.sh update to release version 1.0.0 2026-02-25 12:00:16 +01:00

WP Camera Snapshots

WP Camera Snapshots is a WordPress plugin that accepts periodic snapshot uploads from network cameras via the REST API and displays the latest image on the frontend via shortcode and Gutenberg block. Images are stored on the filesystem inside the plugins storage directory and are rendered on the frontend as inline base64encoded images (data URIs) rather than direct file URLs. This avoids serverside errors caused by webserver rules that block access to plugin directories. The display can fall back to a global or percamera image (or the bundled offline image) when the latest snapshot is unavailable or stale.

1. Requirements

  • WordPress 6.9 or newer
  • PHP 8.1 or newer
  • Node.js + npm (for building the Gutenberg block in development)

2. Building the plugin

For detailed build instructions, see BUILD.md. In short:

cd /path/to/wp_camera_plugin
chmod +x build-plugin.sh
./build-plugin.sh        # debug build → wp-camera-snapshots-dev.zip

# For a release build (e.g. 1.0.0):
export RELEASE_VERSION=1.0.0
./build-plugin.sh        # release build → wp-camera-snapshots-1.0.0.zip

This will:

  • Install the JS build tooling in wp-camera-snapshots/ if missing
  • Build the block assets into wp-camera-snapshots/build/
  • Copy assets/camera_offline.png into wp-camera-snapshots/assets/
  • Compile translations (.po.mo) using msgfmt
  • Update plugin metadata (header, WPCS_VERSION, and openapi.json) to the chosen version (0.0.0-dev for debug builds or RELEASE_VERSION for releases)
  • Create wp-camera-snapshots-dev.zip or wp-camera-snapshots-<version>.zip in the project root, ready to upload

3. Installing in WordPress

  1. Log in to your WordPress admin.
  2. Navigate to Plugins → Add New → Upload Plugin.
  3. Upload wp-camera-snapshots.zip and click Install Now.
  4. Click Activate Plugin.

You can reupload a new zip with the same folder name to replace the existing plugin (WordPress will show a “replace current with uploaded” prompt).

4. Configuring cameras

  1. In the WP admin, go to Settings → Camera Snapshots.
  2. Global fallback image:
    • Click Select image to pick a global fallback from the Media Library.
    • A small preview shows the current selection.
  3. Cameras table:
    • Camera ID: a unique identifier (e.g. camera_entrance). This is used in the REST endpoint URL and shortcode/block attributes.
    • Filename (optional): base name for the snapshot file. When left empty, the camera ID is used as the base name. The plugin will automatically look for base.jpg, base.jpeg or base.png in its storage directory.
    • Fallback Attachment:
      • Click Select image to choose a percamera fallback from the Media Library.
      • The global fallback is used when no percamera fallback is set.

The plugin also ships a bundled offline image (assets/camera_offline.png) which is used as an ultimate fallback when no valid attachment fallback is available.

4.1 Rate limiting

Under Rate limiting in the settings you can configure a global rate limit window per camera:

  • Rate limit window per camera (seconds, 0 = disabled):
    • Default is 60 seconds.
    • If a camera sends snapshots more frequently than this window, additional requests will be rejected with HTTP 429 Too Many Requests.
    • Set to 0 to disable rate limiting entirely.

5. Data flow overview

The highlevel data flow from camera upload to browser rendering is illustrated in the following diagram:

WP Camera Snapshots data flow

6. Uploading snapshots (for camera developers)

  • REST endpoint:

    POST /wp-json/wp-camera-snapshots/v1/cameras/{camera_id}
    
  • Authentication:

    • Use a dedicated WordPress user with an Application Password.
    • Send HTTP Basic Auth over HTTPS.
  • Request:

    • Raw binary body (image/jpeg or image/png).
    • {camera_id} must match a configured camera ID in the settings.
  • Responses (examples):

    • 201 Created: snapshot stored successfully.
    • 400 Bad Request: missing/invalid payload.
    • 401 Unauthorized: invalid credentials.
    • 404 Not Found: unknown camera_id.
    • 429 Too Many Requests: rate limit exceeded for this camera.

6.1 Required user role / capability

The upload endpoint uses a permission check:

  • The authenticated user must have the upload_files capability.
  • In a default WordPress installation this means:
    • Allowed: Author, Editor, Administrator (and any custom role that can upload files).
    • Not allowed: Subscriber, Contributor.

For production use, it is recommended to create a dedicated lowprivilege user role with only the capabilities needed for this plugin (including upload_files) and use that account for Application Passwords.

See wp-camera-snapshots/openapi.json for a machinereadable API description.

7. Displaying snapshots

7.1 Shortcode

Use the shortcode in posts, pages, or widgets:

[camera id="camera_entrance" refresh="600" show_fallback="0"]

With automatic frontend updates enabled:

[camera id="camera_entrance" refresh="60" auto_update="1"]
  • id (required): camera ID as configured in the settings.
  • refresh (optional): freshness window in seconds (default 600).
  • show_fallback (optional): reserved for UI variations; currently affects only internal state, not markup.
  • auto_update (optional, default false): when truthy (1, true, yes, etc.), the snapshot is automatically refreshed on the frontend without reloading the entire page.
  • auto_update_interval (optional, default 0): interval in seconds for automatic frontend refreshes. When set to 0 or omitted while auto_update is enabled, the plugin reuses the refresh value as the autoupdate interval.
What is the freshness window?

Each camera snapshot is stored as a single image file on disk. The plugin checks how old this file is using its modification time:

  • If the file is younger than the freshness window, it is considered “fresh” and will be shown.
  • If the file is older than the freshness window, the plugin assumes the camera may be offline or not updating and will show the fallback image instead (percamera fallback, then global fallback, then the bundled offline image).

Examples:

  • refresh="60" → If no new snapshot arrives within 60 seconds, the frontend will switch to the fallback image.
  • refresh="0" or a very large value effectively disables staleness detection and will keep showing the last snapshot until it is replaced.

A short freshness window makes stale cameras visible quickly but may show the fallback image more often. A longer window is more tolerant of irregular uploads.

7.2 Gutenberg block

In the block editor:

  1. Add the “Camera Snapshot” block.
  2. In the block sidebar:
    • Set Camera ID to the configured camera ID.
    • Optionally adjust Refresh interval (seconds) (same meaning as the shortcode refresh attribute).
    • Optionally enable Automatically update image to refresh the snapshot on an interval without reloading the page.
    • Optionally set Autoupdate interval (seconds). When this is 0, the block reuses the Refresh interval (seconds) as the autoupdate interval.
    • Optionally enable Show fallback indicator when stale (used internally).

The block uses the same rendering logic as the shortcode, including freshness and fallback behavior.

8. Uninstall behavior

When the plugin is uninstalled via the WordPress Plugins screen:

  • The wpcs_settings option and storage configuration options are removed.
  • The snapshot storage directory (either under the plugin or under uploads/, depending on environment) and all stored snapshot files are deleted.
  • Media Library attachments used as fallbacks are not deleted.

9. How images are served (base64 data URIs)

On the frontend the plugin always embeds camera snapshots and fallback images as base64encoded data: URLs in the <img src="..."> attribute. This has two important consequences:

  • No direct HTTP access to the snapshot files is required. Even if the webserver forbids access to wp-content/plugins/wp-camera-snapshots/storage/, the page still renders correctly because the browser only sees an inline image.
  • Fewer serverside configuration surprises: you do not need to adjust .htaccess or webserver rules to allow public access to the storage directory; only PHP needs read access to the files.

The freshness window and fallback logic described above apply exactly the same way; only the transport from disk to browser changes (file → base64 in HTML).

10. Testing and diagnostics

  • For manual REST API tests (using curl) and detailed scenarios (happy path, wrong credentials, unsupported file types, unknown camera IDs), see TEST.md.
  • A helper script test.sh is provided to exercise the most common scenarios automatically against a local WordPress instance.