Categories
Raspberry Pi

Monitoring the temperature of my Raspberry Pi Camera

In late April of this year I wrote a script that would capture the temperature of the Raspberry Pi that sits above my Hummingbird feeder and log it to a file.

It’s a straight forward enough script that captures the date, time and temperature as given by the internal measure_temp function. In code it looks like this:

MyDate="`date +'%m/%d/%Y, %H:%M, '`"
MyTemp="`/opt/vc/bin/vcgencmd measure_temp |tr -d "=temp'C"`"
echo "$MyDate$MyTemp" >> /home/pi/Documents/python_projects/temperature/temp.log

I haven’t ever really done anything with the file, but one thing I wanted to do was to get alerted if (when) the temperature exceeded the recommended level of 70 C.

To do this I installed ssmtp onto my Pi using apt-get

sudo apt-get install ssmtp

With that installed I am able to send an email using the following command:

echo "This is the email body" | mail -s "This is the subject" user@domain.tld

With this tool in place I was able to attempt to send an alert if (when) the Pi’s temperature got above 70 C (the maximum recommended running temp).

At first, I tried adding this code:

if [ "$MyTemp" -gt "70" ]; then
   echo "Camera Pi Running Hot" | mail -s "Warning! The Camera Pi is Running Hot!!!" user@domain.tld
fi

Where the $MyTemp came from the above code that get’s logged to the temp.log file.

It didn’t work. The problem is that the temperature I’m capturing for logging purposes is a float, while the item it was being compared to was an integer. No problem, I’ll just make the “70” into a “70.0” and that will fix the … oh wait. That didn’t work either.

OK. I tried various combinations, trying to see what would work and finally determined that there is a way to get the temperature as an integer, but it meant using a different method to capture it. This is done by adding this line:

ComparisonTemp=$(($(cat /sys/class/thermal/thermal_zone0/temp)/1000))

The code above gets the temperature as an integer. I then use that in my if statement for checking the temperature:

if [ "$ComparisonTemp" -gt "70" ]; then
   echo "Camera Pi Running Hot" | mail -s "Warning! The Camera Pi is Running Hot!!!" user@domain.tld
fi

Giving a final script that looks like this:

MyDate="`date +'%m/%d/%Y, %H:%M, '`"
MyTemp="`/opt/vc/bin/vcgencmd measure_temp |tr -d "=temp'C"`"
echo "$MyDate$MyTemp" >> /home/pi/Documents/python_projects/temperature/temp.log
ComparisonTemp=$(($(cat /sys/class/thermal/thermal_zone0/temp)/1000))

if [ "$ComparisonTemp" -gt "70" ]; then
   echo "Camera Pi Running Hot" | mail -s "Warning! The Camera Pi is Running Hot!!!" user@domain.tld
fi
Categories
Work

Using Drafts 5 at Work

I have many meetings that I go to in any given day. One of the things that I’d been struggling with was being able to keep track of what I needed to do after a meeting and/or documenting certain types of meetings more effectively.

I have been using a Workflow I created a couple of years ago to get the pertinent details of a meeting into Drafts. I spoke about updating that workflow to incorporate drafts 5 here.

Once I was able to get the information into Drafts 5 a new opportunity arose. I was able to run a Workflow in Drafts!

I decided that getting the information into Drafts was great, but I needed a good way to get it out.

There were two sections in the Draft that I decided I could leverage to help:

  1. Actions
  2. Notes

Broadly speaking there are 3 types of meetings I go to:

  1. Daily Standup aka Scrum
  2. One-on-One with direct reports or my manager
  3. General Meetings

Categorizing the meetings helped me to create Draft Actions that run Workflows for each meeting type.

Scrum

This workflow runs through the Actions of the Draft and adds each one to OmniFocus in a Project called Scrum with a Tag of Work. The due date set for these tasks is noon of the same day. My goal is to have the items that come from Scrum totally processed by noon of that day and for 80% of them I can. Some actions are more involved, but having them in OmniFocus helps me to make sure that they get taken care of.

It also creates a calendar meeting for the next business day with my Scrum template and lets me know which team member will start that next day.

One-on-One

This workflow runs similarly to the Scrum workflow. It adds the Action items to OmniFocus with a due date of noon the same day, tagged with Work and in the One-on-One Project.

Instead of creating a calendar meeting for the next business day at 8:30 it appends items from the Notes section to a Dropbox file. The Dropbox path is predefined, but the name of the file matches the name of the person I met with (luckily I don’t have 2 Tom’s reporting to me).

General Meetings

This is the simplest workflow. It adds all of the items under actions to OmniFocus with a due date of noon, project of Meeting Follow Up and Tag of Work.

After the Actions are run from Drafts the notes are archived in Drafts.

I’m toying with the idea of archiving the notes from these meetings into Dropbox, but I’m not sure that it gets me anything … so I haven’t really looked at it too deeply.

Workflow links

The links for each of the workflows can be found here:

Parse Scrum Notes

Parse One-on-One Notes

Parse Meeting Notes

Categories
Productivity Work

Updating my meeting Workflow for Drafts 5

Drafts is a productivity app created by Greg Pierce (@AgileTortoise).

I’ve loved and used Drafts 4 every day for the last several years. I loved it so much I even contributed to the Tip Jar Greg had in the app. Seriously, it’s an amazing app. If you haven’t downloaded it already you totally should.

Recently, Greg released Drafts 5. With this new version comes a new Business Model as well. Instead of a single pay (and hope people ‘tip’ you) he’s converted to a subscription model.

I signed up for the free week and didn’t have a real opportunity to use it before my free week was converted into a pay week but I’ve no regrets. I like what Greg does and want him to keep updating his app so that I can get the benefits of it once I have a real chance to dive in.

Part of the reason I wasn’t able to really use the new version is the way that I primarily use Drafts. I have a WorkFlow that takes a meeting on my work calendar and allows me to take notes about that meetings.

It’s one of the most useful productivity tools I have during my morning standup meetings with my team, and it’s useful for the other (sometimes endless) meetings that I go to.

With the release of Drafts 5 I was not longer able to use both Drafts 5 AND my workflow, so I needed to update my workflow.

With Drafts 4 it was just one of the built in Apps. Because Drafts 5 limits some of the functionality unless you have the PRO version I don’t think that Workflow will be updated to include Drafts 5 like it did Drafts 4.

Once I realized that AND since I’m paying for the app I figured I’d need to update my Workflow instead of waiting and hoping that Workflow would be updated to include Drafts 5.

In order to make the update I had to look for URL Scheme for Drafts 5 … but I couldn’t really find one. I assumed that Drafts 5 URL Scheme would be the same as Drafts 4 (I was right) and made various attempts at getting a copy of the Workflow to work with Drafts 5.

This is the section of the workflow that needs to be updated:

Since Drafts 5 isn’t included in the Built in Apps I was going to need to pass a URL and open the app.

This would require 3 separate steps in Workflow

  1. Convert Text into URL Encoded string
  2. Prepend the URL Scheme for creating a new draft to the URL Encoded String
  3. Open the URL

This basically means that 1 step is now replaced with 3 … but hey, that’s the price of progress must be paid!

Both the Drafts 4 and Drafts 5 versions of these workflows are available.

If you enjoy them, hit me up in the comments or let me know on Twitter @ryancheley!

Categories
Automation

Automating the Hummingbird Video Upload to YouTube or How I finally got Cron to do what I needed it to do but in the ugliest way possible

Several weeks ago in Cronjob Redux I wrote that I had finally gotten Cron to automate the entire process of compiling the h264 files into an mp4 and uploading it to YouTube.

I hadn’t. And it took the better part of the last 2 weeks to figure out what the heck was going on.

Part of what I wrote before was correct. I wasn’t able to read the client_secrets.json file and that was leading to an error.

I was not correct on the creation of the create_mp4.sh though.

The reason I got it to run automatically that night was because I had, in my testing, created the create_mp4.sh and when cron ran my run_script.sh it was able to use what was already there.

The next night when it ran, the create_mp4.sh was already there, but the h264 files that were referenced in it weren’t. This lead to no video being uploaded and me being confused.

The issue was that cron was unable to run the part of the script that generates the script to create the mp4 file.

I’m close to having a fix for that, but for now I did the most inelegant thing possible. I broke up the script in cron so it looks like this:

00 06 * * * /home/pi/Documents/python_projects/cleanup.sh
10 19 * * * /home/pi/Documents/python_projects/create_script_01.sh
11 19 * * * /home/pi/Documents/python_projects/create_script_02.sh >> $HOME/Documents/python_projects/create_mp4.sh 2>&1
12 19 * * * /home/pi/Documents/python_projects/create_script_03.sh
13 19 * * * /home/pi/Documents/python_projects/run_script.sh

At 6am every morning the cleanup.sh runs and removes the h264 files, the mp4 file and the create_mp4.sh script

At 7:10pm the ‘header’ for the create_mp4.sh runs. At 7:11pm the ‘body’ for create_mp4.sh runs. At 7:12pm the ‘footer’ for create_mp4.sh runs.

Finally at 7:13pm the run_script.sh compiles the h264 files into an mp4 and uploads it to YouTube.

Last night while I was at a School Board meeting the whole process ran on it’s own. I was super pumped when I checked my YouTube channel and saw that the May 1 hummingbird video was there and I didn’t have to do anything.

Categories
Automation Raspberry Pi

Cronjob Redux

After days of trying to figure this out, I finally got the video to upload via a cronjob.

There were 2 issues.

Issue the first

Finally found the issue. Original script from YouTube developers guidehad this:

CLIENT_SECRETS_FILE = "client_secrets.json"

And then a couple of lines later, this:

% os.path.abspath(os.path.join(os.path.dirname(__file__), CLIENT_SECRETS_FILE))

When crontab would run the script it would run from a path that wasn’t where the CLIENT_SECRETS_FILE file was and so a message would be displayed:

WARNING: Please configure OAuth 2.0
To make this sample run you will need to populate the client_secrets.json file
found at:

  %s

with information from the Developers Console
https://console.developers.google.com/

For more information about the client_secrets.json file format, please visit:
https://developers.google.com/api-client-library/python/guide/aaa_client_secrets

What I needed to do was to update the CLIENT_SECRETS_FILE to be the whole path so that it could always find the file.

A simple change:

CLIENT_SECRETS_FILE  = os.path.abspath(os.path.join(os.path.dirname(__file__), CLIENT_SECRETS_FILE))

Issue the second

When the create_mp4.sh script would run it was reading all of the h264 files from the directory where they lived BUT they were attempting to output the mp4 file to / which it didn’t have permission to write to.

This was failing silently (I’m still not sure how I could have caught the error). Since there was no mp4 file to upload that script was failing (though it was true that the location of the CLIENT_SECRETS_FILE was an issue).

What I needed to do was change the create_mp4.sh file so that when the MP4Box command output the mp4 file to the proper directory. The script went from this:

(echo '#!/bin/sh'; echo -n "MP4Box"; array=($(ls ~/Documents/python_projects/*.h264)); for index in ${!array[@]}; do if [ "$index" -eq 0 ]; then echo -n " -add ${array[index]}"; else echo -n " -cat ${array[index]}"; fi; done; echo -n " hummingbird.mp4") > create_mp4.sh

To this:

(echo '#!/bin/sh'; echo -n "MP4Box"; array=($(ls ~/Documents/python_projects/*.h264)); for index in ${!array[@]}; do if [ "$index" -eq 0 ]; then echo -n " -add ${array[index]}"; else echo -n " -cat ${array[index]}"; fi; done; echo -n " /home/pi/Documents/python_projects/hummingbird.mp4") > /home/pi/Documents/python_projects/create_mp4.sh

The last bit /home/pi/Documents/python_projects/create_mp4.sh may not be neccesary but I’m not taking any chances.

The video posted tonight is the first one that was completely automatic!

Now … if I could just figure out how to automatically fill up my hummingbird feeder.

Categories
Raspberry Pi

Using MP4Box to concatenate many .h264 files into one MP4 file

The general form of the concatenate command for MP4Box is:

MP4Box -add <filename>.ext -cat <filename>.ext output.ext1

When you have more than a couple of output files, you’re going to want to automate that -cat part as much as possible because let’s face it, writing out that statement even more than a couple of times will get really old really fast.

The method below works but I’m sure that there is a better way to do it.

  1. echo out the command you want to run. In this case:

(echo -n "MP4Box "; for i in *.h264; do echo -n " -cat $i"; done; echo -n " hummingbird.mp4") >> com.txt

  1. Edit the file com.txt created in (1) so that you can change the first -cat to -add

vim com.txt

  1. While still in vim editing the com.txt file add the #!/bin/sh to the first line. When finished, exit vim2
  2. Change the mode of the file so it can run

chmod +x com.txt

  1. Run the file:

./com.txt

Why am I doing all of this? I have a Raspberry Pi with a Camera attachment and a motion sensor. I’d like to watch the hummingbirds that come to my hummingbird feeder with it for a day or two and get some sweet video. We’ll see how it goes.

  1. The -add will add the <filename> to the output file while the -cat will add any other files to the output file (all while not overwriting the output file so that the files all get streamed together).
  2. I’m sure there’s an xkcd comic about this, but I just can’t find it!