I was reading a brilliant post that pretended that the Electric car had been released first and that the Petrol car was trying to attract its first buyers; I highly recommend that you read that article. But the whole article raised one really important question about how much energy it would take to run your house and car on solar. In it’s distilled form the question is essentially:
How many Solar panels and Tesla Powerwalls would I need to take my Household energy usage and Tesla Model S off the grid? (Such that I don’t need to rely on the Grid and fossil fuels ever again)
To answer those questions I made a publicly available Google Spreadsheet:
To fill in that spreadsheet you only need two pieces of information:
With that information you can work out how many solar panels you would need on your roof and how many Tesla Powerwalls you would need to store all of the energy that they generate. I think that you should give it a shot.
However, my conclusion is this: most people that drive close to or under the average for Australian drivers (<= 43km per day) will find that they don’t need significantly bigger Solar Systems and power packs to cover the costs of their Tesla car. And every single home owner on the planet should be able to get enough Solar panels and Powerwalls to cover their household and car energy usage. Good news!
Note: Currently there is no cost analysis here of how much those components will cost. But I will add that companies like Solar City and Sun Edison make getting solar panels a breeze. Also the Gigafactories being build in America right now should dramatically bring down the price of Solar Panels and Powerwalls.
Hopefully this helps somebody and, if you have any questions then please let me know in the comments.
]]>In a nutshell, the code I wrote takes in a standard displacement diagram used to describe the increase and decrease in displacement of a Cam over time. Something that looks like this:

And uses that information to create a 3D model like this:
A cam on a cylinder (known as a disc cam).

A cam on a ramp (also known as an end cam).
If you don’t know what a Cam is then please read the previously linked Wikipedia page. But just because you know what it is does not explain why you would want to make one.
A Cam is an device that turns rotational motion into linear motion an many different ways; this is extremely powerful. In mechanical engineering is is pretty easy to create rotational motion (Electric Motor, Steam, Windmill, Treadmill with mice, etc). This is great and already useful but, in many cases, we then want to perform some kind of linear movement based on this rotation. For example, maybe we want to use the rotational motion to trigger a button a certain number of times per second (like an odometer). In this scenario the rotational motion needs to be turned into the linear motion of pushing the button up and down. This conversion is extremely useful and almost every modern petrol based engine uses a Cam via the aptly named Camshaft; the thing in your car which make the engine pistons go up and down.
However, I am personally very excited by the combination of combining a cam with a spring follower. This allows you to slowly store more and more energy in a spring and then release it all at once explosively, letting you create an automatic catapult. For a rudimentary example of what I mean please see this olive slinging device:
So, with that in mind I wrote a quick program in OpenSCAD to generate Cam for you. At this point in time you can generate two different types of Cam’s: a disc cam and an end cam. The two methods that allow that let you specify:
Lets run through a quick example to show you how it works. With these variables under your control you can then write openscad code that looks like this:
end_cam(displacement = [ [0, 0], [0.2, 0.8], [0.6, 0.5], [1, 1] ], segments = 360, baseHeight = 1, peakHeight = 3, radius = 2, width = 0.5);
And it would produce a Cam that looked like this:

And here is an even more complex example where we made the displacement diagram be the (sin(x)) ^ 2 function.
[ for(i = [0 : 360]) [i / 360, sin(i) * sin(i)] ]
It looks great:

An edge cam generated with the sin(x) ^ 2 function.
And this is very very powerful, you can now create a cam for your own hobby purposes. Here is the full example of test Cams that you can view just by loading up the test-cam.scad file that exists in the source code:

If you wish to add extra fixtures to the Cam’s so that you can attach them to your motors or rotating mechanical devices then the union and difference functions from OpenSCAD are your friends. Good luck. I hope that this helps you on your mechanical endeavours and please post your creations made using this code in the comments section below. I can’t wait to see them!
]]>At the moment I am working on a project to create “The English Alphabet Audio Database” which aims to be the largest (completely free) collection of people speaking the English Alphabet on the planet.
View or contribute to it here: http://robertmassaioli.bitbucket.org/alphabet-upload.html
Note: All submissions have everything but the sound of your voice stripped from them (like filename), ensuring that you remain anonymous except for your voice. And even then, your voice will be in a database of hundreds or more of other voices.
I am collecting this data for the purpose of aiding some speech recognition work that I am doing and thought that, while I was at it, I may as well make a big collection of audio samples than anybody can use for any purpose. I hope that you submit to the audio database.
At 100 samples collected I will release the first version of this database for public consumption, at the moment I only have 6 samples collected so we could use all of the help that we could get! Please contribute. Your voice may be what helps us to bring speech recognition forwards.
There are roughly 335 million English speakers on the planet. I think it is completely reasonable to hope that you will be one of the awesome english speakers that will submit to the database. With your help we could get submissions in the thousands. I hope to eventually fill this database with 100,000 samples.
]]>In this blog post I present you with another video that explains “How to control a Quartz Clock Mechanism”. In the video I explain and show how to connect the clock to a custom electric circuit that you construct and I then provide a method to speed up and slow down a regular quartz clock. I hope you enjoy the video, if you like the video then please let me know in the comments or share it around:
In the video I run through a number of concepts and I want to provide you the links to those concepts here in one convenient location:
Hopefully you can use these resources to control you own Quartz Clock Mechanisms or other electronic circuits.
I have attempted to explain clearly how to control a Quartz Clock Mechanism in the hope that other people might follow suit. With any luck you can now go out there and do something really interesting with Quartz Clock Mechanisms. If you do then please let me know about it. If you have any comments at all, or would like to see me do something else that is interesting with Quartz Clock Mechanisms then please let me know!
Thanks for watching and reading!
]]>Have you ever been on the command line and tried to perform set operations? Have you ever followed crazy cli guides on the internet that suggest complicated commands to try and perform set operations on files. I have. And I did not like it; I think that we can do better.
Over the weekend I wrote a pretty nifty program that I am calling: Setdown. Setdown requires you to specify the set operations that you wish to perform as a definitions in a set definitions file (often suffixed with ‘.setdown’). The setdown language definitions are written in a very similar format to Makefiles; except that it performs set operations.
If you want to install setdown right now or checkout the code then you can follow these links:
The easiest way to install setdown is to:
$ nix-shell -p haskellPackages.setdown $ setdown --help
If you want to learn how to use setdown and write set operations in it’s language then you should read the README file provided in the source code. However, to show you how easy the language is to read you I have provided an example .setdown file right here:
-- All of the letters of the alphabet alphabet: &quot;alphabet.txt.unsorted&quot; -- Calculating the consonants with a set difference consonants: alphabet - &quot;vowels.txt.unsorted&quot; -- Getting any letter than is e-sounding or a vowel e-or-vowels: &quot;e-letters.txt.unsorted&quot; / &quot;vowels.txt.unsorted&quot; -- Get any letter that is e-sounding and a vowel e-and-vowel: &quot;e-letters.txt.unsorted&quot; / &quot;vowels.txt.unsorted&quot; -- Get all of the e-sounding letters, the vowels and the consonants e-or-vowels-or-consonants: (&quot;e-letters.txt.unsorted&quot; / &quot;vowels.txt.unsorted&quot;) / consonantsYou should install setdown and then check out the setdown-examples project to give it a try right now!
Can you show me an example?
By this point in time you are probably wondering “I love the look of it but show me an example”. So I will. Here is the output of a full running example by checking out the first example in the setdown-examples repository and running it:
$ setdown ex1.setdown ==> Creating the environment... Base Directory: ./ Output Directory: ./output ==> Parsed original definitions... e-or-vowels-or-consonants: ("e-letters.txt.unsorted" / "vowels.txt.unsorted") / consonants e-and-vowel: "e-letters.txt.unsorted" / "vowels.txt.unsorted" e-or-vowels: "e-letters.txt.unsorted" / "vowels.txt.unsorted" consonants: alphabet - "vowels.txt.unsorted" alphabet: "alphabet.txt.unsorted" ==> Verification (Ensuring correctness in the set definitions file) OK: No duplicate definitions found. OK: No unknown identifiers found. OK: All files in the definitions could be found. ==> Simplifying and eliminating duplicates from set definitions...DONE: alphabet: "alphabet.txt.unsorted" consonants: alphabet - "vowels.txt.unsorted" e-and-vowel: "e-letters.txt.unsorted" / "vowels.txt.unsorted" e-or-vowels: "e-letters.txt.unsorted" / "vowels.txt.unsorted" e-or-vowels-or-consonants: e-or-vowels / consonants ==> Checking for cycles in the simplified definitions...DONE: OK: No cycles were found in the definitions. ==> Copying and Sorting all input files from the definitions... "alphabet.txt.unsorted" (unsorted) => "./output/alphabet.txt.unsorted.1.split.sorted" (sorted) "e-letters.txt.unsorted" (unsorted) => "./output/e-letters.txt.unsorted.1.split.sorted" (sorted) "vowels.txt.unsorted" (unsorted) => "./output/vowels.txt.unsorted.1.split.sorted" (sorted) ==> Computing set operations between the files... Required results: alphabet: ./output/alphabet.txt.unsorted.1.split.sorted consonants: ./output/c989d1cf-b860-41cc-a52c-e2afc1e6a235 e-and-vowel: ./output/a8bd5974-22d5-4fdb-b269-0c09a1eeeb18 e-or-vowels: ./output/c3a8cc7c-f246-4eb4-b321-57f900964960 e-or-vowels-or-consonants: ./output/493ca813-7e3c-4259-9435-e2d5ddb4d6a5 $As you can see we have ended up with a number of output files. Just to pick one example lets see the contents of the consonants file:
$ cat ./output/c989d1cf-b860-41cc-a52c-e2afc1e6a235 b c d f g h j k l m n p q r s t v w x y z $And look at that, we have computed the consonants when we were given the vowels and the rest of the alphabet. Hopefully you can see that this is very powerful and will let you write increasingly more correct set operations from the command line.
The benefits of setdown
Depending on your command line bent you may have used other tools in the past to perform set operations on files, like comm or fgrep, but these tools are quite lacking. Instead let me show you the full range of features that setdown gives you:
==> Parsed original definitions...
C: "b-1.out" - ("a-1.out" / "a-2.out")
B: "a-1.out" / "a-2.out"
A: ("a-1.out" / "a-2.out") / "b-1.out"
==> Verification (Ensuring correctness in the set definitions file)
OK: No duplicate definitions found.
OK: No unknown identifiers found.
OK: All files in the definitions could be found.
==> Simplifying and eliminating duplicates from set definitions...DONE:
A: "b-1.out" / B
B: "a-1.out" / "a-2.out"
C: "b-1.out" - B
==> Simplifying and eliminating duplicates from set definitions...DONE: A: C B: D C: B D: A ==> Checking for cycles in the simplified definitions...DONE: [Error 20] found cyclic dependencies in the definitions! We found the following cycles: A -> C -> B -> D -> A
I think that this is a much more compelling set operations tool for the command line than anything else that exists out there and I am really happy to share it with you today for free. I also really hope that you get some great usage out of this tool and that it makes your life easier.
From experience I can say, without this tool, dealing with complicated set operations on the command line and sharing your results with your co-workers is much more difficult than it should be.
At any rate I hope that you get a great deal of value from this tool and if you have any comments or suggestions then please ask them here on this blog or raise them as issues. If you have any questions then ask them here or on Stack Overflow.
Thanks for reading and I hope this makes somebodies like a little bit easier.
]]>Very recently I was writing a shared service in Haskell and we realised that we would need to integrate with an email service provider. After a little bit of research I concluded that Mailgun was a great service for developers to send their emails so I looked for Mailgun integration libraries that looked like they were being groomed to be “the” Mailgun library for Haskell and I was disappointed to find that the existing libraries did not seem to be very comprehensive or did not make use of type safety.
So I wrote my own library and I called it “Hailgun”. Then I uploaded it to Hackage.
I believe this library to be better because:
And this is just for version 0.1.0.0. To people that read this in the future, you should check out the library on hackage to see what it impiliments now.
I’m going to explain here how to send a test email using hailgun-send so that you can quickly see that the library works and can be used to send your emails in pure Haskell code.
If you don’t have a Mailgun account and a sandbox for it then go sign up for one. Once you have created your account you should have been given an API key and have a sandbox domain name. Please create a file called ‘hailgun.send.conf’ in the current directory and make the contents of the file:
mailgun-domain = "sandbox-mailgun-domain.com"
mailgun-api-key = "key-thatmailgungaveme9234uoah234"
Once you have that file in place you should then be able to use hailgun-send. For example, this is one invocation that I used:
hailgun-send
--from '[email protected]'
--to '[email protected]'
--subject 'Hailgun v0.1.0 test email'
-x data/email.text
-m data/email.html
You will notice that I provided a from and to address, an email subject and the content of the email in two files. You should create the email.text and email.html files yourself or you could simply use the ones that are avaliable in the repository. Please note that the HTML version of the email is optional but the text version is always required.
You should see something like the following email appear in your inbox:

In short you should now be able to send emails, via Mailgun, with Haskell and the library should be improved to have more API support as time goes by. I hope this is useful to some peoplee and, if a Mailgun developer should happen to swing by this post then please feel free to review my code.
]]>Playing with audio data is a ton of fun and something that I believe that Haskell could do very well. Processing audio data safely and efficiently seems to fit very well into Haskell’s model so, overy a year ago, I started working on and off on a WAVE file format parser. I have been working on it very infrequently (bus trips and other spare time) and I rewrote it once but today I am pleased to announce the release of the very first version of my ‘wavy’ package that lets you extract data from WAVE files in Haskell. The features of this release include:
Things which the library is currently missing include:
The code is on hackage as the wavy library so you can install it by:
cabal update
cabal install wavy
Please feel free to give it a try. Probably the best way to quickly see it working is by finding a WAVE file on your machine:
locate '*.wav'
And then passing that wave file as the first argument into wave-info. For example:
$ wave-info /Applications/Steam.app/Contents/MacOS/Friends/friend_join.wav
File: /Applications/Steam.app/Contents/MacOS/Friends/friend_join.wav - 2s
Format
Audio Format: Microsoft PCM
Channels: 2
Sample Rate: 44100
Bits Per Sample: 16
Byte Rate: 176400
Block Alignment: 4
INFO Metadata
Creation Date: 2010-03-11
Engineers: - Kelly Thornton
Creation Software: Sony Sound Forge 9.0
$
As you can see it can parse an audio file very quickly. The wave-info program is very efficient because the library is lazy and does not parse the data chunk unless you specifically require it.
I would recommend that you start by looking at the executables in the libraries source code for examples of how this library can be used in your applications. The wave-info source code can be found on BitBucket.
Once you have finished doing that then you can have a read throug the documentation on Hackage to get a full understanding of what methods the library provides.
If you have any questions then please do not hesitate to contact me or comment on the blog.
(This blog post was produced using pandoc)
]]>In this guide we are going to have a quick run through the cipher-aes library to show how it can be used in your own projects. We will just stick to simple ECB encryption and leave other encodings for a future guide.
Note: In order to follow along with this guide you will need a working knowledge of Haskell (Understanding the first few chapters of Real World Haskell should do the trick)
But first lets get the imports out of the way:
module Main where
import qualified Crypto.Cipher.AES as CCA
import qualified Data.ByteString as B
import qualified Data.ByteString.Char8 as BC
import qualified Data.ByteString.Base16 as B16
import Data.Char (chr)
You will notice that I like to qualify everything to give you a better idea of which libraries these functions are coming from.
Whenever you wish to begin the encryption you need to provide a seed. You can see that in the type of the initAES method:
initAES :: Byteable b => b -> AES
For the sake of this guide we are going to use a 32 byte hash in order to initialise the AES cipher. This library supports starting with 16, 24 and 32 byte hashes. In most programs that you write this initial seed is going to be called a "secret key" or "shared key"; it will often be stuck in a configuration file in a secure location and it should certainly be kept out of the source code. So developers often like specifying this secret key as a big hexadecimal String. However, even though you could read this string straight into a ByteString that would not be correct because each hexidecimal character only has 16 unique points of data (4-bits).
So the quesiton is: how many hexidecimal characters do we need in order to get 32 bytes of random seed data?
Lets just use Haskell to do it for us. We know that there are four bits of data in each hexidecimal character:
bitsPerHexChar :: Integer
bitsPerHexChar = 4
There are 8 bits per byte:
bitsPerByte :: Integer
bitsPerByte = 8
We want 32 bytes of seed data:
requiredSeedBytes :: Integer
requiredSeedBytes = 32
With that information we can work out how many hexidecimal characters are required:
requiredHexChars :: Integer
requiredHexChars = (requiredSeedBytes * bitsPerByte) `div` bitsPerHexChar
Now this only works because either requiredSeedBytes or bitsPerByte is divisible by 4. In our case they both are.
Now that we know that we need to load requiredHexChars many characters in order to initialise the AES encryption. However this is going to be given to us in this form:
type HexStream = B.ByteString
Where every byte in the stream has 4 bits of unique data. However, the initAES function expects the data to be a little more compressed than that. It expects 8 bits of unique data per per byte to make a true seed for the AES algorithm:
type InputSeed = B.ByteString
And before we even try to convert from one type to the other we should validate that our inputs are correctly formated Hexidecimal strings (validate your inputs):
validHex :: HexStream -> Either String HexStream
validHex input = if inputLength == requiredHexChars
then Right input
else Left $ "Expected " ++ show requiredHexChars ++ " hex characters but instead recieved " ++ show inputLength
where
inputLength :: Integer
inputLength = fromIntegral . B.length $ input
Then we will want a function that converts from one to the other and squishes two 4 bit chunks together to form an 8 bit number. We can do that like so by using the base16-bytestring library:
toSeed :: HexStream -> Either String InputSeed
toSeed input = if B.null errors
then Right seedData
else Left "The input data was not made up of Hexidecimal characters."
where
(seedData, errors) = B16.decode input
We can quickly join the two to have a useful function for loading seed data from hex streams:
toValidSeed :: HexStream -> Either String InputSeed
toValidSeed input = toSeed =<< validHex input
In order to actually make use of these methods we need to have a hexidecimal string to start off with as our input. Here is one that I generated for this guide (you will need to generate another truly random one for your production applications):
chosenHexStream :: HexStream
chosenHexStream = BC.pack "e5d6834e0e52a78a47fc1c8887ca0e0ecd0863df89e6a3eebf7085bd131bb854"
We can then use this seed to create an InputSeed but it might not parse so we want to encode that in the types:
potentialInputSeed :: Either String InputSeed
potentialInputSeed = toValidSeed chosenHexStream
Now that we have our input seed we can initialise an AES encryption context:
aesEnc :: Either String CCA.AES
aesEnc = fmap CCA.initAES potentialInputSeed
And with it we can start to do some encryption! Woo! However, we need some data to try and encrypt…hmmm. Lets make some random test strings:
testData0 :: B.ByteString
testData0 = BC.pack $ "It might seem crazy what I’m about to say"
++ "Sunshine she’s here, you can take a break"
++ "I’m a hot air balloon that could go to space"
++ "With the air, like I don’t care baby by the way"
testData1 :: B.ByteString
testData1 = BC.pack "B-b-b-baby, you just ain't seen n-n-nothin' yet Here's something that you never gonna forget"
testData2 :: B.ByteString
testData2 = BC.pack $ "There's a calm surrender to the rush of day"
++ "When the heat of a rolling wind can be turned away"
So, with this test data we can now try and run some encryption. Lets look at the most basic encryption method:
encryptECB :: AES -> ByteString -> ByteString
Okay, that type seems pretty self explanatory, give me an AES context and the thing that you want to encrypt and I’ll run some ECB encryption over it and give the result to you in a Strict ByteString. So you would think that we could just do something like this:
broken :: Either String B.ByteString
broken = fmap (flip CCA.encryptECB testData0) aesEnc
After all, it even compiles! But, surprisingly, that does not work. Instead you get the following error message:
Encryption error: input length must be a multiple of block size (16). Its length is: 173
As you can see the cipher-aes library apparently requires that all data be aligned to a block size of 16 bytes. I know that the correct units are bytes based on the fact that testData0 is 173 units long. To solve this problem we need to make sure that we are always giving the encryptECB function a bytestring that always meets that boundary. The most sensible way I can think to do that is to use a zero padded bytestring. So lets try and build a funciton that will do that for us:
type PaddedByteString = B.ByteString
zeroPadData :: B.ByteString -> PaddedByteString
zeroPadData input = input `B.append` padding
where
padding = BC.replicate requiredPadding (chr 0)
requiredPadding = case inputLength `mod` 16 of
0 -> 0
x -> 16 - x
inputLength = B.length input
Now with this new zeroPadData function we can build an encryption function that will always work:
safeEncryptECB :: CCA.AES -> B.ByteString -> B.ByteString
safeEncryptECB enc input = CCA.encryptECB enc (zeroPadData input)
With this new safe encryption function we can encrypt all of our test data. However, before we do that lets first try and show what happens when you go in the other direction.
Now that we have function that can encrypt our data we really want a function that can go in the other direction and decrypt it. Lets take a look at the decryptECB function from the cipher-aes library:
decryptECB :: AES -> ByteString -> ByteString
Once again this one is pretty simple, given an AES content and an encoded string of data it will decode it back into the original format. So lets try and write a function that will do the reverse of the operation that we did in the safeEncryptECB function. It is important to note that the data also needs to come back in 16 byte blocks otherwise it cannot be decoded. We can ensure that and use types to handle the errors instead of the error command:
safeDecryptECB :: CCA.AES -> B.ByteString -> Either String B.ByteString
safeDecryptECB enc encodedData = if alignment /= 0
then Left $ "Error: encoded data should have been 16 byte aligned but was off by: " ++ show alignment
else Right . fst . BC.spanEnd (== (chr 0)) $ CCA.decryptECB enc encodedData
where
alignment = B.length encodedData `mod` 16
This function handles encrypting and decrypting the data safely. Which is especially important because often the encrypted data has the potential to be modified by other systems before coming back to us.
However, it is really important to note that the safeEncryptECB and safeDecryptECB functions are not inversions of eachother. Specifically, if you have an input string that legitimately has trailing nul characters and you encrypt it and then decrypt it then those characters will be stripped in the final output. That is something to be wary of. However, the set of strings that do not end in nul characters will be invertable by these functions.
Now that we have all of this we can really bring it all together.
Now that we have put in all of that effort we can really bring it all together with a function that will encrypt the data, show it to us encrypted, and then decrypt it again. Lets give that a try:
-- A hobbits tale...
thereAndBackAgain :: CCA.AES -> B.ByteString -> IO ()
thereAndBackAgain enc input = do
putStrLn $ "Data is: " ++ show input
let encData = safeEncryptECB enc input
putStrLn $ "Encrypted data: " ++ show encData
case safeDecryptECB enc encData of
Left error -> putStrLn error
Right originalData -> putStrLn $ "Original data was: " ++ show originalData
newline
newline = putStrLn ""
We can run that little snippet of code on our test data and watch as it encrypts and decrypts our data. But we also want to make sure that invalid data is handled correctly too, so why don’t we also run something that actually modifies the data before trying to decrypt it again and see what happens:
showErrorsHappening :: CCA.AES -> IO ()
showErrorsHappening enc = do
let testData0Enc = safeEncryptECB enc testData0
print $ safeDecryptECB enc (testData0Enc `B.append` (BC.pack "modified"))
And now that we have done that all that is left is to actually run the code:
main = do
putStrLn "Welcome to the cipher-aes guide by Robert Massaioli."
putStrLn $ "We calculated that we need " ++ show requiredHexChars ++ " hexidecimal characters in the seed in order to initialise the AES cipher."
case aesEnc of
Left error -> putStrLn $ "Error parsing chosenHexStream: " ++ error
Right aes -> do
putStrLn "Parsed successfully."
newline
thereAndBackAgain aes testData0
thereAndBackAgain aes testData1
thereAndBackAgain aes testData2
putStrLn "Showing an error happening by data that is too long:"
showErrorsHappening aes
putStrLn "All tests ran successfully"
This guide is actually a literate Haskell source file so you can run it and watch the results printed on the screen. Please check out the repository on BitBucket for this guide to give it a try. If you have any questions then please post them below and thankyou for reading!
(Note: This guide was designed to be converted into HTML for use in WordPress via pandoc.)
]]>The RIFF file format is an old file format that is used as a container format for WAVE files among other things. Recently I decided that I wanted to write some pure Haskell code that could parse this file format so that I can start working my way towards building audio libraries in pure Haskell.
Yes. You can view the results of my efforts on hackage: The riff package. You can even view the code on BitBucket if you like.
That package contains:
You can give it a try today to read some RIFF files and it is all pretty self explanitory. I hope somebody gets some good use out of this. I am going to try and keep this library small and focused; please feel free to contribute and let me know what you think. And if you use it for something then especially let me know. It would make me very happy.
]]>[warn] there were 1 feature warning(s); re-run with -feature for details
[warn] one warning found
[warn] warning: /home/robert/installed/play-2.2.1/framework/../repository/cache/com.atlassian.connect/ac-play-java_2.10/jars/ac-play-java_2.10-0.6.4.jar(com/atlassian/connect/play/java/controllers/AcController.class): major version 51 is newer than 50, the highest major version supported by this compiler.
[warn] It is recommended that the compiler be upgraded.
[warn] warning: /home/robert/installed/play-2.2.1/framework/../repository/cache/com.atlassian.connect/ac-play-java_2.10/jars/ac-play-java_2.10-0.6.4.jar(com/atlassian/connect/play/java/AC.class): major version 51 is newer than 50, the highest major version supported by this compiler.
[warn] It is recommended that the compiler be upgraded.
[warn] warning: /home/robert/installed/play-2.2.1/framework/../repository/cache/com.atlassian.connect/ac-play-java_2.10/jars/ac-play-java_2.10-0.6.4.jar(com/atlassian/connect/play/java/AcHost.class): major version 51 is newer than 50, the highest major version supported by this compiler.
[warn] It is recommended that the compiler be upgraded.
[warn] warning: /home/robert/installed/play-2.2.1/framework/../repository/cache/com.atlassian.connect/ac-play-java_2.10/jars/ac-play-java_2.10-0.6.4.jar(com/atlassian/connect/play/java/CheckValidOAuthRequest.class): major version 51 is newer than 50, the highest major version supported by this compiler.
[warn] It is recommended that the compiler be upgraded.
[warn] warning: /home/robert/installed/play-2.2.1/framework/../repository/cache/com.atlassian.connect/ac-play-java_2.10/jars/ac-play-java_2.10-0.6.4.jar(com/atlassian/connect/play/java/token/CheckValidToken.class): major version 51 is newer than 50, the highest major version supported by this compiler.
[warn] It is recommended that the compiler be upgraded.
[warn] 5 warnings
In this particular case you should notice that it says “major version 51 is newer than 50”. This means that we are using a Java 6 Compiler when we should be using a Java 7 compiler and you can confirm this by:
$ javac -version javac 1.6.0_27 $
As you can see it is, in-fact, the Java 6 compiler (1.6 means Java version 6). So what do we do to fix this problem? Simple, you just make it so that a Java 7 version of javac is higher in your PATH environment variable than the one that is currently being used. You’ll know when you have it working and setup correctly when you see something like this:
$ javac -version javac 1.7.0_40 $
For more information on how to change your path variable see this StackOverflow post.
]]>