Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
152 changes: 76 additions & 76 deletions .github/workflows/ci_pipeline.yml
Original file line number Diff line number Diff line change
@@ -1,76 +1,76 @@
name: ✅ CI Pipeline
on:
pull_request:
branches: [dev, main]
schedule:
- cron: "0 3 * * 1" # Läuft jeden Montag um 03:00 UTC für automatische Updates
permissions:
contents: read
concurrency:
# Bei Push: "CI-push-dev", bei PR zu main: "CI-pr-123"
group: ${{ github.workflow }}-${{ github.event_name }}-${{ github.event_name == 'push' && github.ref_name || github.event.pull_request.number }}
cancel-in-progress: true
jobs:
lint:
name: "🔍 Linting & Static Analysis"
runs-on: ubuntu-latest
steps:
- name: Checkout Repository
uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v4
with:
python-version: "3.11"
- name: Install dependencies
run: |
pip install black pylint
- name: Autoformat with Black
run: black . --line-length=88 --fast
- name: Run Pylint
run: |
pylint custom_components/diveracontrol --exit-zero
security_checks:
name: "🔒 Security Checks"
runs-on: ubuntu-latest
steps:
- name: 📥 Checkout Code
uses: actions/checkout@v3
- name: 🐍 Set up Python
uses: actions/setup-python@v4
with:
python-version: "3.13"
- name: 🔒 Install Security Tools
run: pip install bandit safety
- name: 🔍 Run Bandit (Code Security)
run: bandit -r custom_components/ -ll -i
- name: 🛡️ Run Safety (Dependency Security)
run: safety check --full-report
secrets_scan:
name: "🕵️ Secret Scanning"
runs-on: ubuntu-latest
steps:
- name: 📥 Checkout Code (Full History)
uses: actions/checkout@v3
with:
fetch-depth: 0
- name: 🐽 TruffleHog OSS
uses: trufflesecurity/[email protected]
with:
base: HEAD~50
head: HEAD
extra_args: "--only-verified --json"
name: ✅ CI Pipeline

on:
pull_request:
branches: [dev, main]
schedule:
- cron: "0 3 * * 1" # Läuft jeden Montag um 03:00 UTC für automatische Updates

permissions:
contents: read

concurrency:
# Bei Push: "CI-push-dev", bei PR zu main: "CI-pr-123"
group: ${{ github.workflow }}-${{ github.event_name }}-${{ github.event_name == 'push' && github.ref_name || github.event.pull_request.number }}
cancel-in-progress: true

jobs:
lint:
name: "🔍 Linting & Static Analysis"
runs-on: ubuntu-latest
steps:
- name: Checkout Repository
uses: actions/checkout@v4

- name: Set up Python
uses: actions/setup-python@v4
with:
python-version: "3.11"

- name: Install dependencies
run: |
pip install black pylint

- name: Autoformat with Black
run: black . --line-length=88 --fast

- name: Run Pylint
run: |
pylint custom_components/diveracontrol --exit-zero

security_checks:
name: "🔒 Security Checks"
runs-on: ubuntu-latest
steps:
- name: 📥 Checkout Code
uses: actions/checkout@v3

- name: 🐍 Set up Python
uses: actions/setup-python@v4
with:
python-version: "3.13"

- name: 🔒 Install Security Tools
run: pip install bandit safety

- name: 🔍 Run Bandit (Code Security)
run: bandit -r custom_components/ -ll -i

- name: 🛡️ Run Safety (Dependency Security)
run: safety check --full-report

secrets_scan:
name: "🕵️ Secret Scanning"
runs-on: ubuntu-latest
steps:
- name: 📥 Checkout Code (Full History)
uses: actions/checkout@v3
with:
fetch-depth: 0

- name: 🐽 TruffleHog OSS
uses: trufflesecurity/[email protected]
with:
base: HEAD~50
head: HEAD
extra_args: "--only-verified --json"
54 changes: 27 additions & 27 deletions .github/workflows/hacs.yml
Original file line number Diff line number Diff line change
@@ -1,27 +1,27 @@
name: HACS Quality Checks
on:
pull_request:
branches: [dev, main]
schedule:
- cron: "0 0 * * *"
permissions:
contents: read
concurrency:
# Bei Push: "HACS-push-dev", bei PR zu main: "HACS-pr-123"
group: ${{ github.workflow }}-${{ github.event_name }}-${{ github.event_name == 'push' && github.ref_name || github.event.pull_request.number }}
cancel-in-progress: true
jobs:
hacs:
name: HACS
runs-on: "ubuntu-latest"
steps:
- name: Checkout Code
uses: actions/checkout@v3
- name: HACS validation
uses: "hacs/action@main"
with:
category: "integration"
name: HACS Quality Checks

on:
pull_request:
branches: [dev, main]
schedule:
- cron: "0 0 * * *"

permissions:
contents: read

concurrency:
# Bei Push: "HACS-push-dev", bei PR zu main: "HACS-pr-123"
group: ${{ github.workflow }}-${{ github.event_name }}-${{ github.event_name == 'push' && github.ref_name || github.event.pull_request.number }}
cancel-in-progress: true

jobs:
hacs:
name: HACS
runs-on: "ubuntu-latest"
steps:
- name: Checkout Code
uses: actions/checkout@v3
- name: HACS validation
uses: "hacs/action@main"
with:
category: "integration"
46 changes: 23 additions & 23 deletions .github/workflows/hass.yml
Original file line number Diff line number Diff line change
@@ -1,23 +1,23 @@
name: Home Assistant Quality Checks
on:
pull_request:
branches: [dev, main]
schedule:
- cron: "0 0 * * *"
permissions:
contents: read
concurrency:
# Bei Push: "HASS-push-dev", bei PR zu main: "HASS-pr-123"
group: ${{ github.workflow }}-${{ github.event_name }}-${{ github.event_name == 'push' && github.ref_name || github.event.pull_request.number }}
cancel-in-progress: true
jobs:
hass:
name: HASS
runs-on: "ubuntu-latest"
steps:
- uses: "actions/checkout@v4"
- uses: "home-assistant/actions/hassfest@master"
name: Home Assistant Quality Checks

on:
pull_request:
branches: [dev, main]
schedule:
- cron: "0 0 * * *"

permissions:
contents: read

concurrency:
# Bei Push: "HASS-push-dev", bei PR zu main: "HASS-pr-123"
group: ${{ github.workflow }}-${{ github.event_name }}-${{ github.event_name == 'push' && github.ref_name || github.event.pull_request.number }}
cancel-in-progress: true

jobs:
hass:
name: HASS
runs-on: "ubuntu-latest"
steps:
- uses: "actions/checkout@v4"
- uses: "home-assistant/actions/hassfest@master"
17 changes: 11 additions & 6 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,12 @@
{
"python.testing.pytestArgs": [
"tests"
],
"python.testing.unittestEnabled": false,
"python.testing.pytestEnabled": true
}
"python.testing.pytestArgs": ["tests"],
"python.testing.unittestEnabled": false,
"python.testing.pytestEnabled": true,
"python-envs.pythonProjects": [
{
"path": ".",
"envManager": "ms-python.python:venv",
"packageManager": "ms-python.python:pip"
}
]
}
4 changes: 3 additions & 1 deletion README.en.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ This is where **DiveraControl** comes in: it provides the interface to alerting
- **Owners** and **administrators** of a Divera unit
- **Curious users** who want to explore the possibilities of the Divera API

> **Note:** The integration also works with limited permissions, but with reduced functionality. For regular users of a unit without extended permissions, the existing [Divera 24/7 Integration for Home Assistant](https://github.com/fwmarcel/home-assistant-divera) is recommended.
> **Note:** The integration also works with limited permissions, but with reduced functionality. For regular users of a unit without extended permissions, the existing [Divera 24/7 Integration for Home Assistant](https://github.com/moehrem/ha-divera) is recommended.

---

Expand Down Expand Up @@ -204,6 +204,8 @@ More details on actions and required/optional parameters are available in Home A

Actions that modify existing data (for example vehicle position) also update local integration data. This keeps Home Assistant up to date without waiting for the next Divera sync. This does not apply to new records: new alarms or messages are always created in Divera first and then synchronized to Home Assistant.

> **Note:** Actions are subject to permissions granted! Each unit (registered as device) shows only such actions the user is allowed to execute. Despite that a permission check is done every time an action is executed. If permission is not granted, the action will abort.

#### Technical service IDs

For YAML, automations, and developer tools, these service IDs are available:
Expand Down
10 changes: 4 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,6 @@

[![GitHub Release](https://img.shields.io/github/v/release/moehrem/DiveraControl?sort=semver)](https://github.com/moehrem/DiveraControl/releases)

<!-- [![GitHub Release Date](https://img.shields.io/github/release-date/moehrem/DiveraControl)](https://github.com/moehrem/DiveraControl/releases) -->
<!-- ![GitHub Downloads (all assets, latest release)](https://img.shields.io/github/downloads/moehrem/DiveraControl/latest/total?label=Downloads%20latest%20Release)
![GitHub Workflow Status](https://img.shields.io/github/actions/workflow/status/moehrem/DiveraControl/ci_pipeline.yml?branch=main) -->

![GitHub commit activity](https://img.shields.io/github/commit-activity/m/moehrem/DiveraControl)
![GitHub last commit](https://img.shields.io/github/last-commit/moehrem/DiveraControl)
![GitHub issues](https://img.shields.io/github/issues/moehrem/DiveraControl)
Expand Down Expand Up @@ -52,7 +48,7 @@ Hier kommt **DiveraControl** ins Spiel: Es stellt die Schnittstelle zur Alarmier
- **Besitzer** und **Administratoren** einer Divera-Einheit
- **Neugierige Nutzer**, die die Möglichkeiten der Divera-API erkunden wollen

> **Hinweis:** Die Integration funktioniert auch mit eingeschränkten Rechten, dann allerdings mit reduziertem Funktionsumfang. Für reine Nutzer einer Einheit ohne erweiterte Berechtigungen empfiehlt sich die bestehende [Divera 24/7 Integration for Home Assistant](https://github.com/fwmarcel/home-assistant-divera).
> **Hinweis:** Die Integration funktioniert auch mit eingeschränkten Rechten, dann allerdings mit reduziertem Funktionsumfang. Für reine Nutzer einer Einheit ohne erweiterte Berechtigungen empfiehlt sich die [Divera 24/7 Integration for Home Assistant](https://github.com/moehrem/ha-divera).

---

Expand Down Expand Up @@ -201,12 +197,14 @@ Zur Interaktion mit Divera sind verschiedene Aktionen in HomeAssistant implement
- Erstellen einer neuen Mitteilung

Alle Aktionen sind geräteabhängig. Das heißt, dass jeder Ausführung die anzusprechende Einheit mitgegeben werden muss. Über Automationen und im Frontend kann als Auslöser einfach eine Einheit gewählt und die gewünschte Aktion ausgeführt werden. Hier sind viele Felder auch mit Auswahlhilfen versehen.
In den Entwickleroptionen oder bei anderer Implementierung der Aktionen muss ein target in Form der device_id eingegeben werden. Aus technischen Gründen können hier einige Felder nicht mit Auswahlhilfen versorgt werden. Das betrifft alle änderbaren Wertehilfen, z.B. Alarme, Fahrzeuge, Besatzung, Gruppen etc. In die Felder muss stattdessen die entsprechende ID, bei mehreren IDs durch Komma getrennt, eingegeben werden.
In den Entwickleroptionen oder bei anderer Implementierung der Aktionen muss ein target in Form der device_id eingegeben werden. Aus technischen Gründen können hier einige Felder nicht mit Auswahlhilfen versorgt werden. Das betrifft alle änderbaren Wertehilfen, z.B. Alarme, Fahrzeuge, Besatzung, Gruppen etc. In diese Felder muss stattdessen die entsprechende ID, bei mehreren IDs durch Komma getrennt, eingegeben werden.

Weitere Details zu den Aktionen, insbesondere zu obligatorischen und optionalen Parametern, können im HomeAssistant unter "Entwicklungswerkzeuge" -> "Aktionen" eingesehen werden. Die Umsetzung umfasst sowohl den "YAML-Modus" als auch den "UI-Modus". Alle Aktionen beginnen mit "DiveraControl: ", gefolgt vom Namen und einer kurzen Beschreibung. Es ist dort außerdem möglich, Aktionen manuell zu testen. Weitere Informationen zur Funktionsweise und dem Einsatz von Aktionen [sind hier zu finden](https://www.home-assistant.io/docs/scripts/perform-actions/).

Aktionen, die bestehende Daten ändern, z.B. eine Fahrzeugposition, tun dies auch bei den lokalen Daten. Somit ist HomeAssistant immer aktuell und muss nicht auf eine Aktualisierung von Divera warten. Dies gilt jedoch nicht für neue Datensätze! So wird z.B. ein neuer Alarm oder eine neue Nachricht immer bei Divera erstellt und erst danach mit HomeAssistant synchronisiert.

> **Hinweis**: Aktionen sind berechtigungsabhängig! Zu jeder Einheit (abgebildet als Gerät) werden nur solche Aktionen angeboten, für die der Nutzer Berechtigungen hat. Unabhängig davon wird vor jeder Aktionsausführung die Berechtigung geprüft und die Aktion ggf. abgebrochen.

#### Technische Service-IDs

Für YAML, Automationen und Entwicklerwerkzeuge sind folgende Service-IDs relevant:
Expand Down
13 changes: 8 additions & 5 deletions custom_components/diveracontrol/config_flow.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@
D_UPDATE_INTERVAL_ALARM,
D_UPDATE_INTERVAL_DATA,
D_USE_WEBHOOKS,
D_WEBHOOK_ID,
DOMAIN,
MINOR_VERSION,
PATCH_VERSION,
Expand Down Expand Up @@ -77,7 +76,7 @@ async def async_step_user(
user_input: The user input data of step "user".

Returns:
ConfigFLowResult: The result of the config flow step "user".
ConfigFlowResult: The result of the config flow step "user".

"""

Expand All @@ -100,7 +99,11 @@ async def async_step_user(
if method == "api_key":
return await self.async_step_api_key()

return self.async_abort(reason="unknown_step")
return self.async_show_form(
step_id="user",
data_schema=get_entry_form_schema(),
errors=self.errors,
)

async def async_step_login(
self,
Expand All @@ -112,7 +115,7 @@ async def async_step_login(
user_input: The user input data of step "login".

Returns:
ConfigFLowResult: The result of the config flow step "login".
ConfigFlowResult: The result of the config flow step "login".

"""

Expand All @@ -136,7 +139,7 @@ async def async_step_api_key(
user_input: The user input data of step "api_key".

Returns:
ConfigFLowResult: The result of the config flow step "api_key".
ConfigFlowResult: The result of the config flow step "api_key".

"""

Expand Down
3 changes: 2 additions & 1 deletion custom_components/diveracontrol/coordinator.py
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,8 @@ async def _async_update_data(self) -> dict[str, Any]:

try:
# read data from Divera API
new_cluster_data = await update_data(self.api, self.data)
raw_ucr_data = await self.api.get_ucr_data()
new_cluster_data = await update_data(self.api, raw_ucr_data, self.data)

# dynamically change update interval
self.update_interval = set_update_interval(
Expand Down
Loading
Loading