Files in the top-level directory in any check-in
- .gitignore
- headsilose.erl
- LICENSE
- osrm.erl
- polyline.erl
- README.md
- weather_types.erl
Heads I Lose
This started as a little learning exercise in Erlang, but I've been building on it to make it more useful for my cycle commute. It looks up the wind direction (via the MetOffice Datapoint API) and for a given route (a polyline from OSRM) determines how much of the route is a headwind sidewind or tailwind.
Usage
Since it has just been developed for personal use installation is not very polished.
- Get a MetOffice Datapoint API key and save in a file called
~/.datapoint
. - Get/install Jiffy. (I just cloned the repository, issued
make
and copied theebin
andpriv
directories to myheads-I-lose
directory). - Within the
heads-I-lose
directory, compile witherlc headsilose.erl; erlc weather_types.erl; erlc osrm.erl; erlc polyline.erl
. - Run
erl -run headsilose get_locations <Optional search term> -noshell -s init stop
to get a list of locations and Ids. The optional search term cannot contain spaces. - From within the erlang shell (because I don't yet know how to pass negative numbers on the command line) run
osrm:get_route([<start_lat> ,<start_lon>],[<end_lat>,<end_lon>])
to get a route from OSRM. You'll have to find the latitude and longitudes by some other means) for now. This will save the route in~/.headsilose-route
. - Run
erl -run headsilose headsilose <location id> -noshell
to get the result.
Since I wrote this to be semi-useful for me, the result returned depends on the time of the day. If it's run before 8am it looks for the 6am weather data (since data is in 3 hour periods) and assumes the route is being traversed normally, run between 8am and 7pm it looks for the 6pm data for going home and therefore also traverses the saved route in reverse, and run after that time it looks again for the 6am data, but for the next day, and thus the route is back to being traversed in the normal direction.
Hint: I have a shell function defined as follows:
function headsilose {
erl -pa /home/simon/Code/github/atomicules/heads-I-lose /home/simon/Code/github/atomicules/heads-I-lose/ebin -run headsilose headsilose XXXXXX alternative_geometries -noshell;
}
So I can just call
headsilose
Which will result in something like the following being printed out:
It's a draw
47.1% Headwind
51.45% Sidewind
1.45% Tailwind
Direction: SSW
Speed: 13 mph
Gust: 29 mph
Weather type: Cloudy
Temperature: 4 deg C
Note1: Since the route is from OSRM there is the option to specify alternative_geometries
as an argument. In theory OSRM can return more than one alternative route, but in practice (at least as far as I can tell) I think it only ever returns one alternative route so although the argument is alternative_geometries
it is actually the first alternative that is used. If alternative_geometries
is not specified then the default route is used. If you'd like to see visually which route is the default and which is the alternative you can see them at Project OSRM as routes A (default) and B (alternative).
Note2: I don't use init stop in my main command line call as I have that in my script instead. Otherwise, if headsilose
errors out then init stop
will crash out (I guess because it is trying to stop something that isn't running).
Credits
Various posts I've found that have helped me out:
- Initial inspiration from PragDave - A First Erlang Program
- Putting initial inspiration to practice (i.e.
inets:start
) from Andrew Locatelli Woodcock - Connecting to Cloudant from Erlang: a quick example of using HTTPS from httpc:request - The recursive parsing of XML from Sam Ruby - Parsing Atom with Erlang
- Formating dates with leading zeroes from Warren Young on Stack Overflow
- Figuring out command line arguments from Cody on Stack Overflow
- Figuring out Jiffy
- Rounding numbers
- Converting between binary and decimal
I did read through a number of posts/implementations of polyline decoders, but they didn't really help me in Erlang so I just worked backwards through the specification and wrote my own, much less concise, version rather than porting an existing implementation.
Todo
I should really put these as issues
- Sort the list of locations?
- Finish off implementing the list of client "supposed to"s from the OSRM API, such as checksum and hint data, but this would mean caching all previous requests made.
- Use postcodes to get the latitudes and longitudes via UK Postcodes
- Figure out how to pass negative numbers on the command line (perhaps use getopt?)
- Use tuples instead of lists where it makes sense