Moin
Ich habe im Außenbereich eine Kamera von Instar, die sich über Homeassi per CGI Befehle (RESTful Command - Home Assistant)) steuern läßt, siehe auch https://wiki.instar.com/de/1440p_Serie_CGI_Befehle/ Mit diesen habe ich die letzten Stunden experimentiert.
Das Auslesen des Kamera Logfiles war eine Herausforderung und ich möchte die Lösung kurz für Nachbauer dokumentieren. Falls einer weiß, wie es einfacher geht, bitte gerne schreiben.
Was ich für den Logfile verwende
- ein REST command in der configuration.yaml
rest_command:
get_system_log:
url: "http://192.xxx.xxx.xxx/param.cgi?cmd=getsyslog&user=xxx&pwd=xxx"
method: GET
- einen MQTT Sensor ebenfalls in der configuration.yaml
mqtt:
sensor:
- name: carport_camera_logfile
unique_id: carport_camera_logfile
state_topic: "camera/log/trigger"
value_template: "valid"
json_attributes_topic: "camera/log/data"
In diesem Sensor wird das Logfile der Kamera als Atrribut zwischengespeichert. Attribut deshalb weil man ansonsten der 255 Zeichen Beschränkung unterliegt.
Ich hatte zuerst viel mit Restful Sensor probiert aber es nicht hinbekommen.
Ihr solltet für diesen Sensor in Eurem Recorder die History deaktivieren weil ansonsten sich schnell die DB Größe erhöht.
- ein Script, das den rest_command triggert und dessen Antwort verarbeitet
alias: om_scr_draussen_carport_kamera_refresh_logfile
description: >-
### Holt sich per rest_command den logfile der Kamera und veröffentlicht über
mqtt
sequence:
- action: rest_command.get_system_log
response_variable: logfile
data: {}
- delay:
seconds: 2
- if:
- condition: template
value_template: "{{ logfile['status'] == 200 }}"
then:
- action: mqtt.publish
data:
topic: camera/log/data
payload: |2-
{
"log_content": {{ (
logfile['content']
| regex_findall('(?s)log="(.*?)";')
| first
| default('')
) | tojson }}
}
retain: true
else:
- action: mqtt.publish
data:
topic: camera/log/data
payload: |2-
{
"log_content": "Kamera Logfile konnte nicht gelesen werden."
}
retain: true
icon: mdi:webcam
Das Script stoße ich über den Refresh Button auf dem Dashboard an. Theorethisch könnte man dies auch automatisieren.
Das Logfile kommt nicht als Zeilen separiert an, sondern in Variablen log=“…” und dieser Inhalt wird gleich extrahiert. Eigentlich wollte ich das später mit Jinja machen aber dann kam es hier immer zu einem Fehler, “out of index” und der Logfile war nicht komplett.
- einen input_number Helfer, mit dem ich die Anzahl der angezeigten Logzeilen varieren kann.
input_number.camera_logfile_lines
Man könnte diesen Helfer direkt auf dem Dashboard veränderbar machen, aber ich habe mich für +/- Buttons entschieden, die jeweils die Anzahl der Zeilen um 1 erhöhen/reduzieren.
- und eine Markdownkarte, in dem die gewünschte Logfiles angezeigt werden mit etwas Datum/Uhrzeit Kosmetik um Platz zu sparen
type: markdown
content: |-
{% set number_of_lines = states('input_number.camera_logfile_lines') | int -%}
{% set raw = state_attr('sensor.carport_camera_logfile', 'log_content') -%}
{% if raw != none -%}
{% set lines = raw.split('\n') | map('trim') | reject('equalto', '') | list%}
{# Empfangene Liste is aufsteigend aber ich will absteigend #}
{% set last = lines[-number_of_lines:] | reverse -%}
#### Zeige letzten {{number_of_lines}} Logfile Einträge
{% for line in last -%}
{% set parts = line.split(':', 3) -%}
{% if parts | length >= 3 -%}
{% set ts = parts[0] ~ ':' ~ parts[1] ~ ':' ~ parts[2] -%}
{% set dt = ts | as_datetime(default=None) -%}
{% if dt -%}
{{ dt.strftime('%d.%m. %H:%M') }} {{ parts[3] | default('') }}
{% else -%}
{{ line }}
{% endif -%}
{% else -%}
{{ line }}
{% endif -%}
{% endfor -%}
{% else -%}
Kein Logfile geladen
{% endif -%}
Im Dashboard Abschnitt
habe ich viel mit custom:button-card gearbeitet. Falls jemand das nachbauen möchte, hier der Code
Zusammenfassung
type: grid
cards:
- type: heading
icon: mdi:webcam
heading: Carport
heading_style: title
- type: entities
entities:
- entity: switch.carportkamerashelly_switch_0
name: Ein/Aus schalten
- entity: sensor.carportkamerashelly_switch_0_power
state_color: true
show_header_toggle: false
card_mod:
style: |
ha-card {
box-shadow: 0px 2px 4px 0px rgba(128,128,128,0.66);
}
- type: custom:webrtc-camera
entity: camera.kameracarport
title: Carport 39
mouse_drag_pan: true
mouse_wheel_zoom: true
mouse_double_click_zoom: true
touch_drag_pan: true
touch_pinch_zoom: true
touch_tap_drag_zoom: true
persist: true
muted: true
ui: true
visibility:
- condition: state
entity: switch.carportkamerashelly_switch_0
state: "on"
- type: vertical-stack
cards:
- type: horizontal-stack
cards:
- type: custom:button-card
color_type: card
color: white
icon: mdi:numeric-1-box-outline
size: 5
tap_action:
action: perform-action
service: rest_command.goto_position_1
- type: custom:button-card
color_type: card
color: white
icon: mdi:numeric-2-box-outline
size: 5
tap_action:
action: perform-action
service: rest_command.goto_position_2
- type: custom:button-card
color_type: card
color: white
icon: mdi:numeric-3-box-outline
size: 5
tap_action:
action: perform-action
service: rest_command.goto_position_3
- type: custom:button-card
color_type: card
color: white
icon: mdi:numeric-4-box-outline
size: 5
tap_action:
action: perform-action
service: rest_command.goto_position_4
- type: custom:button-card
color_type: card
color: white
icon: mdi:numeric-5-box-outline
size: 5
tap_action:
action: perform-action
service: rest_command.goto_position_5
- type: custom:button-card
color_type: card
color: white
icon: mdi:numeric-6-box-outline
size: 5
tap_action:
action: perform-action
service: rest_command.goto_position_6
- type: custom:button-card
color_type: card
color: white
icon: mdi:numeric-7-box-outline
size: 5
tap_action:
action: perform-action
service: rest_command.goto_position_7
- type: custom:button-card
color_type: card
color: white
icon: mdi:numeric-8-box-outline
size: 5
tap_action:
action: perform-action
service: rest_command.goto_position_8
visibility:
- condition: state
entity: switch.carportkamerashelly_switch_0
state: "on"
- type: vertical-stack
cards:
- type: horizontal-stack
cards:
- type: custom:button-card
color_type: card
color: white
icon: mdi:bell-outline
size: 30%
tap_action:
action: perform-action
service: rest_command.enable_alert
- type: custom:button-card
color_type: card
color: white
icon: mdi:bell-off-outline
size: 30%
tap_action:
action: perform-action
service: rest_command.disable_alert
confirmation:
text: Soll der Alarm wirklich dauerhaft deaktiviert werden ?
- type: custom:button-card
color_type: card
color: white
icon: mdi:volume-high
size: 30%
tap_action:
action: perform-action
service: rest_command.enable_audio
- type: custom:button-card
color_type: card
color: white
icon: mdi:volume-mute
size: 30%
tap_action:
action: perform-action
service: rest_command.disable_audio
confirmation:
text: Soll Audio wirklich deaktiviert werden ?
visibility:
- condition: state
entity: switch.carportkamerashelly_switch_0
state: "on"
- type: custom:button-card
icon: mdi:record-rec
name: Starte kurze Alarm Aufnahme
size: 40%
layout: icon_name
tap_action:
action: perform-action
service: rest_command.trigger_alert_recording
styles:
card:
- padding: 5px
grid:
- grid-template-areas: "\"i n\""
- grid-template-columns: auto 1fr
icon:
- width: 50px
- height: 50px
name:
- justify-self: start
visibility:
- condition: state
entity: switch.carportkamerashelly_switch_0
state: "on"
- type: markdown
content: >-
{% set number_of_lines = states('input_number.camera_logfile_lines') | int
-%}
{% set raw = state_attr('sensor.carport_camera_logfile', 'log_content')
-%}
{% if raw != none -%}
{% set lines = raw.split('\n') | map('trim') | reject('equalto', '') | list%}
{# Empfangene Liste is aufsteigend aber ich will absteigend #}
{% set last = lines[-number_of_lines:] | reverse -%}
#### Zeige letzten {{number_of_lines}} Logfile Einträge
{% for line in last -%}
{% set parts = line.split(':', 3) -%}
{% if parts | length >= 3 -%}
{% set ts = parts[0] ~ ':' ~ parts[1] ~ ':' ~ parts[2] -%}
{% set dt = ts | as_datetime(default=None) -%}
{% if dt -%}
{{ dt.strftime('%d.%m. %H:%M') }} {{ parts[3] | default('') }}
{% else -%}
{{ line }}
{% endif -%}
{% else -%}
{{ line }}
{% endif -%}
{% endfor -%}
{% else -%}
Kein Logfile geladen
{% endif -%}
visibility:
- condition: state
entity: switch.carportkamerashelly_switch_0
state: "on"
- type: vertical-stack
cards:
- type: horizontal-stack
cards:
- type: custom:button-card
color_type: card
color: white
icon: mdi:plus
size: 30%
styles:
card:
- padding: 0px
- width: 50px
- height: 30px
tap_action:
action: perform-action
service: input_number.increment
service_data:
entity_id: input_number.camera_logfile_lines
- type: custom:button-card
color_type: card
color: white
icon: mdi:minus
size: 30%
styles:
card:
- padding: 0px
- width: 50px
- height: 30px
tap_action:
action: perform-action
service: input_number.decrement
service_data:
entity_id: input_number.camera_logfile_lines
- type: custom:button-card
icon: mdi:refresh
name: Refresh
size: 30%
layout: icon_name
tap_action:
action: perform-action
service: script.turn_on
service_data:
entity_id: script.om_scr_draussen_carport_kamera_refresh_logfile
styles:
card:
- padding: 0px
- width: 100px
grid:
- grid-template-areas: "\"i n\""
- grid-template-columns: auto 1fr
icon:
- width: 30px
- height: 30px
name:
- font-size: 15px
visibility:
- condition: state
entity: switch.carportkamerashelly_switch_0
state: "on"
grid_options:
columns: 11
rows: auto
- type: markdown
content: "#### Alarm temporär deaktivieren"
title: s
text_only: true
visibility:
- condition: state
entity: switch.carportkamerashelly_switch_0
state: "on"
- type: custom:mushroom-select-card
entity: input_select.carport_kamera_alarm_aus_zeiten
name: für ...
icon: mdi:bell-off-outline
fill_container: false
icon_color: black
primary_info: none
secondary_info: none
layout: vertical
visibility:
- condition: state
entity: switch.carportkamerashelly_switch_0
state: "on"
grid_options:
columns: 6
rows: 1
card_mod:
style: |
ha-card {
--ha-card-background: {% if is_state('timer.carport_kamera_alarm_aus_timer', 'active') %}red{% else %}transparent{% endif %};
}
- type: entities
entities:
- entity: timer.carport_kamera_alarm_aus_timer
name: " "
secondary_info: none
visibility:
- condition: state
entity: switch.carportkamerashelly_switch_0
state: "on"
card_mod:
style: |
ha-card {
--ha-card-background: {% if is_state('timer.carport_kamera_alarm_aus_timer', 'active') %}red{% else %}transparent{% endif %};
color: white;
font-weight: bold;
--card-mod-icon-color: white;
}
grid_options:
columns: 6
rows: 1
- type: markdown
content: "### Kamera Carport ist aus."
visibility:
- condition: state
entity: switch.carportkamerashelly_switch_0
state: "off"
column_span: 1
Gutes Gelingen und Anregungen sind jederzeit willkommen!
PS: Ich muß jetzt unbedingt ins Bett sonst kriege ich morgen ach heute auf Arbeit nichts gebacken
EDIT1:
Nur ein bischen Kosmetik und im Markdown Code noch ein weiteres if/then eingebaut falls der MQQT Sensor aus irgendeinem Grund keinen Inhalt hat und auf Dashboard einen Fehler anzeigt.