anchor.diff:      Revision : uint32 option
   }
   with
  -    static member From(pkt : Udp.UdpReceived) =
  -
  -        let cms = Aris.ProtocolMessages.CommandModule.CommandModuleBeacon.ParseFrom(pkt.udpResult.Buffer)
  +    static member inline ValueOrNone<'T when 'T : equality> (v : 'T)
  +        = if (v = Unchecked.defaultof<'T>) then None else Some v
  +
  +    static member internal From(pkt : Udp.UdpReceived) =
  +
  +        let cms = Aris.CommandModuleBeacon.Parser.ParseFrom(pkt.udpResult.Buffer)
           {
               SrcIpAddr = pkt.udpResult.RemoteEndPoint.Address
  -            ArisCurrent =   if cms.HasArisCurrent       then Some cms.ArisCurrent       else None
  -            ArisPower =     if cms.HasArisPower         then Some cms.ArisPower         else None
  -            ArisVoltage =   if cms.HasArisVoltage       then Some cms.ArisVoltage       else None
  -            CpuTemp =       if cms.HasCpuTemp           then Some cms.CpuTemp           else None
  -            Revision =      if cms.HasRevision          then Some cms.Revision          else None
  +            ArisCurrent =   CommandModuleBeacon.ValueOrNone cms.ArisCurrent
  +            ArisPower =     CommandModuleBeacon.ValueOrNone cms.ArisPower
  +            ArisVoltage =   CommandModuleBeacon.ValueOrNone cms.ArisVoltage
  +            CpuTemp =       CommandModuleBeacon.ValueOrNone cms.CpuTemp
  +            Revision =      CommandModuleBeacon.ValueOrNone cms.Revision
           }
   
   
  
positive.code:     let Voyager = "VG"
  
  type SonarBeacon = {
      timestamp: DateTime
      srcIpAddr: IPAddress
      serialNumber: SerialNumber
      systemType: SystemType
      softwareVersion: SoftwareVersion
      connectionState: AvailabilityState
      cpuTemp: float32 option
      isDiverHeld: bool
      isVoyager: bool
  }
  
  // Defender beacon
  
negative.code:                 sn, addr1, addr2)
  
      module DefenderLog =
          let logDefenderDetected (sn : SerialNumber) (ipAddr : IPAddress) =
              Log.Information("Defender {SerialNumber} detected at {IPAddress}", sn, ipAddr)
  
          let logDefenderExpired (sn : int) (lastHeard : DateTimeOffset) (ipAddr : IPAddress) =
              Log.Information("Defender {SerialNumber} expired from available table; last heard {LastHeader} on {IPAddr}",
                  sn, lastHeard, ipAddr)
  
          let logDefenderChangedAddress (sn : int) (addr1 : IPAddress) (addr2 : IPAddress) =
              Log.Information("Defender {SerialNumber} changed IP address from {OldIPAddress} to {NewIPAddress}",
                  sn, addr1, addr2)
  
  