Skip to content

Commit

Permalink
Fix #60 - configuration generating process and README links + features
Browse files Browse the repository at this point in the history
  • Loading branch information
elad-bar committed Apr 25, 2020
1 parent 03c57ea commit 8639c3e
Show file tree
Hide file tree
Showing 15 changed files with 237 additions and 174 deletions.
11 changes: 11 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,16 @@
# Changelog

## 2020-04-25

**Implemented enhancements:**

- Moved auto-generating configurations service `blueiris.generate_advanced_configurations` to Integration -> Options
- Added ability to configure the log level of the component from Integration - Options, more details in README

**Fixed bugs:**

- Fix [\#56](https://github.com/elad-bar/ha-bleuiris/issues/51) configuration generating process and README links

## 2020-04-24 #2

**Fixed bugs:**
Expand Down
128 changes: 64 additions & 64 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,21 +25,38 @@ Look for "Integration with Blue Iris NVR" and install

#### Integration settings
###### Basic configuration (Configuration -> Integrations -> Add BlueIris)
```
host: hostname or ip
port: port
username: Username of admin user for BI
password: Password of admin user for BI
ssl: should use ssl?
```
Fields name | Type | Required | Default | Description
--- | --- | --- | --- | --- |
Host | Texbox | + | None | Hostname or IP address of the BlueIris server
Host | Textbox | + | 0 | HTTP Port to access BlueIris server
SSL | Check-box | + | Unchecked | Is SSL supported?
Username | Textbox | - | | Username of admin user for BlueIris server
Password | Textbox | - | | Password of admin user for BlueIris server

###### Integration options (Configuration -> Integrations -> BlueIris Integration -> Options)
```
Username: Username of admin user for BI
Password: Password of admin user for BI
Clear credentials: Checkbox, workaround to clear the textbox of username & password due to an issue while filling partially form in HA Options, default=False
Exclude system camera: should include / exclude system camera (All / Cycle), default=False
```
Fields name | Type | Required | Default | Description
--- | --- | --- | --- | --- |
Username | Textbox | - | Last stored username | Username of admin user for BlueIris server
Password | Textbox | - | Last stored password | Password of admin user for BlueIris server
Clear credentials | Check-box | + | Unchecked | Workaround to clear the username & password since there is not support for optional fields (Not being stored under options)
SSL | Check-box | + | Unchecked | Will take generate store and configuration for HA, more details below (Not being stored under options)
SSL | Drop-down | + | Default | Changes component's log level (more details below)

######## Log Level's drop-down
New feature to set the log level for the component without need to set log_level in `customization:` and restart or call manually `logger.set_level` and loose it after restart.

Upon startup or integration's option update, based on the value chosen, the component will make a service call to `logger.set_level` for that component with the desired value,

In case `Default` option is chosen, flow will skip calling the service, after changing from any other option to `Default`, it will not take place automatically, only after restart

###### Auto-generating configurations files:
Will create YAML with all the configurations in the config directory under blueiris.advanced_configurations.yaml:
- Input select (drop-downs)
- Script to cast based on the selection
- UI of all the components created by BlueIris based on the description above

[Example of configuration output](https://github.com/elad-bar/ha-blueiris/blob/master/docs/configs/casting/configuration.yaml)


###### Configuration validations
Upon submitting the form of creating an integration or updating options,
Expand All @@ -62,77 +79,60 @@ EdgeOS password is not encrypted, please remove integration and reintegrate
## Components

###### Binary Sensor - Alerts
```
State: represents whether there is an active alert or not
Attributes:
Active alerts #
System name
Version
License
Support expiration
Logged in User
Latitude
Longitude
```
Represents whether there is an active alert or not

Attributes |
--- |
Active alerts # |
System name |
Version |
License |
Support expiration |
Logged in User |
Latitude |
Longitude |

###### Binary Sensor - Connectivity - Non-system-camera
```
State: represents whether the camera is online or not (based on MQTT message)
```
Represents whether the camera is online or not (based on MQTT message)

###### Binary Sensor - Audio - Non-system-camera and camera supports audio
```
State: represents whether the camera is triggered for noise or not (based on MQTT message)
```
Represents whether the camera is triggered for noise or not (based on MQTT message)

###### Binary Sensor - Motion - Non-system-camera
```
State: represents whether the camera is triggered for motion or not (based on MQTT message)
```
Represents whether the camera is triggered for motion or not (based on MQTT message)

###### Camera
```
State: Idle
Attributes:
FPS
Audio support
Width
Height
Is Online
Is Recording
Issue (Camera is yellow)
Alerts #
Triggers #
Clips #
No Signal #
Error
```

Attributes |
--- |
FPS |
Audio support |
Width |
Height |
Is Online |
Is Recording |
Issue (Camera is yellow) |
Alerts # |
Triggers # |
Clips # |
No Signal # |
Error |

###### Switch - Profile (Per profile)
Allows to set the active profile, only one of the profile switches can be turned on at a time

If you are turning off one of the switch it will work according to the following order:
Profile #1 turned off, will turn on Profile #0
All the other profiles upon turning off, will turn on Profile #1

```
State: Allows to set the active profile, only one of the profile switches can be turned on at a time
```


## Lovelace UI Configuration
[Example of UI layout](https://github.com/elad-bar/ha-blueiris/blob/master/docs/config/casting/configuration.yaml)
[Example of UI layout](https://github.com/elad-bar/ha-blueiris/blob/master/docs/configs/casting/configuration.yaml)

## Casting

Currently the Stream Component is a bit ragged to use to cast Blue Iris video streams, which don't need proxying.

#### Auto-generating configurations service:
`blueiris.generate_advanced_configurations` service will create YAML with all the configurations in the config directory under blueiris.advanced_configurations.yaml:
- Input select (drop-downs)
- Script to cast based on the selection
- UI of all the components created by BlueIris based on the description above

[Example of configuration output](https://github.com/elad-bar/ha-blueiris/blob/master/docs/config/casting/configuration.yaml)

#### Lovelace UI for casting

```YAML
Expand All @@ -146,7 +146,7 @@ Currently the Stream Component is a bit ragged to use to cast Blue Iris video st
- entity: script.execute_cast_dropdown
```
[Example of configuration output](https://github.com/elad-bar/ha-blueiris/blob/master/docs/config/casting/ui-lovelace.yaml)
[Example of configuration output](https://github.com/elad-bar/ha-blueiris/blob/master/docs/configs/casting/ui-lovelace.yaml)
## Contributors
Expand Down
4 changes: 3 additions & 1 deletion custom_components/blueiris/.translations/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,9 @@
"username": "Username",
"password": "Password",
"exclude-system-camera": "Exclude system camera",
"clear-credentials": "Clear credentials"
"clear-credentials": "Clear credentials",
"log_level": "Log level",
"generate-config-files": "Generate configuration files"
}
}
},
Expand Down
6 changes: 5 additions & 1 deletion custom_components/blueiris/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
from homeassistant.config_entries import ConfigEntry
from homeassistant.core import HomeAssistant

from .helpers import async_set_ha, clear_ha, get_ha
from .helpers import async_set_ha, clear_ha, get_ha, handle_log_level
from .helpers.const import *

_LOGGER = logging.getLogger(__name__)
Expand All @@ -24,6 +24,8 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
initialized = False

try:
await handle_log_level(hass, entry)

_LOGGER.debug(f"Starting async_setup_entry of {DOMAIN}")
entry.add_update_listener(async_options_updated)
host = entry.data.get(CONF_HOST)
Expand Down Expand Up @@ -56,6 +58,8 @@ async def async_unload_entry(hass: HomeAssistant, entry: ConfigEntry):

async def async_options_updated(hass: HomeAssistant, entry: ConfigEntry):
"""Triggered by config entry options updates."""
await handle_log_level(hass, entry)

_LOGGER.info(f"async_options_updated, Entry: {entry.as_dict()} ")

host = entry.data.get(CONF_HOST)
Expand Down
9 changes: 9 additions & 0 deletions custom_components/blueiris/config_flow.py
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,15 @@ async def async_step_blue_iris_additional_settings(self, user_input=None):
errors = result.get("errors")

if errors is None:
if user_input.get(CONF_GENERATE_CONFIG_FILES, False):
ha = get_ha(self.hass, self._config_flow.config_data.host)

if ha is not None:
ha.generate_config_files()

del user_input[CONF_CLEAR_CREDENTIALS]
del user_input[CONF_GENERATE_CONFIG_FILES]

return self.async_create_entry(title="", data=user_input)

data_schema = self._config_flow.get_default_options()
Expand Down
11 changes: 11 additions & 0 deletions custom_components/blueiris/helpers/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,3 +45,14 @@ async def async_set_ha(hass: HomeAssistant, host, entry: ConfigEntry):
line_number = tb.tb_lineno

_LOGGER.error(f"Failed to async_set_ha, error: {ex}, line: {line_number}")


async def handle_log_level(hass: HomeAssistant, entry: ConfigEntry):
log_level = entry.options.get(CONF_LOG_LEVEL, LOG_LEVEL_DEFAULT)

if log_level == LOG_LEVEL_DEFAULT:
return

log_level_data = {f"custom_components.{DOMAIN}": log_level.lower()}

await hass.services.async_call(DOMAIN_LOGGER, SERVICE_SET_LEVEL, log_level_data)
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
from homeassistant.core import HomeAssistant
from homeassistant.util import slugify

from ..models.entity_data import EntityData
from .const import *

_LOGGER = logging.getLogger(__name__)
Expand All @@ -23,15 +24,14 @@ def __init__(self, hass: HomeAssistant, ha):
self._hass = hass

self._ha = ha
self._api = self._ha.api

def generate_advanced_configurations(self, event_time):
def generate(self, event_time):
_LOGGER.info(f"Started to generate advanced configuration @ {event_time}")
components_path = self._hass.config.path("blueiris.components.yaml")
lovelace_path = self._hass.config.path("blueiris.lovelace.yaml")

camera_list = self._ha.api.camera_list
media_players = self._hass.states.entity_ids("media_player")
media_players = self._hass.states.async_entity_ids("media_player")

input_select_camera = self.generate_input_select_camera(camera_list)
input_select_media_player = self.generate_input_select_media_player(
Expand Down Expand Up @@ -130,15 +130,15 @@ def generate_ui_lovelace(self):

for camera_entity_name in camera_entities:
camera_entity = camera_entities[camera_entity_name]
camera_entity_id = camera_entity.get(ENTITY_ID)
camera_entity_id = camera_entity.id

ui_component = {DOMAIN_CAMERA: camera_entity}

for binary_sensors_entity_name in binary_sensors_entities:
binary_sensors_entity = binary_sensors_entities[
binary_sensors_entity_name
]
binary_sensors_entity_id = binary_sensors_entity.get(ENTITY_ID)
binary_sensors_entity_id = binary_sensors_entity.id

if binary_sensors_entity_id == camera_entity_id:
if DOMAIN_BINARY_SENSOR not in ui_component:
Expand All @@ -155,7 +155,7 @@ def generate_ui_lovelace(self):

for binary_sensors_entity_name in binary_sensors_entities:
binary_sensors_entity = binary_sensors_entities[binary_sensors_entity_name]
binary_sensors_entity_id = binary_sensors_entity.get(ENTITY_ID)
binary_sensors_entity_id = binary_sensors_entity.id

if binary_sensors_entity_id is None:
if DOMAIN_BINARY_SENSOR not in ui_system_components:
Expand Down Expand Up @@ -184,7 +184,7 @@ def generate_ui_lovelace(self):
system_component_domain = ui_system_components[system_component_domain_name]

for system_component_domain_entity in system_component_domain:
entity_name = system_component_domain_entity.get(ENTITY_NAME)
entity_name = system_component_domain_entity.name
lines.append(
f" - {system_component_domain_name}.{slugify(entity_name)}"
)
Expand All @@ -201,8 +201,8 @@ def generate_camera_section(lines, camera_type, camera_list):
lines.append(f" cards:")

for camera_item in camera_list:
camera = camera_item[DOMAIN_CAMERA]
camera_name = camera.get(ENTITY_NAME)
camera: EntityData = camera_item[DOMAIN_CAMERA]
camera_name = camera.name

lines.append(f" - camera_image: camera.{slugify(camera_name)}")
lines.append(f" type: picture-glance")
Expand All @@ -213,8 +213,8 @@ def generate_camera_section(lines, camera_type, camera_list):
binary_sensors = camera_item[DOMAIN_BINARY_SENSOR]

for binary_sensor_name in binary_sensors:
binary_sensor = binary_sensors[binary_sensor_name]
binary_sensor_type = binary_sensor[ENTITY_EVENT]
binary_sensor: EntityData = binary_sensors[binary_sensor_name]
binary_sensor_type = binary_sensor.event

lines.append(
f" - entity: binary_sensor.{slugify(binary_sensor_name)}"
Expand Down Expand Up @@ -273,8 +273,8 @@ def generate_script(self, camera_list, media_players):
return result

def get_cast_template(self):
username = self._ha.api.username
password = self._ha.api.password
username = self._ha.config_data.username
password = self._ha.config_data.password_clear_text

credentials = ""
if username is not None and password is not None:
Expand Down
20 changes: 20 additions & 0 deletions custom_components/blueiris/helpers/const.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@
CONF_USERNAME,
)

CONF_LOG_LEVEL = "log_level"

VERSION = "2.0.0"

DOMAIN = "blueiris"
Expand All @@ -41,6 +43,9 @@

DOMAIN_KEY_FILE = f"{DOMAIN}.key"

DOMAIN_LOGGER = "logger"
SERVICE_SET_LEVEL = "set_level"

ATTR_ADMIN_PROFILE = "Profile"
ATTR_SYSTEM_CAMERA_ALL_NAME = "All"
ATTR_SYSTEM_CAMERA_ALL_ID = "Index"
Expand Down Expand Up @@ -173,6 +178,7 @@

CONF_EXCLUDE_SYSTEM_CAMERA = "exclude-system-camera"
CONF_CLEAR_CREDENTIALS = "clear-credentials"
CONF_GENERATE_CONFIG_FILES = "generate-config-files"

DOMAIN_LOAD = "load"
DOMAIN_UNLOAD = "unload"
Expand All @@ -182,3 +188,17 @@
CONF_STILL_IMAGE_URL = "still_image_url"
CONF_STREAM_SOURCE = "stream_source"
CONF_FRAMERATE = "framerate"

LOG_LEVEL_DEFAULT = "Default"
LOG_LEVEL_DEBUG = "Debug"
LOG_LEVEL_INFO = "Info"
LOG_LEVEL_WARNING = "Warning"
LOG_LEVEL_ERROR = "Error"

LOG_LEVELS = [
LOG_LEVEL_DEFAULT,
LOG_LEVEL_DEBUG,
LOG_LEVEL_INFO,
LOG_LEVEL_WARNING,
LOG_LEVEL_ERROR,
]
Loading

0 comments on commit 8639c3e

Please sign in to comment.