homesec 0.1.0__tar.gz → 0.1.1__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {homesec-0.1.0 → homesec-0.1.1}/.gitignore +1 -0
- homesec-0.1.1/.idea/.gitignore +3 -0
- homesec-0.1.1/.idea/homesec.iml +9 -0
- homesec-0.1.1/.idea/libraries/my_test_package.xml +9 -0
- homesec-0.1.1/.idea/misc.xml +6 -0
- homesec-0.1.1/.idea/modules.xml +8 -0
- homesec-0.1.1/.idea/vcs.xml +6 -0
- homesec-0.1.1/.idea/workspace.xml +57 -0
- {homesec-0.1.0 → homesec-0.1.1}/Makefile +6 -2
- {homesec-0.1.0 → homesec-0.1.1}/PKG-INFO +28 -1
- {homesec-0.1.0 → homesec-0.1.1}/README.md +27 -0
- {homesec-0.1.0 → homesec-0.1.1}/pyproject.toml +1 -1
- {homesec-0.1.0 → homesec-0.1.1}/src/homesec/__init__.py +1 -1
- {homesec-0.1.0 → homesec-0.1.1}/uv.lock +2 -2
- {homesec-0.1.0 → homesec-0.1.1}/.env.example +0 -0
- {homesec-0.1.0 → homesec-0.1.1}/AGENTS.md +0 -0
- {homesec-0.1.0 → homesec-0.1.1}/DESIGN.md +0 -0
- {homesec-0.1.0 → homesec-0.1.1}/LICENSE +0 -0
- {homesec-0.1.0 → homesec-0.1.1}/alembic/env.py +0 -0
- {homesec-0.1.0 → homesec-0.1.1}/alembic.ini +0 -0
- {homesec-0.1.0 → homesec-0.1.1}/config/example.yaml +0 -0
- {homesec-0.1.0 → homesec-0.1.1}/config/local.yaml +0 -0
- {homesec-0.1.0 → homesec-0.1.1}/config/production.yaml +0 -0
- {homesec-0.1.0 → homesec-0.1.1}/config/sample.yaml +0 -0
- {homesec-0.1.0 → homesec-0.1.1}/docker-compose.postgres.yml +0 -0
- {homesec-0.1.0 → homesec-0.1.1}/src/homesec/app.py +0 -0
- {homesec-0.1.0 → homesec-0.1.1}/src/homesec/cli.py +0 -0
- {homesec-0.1.0 → homesec-0.1.1}/src/homesec/config/__init__.py +0 -0
- {homesec-0.1.0 → homesec-0.1.1}/src/homesec/config/loader.py +0 -0
- {homesec-0.1.0 → homesec-0.1.1}/src/homesec/config/validation.py +0 -0
- {homesec-0.1.0 → homesec-0.1.1}/src/homesec/errors.py +0 -0
- {homesec-0.1.0 → homesec-0.1.1}/src/homesec/health/__init__.py +0 -0
- {homesec-0.1.0 → homesec-0.1.1}/src/homesec/health/server.py +0 -0
- {homesec-0.1.0 → homesec-0.1.1}/src/homesec/interfaces.py +0 -0
- {homesec-0.1.0 → homesec-0.1.1}/src/homesec/logging_setup.py +0 -0
- {homesec-0.1.0 → homesec-0.1.1}/src/homesec/maintenance/__init__.py +0 -0
- {homesec-0.1.0 → homesec-0.1.1}/src/homesec/maintenance/cleanup_clips.py +0 -0
- {homesec-0.1.0 → homesec-0.1.1}/src/homesec/models/__init__.py +0 -0
- {homesec-0.1.0 → homesec-0.1.1}/src/homesec/models/alert.py +0 -0
- {homesec-0.1.0 → homesec-0.1.1}/src/homesec/models/clip.py +0 -0
- {homesec-0.1.0 → homesec-0.1.1}/src/homesec/models/config.py +0 -0
- {homesec-0.1.0 → homesec-0.1.1}/src/homesec/models/events.py +0 -0
- {homesec-0.1.0 → homesec-0.1.1}/src/homesec/models/filter.py +0 -0
- {homesec-0.1.0 → homesec-0.1.1}/src/homesec/models/source.py +0 -0
- {homesec-0.1.0 → homesec-0.1.1}/src/homesec/models/storage.py +0 -0
- {homesec-0.1.0 → homesec-0.1.1}/src/homesec/models/vlm.py +0 -0
- {homesec-0.1.0 → homesec-0.1.1}/src/homesec/pipeline/__init__.py +0 -0
- {homesec-0.1.0 → homesec-0.1.1}/src/homesec/pipeline/alert_policy.py +0 -0
- {homesec-0.1.0 → homesec-0.1.1}/src/homesec/pipeline/core.py +0 -0
- {homesec-0.1.0 → homesec-0.1.1}/src/homesec/plugins/__init__.py +0 -0
- {homesec-0.1.0 → homesec-0.1.1}/src/homesec/plugins/alert_policies/__init__.py +0 -0
- {homesec-0.1.0 → homesec-0.1.1}/src/homesec/plugins/alert_policies/default.py +0 -0
- {homesec-0.1.0 → homesec-0.1.1}/src/homesec/plugins/alert_policies/noop.py +0 -0
- {homesec-0.1.0 → homesec-0.1.1}/src/homesec/plugins/analyzers/__init__.py +0 -0
- {homesec-0.1.0 → homesec-0.1.1}/src/homesec/plugins/analyzers/openai.py +0 -0
- {homesec-0.1.0 → homesec-0.1.1}/src/homesec/plugins/filters/__init__.py +0 -0
- {homesec-0.1.0 → homesec-0.1.1}/src/homesec/plugins/filters/yolo.py +0 -0
- {homesec-0.1.0 → homesec-0.1.1}/src/homesec/plugins/notifiers/__init__.py +0 -0
- {homesec-0.1.0 → homesec-0.1.1}/src/homesec/plugins/notifiers/mqtt.py +0 -0
- {homesec-0.1.0 → homesec-0.1.1}/src/homesec/plugins/notifiers/multiplex.py +0 -0
- {homesec-0.1.0 → homesec-0.1.1}/src/homesec/plugins/notifiers/sendgrid_email.py +0 -0
- {homesec-0.1.0 → homesec-0.1.1}/src/homesec/plugins/storage/__init__.py +0 -0
- {homesec-0.1.0 → homesec-0.1.1}/src/homesec/plugins/storage/dropbox.py +0 -0
- {homesec-0.1.0 → homesec-0.1.1}/src/homesec/plugins/storage/local.py +0 -0
- {homesec-0.1.0 → homesec-0.1.1}/src/homesec/plugins/utils.py +0 -0
- {homesec-0.1.0 → homesec-0.1.1}/src/homesec/py.typed +0 -0
- {homesec-0.1.0 → homesec-0.1.1}/src/homesec/repository/__init__.py +0 -0
- {homesec-0.1.0 → homesec-0.1.1}/src/homesec/repository/clip_repository.py +0 -0
- {homesec-0.1.0 → homesec-0.1.1}/src/homesec/sources/__init__.py +0 -0
- {homesec-0.1.0 → homesec-0.1.1}/src/homesec/sources/base.py +0 -0
- {homesec-0.1.0 → homesec-0.1.1}/src/homesec/sources/ftp.py +0 -0
- {homesec-0.1.0 → homesec-0.1.1}/src/homesec/sources/local_folder.py +0 -0
- {homesec-0.1.0 → homesec-0.1.1}/src/homesec/sources/rtsp.py +0 -0
- {homesec-0.1.0 → homesec-0.1.1}/src/homesec/state/__init__.py +0 -0
- {homesec-0.1.0 → homesec-0.1.1}/src/homesec/state/postgres.py +0 -0
- {homesec-0.1.0 → homesec-0.1.1}/src/homesec/storage_paths.py +0 -0
- {homesec-0.1.0 → homesec-0.1.1}/src/homesec/telemetry/__init__.py +0 -0
- {homesec-0.1.0 → homesec-0.1.1}/src/homesec/telemetry/db/__init__.py +0 -0
- {homesec-0.1.0 → homesec-0.1.1}/src/homesec/telemetry/db/log_table.py +0 -0
- {homesec-0.1.0 → homesec-0.1.1}/src/homesec/telemetry/db_log_handler.py +0 -0
- {homesec-0.1.0 → homesec-0.1.1}/src/homesec/telemetry/postgres_settings.py +0 -0
- {homesec-0.1.0 → homesec-0.1.1}/tests/__init__.py +0 -0
- {homesec-0.1.0 → homesec-0.1.1}/tests/conftest.py +0 -0
- {homesec-0.1.0 → homesec-0.1.1}/tests/homesec/__init__.py +0 -0
- {homesec-0.1.0 → homesec-0.1.1}/tests/homesec/conftest.py +0 -0
- {homesec-0.1.0 → homesec-0.1.1}/tests/homesec/mocks/__init__.py +0 -0
- {homesec-0.1.0 → homesec-0.1.1}/tests/homesec/mocks/event_store.py +0 -0
- {homesec-0.1.0 → homesec-0.1.1}/tests/homesec/mocks/filter.py +0 -0
- {homesec-0.1.0 → homesec-0.1.1}/tests/homesec/mocks/notifier.py +0 -0
- {homesec-0.1.0 → homesec-0.1.1}/tests/homesec/mocks/state_store.py +0 -0
- {homesec-0.1.0 → homesec-0.1.1}/tests/homesec/mocks/storage.py +0 -0
- {homesec-0.1.0 → homesec-0.1.1}/tests/homesec/mocks/vlm.py +0 -0
- {homesec-0.1.0 → homesec-0.1.1}/tests/homesec/test_alert_policy.py +0 -0
- {homesec-0.1.0 → homesec-0.1.1}/tests/homesec/test_app.py +0 -0
- {homesec-0.1.0 → homesec-0.1.1}/tests/homesec/test_cleanup_clips.py +0 -0
- {homesec-0.1.0 → homesec-0.1.1}/tests/homesec/test_clip_repository.py +0 -0
- {homesec-0.1.0 → homesec-0.1.1}/tests/homesec/test_clip_sources.py +0 -0
- {homesec-0.1.0 → homesec-0.1.1}/tests/homesec/test_config.py +0 -0
- {homesec-0.1.0 → homesec-0.1.1}/tests/homesec/test_dropbox_storage.py +0 -0
- {homesec-0.1.0 → homesec-0.1.1}/tests/homesec/test_event_store.py +0 -0
- {homesec-0.1.0 → homesec-0.1.1}/tests/homesec/test_health.py +0 -0
- {homesec-0.1.0 → homesec-0.1.1}/tests/homesec/test_integration.py +0 -0
- {homesec-0.1.0 → homesec-0.1.1}/tests/homesec/test_local_folder_deduplication.py +0 -0
- {homesec-0.1.0 → homesec-0.1.1}/tests/homesec/test_mqtt_notifier.py +0 -0
- {homesec-0.1.0 → homesec-0.1.1}/tests/homesec/test_notifiers.py +0 -0
- {homesec-0.1.0 → homesec-0.1.1}/tests/homesec/test_openai_vlm.py +0 -0
- {homesec-0.1.0 → homesec-0.1.1}/tests/homesec/test_pipeline.py +0 -0
- {homesec-0.1.0 → homesec-0.1.1}/tests/homesec/test_pipeline_events.py +0 -0
- {homesec-0.1.0 → homesec-0.1.1}/tests/homesec/test_plugin_registration.py +0 -0
- {homesec-0.1.0 → homesec-0.1.1}/tests/homesec/test_rtsp_helpers.py +0 -0
- {homesec-0.1.0 → homesec-0.1.1}/tests/homesec/test_state_store.py +0 -0
- {homesec-0.1.0 → homesec-0.1.1}/tests/homesec/test_yolo_filter.py +0 -0
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
|
2
|
+
<module type="JAVA_MODULE" version="4">
|
|
3
|
+
<component name="NewModuleRootManager" inherit-compiler-output="true">
|
|
4
|
+
<exclude-output />
|
|
5
|
+
<content url="file://$MODULE_DIR$" />
|
|
6
|
+
<orderEntry type="inheritedJdk" />
|
|
7
|
+
<orderEntry type="sourceFolder" forTests="false" />
|
|
8
|
+
</component>
|
|
9
|
+
</module>
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
<component name="libraryTable">
|
|
2
|
+
<library name="my-test-package">
|
|
3
|
+
<CLASSES>
|
|
4
|
+
<root url="jar://$PROJECT_DIR$/.venv/lib/python3.14/site-packages/pkg_resources/tests/data/my-test-package-zip/my-test-package.zip!/" />
|
|
5
|
+
</CLASSES>
|
|
6
|
+
<JAVADOC />
|
|
7
|
+
<SOURCES />
|
|
8
|
+
</library>
|
|
9
|
+
</component>
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
|
2
|
+
<project version="4">
|
|
3
|
+
<component name="ProjectRootManager" version="2" languageLevel="JDK_21" default="true" project-jdk-name="openjdk-21" project-jdk-type="JavaSDK">
|
|
4
|
+
<output url="file://$PROJECT_DIR$/out" />
|
|
5
|
+
</component>
|
|
6
|
+
</project>
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
|
2
|
+
<project version="4">
|
|
3
|
+
<component name="ChangeListManager">
|
|
4
|
+
<list default="true" id="33313ace-5c3b-4532-abc0-26bda0c300f7" name="Changes" comment="">
|
|
5
|
+
<change beforePath="$PROJECT_DIR$/Makefile" beforeDir="false" afterPath="$PROJECT_DIR$/Makefile" afterDir="false" />
|
|
6
|
+
<change beforePath="$PROJECT_DIR$/pyproject.toml" beforeDir="false" afterPath="$PROJECT_DIR$/pyproject.toml" afterDir="false" />
|
|
7
|
+
<change beforePath="$PROJECT_DIR$/src/homesec/__init__.py" beforeDir="false" afterPath="$PROJECT_DIR$/src/homesec/__init__.py" afterDir="false" />
|
|
8
|
+
<change beforePath="$PROJECT_DIR$/uv.lock" beforeDir="false" afterPath="$PROJECT_DIR$/uv.lock" afterDir="false" />
|
|
9
|
+
</list>
|
|
10
|
+
<option name="SHOW_DIALOG" value="false" />
|
|
11
|
+
<option name="HIGHLIGHT_CONFLICTS" value="true" />
|
|
12
|
+
<option name="HIGHLIGHT_NON_ACTIVE_CHANGELIST" value="false" />
|
|
13
|
+
<option name="LAST_RESOLUTION" value="IGNORE" />
|
|
14
|
+
</component>
|
|
15
|
+
<component name="Git.Settings">
|
|
16
|
+
<option name="RECENT_GIT_ROOT_PATH" value="$PROJECT_DIR$" />
|
|
17
|
+
</component>
|
|
18
|
+
<component name="ProjectColorInfo"><![CDATA[{
|
|
19
|
+
"associatedIndex": 7
|
|
20
|
+
}]]></component>
|
|
21
|
+
<component name="ProjectId" id="385rR38zU8CFOYRby1hUP1t3Ubh" />
|
|
22
|
+
<component name="ProjectViewState">
|
|
23
|
+
<option name="hideEmptyMiddlePackages" value="true" />
|
|
24
|
+
<option name="showLibraryContents" value="true" />
|
|
25
|
+
</component>
|
|
26
|
+
<component name="PropertiesComponent"><![CDATA[{
|
|
27
|
+
"keyToString": {
|
|
28
|
+
"ModuleVcsDetector.initialDetectionPerformed": "true",
|
|
29
|
+
"RunOnceActivity.ShowReadmeOnStart": "true",
|
|
30
|
+
"RunOnceActivity.git.unshallow": "true",
|
|
31
|
+
"RunOnceActivity.typescript.service.memoryLimit.init": "true",
|
|
32
|
+
"kotlin-language-version-configured": "true",
|
|
33
|
+
"last_opened_file_path": "/Users/levneiman/code/homesec",
|
|
34
|
+
"nodejs_package_manager_path": "npm"
|
|
35
|
+
}
|
|
36
|
+
}]]></component>
|
|
37
|
+
<component name="SharedIndexes">
|
|
38
|
+
<attachedChunks>
|
|
39
|
+
<set>
|
|
40
|
+
<option value="bundled-jdk-30f59d01ecdd-26cb7f24e5b0-intellij.indexing.shared.core-IU-253.29346.138" />
|
|
41
|
+
</set>
|
|
42
|
+
</attachedChunks>
|
|
43
|
+
</component>
|
|
44
|
+
<component name="TaskManager">
|
|
45
|
+
<task active="true" id="Default" summary="Default task">
|
|
46
|
+
<changelist id="33313ace-5c3b-4532-abc0-26bda0c300f7" name="Changes" comment="" />
|
|
47
|
+
<created>1768100260356</created>
|
|
48
|
+
<option name="number" value="Default" />
|
|
49
|
+
<option name="presentableId" value="Default" />
|
|
50
|
+
<updated>1768100260356</updated>
|
|
51
|
+
</task>
|
|
52
|
+
<servers />
|
|
53
|
+
</component>
|
|
54
|
+
<component name="TypeScriptGeneratedFilesManager">
|
|
55
|
+
<option name="version" value="3" />
|
|
56
|
+
</component>
|
|
57
|
+
</project>
|
|
@@ -3,7 +3,7 @@ SHELL := /bin/bash
|
|
|
3
3
|
|
|
4
4
|
.PHONY: help homesec test typecheck check
|
|
5
5
|
.PHONY: db-up db-down db-logs db-migrate db-migrate-homesec
|
|
6
|
-
.PHONY: pypi-build pypi-check pypi-publish
|
|
6
|
+
.PHONY: pypi-clean pypi-build pypi-check pypi-publish
|
|
7
7
|
|
|
8
8
|
help:
|
|
9
9
|
@echo "Targets:"
|
|
@@ -16,6 +16,7 @@ help:
|
|
|
16
16
|
@echo " make db-logs Tail Postgres logs (telemetry)"
|
|
17
17
|
@echo " make db-migrate Run alembic migrations (telemetry + clip state/events)"
|
|
18
18
|
@echo " make db-migrate-homesec Run alembic migrations (clip state/events)"
|
|
19
|
+
@echo " make pypi-clean Remove local build artifacts (dist/, build/)"
|
|
19
20
|
@echo " make pypi-build Build sdist/wheel for PyPI"
|
|
20
21
|
@echo " make pypi-check Validate dist artifacts with twine"
|
|
21
22
|
@echo " make pypi-publish Build, check, and upload to PyPI"
|
|
@@ -51,7 +52,10 @@ db-migrate:
|
|
|
51
52
|
db-migrate-homesec:
|
|
52
53
|
$(MAKE) db-migrate
|
|
53
54
|
|
|
54
|
-
pypi-
|
|
55
|
+
pypi-clean:
|
|
56
|
+
rm -rf dist build
|
|
57
|
+
|
|
58
|
+
pypi-build: pypi-clean check
|
|
55
59
|
uv run --with build python -m build
|
|
56
60
|
|
|
57
61
|
pypi-check:
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: homesec
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.1
|
|
4
4
|
Summary: Pluggable async home security camera pipeline with detection, VLM analysis, and alerts.
|
|
5
5
|
Project-URL: Homepage, https://github.com/lan17/homesec
|
|
6
6
|
Project-URL: Source, https://github.com/lan17/homesec
|
|
@@ -261,6 +261,7 @@ best-effort, and non-critical stages can fail without losing the alert.
|
|
|
261
261
|
- Policy-driven alerts with per-camera overrides
|
|
262
262
|
- Fan-out notifiers (MQTT for Home Assistant, SendGrid email)
|
|
263
263
|
- Postgres-backed state + events with graceful degradation
|
|
264
|
+
- Built around small, stable interfaces so new plugins drop in cleanly
|
|
264
265
|
- Health endpoint plus optional Postgres telemetry logging
|
|
265
266
|
|
|
266
267
|
## Pipeline at a glance
|
|
@@ -377,6 +378,27 @@ storage:
|
|
|
377
378
|
- For a quick local run, pair `local_folder` with `local` storage and drop a clip
|
|
378
379
|
into `recordings/`.
|
|
379
380
|
|
|
381
|
+
## Extensible by design
|
|
382
|
+
|
|
383
|
+
HomeSec is intentionally modular. Each major capability is an interface
|
|
384
|
+
(`ClipSource`, `StorageBackend`, `ObjectFilter`, `VLMAnalyzer`, `AlertPolicy`,
|
|
385
|
+
`Notifier`) defined in `src/homesec/interfaces.py`, and plugins are discovered at
|
|
386
|
+
runtime via entry points. This keeps the core pipeline small while making it
|
|
387
|
+
easy to add new backends without editing core code.
|
|
388
|
+
|
|
389
|
+
What this means in practice:
|
|
390
|
+
- Swap storage or notifications by changing config, not code.
|
|
391
|
+
- Add a new plugin type as a separate package and register it.
|
|
392
|
+
- Keep config validation strict by pairing each plugin with a Pydantic model.
|
|
393
|
+
|
|
394
|
+
Extension points (all pluggable):
|
|
395
|
+
- Sources: RTSP motion detection, FTP uploads, local folders
|
|
396
|
+
- Storage backends: Dropbox, local disk, or your own
|
|
397
|
+
- Filters: object detection (YOLO or custom models)
|
|
398
|
+
- VLM analyzers: OpenAI-compatible APIs or local models
|
|
399
|
+
- Alert policies: per-camera rules and thresholds
|
|
400
|
+
- Notifiers: MQTT, email, or anything else you can send from Python
|
|
401
|
+
|
|
380
402
|
## CLI
|
|
381
403
|
|
|
382
404
|
- Run the pipeline:
|
|
@@ -399,6 +421,11 @@ storage:
|
|
|
399
421
|
HomeSec discovers plugins via entry points in the `homesec.plugins` group. A plugin
|
|
400
422
|
module just needs to import and register itself.
|
|
401
423
|
|
|
424
|
+
Each plugin provides:
|
|
425
|
+
- A unique name (used in config)
|
|
426
|
+
- A Pydantic config model for validation
|
|
427
|
+
- A factory that builds the concrete implementation
|
|
428
|
+
|
|
402
429
|
```python
|
|
403
430
|
# my_package/filters/custom.py
|
|
404
431
|
from pydantic import BaseModel
|
|
@@ -18,6 +18,7 @@ best-effort, and non-critical stages can fail without losing the alert.
|
|
|
18
18
|
- Policy-driven alerts with per-camera overrides
|
|
19
19
|
- Fan-out notifiers (MQTT for Home Assistant, SendGrid email)
|
|
20
20
|
- Postgres-backed state + events with graceful degradation
|
|
21
|
+
- Built around small, stable interfaces so new plugins drop in cleanly
|
|
21
22
|
- Health endpoint plus optional Postgres telemetry logging
|
|
22
23
|
|
|
23
24
|
## Pipeline at a glance
|
|
@@ -134,6 +135,27 @@ storage:
|
|
|
134
135
|
- For a quick local run, pair `local_folder` with `local` storage and drop a clip
|
|
135
136
|
into `recordings/`.
|
|
136
137
|
|
|
138
|
+
## Extensible by design
|
|
139
|
+
|
|
140
|
+
HomeSec is intentionally modular. Each major capability is an interface
|
|
141
|
+
(`ClipSource`, `StorageBackend`, `ObjectFilter`, `VLMAnalyzer`, `AlertPolicy`,
|
|
142
|
+
`Notifier`) defined in `src/homesec/interfaces.py`, and plugins are discovered at
|
|
143
|
+
runtime via entry points. This keeps the core pipeline small while making it
|
|
144
|
+
easy to add new backends without editing core code.
|
|
145
|
+
|
|
146
|
+
What this means in practice:
|
|
147
|
+
- Swap storage or notifications by changing config, not code.
|
|
148
|
+
- Add a new plugin type as a separate package and register it.
|
|
149
|
+
- Keep config validation strict by pairing each plugin with a Pydantic model.
|
|
150
|
+
|
|
151
|
+
Extension points (all pluggable):
|
|
152
|
+
- Sources: RTSP motion detection, FTP uploads, local folders
|
|
153
|
+
- Storage backends: Dropbox, local disk, or your own
|
|
154
|
+
- Filters: object detection (YOLO or custom models)
|
|
155
|
+
- VLM analyzers: OpenAI-compatible APIs or local models
|
|
156
|
+
- Alert policies: per-camera rules and thresholds
|
|
157
|
+
- Notifiers: MQTT, email, or anything else you can send from Python
|
|
158
|
+
|
|
137
159
|
## CLI
|
|
138
160
|
|
|
139
161
|
- Run the pipeline:
|
|
@@ -156,6 +178,11 @@ storage:
|
|
|
156
178
|
HomeSec discovers plugins via entry points in the `homesec.plugins` group. A plugin
|
|
157
179
|
module just needs to import and register itself.
|
|
158
180
|
|
|
181
|
+
Each plugin provides:
|
|
182
|
+
- A unique name (used in config)
|
|
183
|
+
- A Pydantic config model for validation
|
|
184
|
+
- A factory that builds the concrete implementation
|
|
185
|
+
|
|
159
186
|
```python
|
|
160
187
|
# my_package/filters/custom.py
|
|
161
188
|
from pydantic import BaseModel
|
|
@@ -731,7 +731,7 @@ name = "exceptiongroup"
|
|
|
731
731
|
version = "1.3.1"
|
|
732
732
|
source = { registry = "https://pypi.org/simple" }
|
|
733
733
|
dependencies = [
|
|
734
|
-
{ name = "typing-extensions", marker = "python_full_version < '3.
|
|
734
|
+
{ name = "typing-extensions", marker = "python_full_version < '3.11'" },
|
|
735
735
|
]
|
|
736
736
|
sdist = { url = "https://files.pythonhosted.org/packages/50/79/66800aadf48771f6b62f7eb014e352e5d06856655206165d775e675a02c9/exceptiongroup-1.3.1.tar.gz", hash = "sha256:8b412432c6055b0b7d14c310000ae93352ed6754f70fa8f7c34141f91c4e3219", size = 30371, upload-time = "2025-11-21T23:01:54.787Z" }
|
|
737
737
|
wheels = [
|
|
@@ -1021,7 +1021,7 @@ wheels = [
|
|
|
1021
1021
|
|
|
1022
1022
|
[[package]]
|
|
1023
1023
|
name = "homesec"
|
|
1024
|
-
version = "0.1.
|
|
1024
|
+
version = "0.1.1"
|
|
1025
1025
|
source = { editable = "." }
|
|
1026
1026
|
dependencies = [
|
|
1027
1027
|
{ name = "aiohttp" },
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|