April 2009 - Posts

I spoke with Ipswich City Council Senior Plumbing Inspector Greg Brown regarding flood levels, septic systems and appertinent regulations. He gave me his official opinion, checked council records regarding lot 409 and finished by giving me his direct number and offering to speak to the bank or the valuer.

This was the substance of the discussion:

  • The house is above the 100 year flood level.
  • The SL (surface level) of the septic system is above the 20 year flood level as required by law.
  • The SL of the septic system is incidentally also above the 100 year flood level. The regulated maximum depth is 2m, and given the details of the septic plans for lot 409 as lodged with council, the bottom of the septic disposal area is also above the 20 year flood level, although this is not a requirement.

FloodOverlayLOT409

Posted by peterw | with no comments

Transactions. If you don’t know why you need them, it’s high time you learnt. But don’t look at me, you should have known that stuff by the end of semester one at uni.

If you do know why you need transactions you also know what a drama they are when the transaction context spans multiple machines and sometimes extended periods. Microsoft has been farting around with this stuff since time out of mind. I remember back in the late nineties, the DTC (distributed transaction controller) was going to be all things to everyone and we were all going to go home early and have long transactional vacations in the Caribbean (or Europe, if like me you prefer snow to sand).

It was all terribly complicated and you had to go through all manner of contortions and it leaked like a bucket with no bottom, and no one had a clear idea of how COM worked, much less COM+, there were huge teams of confused people spouting acronyms and getting in each others’ way, and lordy what a mess.

I wandered off and worked on smaller systems for people who never heard of transactions, even if they really should have, and other people who really didn’t need them at all, met a nice girl and on the whole managed to stay out of trouble. Mostly.

Finally it all caught up with me. This afternoon I was debugging some code that does several things to several databases potentially on multiple servers and it went pear shaped. This was not terribly surprising with unfinished code, but it did leave the aggregate system with inconsistent state, and while I cleaned up the mess it occurred to me that a distributed transaction was required.

I could tell you about it, but let’s skip a whole bunch of tiresome research, and just say that I’ve discovered the System.Transaction namespace and (with particular glee) TransactionScope.

Here’s a code snippet from this afternoon’s labours that illustrates very nicely how ridiculously easy it is to use:

   60             using (TransactionScope scope = new TransactionScope())

   61             {

   62               var selectedAssetDevice = (

   63                 from a in dcAtomdb.Assets

   64                 join d in dcAtomdb.Devices

   65                 on a.AttachedDeviceID equals d.Id

   66                 where a.Id == selectedAsset.Id

   67                 select new { a.AttachedDeviceID, d.DeviceNumber }).FirstOrDefault();

   68               if (selectedAssetDevice.DeviceNumber == _deviceNumber.ToString())

   69                 DialogResult = DialogResult.OK;

   70               else

   71               {

   72                 string msg =string.Format(

   73                   "You are changing the device associated with {0}",

   74                   selectedAsset.AssetName);

   75                 DialogResult dr = MessageBox.Show(

   76                   this, msg, "Overwrite", MessageBoxButtons.OKCancel,

   77                   MessageBoxIcon.Warning, MessageBoxDefaultButton.Button2);

   78                 if (dr == DialogResult.OK)

   79                 {

   80                   try

   81                   {

   82                     dcAspnetdb.RegisterDevice(ServerName, DatabaseName, DeviceNumber);

   83                     Guid? deviceId = Guid.Empty;

   84                     dcAtomdb.GetDeviceId(_deviceNumber.ToString(), ref deviceId);

   85                     dcAtomdb.SetAssetDevice(selectedAsset.Id, deviceId);

   86                     scope.Complete();

   87                   }

   88                   catch (Exception ex)

   89                   {

   90                     MessageBox.Show(

   91                       this, string.Format("Transaction failed: {0}", ex.Message),

   92                       "Update Failed", MessageBoxButtons.OK, MessageBoxIcon.Error);

   93                   }

   94                   DialogResult = DialogResult.OK;

   95                 }

   96                 else

   97                   DialogResult = DialogResult.None;

   98               }

   99             }

It does everything. Including escalation to DTS if necessary. The code is simple, because to roll back you don’t have to do anything but let the transaction scope object go out of scope without committing. So essentially you define the transaction scope literally and explicitly with a using statement on a TransactionScope instance, and you write normal exception handlers, and the last thing you do on the success path is invoke scope.Complete() to commit the transaction. All the DTC enlistment waffle is taken care of automatically, including working out whether it’s necessary at all.

Fantastic stuff, Microsoft. It took a decade, but it was worth it.

Posted by peterw | with no comments

Religions at large are toxic and objectionable. I don’t just mean organised religion. I mean deliberate inculcation of superstition in children. Look, here it is in a nutshell: no credible explanation of anything has ever worked better with God in it. Let’s deconstruct some of the more annoying bullshit.

The world is unlikely, therefore someone made it.

Everything that happens every day is vanishingly improbable. The chances that something will happen are 100%, and there are so many candidate futures that if they are randomly distributed then all of them are unspeakably implausible. Thus, the chances of realising an unbelievably implausible future are 100%. All this is modified by the fact that the world is an emergent system full of strange attractors, rendering certain outcomes close to inevitable. But that model also precludes divine intervention: given the myriad complex paths the water might take down the side of a wineglass, what are the chances that most of the water will end up in the bottom of the glass? 100%.

Chances that God did it just for me: lim x→0.

Even if we were to allow the complexity argument, adding God doesn’t solve the problem, it simply moves it. You then have to explain an even more implausible super-being that creates universes but doesn’t like being looked at and keeps hiding, despite an allegedly profound personal interest in each and every one of us: a kind of galactic snuffleupagus. Churches dodge this glaring flaw in their twaddle by telling their marks that God is ineffable. This is merely an erudite way of giving them a clip round the ear and telling them to eat their dinner.

Evolution is unlikely, therefore it doesn’t happen.

Bollocks. Apart from the fact that nearly everything is unlikely, the probability of evolution occurring is 100% because it has already been observed to take place. Nearly all mosquitoes carry the genes for tolerance of DDT. All rabbits in Australia have high resistance to myxomatosis I and II (bio-weapons tested on them by the Australian government).

You can’t breed dogs with cats, therefore it’s impossible to turn one species into another, therefore evolution can’t happen. The existence of many species is therefore an observed miracle and evidence of the existence of God.

Once again this falls apart in the first phrase. You can breed dogs with cats, you just can’t do it the old fashioned way. You can even breed fruit-flies with jellyfish, producing glow-in-the-dark fruit-flies. I hear someone even produced a cat with glow-in-the-dark fur, using the same spliced gene. Having disposed of the

You can’t coherently counter argue this because the argument is utterly specious. It’s a progression of non-sequiturs beginning with a false statement.

Evolution works like this: you buy all the lotto tickets. Not only are your chances of winning quite high, you keep last week’s winner and cash it in again. Over time it’s like sorting through a deck of cards patiently extracting high-value cards. It doesn’t take long to find yourself in possession of a genetic full-house. Unfortunately, everyone else is doing this too so you have to keep cheating like mad.

You can’t prove the non-existence of God, therefore God exists.

However much fun it may be to to flip this on its head (you can’t prove the existence of God, therefore God does not exist) both arguments are bollocks for reasons hilariously explicated by John Cleese.

However, you can formulate explanations of the world with and without, and Occam’s Razor tells us to choose the simplest reliable explanation. Reliability is measured by the utility and repeatability of prediction. Occasional pearls of actual wisdom are salted through superstition in an attempt to give it credibility prior to gulling the marks, and unfortunately many people are stupid, and even some intelligent people are so desperate for meaning in their tawdry, frustrated lives that they’ll believe any old ***.

Posted by peterw | with no comments
  • Necessity is the mother of invention.
  • Each new invention creates new needs.
  • This leads to more invention.
  • This feedback loop is an exponential function limited by resources.
  • Resource accessibility is itself a need spawning invention.

These factors combine to produce first industrial, then technological revolutions.

  • Invention is to some extent the searching of a phase space for a solution space.
  • Initially, finding any part of the solution space is regarded as a success.
  • When a solution is known, the terms are redefined to map the solution space in search of higher-yield solutions.

This is an evolutionary process.

  • At any point in the evolution of a technology, the immediately preceding state was a necessary precursor.

Therefore technology is an end as well as a means.

Technologist, bootstrap thyself!

Posted by peterw | with no comments

Packet structure

Field Length in bytes Start byte Description
Packet start marker 5   [SOH]ATOM
[SOH] = 0x01
Packet number 1 0 Rolls over ever 256 packets. Multi-packet operations like firmware transfers often hold a constant packet number, using it as a sort of session identifier.
Has payload 1 1 Set bit 0 to indicate that the packet includes a payload.
Sender 2 2 Device number. This is a ushort that identifies the device that sent the packet. Often set to zero. Not terribly important.
Recipient 2 4 Device number. This is a ushort that identifies the device to which the packet is being sent. 0 is self, 1 is broadcast.
Command 2 6 This is a processing command. For example, a command of LongPollRequest when sent to an ATOM will cause it to reply with a command of LongPollResponse and a payload full of positional information and other telemetry. You do not need a separate command for every possible CAS event, because you can include that information in the payload.
Payload length 1 8 The payload length is one byte larger than the value specified in this field, supporting payload lengths of up to 256 bytes.
Header checksum 1 9

  112 int Checksum(byte[] buffer, int startIndex, int length, int m)

  113 {

  114   int c = 0;

  115   for (int i = 0; i < length; i++) c += buffer[startIndex + i];

  116   return c % m;

  117 }

Payload X 10 Payload length (PL).
Payload checksum 1 10 + X Same function as header checksum applied to X payload bytes
Payload XOR 1 11 + X

  119 byte CheckXor(byte[] buffer, int startIndex, int length)

  120 {

  121   byte b = 0;

  122   for (int i = 0; i < length; i++) b ^= buffer[startIndex + i];

  123   return b;

  124 }

Trailer 1 10 or
12 + X
This is a literal [Newline] (0x0A) that follows either the header checksum or the payload XOR, depending on whether there is a payload.

Events and commands

These are the currently defined event and command codes. Atoms have a couple of commands for reading events, and the interpretation of an event depends on the event code within the payload. You could piggyback this or you could create your own parallel mechanism for CAS logs (probably the better idea).

   10 public enum AtomEvent

   11 {

   12   Log = 0,

   13   CalibrationDataAcknowledgement = 1,

   14   PowerupFail = 2,

   15   PositionReport = 3,

   16   DigitalInputChange = 4,

   17   DigitalPulseStart = 5, DigitalPulseStop = 6, //magflo   

   18   AtomStartup = 7,

   19   AlarmSet = 8, AlarmReset = 9,

   20   EquipmentStart = 10, EquipmentStop = 11,

   21   EmergencyRequiresAck = 12,

   22   UserStatusUpdate = 13,

   23   ExternalAlert = 14,

   24   EmergencyNoAck = 15,

   25   AtomShutdown = 16,

   26   MovementHalted = 17, MovementResumed = 18,

   27   CorruptedEvent = 19,

   28   GeofenceEntry = 20, GeofenceExit = 21,

   29   GeofenceSpeedExceeded = 22,

   30   CorruptAtomId = 23,

   31   DigitalAlarmSet1 = 32, DigitalAlarmSet2 = 33,

   32   DigitalAlarmSet3 = 34, DigitalAlarmSet4 = 35,

   33   DigitalAlarmSet5 = 36, DigitalAlarmSet6 = 37,

   34   DigitalAlarmSet7 = 38, DigitalAlarmSet8 = 39,

   35   AnalogAlarmSet1 = 40, AnalogAlarmSet2 = 41,

   36   AnalogAlarmSet3 = 42, AnalogAlarmSet4 = 43,

   37   AnalogAlarmSet5 = 44, AnalogAlarmSet6 = 45,

   38   AnalogAlarmSet7 = 46, AnalogAlarmSet8 = 47,

   39   DigitalAlarmReset1 = 48, DigitalAlarmReset2 = 49,

   40   DigitalAlarmReset3 = 50, DigitalAlarmReset4 = 51,

   41   DigitalAlarmReset5 = 52, DigitalAlarmReset6 = 53,

   42   DigitalAlarmReset7 = 54, DigitalAlarmReset8 = 55,

   43   AnalogAlarmReset1 = 56, AnalogAlarmReset2 = 57,

   44   AnalogAlarmReset3 = 58, AnalogAlarmReset4 = 59,

   45   AnalogAlarmReset5 = 60, AnalogAlarmReset6 = 61,

   46   AnalogAlarmReset7 = 62, AnalogAlarmReset8 = 63,

   47   BandSpeed = 64,

   48   BandRpm = 65,

   49   BandServiceBrakeBySpeed = 66,

   50   BandGear1 = 67, BandGear2 = 68, BandGear3 = 69,

   51   BandTurnG1 = 70, BandTurnG2 = 71, BandTurnG3 = 72, BandTurnG4 = 73,

   52   BandTurnG5 = 74, BandTurnG6 = 75, BandTurnG7 = 76, BandTurnG8 = 77,

   53   HardBrakeAccelerometer = 78,

   54   HardBrakeDeltaVDeltaT = 79,

   55   HardCornering = 80,

   56   DigitalPotCalibrationAcknowledgement = 88,

   57   IButtonScanned = 89,

   58   AnonymousMovement = 90,

   59   GeofenceSpeedExceededDelta = 91,

   60   GeofenceSpeedExceededBoundary = 92,

   61   ManDownDuressActivated = 93,

   62   DistanceTravelled = 94,

   63   Rollover = 100,

   64   ManDownNoMovement = 101,

   65   ManDownOutOfRange = 102,

   66   PumpCounter1Data = 103, PumpCounter2Data = 104,

   67   FuelLevelChanged = 105,

   68   Pump1Start = 106, Pump1End = 107,

   69   Pump2Start = 108, Pump2End = 109,

   70   RpmRunningSeconds = 110,

   71   ExcessiveRpmStart = 111, ExcessiveRpmEnd = 112,

   72   Terrain = 113,

   73   GeofenceSpeedExceededSummary = 114,

   74   RollingInNeutralStart = 25, RollingInNeutralEnd = 115,

   75   LogViaSatellite = 116,

   76   TripSummary = 117,

   77   RunningPeriodEnd = 118,

   78   FirstValidGpsLock = 119,

   79   Seatbelt = 120,

   80   Handbrake = 121,

   81   DriverRestSelected = 122,

   82   DriverResumptionSelected = 123,

   83   DriverLogOutSelected = 124,

   84   DriverFixedMessage = 125,

   85 }

   86 public enum Command

   87 {

   88   DeviceNotResponding = 0xFF00,

   89   FirmwareProgress = 0xFF01,

   90   DestroySession = 0xFF02,

   91   EventsWaiting = 0x0100,

   92   ShortPollRequest = 0x0200,

   93   ShortPollResponse = 0x0300,

   94   LongPollRequest = 0x0400,

   95   LongPollResponse = 0x0500,

   96   EventResponse = 0x0600,

   97   Acknowledge = 0x0700,

   98   LogRequest = 0x0800,

   99   LogResponse = 0x0900,

  100   RequestNextLog = 0x0A00,

  101   WriteParameterBlock = 0x0C00,

  102   ReadParameterBlock = 0x0D00,

  103   BlockMapRequest = 0x1400,

  104   BlockMapResponse = 0x1500,

  105   CommitFirmware = 0x1601,

  106   RebootDevice = 0x1700,

  107   ServerPresenceRequest = 0x7300,

  108   ServerPresenceResponse = 0x7400,

  109   ParameterBlock = 0x0E00,

  110   EventRequest = 0x1B00,

  111   BurstFirmwareBlock = 0x4000,

  112   WriteFirmwareBlock = 0x5000,

  113   AckFirmwareBlock = 0x6000,

  114   WriteString = 0x2400,

  115   ReadString = 0x2500,

  116   ReadStringResponse = 0x2600,

  117   NegativeAcknowledge = 0x2700,

  118   PrimaryDigitalOutHigh = 0x7500,

  119   SatelliteEventResponse = 0x9000,

  120   SatelliteEventResponseRequiresAck = 0x9100,

  121   SatelliteEventAck = 0x9200,

  122 }

Posted by peterw | with no comments
More Posts Next page »