unit ObservedAndWM;

  interface
    type
      tBaseToWindows = (
        {$INCLUDE 'G:\source code\Teensy\home control\HC3\shared\enumerations\BaseToWindows.inc'}
                       );

           //          0         1             2            3         4
      tBoardSlot  = (bsBogus, bsACDetect_1, bsACDetect_2, bsBMP085, bsDepth,
           //              5         6              7               8
                       bsDHT22_1, bsDHT22_2, bsLightningNOTUSED, bsRelay_1,
           //               9               10              11           12
                       bsResistance_1, bsResistance_2, bsResistance_3, bsSPS30,
           //              13         14           15       16
                       bsSwitch_1, bsSwitch_2, bsVC0706, bsVoltage_1,
           //              17          18         19          20
                       bsVoltage_2, bsRelay_2, bsRelay_3, bsSwitch_3,
           //              21         22        23          24
                       bsSwitch_4, bsWire_1, bsBroadcast, bsWire_2,
           //              25           26           27           28
                       bsAnemometer, bsRainGauge, bsACIntent, bsHeatIntent,
           //              29            30
                       bsBoardReboot, bsMemoryCheck); // hardcoded to jibe with table

      tFailureReason = (
        {$INCLUDE 'G:\source code\Teensy\home control\HC3\shared\enumerations\FailureReasons.inc'}
                       );

      tObserved = (obZeroDoNotRemove, obAC, obFurnace, obGuestRoom, obHobbyRoom,
                 //      5             6          7         8         9
                     obImplicit, obKitchen, obLeftPower, obLibrary, obLR,
                 //    10         11     12         13       14       15
                     obLRRelay, obMBR, obOffice, obOutside, obPond, obRightPower,
                 //    16         17          18          19
                      obShop, obShopHeater, obShopRelay, obTBD,
                 //     20        21         22        23         24
                     obTVRoom, obTVRelay, obCarport, obDeck, obPrototypeRelay,
                 //     25             26               27         28
                     obGCFridge, obGCFridgeSetting, obPrototype, obACIntent,
                 //     29
                     obHeatIntent);
                 //         0            1          2           3              4
      tRRFFieldType = (rrftUnknown, rrftBoolean, rrftFloat, rrftInteger, rrftBooleanIntent);

           //               0              1         2         3         4
      tSensorType = (stZeroDoNotRemove, stDHT22, stSPS30, stACDetect, stBMP085,
          //               5               6             7            8
                       stWeathervane, stRainGauge, stAnemometer, stDepthGauge,
          //               9           10               11        12        13
                       stSwitch, stLightningNOTUSED, stRelay, stVC0706, stPhotocell,
          //               14        15       16       17      18         19
                       stVoltage, stBogus, stSCD40, stSCD30, stDHT20, stBroadcast,
          //               20        21
                       stSpeedup, stSHT45 );
                       // hardcoded to jibe with table

      tSeriesKind = (skAreaSeries, skLineSeries, skPointSeries);

                   //  0         1                  2        3       4        5
      tTableUsed = (tuLight, tuLightningNOTUSED, tuOnOff, tuPond, tuPower, tuRain,
                   //   6          7            8        9       10       11
                      tuSPS30, tuThermostats, tuTRHP, tuWind, tuVC0706, tuCO2);  // fixed order

                //     0             1        2         3            4
      tWhatMeasured2 = (
                        {$INCLUDE 'G:\source code\Teensy\home control\HC3\shared\enumerations\WhatMeasured2.inc'}
                       );
             // see InitializeObservedAndWM.LoadMeasurement2Info

      tWindowsToBase = (
        {$INCLUDE 'G:\source code\Teensy\home control\HC3\shared\enumerations\WindowsToBase.inc'}
                       );
    const
      DHT20FailureReasons =[frDHT20_BadChecksum, frDHT20_BadConnection,
                              frDHT20_BytesAllZero, frDHT20_MissingBytes,
                              frDHT20_Timeout, frDHT20_TWI_Data_NAK,
                              frDHT20_TWI_DataTooLong, frDHT20_TWI_Mystery,
                              frDHT20_TWI_SLA_NAK];
      NoValueMeasurements = [wm2Bogus, wm2Calibrate];
      SeriesKindName: array[tSeriesKind] of string =
                         ('area series', 'line series', 'point series');
      SPS30FailureReasons = [frSPS30NoFan, frSPS30NoOldAutoclean, frSPS30NoReset,
                               frSPS30NoResponse, frSPS30NoSerialPort,
                               frSPS30NoSetAutoclean, frSPS30NoShutdown,
                               frSPS30NoStartMeasurement];

    type
      tMeasurements2 = set of tWhatMeasured2;

    type
      tMeasurementDescription2 = record
        Name: string;
        FieldType: tRRFFieldType;
        PlotZeroes: boolean;
        TheSeriesKind: tSeriesKind;
        end (* tMeasurementDescription2 *);

    const
      TBD = '(TBD)';

    var
      MeasurementInfo2: array[tWhatMeasured2] of tMeasurementDescription2;

    function  GetObservedName(const OB: tObserved): string;
    procedure InitializeObservedAndWM;
    function  MeasurementNames(const M: tMeasurements2): string;

  implementation
    uses
      HC3DM    (* dmHC3 *),
      MyConsts (* nullstring *),
      SysUtils (* Format *);

    const
      clDepth    = $99BAFF;
      clPressure = $FF89FF;

    function GetObservedName(const OB: tObserved): string;
      (* just look it up *)
    
      begin (* GetObservedName *)
        with dmHC3.qObserved do
          if Locate('UID', ord(OB), []) then
            Result := FieldByName('Observed').AsString
          else
            Result := Format('name not defined(%d)', [ord(OB)])
      end   (* GetObservedName *);

    procedure InitializeObservedAndWM;
      (* called from TableManager *)

      procedure LoadMeasurement2Info;
        (* debulk *)

        procedure LMI(const WM: tWhatMeasured2;
                      const Nam: string;
                      FT: tRRFFieldType = rrftFloat;
                      SeriesKind: char = 'L';
                      PlotZ: boolean = true);
          (* shortcut *)

          begin (* LMI *)
            with dmHC3.qNewWhatMeasured do
              begin (* qNewWhatMeasured *)
                ParamByName('UID').AsInteger := ord(WM);
                ParamByName('WM' ).AsString  := Nam;
                ExecSQL
              end   (* qNewWhatMeasured *);

            with MeasurementInfo2[WM] do
              begin (* MeasurementInfo2[WM] *)
                Name := Nam;
                FieldType := FT;
                case SeriesKind of
                  'A': TheSeriesKind := skAreaSeries;
                  'L': TheSeriesKind := skLineSeries;
                  'P': TheSeriesKind := skPointSeries
                  end (* case *);
                PlotZeroes := PlotZ
              end   (* MeasurementInfo2[WM] *)
          end   (* LMI *);

        procedure LMINZ(const WM: tWhatMeasured2;
                        const Nam: string;
                        FT: tRRFFieldType = rrftFloat;
                        SeriesKind: char = 'L');
          (* don't plot zeroes *)

          begin (* LMINZ *)
            LMI(WM, Nam, FT, SeriesKind, false)
          end   (* LMINZ *);
              // see also BoardManager.qAllBoardSensorsAfterScroll
        begin (* LoadMeasurement2Info *)
          dmHC3.qClearWhatMeasured.ExecSQL;

          //     WM                         Name              FieldType     SeriesKind
          LMI  (wm2Bogus,                 'bogus'                                );
          LMI  (wm2Calibrate,             'calibrate'                            );
          LMI  (wm2CO2ppm,                'CO2 (ppm)'                            );
          LMI  (wm2Debugging,             'debugging'                            );
          LMINZ(wm2DepthInches,           'depth (inches)',    rrftFloat         );
          LMI  (wm2DeviceFailure,         'device failure',    rrftInteger       );
          LMI  (wm2EventCount,            'event count',       rrftInteger,  'A' );
          LMINZ(wm2DewpointF,             'dew point, °F'                        );
          LMI  (wm2FailureDatum,          'datum'                                );
          LMI  (wm2Frequency,             'damped frequency'                     );
          LMI  (wm2Jammed,                'jammed'                               );
          LMI  (wm2FrequencyMax,          'max frequency'                        );
          LMI  (wm2FrequencyMin,          'min frequency'                        );
          LMI  (wm2FrequencyRaw,          'raw frequency'                        );
          LMINZ(wm2HumidexF,              'HumidexF'                             );
          LMI  (wm2IsNowOn,               'on?',               rrftBoolean,  'A' );
          LMINZ(wm2MassPM1,               'PM  1.0, µg/m^3'                      );
          LMINZ(wm2MassPM10,              'PM 10.0, µg/m^3'                      );
          LMINZ(wm2MassPM25,              'PM  2.5, µg/m^3',   rrftFloat,    'P' );
          LMINZ(wm2MassPM4,               'PM  4.0, µg/m^3'                      );
          LMINZ(wm2NumPM05,               'PM  0.5, #/cm^3'                      );
          LMINZ(wm2NumPM1,                'PM  1.0, #/cm^3'                      );
          LMINZ(wm2NumPM10,               'PM 10.0, #/cm^3'                      );
          LMINZ(wm2NumPM25,               'PM  2.5, #/cm^3'                      );
          LMINZ(wm2NumPM4,                'PM  4.0, #/cm^3'                      );
          LMI  (wm2NewEvents,             'new events',        rrftInteger       );
          LMINZ(wm2OnOffIntent,           'intent',            rrftBooleanIntent );
          LMINZ(wm2PartSize,              'avg size, µm'                         );
          LMINZ(wm2PressureInches,        'pressure'                             );
          LMINZ(wm2RainMMPerHour,         'rain mm/hr'                           );
          LMI  (wm2Resistance,            'resistance',        rrftFloat,    'A' );
          LMINZ(wm2RH,                    'RH'                                   );
          LMI  (wm2SpeedupChanged,        'speedup',           rrftInteger       );
          LMI  (wm2SwitchClosed,          'closed?',           rrftBoolean       );
          LMINZ(wm2TargetF,               'target, °F'                           );
          LMINZ(wm2TempF,                 'temperature, °F'                      );
          LMI  (wm2Undefined,             'undefined'                            );
          LMI  (wm2VC0706Manual,          'manual',            rrftInteger       );
          LMI  (wm2VC0706Motion,          'motion-detected',   rrftInteger       );
          LMI  (wm2VC0706Snap,            'scheduled',         rrftInteger       );
          LMINZ(wm2Voltage,                'voltage',          rrftFloat,    'P' );
        end   (* LoadMeasurement2Info *);

      begin (* InitializeObservedAndWM *)
        dmHC3.qObserved.Open;
        LoadMeasurement2Info
      end   (* InitializeObservedAndWM *);

    function MeasurementNames(const M: tMeasurements2): string;
      (* service for device creators *)

      var
        WM: tWhatMeasured2;

      begin (* MeasurementNames *)
        Result := nullstring;
        for WM := low(tWhatMeasured2) to high(tWhatMeasured2) do
          if WM in M then
            Result := Format('%s, %s', [Result, MeasurementInfo2[WM].Name]);
        if Result <> nullstring then
          Result := copy(Result, 3, maxint)
      end   (* MeasurementNames *);


end.
