From:
[email protected]
Date: 2018-10-24
Subject: Using GNU Recutils to Track Car Maintenance History
I have an older car that needs regular maintenance. My maintenance
history is stored on a pile of crumpled papers in the glovebox.
This makes it hard to get a holistic picture of my car's mainte-
nance history. It's good to know what you've had done when the
service department is making recommendations.
There are services like Carfax that will provide a detailed history
for a little money, but the value of something like Carfax is to
see maintenance records for a used car before you buy it, not to
track maintenance on a vehicle you already own. Plus, I already
have two years of maintenance data sitting in the glovebox.
What information to track? I've created a class diagram to help me
think through this.
@startuml
'render at plantuml.com/plantuml
class Car
class Activity
class Provider
Car: make
Car: model
Car: year
Activity: date
Activity: mileage
Service: description
Provider: name
Provider: address
Provider: city
Provider: state
Provider: zip
Car *-- Activity
Provider *-- Activity
Activity *-- Service
@enduml
So we have a **Car** that represents my Honda, a **Provider** like
Jiffy Lube, an **Activity** representing a visit to the shop, and
**Service** items that represent specific things that were done to
the car, like an oil change.
I'm going to change this a bit when I implement it in recutils.
* I only have one car, so I'm not going to associate data with a car.
* I'm going to merge the Activity and Service objects. There
will be some duplication of data, but it will be easier to manage.
* I'll be doing all my reporting from the Service type, so that's
where I'll store all the foreign keys.
Here is my recfile with all the field properties. You could, of
course, do much of this in a spreadsheet, sacrificing some flexi-
bility.
%rec: Service
%key: Id
%auto: Id
%type: Provider rec Provider
%type: Mileage int
%sort: Mileage
%mandatory: Id Date Mileage Description Provider
%rec: Provider
%key: Id
%auto: Id
%mandatory: Id Name
Now, I've gone through the nominally laborious task of translating
my service invoices into recfiles. I had to summarize some of the
line items on the invoices. I did this in an editor, but you could
also use recins, possibly within a script.
%rec: Service
%key: Id
%auto: Id
%type: Provider rec Provider
%sort: Mileage
Id: 1
Date: 2017-06-12
Mileage: 151140
Description: Tire rotation
Provider: 1
Id: 2
Date: 2017-06-12
Mileage: 151140
Description: Replaced thermostat, refilled and bled cooling system
Provider: 1
Id: 3
Date: 2017-06-12
Mileage: 151140
Description: Replaced cabin air filter
Provider: 1
%rec: Provider
%key: Id
%auto: Id
Id: 1
Name: Honda Dealer
Now I can pull a succinct history using recsel.
recsel -t Service -pDate,Mileage,Description service.rec
to get
Date: 2018-09-10
Mileage:
Description: Reinstall FR bumper, clips
Date: 2017-02-21
Mileage: 148881
Description: Minor inspection
Date: 2017-02-27
Mileage: 149003
Description: Oil Change
I can limit the data returned using a selection expression. For
example, I can have it show only oil changes.
recsel -t Service -e 'Description = "Oil Change"' -pDate,Mileage,Description service.rec
to get
Date: 2017-02-27
Mileage: 149003
Description: Oil Change
Date: 2017-10-20
Mileage: 155328
Description: Oil Change
Date: 2018-01-03
Mileage: 158262
Description: Oil Change
It would be pretty neat to see how many miles had elapsed between
oil changes. I think awk would be a good tool for this. First, we
need to transform these vertical records into linewise records.
There are probably a number of ways to do this. Here's an awk
script that does the job.
awk '/./ {ln = ln $0 "\t"}; /^$/ {print ln; ln = ""};'
You could also do it in sed like this:
sed -ne '/./ H;/^$/ {x;s/^\n//;s/\n/\t/g;p};${g;s/^\n//;s/\n/\t/g;p}'
One more thing we need to do is strip the field labels from the
output of recsel. This is easily done by changing the `-p` option
to `-P`. So, to get tabular output, we pipe the output of recsel
into awk.
recsel -t Service -e 'Description = "Oil Change"' -PDate,Mileage,Description service.rec | awk '/./ {ln = ln $0 "\t"}; /^$/ {print ln; ln = ""};'
to get
2017-02-27 149003 Oil Change
2017-10-20 155328 Oil Change
2018-01-03 158262 Oil Change
2018-05-17 162140 Oil Change
Now we can do some math with another awk script. This script looks
at the mileage on each line, subtracts the mileage from the previ-
ous line, and displays the difference at the end of the line.
awk '{print $0 "\t" $2-prev; prev = $2}'
We can pipe the output of the previous command into this awk script
to get
2017-02-27 149003 Oil Change 149003
2017-10-20 155328 Oil Change 6325
2018-01-03 158262 Oil Change 2934
2018-05-17 162140 Oil Change 3878
My guess is I lost a service record for an oil change somewhere
during June 2017. I could check my credit card statements during
that period to see if I can find a payment to an auto shop. I like
to think that I'm diligent about oil changes, but I can see I have
some room for improvement.
More ideas:
* Add an Exhibit Number to each Service record so that you
can quickly find the specific paper maintenance record that it
came from.
* Use a plotting tool like GNUplot or Google Charts to plot
mileage or expense over time.
* Track maintenance expenses against the market value of the
car to help you decide when to replace it.
* Print a succinct maintenance history to keep in your glovebox.