fix zero handling
This commit is contained in:
@@ -46,6 +46,20 @@ Compose builds the internal database URL from `MYSQL_USER`, `MYSQL_PASSWORD`,
|
|||||||
and `MYSQL_DATABASE`. Set `DATABASE_URL` only if you want to point the app at a
|
and `MYSQL_DATABASE`. Set `DATABASE_URL` only if you want to point the app at a
|
||||||
different database.
|
different database.
|
||||||
|
|
||||||
|
## Maintenance
|
||||||
|
|
||||||
|
Remove bad readings where temperature, humidity, and battery are all zero:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
scripts/remove_zero_readings.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
Preview the count without deleting:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
scripts/remove_zero_readings.sh --dry-run
|
||||||
|
```
|
||||||
|
|
||||||
## Reports
|
## Reports
|
||||||
|
|
||||||
Open `/reports` in the web app to generate a date-range summary. Use the
|
Open `/reports` in the web app to generate a date-range summary. Use the
|
||||||
|
|||||||
@@ -24,6 +24,10 @@ logger = logging.getLogger(__name__)
|
|||||||
SENSOR_DEVICE_TYPES = {"WoIOSensor"}
|
SENSOR_DEVICE_TYPES = {"WoIOSensor"}
|
||||||
|
|
||||||
|
|
||||||
|
def is_all_zero_reading(status: dict[str, Any]) -> bool:
|
||||||
|
return status.get("temperature") == 0 and status.get("humidity") == 0 and status.get("battery") == 0
|
||||||
|
|
||||||
|
|
||||||
def upsert_device(device_data: dict[str, Any]) -> None:
|
def upsert_device(device_data: dict[str, Any]) -> None:
|
||||||
device_id = device_data["deviceId"]
|
device_id = device_data["deviceId"]
|
||||||
with session_scope() as session:
|
with session_scope() as session:
|
||||||
@@ -55,6 +59,10 @@ def save_reading(device: Device, status: dict[str, Any]) -> None:
|
|||||||
logger.info("Skipping %s (%s): status has no temperature/humidity", device.name, device.id)
|
logger.info("Skipping %s (%s): status has no temperature/humidity", device.name, device.id)
|
||||||
return
|
return
|
||||||
|
|
||||||
|
if is_all_zero_reading(status):
|
||||||
|
logger.info("Skipping %s (%s): status is all zeros", device.name, device.id)
|
||||||
|
return
|
||||||
|
|
||||||
reading = Reading(
|
reading = Reading(
|
||||||
device_id=device.id,
|
device_id=device.id,
|
||||||
recorded_at=datetime.now(timezone.utc).replace(tzinfo=None),
|
recorded_at=datetime.now(timezone.utc).replace(tzinfo=None),
|
||||||
|
|||||||
Executable
+68
@@ -0,0 +1,68 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
usage() {
|
||||||
|
cat <<'USAGE'
|
||||||
|
Usage: scripts/remove_zero_readings.sh [--dry-run] [--yes]
|
||||||
|
|
||||||
|
Removes readings where temperature, humidity, and battery are all zero.
|
||||||
|
|
||||||
|
Options:
|
||||||
|
--dry-run Count matching readings without deleting them.
|
||||||
|
--yes Delete without prompting.
|
||||||
|
--help Show this help.
|
||||||
|
USAGE
|
||||||
|
}
|
||||||
|
|
||||||
|
dry_run=0
|
||||||
|
assume_yes=0
|
||||||
|
|
||||||
|
while [[ $# -gt 0 ]]; do
|
||||||
|
case "$1" in
|
||||||
|
--dry-run)
|
||||||
|
dry_run=1
|
||||||
|
;;
|
||||||
|
--yes|-y)
|
||||||
|
assume_yes=1
|
||||||
|
;;
|
||||||
|
--help|-h)
|
||||||
|
usage
|
||||||
|
exit 0
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
echo "Unknown option: $1" >&2
|
||||||
|
usage >&2
|
||||||
|
exit 2
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
shift
|
||||||
|
done
|
||||||
|
|
||||||
|
where_clause="temperature = 0 AND humidity = 0 AND battery = 0"
|
||||||
|
|
||||||
|
run_mysql() {
|
||||||
|
docker compose exec -T db sh -c 'MYSQL_PWD="$MYSQL_PASSWORD" exec mysql -u"$MYSQL_USER" "$MYSQL_DATABASE" "$@"' sh "$@"
|
||||||
|
}
|
||||||
|
|
||||||
|
matching_count=$(
|
||||||
|
printf 'SELECT COUNT(*) FROM readings WHERE %s;\n' "$where_clause" | run_mysql --batch --skip-column-names
|
||||||
|
)
|
||||||
|
|
||||||
|
echo "Found ${matching_count} all-zero reading(s)."
|
||||||
|
|
||||||
|
if [[ "$dry_run" -eq 1 || "$matching_count" -eq 0 ]]; then
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ "$assume_yes" -ne 1 ]]; then
|
||||||
|
read -r -p "Delete these readings? Type 'yes' to continue: " answer
|
||||||
|
if [[ "$answer" != "yes" ]]; then
|
||||||
|
echo "No records deleted."
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
printf 'DELETE FROM readings WHERE %s;\nSELECT ROW_COUNT();\n' "$where_clause" |
|
||||||
|
run_mysql --batch --skip-column-names |
|
||||||
|
tail -n 1 |
|
||||||
|
xargs printf 'Deleted %s all-zero reading(s).\n'
|
||||||
Reference in New Issue
Block a user