This is a project I have been working on a while called Tappt.  Tappt is a frontend for your kegerator which tracks temperature and the beer in your keg.

The hardware is built using an Arduino Uno, a NFC shield, and a WiFi shield. For the app I am using Android but I will port this to iOS and windows phone.  The backend and website were written using ASP.Net MVC 4 and WebApi as well as Angular.js.

The Arduino and Android portions of this prototype can be found on github at https://github.com/jlkalberer/Tappt-Kegerator and https://github.com/jlkalberer/Tappt-Android.

** Update **
Someone has already started work on the library.  You can read about it here.  You can view the library on github (as of this writing) here.

So if you like me wanted to do a project using NFC peer-to-peer (P2P) between Android and Arduino (the P532 chip) there is no doubt that you have spent countless hours searching for libraries or examples which have already implemented this feature.  You may have even built test application for Android (I used this one) and a sketch for your Arduino (I started with this sketch).  I at least saw that the NFC was communicating between the devices so it’s a start.  It took me a few days of searching before I even got to this point.  Now I needed to figure out why I wasn’t actually sending the NDEF message from Android — the breakpoint at createNdefMessage is never reached. Continue reading

So I am writing this post mostly to help people get up to speed who like myself, had never programmed Android before and need to set up their Nexus 7 device.

Through a simple google search you probably end up at the Using Hardware Devices page on the Android site.  The instructions here are pretty straight forward but I wanted to include a few gotchas in my guide. Continue reading

For many of my projects I use MediaElementJS. This is an awesome library for HTML5 video with a fallback to Flash or Silverlight. Anyway, I had a client request to add google analytics for all their videos. I found the following code which adds the events to each player in order to start tracking events.   The code is a great start but I needed a deeper dive than simply the play, pause, and completed counts for each video.  I decided to track which parts of the videos were viewed by bucketing the videos into 30 second chunks.

google analytics mediaelementjs example

*I was tweaking the code while working on it so the last three buckets (8,9,10) should be merged with 4,5,6 but you get the idea.

The code is fairly straight forward but I thought I would post it as it may help someone out who needs to accomplish the same task.

$.extend(mejs.MepDefaults, {
    googleAnalyticsTitle: '',
    googleAnalyticsCategory: 'Videos',
    googleAnalyticsEventPlay: 'Play',
    googleAnalyticsEventPause: 'Pause',
    googleAnalyticsEventEnded: 'Ended',
    googleAnalyticsEventTime: 'Time'
});

var formatTime = function (timeInSeconds) {
    var sec_numb = parseInt(timeInSeconds);
    var hours = Math.floor(sec_numb / 3600);
    var minutes = Math.floor((sec_numb - (hours * 3600)) / 60) + hours * 60;
    var seconds = sec_numb - (hours * 3600) - (minutes * 60);

    if (seconds < 10) { seconds = "0" + seconds; }
    return minutes + ':' + seconds;
};

$.extend(MediaElementPlayer.prototype, {
    buildgoogleanalytics: function (player, controls, layers, media) {
        var timeInterval = 30, counter = 1, time, currentInterval = 0;
        media.addEventListener('play', function () {
            if (typeof _gaq != 'undefined') {
                _gaq.push(['_trackEvent',
					player.options.googleAnalyticsCategory,
					player.options.googleAnalyticsEventPlay,
					(player.options.googleAnalyticsTitle === '') ? player.currentSrc : player.options.googleAnalyticsTitle,
                    parseInt(player.getCurrentTime())
				]);
            }

            time = parseInt(player.getCurrentTime());
            counter = 1;
            while (timeInterval * counter < time) {
                counter += 1;
            }
        }, false);

        media.addEventListener('pause', function () {
            if (typeof _gaq != 'undefined') {
                _gaq.push(['_trackEvent',
					player.options.googleAnalyticsCategory,
					player.options.googleAnalyticsEventPause,
					(player.options.googleAnalyticsTitle === '') ? player.currentSrc : player.options.googleAnalyticsTitle,
                    parseInt(player.getCurrentTime())
				]);
            }
        }, false);

        media.addEventListener('ended', function () {
            if (typeof _gaq != 'undefined') {
                time = parseInt(player.getCurrentTime());
                currentInterval = timeInterval * counter;
                _gaq.push(['_trackEvent',
                        player.options.googleAnalyticsCategory,
                        player.options.googleAnalyticsEventEnded,
                        (player.options.googleAnalyticsTitle === '') ? player.currentSrc : player.options.googleAnalyticsTitle,
                        time
                    ]);
                _gaq.push(['_trackEvent',
                    player.options.googleAnalyticsCategory,
                    formatTime(currentInterval - timeInterval) + " - " + formatTime(time),
                    (player.options.googleAnalyticsTitle === '') ? player.currentSrc : player.options.googleAnalyticsTitle
                ]);
            }
        }, false);

        media.addEventListener('timeupdate', function () {
            if (typeof _gaq != 'undefined') {
                time = parseInt(player.getCurrentTime());
                currentInterval = timeInterval * counter;
                if (time > currentInterval) {
                    counter += 1;
                    _gaq.push(['_trackEvent',
                        player.options.googleAnalyticsCategory,
                        formatTime(currentInterval - timeInterval) + " - " + formatTime(currentInterval),
                        (player.options.googleAnalyticsTitle === '') ? player.currentSrc : player.options.googleAnalyticsTitle
                    ]);
                }
            }
        }, true);
    }
});

Just a quick diversion between company projects at work.  This is our company holiday card.  I used ImpactJS to write it — the library had some compatibility issues here and there with various mobile devices but overall it is a good framework.

P.S.  I am back in the land of Appcelerator for the time being so I should have a large update to the Mvc framework at some point.

So as promised, I am diving deeper into my Appcelerator Mvc framework. In this post I will give more complex examples on how to use my framework in conjunction with joli so you can truely see how to integrate my framework in a complex, data-driven application. If you haven’t read over the basics or how the routing module works, I recommend you do so. You may also want to read my post on jsAutomapper. Continue reading

Hey, I just wanted to get it out there that my Appcelerator Mvc implementation is up in the Appcelerator marketplace. It has some bug fixes and improvements over the original example I gave here.

This week I plan on writing the more in-depth tutorial for using the framework so that should give some better examples on how to use the framework on a large application.

Now that we have went over the basics of my Appcelerator Mvc implementation, we can move onto more advanced features. For this post I will focus on routing. The post should be fairly short since the routing is fairly straight forward. As I mentioned in the first post on this framework, I borrowed heavily from the routing model used in Asp.Net. Although I don’t implement all the routing principles used in it’s model, I think what I have implemented should be more than enough for any Appcelerator application. Fish On!

I was recently tasked to create a mobile app at work. Since I had never worked on a mobile app (not counting web-based apps), I started searching for a cross-platform framework. To make a long story short, I settled with Appcelerator. I have run into some issues while working on my app but for the most part there are simple workarounds. I love working with javascript and I can definitely see the platform is going somewhere. What I didn’t like is how easy it is to make bad javascript and end up with very large files. This was a problem that I could solve myself.

I searched around the internet and found a few solutions. Some people were using PureMvc or similar frameworks. I read through the documentation and the frameworks were either too complex for my needs or may have felt out of place when used with Appcelerator. I did find something close to what I wanted by Scott Montgomerie. My issues with his implementation was that you constantly have to deal with the current window context and you are coupling your views with your controllers. I also like to stay away from the ‘new’ keyword when working with javascript. In addition I wanted routing as I am used to the MVC style of Asp.Net MVC (may be overkill but it was nice to have). It’s what I know and I love it :) . Keep reading