USPS Mail Camera

Let me first admit that this is very, very hacky, but it works! This code modification and a corresponding local file camera entity will allow you to see today’s received mail, cycled through as a gif.

UPDATE: @mezz64 has created a more elegant version of this feature published to Github: USPS Mail Camera. I will continue to update the code below when changes are required, but his solution might be a better choice.

  1. Install ImageMagick using your package manager of choice.

  2. Modify path_to_homeassistant_directory/deps/myusps/__init__.py [version 0.50+ has this file at path_to_homeassistant_directory/deps/lib/python3.?/site-packages/myusps/__init__.py] and replace the get_mail function (really just modify the last few lines) then add a download_images function:

Modify get_mail function (you can use http://imgur.com/a/bZc6n for your nomail.gif):

def get_mail(session, date=None):
    """Get mail data."""
    _LOGGER.info("attempting to get informed delivery data")
    if not date:
        date = datetime.datetime.now().date()
    mail = []
    response = session.post(INFORMED_DELIVERY_URL, {
        'selectedDate': '{0:%m}/{0:%d}/{0:%Y}'.format(date)
    })
    container = _require_elem(response, INFORMED_DELIVERY_TAG, INFORMED_DELIVERY_ATTRS)
    for row in container.find_all(MAIL_IMAGE_TAG, MAIL_IMAGE_ATTRS):
        img = row.find('img').get('src')
        mail.append({
            'id': img.split('=')[1],
            'date': str(date),
            'image': '{}{}'.format(INFORMED_DELIVERY_IMAGE_URL, img)
        })
    """Download and compile images if we got mail, otherwise copy nomail image over GIF"""
    if len(mail) >= 1:
        download_images(session, mail)
    else:
        os.system("cp /opt/homeassistant/mail/nomail /opt/homeassistant/mail/mail.gif")
    return mail

Add download_images function (modify the paths below to actual paths on your system):

def download_images(session, mail):
    os.system("rm /opt/homeassistant/mail/*.jpg")
    count = 1
    total = len(mail)
    for mailpiece in mail:
        img_data = session.get(mailpiece['image']).content
        """Download the image"""
        with open('/opt/homeassistant/mail/' + mailpiece['id'] + '.jpg', 'wb') as handler:
            handler.write(img_data)
        """Annotate image with it's number over the total so we can keep track in the final GIF"""
        os.system("convert /opt/homeassistant/mail/" + mailpiece['id'] + ".jpg -fill white -undercolor \
            '#00000080' -gravity SouthWest -pointsize 18 -annotate +0+0 '" + str(count) + "/" + \
            str(total) + "' /opt/homeassistant/mail/" + str(count) + ".jpg 2>/dev/null")
        """Remove un-annotated image"""
        os.system("rm /opt/homeassistant/mail/" + mailpiece['id'] + ".jpg")
        count += 1
    """Create GIF of all mail images"""
    os.system("convert -delay 300 -loop 0 -dispose previous /opt/homeassistant/mail/*.jpg /opt/homeassistant/mail/mail.gif")

Now add a camera entity that reflects the location of mail.gif:

- platform: local_file
  name: Mail
  file_path: /opt/homeassistant/mail/mail.gif

That’s it! This could probably be done much more elegantly (stop doing IO in sensor updates!!!) but it works well for me. I’d love to see this integrated into HA somehow but I can’t think of an appropriate way for that to happen, maybe this will inspire someone!

7 Likes

The default parameter for get_mail() is not going to do what you want. The value will be evaluated when python first parses the function. That single value will be used for every call. If you the default value to be the current datetime for when the function was called, the default value should be changed to None. Then, in the function body, if the variable is None, assign it the value returned by the expression you are currently using.

Ah, thank you for pointing that out! This was a leftover from testing when I had to supply a date in the future! I’ve modified the code above.

This could be interesting if reworked to be a patch in HA… I guess it would have to go in the myusps python lib, then exposed in HA.

1 Like

@aneisch, after you signup for informed delivery, how long until you start seeing images in the usps dashboard?

Unfortunately I do not remember. I want to say that after signing up and being verified it was almost immediately. Can you scroll back to other days and see mail on the dashboard?

Hmm, I verified online and it simply shows no mail for the other days I can select, but I certainly have received mail.

They might not start “providing” the scans until after sign up. Hopefully tomorrow!

Easiest way to modify this to contribute it officially is to split up the current USPS Sensor into a main USPS component with a sensor and camera sub components. You wouldn’t need to actually download the images for the camera component, just fetch the url list once a day and cycle through them. It looks like you’ve already done the hard part, it just requires some refactoring into the hass architecture.

2 Likes

I keep getting a Mail(Error loading image) component instead of the images. I’ve copied nomail.gif into my folder, but I can see that I have mail today so that shouldn’t be a problem. I can also see the mail when I log into USPSs site.

But I’m not seeing any errors anywhere. I know that’s not very helpful, but any ideas?

Sounds like you might not have permission to view the image that’s been created. Are you able to scp the image off of your server and view them? Are there 1.jpg, 2.jpg images in the directory you’re writing to?

Actually no, I don’t see any *.jpg images ( should have 7 today).

I did however chmod 777 to opt/homeassistant and opt/homeassistant/mail as well as /opt/homeassistant/mail/nomail.gif to try and make sure it wasn’t a permissions issue.

PM’d you…

Loving this! Thank you!

Been giving this some thought and it would be really nice to see this coupled with OCR to allow for notifications when important mail arrives based on keywords detected on the mail itself.

Keywords could be something like “statement”.

Or “Jury Duty” :smile:

That’s beyond my abilities but would be super cool!

Just did a quick hack with tesseract (an open source OCR tool) and it seems that the images are not sufficiently hi-res to provide good image to text and mostly it just spits out garbage.

Here is the tesseract output from your mail image above:

‘ mmmeaoo

' mwnvm
' mma
m us vomas

(mm m

we

 

w uc-asua “WW wan)an

Not very useful as you can see. I’ll keep working on it though.

Oh wow, I just spent a little time installing and implementing the google cloud vision API and it is insanely impressive.

To see what it can do go here: https://cloud.google.com/vision/ and upload the image above to the demo.

Wow, that’s very impressive. Is it free?

Seems to be free (some parts of it are limited to 1000 requests per month)