Skip to main content

Components

info

The developer documentation is still under construction and this page is not complete.

Viseron is built up of multiple components. These components are responsible for different tasks such as object detection, face recognition, recording etc. This guide will walk you through the process of creating a new component.

info

A component name of fancy_component will be used as an example throughout this guide.

Creating a new Component

To create a new component called fancy_component you need to create the directory viseron/components/fancy_component. The directory name should be in lowercase.

Inside the directory you need to create an __init__.py file with a setup function.

/viseron/components/fancy_component/__init__.py
"""The fancy_component component."""
from __future__ import annotations

from typing import TYPE_CHECKING, Any

if TYPE_CHECKING:
from viseron import Viseron


def setup(vis: Viseron, config: dict[str, Any]) -> bool:
"""Set up the fancy_component component."""
# Your setup code for the fancy_component here

return True

The setup function will be called when Viseron is started. The function should return True if the setup was successful, otherwise False.

You should also create a const.py file where you define constants for your component.

viseron/components/fancy_component/const.py
"""Constants for the fancy_component component."""

COMPONENT = "fancy_component"

From here you can start adding your component code. The component will be loaded by adding the component name to the config.yaml:

/config/config.yaml
fancy_component:

Configuration schema

Viseron uses voluptuous for configuration validation.

To add configuration options to your component you need to define a CONFIG_SCHEMA constant in the __init__.py file.

/viseron/components/fancy_component/__init__.py
"""The fancy_component component."""
from __future__ import annotations

from typing import TYPE_CHECKING, Any

import voluptuous as vol

from viseron.components.fancy_component.const import (
CONFIG_COOL_OPTION,
DEFAULT_COOL_OPTION,
DESC_COOL_OPTION,
)
from viseron.components.storage.const import COMPONENT, DESC_COMPONENT

if TYPE_CHECKING:
from viseron import Viseron


CONFIG_SCHEMA = vol.Schema(
{
vol.Required(COMPONENT, description=DESC_COMPONENT): vol.Schema(
{
vol.Optional(
CONFIG_COOL_OPTION,
default=DEFAULT_COOL_OPTION,
description=DESC_COOL_OPTION,
): str,
}
)
},
extra=vol.ALLOW_EXTRA,
)


def setup(vis: Viseron, config: dict[str, Any]) -> bool:
"""Set up the fancy_component component."""
# Your setup code for the fancy_component here

return True

/viseron/components/fancy_component/const.py
"""Constants for the fancy_component component."""

COMPONENT = "fancy_component"
DESC_COMPONENT = "The fancy_component component."

CONFIG_COOL_OPTION = "cool_option"
DESC_COOL_OPTION = "A cool option"
DEFAULT_COOL_OPTION = "cool_value"

tip

The description is used to generate documentation for the component. More information can be found in the documentation section.

Deprecating a config option

If you need to deprecate a config option, you can use the Deprecated validator.

/viseron/components/fancy_component/__init__.py
import voluptuous as vol

from viseron.components.fancy_component.const import (
CONFIG_COOL_OPTION,
DEFAULT_COOL_OPTION,
DESC_COOL_OPTION,
)
from viseron.components.storage.const import COMPONENT, DESC_COMPONENT

if TYPE_CHECKING:
from viseron import Viseron


CONFIG_SCHEMA = vol.Schema(
{
vol.Required(COMPONENT, description=DESC_COMPONENT): vol.Schema(
{
Deprecated(
CONFIG_FILENAME_PATTERN,
description=DESC_FILENAME_PATTERN_THUMBNAIL,
message=DEPRECATED_FILENAME_PATTERN_THUMBNAIL,
warning=WARNING_FILENAME_PATTERN_THUMBNAIL,
): str,
}
)
},
extra=vol.ALLOW_EXTRA,
)

Deprecated

The Deprecated validator has the following parameters:

  • config: The config option to deprecate.
  • description: Displayed in the generated documentation.
  • message: Displayed in the generated documentation.
  • warning: Displayed in the logs.

Setup domains

If your component needs to set up domains, it has to be done in the components setup function.

/viseron/components/fancy_component/__init__.py
from __future__ import annotations

from typing import TYPE_CHECKING, Any

import voluptuous as vol

from viseron.components.fancy_component.const import (
CONFIG_COOL_OPTION,
CONFIG_MOTION_DETECTOR,
DEFAULT_COOL_OPTION,
DESC_COOL_OPTION,
DESC_MOTION_DETECTOR,
)
from viseron.components.storage.const import COMPONENT, DESC_COMPONENT
from viseron.domains import RequireDomain, setup_domain
from viseron.domains.motion_detector import CAMERA_SCHEMA_SCANNER
from viseron.domains.motion_detector.const import CONFIG_CAMERAS, DESC_CAMERAS
from viseron.helpers.validators import CameraIdentifier, CoerceNoneToDict

if TYPE_CHECKING:
from viseron import Viseron


CONFIG_SCHEMA = vol.Schema(
{
vol.Required(COMPONENT, description=DESC_COMPONENT): vol.Schema(
{
vol.Optional(
CONFIG_COOL_OPTION,
default=DEFAULT_COOL_OPTION,
description=DESC_COOL_OPTION,
): str,
vol.Required(
CONFIG_MOTION_DETECTOR, description=DESC_MOTION_DETECTOR
): {
vol.Required(CONFIG_CAMERAS, description=DESC_CAMERAS): {
CameraIdentifier(): vol.All(CoerceNoneToDict(), CAMERA_SCHEMA_SCANNER),
},
},
}
)
},
extra=vol.ALLOW_EXTRA,
)


def setup(vis: Viseron, config: dict[str, Any]) -> bool:
"""Set up the fancy_component component."""
config = config[COMPONENT]
for camera_identifier in config[CONFIG_MOTION_DETECTOR][CONFIG_CAMERAS].keys():
setup_domain(
vis,
COMPONENT,
CONFIG_MOTION_DETECTOR,
config,
identifier=camera_identifier,
require_domains=[
RequireDomain(
domain="camera",
identifier=camera_identifier,
)
],
)

return True

Component documentation

For information on how to generate documentation for your component, see the documentation section.