namespace IfLoc.Sim; // Reference constants for the frozen IF-LOC v1.0 contract. // Source of truth: meta/contracts/ble-device-interface.md. Keep the two in lockstep; // enum values and message-type ids are append-only once frozen. /// Wire message-type ids (frame header byte 1). public enum MessageType : byte { Telemetry = 0x01, CaptureTrigger = 0x02, CaptureResult = 0x03, Alert = 0x04, Ack = 0x05, CmdRequestSnapshot = 0x10, CmdSetFrequency = 0x11, CmdSetMode = 0x12, CmdSetTelemetryRate = 0x13, CmdTimeSync = 0x14, CmdSetUtility = 0x15, OtaBegin = 0x20, OtaData = 0x21, OtaEnd = 0x22, UsageLogRequest = 0x30, UsageLogRecord = 0x31, UsageLogEnd = 0x32, ClaimChallenge = 0x40, ClaimAssertion = 0x41, ClaimCertReq = 0x42, ClaimCert = 0x43, } /// §4.1 locateMode. public enum LocateMode : byte { Single = 0, Twin = 1, Null = 2, Sweep = 3, TwinSweep = 4, Omni = 5, TwinOmni = 6, NotAvailable = 0xFF, } /// §4.2 signalType. public enum SignalType : byte { Active = 0, LineDropActive = 1, Power = 2, GroupedPower = 3, Cathodic = 4, Sonde = 5, Radio = 6, FaultFind = 7, NotAvailable = 0xFF, } /// §4.4 utilityType (APWA-aligned). public enum UtilityType : byte { None = 0, Gas = 1, Power = 2, Communications = 3, Water = 4, Sewer = 5, Fiber = 6, Other = 7, NotAvailable = 0xFF, } /// §4.3 warningFlags bitfield. [Flags] public enum WarningFlags : ushort { None = 0, Shallow = 1 << 0, Overload = 1 << 1, SwingTilt = 1 << 2, DepthInvalid = 1 << 3, CurrentInvalid = 1 << 4, OutOfRange = 1 << 5, DistortionHigh = 1 << 6, LowBattery = 1 << 7, } /// §4.5 statusFlags bitfield. [Flags] public enum StatusFlags : byte { None = 0, Locating = 1 << 0, MenuActive = 1 << 1, TimeSynced = 1 << 2, DepthModeAuto = 1 << 3, } /// §5.1 triggerType. public enum TriggerType : byte { ButtonSingle = 0, ButtonHold = 1, OffsetRequest = 2, AppInitiated = 3, } /// §5.2 outcome — the deterministic capture outcome (SRS-LOG-7). public enum CaptureOutcome : byte { Stored = 0, StoredFlagged = 1, Rejected = 2, } /// §5.4 reasonCode / gateStatus. public enum ReasonCode : byte { Ok = 0, FixTypeTooLow = 1, HrmsExceeded = 2, VrmsExceeded = 3, CorrectionAgeExceeded = 4, NoActiveTicket = 5, ImuCalibrationInvalid = 6, HeadingConfidenceLow = 7, BufferFull = 8, NoPosition = 9, WaiverRequired = 10, Other = 255, } /// §5.2 fixType (GGA-quality mapping; 3 reserved). public enum FixType : byte { NoFix = 0, Autonomous = 1, Dgps = 2, RtkFixed = 4, RtkFloat = 5, } /// Frozen wire constants and sentinels. public static class IfLoc { public const byte FrameVersion = 0x01; // Fixed frame lengths (Appendix A). public const int HeaderLen = 4; public const int TelemetryFrameLen = 32; public const int TelemetryPayloadLen = 28; // offsets 4..31 public const int CaptureTriggerFrameLen = 36; public const int CaptureResultFrameLen = 52; // Sentinels (§1). public const short DepthNoValue = unchecked((short)0x8000); public const ushort CurrentInvalid = 0xFFFF; public const uint FrequencyNa = 0xFFFFFFFF; public const short GuidanceNa = unchecked((short)0x8000); public const int PositionNoValue = unchecked((int)0x80000000); public const ushort RmsUnknown = 0xFFFF; // GATT (§2) — recommended UUIDs the App builds against. public const string BaseUuidFormat = "A9E1{0:X4}-1B4C-4F9A-9B7E-2D6F0C3A5E11"; public static string LocateServiceUuid => string.Format(BaseUuidFormat, 0x0001); public static string ProtocolInfoUuid => string.Format(BaseUuidFormat, 0x0002); public static string TelemetryUuid => string.Format(BaseUuidFormat, 0x0003); public static string EventUuid => string.Format(BaseUuidFormat, 0x0004); public static string CommandUuid => string.Format(BaseUuidFormat, 0x0005); public static string CaptureResultUuid => string.Format(BaseUuidFormat, 0x0006); public static string LinkStateUuid => string.Format(BaseUuidFormat, 0x0007); public static string BulkOtaUuid => string.Format(BaseUuidFormat, 0x0008); public static string ClaimUuid => string.Format(BaseUuidFormat, 0x0009); }