Solid, practical and cheap(ish) laptop

I’ve been fortunate enough to be supplied with MacBook Pros for my last few jobs, including my current role. I passed my own (now aged) MacBook Air on to my Wife when we met and since then I’ve been pretty much using my work machines for personal stuff too.

I was thinking about buying a cheap, reliable laptop for web browsing, coding and other odds and ends. Unfortunately the requirement that it should be cheap pretty much disqualified all Apple products. So I thought I’d look through eBay and see what I could find.

The keys feel very similar to, or possibly better than, those on the MacBook Pro.

In the end I settled on a Lenovo ThinkPad T430 (circa 2012). I chose it because it was available under £250, had a reasonable spec, solid build quality and a very, very nice keyboard. The model I bought was an i7 2.90Ghz with 8GB of RAM, NVIDIA NVS 5400M graphics, a 500GB HDD, DVD-CDRW and a 1600 x 900 antiglare display.

The first modification I made was replacing the optical drive with a HDD caddy and relocating the original HDD there. I then installed the cheapest 240GB SSD I could find as the boot drive.

ThinkPad DVDRW & HDD Caddy
I mean seriously, who needs an optical drive in 2017?

Next up I installed Windows 10 Pro and dual booted it with Linux Mint. I followed an online guide to setup a development environment in Windows, although I expect the Windows partition will mostly be used for coding C# in Visual Studio. I set up the Linux partition as I’ve never experimented with Linux before and this seemed like a good opportunity.

The trackpad was showing its age and had that weird spotty texture that only seems to exist on ThinkPads. It turns out the entire surface is just a sticker. So I peeled it off and replaced it with a smooth trackpad surface made to fit the T430.

Hey that’s smooth

So now I had a machine that ran the OSes I was interested in playing with, held a good charge, had a usable trackpad, a secondary drive for storage and booted up quickly thanks to the SSD. The one remaining and somewhat unexpected issue was the screen. The antiglare TN panel fitted to the T430 is one of the worst displays I have ever seen. It had to go.

A bit of research later and it seems that I was by no means alone in my assessment of the display. Several other users had investigated alternative displays. Sadly it seems there are no IPS displays that are a straight swap. The best alternative appears to be the AlienWare M14X R2 glossy display. The first one I ordered from eBay was a bust as they lied in the description and shipped me the same antiglare panel I already had. In the end I found the panel from laptopscreen.com. The difference is night and day, it’s still not an IPS display but the viewing angles are significantly better and the image is so much sharper.

All in all I’m pretty impressed with this ex-corporate brick. It boots up almost instantly thanks to the SSD. The fingerprint scanner is a surprisingly handy addition and works flawlessly with Windows Hello. The discreet graphics, although old, have turned out to be surprisingly capable. I’ve played Darksiders, Tony Hawks HD and Grid 2 at reasonable frame-rates without issues. On the flip-side rendering in blender is pretty lacklustre, the BMW scene renders in 38 minutes. However for under £350 all in it’s a pretty competent all-rounder!


The things I wish I’d known before I started

You can use sellotape to remove the HDD if it has lost its tab
If you watch any of the many YouTube videos on changing the HDD in a ThinkPad you’ll see how you simply undo one screw, slip off the plastic cover, fish out the tab, give it a tug and you’re done. Sadly it turned out that when I tried this my HDD had no tab to tug.
I contemplated a few approaches to retrieving the stubborn storage device, needle-nosed pliers, supergluing wire to it, even disassembling most of the laptop to get better access. Eventually I figured I should try using some tape. It was pretty fiddly to thread the tape between the HDD and the edge of the enclosure, and then to get it to stick to the HDD but I managed it on the third try. One gentle tug and the drive was out.
The standard display on the T430 is truly an abomination
If I had realised how bad the screen was I would probably have spent the extra for a newer ThinkPad that came with an IPS display. I genuinely hadn’t realised how spoilt I had been by the screens on the Apple laptops I’ve had over the years.
Replacement screens are harder to find than I anticipated
I bought an allegedly 1600 x 900 glossy screen from eBay. I removed the screen that was in the laptop and then fitted the new one. Only to discover that when I removed the protective film it wasn’t a glossy screen at all. It was exactly the same antiglare (matte) screen that I had replaced. After a bit of arguing with the supplier, swapping the screens back over and a trip to the post office I managed to get my money back. I then managed to source a replacement from laptopscreens.com. I suppose scarcity of parts for a 5 year old laptop is to be expected but you need to be careful when buying screens online, there are a lot of misinformed dishonest sellers out there.
Make sure you disconnect the battery before swapping displays
In the interests of full disclosure the machine pictured in this post is not the machine I’m using. It’s an i5 model that I did all of the upgrades on. Unfortunately in my excitement to get rid of the awful display that came with the machine I forgot to disconnect the battery. I took the old display out, swapped the new one in and booted it up. The screen showed an image but it was only visible under a very strong light. Some research online led me to believe that I blew a fuse on the motherboard that controls the power to the backlight.
Disassembling the entire machine and a quick continuity test with a multi-meter seemed to confirm my suspicions. I considered my options, a new motherboard would have been around £100, the proper tools to replace a surface mount fuse would have been well over £100 and neither would guarantee a working machine. So I went back on to eBay and bought a second ThinkPad (the i7 mentioned above) and transferred all of the upgrades over to the new machine. I’m hoping I can sell the other one for spares/repairs.

Peeking behind the curtain

Recently I’ve begun experimenting with things I would have thought impossible a few years ago. The python script I wrote last week and the data scraping project that I’ve yet to write about have both made me realise that none of this stuff is witchcraft. With my hosting renewal coming up I started wondering about moving from shared hosting to a VPS.

For the last decade my personal sites and email accounts have been hosted with the same shared hosting company. They have always provided me with excellent service for a reasonable price and I’ve always been happy to recommend them to my clients. Now that my requirements have reduced a little and I’ve been seeing VPS offered for a fraction of the cost I thought it worth investigating.

It’s probably worth noting that none of my sites are high traffic or high importance. They consist of this blog and its predecessor, a domain I bought for my wedding, a development server and my mostly dormant company site. I’m not sure that I’d be confident deploying a client’s site on a VPS yet but for my needs it works just fine.

New adventures in hosting

For my first foray into configuring my own hosting I chose to go with Digital Ocean’s $10 VPS. I had some teething troubles with their one-click WordPress installer so I decided to roll my own by following their excellent documentation.

All of that got this site up and running and allowed me to use WordPress’ auto update feature. The only thing left to do was to get a mail server set up. I decided to take the easy option and went with Zoho. All you have to do is create a CNAME record for the domain to prove to Zoho that you own it and then you need to set two MX records and it’s good to go.

The whole kit and caboodle

Having been encouraged by getting this blog working I span up another droplet and went through the first three tutorials again to get a LAMP stack up and running. This time I remembered to create a snapshot of it so in future I can just create a droplet with my preferences in one click.

Once it was up and running I looked at the content I needed to migrate:

  • Company site: A few php files
  • Old blog: A WordPress site
  • Development server: Several sites, mostly php but a few also require MySQL databases
  • Wedding site: A holding page

I guessed that it would be possible to host all of these on one droplet, as they’re all fairly low traffic sites. I looked into setting up virtual hosts in apache and was relieved to find that again Digital Ocean’s documentation didn’t let me down.

I had decided that there was no point continuing with the old blog as I hadn’t posted in it for over a year. However I wanted to be a good net citizen and not break any old inbound links. So I decided to import the content of the old blog here and set up a redirect for old links. To redirect all requests from one domain to another all you need is these two lines in the .htaccess file on the old domain.

RewriteEngine on
RewriteRule (.*) http://www.newdomain.com/$1 [R=301,L]

Having set up four virtual hosts, transferred all of the required files, set up my .htaccess file and pointed my name servers at Digital Ocean my hosting was done. Setting up Zoho for each domain was a little laborious but as they provide free mail servers I’m not about to complain.

Was it worth it?

Compared to standard shared hosting you’ll have a lot more passwords to keep track of, you’ll spend most of your time in terminal rather than a web based control panel and you are your own tech support. It’s definitely not for everyone and your mileage may vary but I learnt a lot from the process and have cut my hosting bill by about 66%.

Over-engineering #firstworldproblems

I have finally backed a kickstarter campaign for the first time. It’s a 3D printer called Tiko and I’m really excited about receiving it. So excited in fact that I would really like to get it earlier than the February ETA I originally pledged for.

Some of the early backers have been concerned about the lack of updates, photos and videos from the Tiko team and have been cancelling their pledges. This has opened spaces in the pledges with earlier estimated shipping dates. The other day I was fortunate that I refreshed the page at just the right moment and managed to change my pledge to one with a January shipment. That got me wondering if I could come up with something that would alert me when the slots opened up.

It turns out I was not alone in my thinking as there is a project on github that automates the whole process, including managing your pledge. The author notes that it is somewhat dubious and probably goes against kickstarter’s T’s & C’s. So I decided that I’d have a go at rolling my own version that would just alert me.

Everything I read said that for scraping Python was the way to go. Having never written a line of python I thought it would be an interesting project to play with a new language. I quickly found BeautifulSoup and after a few visits to a number of tutorials I had a script that would output the info I wanted to the command line.

Automating and alerting

This first script would have been fine if I was always sat at my laptop but ultimately isn’t anymore useful than hitting cmd-r on the kickstarter page itself. So I needed a way for the script to alert me. I remembered playing with PushOver a while back to get alerts from my minecraft server. I created an account with them and set up an application, looked at their python documentation, installed the iOS app on my phone and that was that.

All that was left was to automate running the script. I’ve heard of cron jobs but had never needed to create one until now. A quick google lead me to a simple tutorial and I was up and running.

Putting it all together

The cron job triggers the script, the script scrapes for all of the reward info from the kickstarter page. If there is a reward with a ship date in November and there are currently less than the maximum number of backers it triggers a PushOver notification. My phone then receives the notification and pushes it to my pebble.

Within five hours of launching the cron job my pebble buzzed to tell me the November slot was available and after some over-excited mashing of the keyboard I secured the slot.

Win!

The script itself

As I mentioned earlier I have never written a line of python before this project. The code below works but it definitely could be refactored and improved (try not to judge me).

import requests
from bs4 import BeautifulSoup
import httplib, urllib

url = "https://www.kickstarter.com/projects/tiko3d/tiko-the-unibody-3d-printer/description"
r = requests.get(url)

soup = BeautifulSoup(r.content)

rewards = soup.find_all("li", {"class": "NS-projects-reward"})

print "nn"

for reward in rewards:
    rewardCost = str(reward.find("h5").find("span").text)
    shipDate = str(reward.find("time").text)
    numBackers = str(reward.find("span", "num-backers").text)
    x = int(numBackers.replace(" backers", "").replace(",", ""))

    # backersClean = backers.rstrip()
    if shipDate == "Nov 2015" and rewardCost == "$179 USD":
      if x < 2500:
        conn = httplib.HTTPSConnection("api.pushover.net:443")
        conn.request("POST", "/1/messages.json",
          urllib.urlencode({
            "token": "[TOKEN]",
            "user": "[USER]",
            "message": "$179 reward now available",
            "device": "iphone",
          }), { "Content-type": "application/x-www-form-urlencoded" })
        conn.getresponse()
    if shipDate == "Nov 2015" and rewardCost == "$139 USD":
      if x < 400:
        conn = httplib.HTTPSConnection("api.pushover.net:443")
        conn.request("POST", "/1/messages.json",
          urllib.urlencode({
            "token": "[TOKEN]",
            "user": "[USER]",
            "message": "$139 reward now available",
            "device": "iphone",
          }), { "Content-type": "application/x-www-form-urlencoded" })
        conn.getresponse()
    if shipDate == "Nov 2015" and rewardCost == "$99 USD":
      if x < 100:
        conn = httplib.HTTPSConnection("api.pushover.net:443")
        conn.request("POST", "/1/messages.json",
          urllib.urlencode({
            "token": "[TOKEN]",
            "user": "[USER]",
            "message": "$99 reward now available",
            "device": "iphone",
          }), { "Content-type": "application/x-www-form-urlencoded" })
        conn.getresponse()

UPDATE: Disappointingly it looks like my Tiko is never going to arrive as the creators seem to have run out of money.