Food Labels via a Dymo Label Printer

We’ve always labelled food which goes in the freezer, it makes a freezer rummage much easier, and avoid mystery meals.

The Dymo printer does a decent job, but it’s really limited to desktop computers (unless you buy yet another dymo), which makes it a pain to print the food labels. My handwriting beyond abysmal…

Obligatory Video

First, there isn’t a home assistant integration for a dymo label printer, so we’re in to dirty hacks pretty quickly.

First, setup lprint on a linux box, the instructions seemed to work fine for my LabelWriter 450 Duo.

Next problem, lprint it doesn’t take text files directly, You’ll see it needs PNG files, which ImageMagick can do relatively easily. It doesn’t automatically resize based on content length, so I added a little bit of branch logic based on the size of the first line. The last line finishes with the number of labels required

wishy@niska:~$ cat printlabel.sh
#!/bin/bash

declare -a lines

readarray -d "\n" lines <<< "$1"

char_count=${#lines[0]}

label=$(head -c -3 <<<"$1")
prints=$(tail -c 2 <<<"$1")

if [[ $char_count -lt 13 ]]; then
  convert -size 673x378 xc:white -font "AvantGarde-Book" -pointsize 96 -fill black -annotate +30+100 "$label" image.png
else
  convert -size 673x378 xc:white -font "AvantGarde-Book" -pointsize 64 -fill black -annotate +30+130 "$label" image.png
fi
lprint image.png -o media=oe_md-multipurpose-label_2.25x1.25in -n "$prints"

We can test using

./printlabel.sh 'Toad in the Hole\n2 Portion\n10/03/2024,1'

Now, how do we hook that up to home assistant. First, write a short calling script. This SSHs to the linux box and runs the print command, you’ll need to set up SSH keys for authentication from the homeassistant user. I added a little escaping for ’ as is breaks the script

root@nandi:/home/homeassistant# cat printlabel.sh
#!/bin/bash
MESSAGE=$(cat)
CLEAN_MESSAGE=$(echo "$MESSAGE" | tr -d "'")
/usr/bin/ssh [email protected] "./printlabel.sh '$CLEAN_MESSAGE'"

And we can hook that up via command line notify

command_line:
  - notify:
      command: /home/homeassistant/printlabel.sh
      name: "Print Dymo Label"

Finally, the voice bit! We could just work directly from a single prompt, but I decided that I probably didn’t want labels printed until I’ve had a chance to see what speech to text has come back with. Hence one automation to create labels and save these to helpers

alias: Dymo Create Label by Voice
description: ""
trigger:
  - platform: conversation
    command:
      - >-
        [Create|Print] [a] [dymo|food] label {quantity} [portions|portion] [of]
        {food} 
condition: []
action:
  - service: input_text.set_value
    metadata: {}
    data:
      value: "{{ trigger.slots.food |title}}"
    target:
      entity_id: input_text.dymo_food_label
  - service: input_text.set_value
    metadata: {}
    data:
      value: "{{ trigger.slots.quantity }}"
    target:
      entity_id: input_text.dymo_food_portion
  - set_conversation_response: OK, {{ trigger.slots.food | title}}. Say 'print 2 labels'
mode: single

and another to actually print. I had some problems here, I need to pass an integer number of prints to the script, but speech-to-text tends to use words rather than digits. It would be handy if custom sentence could somehow be cast as integers with some reasonably logic around it, but for the moment, I’ve just bodged some find and replace logic for two->2. I also found some words are commonly mistaken by speech-to-text (Too instead of two, Free instead of Three) and hard coded some corrections in

alias: Dymo Label - Print Food Label (Voice)
description: ""
trigger:
  - platform: state
    entity_id:
      - input_button.dymo_print_label
  - platform: conversation
    command:
      - Print {number} Labels
      - Print Label
      - Print [1|one|a] [Label|Labels]
condition: []
action:
  - if:
      - condition: template
        value_template: "{{ trigger.slots.number|length != 0 }}"
      - condition: template
        value_template: >-
          {{trigger.slots.number|replace('one','1')|replace('to','2')|replace('too','2')|replace('two','2')|replace('free','3')|replace('three','3')|replace('four','4')|replace('five','5')|replace('six','6')|int<7}}
    then:
      - service: notify.print_dymo_label
        data:
          message: >-
            {{states('input_text.dymo_food_label')}}\n{{states('input_text.dymo_food_portion')}}
            Portion\n{{now().day}}/{{now().month}}/{{now().year}},{{trigger.slots.number|replace('one','1')|replace('two','2')|replace('to','2')|replace('too','2')|replace('free','3')|replace('three','3')|replace('four','4')|replace('five','5')|replace('six','6')}}
    else:
      - service: notify.print_dymo_label
        data:
          message: >-
            {{states('input_text.dymo_food_label')}}\n{{states('input_text.dymo_food_portion')}}
            Portion\n{{now().day}}/{{now().month}}/{{now().year}},1
mode: single

Final result, it works, even if there are some dirty hacks.
As far as I can see I’m the first to hook up a Dymo to home assistant, so I hope it’s useful for others in the future.

Truly awesome … I LOVE IT!

The results of the contest are out!
They may be of interest to you :wink:
Have a look!

1 Like