Expose all events from an Amcrest device to an MQTT broker
You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
Go to file
Jeff Culverhouse 94a4297665 refactor: fully async device setup and improved SDK value handling
- Converted device initialization and state building to async coroutines
- Parallelized Amcrest camera connections using asyncio.gather
- Added clean_value() helper for tuple/list/string SDK outputs
- Added fallback for missing DefaultInterface in network config
- Improved error handling, timeouts, and type annotations
- Verified code quality (ruff, black, mypy all passing)
3 months ago
.github fix: add last_device_check sensor; fix service status; only post messages on changes 3 months ago
src refactor: fully async device setup and improved SDK value handling 3 months ago
tools feat!: complete MQTT and service refactor, add timestamp + event tracking, and new modular mixins 3 months ago
.dockerignore feat!: complete MQTT and service refactor, add timestamp + event tracking, and new modular mixins 3 months ago
.gitignore feature: move things around, cleaner code 3 months ago
.releaserc chore: skip invalid PR references 4 months ago
.trivyignore feature: move things around, cleaner code 3 months ago
CHANGELOG.md chore(release): 2.1.0 [skip ci] 3 months ago
Dockerfile fix: mkdir /media to prep for mounted volume 3 months ago
LICENSE Initial commit 5 years ago
README.md feature: add reboot button, fix other switches 3 months ago
VERSION chore: update VERSION to v2.1.0 3 months ago
config.yaml.sample feature: added max_size (MB) to 'media' config section 3 months ago
docker-compose.yaml chore: no need for timezone in config, just set in ENV; update sample files and README 3 months ago
package-lock.json chore: needed to add dev-deps 4 months ago
package.json chore: needed to add dev-deps 4 months ago
pyproject.toml feature: add reboot button, fix other switches 3 months ago
requirements.txt add support for config.yaml; sample config; revamp config 12 months ago
uv.lock refactor: fully async device setup and improved SDK value handling 3 months ago

README.md

weirdtangent/amcrest2mqtt

Expose multiple Amcrest cameras and events to an MQTT broker, primarily designed to work with Home Assistant. Uses the python-amcrest library.

Forked from dchesterton/amcrest2mqtt

UPDATES:

  • 10/2025 Added a "media" config where mp4 recordings of motions events can be stored (11/2025 now with "max_size" option)
  • 10/2025 "Rediscover" button added to service - when pressed, device discovery is re-run so HA will rediscover deleted devices

Docker

For docker-compose, use the configuration included in this repository.

An docker image is available at graystorm/amcrest2mqtt:latest. You can mount your configuration volume at /config (and see the included config.yaml.sample file) or use the ENV variables:

It supports the following environment variables:

  • AMCREST_HOSTS (required, 1+ space-separated list of hostnames/ips)

  • AMCREST_NAMES (required, 1+ space-separated list of device names - must match count of AMCREST_HOSTS)

  • AMCREST_PORT (optional, default = 80)

  • AMCREST_USERNAME (optional, default = admin)

  • AMCREST_PASSWORD (required)

  • AMCREST_WEBRTC_HOST (optional, webrtc hostname for link, but then link/sources below become required:)

  • AMCREST_WEBRTC_PORT (webrtc port, default = 1984)

  • AMCREST_WEBRTC_LINK (webrtc stream link, default = 'stream.html')

  • AMCREST_WEBRTC_SOURCES (webrtc "Source" param for each camera, same count and order of AMCREST_HOSTS above)

  • MQTT_USERNAME (required)

  • MQTT_PASSWORD (optional, default = empty password)

  • MQTT_HOST (optional, default = 'localhost')

  • MQTT_QOS (optional, default = 0)

  • MQTT_PORT (optional, default = 1883)

  • MQTT_TLS_ENABLED (required if using TLS) - set to true to enable

  • MQTT_TLS_CA_CERT (required if using TLS) - path to the ca certs

  • MQTT_TLS_CERT (required if using TLS) - path to the private cert

  • MQTT_TLS_KEY (required if using TLS) - path to the private key

  • MQTT_PREFIX (optional, default = amgrest2mqtt)

  • MQTT_DISCOVERY_PREFIX (optional, default = 'homeassistant')

  • MEDIA_PATH (optional) - path to store motion recordings (mp4) files

  • MEDIA_SOURCE (optional) - HomeAssistant url for accessing those recordings (see config.yaml.sample)

  • STORAGE_UPDATE_INTERVAL (optional, default = 900) - how often to fetch storage stats (in seconds)

  • SNAPSHOT_UPDATE_INTERVAL (optional, default = 60) - how often to fetch camera snapshot (in seconds)

It exposes through device discovery a service and a device with components for each camera:

  • homeassistant/device/amcrest-service - service config

  • homeassistant/device/amcrest-[SERIAL_NUMBER] per camera, with components:

  • event - most all "other" events, not exposed below

  • camera - a snapshot is saved every SNAPSHOT_UPDATE_INTERVAL (also based on how often camera saves snapshot image), also an "eventshot" is stored at the time an "event" is triggered in the camera. This is collected by filename, when the Amcrest camera logs a snapshot was saved because of an event (rather than just a routine timed snapshot)

  • doorbell - doorbell status (if AD110 or AD410)

  • human - human detection (if AD410)

  • motion - motion events (if supported)

  • config - device configuration information

  • storage - storage stats

  • privacy_mode - get (and set) the privacy mode switch of the camera

  • motion_detection - get (and set) the motion detection switch of the camera

Snapshots/Eventshots plus Home Assistant Area Cards

The camera snapshots work really well for the HomeAssistant Area cards on a dashboard - just make this MQTT camera device the only camera for an area and place an Area card for that location.

An "event snapshot" (eventshot) is separately (and specifically, by filename) collected when the camera automatically records a snapshot because of an event. Note, that if the Amcrest camera is configured to record 3 or 5 snapshots on an event - each of those will be updated by amcrest2mqtt and you will very quickly end up with (only) the last snapshot stored. This might alter you decision on how to configure your camera for this setting. (Or perhaps I can turn the snapshots-for-an-event into an animated image on the HA-side, thought that seems like overkill.)

WebRTC

The WebRTC option works very well with the go2rtc package which is a streaming server that works very well for (my) Amcrest cameras. If you setup the WebRTC config here, the configuration_url for the MQTT device will be the streaming RTC link instead of just a link to the hostname (which is arguably a more correct "configuration" url, but I'd rather have a simple link from the device page to jump to a live stream).

Device Support

The app supports events for any Amcrest device supported by python-amcrest.

Home Assistant

The app has built-in support for Home Assistant discovery. Set the MQTT_HOMEASSISTANT environment variable to true to enable support. If you are using a different MQTT prefix to the default, you will need to set the MQTT_DISCOVERY_PREFIX environment variable.

Running the app

To run via env variables with Docker Compose, see docker-compose.yaml or make sure you attach a volume with the config file and point to that directory, for example:

CMD [ "python", "-u", "./app.py", "-c", "/config" ]

Mounted Volume Permissions (Synology)

If you mount a host folder into /media for saving recordings, ensure the container has write access. On Synology NAS, shared folders use ACLs that can block Docker containers even when chmod 777 appears open.

To reset permissions and make the volume writable by the containers default user (uid=1000, gid=1000), run the following via SSH:

sudo synoacltool -del /volume1/photo/Amcrest
sudo chmod 777 /volume1/photo/Amcrest
sudo chown 1000:1000 /volume1/photo/Amcrest

Then verify inside the container:

docker exec -it amcrest2mqtt ls -ld /media

You should see permissions like:

drwxrwxrwx 1 appuser appuser ... /media

Once configured correctly, you should see new recordings appear in your mounted folder with ownership 1000:1000 and a symlink to the latest file.

Also, make sure you have

environment:
  - TZ=America/New_York

in your docker-compose if you want the recording filenames to by local time and not UTC.

Out of Scope

Non-Docker Environments

Docker is the only supported way of deploying the application. The app should run directly via Python but this is not supported.

See also

Buy Me A Coffee

A few people have kindly requested a way to donate a small amount of money. If you feel so inclined I've set up a "Buy Me A Coffee" page where you can donate a small sum. Please do not feel obligated to donate in any way - I work on the app because it's useful to myself and others, not for any financial gain - but any token of appreciation is much appreciated 🙂

Buy Me A Coffee

How Happy am I?