QR code generation/recognition

We can use the OCR component by @fabaff to read characters, but adding QR codes would be useful for displaying or capturing data from QR codes. For example, perhaps you want to share your wifi key with visitors and HA could display a QR code on the front end. Another use case is integration with the image_processing component to recognise QR codes on Agile cards, to enable a camera to monitor the progress of these cards on a physical whiteboard viewed with a camera.

Useful package here

I suppose the generation of QR code should be pretty simple to integrate, since python library to generate QR Code are already wildly available.

This is something I threw together and it seems to work just fine. I have my guest wifi automatically change on a weekly basis and that pushes the value to sensor.guest_wifi. (Yes I know it is unnecessary but this was to see if I could, and I can, so I did :slight_smile: )

I am not a python wizard so feel free to give feedback.

# Configuration.yaml
camera:
  - platform: qrcode
    name: Guest WiFi
    value_template: "WIFI:S:GUEST_NETWORK;T:WPA/WPA2;P:{{states.sensor.guest_wifi.state}};;"
import logging
import io
import voluptuous as vol
from homeassistant.core import callback

from homeassistant.const import (
    CONF_NAME, CONF_VALUE_TEMPLATE, ATTR_ENTITY_ID, EVENT_HOMEASSISTANT_START)
from homeassistant.components.camera import (PLATFORM_SCHEMA, Camera)
import homeassistant.helpers.config_validation as cv
from homeassistant.helpers.event import async_track_state_change

REQUIREMENTS = ['pyqrcode==1.2.1', 'pypng==0.0.18']
_LOGGER = logging.getLogger(__name__)

DEFAULT_NAME = 'qr_code'

# SCAN_INTERVAL = timedelta(seconds=2)
PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
    vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string,
    vol.Required(CONF_VALUE_TEMPLATE): cv.template,
    vol.Optional(ATTR_ENTITY_ID): cv.entity_ids,
})


async def async_setup_platform(hass, config, add_devices, discovery_info=None):
    """Set up the QRCode image platform."""
    name = config.get(CONF_NAME)
    value_template = config.get(CONF_VALUE_TEMPLATE)

    if value_template is not None:
        value_template.hass = hass
    entity_ids = (config.get(ATTR_ENTITY_ID)
                  or value_template.extract_entities())

    add_devices([QRCodeCamera(hass, name, value_template, entity_ids)])
    return True


class QRCodeCamera(Camera):
    """Representation of an QRCode image."""

    def __init__(self, hass, name, template, entity_ids):
        """Initialize the QRCode entity."""
        super().__init__()
        self._hass = hass
        self._name = name
        self._template = template
        self._entities = entity_ids
        self._image = io.BytesIO()
        self._refresh_()

    async def async_added_to_hass(self):
        """Register callbacks."""
        @callback
        def qr_state_listener(entity, old_state, new_state):
            """Handle device state changes."""
            self._refresh_()

        @callback
        def qr_sensor_startup(event):
            """Update template on startup."""
            async_track_state_change(
                self.hass, self._entities, qr_state_listener)

        self.hass.bus.async_listen_once(
            EVENT_HOMEASSISTANT_START, qr_sensor_startup)

    @property
    def name(self):
        """Return the name of the image processor."""
        return self._name

    @property
    def should_poll(self):
        """Update the recording state periodically."""
        return True

    @property
    def state(self):
        return self._template.async_render()

    def camera_image(self):
        """Process the image."""
        return self._image.getvalue()

    def _refresh_(self):
        import pyqrcode
        import png
        qr_code = pyqrcode.create(self._template.async_render())
        self._image.truncate(0)
        self._image.seek(0)

        qr_code.png(self._image, scale=6, module_color=[
                   0xff, 0xff, 0xff], background=[0, 0, 0, 128])

1 Like

Looks good enough to submit as a full component?

I’ve been meaning to setup my environment for submitting some of my components but haven’t bitten the bullet to actually do it. A lot of that is relatively new to me so just need to familiarize myself with it a bit.

Happy to offer any advice

Just wanted to say thank you @editter. I set this up yesterday and it worked right away.

The only modification I did was to add the connection string as an entry in secrets.yaml instead of using a separate sensor for it.

1 Like

At @editter any plans to submit a PR with this?

That was the intention but the life and work has gotten in the way. I am getting married next week so hopefully after that is done I will have more time on my hands to get back into things again.

1 Like

QRCode recognition would be a nice feature.

As an example, you can have a QRCode printed somewhere in your car so garage door will automatically open when frontdoor camera detects that QRCode.

This might help:

1 Like

QR recognition.

Thanks @hmronline

# configuration.yaml
image_processing:
  - platform: qr
    source:
      - entity_id: camera.xxxxx
# qr.py, save this in .homeassistant/custom_components/image_processing/qr.py
import logging
import voluptuous as vol
import homeassistant.helpers.config_validation as cv

from homeassistant.core import split_entity_id
from homeassistant.components.image_processing import (
    ImageProcessingEntity, CONF_SOURCE, CONF_ENTITY_ID, CONF_NAME)

REQUIREMENTS = ['pyzbar==0.1.7', 'pillow==5.3.0']

_LOGGER = logging.getLogger(__name__)

def setup_platform(hass, config, add_entities, discovery_info=None):
    """Set up the demo image processing platform."""
    entities = []
    for camera in config[CONF_SOURCE]:
        entities.append(QrEntity(
            camera[CONF_ENTITY_ID], camera.get(CONF_NAME)
        ))

    add_entities(entities)

class QrEntity(ImageProcessingEntity):
    """QR image processing entity."""

    def __init__(self, camera_entity, name):
        """Initialize QR image processing entity."""
        super().__init__()

        self._camera = camera_entity
        if name:
            self._name = name
        else:
            self._name = "QR {0}".format(
                split_entity_id(camera_entity)[1])
        self._state = None

    @property
    def camera_entity(self):
        """Return camera entity id from process pictures."""
        return self._camera

    @property
    def state(self):
        """Return the state of the entity."""
        return self._state

    @property
    def name(self):
        """Return the name of the entity."""
        return self._name

    def process_image(self, image):
        """Process image."""
        import io
        from pyzbar import pyzbar
        from PIL import Image

        stream = io.BytesIO(image)
        img = Image.open(stream)

        barcodes = pyzbar.decode(img)
        if barcodes:
            self._state = barcodes[0].data.decode("utf-8")
        else:
            self._state = None
2 Likes

maybe this is need on raspberrypi(I’m not sure):
sudo apt-get install libzbar0

@robmarkcole @editter

I am looking to add barcode scanner to my home assistant instance. My target is to scan products from my phone. I want it to be part of the HA UI and not using external tool for it.

I see above that you worked on that. My question: Is there a good solution for QR code scanner within HA UI?

Thx for the help

For my lovelace UI I just use a simple picture-entity card like this

entity: camera.guest_wifi
show_name: false
show_state: false
type: picture-entity

Could u maybe explain where to put that python file and how to name it?

I’m not able to figure that out.

now available in HACS: GitHub - DeerMaximum/QR-Code-Generator: Custom Home Assistant integration to create a camera that displays a custom QR-Code

Hi, check out my solution which I created for generating and reading QR Codes from camera! :wink:

https://community.home-assistant.io/t/opening-gate-with-qr-code-for-airbnb-guests/