2015-05-29

It all started with a trip to a garage sale where I purchased a weedwacker and a scythe....

While the weedwacker sort of kind of did an OK job on the weeds at my place, it certainly wasn't up to the task of clearing out some blackberries. After putting a decent edge on the scythe, I proceeded to get some exercise by putting a hurting on some head high blackberries.

The scythe had a short thick blade that is ideal for weeds and brush. However, I wanted something a bit lighter and geared more toward cutting grass and pasture plants..... so off to the interwebs I went!

Fortunately for me, I soon found http://www.baryonyxknife.com/, and woooweee am I glad that I did.

My order was simple: a "beater" grass blade, and please draw a coffee cup on the packaging.

a few days later

less than a week later, this package arrived for me. Look at that sweet coffee cup!

Thanks http://www.baryonyxknife.com/!!!

a little something extra

Within the package, was a cardboard wrapped grass blade... and taped to the cardboard wrapping was a small steel can-opener. How cool is that? hella cool.

bolted to the snath

A few turns of the wrench later, and my new blade was attached to a snath that I had purchased a few weeks prior.

Oh, in case you didn't know, a snath is a scythe handle.

a comparison

The long slender bladed scythe with the aluminium snath is Gloria, and the squat blade with the wooden handle is Agnes (yes, it is named after Groundkeeper Willie's shovel)

Gloria is light, nimble and ready to bring down some grass. Agnes on the other hand, is beefy and ready to make blackberries weep.

mmmmm beans

Then I used the can-opener to open some beans. It took far less time than I thought it would. :)

If there is a comments section as part of an online order form, I will always write "please draw a coffee cup on the packaging", and I can say that http://www.baryonyxknife.com/ really pulled through.

Now if you will excuse me, I have a scythe that needs sharpening, and there are a few items I need to order from baryonyx. :)

Comments
Name:
not required
Email:
not required (will not be displayed)
Website:
not required (will link your name to your site)
Comment:
required
Please do not post HTML code or bbcode unless you want it to show up as code in your post. (or if you are a blog spammer, in which case, you probably aren't reading this anyway).
Prove you are human by solving a math problem! I'm sorry, but due to an increase of blog spam, I've had to implement a CAPTCHA.
Problem:
9 minus 5
Answer:
required
  • Tags:
2015-04-08

Not too long ago, I purchased a programmable remote for my DSLR camera so that I could take long exposures as well as multiple exposures in order to create time lapse videos. While the timer does a great job, I still needed a way to convert a series of images into a video.

Fortunately, ffmpeg does a great job of converting a pile of images into a video file, and I most certainly have ffmpeg installed on my laptop. Now all I need is a bit of code to:

  1. search for some files
  2. copy and rename the files
  3. always skip step 3 :)
  4. use ffmpeg to convert the files to a video

When the script runs, it looks for a directory named 'images' and recursively looks for files in that directory (my camera tends to make multiple directories of files). Then the files are copied into a temp folder and given a 6 digit name: 000001, 000002, 000003, etc. Finally, ffmpeg converts those 6 digit named files into a video.

Enter The Ruby

#!/usr/bin/env ruby
require 'fileutils'
require 'date'

#where will we look for files?
LOCAL_DIR File.expand_pathFile.dirname(__FILE__) )
TEMP_DIR File.join(LOCAL_DIR"temp")
IMAGES_DIR File.join(LOCAL_DIR"images")
#if the temp dir exists, delete it and its contents
if Dir.exists? TEMP_DIR
    FileUtils.rm_rf TEMP_DIR
end

#make the temp dir
FileUtils.mkdir TEMP_DIR

#keep track of how many files we have
@file_count 0

def copy_files(location)
  files = []
  dirs = []
  Dir.foreach(locationdo |name|
    #ignore . and ..
    if name!='.' and name!='..'
      #what is the path of the item?
      path File.join(location,name)
      #recurse if path is a directory
      if Dir.exists? path
        dirs << path
      else
        files << path
      end
    end
  end
  #sort the directories by name and recurse
  dirs dirs.sort()
  dirs.each do |d|
    puts "DIRECTORY: #{d}"
    copy_files(d)
  end
  #sort the files by name and recurse
  files files.sort()
  files.each do |d|
    new_name @file_count.to_s
    #increment the file_count
    @file_count+=1
    ## pad the new file name with 0
    (6-new_name.length()).times do
      new_name "0"+new_name
    end
    #determine where the new file is going
    new_file File.join(TEMP_DIRnew_name)
    #what is the command to copy the file?
    copy_command "cp #{d} #{new_file}"
    puts copy_command
    #run the command
    `#{copy_command}`
  end
end

#recursively get a list of all files in the current directory
copy_files(IMAGES_DIR)

#what day is it?
ymd Date.today.strftime("%Y%m%d")

#what video command should we run?
cmd "ffmpeg -y -f image2 -i temp/%06d -b:v 50000k  #{ymd}_timelapse.avi"
#run the command
`#{cmd}`

By default, the ffmpeg command will create a video at 10 frames/second.

My first time lapse was during Sunset on the Equinox

Sadly, I didn't adjust the camera properly when capturing the April 4th Lunar Eclipse. However, considering I set everything up 7 hours before the eclipse, I think I did a fairly sweet job of determining where to point the camera. :)

Now quit reading, slow down, and speed up.

Comments
2015-04-22 Alison Chaiken:
'gst-launch multifilesrc location="somematchingstring"' would work as well.
Name:
not required
Email:
not required (will not be displayed)
Website:
not required (will link your name to your site)
Comment:
required
Please do not post HTML code or bbcode unless you want it to show up as code in your post. (or if you are a blog spammer, in which case, you probably aren't reading this anyway).
Prove you are human by solving a math problem! I'm sorry, but due to an increase of blog spam, I've had to implement a CAPTCHA.
Problem:
5 minus 5
Answer:
required
2015-03-15

The Magic starts at 3:30AM... because at 3:30AM every day, a cron task runs on the chicken coop computer to determine when the coop door should open and close later that day. For most of my weather needs I had been using the http://wunderground.com API, but for some reason, they don't offer access to twilight data through the API and I didn't want to write a webpage scraper to harvest the data from their website.

Fortunately for me, hamweather.com has a wonderful API accessible weather service with great documentation, all at a very reasonable price (free, if making less than 750 API calls per day).

For this piece of the project, I decided to use civil twilight as the opening and closing times. Then it was just a matter of reading the hamweather API documentation for sun and moon data and then hacking together some code. Since the majority of the code is written in Python, I opted to use python for this script.

Enter the Python

#!/usr/bin/env python2
import urllib
import json
import os.path
import subprocess
import time

client_id "MY_CLIENT_ID"
client_secret "MY_CLIENT_SECRET"
url="http://api.aerisapi.com/sunmoon/MY_CLOSEST_TOWN?client_id=%s&client_secret=%s" % (client_idclient_secret)

print url

script_dir os.path.dirnameos.path.realpath(__file__) )
data_file os.path.join(script_dir'sunmoon.json')
open_script os.path.join(script_dir,"open_door.sh")
close_script os.path.join(script_dir,"close_door.sh")

try:
  #read the data from the url and write it to a file
  response urllib.urlopen(url)
  data response.read()
  open(data_file"w")
  f.write(data)
  f.close()
except:
  #something failed, open the old data file
  open(data_file,'r')
  data f.read()

#load the json into an object
json_object json.loads(data)

#get the twilight from the json object
twilight json_object['response'][0]['sun']['twilight']

#get the twilight start and end
civilbegin twilight['civilBegin']
civilend twilight['civilEnd']

#format the start and end times in Hour:Minute format
twilight_start time.strftime("%H:%M"time.localtime(civilbegin))
twilight_end time.strftime("%H:%M",time.localtime(civilend))

#create commands based on the times
open_cmd =  "at -f "+open_script +' '+twilight_start
close_cmd =  "at -f "+close_script +' 'twilight_end

#run the commands as a subprocess
subprocess.call(open_cmdshell=True)
subprocess.call(close_cmdshell=True)

During the event loop of my door controller, a file is checked to see if the door should open or close, and the door behaves accordingly. This twilight fetching script will determine when to open and close the door, and submits a command to at, which then handles the timing for running the open or close script.

The chickens will be going into their new home next weekend, and the close time will probably need to be adjusted, but that just means I need to hang out in the hammock at sunset/twilight and see if all the chickens go in the coop before the door closes.

Now quit reading, and go make something that can only be tested by relaxing in a hammock at sunset. :)

Comments
2015-06-28 Tim Diskataneous:
Nice work. I'm looking for my first project and it's cool to see what you made. I bet the chickens wonder who opens and closes the door every day!
Name:
not required
Email:
not required (will not be displayed)
Website:
not required (will link your name to your site)
Comment:
required
Please do not post HTML code or bbcode unless you want it to show up as code in your post. (or if you are a blog spammer, in which case, you probably aren't reading this anyway).
Prove you are human by solving a math problem! I'm sorry, but due to an increase of blog spam, I've had to implement a CAPTCHA.
Problem:
5 minus 5
Answer:
required
  • Tags:
  • Python
subscribe
 
2015
2014
2013
2012
2011
2010
December
November
October
September
August
July
June
May
April
March
February
January
2009
December
November
October
September
August
July
June
May
April
March
February
January
2008