From e60239a6ccd12f76ec30d2318b1a9094f3010ac1 Mon Sep 17 00:00:00 2001 From: gbamber Date: Mon, 9 Jan 2017 07:56:13 +0000 Subject: [PATCH] V0.2.1.0: Triggers working git-svn-id: https://svn.code.sf.net/p/lazarus-ccr/svn@5612 8e941d3f-bd1b-0410-a28a-d453659cc2b4 --- applications/foobot/foobot_utility.pas | 111 +++++++------ applications/foobot/monitor/foobotmonitor.lps | 151 +++++++++--------- applications/foobot/monitor/umainform.pas | 120 ++++++++------ 3 files changed, 204 insertions(+), 178 deletions(-) diff --git a/applications/foobot/foobot_utility.pas b/applications/foobot/foobot_utility.pas index 3f014d6ed..4c52be8bd 100644 --- a/applications/foobot/foobot_utility.pas +++ b/applications/foobot/foobot_utility.pas @@ -49,14 +49,17 @@ const C_CO2 = 4; C_VOC = 5; C_ALLPOLLU = 6; + // Used in Trigger functions + C_HIGH = 0; + C_LOW = 1; type TDataFetchType = (dfLast, dfStartEnd); // FetchFoobotData // Unused - TSensorType = (st_time, st_pm, st_tmp, st_hum, st_co2, st_voc, st_allpollu); // Unused + TSensorType = (st_time, st_pm, st_tmp, st_hum, st_co2, st_voc, st_allpollu); // Unused - TAlertType = (at_high, at_low); // TAlertRec + TAlertType = (at_high, at_low); TAlertRec = record AlertTriggered: boolean; @@ -157,29 +160,29 @@ begin WriteInteger('Foobot', 'CurrentFoobot', TheCurrentFoobot); WriteString('Foobot', 'CurrentFoobotName', sFoobotName); WriteFloat(sFoobotName, 'pmTriggerHigh', - double(FooBotTriggerArray[0, C_PM])); + double(FooBotTriggerArray[C_HIGH, C_PM])); WriteFloat(sFoobotName, 'pmTriggerLow', - double(FooBotTriggerArray[1, C_PM])); + double(FooBotTriggerArray[C_LOW, C_PM])); WriteFloat(sFoobotName, 'tmpTriggerHigh', - double(FooBotTriggerArray[0, C_TMP])); + double(FooBotTriggerArray[C_HIGH, C_TMP])); WriteFloat(sFoobotName, 'tmpTriggerLow', - double(FooBotTriggerArray[1, C_TMP])); + double(FooBotTriggerArray[C_LOW, C_TMP])); WriteFloat(sFoobotName, 'humTriggerHigh', - double(FooBotTriggerArray[0, C_HUM])); + double(FooBotTriggerArray[C_HIGH, C_HUM])); WriteFloat(sFoobotName, 'humTriggerLow', - double(FooBotTriggerArray[1, C_HUM])); + double(FooBotTriggerArray[C_LOW, C_HUM])); WriteFloat(sFoobotName, 'co2TriggerHigh', - double(FooBotTriggerArray[0, C_CO2])); + Integer(FooBotTriggerArray[C_HIGH, C_CO2])); WriteFloat(sFoobotName, 'co2TriggerLow', - double(FooBotTriggerArray[1, C_CO2])); + Integer(FooBotTriggerArray[C_LOW, C_CO2])); WriteFloat(sFoobotName, 'vocTriggerHigh', - double(FooBotTriggerArray[0, C_VOC])); + Integer(FooBotTriggerArray[C_HIGH, C_VOC])); WriteFloat(sFoobotName, 'vocTriggerLow', - double(FooBotTriggerArray[1, C_VOC])); + Integer(FooBotTriggerArray[C_LOW, C_VOC])); WriteFloat(sFoobotName, 'allpolluTriggerHigh', - double(FooBotTriggerArray[0, C_ALLPOLLU])); + double(FooBotTriggerArray[C_HIGH, C_ALLPOLLU])); WriteFloat(sFoobotName, 'allpolluTriggerLow', - double(FooBotTriggerArray[1, C_ALLPOLLU])); + double(FooBotTriggerArray[C_LOW, C_ALLPOLLU])); end; Result := True; except @@ -206,19 +209,19 @@ begin // Load current Foobot triggers with HLINI do begin - FooBotTriggerArray[0, C_PM] := ReadFloat(sFoobotName, 'pmTriggerHigh', 0); - FooBotTriggerArray[1, C_PM] := ReadFloat(sFoobotName, 'pmTriggerLow', 0); - FooBotTriggerArray[0, C_TMP] := ReadFloat(sFoobotName, 'tmpTriggerHigh', 0); - FooBotTriggerArray[1, C_TMP] := ReadFloat(sFoobotName, 'tmpTriggerLow', 0); - FooBotTriggerArray[0, C_HUM] := ReadFloat(sFoobotName, 'humTriggerHigh', 0); - FooBotTriggerArray[1, C_HUM] := ReadFloat(sFoobotName, 'humTriggerLow', 0); - FooBotTriggerArray[0, C_CO2] := ReadFloat(sFoobotName, 'co2TriggerHigh', 0); - FooBotTriggerArray[1, C_CO2] := ReadFloat(sFoobotName, 'co2TriggerLow', 0); - FooBotTriggerArray[0, C_VOC] := ReadFloat(sFoobotName, 'vocTriggerHigh', 0); - FooBotTriggerArray[1, C_VOC] := ReadFloat(sFoobotName, 'vocTriggerLow', 0); - FooBotTriggerArray[0, C_ALLPOLLU] := + FooBotTriggerArray[C_HIGH, C_PM] := ReadFloat(sFoobotName, 'pmTriggerHigh', 0); + FooBotTriggerArray[C_LOW, C_PM] := ReadFloat(sFoobotName, 'pmTriggerLow', 0); + FooBotTriggerArray[C_HIGH, C_TMP] := ReadFloat(sFoobotName, 'tmpTriggerHigh', 0); + FooBotTriggerArray[C_LOW, C_TMP] := ReadFloat(sFoobotName, 'tmpTriggerLow', 0); + FooBotTriggerArray[C_HIGH, C_HUM] := ReadFloat(sFoobotName, 'humTriggerHigh', 0); + FooBotTriggerArray[C_LOW, C_HUM] := ReadFloat(sFoobotName, 'humTriggerLow', 0); + FooBotTriggerArray[C_HIGH, C_CO2] := ReadFloat(sFoobotName, 'co2TriggerHigh', 0); + FooBotTriggerArray[C_LOW, C_CO2] := ReadFloat(sFoobotName, 'co2TriggerLow', 0); + FooBotTriggerArray[C_HIGH, C_VOC] := ReadFloat(sFoobotName, 'vocTriggerHigh', 0); + FooBotTriggerArray[C_LOW, C_VOC] := ReadFloat(sFoobotName, 'vocTriggerLow', 0); + FooBotTriggerArray[C_HIGH, C_ALLPOLLU] := ReadFloat(sFoobotName, 'allpolluTriggerHigh', 0); - FooBotTriggerArray[1, C_ALLPOLLU] := + FooBotTriggerArray[C_LOW, C_ALLPOLLU] := ReadFloat(sFoobotName, 'allpolluTriggerLow', 0); end; Result := True; @@ -377,19 +380,17 @@ var FoobotDataHighTimes[iMember] := aDateTime; SaveHighLows; end; - if ((UseTriggers = True) and (FooBotTriggerArray[0, iMember] <> 0)) then + if ((UseTriggers = True) and (FooBotTriggerArray[C_HIGH, iMember] <> 0)) then begin // Do High Trigger // Sets AlertRec record - if (aValue > FooBotTriggerArray[0, iMember]) then - begin - AlertRec[iMember].AlertTriggered := True; - AlertRec[iMember].AlertTime := aDateTime; - AlertRec[iMember].AlertType := 0; - AlertRec[iMember].AlertValue := aValue; - end - else - AlertRec[iMember].AlertTriggered := False; + if (aValue > FooBotTriggerArray[C_HIGH, iMember]) then + begin + AlertRec[iMember].AlertTriggered := True; + AlertRec[iMember].AlertTime := aDateTime; + AlertRec[iMember].AlertType := C_HIGH; + AlertRec[iMember].AlertValue := aValue; + end; end; end; @@ -402,21 +403,29 @@ var FoobotDataLowTimes[iMember] := aDateTime; SaveHighLows; end; - if ((UseTriggers = True) and (FooBotTriggerArray[1, iMember] <> 0)) then + if ((UseTriggers = True) and (FooBotTriggerArray[C_LOW, iMember] <> 0)) then begin // Do Low Trigger // Sets AlertRec record - if (aValue < FooBotTriggerArray[1, iMember]) then + if (aValue < FooBotTriggerArray[C_LOW, iMember]) then begin AlertRec[iMember].AlertTriggered := True; AlertRec[iMember].AlertTime := aDateTime; - AlertRec[iMember].AlertType := 1; + AlertRec[iMember].AlertType :=C_LOW; AlertRec[iMember].AlertValue := aValue; - end - else - AlertRec[iMember].AlertTriggered := False; + end; end; end; + + procedure ClearTriggers; + Var iCount:Integer; + begin + for iCount := C_PM to C_ALLPOLLU do + begin + AlertRec[iCount].AlertTriggered:=False; + AlertRec[iCount].AlertValue := 0; + end; + end; // ========== Internal routines end ============= begin ResetArrays; @@ -428,6 +437,8 @@ begin Exit(False); if FooBotDataObject.units.Count = 0 then Exit(False); + // Reset all triggers (if on) + If UseTriggers then ClearTriggers; // J=Column, K=Row for K := VarArrayLowBound(FoobotDataObject.datapoints, 1) to VarArrayHighBound(FoobotDataObject.datapoints, 1) do @@ -494,45 +505,41 @@ begin end; function GetHighTrigger(Const aSensor:Integer):Variant; -//TAlertType = (at_high, at_low) begin Result:=0; if UseTriggers = False then Exit; If ((aSensor < C_PM) or (aSensor > C_ALLPOLLU)) then exit; - Result:=FooBotTriggerArray[0, aSensor]; + Result:=FooBotTriggerArray[C_HIGH, aSensor]; end; function GetLowTrigger(Const aSensor:Integer):Variant; -//TAlertType = (at_high, at_low) begin Result:=0; if UseTriggers = False then Exit; If ((aSensor < C_PM) or (aSensor > C_ALLPOLLU)) then exit; - Result:=FooBotTriggerArray[1, aSensor]; + Result:=FooBotTriggerArray[C_LOW, aSensor]; end; function SetHighTrigger(const aSensor: integer; const aValue: variant): boolean; -//TAlertType = (at_high, at_low) begin Result := False; if UseTriggers = False then Exit; - if aValue <> FooBotTriggerArray[0, aSensor] then + if aValue <> FooBotTriggerArray[C_HIGH, aSensor] then begin - FooBotTriggerArray[0, aSensor] := aValue; + FooBotTriggerArray[C_HIGH, aSensor] := aValue; Result := True; end; end; function SetLowTrigger(const aSensor: integer; const aValue: variant): boolean; -//TAlertType = (at_high, at_low) begin Result := False; if UseTriggers = False then Exit; - if aValue <> FooBotTriggerArray[1, Ord(aSensor)] then + if aValue <> FooBotTriggerArray[C_LOW, Ord(aSensor)] then begin - FooBotTriggerArray[1, aSensor] := aValue; + FooBotTriggerArray[C_LOW, aSensor] := aValue; Result := True; end; end; diff --git a/applications/foobot/monitor/foobotmonitor.lps b/applications/foobot/monitor/foobotmonitor.lps index c37a912cd..0e0121a0d 100644 --- a/applications/foobot/monitor/foobotmonitor.lps +++ b/applications/foobot/monitor/foobotmonitor.lps @@ -3,14 +3,14 @@ - + - + @@ -19,9 +19,9 @@ - - - + + + @@ -34,7 +34,7 @@ - + @@ -44,7 +44,7 @@ - + @@ -53,15 +53,16 @@ - + + - - - + + + @@ -71,7 +72,7 @@ - + @@ -79,7 +80,7 @@ - + @@ -90,7 +91,7 @@ - + @@ -101,7 +102,7 @@ - + @@ -110,15 +111,15 @@ - + - + - + @@ -189,7 +190,7 @@ - + @@ -218,14 +219,14 @@ - + - + @@ -269,130 +270,130 @@ - + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - + - + - - + + - - + + - - + + - - + + - + - - + + - - + + - - + + - + - + - - + + - - + + - + - - + + - - + + - - + + - - + + - - + + - + diff --git a/applications/foobot/monitor/umainform.pas b/applications/foobot/monitor/umainform.pas index 9bb43c3f3..863d465a2 100644 --- a/applications/foobot/monitor/umainform.pas +++ b/applications/foobot/monitor/umainform.pas @@ -187,6 +187,7 @@ type bDisplayGuagesOnly, bDisplayYellowLines, bDisplayRedLines: boolean; iFudgeFactor: integer; iCurrentFoobot: integer; + HighTriggerColor,LowTriggerColor:TColor; foobotmenuarray: array of TMenuItem; procedure DisplayReadings; procedure UpdateGuage(Sender: TAnalogSensor; SensorNumber: integer); @@ -240,6 +241,8 @@ begin iFudgeFactor := 20; // only needed if height set in form.create bDisplayGuagesOnly := False; INI.PlainTextMode := True; + HighTriggerColor:=clYellow; + LowTriggerColor:=clAqua; bDisplayYellowLines := INI.ReadBool('Config', 'DisplayYellowLines', False); mnu_optionsDisplayYellowLines.Checked := bDisplayYellowLines; bDisplayRedLines := INI.ReadBool('Config', 'DisplayRedLines', False); @@ -254,6 +257,12 @@ begin {$IFDEF DEBUGMODE} UseTriggers := False; {$ENDIF} + If UseTriggers then + begin + mnu_options_triggersActivateTriggers.Enabled:=TRUE; + mnu_options_triggersActivateTriggers.Checked:=TRUE; + mnu_options_triggersActivateTriggers.Caption:='Set Triggers Off'; + end; end; procedure Tmainform.FormActivate(Sender: TObject); @@ -421,6 +430,8 @@ begin WriteBool('Config', 'DisplayRedLines', bDisplayRedLines); // Triggers WriteBool('Config', 'UseTriggers', UseTriggers); + WriteString('Config', 'HighTriggerColour', ColorToString(HighTriggerColor)); + WriteString('Config', 'LowTriggerColour', ColorToString(LowTriggerColor)); PlainTextMode := False; end; end; @@ -494,7 +505,9 @@ begin as_allpollu.ValueMax := INI.ReadFloat('Config', 'allpolluMaxValue', MAX_ALLPOLLU); // Triggers UseTriggers:=INI.ReadBool('Config', 'UseTriggers', False); - INI.PlainTextMode := False; + HighTriggerColor:=StringToColor(INI.ReadString('Config', 'HighTriggerColour', 'clYellow')); + LowTriggerColor:=StringToColor(INI.ReadString('Config', 'LowTriggerColour', 'clAqua')); +INI.PlainTextMode := False; end; procedure Tmainform.FormWindowStateChange(Sender: TObject); @@ -782,23 +795,23 @@ begin end; C_CO2: begin - lbl_co2high.Caption := Format('High: %f %s', - [double(FoobotDataHighs[SensorNumber]), FoobotDataObject.Units[SensorNumber]]) + + lbl_co2high.Caption := Format('High: %d %s', + [Integer(FoobotDataHighs[SensorNumber]), FoobotDataObject.Units[SensorNumber]]) + LineEnding + 'on ' + FormatDateTime('dd/mm tt', TDateTime(FoobotDataHighTimes[SensorNumber])); - lbl_co2Low.Caption := Format('Low: %f %s', - [double(FoobotDataLows[SensorNumber]), FoobotDataObject.Units[SensorNumber]]) + + lbl_co2Low.Caption := Format('Low: %d %s', + [Integer(FoobotDataLows[SensorNumber]), FoobotDataObject.Units[SensorNumber]]) + LineEnding + 'on ' + FormatDateTime('dd/mm tt', TDateTime( FoobotDataLowTimes[SensorNumber])); end; C_VOC: begin - lbl_vochigh.Caption := Format('High: %f %s', - [double(FoobotDataHighs[SensorNumber]), FoobotDataObject.Units[SensorNumber]]) + + lbl_vochigh.Caption := Format('High: %d %s', + [Integer(FoobotDataHighs[SensorNumber]), FoobotDataObject.Units[SensorNumber]]) + LineEnding + 'on ' + FormatDateTime('dd/mm tt', TDateTime(FoobotDataHighTimes[SensorNumber])); - lbl_vocLow.Caption := Format('Low: %f %s', - [double(FoobotDataLows[SensorNumber]), FoobotDataObject.Units[SensorNumber]]) + + lbl_vocLow.Caption := Format('Low: %d %s', + [Integer(FoobotDataLows[SensorNumber]), FoobotDataObject.Units[SensorNumber]]) + LineEnding + 'on ' + FormatDateTime('dd/mm tt', TDateTime( FoobotDataLowTimes[SensorNumber])); end; @@ -825,32 +838,32 @@ begin case SensorNumber of C_PM: begin - Value := FoobotData_pm[0]; + Value := FoobotData_pm[iCurrentFoobot]; Caption := Format('PM (%s): ', [FoobotDataObject.Units[SensorNumber]]); end; C_TMP: begin - Value := FoobotData_tmp[0]; + Value := FoobotData_tmp[iCurrentFoobot]; Caption := Format('Temp (%s): ', [FoobotDataObject.Units[SensorNumber]]); end; C_HUM: begin - Value := FoobotData_hum[0]; + Value := FoobotData_hum[iCurrentFoobot]; Caption := Format('Hum. (%s): ', [FoobotDataObject.Units[SensorNumber]]); end; C_CO2: begin - Value := FoobotData_co2[0]; + Value := FoobotData_co2[iCurrentFoobot]; Caption := Format('CO2 (%s): ', [FoobotDataObject.Units[SensorNumber]]); end; C_VOC: begin - Value := FoobotData_voc[0]; + Value := FoobotData_voc[iCurrentFoobot]; Caption := Format('VOC (%s): ', [FoobotDataObject.Units[SensorNumber]]); end; C_ALLPOLLU: begin - Value := FoobotData_allpollu[0]; + Value := FoobotData_allpollu[iCurrentFoobot]; Caption := Format('All (%s): ', [FoobotDataObject.Units[SensorNumber]]); end; end; @@ -866,24 +879,24 @@ end; procedure Tmainform.DoHighTriggerAlert(Const iSensorNum:Integer;Const aValue:Variant); begin Case iSensorNum of - C_PM:as_pm.Color:=clYellow; - C_TMP:as_tmp.Color:=clYellow; - C_HUM:as_hum.Color:=clYellow; - C_CO2:as_co2.Color:=clYellow; - C_VOC:as_voc.Color:=clYellow; - C_ALLPOLLU:as_allpollu.Color:=clYellow; + C_PM:as_pm.Color:=HighTriggerColor; + C_TMP:as_tmp.Color:=HighTriggerColor; + C_HUM:as_hum.Color:=HighTriggerColor; + C_CO2:as_co2.Color:=HighTriggerColor; + C_VOC:as_voc.Color:=HighTriggerColor; + C_ALLPOLLU:as_allpollu.Color:=HighTriggerColor; end; end; procedure Tmainform.DoLowTriggerAlert(Const iSensorNum:Integer;Const aValue:Variant); begin Case iSensorNum of - C_PM:as_pm.Color:=clAqua; - C_TMP:as_tmp.Color:=clAqua; - C_HUM:as_hum.Color:=clAqua; - C_CO2:as_co2.Color:=clAqua; - C_VOC:as_voc.Color:=clAqua; - C_ALLPOLLU:as_allpollu.Color:=clAqua; + C_PM:as_pm.Color:=LowTriggerColor; + C_TMP:as_tmp.Color:=LowTriggerColor; + C_HUM:as_hum.Color:=LowTriggerColor; + C_CO2:as_co2.Color:=LowTriggerColor; + C_VOC:as_voc.Color:=LowTriggerColor; + C_ALLPOLLU:as_allpollu.Color:=LowTriggerColor; end; end; @@ -913,29 +926,19 @@ begin UpdateGuage(as_co2, C_CO2); UpdateGuage(as_voc, C_VOC); UpdateGuage(as_allpollu, C_ALLPOLLU); - if not bDisplayGuagesOnly then - begin - for iCount := 1 to 6 do - UpdateHighLow(iCount); - end; - GraphCurrentReading; - // Process Trigger Alerts on each call to FoobotDataObjectToArrays if UseTriggers then try // Look for alerts in each sensor for iCount := C_PM to C_ALLPOLLU do - if AlertRec[iCount].AlertTriggered then + begin + if (AlertRec[iCount].AlertTriggered=TRUE) then begin // Alert found. High or low? - if AlertRec[iCount].AlertType = 0 then + if (AlertRec[iCount].AlertType = C_HIGH) then begin // A high alert - do something DoHighTriggerAlert(iCount,AlertRec[iCount].AlertValue); - { - ShowMessageFmt('High alert member %d (value %f) exceeded', - [iCount, double(AlertRec[iCount].AlertValue)]); - } end else begin @@ -948,9 +951,18 @@ begin end; end else RestoreNormalColour(iCount); + end; except raise Exception.Create('Unable to process triggers in DisplayReadings'); end; + if not bDisplayGuagesOnly then + begin + for iCount := 1 to 6 do + UpdateHighLow(iCount); + end; + GraphCurrentReading; + + end else raise Exception.Create('FoobotDataObjectToArrays error in DisplayReadings'); @@ -970,18 +982,18 @@ begin Exit; {$ENDIF} try - lineseries_pm.AddXY(FoobotData_time[0], - AsPercent(FoobotData_pm[0], as_pm.ValueMin, as_pm.ValueMax)); - lineseries_tmp.AddXY(FoobotData_time[0], AsPercent(FoobotData_tmp[0], + lineseries_pm.AddXY(FoobotData_time[iCurrentFoobot], + AsPercent(FoobotData_pm[iCurrentFoobot], as_pm.ValueMin, as_pm.ValueMax)); + lineseries_tmp.AddXY(FoobotData_time[iCurrentFoobot], AsPercent(FoobotData_tmp[iCurrentFoobot], as_tmp.ValueMin, as_tmp.ValueMax)); - lineseries_hum.AddXY(FoobotData_time[0], - AsPercent(FoobotData_hum[0], as_hum.ValueMin, as_hum.ValueMax)); - lineseries_co2.AddXY(FoobotData_time[0], - AsPercent(FoobotData_co2[0], as_co2.ValueMin, as_co2.ValueMax)); - lineseries_voc.AddXY(FoobotData_time[0], - AsPercent(FoobotData_voc[0], as_voc.ValueMin, as_voc.ValueMax)); - lineseries_allpollu.AddXY(FoobotData_time[0], - AsPercent(FoobotData_allpollu[0], as_allpollu.ValueMin, as_allpollu.ValueMax)); + lineseries_hum.AddXY(FoobotData_time[iCurrentFoobot], + AsPercent(FoobotData_hum[iCurrentFoobot], as_hum.ValueMin, as_hum.ValueMax)); + lineseries_co2.AddXY(FoobotData_time[iCurrentFoobot], + AsPercent(FoobotData_co2[iCurrentFoobot], as_co2.ValueMin, as_co2.ValueMax)); + lineseries_voc.AddXY(FoobotData_time[iCurrentFoobot], + AsPercent(FoobotData_voc[iCurrentFoobot], as_voc.ValueMin, as_voc.ValueMax)); + lineseries_allpollu.AddXY(FoobotData_time[iCurrentFoobot], + AsPercent(FoobotData_allpollu[iCurrentFoobot], as_allpollu.ValueMin, as_allpollu.ValueMax)); except raise Exception.Create('Unable to update graph in GraphCurrentReading'); end; @@ -993,10 +1005,15 @@ procedure Tmainform.GraphHistory; var iCount: integer; iStartSeconds, iEndSeconds: int64; + bTempUseTriggers:Boolean; begin {$IFDEF DEBUGMODE} Exit; {$ENDIF} + // Turn off triggers (if on) + bTempUseTriggers:=UseTriggers; + UseTriggers:=FALSE; + iEndSeconds := DateTimeToUnix(Now) - 3600; iStartSeconds := iEndSeconds - (2 * (24 * 3600)); // 49 hours before Now grp_chart.Caption := Format('History since %s', @@ -1023,6 +1040,7 @@ begin as_allpollu.ValueMax)); end; finally + UseTriggers:=bTempUseTriggers; ResetArrays; // at end end; end;