Category : Web

Listen Live

imageToo much effort reading my ramblings ? Want to listen instead ? Now you can !!

Courtesy of the excellent odiogo, the excellent text to speech service. This is a free service that bloggers can use, it takes your RSS feed, splits it out to each separate post and then creates a MP3 for the post.

The text-to-speech quality is really good, only about 1 in 50 words is corrupt/unintelligible – easily high enough quality to get a good rendition of the post. Obviously it depends on the content of the post, I have not yet listened to a post with lots of sample code or the like, but I expect it would be pretty hard going.

Get the audio for this blog here. You can even subscribe in iTunes. I will also update the site to include the links in the sidebar.

GEO 51.4043197631836:-1.28760504722595

NikePlus Gets An F Minus

One of the things I find really helpful in terms of motivation (for running) is having easy visibility of weekly, monthly and total mileages, times, paces etc.

nikeplus_sportband So, a couple of weeks ago I bought myself a Nike+ Sportband. This promised it all – a senor that fits in your shoe and automatically records your distance, time and speed and wirelessly transmits it to a wristband. The wristband also has a detachable USB connector / screen that you simply plug into your PC and the data is auto uploaded to the Nike+ web site.

For too long I have been using an Excel spreadsheet and manually copying it between PCs, in the past couple of months I had started getting to grips with WCF by putting together a running log application that I had planned to host on my web site (just for me) – no need for that any longer, Nike+ was going to solve all my problems and more…

How wrong I was. I cannot tell you (although that is exactly what this post is trying to do) how technically inept this product is, not just the wristband but also the web site, the whole experience in fact.

coding-horror-official-logo-small If you are familiar with the class book ‘Code Complete’ you will know about a ‘Coding Horror’ (things you really should not do when writing software), Jeff Atwood even used the term for the name of his great blog – well this isn’t all software, so lets call them ‘Design Horrors’.

The first ‘Design Horror’ comes from trying to invent a new and snazzy way to secure a piece of technology to your wrist. Watch straps have been around for hundreds of years, everyone knows how to use it right ?, the only advancement in wrist fastening / securing technology ever was to use a Velcro patch to secure the two separate lengths of strap together (typically in sports pieces, for added speed). Did this stop the Nike engineers, no way – they came up with a new paradigm in wrist strap technology. One length of strap has 10 small holes, spaced by about 2 or 3 mm, the other length has two stud like protrusions that (using one hand) you must line up with the required two holes and push into place with a force just less than that required to push your thumb through the flesh of your wrist.

‘Design Horror’ 2 (DH2) is similar to that of DH1, remember the detachable USB connector / screen thing I mentioned, well to secure it the USB connector pushing into a slot in the wristband and then it is secured by one of these studs pressed into a hole, however the button on the face of the screen is exactly above that stud and pushing the USB thingy down to make sure it is secured typically results in the button being forcibly pressed for a few seconds (resulting in the device trying to locate the shoe sensor), also I’m not comfortable with the amount of pressure placed upon the button this regularly (thumb through the wrist pressure)….

nikeplus_logo ‘Design Horror’ 3 (DH3) is the ‘clock’ facility of the wristband. I may be being unfair here, this could be a ‘by design’ issue that was never part of the requirements (which would make it a Product Requirements Horror instead). The wristband has the ability to display the current time, as well as the mileages, pace etc. Naturally you would think that Nike position it as a watch replacement for runners, however I cannot believe that is the case. how could they imagine it would replace my watch which not only has alarms, date functions, countdown timers etc with something that only shows the time, nothing else, and does so without any form of backlighting, so that trying to read it outside the core hours of 10am to 4pm result in a painful headache and a trip to the optician for thick lenses. Obviously the decision to save what couldn’t be more than 10p, for a tiny surface mount device giving date/time features, in the cost of materials seemed important to them.

‘Design Horror’ 4 (DH4) is the orientation of the display. This is in the most difficult to read position available (regardless of how the thing is worn). The display does not read along the length/drop of your arm like most watches – no, it reads perpendicular to the length/drop of your arm. So, now, instead of just squinting at the display with no backlighting you are also skewing your arm / wrist into some crazy angle like a contortionist.

nikeplus_utility ‘Design Horror’ 5 (DH5) brings us to the client side software that you need on your PC to interface with the USB thingy and auto upload your run data. When you plug the USB thingy in it auto starts the ‘Nike+ Utility’, however it is started behind all other application windows. Further, on first using it it displays a login facility pre-populated with the username of ‘Guest’. Clicking in the username textbox to try and change it results in nothing ?? Nowhere does it mention it, but I have since determined that you log into the site via a browser and then the Username is picked up for the ‘Nike+ Utility’ from a cookie or something…
What part of “we’ll show a username that the user knows is not theirs and give them no visible means of changing it” seemed sensible at the design stage ??

‘Design Horror’ 6 (DH6) falls into the areas of calibration and uploading runs. You can see from the screen shot that there is a calibration tab (the sensor is basically a pedometer and it needs to be calibrated to your stride length for accuracy) – the problem is that as soon as the USB thingy is plugged in the Nike+ utility starts and uploads any outstanding runs, before you calibrate. So my very first experience with this, when I’m still in the ‘happy’ zone about my purchase is a run being uploaded that is the wrong distance. All the shiny graphics depict that I am considerably slower and run shorter distances than I actually do – what a deflation. of course, my first though is that I’ll just edit the run and update it with the correct distance  – leading me nicely to DH7.

‘Design Horror’ 7 (DH7) is the fact that I cannot edit any of the runs I upload, neither can I manually upload/input runs. With all the (fun) challenges available on the site, design to further motivate people, not providing this feature is a big letdown. Just in terms of personal motivation, Nike+ shows my Total for this year as 18 odd miles, but I didn’t buy it till July, being able to correct that with accurate values should be possible, unfortunately it’s not. Likewise some kind of import facility for all my old runs, should be – but isn’t…

‘Design Horror’ 8 (DH8) is the communication between the wristband and the Nike+ web site – it seems to be one way, certainly none of the totals from the web site are reflected in the wristband figures – I ‘reset’ my wristband the other day to recalibrate (the distances suggested by the unit were 1.05 miles in 8 out, even after calibration) and now it tells me my total is 1.93 miles (even though I calibrated it to 2 miles exactly).nikeplus_run

The final ‘Design Horror’ (DH9) is the accuracy of the data. The run depicted in the image was an 8 miler I did, steady pace, no walking, flat terrain and a fast finish. the data does not reflect that, it looks like I actually stopped around 2.5 miles and slowed at the end. Nice graphs are great, but if I don’t trust your data then what’s the point.

The whole web site is flash/shockwave based and pretty slow, it is also difficult to navigate and non intuitive.

On the flip side, it is a great idea, some of the web site features are really neat – the ability to challenge other runners, join ‘virtual teams’ and have team challenges – it’s a pretty good social networking for runners site all in all. It only costs £40 for the kit (sensor and wristband), so it doesn’t break the bank.
BUT – It could be incredible if the hardware and software are sorted out !!

My message to Nike – Just Do It

GEO 51.4043197631836:-1.28760504722595 

Replace in Files for PowerShell

A while back I restructured my website so that this blog no longer started at the root, instead starting from /blog. This was so that I could introduce some other web apps and have a subfolder for projects etc.

One of the pains of this restructure was modifying all the links – I thought I had caught all this with a Redirector HttpModule, but recently realised that for some reason I had not caught images embedded in the posts themselves.
Also it was becoming a pain having to remember to include the HttpModule in my web.config everytime I upgraded my blog (dasBlog)

I wanted it fixed properly this time, so grabbed a copy of all the XML files in my ‘content’ folder, copied them to a local folder and cracked open PowerShell…

I wanted every instance of www.mywebsite.com changed to www.mywebsite.com/blog – not difficult, but this would also change valid urls such as www.mywebsite.com/blog/page.aspx to www.mywebsite.com/blog/blog/page.aspx (note the /blog/blog in the url)

So I got everything I needed done with two ‘one liners’ in PowerShell…

dir | %{ $a = get-content $_ ; $a = $a -replace (“www.mywebsite.com”, “www.mywebsite.com/blog”) ; set-content $_ $a }

…and…

dir | %{ $a = get-content $_ ; $a = $a -replace (“www.mywebsite.com/blog/blog”, “www.mywebsite.com/blog”) ; set-content $_ $a }

All fixed…

 

GEO 51.4043197631836:-1.28760504722595 

drop.io

I was recording some audio earlier today and the quality from my cheap, generic headset/microphone was woeful.dropio_logo-1, so I searched around for a service that I could make a telephone call into and it would record the spoken audio and give me a WAV or MP3file.

I came across http://drop.io – this is a neat little Web 2.0 service that allows sharing of files, media etc, sending stuff via email, receiving stuff via email, fax, voice etc.

One of the features was a US telephone voicemail service that recorded my spoken content and stored it in my private ‘drop’ as an MP3 – exactly what I was looking for.

Whilst I could have, undoubtedly, found the specific service I was looking for from a UK provider the cool features that these guys provide made me want to use them :-

  • Conference Calling number (not recorded). drop.io
  • Voicemail Number (audio is recorded and left in your ‘drop’ as a MP3).
  • Add content via a custom @drop.io email address.
  • Add content via fax.
  • Email alerts to any updates to your drop.
  • RSS feed for action on your drop.
  • Security model where I can invite people to view my drop, or add content etc.
  • Add notes / links to your drop.
  • Zip up the whole drop and provide a link.
  • Really nice, clean look and feel.
  • FREE !!

You can also upgrade to pro version (paid for) that provide more than the 1GB of storage or keep drops open for longer than the defaults or even shorten the url of your drop (in the free version this is http://drop.io/user_chosen_drop_name min of 7 characters) – to two letters http://drop.io.kj for example…

GEO 51.4043197631836:-1.28760504722595

Outlook IMAP

OutlookIMAPFoldersNow that I have moved us over to Google Apps For Your Domain (GAFYD) completely, I have been fighting with Outlook to get a decent user / email experience.

It just doesn’t seem to flow well – I got the SMTP/IMAP send/receive stuff all set up and working correctly, but it’s clunky.

I have all the folders appearing in my Outlook client but the UX just does not flow – in order to LABEL a email (in google terms) I have to move it to a folder named as the LABEL I want to apply (if I want to label it ‘Outdoor’ I simply move it to the ‘Outdoor’ folder). Equally, anything I have labelled will be visible in that folder (if I labelled it ‘Outdoor’ then it’ll be in my ‘Outdoor’ folder).

There are plenty of sites with step by step guides for configuring Outlook with GoogleMail, so I wont go into that but I will share this tip:

To download full emails (not just headers) you need to do the following :-

  • Tools -> Send/Receive -> Send/Receive Settings -> Define Send/Receive Groups…
  • Select the group your IMAP account is in (typically ‘All Accounts’)
  • Click ‘Edit’
  • Select the account if there is more than one
  • Select the option for ‘Download complete items’ (this is different for OL2003 and OL2007, below is OL2003)

OutlookIMAPDownload

 

However the biggest pain with Outlook is that it does not by default open in any account that does not have the usual default folders (Contacts, Calendar, Inbox etc).

As a Google IMAP account does not have these it automatically adds a ‘Personal Folders’ PST file and opens at the Inbox folder folder of that instead.

I am pretty much settled on letting OL grab a copy of my mail (just in case I need to edit offline), but am finding myself using Google’s web mail interface most of the time.

GEO 51.4043197631836:-1.28760504722595

Redirector HttpModule

imageOriginally I had my website set up to default to my blog (so dasBlog was installed at the website root level instead of in a /blog subfolder).

Recently I have been writing some Web Applications and wanted to restructure my website so that there is a subfolder for each app / main area (blog, projects, etc).

The problem being that all the links out there point to https://kapie.com/2007/12/19/RedirectorHttpModule.aspx and these would all be dead link when moved to https://kapie.com/2007/12/19/RedirectorHttpModule.aspx, so I needed to respond with a HTTP 302 to the original links and tell the client that it should temporarily redirect to the new location (changing to a HTTP 301 when I am happy that it is all working).

This called for a HttpModule…

namespace KSL
{
     public class BlogRedirector : IHttpModule
     {
VisualStudioLogo         private EventHandler onBeginRequest;

public BlogRedirector()
{
onBeginRequest = new EventHandler(this.HandleBeginRequest);
}

void IHttpModule.Dispose()
{
}

void IHttpModule.Init(HttpApplication context)
{
context.BeginRequest += onBeginRequest;
}

private void HandleBeginRequest( object sender, EventArgs evargs )
{
HttpApplication app = sender as HttpApplication;

if ( app != null )
{
HttpContext context = app.Context;
string host = app.Request.Url.Host;
string requestUrl = app.Request.Url.PathAndQuery;

if (requestUrl.Contains(@”/blog/”)
|| requestUrl.Contains(@”/foo1/”)
|| requestUrl.Contains(@”/foo2/”)
|| requestUrl.Contains(@”/foo3/”)
|| requestUrl.Contains(@”/foo4/”)
|| (requestUrl.ToLower() == app.Request.Url.Scheme + @”://” + host + @”/default.aspx”))
{
return;
}
else
{
Uri newURL = new Uri(app.Request.Url.Scheme + @”://” + host + @”/blog” + requestUrl);
context.Response.RedirectLocation = newURL.ToString();
context.Response.StatusCode = 302;
context.Response.End();
return;
}
}
}
}
}

 

This basically allows me to redirect any url that does not contain /blog/ or /foo*/ or is not /default.aspx by sending a 302 status code and adding /blog/ to the url to generate the redirect url. The compiled DLLs were stored in the bin folder off the root and the web.config in the root needed the following adding…

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
  <system.web>
    <httpModules>
      <add type="KSL.BlogRedirector,BlogRedirector" name="BlogRedirector" />
    </httpModules>
  </system.web>
</configuration>

 

This seemed to work fine some of the time, but was a bit hit and miss…. Further investigation pointed me at the web.config files in the subfolders and that they would inherit the sections from the root web.config. So all the subfolder web.config files got the following added.

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
  <system.web>
    <httpModules>
      <remove name="BlogRedirector" />
    </httpModules>
  </system.web>
</configuration>

 

GEO 51.4043197631836:-1.28760504722595

Do it yourself ringtones

ruby_kaiserchiefs Sarah wanted ‘Ruby Ruby Ruby’ by the Kaiser Chiefs as her ringtone. Her mobile doesn’t have any easy way of connecting to a PC, so she joined one of the rip-off ‘Ringtones R Us’ services that force you into paying £4.50 / week for as many ringtone downloads as you want (aside: I must be getting old – why would anyone want to change their ringtone that often ??).

Anyway, after downloading the mp3 she found it start relatively quietly and she was missing some calls. What she had actually wanted was the chorus….

So cue Kens Do It Yourself Ringtone Creater and Transfererimage

Step by step instructions :-

  1. Rip the song to an MP3 (from the CD which we do own – no copyright issues) 
  2. Download Audacity.
  3. Cut the chorus out of the original track (loaded MP3 file)
  4. Create a new stereo track and paste the chorus into the new track.
  5. Mute the original tracksimage
  6. Play / listen to the new track, make sure you are happy with it.
  7. Download lame_enc.dll to allow Audacity to export as MP3 (see this Audacity FAQ)
  8. Export the new track from Audacity as an MP3.
  9. FTP the MP3 file to your website
  10. Using 3G / GPRS etc on the mobile phone connect to the internet
  11. Browse to the MP3 file and download it to the mobile
  12. Set the MP3 as the ringtone.
  13. Cancel the expensive MP3 ringtone service (if applicable).
 
GEO 51.4043197631836:-1.28760504722595

Consuming SOAP Web Services from VBScript

I spent a day this past week visiting one of our Technology Partners in New Jersey. The objective was do put together a proof concept for some integration we are planning.

We have some very cool stuff, about to be announced at one of the big shows coming up and the integration is around this new stuff. Anyway one of the things we had to do was to connect to a Web Service that returned complex types from a dynamic language.

I chose VBScript as the language because it’s widely available and can be executed on virtually any windows machine. I also wanted to ensure we only used commonly available (installed) ActiveX objects. The other constraint was the Web Services only used SOAP and HTTP POSTs, no HTTP GET support.

So the work involved was to :

  1. Create an XMLHTTP object
  2. Create the SOAP Body
  3. Send it to the Web Service
  4. Parse the results

Below is how we went about it.
It is messy and pretty horrible text manipulation to generate the SOAP bodies etc, but it is the only way I found from scripting..

Let me know if you have better / easier methods…

 

Const URL = "http://www.domain.com/folder/service.asmx"
Const nsUrl = "http://www.domain.com/namespace-name"


' Create the http request text
Dim strSoapReq
strSoapReq = GenerateSoapBodyStart()
strSoapReq = strSoapReq + GenerateSoapFunctionCallStart("WebServiceFunctionName")
strSoapReq = strSoapReq + GenerateSoapParameter("paramName1", paramValue1)
strSoapReq = strSoapReq + GenerateSoapParameter("paramName2", paramValue2)
strSoapReq = strSoapReq + GenerateSoapFunctionCallEnd("WebServiceFunctionName")
strSoapReq = strSoapReq + GenerateSoapBodyEnd()

Dim oHttp
Dim strResult
Set oHttp = CreateObject("Msxml2.XMLHTTP")
oHttp.open "POST", URL, false
oHttp.setRequestHeader "Content-Type", "text/xml"
oHttp.setRequestHeader "SOAPAction", URL + "WebServiceFunctionName"
oHttp.send strSoapReq
strResult = oHttp.responseText

' parse XML in strResult




Function GetResult(byval responseText, byval resultParam)

    Dim oXml
    Set oXml = CreateObject("Msxml2.DOMDocument")
    oXml.Async = true
    oXml.LoadXml responseText

    Dim strPath
    strPath = "/*/*/*/" + resultParam
    Dim oNode
    Set oNode = oXml.documentElement.SelectSingleNode(strPath)
    GetResult = oNode.Text

End Function


Function GenerateSoapBodyStart()

    Dim strSoap
    strSoap = "<?xml version=""1.0"" encoding=""utf-8""?>"
    strSoap = strSoap + "<soap12:Envelope "
    strSoap = strSoap + "xmlns:xsi=""http://www.w3.org/2001/XMLSchema-instance"" "
    strSoap = strSoap + "xmlns:xsd=""http://www.w3.org/2001/XMLSchema"" "
    strSoap = strSoap + "xmlns:soap12=""http://www.w3.org/2003/05/soap-envelope""> "
    strSoap = strSoap + "<soap12:Body>"
    GenerateSoapBodyStart = strSoap

End Function

Function GenerateSoapBodyEnd()

    Dim strSoap
    strSoap = "</soap12:Body>"
    strSoap = strSoap + "</soap12:Envelope>"
    GenerateSoapBodyEnd = strSoap

End Function

Function GenerateSoapFunctionCallStart(byval strFunction)

    Dim strSoap
    strSoap = "<" + strFunction + " xmlns=""" + nsUrl + """>"
    GenerateSoapFunctionCallStart = strSoap

End Function

Function GenerateSoapFunctionCallEnd(byval strFunction)

    Dim strSoap
    strSoap = "</" + strFunction + ">"
    GenerateSoapFunctionCallEnd = strSoap

End Function

Function GenerateSoapParameter(byval strParam, byval strValue)

    Dim strSoap
    strSoap = "<" + strParam + ">"
    strSoap = strSoap + strValue
    strSoap = strSoap + "</" + strParam + ">"
    GenerateSoapParameter = strSoap

End Function

 

Fair Lawn, NJ – 40.9381556054652:-74.132137298584

Insert Geo Microformat Plugin for Windows Live Writer

InsertPanel I have just completed a new Windows Live Writer plugin. This extension allows ease insertion of geo microformat information.

It allows the user to easily choose the location they want to insert (in microformat) from a Virtual Earth map and also configure how it is displayed (if at all on the post.

Recently I (with considerable help from Alexander Groß) added GeoRss support for dasBlog. The co-ordinates can be specified when adding a post via the web interface. This plugin is stage two of this support, stage three will be parsing the geo microformat when a post is added and using that to populate the GeoRss info.

The end goal being to allow the geo info to be entered when creating a post in Writer and having that info available in GeoRss format in the feed.

I started this plugin with the view to using Google Maps, however they require that you get an API key and that key is only valid for a particular web site / URL path. This foiled my plans to embed the map in a Windows Forms WebBrowser control (I did look at producing an html page that was served from my web site, and using it embedded in the WebBrowser – not scaleable and too much configuration for a normal user to do.

InsertMicroformat 

I hadn’t looked in depth at Virtual Earth, but recently went to MixUK:07 and saw a couple of demos / presentations on it – a quick look found that it didn’t need a API and was not tied to a particular URL / path – the JavaScript for it is pretty similar to the one for Google Maps so learning curve was pretty short. The only issue I have with http://local.live.com is that there is no (currently) facility to enter a GeoRss feed in the search query and just display the data (the current method of displaying this kind of data is to embed a map in your own pages and use their API to display the items as a ‘collection’).

You can get the installer for it here InsertGeoFormatSetup.msi (325Kb).

GEO 51.4043243116043:-1.28760516643523

Mix UK using social networking tool

Mixuk I registered for Mix:UK a few weeks ago and today got an email from the Mix team about a social networking tool they are using to help people make the most of the conference.

backnetworkThey are using backnetwork, which allows creation of profiles, blogging, photos, adding friends / colleagues etc (all the usual social networking stuff). It also allows you to add any colleagues / friends automagically from any previous backnetwork events you have been to.

 This is certainly a step in the right direction, but it’s missing an ‘auto-suggest relationship’ feature that could analyze your profile (or tags) and suggest other people who have similar interests.

So… my profile is here, anyone interested in any of my tags feel free to contact me and set up a meeting/chat/lunch/coffee/whatever…