Author Archives: druss

Export all workouts from Sports Tracker


Advertisement from Google

sports tracker export all workouts in gpx formatAlmost all sport tracking sites do not have “Export all” functionality. They want you to stay with them as long as possible. The same with Sports Tracker. There is no such functionality on their website, you can export workouts only one by one (which is annoying).

But with a bit of JS magic, we can download all workouts in GPX format.

  1. Login at http://www.sports-tracker.com/
  2. Go to http://www.sports-tracker.com/diary/workout-list
  3. Click “Show more” button at the end of the page until you have all workouts loaded.
  4. Go to developer console (press Ctrl + Shift + I in Google Chrome)
  5. Insert following JS and press Enter:

Advertisement from Google

var items = $("ul.workouts li a");

var key = "sessionkey=";
var valueStartIndex = document.cookie.indexOf(key) + key.length;
var token = document.cookie.substring(valueStartIndex, document.cookie.indexOf(';', valueStartIndex));

$('body').html('');

$.each(items,function(i, value)
{
    var href = $(value).attr("href");
    var id = href.substr(href.lastIndexOf('/') + 1, 24);
    var url = 'http://www.sports-tracker.com/apiserver/v1/workout/exportGpx/' + id + '?token=' + token;
    var filename = 'SportsTracker-' + id + '.gpx';
    $.ajax({
        url: url,
        success: function(data, textStatus, jqXHR)
        {
            if(textStatus == 'success')
            {
                $('<a/>', {
                    'href' : 'data:text/plain;charset=utf-8,' + encodeURIComponent(jqXHR.responseText),
                    'download' : filename,
                    'id' : id
                }).html(filename)
                .before(i + '. Downloaded: ')
                .after('<br/>')
                .prependTo('body');

                $('#' + id)[0].click();
            }
            else
            {
                console.log(textStatus);
            }
        },
        dataType: 'xml'
    });
});

All gpx files will be in Download folder.

[ASP.NET Core 1.0] Automatic Migrations in Entity Framework 7 (EF Core 1.0)

There is no more

public Configuration()
{
    AutomaticMigrationsEnabled = false;
}

in Entity Framework Core 1.0 (formerly  EF 7.0)

Now you can use extension Migrate method during database initialization.

For example, you have custom DBInitializer class:

public class DBInitialization
{
    public static void Initialize()
    {
        using (var context = new DbContext())
        {
            context.Database.Migrate();
           
            // Other db initialization code.
        }
    }
}

There is also async version of this method. This method will apply any pending migrations.

You can call DBInitialization.Initialize at the end of Configure method at Startup class.

ZohoPeopleTimeLogger v1.3 – Show me the error

At Novility, we have  found that we cannot log working time anymore. You just press “Make me happy” button and nothing 🙁

When ZohoPeopleTimeLogger tries to make you happy it needs information about current jobs from ZOHO. For example, if I try to log time for January 16 and there is no job for this date I will get an error. But user was not able to see that error. That is fixed in release v1.3.

Download

GitHub

User will see message box with detailed description and nice instructions:ZohoPeopleTimeLogger-v1.3

[IoT] Connect Intel Galileo Gen 2 to Arduino Uno via nRF24L01

Connect Intel Galileo Gen2 to Arduino Uno via nRF24L01Guys from Newark element14 have sent me a nice dev board – Intel Galileo Gen2. I was curious because before, Microsoft declared that Windows 10 IoT Core will run on this board. I planned to run my previous benchmark on this board to see if it can beat Raspberry PI 2. Unfortunately, with the latest release they removed this board from the compatibility list 🙁

But this is not a big problem because I have some plans about home automation and I can use this board in it. I have couple nRF24L01 modules in my desk, so I’ve decided to test how good this module will work with Galileo board. To test wireless connection I need a second device, and I have one! Arduino Uno 🙂 I’ve connected one nRF24L01 to the Galileo board and one to Arduino. Galileo has worked as transmitter and Arduino as a receiver. Now, I will describe how I did that.

Setup

  1. Download the Arduino Software
  2. Open Arduino IDE
  3. Go to Tools -> Board -> Boards Manager and install the Intel i586 core
  4. Connect Intel Galileo to power supply
  5. Connect it to USB
  6. Open example: File -> Examples -> 1.Basics -> Blink.
  7. Select board: Tools -> Boards -> Intel Galileo Gen2
  8. Select port: Tools -> Port -> COM# (where # is number, usually 3)
  9. Press Upload button
  10. You should see blinking LED

Install nRF24L01 library

Now we need some library to work with nRF24L01. Here you can find a lot of them, I will use RF24.

  1. Download library
  2. In Arduino IDE go to Sketch -> Include Library -> Add .Zip Library…
  3. Select downloaded archive
  4. Done!

Send data

Let’s send some data to test if this library is working well. We will send current time to the other board and will receive a response with the same data. Also we will calculate a time between send and receive operations.

But we first need to connect nRF24L01 to our boards. Here is pinout from nRF24L01:

24L01Pinout-800

and this is how you should connect it:

PIN	NRF24L01	Intel Galileo Gen2	
1	GND	        GND	
2	VCC	        3.3V	
3	CE	        digIO 7
4	CSN	        digIO 8
5	SCK	        digIO 13
6	MOSI	    digIO 11
7	MISO	    digIO 12
8	IRQ	        -

You should use the same for Arduino board.

Now open new sketch and past this code:

/*
* Getting Started example sketch for nRF24L01+ radios
* This is a very basic example of how to send data from one node to another
* Updated: Dec 2014 by TMRh20
*/
#include <SPI.h>
#include "RF24.h"
/****************** User Config ***************************/
/***      Set this radio as radio number 0 or 1         ***/
bool radioNumber = 0;
/* Hardware configuration: Set up nRF24L01 radio on SPI bus plus pins 7 & 8 */
RF24 radio(7,8);
/**********************************************************/
byte addresses[][6] = {"1Node","2Node"};
// Used to control whether this node is sending or receiving
bool role = 0;
void setup() {
  Serial.begin(115200);
  Serial.println(F("RF24/examples/GettingStarted"));
  Serial.println(F("*** PRESS 'T' to begin transmitting to the other node"));
  
  radio.begin();
  // Set the PA Level low to prevent power supply related issues since this is a
 // getting_started sketch, and the likelihood of close proximity of the devices. RF24_PA_MAX is default.
  radio.setPALevel(RF24_PA_LOW);
  
  // Open a writing and reading pipe on each radio, with opposite addresses
  if(radioNumber){
    radio.openWritingPipe(addresses[1]);
    radio.openReadingPipe(1,addresses[0]);
  }else{
    radio.openWritingPipe(addresses[0]);
    radio.openReadingPipe(1,addresses[1]);
  }
  
  // Start the radio listening for data
  radio.startListening();
}
void loop() {
  
  
/****************** Ping Out Role ***************************/  
if (role == 1)  {
    
    radio.stopListening();                                    // First, stop listening so we can talk.
    
    
    Serial.println(F("Now sending"));
    unsigned long time = micros();                             // Take the time, and send it.  This will block until complete
     if (!radio.write( &time, sizeof(unsigned long) )){
       Serial.println(F("failed"));
     }
        
    radio.startListening();                                    // Now, continue listening
    
    unsigned long started_waiting_at = micros();               // Set up a timeout period, get the current microseconds
    boolean timeout = false;                                   // Set up a variable to indicate if a response was received or not
    
    while ( ! radio.available() ){                             // While nothing is received
      if (micros() - started_waiting_at > 200000 ){            // If waited longer than 200ms, indicate timeout and exit while loop
          timeout = true;
          break;
      }      
    }
        
    if ( timeout ){                                             // Describe the results
        Serial.println(F("Failed, response timed out."));
    }else{
        unsigned long got_time;                                 // Grab the response, compare, and send to debugging spew
        radio.read( &got_time, sizeof(unsigned long) );
        unsigned long time = micros();
        
        // Spew it
        Serial.print(F("Sent "));
        Serial.print(time);
        Serial.print(F(", Got response "));
        Serial.print(got_time);
        Serial.print(F(", Round-trip delay "));
        Serial.print(time-got_time);
        Serial.println(F(" microseconds"));
    }
    // Try again 1s later
    delay(1000);
  }
/****************** Pong Back Role ***************************/
  if ( role == 0 )
  {
    unsigned long got_time;
    
    if( radio.available()){
                                                                    // Variable for the received timestamp
      while (radio.available()) {                                   // While there is data ready
        radio.read( &got_time, sizeof(unsigned long) );             // Get the payload
      }
     
      radio.stopListening();                                        // First, stop listening so we can talk   
      radio.write( &got_time, sizeof(unsigned long) );              // Send the final one back.      
      radio.startListening();                                       // Now, resume listening so we catch the next packets.     
      Serial.print(F("Sent response "));
      Serial.println(got_time);  
   }
 }
/****************** Change Roles via Serial Commands ***************************/
  if ( Serial.available() )
  {
    char c = toupper(Serial.read());
    if ( c == 'T' && role == 0 ){      
      Serial.println(F("*** CHANGING TO TRANSMIT ROLE -- PRESS 'R' TO SWITCH BACK"));
      role = 1;                  // Become the primary transmitter (ping out)
    
   }else
    if ( c == 'R' && role == 1 ){
      Serial.println(F("*** CHANGING TO RECEIVE ROLE -- PRESS 'T' TO SWITCH BACK"));      
       role = 0;                // Become the primary receiver (pong back)
       radio.startListening();
       
    }
  }
} // Loop

This is default example from the RF24 library. We will run this code on both boards, the only difference is line number 10:

bool radioNumber = 0;

you should change it to:

bool radioNumber = 1;

before uploading to Arduino, so Intel Galileo will have radioNumber set to 0 and Arduino to 1.

  • Upload this sketch to both Arduino and Galileo.
  • Keep both boards connected via USB
  • Open putty
  • Connect one instance of putty to Serial COM3 (Galileo port) with 115200 baud
  • Other one to COM4 with the same speed
  • In first terminal press T
  • You should see messages about sending and receiving data.
  • If not, check your circuit and code (do not forget about radioNumber).

Here is more photos from my evening:

Intel Galileo Gen2 nrf24l01

Work in progress…

 

Intel Galileo Gen2

Intel Galileo Gen2

 

In the next article, I will describe linux side of the Intel Galileo Gen2 board.

Build and test ASP.NET 5 application using AppVeyor

ASP.NET 5 vNextFor those who do not know, AppVeyor is Continuous Integration and Deployment service for .NET projects. It is free for open-source projects.

Currently, AppVeyor supports latest DNX version (1.0.0-rc1-final) and I’ve recently migrated my pet project to this version. I will show you how easy it is to build and run all unit tests on CI server every time you commit to GitHub.

Visual Studio project (MSBuild)

In LearnWordsFast project we are using Visual Studio 2015 as a development environment, so in AppVeyor we can use default configuration with a bit of tweaking.

By default AppVeyor will use MSBuild to build your project. Here is the steps needed to configure AppVeyor:

  • Restore nuget packages.  Set dnu restore as “before build script” in build settings.
  • Configure custom test command. Set dnx -p test/LearnWordsFast.Test test script in a test settings.

Now your project is ready for build and test. Just press “New Build” button.

It is also recomended to keep your CI settings in a repo. So just put appveyor.yml in your repo:

version: 1.0.{build}
before_build:
- cmd: dnu restore
test_script:
- cmd: dnx -p test/LearnWordsFast.Test test
build:
  verbosity: normal

You can use following links as examples:

GitHub: https://github.com/drussilla/LearnWordsFast

AppVeyor: https://ci.appveyor.com/project/druss/learnwordsfast

DNX project

I have also created “pure” dnx project. No *.sln or *.xproj files. To build it with AppVeyor you just need to change build script setting

Set dnu build src\Backend test\Backend.Test as a cmd script in build settings.

I have also added one optimization to reduce build time. By default, every time you build your project AppVeyor creates a clean environment. We can save our packages folder, so dnu restore does not need to download all packages every build. Add C:\Users\appveyor\.dnx\packages folder to “Cached directories and files” in Environment settings.

Resulted appveyor.yml:

version: 1.0.{build}
cache: C:\Users\appveyor\.dnx\packages
before_build:
- cmd: dnu restore
build_script:
- cmd: dnu build src\Backend test\Backend.Test
test_script:
- cmd: dnx -p test/Backend.Test test
build:
  verbosity: normal

You can use following links as examples:

GitHub: https://github.com/drussilla/EmptyDnxApplication

AppVeyor: https://ci.appveyor.com/project/druss/emptydnxapplication

You can just copy EmptyDnxApplication repo and use it as a skeleton for your own projects.

In the next article, I will show you how to deploy your APS.NET 5 application to a Linux server using AppVeyor deployment functionality.

[ASP.NET 5] Lazy DBContext initialization with Entity Framework 7

vNext

I will show you how to do lazy db context initialization with Entity Framework 7.

The idea is simple, we need an easy way to get database context in a request. If db context was used in the request we should call SaveChanges method and dispose used context if not we shouldn’t do anything.

For “client”, code should look like this:

public class SomeRepository
{
    private readonly IDbContext _db;

    public SomeRepository(IDbContext db)
    {
        _db = db;
    }

    public void Add(Item item)
    {
        _db.Current.Items.Add(item);
    }
}

Nothing more. All routine will happen under the hood.

Let’s define IDbContext interface first:

public interface IDbContext
{
    void SetContext(Lazy<DbContext> context);

    DbContext Current { get; }
}

And “lazy” implementation:

public class LazyDbContext : IDbContext
{
    private Lazy<DbContext> _currentContext; 
    public void SetContext(Lazy<DbContext> currentContext)
    {
        _currentContext = currentContext;
    }

    public DbContext Current => _currentContext.Value;
}

As you can see this is just a “container” for our lazy context initializer. Whenever we want to use DbContext we should call IDbContext.Current and it will be created.

Let’s register this implementation in DI container:

 services.AddScoped<IDbContext, LazyDbContext>();

As you can see I’ve used scoped context. LazyDbContext will be created for each request.

Now we need a place to create lazy initializer and place to call SaveChanges and Dispose method in case DbContext was used. For this we can use SessionMiddleware:

public class SessionMiddleware
{
    private readonly RequestDelegate _request;
    
    public SessionMiddleware(RequestDelegate request)
    {
        _request = request;
    }

    public async Task Invoke(HttpContext context)
    {
        var contextProvider = context.RequestServices.GetService(typeof(IDbContext)) as IDbContext;
        if (contextProvider == null)
        {
            throw new Exception("IDbContext is not registered.");
        }

        var lazyContext = new Lazy<DbContext>(() => new DbContext());
        contextProvider.SetContext(lazyContext);
        using (new RequestDbContext(lazyContext))
        {
            await _request(context);
        }
    }
}

I am using Disposable pattern here to ensure that DbContext is destroyed. Here is implementation:

public class RequestDbContext : IDisposable
{
    private readonly Lazy<DbContext> _context;
     
    public RequestDbContext(Lazy<DbContext> context)
    {
        _context = context;
    }

    public void Dispose()
    {
        if (_context.IsValueCreated && _context.Value != null)
        {
            _context.Value.SaveChanges();
            _context.Value.Dispose();
        }
    }
}

And now register your SessionMiddleware:

app.UseMiddleware<SessionMiddleware>();

As you can see implementation is pretty simple but weel enough to meet my requirements. Now we will have access to the same DbContext in the same request. And if we do not use DbContext at all it will not be created.

All of this was tested on Linux with SQLite database provider.

[WPF][MVVM] TreeView: Scroll To Selected Item

Here is the MVVM way to bring selected TreeViewItem into a view.

First we need an attached behavior. We cannot use regular behavior because we will attach this property through Style.

public class BringSelectedItemIntoViewBehavior
{
	public static readonly DependencyProperty IsBringSelectedIntoViewProperty = DependencyProperty.RegisterAttached(
		"IsBringSelectedIntoView", typeof (bool), typeof (BringSelectedItemIntoViewBehavior), new PropertyMetadata(default(bool), PropertyChangedCallback));

	public static void SetIsBringSelectedIntoView(DependencyObject element, bool value)
	{
		element.SetValue(IsBringSelectedIntoViewProperty, value);
	}

	public static bool GetIsBringSelectedIntoView(DependencyObject element)
	{
		return (bool) element.GetValue(IsBringSelectedIntoViewProperty);
	}

	private static void PropertyChangedCallback(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs dependencyPropertyChangedEventArgs)
	{
		var treeViewItem = dependencyObject as TreeViewItem;
		if (treeViewItem == null)
		{
			return;
		}

		if (!((bool) dependencyPropertyChangedEventArgs.OldValue) &&
			((bool) dependencyPropertyChangedEventArgs.NewValue))
		{
			treeViewItem.Unloaded += TreeViewItemOnUnloaded;
			treeViewItem.Selected += TreeViewItemOnSelected;
		}
	}

	private static void TreeViewItemOnUnloaded(object sender, RoutedEventArgs routedEventArgs)
	{
		var treeViewItem = sender as TreeViewItem;
		if (treeViewItem == null)
		{
			return;
		}

		treeViewItem.Unloaded -= TreeViewItemOnUnloaded;
		treeViewItem.Selected -= TreeViewItemOnSelected;
	}

	private static void TreeViewItemOnSelected(object sender, RoutedEventArgs routedEventArgs)
	{
		var treeViewItem = sender as TreeViewItem;
		treeViewItem?.BringIntoView();
	}
}

And now we can attach this behavior through property in a ItemContainerStyle:

<TreeView>
	<TreeView.ItemContainerStyle>
		<Style TargetType="{x:Type TreeViewItem}">
			<Setter Property="local:BringSelectedItemIntoViewBehavior.IsBringSelectedIntoView" Value="True"/>
			<Setter Property="IsSelected"
					Value="{Binding IsSelected, Mode=TwoWay}" />
		</Style>
	</TreeView.ItemContainerStyle>
</TreeView>

Done! Just set IsSelected to true from code.

Here is full project (C# 6.0) on GitHub

[ASP.NET 5] Production Ready Web Server on Linux. Kestrel + Supervisord

vNextIn the previous article I’ve used nohup + su + init.d script to run kestrel in a background. But as Daniel Lo Nigro suggested in comments it’s much easier to do the same with Supervisor

And he was absolutelly right, config is much smaller, and you can easelly see status and output of a program.

First, install supervisor:

sudo apt-get install supervisor

Now you can create config for your application:

sudo nano /etc/supervisor/conf.d/kestrel_default.conf

With following content:

[program:kestrel_default]
command=su -c "/home/username/.k/runtimes/kre-mono.1.0.0-beta3/bin/k kestrel" username
directory=/home/username/mvc/HelloMvc
autorestart=true
autostart=true
stdout_logfile=/home/username/mvc/HelloMvc/logs/app_std_out.log
stderr_logfile=/home/username/mvc/HelloMvc/logs/app_err.log

Specify path to your dnx and application, as well as username under which you want to run your application (usually user who has dnx installed)

Now you can tell supervisor to reread configurations:

sudo supervisorctl reread
sudo supervisorctl update

This command will automaticaly start your application (we specified autostart=true in config).

To see current status and start\stop applications execute:

sudo supervisorctl

There you can stop application:

stop kestrel_default

Start:

start kestrel_default

Or check program’s output:

tail kestrel_default

ZohoPeopleTimeLogger v1.2 – Special for Andre

Because Andre is so special, the previous version of ZohoPeopleTimeLogger was not working with his account. I’ve fixed couple issues in the program to make him happy. Now, my friend, you can enjoy this lovely program! This release (v1.2) is dedicated to you!

Download

Now seriously!

There was a small issue in a way I got information from zoho. I used user email to get user specific data (time log) but as I found out it is case sensitive, so Andre@something.com and andre@something.com are different logins. And guess what? Only Andre has his email with a capital letter. Zoho people login process is case insensitive, so it doesn’t matter in which case you type you email.

Now, when you login, ZohoPeopleTimeLogger will retrieve your unique user id from zoho and will use it in all further requests instead of your email.

As a bonus, I have added one UX improvement. ZohoPeopleTimeLogger will remember your last entered email, so you don’t need to retype it again in case of wrong password response.

ZohoPeopleTimeLogger Login

 

P.S. As always, source code available on github

[C#] Zoho People Client Library

zoho-people-icon Zoho People Client v1.0.0 released.

ZohoPeopleClient – C# asynchronous client library to interact with the Zoho People API.

Supported API

  • TimeLogAPI (Get/Add/Delete)
  • JobsAPI (Get)
  • LeaveAPI (GetHolidays)
  • FetchRecordAPI (Get)

NuGet Package

NuGet package

Source Code

GitHub

Current Release

Latest Release

Build Status

Build Status

Examples

Sign in with login and password

var client = new ZohoClient();
var token = await client.LoginAsync(login, password);
// save token for further use

Sing in with token

// load token from storage
var client = new ZohoClient();
client.Login(token);

Get TimeLog items

var timeLogItems = await client.TimeTracker.TimeLog.GetAsync(
 "testUser@email.com",
 new DateTime(2015, 07, 01),
 new DateTime(2015, 07, 20));

Add TimeLog record

var newLogId = await client.TimeTracker.TimeLog.AddAsync(
 "testUser@email.com",
 new DateTime(2015, 07, 30),
 "269998000000314122",
 TimeSpan.FromHours(8),
 "non-billable");