1
0
mirror of synced 2026-03-30 14:23:46 +00:00
This commit is contained in:
Cam Soper
2022-02-10 14:38:53 -06:00
6 changed files with 107 additions and 16 deletions

View File

@@ -12,17 +12,16 @@ jobs:
runs-on: ubuntu-20.04
steps:
- name: Checkout code
uses: actions/checkout@v2.3.4
uses: actions/checkout@v2.4.0
- name: Bump version
uses: remorses/bump-version@js
id: version
with:
version_file: ./VERSION
github_token: ${{ secrets.GITHUB_TOKEN }}
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Checkout code
uses: actions/checkout@v2.3.4
uses: actions/checkout@v2.4.0
with:
ref: main
- name: Set up QEMU
@@ -30,14 +29,14 @@ jobs:
with:
platforms: linux/386,linux/amd64,linux/arm/v6,linux/arm/v7,linux/arm64/v8,linux/ppc64le,linux/s390x
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v1.5.1
uses: docker/setup-buildx-action@v1.6.0
- name: Login to DockerHub
uses: docker/login-action@v1.10.0
uses: docker/login-action@v1.12.0
with:
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_PASSWORD }}
- name: Build and push
uses: docker/build-push-action@v2.6.1
uses: docker/build-push-action@v2.7.0
with:
context: .
push: true

View File

@@ -8,6 +8,7 @@ COPY requirements.txt /
RUN pip install --no-warn-script-location --prefix=/install -r /requirements.txt
FROM base
STOPSIGNAL SIGINT
COPY --from=builder /install /usr/local
COPY src /app
COPY VERSION /app

View File

@@ -22,6 +22,7 @@ It supports the following environment variables:
- `HOME_ASSISTANT` (optional, default = false)
- `HOME_ASSISTANT_PREFIX` (optional, default = 'homeassistant')
- `STORAGE_POLL_INTERVAL` (optional, default = 3600) - how often to fetch storage data (in seconds)
- `DEVICE_NAME` (optional) - override the default device name used in the Amcrest app
It exposes events to the following topics:
@@ -29,6 +30,7 @@ It exposes events to the following topics:
- `amcrest2mqtt/[SERIAL_NUMBER]/doorbell` - doorbell status (if AD110 or AD410)
- `amcrest2mqtt/[SERIAL_NUMBER]/human` - human detection (if AD410)
- `amcrest2mqtt/[SERIAL_NUMBER]/motion` - motion events (if supported)
- `amcrest2mqtt/[SERIAL_NUMBER]/config` - device configuration information
## Device Support
@@ -63,7 +65,7 @@ services:
### Multiple Devices
The app will not support multiple devices. You can run multiple instances of the app if you need to expose events for multiple devies.
The app will not support multiple devices. You can run multiple instances of the app if you need to expose events for multiple devices.
### Non-Docker Environments

View File

@@ -1 +1 @@
1.0.9
1.0.15

View File

@@ -1,3 +1,3 @@
amcrest==1.8.0
paho-mqtt==1.5.1
amcrest==1.9.3
paho-mqtt==1.6.1
python-slugify==5.0.2

View File

@@ -17,8 +17,10 @@ amcrest_host = os.getenv("AMCREST_HOST")
amcrest_port = int(os.getenv("AMCREST_PORT") or 80)
amcrest_username = os.getenv("AMCREST_USERNAME") or "admin"
amcrest_password = os.getenv("AMCREST_PASSWORD")
storage_poll_interval = int(os.getenv("STORAGE_POLL_INTERVAL") or 3600)
camera_ping_enabled = os.getenv("CAMERA_PING_ENABLED") == "true"
device_name = os.getenv("DEVICE_NAME")
mqtt_host = os.getenv("MQTT_HOST") or "localhost"
mqtt_qos = int(os.getenv("MQTT_QOS") or 0)
@@ -93,12 +95,16 @@ def refresh_storage_sensors():
try:
storage = camera.storage_all
mqtt_publish(topics["storage_used_percent"], str(storage["used_percent"]))
mqtt_publish(topics["storage_used"], str(storage["used"][0]))
mqtt_publish(topics["storage_total"], str(storage["total"][0]))
mqtt_publish(topics["storage_used"], to_gb(storage["used"]))
mqtt_publish(topics["storage_total"], to_gb(storage["total"]))
except AmcrestError as error:
log(f"Error fetching storage information {error}", level="WARNING")
def to_gb(total):
return str(round(float(total[0]) / 1024 / 1024 / 1024, 2))
def ping_camera():
Timer(30, ping_camera).start()
response = os.system(f"ping -c1 -W100 {amcrest_host} >/dev/null 2>&1")
@@ -150,9 +156,16 @@ try:
is_ad110 = device_type == "AD110"
is_ad410 = device_type == "AD410"
is_doorbell = is_ad110 or is_ad410
serial_number = camera.serial_number.strip()
serial_number = camera.serial_number
if not isinstance(serial_number, str):
log(f"Error fetching serial number", level="ERROR")
exit_gracefully(1)
sw_version = camera.software_information[0].replace("version=", "").strip()
if not device_name:
device_name = camera.machine_name.replace("name=", "").strip()
device_slug = slugify(device_name, separator="_")
except AmcrestError as error:
log(f"Error fetching camera details", level="ERROR")
@@ -174,13 +187,27 @@ topics = {
"storage_used": f"amcrest2mqtt/{serial_number}/storage/used",
"storage_used_percent": f"amcrest2mqtt/{serial_number}/storage/used_percent",
"storage_total": f"amcrest2mqtt/{serial_number}/storage/total",
"home_assistant": {
"home_assistant_legacy": {
"doorbell": f"{home_assistant_prefix}/binary_sensor/amcrest2mqtt-{serial_number}/{device_slug}_doorbell/config",
"human": f"{home_assistant_prefix}/binary_sensor/amcrest2mqtt-{serial_number}/{device_slug}_human/config",
"motion": f"{home_assistant_prefix}/binary_sensor/amcrest2mqtt-{serial_number}/{device_slug}_motion/config",
"storage_used": f"{home_assistant_prefix}/sensor/amcrest2mqtt-{serial_number}/{device_slug}_storage_used/config",
"storage_used_percent": f"{home_assistant_prefix}/sensor/amcrest2mqtt-{serial_number}/{device_slug}_storage_used_percent/config",
"storage_total": f"{home_assistant_prefix}/sensor/amcrest2mqtt-{serial_number}/{device_slug}_storage_total/config",
"version": f"{home_assistant_prefix}/sensor/amcrest2mqtt-{serial_number}/{device_slug}_version/config",
"host": f"{home_assistant_prefix}/sensor/amcrest2mqtt-{serial_number}/{device_slug}_host/config",
"serial_number": f"{home_assistant_prefix}/sensor/amcrest2mqtt-{serial_number}/{device_slug}_serial_number/config",
},
"home_assistant": {
"doorbell": f"{home_assistant_prefix}/binary_sensor/amcrest2mqtt-{serial_number}/doorbell/config",
"human": f"{home_assistant_prefix}/binary_sensor/amcrest2mqtt-{serial_number}/human/config",
"motion": f"{home_assistant_prefix}/binary_sensor/amcrest2mqtt-{serial_number}/motion/config",
"storage_used": f"{home_assistant_prefix}/sensor/amcrest2mqtt-{serial_number}/storage_used/config",
"storage_used_percent": f"{home_assistant_prefix}/sensor/amcrest2mqtt-{serial_number}/storage_used_percent/config",
"storage_total": f"{home_assistant_prefix}/sensor/amcrest2mqtt-{serial_number}/storage_total/config",
"version": f"{home_assistant_prefix}/sensor/amcrest2mqtt-{serial_number}/version/config",
"host": f"{home_assistant_prefix}/sensor/amcrest2mqtt-{serial_number}/host/config",
"serial_number": f"{home_assistant_prefix}/sensor/amcrest2mqtt-{serial_number}/serial_number/config",
},
}
@@ -236,6 +263,9 @@ if home_assistant:
}
if is_doorbell:
doorbell_name = "Doorbell" if device_name == "Doorbell" else f"{device_name} Doorbell"
mqtt_publish(topics["home_assistant_legacy"]["doorbell"], "")
mqtt_publish(
topics["home_assistant"]["doorbell"],
base_config
@@ -243,13 +273,15 @@ if home_assistant:
"state_topic": topics["doorbell"],
"payload_on": "on",
"payload_off": "off",
"name": f"{device_name} Doorbell",
"icon": "mdi:doorbell",
"name": doorbell_name,
"unique_id": f"{serial_number}.doorbell",
},
json=True,
)
if is_ad410:
mqtt_publish(topics["home_assistant_legacy"]["human"], "")
mqtt_publish(
topics["home_assistant"]["human"],
base_config
@@ -264,6 +296,7 @@ if home_assistant:
json=True,
)
mqtt_publish(topics["home_assistant_legacy"]["motion"], "")
mqtt_publish(
topics["home_assistant"]["motion"],
base_config
@@ -278,7 +311,56 @@ if home_assistant:
json=True,
)
mqtt_publish(topics["home_assistant_legacy"]["version"], "")
mqtt_publish(
topics["home_assistant"]["version"],
base_config
| {
"state_topic": topics["config"],
"value_template": "{{ value_json.sw_version }}",
"icon": "mdi:package-up",
"name": f"{device_name} Version",
"unique_id": f"{serial_number}.version",
"entity_category": "diagnostic",
"enabled_by_default": False
},
json=True,
)
mqtt_publish(topics["home_assistant_legacy"]["serial_number"], "")
mqtt_publish(
topics["home_assistant"]["serial_number"],
base_config
| {
"state_topic": topics["config"],
"value_template": "{{ value_json.serial_number }}",
"icon": "mdi:alphabetical-variant",
"name": f"{device_name} Serial Number",
"unique_id": f"{serial_number}.serial_number",
"entity_category": "diagnostic",
"enabled_by_default": False
},
json=True,
)
mqtt_publish(topics["home_assistant_legacy"]["host"], "")
mqtt_publish(
topics["home_assistant"]["host"],
base_config
| {
"state_topic": topics["config"],
"value_template": "{{ value_json.host }}",
"icon": "mdi:ip-network",
"name": f"{device_name} Host",
"unique_id": f"{serial_number}.host",
"entity_category": "diagnostic",
"enabled_by_default": False
},
json=True,
)
if storage_poll_interval > 0:
mqtt_publish(topics["home_assistant_legacy"]["storage_used_percent"], "")
mqtt_publish(
topics["home_assistant"]["storage_used_percent"],
base_config
@@ -287,11 +369,14 @@ if home_assistant:
"unit_of_measurement": "%",
"icon": "mdi:micro-sd",
"name": f"{device_name} Storage Used %",
"object_id": f"{device_slug}_storage_used_percent",
"unique_id": f"{serial_number}.storage_used_percent",
"entity_category": "diagnostic",
},
json=True,
)
mqtt_publish(topics["home_assistant_legacy"]["storage_used"], "")
mqtt_publish(
topics["home_assistant"]["storage_used"],
base_config
@@ -301,10 +386,12 @@ if home_assistant:
"icon": "mdi:micro-sd",
"name": f"{device_name} Storage Used",
"unique_id": f"{serial_number}.storage_used",
"entity_category": "diagnostic",
},
json=True,
)
mqtt_publish(topics["home_assistant_legacy"]["storage_total"], "")
mqtt_publish(
topics["home_assistant"]["storage_total"],
base_config
@@ -314,6 +401,7 @@ if home_assistant:
"icon": "mdi:micro-sd",
"name": f"{device_name} Storage Total",
"unique_id": f"{serial_number}.storage_total",
"entity_category": "diagnostic",
},
json=True,
)
@@ -326,6 +414,7 @@ mqtt_publish(topics["config"], {
"device_name": device_name,
"sw_version": sw_version,
"serial_number": serial_number,
"host": amcrest_host,
}, json=True)
if storage_poll_interval > 0: