Aug 232015
 

Something got me thinking tonight.  We were out visiting a friend of ours and it was decided we’d go out for dinner.  Nothing unusual there, and there were a few places we could have gone for a decent meal.

As it happens, we went to a bowls club for dinner.  I won’t mention which one.

Now, I’d admit that I do have a bit of a rebel streak in me.  Let’s face it, if nobody challenged the status quo, we’d still be in the trees, instead someone decided they liked the caves better and so developed modern man.

In my case, I’m not one to make a scene, but the more uptight the venue, the more uncomfortable I am being there.  If a place feels it necessary to employ a bouncer, or feels it necessary to place a big plaque out front listing rules in addition to what ought to be common sense, that starts to get the alarm bells ringing in my head.

Some rules are necessary, most of these are covered by the laws that maintain order on our streets.  In a club or restaurant, okay, you want to put some limits: someone turning up near-starkers is definitely not on.  Nobody would appreciate someone covered in grease or other muck leaving a trail throughout the place everywhere they go, nor should others be subjected to some T-shirt with text or imagery that is in any way “offencive” to the average person.

(I’ll ignore the quagmire of what people might consider offencive.  I’m sure someone would take exception to me wearing largely blank clothing.  I, for one, abhor branding or slogans on my clothing.)

Now, something that obstructs your ability to identify the said person, such as a full-face balaclava, burka (not sure how that’s spelled) or a full-face helmet: there’s quite reasonable grounds.

As for me, I never used to wear anything on my head until later in high school when I noted how much less distracted I was from overhead lighting.  I’m now so used to it, I consider myself partially undressed if I’m not wearing something.  Something just doesn’t feel right.  I don’t do it to obscure identity, if anything, it’d make me easier to identify.  (Coolie hats aren’t common in Brisbane, nor are spitfire or gatsby caps.)

It’s worth pointing out that the receptionist at this club not only had us sign in with full name and address, but also checked ID on entry.  So misbehaviour would be a pointless exercise: they already had our details, and CCTV would have shown us walking through the door.

The bit that got me with this club, was in amongst the lengthy list of things they didn’t permit, they listed “mens headwear”.  It seemed a sexist policy to me.  Apparently women’s headwear was fine, and indeed, I did see some teens wearing baseball caps as I left, no one seemed to challenge them.

In “western society”, many moons ago, it was considered “rude” for a man to wear a hat indoors.  I do not know what the rationale behind that was.  Women were exempt then from the rule, as their headwear was generally more elaborate and required greater preparation and care to put on and take off.

I have no idea whether a man would be exempt if his headgear was as difficult to remove in that time.  I certainly consider it a nuisance having to carry something that could otherwise just sit on my head and generally stay out of my way.

Today, people of both sexes, if they have anything on their head at all, it’s mostly of a unisex nature, and generally not complicated to put on or remove.  So the reasoning behind the exemption would appear to be largely moot now.

Then there’s the gender equality movement to consider.  Women for years, fought to have the same rights as men.  Today, there’s some inequality, but the general consensus seems to be that things have improved in that regard.

This said, if doing something is not acceptable for men, I don’t see how being female makes it better or worse.

Perhaps then, in the interests of equal rights, we should reconsider some of our old customs and their exemptions in the context of modern life.

Jun 142015
 

What is it? Well, the term “quaxing” originated from Auckland’s councillor, Dick Quax who stated:

@lukechristensen @BenRoss_AKL @Brycepearce no one in the entire western world uses the train for their shopping trips

@Brycepearce @lukechristensen @BenRoss_AKL the very idea that people lug home their weekly supermarket shopping on the train is fanciful

@Brycepearce @lukechristensen @BenRoss_AKL sounds like that would make great Tui ad. “I ride my bike to get my weekly shopping – yeah right”

While I’ve never described it as “quaxing”, and likely will not describe it that way, this is how I’ve been shopping for the past 5 years.

This, is my shopping trolley, literally… it gets unhitched and taken into the shop with me.

Shopping on the bike, "quaxing" to the twitter-croud.

Shopping on the bike, “quaxing” to the twitter-croud.

Now true, strictly speaking, Australia is not the “western world” geographically speaking. Neither is NZ; any further east and you hit the International Date Line. However this is a “westernised” country, as is NZ. Isn’t it funny how people assume cycling is merely a third-world phenomenon?

May 212015
 

This is more a quick dump of some proof-of-concept code.  We’re in the process of writing communications drivers for an energy management system, many of which need to communicate with devices like Modbus energy meters.

Traditionally I’ve just used the excellent pymodbus library with its synchronous interface for batch-processing scripts, but this time I need real-time and I need to do things asynchronously.  I can either run the synchronous client in a thread, or, use the Twisted interface.

We’re actually using Tornado for our core library, and thankfully there’s an adaptor module to allow you to use Twisted applications.  But how do you do it?  Twisted code requires quite a bit of getting used to, and I’ve still not got my head around it.  I haven’t got my head fully around Tornado either.

So how does one combine these?

The following code pulls out the first couple of registers out of a CET PMC330A energy meter that’s monitoring a few circuits in our office. It is a stripped down copy of this script.

#!/usr/bin/env python
'''
Pymodbus Asynchronous Client Examples -- using Tornado
--------------------------------------------------------------------------

The following is an example of how to use the asynchronous modbus
client implementation from pymodbus.
'''
#---------------------------------------------------------------------------# 
# import needed libraries
#---------------------------------------------------------------------------# 
import tornado
import tornado.platform.twisted
tornado.platform.twisted.install()
from twisted.internet import reactor, protocol
from pymodbus.constants import Defaults

#---------------------------------------------------------------------------# 
# choose the requested modbus protocol
#---------------------------------------------------------------------------# 
from pymodbus.client.async import ModbusClientProtocol
#from pymodbus.client.async import ModbusUdpClientProtocol

#---------------------------------------------------------------------------# 
# configure the client logging
#---------------------------------------------------------------------------# 
import logging
logging.basicConfig()
log = logging.getLogger()
log.setLevel(logging.DEBUG)

#---------------------------------------------------------------------------# 
# example requests
#---------------------------------------------------------------------------# 
# simply call the methods that you would like to use. An example session
# is displayed below along with some assert checks. Note that unlike the
# synchronous version of the client, the asynchronous version returns
# deferreds which can be thought of as a handle to the callback to send
# the result of the operation.  We are handling the result using the
# deferred assert helper(dassert).
#---------------------------------------------------------------------------# 
def beginAsynchronousTest(client):
    io_loop = tornado.ioloop.IOLoop.current()

    def _dump(result):
        logging.info('Register values: %s', result.registers)
    def _err(result):
        logging.error('Error: %s', result)

    rq = client.read_holding_registers(0, 4, unit=1)
    rq.addCallback(_dump)
    rq.addErrback(_err)

    #-----------------------------------------------------------------------# 
    # close the client at some time later
    #-----------------------------------------------------------------------# 
    io_loop.add_timeout(io_loop.time() + 1, client.transport.loseConnection)
    io_loop.add_timeout(io_loop.time() + 2, io_loop.stop)

#---------------------------------------------------------------------------# 
# choose the client you want
#---------------------------------------------------------------------------# 
# make sure to start an implementation to hit against. For this
# you can use an existing device, the reference implementation in the tools
# directory, or start a pymodbus server.
#---------------------------------------------------------------------------# 
defer = protocol.ClientCreator(reactor, ModbusClientProtocol
        ).connectTCP("10.20.30.40", Defaults.Port)
defer.addCallback(beginAsynchronousTest)
tornado.ioloop.IOLoop.current().start()
May 152015
 

… or how to emulate Red Hat’s RPM dependency hell in Debian with Python.

There are times I love open source systems and times when it’s a real love-hate relationship. No more is this true than trying to build Python module packages for Debian.

On Gentoo this is easy: in the past we had g-pypi. I note that’s gone now and replaced with a gsourcery plug-in called gs-pypi. Both work. The latter is nice because it gives you an overlay potentially with every Python module.

Building packages for Debian in general is fiddly, but not difficult, but most Python packages follow the same structure: a script, setup.py, calls on distutils and provides a package builder and installer. You call this with some arguments, it builds the package, plops it in the right place for dpkg-buildpackage and the output gets bundled up in a .deb.

Easy. There’s even a helper script: stdeb that plugs into distutils and will do the Debian packaging all for you. However, stdeb will not source dependencies for you. You must do that yourself.

So quickly, building a package for Debian becomes reminiscent of re-living the bad old days with early releases of Red Hat Linux prior to yum/apt4rpm and finding the RPM you just obtained needs another that you’ll have to hunt down from somewhere.

Then you get the people who take the view, why have just one package builder when you can have two. fysom needs pybuilder to compile. No problems, I’ll just grab that. Checked it out of github, uhh ohh, it uses itself to build, and it needs other dependencies.

Lovely. It gets better though, those dependencies need pybuilder to build. I just love circular dependencies!

So as it turns out, in order to build this, you’ll need to enlist pip to install these behind Debian’s back (I just love doing that!) then you’ll have the dependencies needed to actually build pybuilder and ultimately fysom.

Your way out of this maze is to do the following:

  • Ensure you’ve got the python-stdeb, dh-python and python-pip packages installed.
  • Use pip to install the dependencies for pybuilder and its dependencies: pip install fluentmock pybuilder pyassert pyfix pybuilder-external-plugin-demo pybuilder_header_plugin pybuilder_release_plugin
  • Now you should be able to build pybuilder, do pyb publish in the directory, then look under target/dist/pybuilder-${VERSION} you should see the Python sources with a setup.py you can use with stdeb.

Any other dependencies are either in Debian repositories, or you can download the sources yourself and use the stdeb technique to build them.

May 032015
 

The Problem

I’ve been running a station from the bicycle for some time now and I suppose I’ve tried a few different battery types on the station.

Originally I ran 9Ah 12V gel cells, which work fine for about 6 months, then the load of the radio gets a bit much and I find myself taking two with me on a journey to work because one no longer lasts the day.  I replaced this with a 40Ah Thundersky LiFePO4 pack which I bought from EVWorks, which while good, weighed 8kg!  This is a lot lighter than an equivalent lead acid, gel cell or AGM battery, but it’s still a hefty load for a bicycle.

At the time that was the smallest I could get.  Eventually I found a mob that sold 10Ah packs. These particular cells were made by LiFeBatt, and while pricey, I’ve pretty much recouped my costs. (I’d have bought and disposed of about 16 gel cell batteries in this time at $50 each, versus $400 for one of these.)   These are what I’ve been running now since about mid 2011, and they’ve been pretty good for my needs.  They handle the load of the FT-857 okay on 2m FM which is what I use most of the time.

A week or two back though, I was using one of these packs outside with the home base in a “portable” set-up with my FT-897D.  Tuned up on the 40m WICEN net on 7075kHz, a few stations reported that I had scratchy audio.  Odd, the radio was known to be good, I’ve operated from the back deck before and not had problems, what changed?

The one and only thing different is I was using one of these 10Ah packs.  I’ve had fun with RF problems on the bicycle too.  On transmit, the battery was hovering around the 10.2V mark, perhaps a bit low.  Could it be the radio is distorting on voice peaks due to input current starvation?  I tried after the net swapping it for my 40Ah pack, which improved things.  Not totally cleared up, but it was better, and the pack hadn’t been charged in a while so it was probably a little low too.

The idea

I thought about the problem for a bit.  SSB requires full power on voice peaks.  For a 100W radio, that’s a 20A load right now.  Batteries don’t like this.  Perhaps there was a bit of internal resistance from age and the nature of the cells?  Could I do something to give it a little hand?

Supercapacitors are basically very high capacity electrolytic capacitors with a low breakdown voltage, normally in the order of a few volts and capacitances of over a farad.  They are good for temporarily storing charge that needs to be dumped into a load in a hurry.  Could this help?

My cells are in a series bank of 4: ~3.3V/cell with 4 cells gives me 13.2V.  There’s a battery balancer already present.  If a cell gets above 4V, that cell is toast, so the balancer is present to try to prevent that from happening.  I could buy these 1F 5.5V capacitors for only a few dollars each, so I thought, “what the hell, give it a try”.  I don’t have much information on them other that Elna Japan made them.  The plan was to make some capacitor “modules” that would hook in parallel to each cell.

My 13.2V battery pack, out of case

My 13.2V battery pack, out of its case

Supercapacitors

Supercapacitors

For my modules, the construction was simple, two reasonably heavy gauge wires tacked onto the terminals, the whole capacitor then encased in heatshrink tubing and ring lugs crimped to the leads. I was wondering whether I should solder a resistor and diode in parallel and put that in series with the supercap to prevent high in-rush current, but so far that hasn’t been necessary.

The re-assembled pack

I’ve put the pack back together and so far, it has charged up and is ready to face its first post-retrofit challenge.  I guess I’ll be trying out the HF station tomorrow to see how it goes.

Assembled pack

Assembled pack

The Verdict

Not a complete solution to the RF feedback, it seems to help in other ways. I did a quick test on the drive way first with the standard Yaesu handmic and with the headset. Headset still faces interference problems on HF, but I can wind it up to about 30W~40W now instead of 20.

More pondering to come but we’ll see what the other impacts are.

Apr 112015
 

To whom it may concern,

There have been reports of web browser sessions from people outside China to websites inside China being hijacked and having malware injected.  Dubbed “Great Cannon”, this malware having the sole purpose of carrying out distributed denial of service attacks on websites that the Chinese Government attempts to censor from its people.  Whether it be the Government there itself doing this deliberately, or someone hijacking major routing equipment is fundamentally irrelevant here, either way the owner of the said equipment needs to be found, and a stop put to this malware.

I can understand you wish to prevent people within your borders from accessing certain websites, but let me make one thing abundantly clear.

COUNT ME OUT!

I will not accept my web browser which is OUTSIDE China being hijacked and used as a mule for carrying out your attacks.  It is illegal for me to carry out these attacks, and I do not authorise the use of my hardware or Internet connection for this purpose.  If this persists, I will be blocking any and all Chinese-owned websites’ executable code in my browser.

This will hurt Chinese business more than it hurts me.  If you want to ruin yourselves economically, go ahead, it’ll be like old times before the Opium Wars.

Apr 102015
 

This afternoon, whilst waiting for a build job to complete I thought I’d do some further analysis on my annual mileage.

Now I don’t record my odometer readings daily (perhaps I should), but I do capture them every Sunday morning.  So I can possibly assume that the distance done for each day of a “run” is the total distance divided by the number of days.  I’m using a SQLite3 database to track this, question is, how do I extract this information?

This turned out to be the key to the answer.  I needed to enumerate all the days between two points.  SQLite3 has a julianday function, and with that I have been able to extract the information I need.

My database schema is simple. There are two tables:
CREATE TABLE bikes (id integer primary key not null, description varchar(64));
CREATE TABLE odometer (timestamp datetime not null default current_timestamp, action char(8) not null, bike_id integer not null, odometer real not null, constraint duplicate_log unique (timestamp, action, bike_id) on conflict replace);

Then there are the views.
CREATE VIEW run_id as select s.rowid as start_id, (select rowid from odometer where bike_id=s.bike_id and timestamp > s.timestamp and action='stop' order by timestamp asc limit 1) as stop_id from odometer as s where s.action='start';
CREATE VIEW "run" AS select start.timestamp as start_timestamp, stop.timestamp as stop_timestamp, start.bike_id as bike_id, start.odometer as start_odometer, stop.odometer as stop_odometer, stop.odometer-start.odometer as distance,julianday(start.timestamp) as start_day, julianday(stop.timestamp) as stop_day from (run_id join odometer as start on run_id.start_id=start.rowid) join odometer as stop on run_id.stop_id=stop.rowid;

The first view breaks up the start and stop events, and gives me row IDs for where each “run” starts and stops. I then use that in my run view to calculate distances and timestamps.

Here’s where the real voodoo lies, to enumerate days, I start at the very first timestamp in my dataset, find the Julian Day for that, then keep adding one day on until I get to the last timestamp. That gives me a list of Julian days that I can marry up to the data in the run view.

CREATE VIEW distance_by_day as
SELECT day_of_year, avg_distance FROM (
SELECT days.day - julianday(date(days.day,'start of year')) as day_of_year, sum(run.distance/max((run.stop_day-run.start_day),1))/count(*) as avg_distance
FROM run,
(WITH RECURSIVE
days(day) as (
SELECT julianday((select min(timestamp) from odometer))
union all
SELECT day+1 from days
limit cast(round(julianday((select max(timestamp) from odometer))-julianday((select min(timestamp) from odometer))) as int)
) SELECT day from days) as days
where
run.start_day < = days.day AND run.stop_day >= days.day
group by day_of_year) dist_by_doy;

This is the result.

Distance by Day Of Year

Distance by Day Of Year

Apr 062015
 

I’ve been a long time user of PGP, had a keypair since about 2003.  OpenPGP has some nice advantages in that it’s a more social arrangement in that verification is done by physically meeting people.  I think it is more personal that way.

However, you still can get isolated islands, my old key was a branch of the strong set, having been signed by one person who did do a lot of key-signing, but sadly thanks to Heartbleed, I couldn’t trust it anymore.  So I’ve had to start anew.

The alternate way to ensure communications is to use some third party like a certificate authority and use S/MIME.  This is the other side of the coin, where a company verifies who you are.  The company is then entrusted to do their job properly.  If you trust the company’s certificate in your web browser or email client, you implicitly trust every non-revoked valid certificate that company has signed.  As such, there is a proliferation of companies that act as a CA, and a typical web browser will come with a list as long as your arm/leg/whatever.

I’ve just set up one such certificate for myself, using StartCOM‘s CA as the authority.  If you trust StartCOM, and want my GPG key, you’ll find a S/MIME signed email with my key here.  If you instead trust my GPG signature and want my S/MIME public key, you can get that here.  If you want to throw caution to the wind, you can get the bare GPG key or S/MIME public key instead.

Update: I noticed GnuPG 2.1 has been released, so I now have an ECDSA key; fingerprint B8AA 34BA 25C7 9416 8FAE  F315 A024 04BC 5865 0CF9.  You may use it or my existing RSA key if your software doesn’t support ECDSA.

Mar 312015
 

Every now and again, I get some invite to join some social network or to “Confirm I know ${PERSON}”.  It doesn’t really matter what platform you choose, the end result is the same.

There are a couple of reasons I do not participate on these systems.

Number one is that when I get home, I typically cannot be stuffed having much to do with computers.  Sure I’ll be checking what news has happened during the day, I have an RSS aggregator for that.  I’ll check what the weather is doing tomorrow (as a cyclist, this is of high importance).  I’ll check emails, as that is how I keep in touch with people (I know, how quaint, but it works).

Maybe check some public forums/newsgroups.  That’s about it.  I really cannot be stuffed doing much else having fought with computers all day, I’m really not in the mood when I get home.

Second reason is the nature of these social networks.  Much of the interaction happens behind the scenes.  You’re “sharing” to an audience behind closed doors.  That audience has to be a member of that same group to even see your material.  Don’t believe me?  Try to log into Facebook and then go “Friend” a Google+ user and share something with them.  Or how about go log into Google+ and “circle” (is that the term?) a Linked In user.  These new-breed “social” networks are about as anti-social as it gets.

They’re today’s bulletin board system.  I’m sorry, are we really abandoning the World Wide Web for what’s little more than a BBS?  About the only difference I see is that JavaScript and HTML5 replace the ANSI/DEC escape sequences of old.  It’s still an isolated silo from which your information is locked in and only those who have opted into that network can participate.

A forum can be publicly viewed in most cases, in fact forums generally have trouble attracting an audience if they’re not publicly visible.

Finally there’s the privacy.  Sharing what you’re doing in your day to day life is one thing.  You can share a lot without giving much away personally.  “Friend”-ing people however is basically uploading your social graph, one link at a time.  One’s social graph is one of the most personal things one can expose about themselves, and increasingly the privacy policies of these social networks have been found lacking in several aspects.

Companies have been working on sophisticated ways in order to search and map out these social graphs, they would not be doing this if there wasn’t financial incentive to do so.  Knowing who someone’s friends are is the first step in being able to manipulate that person.  I’d rather not be someone’s puppet.

There’s also the phishing risk.  They’re popular sites to try and spoof.  I recently received one alleging to be from The Register author Simon Rockman.  It could be authentic, but then again, anyone could sign up for an account on one of these social network, claim to be someone they’re not, and try to lure you in.  I’ve got no way of verifying this, and with a broken “Reply-to” header, in the bin it goes.

So, next time you think of putting my email address in to a form on a social network page to invite me to join, don’t bother.  I do respond to emails, I even respond to comments left here (unless they’re spam), but I will not respond to social network invites, in fact I may not even receive them.

Mar 192015
 
Tropical Cyclone Nathan, Forecast map as of 2:50PM

Tropical Cyclone Nathan, Forecast map as of 2:50PM

This cyclone has harassed the far north once already, wobbled out in the Pacific like a drunken cyclist as a tropical low, has gained strength again and is now making a bee-line for Cape Flattery.

As seen, it also looks like doing the same stunt headed for Gove once it’s finished touching up far north Queensland.  Whoever up there is doing this rain dancing, you can stop now, it’s seriously pissing off the weather gods.

National and IARU REGION III Emergency Frequencies (Please keep clear and listen for emergency traffic)

  • 80m
    • 3.600MHz LSB (IARU III+WICEN)
  • 40m
    • 7.075MHz LSB (WICEN)
    • 7.110MHz LSB (IARU III)
  • 20m
    • 14.125MHz USB (WICEN)
    • 14.300MHz USB (IARU III)
    • 14.183MHz USB: NOT an emergency frequency, but Queensland State WICEN hold a net on this frequency every Sunday morning at around 08:00+10:00 (22:00Z Saturday).
  • 15m
    • 21.190MHz USB (WICEN)
    • 21.360MHz USB (IARU III)
  • 10m
    • 28.450MHz USB (WICEN)

I’ll be keeping an ear out on 14.125MHz in the mornings.

Update 20 March 4:31am: It has made landfall between Cape Melville and Cape Flattery as a category 4 cyclone.