V0.2.1.0.0 Work-in-progress

git-svn-id: https://svn.code.sf.net/p/lazarus-ccr/svn@5608 8e941d3f-bd1b-0410-a28a-d453659cc2b4
This commit is contained in:
gbamber
2017-01-08 16:05:33 +00:00
parent 7b9d82db39
commit a137e86358
13 changed files with 553 additions and 261 deletions

View File

@ -41,10 +41,26 @@ const
FOOBOT_DATA_START_FINISH_URL = FOOBOT_DATA_START_FINISH_URL =
'https://api.foobot.io/v2/device/%s/datapoint/%s/%s/%s/'; 'https://api.foobot.io/v2/device/%s/datapoint/%s/%s/%s/';
HIGHLOWMAX = 6; HIGHLOWMAX = 6;
C_TIME = 0;
C_PM = 1;
C_TMP = 2;
C_HUM = 3;
C_CO2 = 4;
C_VOC = 5;
C_ALLPOLLU = 6;
C_NONE = 7;
type type
TDataFetchType = (dfLast, dfStartEnd); TDataFetchType = (dfLast, dfStartEnd);
TSensorType = (st_time, st_pm, st_tmp, st_hum, st_co2, st_voc, st_allpollu); TSensorType = (st_time, st_pm, st_tmp, st_hum, st_co2, st_voc, st_allpollu);
TAlertType = (at_high, at_low);
TAlertRec = record
AlertTriggered: boolean;
AlertTime: TDateTime;
AlertType: TAlertType;
AlertValue: variant;
end;
function EncodeStringBase64(const s: string): string; function EncodeStringBase64(const s: string): string;
function FetchAuthenticationKey(aUsername, aUserPassword: string): boolean; function FetchAuthenticationKey(aUsername, aUserPassword: string): boolean;
@ -62,6 +78,7 @@ function FetchFoobotData(DataFetchType: TDataFetchType = dfLast;
// - also populates HighLow arrays // - also populates HighLow arrays
function FoobotDataObjectToArrays: boolean; function FoobotDataObjectToArrays: boolean;
// Utility functions // Utility functions
function ResetArrays: boolean; function ResetArrays: boolean;
function ResetObjects: boolean; function ResetObjects: boolean;
@ -70,15 +87,24 @@ function SaveHighLows: boolean;
function LoadHighLows: boolean; function LoadHighLows: boolean;
var var
// Used to fetch server data
HttpClient: TFPHTTPClient; HttpClient: TFPHTTPClient;
// Holds identity values for multiple Foobots
FoobotIdentityObject: TFoobotIdentityObject; FoobotIdentityObject: TFoobotIdentityObject;
// Holds data for current Foobot
FoobotDataObject: TFoobotDataObject; FoobotDataObject: TFoobotDataObject;
sAuthenticationKey: string; sAuthenticationKey: string;
SensorType: TSensorType; SensorType: TSensorType; // st_time, st_pm, st_tmp etc.
// Boolean to enable/disable serialisation of HighLows. Default = TRUE
SaveLoadHighLows: boolean; SaveLoadHighLows: boolean;
// Boolean to enable/disable Trigger functions
UseTriggers: boolean;
// Used in data fetch
TheCurrentFoobot: integer; TheCurrentFoobot: integer;
// INIFile located in GetAppConfig(false) folder
HLINI: TIniFile; HLINI: TIniFile;
// Easier access to datapoints // Dynamic arrays - easier access to datapoints
// Call FoobotDataObjectToArrays to populate them // Call FoobotDataObjectToArrays to populate them
FoobotData_time: array of TDateTime; FoobotData_time: array of TDateTime;
FoobotData_pm: array of double; FoobotData_pm: array of double;
@ -93,9 +119,17 @@ var
FoobotDataHighTimes: array[0..HIGHLOWMAX] of variant; FoobotDataHighTimes: array[0..HIGHLOWMAX] of variant;
FoobotDataLowTimes: array[0..HIGHLOWMAX] of variant; FoobotDataLowTimes: array[0..HIGHLOWMAX] of variant;
// [0=Low(at_low)..1=High(at_high), C_PM..C_ALLPOLLU]
// Dynamic in case of future changes (e.g. more triggers)
FooBotTriggerArray: array of array of variant;
// Set by FoobotDataObjectToArrays
AlertRec: array [C_TIME..C_ALLPOLLU] of TAlertRec;
giCount: integer; // used in initialization
implementation implementation
function SaveHighLows: boolean; function SaveHighLows: boolean;
// Save values to an INI data file
var var
sFoobotName: string; sFoobotName: string;
begin begin
@ -109,39 +143,42 @@ begin
HLINI.WriteString('Foobot', 'CurrentFoobotName', sFoobotName); HLINI.WriteString('Foobot', 'CurrentFoobotName', sFoobotName);
// Particulates // Particulates
HLINI.WriteFloat(sFoobotName, 'pmHigh', double(FoobotDataHighs[1])); HLINI.WriteFloat(sFoobotName, 'pmHigh', double(FoobotDataHighs[C_PM]));
HLINI.WriteDateTime(sFoobotName, 'pmHighTime', TDateTime(FoobotDataHighTimes[1])); HLINI.WriteDateTime(sFoobotName, 'pmHighTime', TDateTime(FoobotDataHighTimes[C_PM]));
HLINI.WriteFloat(sFoobotName, 'pmLow', double(FoobotDataLows[1])); HLINI.WriteFloat(sFoobotName, 'pmLow', double(FoobotDataLows[C_PM]));
HLINI.WriteDateTime(sFoobotName, 'pmLowTime', TDateTime(FoobotDataLowTimes[1])); HLINI.WriteDateTime(sFoobotName, 'pmLowTime', TDateTime(FoobotDataLowTimes[C_PM]));
// Temp // Temp
HLINI.WriteFloat(sFoobotName, 'tmpHigh', double(FoobotDataHighs[2])); HLINI.WriteFloat(sFoobotName, 'tmpHigh', double(FoobotDataHighs[C_TMP]));
HLINI.WriteDateTime(sFoobotName, 'tmpHighTime', TDateTime(FoobotDataHighTimes[2])); HLINI.WriteDateTime(sFoobotName, 'tmpHighTime', TDateTime(FoobotDataHighTimes[C_TMP]));
HLINI.WriteFloat(sFoobotName, 'tmpLow', double(FoobotDataLows[2])); HLINI.WriteFloat(sFoobotName, 'tmpLow', double(FoobotDataLows[C_TMP]));
HLINI.WriteDateTime(sFoobotName, 'tmpLowTime', TDateTime(FoobotDataLowTimes[2])); HLINI.WriteDateTime(sFoobotName, 'tmpLowTime', TDateTime(FoobotDataLowTimes[C_TMP]));
// Humidity // Humidity
HLINI.WriteFloat(sFoobotName, 'humHigh', double(FoobotDataHighs[3])); HLINI.WriteFloat(sFoobotName, 'humHigh', double(FoobotDataHighs[C_HUM]));
HLINI.WriteDateTime(sFoobotName, 'humHighTime', TDateTime(FoobotDataHighTimes[3])); HLINI.WriteDateTime(sFoobotName, 'humHighTime', TDateTime(FoobotDataHighTimes[C_HUM]));
HLINI.WriteFloat(sFoobotName, 'humLow', double(FoobotDataLows[3])); HLINI.WriteFloat(sFoobotName, 'humLow', double(FoobotDataLows[C_HUM]));
HLINI.WriteDateTime(sFoobotName, 'humLowTime', TDateTime(FoobotDataLowTimes[3])); HLINI.WriteDateTime(sFoobotName, 'humLowTime', TDateTime(FoobotDataLowTimes[C_HUM]));
// CO2 // CO2
HLINI.WriteInteger(sFoobotName, 'co2High', integer(FoobotDataHighs[4])); HLINI.WriteInteger(sFoobotName, 'co2High', integer(FoobotDataHighs[C_CO2]));
HLINI.WriteDateTime(sFoobotName, 'co2HighTime', TDateTime(FoobotDataHighTimes[4])); HLINI.WriteDateTime(sFoobotName, 'co2HighTime', TDateTime(FoobotDataHighTimes[C_CO2]));
HLINI.WriteInteger(sFoobotName, 'co2Low', integer(FoobotDataLows[4])); HLINI.WriteInteger(sFoobotName, 'co2Low', integer(FoobotDataLows[C_CO2]));
HLINI.WriteDateTime(sFoobotName, 'co2LowTime', TDateTime(FoobotDataLowTimes[4])); HLINI.WriteDateTime(sFoobotName, 'co2LowTime', TDateTime(FoobotDataLowTimes[C_CO2]));
// Volatile Compounds // Volatile Compounds
HLINI.WriteInteger(sFoobotName, 'vocHigh', integer(FoobotDataHighs[5])); HLINI.WriteInteger(sFoobotName, 'vocHigh', integer(FoobotDataHighs[C_VOC]));
HLINI.WriteDateTime(sFoobotName, 'vocHighTime', TDateTime(FoobotDataHighTimes[5])); HLINI.WriteDateTime(sFoobotName, 'vocHighTime', TDateTime(FoobotDataHighTimes[C_VOC]));
HLINI.WriteInteger(sFoobotName, 'vocLow', integer(FoobotDataLows[5])); HLINI.WriteInteger(sFoobotName, 'vocLow', integer(FoobotDataLows[C_VOC]));
HLINI.WriteDateTime(sFoobotName, 'vocLowTime', TDateTime(FoobotDataLowTimes[5])); HLINI.WriteDateTime(sFoobotName, 'vocLowTime', TDateTime(FoobotDataLowTimes[C_VOC]));
// All Pollution // All Pollution
HLINI.WriteFloat(sFoobotName, 'allpolluHigh', double(FoobotDataHighs[6])); HLINI.WriteFloat(sFoobotName, 'allpolluHigh', double(FoobotDataHighs[C_ALLPOLLU]));
HLINI.WriteDateTime(sFoobotName, 'allpolluHighTime', TDateTime(FoobotDataHighTimes[6])); HLINI.WriteDateTime(sFoobotName, 'allpolluHighTime',
HLINI.WriteFloat(sFoobotName, 'allpolluLow', double(FoobotDataLows[6])); TDateTime(FoobotDataHighTimes[C_ALLPOLLU]));
HLINI.WriteDateTime(sFoobotName, 'allpolluLowTime', TDateTime(FoobotDataLowTimes[6])); HLINI.WriteFloat(sFoobotName, 'allpolluLow', double(FoobotDataLows[C_ALLPOLLU]));
Result:=TRUE; HLINI.WriteDateTime(sFoobotName, 'allpolluLowTime',
TDateTime(FoobotDataLowTimes[C_ALLPOLLU]));
Result := True;
end; end;
function LoadHighLows: boolean; function LoadHighLows: boolean;
// Load values from an INI data file
var var
sFoobotName: string; sFoobotName: string;
begin begin
@ -158,47 +195,55 @@ begin
Exit(False); Exit(False);
// Particulates // Particulates
FoobotDataHighs[1] := HLINI.ReadFloat(sFoobotName, 'pmHigh', 0); FoobotDataHighs[C_PM] := HLINI.ReadFloat(sFoobotName, 'pmHigh', 0);
FoobotDataHighTimes[1] := HLINI.ReadDateTime(sFoobotName, 'pmHighTime', Now); FoobotDataHighTimes[C_PM] := HLINI.ReadDateTime(sFoobotName, 'pmHighTime', Now);
FoobotDataLows[1] := HLINI.ReadFloat(sFoobotName, 'pmLow', 0); FoobotDataLows[C_PM] := HLINI.ReadFloat(sFoobotName, 'pmLow', 0);
FoobotDataLowTimes[1] := HLINI.ReadDateTime(sFoobotName, 'pmLowTime', Now); FoobotDataLowTimes[C_PM] := HLINI.ReadDateTime(sFoobotName, 'pmLowTime', Now);
// Temp // Temp
FoobotDataHighs[2] := HLINI.ReadFloat(sFoobotName, 'tmpHigh', 0); FoobotDataHighs[C_TMP] := HLINI.ReadFloat(sFoobotName, 'tmpHigh', 0);
FoobotDataHighTimes[2] := HLINI.ReadDateTime(sFoobotName, 'tmpHighTime', Now); FoobotDataHighTimes[C_TMP] := HLINI.ReadDateTime(sFoobotName, 'tmpHighTime', Now);
FoobotDataLows[2] := HLINI.ReadFloat(sFoobotName, 'tmpLow', 0); FoobotDataLows[C_TMP] := HLINI.ReadFloat(sFoobotName, 'tmpLow', 0);
FoobotDataLowTimes[2] := HLINI.ReadDateTime(sFoobotName, 'tmpLowTime', Now); FoobotDataLowTimes[C_TMP] := HLINI.ReadDateTime(sFoobotName, 'tmpLowTime', Now);
// Humidity // Humidity
FoobotDataHighs[3] := HLINI.ReadFloat(sFoobotName, 'humHigh', 0); FoobotDataHighs[C_HUM] := HLINI.ReadFloat(sFoobotName, 'humHigh', 0);
FoobotDataHighTimes[3] := HLINI.ReadDateTime(sFoobotName, 'humHighTime', Now); FoobotDataHighTimes[C_HUM] := HLINI.ReadDateTime(sFoobotName, 'humHighTime', Now);
FoobotDataLows[3] := HLINI.ReadFloat(sFoobotName, 'humLow', 0); FoobotDataLows[C_HUM] := HLINI.ReadFloat(sFoobotName, 'humLow', 0);
FoobotDataLowTimes[3] := HLINI.ReadDateTime(sFoobotName, 'humLowTime', Now); FoobotDataLowTimes[C_HUM] := HLINI.ReadDateTime(sFoobotName, 'humLowTime', Now);
// CO2 // CO2
FoobotDataHighs[4] := HLINI.ReadInteger(sFoobotName, 'co2High', 0); FoobotDataHighs[C_CO2] := HLINI.ReadInteger(sFoobotName, 'co2High', 0);
FoobotDataHighTimes[4] := HLINI.ReadDateTime(sFoobotName, 'co2HighTime', Now); FoobotDataHighTimes[C_CO2] := HLINI.ReadDateTime(sFoobotName, 'co2HighTime', Now);
FoobotDataLows[4] := HLINI.ReadInteger(sFoobotName, 'co2Low', 0); FoobotDataLows[C_CO2] := HLINI.ReadInteger(sFoobotName, 'co2Low', 0);
FoobotDataLowTimes[4] := HLINI.ReadDateTime(sFoobotName, 'co2LowTime', Now); FoobotDataLowTimes[C_CO2] := HLINI.ReadDateTime(sFoobotName, 'co2LowTime', Now);
// Volatile Compounds // Volatile Compounds
FoobotDataHighs[5] := HLINI.ReadInteger(sFoobotName, 'vocHigh', 0); FoobotDataHighs[C_VOC] := HLINI.ReadInteger(sFoobotName, 'vocHigh', 0);
FoobotDataHighTimes[5] := HLINI.ReadDateTime(sFoobotName, 'vocHighTime', Now); FoobotDataHighTimes[C_VOC] := HLINI.ReadDateTime(sFoobotName, 'vocHighTime', Now);
FoobotDataLows[5] := HLINI.ReadInteger(sFoobotName, 'vocLow', 0); FoobotDataLows[C_VOC] := HLINI.ReadInteger(sFoobotName, 'vocLow', 0);
FoobotDataLowTimes[5] := HLINI.ReadDateTime(sFoobotName, 'vocLowTime', Now); FoobotDataLowTimes[C_VOC] := HLINI.ReadDateTime(sFoobotName, 'vocLowTime', Now);
// All Pollution // All Pollution
FoobotDataHighs[6] := HLINI.ReadFloat(sFoobotName, 'allpolluHigh', 0); FoobotDataHighs[C_ALLPOLLU] := HLINI.ReadFloat(sFoobotName, 'allpolluHigh', 0);
FoobotDataHighTimes[6] := HLINI.ReadDateTime(sFoobotName, 'allpolluHighTime', Now); FoobotDataHighTimes[C_ALLPOLLU] :=
FoobotDataLows[6] := HLINI.ReadFloat(sFoobotName, 'allpolluLow', 0); HLINI.ReadDateTime(sFoobotName, 'allpolluHighTime', Now);
FoobotDataLowTimes[6] := HLINI.ReadDateTime(sFoobotName, 'allpolluLowTime', Now); FoobotDataLows[C_ALLPOLLU] := HLINI.ReadFloat(sFoobotName, 'allpolluLow', 0);
Result:=TRUE; FoobotDataLowTimes[C_ALLPOLLU] :=
HLINI.ReadDateTime(sFoobotName, 'allpolluLowTime', Now);
Result := True;
end; end;
// ToDo: Multiple Foobots? // Function to make the Foobot data accessible
// Also sets the HighLow array values
// Also sets triggers
{
TAlertRec = Record
Triggered:Boolean;
AlertTime:TDateTime;
AlertType:TAlertType;
AlertValue:Variant;
end;
}
function FoobotDataObjectToArrays: boolean; function FoobotDataObjectToArrays: boolean;
var var
J, K: integer; J, K: integer;
Mydatapoint: variant; Mydatapoint: variant;
{
dtDate, dtStart, dtEnd: TDateTime;
sStart, sEnd: string;
}
iUnixSecs: int64; iUnixSecs: int64;
// ========= Internal routines start =========== // ========= Internal routines start ===========
procedure SetHigh(iMember: integer; aValue: variant; aDateTime: TDateTime); procedure SetHigh(iMember: integer; aValue: variant; aDateTime: TDateTime);
@ -207,6 +252,21 @@ var
begin begin
FoobotDataHighs[iMember] := aValue; FoobotDataHighs[iMember] := aValue;
FoobotDataHighTimes[iMember] := aDateTime; FoobotDataHighTimes[iMember] := aDateTime;
SaveHighLows;
end;
if ((UseTriggers = True) and (FooBotTriggerArray[1, iMember] <> 0)) then
begin
// Process High Trigger
// Sets AlertRec record
if (aValue > FooBotTriggerArray[1, iMember]) then
begin
AlertRec[iMember].AlertTriggered := True;
AlertRec[iMember].AlertTime := aDateTime;
AlertRec[iMember].AlertType := at_high;
AlertRec[iMember].AlertValue := aValue;
end
else
AlertRec[iMember].AlertTriggered := False;
end; end;
end; end;
@ -216,6 +276,21 @@ var
begin begin
FoobotDataLows[iMember] := aValue; FoobotDataLows[iMember] := aValue;
FoobotDataLowTimes[iMember] := aDateTime; FoobotDataLowTimes[iMember] := aDateTime;
SaveHighLows;
end;
if ((UseTriggers = True) and (FooBotTriggerArray[0, iMember] <> 0)) then
begin
// Process Low Trigger
// Sets AlertRec record
if (aValue < FooBotTriggerArray[1, iMember]) then
begin
AlertRec[iMember].AlertTriggered := True;
AlertRec[iMember].AlertTime := aDateTime;
AlertRec[iMember].AlertType := at_low;
AlertRec[iMember].AlertValue := aValue;
end
else
AlertRec[iMember].AlertTriggered := False;
end; end;
end; end;
// ========== Internal routines end ============= // ========== Internal routines end =============
@ -238,60 +313,87 @@ begin
begin begin
Mydatapoint := FoobotDataObject.datapoints[K][J]; Mydatapoint := FoobotDataObject.datapoints[K][J];
case J of case J of
0: // First field is a DateTime C_TIME: // First field is a DateTime
begin begin
iUnixSecs := int64(Mydatapoint); iUnixSecs := int64(Mydatapoint);
SetLength(FoobotData_time, K + 1); SetLength(FoobotData_time, K + 1);
FoobotData_time[K] := UnixToDateTime(iUnixSecs); FoobotData_time[K] := UnixToDateTime(iUnixSecs);
end; end;
1: // Particulate matter C_PM: // Particulate matter
begin begin
SetLength(FoobotData_pm, K + 1); SetLength(FoobotData_pm, K + 1);
FoobotData_pm[K] := double(MyDataPoint); FoobotData_pm[K] := double(MyDataPoint);
SetHigh(J, FoobotData_pm[K], FoobotData_time[K]); SetHigh(J, FoobotData_pm[K], FoobotData_time[K]);
SetLow(J, FoobotData_pm[K], FoobotData_time[K]); SetLow(J, FoobotData_pm[K], FoobotData_time[K]);
end; end;
2: // Temperature C_TMP: // Temperature
begin begin
SetLength(FoobotData_tmp, K + 1); SetLength(FoobotData_tmp, K + 1);
FoobotData_tmp[K] := double(MyDataPoint); FoobotData_tmp[K] := double(MyDataPoint);
SetHigh(J, FoobotData_tmp[K], FoobotData_time[K]); SetHigh(J, FoobotData_tmp[K], FoobotData_time[K]);
SetLow(J, FoobotData_tmp[K], FoobotData_time[K]); SetLow(J, FoobotData_tmp[K], FoobotData_time[K]);
end; end;
3: // Humidity C_HUM: // Humidity
begin begin
SetLength(FoobotData_hum, K + 1); SetLength(FoobotData_hum, K + 1);
FoobotData_hum[K] := double(MyDataPoint); FoobotData_hum[K] := double(MyDataPoint);
SetHigh(J, FoobotData_hum[K], FoobotData_time[K]); SetHigh(J, FoobotData_hum[K], FoobotData_time[K]);
SetLow(J, FoobotData_hum[K], FoobotData_time[K]); SetLow(J, FoobotData_hum[K], FoobotData_time[K]);
end; end;
4: // CO2 C_CO2: // CO2
begin begin
SetLength(FoobotData_co2, K + 1); SetLength(FoobotData_co2, K + 1);
FoobotData_co2[K] := integer(MyDataPoint); FoobotData_co2[K] := integer(MyDataPoint);
SetHigh(J, FoobotData_co2[K], FoobotData_time[K]); SetHigh(J, FoobotData_co2[K], FoobotData_time[K]);
SetLow(J, FoobotData_co2[K], FoobotData_time[K]); SetLow(J, FoobotData_co2[K], FoobotData_time[K]);
end; end;
5: // Volatile compounds C_VOC: // Volatile compounds
begin begin
SetLength(FoobotData_voc, K + 1); SetLength(FoobotData_voc, K + 1);
FoobotData_voc[K] := integer(MyDataPoint); FoobotData_voc[K] := integer(MyDataPoint);
SetHigh(J, FoobotData_voc[K], FoobotData_time[K]); SetHigh(J, FoobotData_voc[K], FoobotData_time[K]);
SetLow(J, FoobotData_voc[K], FoobotData_time[K]); SetLow(J, FoobotData_voc[K], FoobotData_time[K]);
end; end;
6: // All Pollution C_ALLPOLLU: // All Pollution
begin begin
SetLength(FoobotData_allpollu, K + 1); SetLength(FoobotData_allpollu, K + 1);
FoobotData_allpollu[K] := double(MyDataPoint); FoobotData_allpollu[K] := double(MyDataPoint);
SetHigh(J, FoobotData_allpollu[K], FoobotData_time[K]); SetHigh(J, FoobotData_allpollu[K], FoobotData_time[K]);
SetLow(J, FoobotData_allpollu[K], FoobotData_time[K]); SetLow(J, FoobotData_allpollu[K], FoobotData_time[K]);
end; end;
else raise Exception.Create('Error in FoobotDataObjectToArrays Case');
end; // of Case end; // of Case
end; end;
end; end;
SaveHighLows;
end; end;
function SetHighTrigger(const aSensor: TSensorType; const aValue: variant): boolean;
begin
Result := False;
if UseTriggers = False then
Exit;
if aValue <> FooBotTriggerArray[1, Ord(aSensor)] then
begin
FooBotTriggerArray[1, Ord(aSensor)] := aValue;
Result := True;
end;
end;
function SetLowTrigger(const aSensor: TSensorType; const aValue: variant): boolean;
begin
Result := False;
if UseTriggers = False then
Exit;
if aValue <> FooBotTriggerArray[0, Ord(aSensor)] then
begin
FooBotTriggerArray[0, Ord(aSensor)] := aValue;
Result := True;
end;
end;
// Data cleaning functions
function ResetHighLows: boolean; function ResetHighLows: boolean;
var var
iCount: integer; iCount: integer;
@ -341,6 +443,7 @@ begin
end; end;
end; end;
// Authentication functions
function EncodeStringBase64(const s: string): string; function EncodeStringBase64(const s: string): string;
var var
@ -395,10 +498,12 @@ begin
Result := True; Result := True;
end; end;
finally finally
// Empty
end; end;
end; end;
// This function must succeed before calling FetchFoobotData
function FetchFoobotIdentity(aUsername, aSecretKey: string): boolean; function FetchFoobotIdentity(aUsername, aSecretKey: string): boolean;
var var
sUserNameURL: string; sUserNameURL: string;
@ -448,6 +553,7 @@ begin
end; end;
end; end;
// Function FetchFoobotIdentity must be called before this one
function FetchFoobotData(DataFetchType: TDataFetchType; function FetchFoobotData(DataFetchType: TDataFetchType;
iCurrentFoobot, iLastIntervalSeconds, iLastAverageBySeconds: integer; iCurrentFoobot, iLastIntervalSeconds, iLastAverageBySeconds: integer;
iStartTimeSeconds, iEndTimeSeconds: int64; aSecretKey: string): boolean; iStartTimeSeconds, iEndTimeSeconds: int64; aSecretKey: string): boolean;
@ -532,8 +638,17 @@ initialization
HttpClient := TFPHTTPClient.Create(nil); HttpClient := TFPHTTPClient.Create(nil);
FoobotIdentityObject := TFoobotIdentityObject.Create; FoobotIdentityObject := TFoobotIdentityObject.Create;
FoobotDataObject := TFoobotDataObject.Create; FoobotDataObject := TFoobotDataObject.Create;
SaveLoadHighLows := True;
TheCurrentFoobot := 0; TheCurrentFoobot := 0;
SetLength(FooBotTriggerArray, 2, Succ(C_ALLPOLLU));
SaveLoadHighLows := True; // Default
UseTriggers := False; // Defaul
for giCount := C_PM to C_ALLPOLLU do
begin
AlertRec[giCount].AlertTriggered := False;
AlertRec[giCount].AlertTime := Now;
AlertRec[giCount].AlertType := at_low;
AlertRec[giCount].AlertValue := 0;
end;
end; end;
finalization finalization
@ -550,6 +665,7 @@ finalization
SetLength(FoobotData_co2, 0); SetLength(FoobotData_co2, 0);
SetLength(FoobotData_voc, 0); SetLength(FoobotData_voc, 0);
SetLength(FoobotData_allpollu, 0); SetLength(FoobotData_allpollu, 0);
SetLength(FooBotTriggerArray, 0, 0);
end; end;
end. end.

View File

@ -1,5 +1,5 @@
unit foobot_objects; unit foobot_objects;
{ Objects for Foobot Interrogator { Objects for Foobot Lazarus
Copyright (C)2016 Gordon Bamber minsadorada@charcodelvalle.com Copyright (C)2016 Gordon Bamber minsadorada@charcodelvalle.com

View File

@ -23,6 +23,7 @@
<VersionInfo> <VersionInfo>
<UseVersionInfo Value="True"/> <UseVersionInfo Value="True"/>
<MinorVersionNr Value="2"/> <MinorVersionNr Value="2"/>
<RevisionNr Value="1"/>
<StringTable Comments="Uses Foobot public API to query Foobot #1" FileDescription="Monitor for Foobot" InternalName="foobotmonitor" LegalCopyright="(c)2016 minesadorada@charcodelvalle.com" LegalTrademarks="Foobot" ProductName="Foobot" ProductVersion="0.0.0.0"/> <StringTable Comments="Uses Foobot public API to query Foobot #1" FileDescription="Monitor for Foobot" InternalName="foobotmonitor" LegalCopyright="(c)2016 minesadorada@charcodelvalle.com" LegalTrademarks="Foobot" ProductName="Foobot" ProductVersion="0.0.0.0"/>
</VersionInfo> </VersionInfo>
<BuildModes Count="6"> <BuildModes Count="6">
@ -236,7 +237,7 @@
<PackageName Value="LCL"/> <PackageName Value="LCL"/>
</Item4> </Item4>
</RequiredPackages> </RequiredPackages>
<Units Count="9"> <Units Count="10">
<Unit0> <Unit0>
<Filename Value="foobotmonitor.lpr"/> <Filename Value="foobotmonitor.lpr"/>
<IsPartOfProject Value="True"/> <IsPartOfProject Value="True"/>
@ -282,6 +283,13 @@
<HasResources Value="True"/> <HasResources Value="True"/>
<ResourceBaseClass Value="Form"/> <ResourceBaseClass Value="Form"/>
</Unit8> </Unit8>
<Unit9>
<Filename Value="utriggersform.pas"/>
<IsPartOfProject Value="True"/>
<ComponentName Value="triggersform"/>
<HasResources Value="True"/>
<ResourceBaseClass Value="Form"/>
</Unit9>
</Units> </Units>
</ProjectOptions> </ProjectOptions>
<CompilerOptions> <CompilerOptions>
@ -322,9 +330,6 @@
<Other> <Other>
<CustomOptions Value="-FcUTF8 <CustomOptions Value="-FcUTF8
-dDEBUGMODE"/> -dDEBUGMODE"/>
<OtherDefines Count="1">
<Define0 Value="DEBUGMODE"/>
</OtherDefines>
</Other> </Other>
</CompilerOptions> </CompilerOptions>
<Debugging> <Debugging>

View File

@ -15,7 +15,8 @@ uses
cthreads, cthreads,
{$ENDIF}{$ENDIF} {$ENDIF}{$ENDIF}
Interfaces, // this includes the LCL widgetset Interfaces, // this includes the LCL widgetset
Forms, usplash, tachartlazaruspkg, umainform, uconfigform, foobot_sensors Forms, usplash, tachartlazaruspkg, umainform, uconfigform, foobot_sensors,
utriggersform
{ you can add units after this }; { you can add units after this };
{$R *.res} {$R *.res}
@ -29,6 +30,7 @@ begin
Application.ProcessMessages; // process splash paint message Application.ProcessMessages; // process splash paint message
Application.CreateForm(Tmainform, mainform); Application.CreateForm(Tmainform, mainform);
Application.CreateForm(Tconfigform, configform); Application.CreateForm(Tconfigform, configform);
Application.CreateForm(Ttriggersform, triggersform);
Application.Run; Application.Run;
end. end.

View File

@ -3,14 +3,14 @@
<ProjectSession> <ProjectSession>
<PathDelim Value="\"/> <PathDelim Value="\"/>
<Version Value="10"/> <Version Value="10"/>
<BuildModes Active="win32GTK2"/> <BuildModes Active="Debug"/>
<Units Count="32"> <Units Count="33">
<Unit0> <Unit0>
<Filename Value="foobotmonitor.lpr"/> <Filename Value="foobotmonitor.lpr"/>
<IsPartOfProject Value="True"/> <IsPartOfProject Value="True"/>
<EditorIndex Value="13"/> <EditorIndex Value="14"/>
<CursorPos X="55" Y="27"/> <CursorPos Y="35"/>
<UsageCount Value="95"/> <UsageCount Value="102"/>
<Loaded Value="True"/> <Loaded Value="True"/>
</Unit0> </Unit0>
<Unit1> <Unit1>
@ -19,10 +19,9 @@
<ComponentName Value="mainform"/> <ComponentName Value="mainform"/>
<HasResources Value="True"/> <HasResources Value="True"/>
<ResourceBaseClass Value="Form"/> <ResourceBaseClass Value="Form"/>
<IsVisibleTab Value="True"/> <TopLine Value="808"/>
<TopLine Value="774"/> <CursorPos X="54" Y="821"/>
<CursorPos X="42" Y="828"/> <UsageCount Value="102"/>
<UsageCount Value="95"/>
<Loaded Value="True"/> <Loaded Value="True"/>
<LoadedDesigner Value="True"/> <LoadedDesigner Value="True"/>
</Unit1> </Unit1>
@ -32,10 +31,10 @@
<ComponentName Value="configform"/> <ComponentName Value="configform"/>
<HasResources Value="True"/> <HasResources Value="True"/>
<ResourceBaseClass Value="Form"/> <ResourceBaseClass Value="Form"/>
<EditorIndex Value="8"/> <EditorIndex Value="9"/>
<TopLine Value="33"/> <TopLine Value="33"/>
<CursorPos X="41" Y="45"/> <CursorPos X="41" Y="45"/>
<UsageCount Value="85"/> <UsageCount Value="92"/>
<Loaded Value="True"/> <Loaded Value="True"/>
<LoadedDesigner Value="True"/> <LoadedDesigner Value="True"/>
</Unit2> </Unit2>
@ -45,7 +44,7 @@
<EditorIndex Value="-1"/> <EditorIndex Value="-1"/>
<TopLine Value="380"/> <TopLine Value="380"/>
<CursorPos X="35" Y="387"/> <CursorPos X="35" Y="387"/>
<UsageCount Value="77"/> <UsageCount Value="84"/>
</Unit3> </Unit3>
<Unit4> <Unit4>
<Filename Value="..\foobot_objects.pas"/> <Filename Value="..\foobot_objects.pas"/>
@ -54,15 +53,16 @@
<WindowIndex Value="-1"/> <WindowIndex Value="-1"/>
<TopLine Value="-1"/> <TopLine Value="-1"/>
<CursorPos X="-1" Y="-1"/> <CursorPos X="-1" Y="-1"/>
<UsageCount Value="77"/> <UsageCount Value="84"/>
</Unit4> </Unit4>
<Unit5> <Unit5>
<Filename Value="..\foobot_utility.pas"/> <Filename Value="..\foobot_utility.pas"/>
<IsPartOfProject Value="True"/> <IsPartOfProject Value="True"/>
<EditorIndex Value="10"/> <IsVisibleTab Value="True"/>
<TopLine Value="141"/> <EditorIndex Value="11"/>
<CursorPos X="16" Y="190"/> <TopLine Value="337"/>
<UsageCount Value="95"/> <CursorPos X="13" Y="364"/>
<UsageCount Value="102"/>
<Loaded Value="True"/> <Loaded Value="True"/>
</Unit5> </Unit5>
<Unit6> <Unit6>
@ -72,15 +72,15 @@
<WindowIndex Value="-1"/> <WindowIndex Value="-1"/>
<TopLine Value="-1"/> <TopLine Value="-1"/>
<CursorPos X="-1" Y="-1"/> <CursorPos X="-1" Y="-1"/>
<UsageCount Value="77"/> <UsageCount Value="84"/>
</Unit6> </Unit6>
<Unit7> <Unit7>
<Filename Value="foobot_sensors.pas"/> <Filename Value="foobot_sensors.pas"/>
<IsPartOfProject Value="True"/> <IsPartOfProject Value="True"/>
<EditorIndex Value="5"/> <EditorIndex Value="6"/>
<TopLine Value="299"/> <TopLine Value="299"/>
<CursorPos X="14" Y="321"/> <CursorPos X="14" Y="321"/>
<UsageCount Value="29"/> <UsageCount Value="36"/>
<Loaded Value="True"/> <Loaded Value="True"/>
</Unit7> </Unit7>
<Unit8> <Unit8>
@ -89,297 +89,314 @@
<ComponentName Value="splashform"/> <ComponentName Value="splashform"/>
<HasResources Value="True"/> <HasResources Value="True"/>
<ResourceBaseClass Value="Form"/> <ResourceBaseClass Value="Form"/>
<EditorIndex Value="1"/> <EditorIndex Value="2"/>
<CursorPos X="21" Y="35"/> <CursorPos X="42" Y="25"/>
<UsageCount Value="24"/> <UsageCount Value="31"/>
<Loaded Value="True"/> <Loaded Value="True"/>
<LoadedDesigner Value="True"/>
</Unit8> </Unit8>
<Unit9> <Unit9>
<Filename Value="..\latest_stable\foobot_httpclient.pas"/> <Filename Value="utriggersform.pas"/>
<EditorIndex Value="9"/> <IsPartOfProject Value="True"/>
<TopLine Value="43"/> <ComponentName Value="triggersform"/>
<CursorPos X="47" Y="13"/> <HasResources Value="True"/>
<UsageCount Value="64"/> <ResourceBaseClass Value="Form"/>
<EditorIndex Value="1"/>
<CursorPos X="22" Y="7"/>
<UsageCount Value="22"/>
<Loaded Value="True"/> <Loaded Value="True"/>
<LoadedDesigner Value="True"/>
</Unit9> </Unit9>
<Unit10> <Unit10>
<Filename Value="..\latest_stable\foobot_objects.pas"/> <Filename Value="..\latest_stable\foobot_httpclient.pas"/>
<EditorIndex Value="12"/> <EditorIndex Value="10"/>
<CursorPos X="32" Y="61"/> <TopLine Value="43"/>
<UsageCount Value="64"/> <CursorPos X="47" Y="13"/>
<UsageCount Value="68"/>
<Loaded Value="True"/> <Loaded Value="True"/>
</Unit10> </Unit10>
<Unit11> <Unit11>
<Filename Value="..\latest_stable\foobot_objects.pas"/>
<EditorIndex Value="13"/>
<TopLine Value="52"/>
<CursorPos Y="90"/>
<UsageCount Value="68"/>
<Loaded Value="True"/>
</Unit11>
<Unit12>
<Filename Value="..\latest_stable\ugenericcollection.pas"/> <Filename Value="..\latest_stable\ugenericcollection.pas"/>
<EditorIndex Value="-1"/> <EditorIndex Value="-1"/>
<WindowIndex Value="-1"/> <WindowIndex Value="-1"/>
<TopLine Value="-1"/> <TopLine Value="-1"/>
<CursorPos X="-1" Y="-1"/> <CursorPos X="-1" Y="-1"/>
<UsageCount Value="36"/> <UsageCount Value="35"/>
</Unit11>
<Unit12>
<Filename Value="..\latest_stable\umainform.lfm"/>
<EditorIndex Value="-1"/>
<UsageCount Value="8"/>
<DefaultSyntaxHighlighter Value="LFM"/>
</Unit12> </Unit12>
<Unit13> <Unit13>
<Filename Value="..\latest_stable\umainform.lfm"/>
<EditorIndex Value="-1"/>
<UsageCount Value="7"/>
<DefaultSyntaxHighlighter Value="LFM"/>
</Unit13>
<Unit14>
<Filename Value="..\latest_stable\umainform.pas"/> <Filename Value="..\latest_stable\umainform.pas"/>
<EditorIndex Value="-1"/> <EditorIndex Value="-1"/>
<TopLine Value="10"/> <TopLine Value="10"/>
<CursorPos X="57" Y="36"/> <CursorPos X="57" Y="36"/>
<UsageCount Value="8"/> <UsageCount Value="7"/>
</Unit13> </Unit14>
<Unit14> <Unit15>
<Filename Value="..\udataform.pas"/> <Filename Value="..\udataform.pas"/>
<EditorIndex Value="-1"/> <EditorIndex Value="-1"/>
<TopLine Value="74"/> <TopLine Value="74"/>
<CursorPos Y="96"/> <CursorPos Y="96"/>
<UsageCount Value="16"/> <UsageCount Value="15"/>
</Unit14> </Unit15>
<Unit15> <Unit16>
<Filename Value="..\umainform.pas"/> <Filename Value="..\umainform.pas"/>
<EditorIndex Value="-1"/> <EditorIndex Value="-1"/>
<TopLine Value="145"/> <TopLine Value="145"/>
<CursorPos X="81" Y="158"/> <CursorPos X="81" Y="158"/>
<UsageCount Value="44"/> <UsageCount Value="43"/>
</Unit15> </Unit16>
<Unit16> <Unit17>
<Filename Value="C:\trunklatest\lazarus\lcl\lclmessageglue.pas"/> <Filename Value="C:\trunklatest\lazarus\lcl\lclmessageglue.pas"/>
<UnitName Value="LCLMessageGlue"/> <UnitName Value="LCLMessageGlue"/>
<EditorIndex Value="-1"/> <EditorIndex Value="-1"/>
<TopLine Value="93"/> <TopLine Value="93"/>
<CursorPos Y="114"/> <CursorPos Y="114"/>
<UsageCount Value="8"/> <UsageCount Value="7"/>
</Unit16> </Unit17>
<Unit17> <Unit18>
<Filename Value="..\ulogin.pas"/> <Filename Value="..\ulogin.pas"/>
<EditorIndex Value="-1"/> <EditorIndex Value="-1"/>
<CursorPos Y="108"/> <CursorPos Y="108"/>
<UsageCount Value="11"/> <UsageCount Value="10"/>
</Unit17> </Unit18>
<Unit18> <Unit19>
<Filename Value="..\..\..\components\cryptini\latest_stable\ucryptini.pas"/> <Filename Value="..\..\..\components\cryptini\latest_stable\ucryptini.pas"/>
<EditorIndex Value="-1"/> <EditorIndex Value="-1"/>
<TopLine Value="906"/> <TopLine Value="906"/>
<CursorPos X="8" Y="939"/> <CursorPos X="8" Y="939"/>
<UsageCount Value="9"/>
</Unit18>
<Unit19>
<Filename Value="..\backup\foobot_utility.pas"/>
<EditorIndex Value="-1"/>
<TopLine Value="7"/>
<UsageCount Value="8"/> <UsageCount Value="8"/>
</Unit19> </Unit19>
<Unit20> <Unit20>
<Filename Value="C:\trunklatest\lazarus\ide\lazarus.pp"/> <Filename Value="..\backup\foobot_utility.pas"/>
<UnitName Value="Lazarus"/> <EditorIndex Value="-1"/>
<EditorIndex Value="6"/> <TopLine Value="7"/>
<TopLine Value="101"/> <UsageCount Value="7"/>
<CursorPos Y="154"/>
<UsageCount Value="15"/>
<Loaded Value="True"/>
</Unit20> </Unit20>
<Unit21> <Unit21>
<Filename Value="C:\trunklatest\lazarus\ide\lazarus.pp"/>
<UnitName Value="Lazarus"/>
<EditorIndex Value="7"/>
<TopLine Value="101"/>
<CursorPos Y="154"/>
<UsageCount Value="19"/>
<Loaded Value="True"/>
</Unit21>
<Unit22>
<Filename Value="C:\trunklatest\fpc\rtl\objpas\objpas.pp"/> <Filename Value="C:\trunklatest\fpc\rtl\objpas\objpas.pp"/>
<EditorIndex Value="-1"/> <EditorIndex Value="-1"/>
<TopLine Value="11"/> <TopLine Value="11"/>
<CursorPos X="8" Y="33"/> <CursorPos X="8" Y="33"/>
<UsageCount Value="9"/> <UsageCount Value="8"/>
</Unit21> </Unit22>
<Unit22> <Unit23>
<Filename Value="D:\Lazarusprojects\healthmonitor\svn\healthanalysis\healthanalysis\umainform.pas"/> <Filename Value="D:\Lazarusprojects\healthmonitor\svn\healthanalysis\healthanalysis\umainform.pas"/>
<EditorIndex Value="-1"/> <EditorIndex Value="-1"/>
<TopLine Value="540"/> <TopLine Value="540"/>
<CursorPos X="55" Y="593"/> <CursorPos X="55" Y="593"/>
<UsageCount Value="9"/> <UsageCount Value="8"/>
</Unit22> </Unit23>
<Unit23> <Unit24>
<Filename Value="C:\trunklatest\fpc\rtl\objpas\sysutils\datih.inc"/> <Filename Value="C:\trunklatest\fpc\rtl\objpas\sysutils\datih.inc"/>
<EditorIndex Value="-1"/> <EditorIndex Value="-1"/>
<TopLine Value="109"/> <TopLine Value="109"/>
<CursorPos X="10" Y="128"/> <CursorPos X="10" Y="128"/>
<UsageCount Value="8"/> <UsageCount Value="7"/>
</Unit23>
<Unit24>
<Filename Value="C:\trunklatest\fpc\packages\rtl-objpas\src\inc\dateutil.inc"/>
<EditorIndex Value="11"/>
<TopLine Value="381"/>
<CursorPos X="13" Y="384"/>
<UsageCount Value="33"/>
<Loaded Value="True"/>
</Unit24> </Unit24>
<Unit25> <Unit25>
<Filename Value="..\latest_stable\udataform.pas"/> <Filename Value="C:\trunklatest\fpc\packages\rtl-objpas\src\inc\dateutil.inc"/>
<EditorIndex Value="7"/> <EditorIndex Value="12"/>
<TopLine Value="70"/> <TopLine Value="381"/>
<UsageCount Value="33"/> <CursorPos X="13" Y="384"/>
<UsageCount Value="37"/>
<Loaded Value="True"/> <Loaded Value="True"/>
</Unit25> </Unit25>
<Unit26> <Unit26>
<Filename Value="D:\lazarustrunk\common_components\cryptini\ucryptini.pas"/> <Filename Value="..\latest_stable\udataform.pas"/>
<EditorIndex Value="4"/> <EditorIndex Value="8"/>
<TopLine Value="781"/> <TopLine Value="70"/>
<CursorPos X="28" Y="795"/> <UsageCount Value="37"/>
<UsageCount Value="18"/>
<Loaded Value="True"/> <Loaded Value="True"/>
</Unit26> </Unit26>
<Unit27> <Unit27>
<Filename Value="D:\lazarustrunk\common_components\cryptini\ucryptini.pas"/>
<EditorIndex Value="5"/>
<TopLine Value="781"/>
<CursorPos X="28" Y="795"/>
<UsageCount Value="22"/>
<Loaded Value="True"/>
</Unit27>
<Unit28>
<Filename Value="C:\trunklatest\fpc\packages\fcl-base\src\fileinfo.pp"/> <Filename Value="C:\trunklatest\fpc\packages\fcl-base\src\fileinfo.pp"/>
<EditorIndex Value="-1"/> <EditorIndex Value="-1"/>
<TopLine Value="43"/> <TopLine Value="43"/>
<CursorPos X="19" Y="51"/> <CursorPos X="19" Y="51"/>
<UsageCount Value="12"/> <UsageCount Value="11"/>
</Unit27> </Unit28>
<Unit28> <Unit29>
<Filename Value="C:\trunklatest\lazarus\components\IndustrialStuff\industrial.pas"/> <Filename Value="C:\trunklatest\lazarus\components\IndustrialStuff\industrial.pas"/>
<EditorIndex Value="-1"/> <EditorIndex Value="-1"/>
<CursorPos X="18" Y="11"/> <CursorPos X="18" Y="11"/>
<UsageCount Value="10"/> <UsageCount Value="9"/>
</Unit28>
<Unit29>
<Filename Value="..\..\..\components\poweredby\latest_stable\upoweredby.pas"/>
<UnitName Value="uPoweredby"/>
<EditorIndex Value="3"/>
<TopLine Value="190"/>
<CursorPos X="33" Y="205"/>
<UsageCount Value="15"/>
<Loaded Value="True"/>
</Unit29> </Unit29>
<Unit30> <Unit30>
<Filename Value="..\..\..\components\poweredby\latest_stable\upoweredby.pas"/>
<UnitName Value="uPoweredby"/>
<EditorIndex Value="4"/>
<TopLine Value="190"/>
<CursorPos X="33" Y="205"/>
<UsageCount Value="19"/>
<Loaded Value="True"/>
</Unit30>
<Unit31>
<Filename Value="C:\trunklatest\lazarus\lcl\include\customform.inc"/> <Filename Value="C:\trunklatest\lazarus\lcl\include\customform.inc"/>
<EditorIndex Value="-1"/> <EditorIndex Value="-1"/>
<TopLine Value="2228"/> <TopLine Value="2228"/>
<CursorPos X="14" Y="2239"/> <CursorPos X="14" Y="2239"/>
<UsageCount Value="10"/> <UsageCount Value="9"/>
</Unit30> </Unit31>
<Unit31> <Unit32>
<Filename Value="C:\trunklatest\lazarus\lcl\graphics.pp"/> <Filename Value="C:\trunklatest\lazarus\lcl\graphics.pp"/>
<UnitName Value="Graphics"/> <UnitName Value="Graphics"/>
<EditorIndex Value="2"/> <EditorIndex Value="3"/>
<TopLine Value="1811"/> <TopLine Value="1811"/>
<CursorPos X="13" Y="1834"/> <CursorPos X="13" Y="1834"/>
<UsageCount Value="11"/> <UsageCount Value="15"/>
<Loaded Value="True"/> <Loaded Value="True"/>
</Unit31> </Unit32>
</Units> </Units>
<JumpHistory Count="29" HistoryIndex="28"> <JumpHistory Count="30" HistoryIndex="29">
<Position1> <Position1>
<Filename Value="foobotmonitor.lpr"/> <Filename Value="..\foobot_utility.pas"/>
<Caret Line="29"/> <Caret Line="72" Column="34" TopLine="44"/>
</Position1> </Position1>
<Position2> <Position2>
<Filename Value="foobotmonitor.lpr"/> <Filename Value="..\foobot_utility.pas"/>
<Caret Line="30" Column="17"/> <Caret Line="339" Column="25" TopLine="289"/>
</Position2> </Position2>
<Position3> <Position3>
<Filename Value="foobotmonitor.lpr"/> <Filename Value="..\foobot_utility.pas"/>
<Caret Line="28" Column="35"/> <Caret Line="330" Column="40" TopLine="301"/>
</Position3> </Position3>
<Position4> <Position4>
<Filename Value="usplash.pas"/> <Filename Value="..\foobot_utility.pas"/>
<Caret Line="47" Column="84" TopLine="27"/>
</Position4> </Position4>
<Position5> <Position5>
<Filename Value="umainform.pas"/> <Filename Value="..\foobot_utility.pas"/>
<Caret Line="281" Column="26" TopLine="245"/> <Caret Line="233" Column="46" TopLine="213"/>
</Position5> </Position5>
<Position6> <Position6>
<Filename Value="usplash.pas"/> <Filename Value="..\foobot_utility.pas"/>
<Caret Line="33" Column="3"/> <Caret Line="343" TopLine="303"/>
</Position6> </Position6>
<Position7> <Position7>
<Filename Value="usplash.pas"/> <Filename Value="umainform.pas"/>
<Caret Line="16" Column="33"/> <Caret Line="795" Column="55" TopLine="748"/>
</Position7> </Position7>
<Position8> <Position8>
<Filename Value="usplash.pas"/> <Filename Value="..\foobot_utility.pas"/>
<Caret Line="35" Column="49"/> <Caret Line="80" Column="9" TopLine="68"/>
</Position8> </Position8>
<Position9> <Position9>
<Filename Value="usplash.pas"/> <Filename Value="umainform.pas"/>
<Caret Line="34" Column="49"/> <Caret Line="43" Column="66" TopLine="23"/>
</Position9> </Position9>
<Position10> <Position10>
<Filename Value="usplash.pas"/> <Filename Value="usplash.pas"/>
<Caret Line="37" Column="37"/> <Caret Line="38" Column="19"/>
</Position10> </Position10>
<Position11> <Position11>
<Filename Value="usplash.pas"/> <Filename Value="utriggersform.pas"/>
<Caret Line="38" Column="12"/> <Caret Line="26" Column="7"/>
</Position11> </Position11>
<Position12> <Position12>
<Filename Value="usplash.pas"/> <Filename Value="utriggersform.pas"/>
<Caret Line="33" Column="32"/> <Caret Line="34" Column="50"/>
</Position12> </Position12>
<Position13> <Position13>
<Filename Value="usplash.pas"/> <Filename Value="utriggersform.pas"/>
<Caret Line="24" Column="41"/> <Caret Line="35" Column="50"/>
</Position13> </Position13>
<Position14> <Position14>
<Filename Value="usplash.pas"/> <Filename Value="utriggersform.pas"/>
<Caret Line="34" Column="30"/> <Caret Line="37" Column="50"/>
</Position14> </Position14>
<Position15> <Position15>
<Filename Value="umainform.pas"/> <Filename Value="umainform.pas"/>
<Caret Line="229" Column="61" TopLine="209"/> <Caret Line="30" Column="19" TopLine="23"/>
</Position15> </Position15>
<Position16> <Position16>
<Filename Value="umainform.pas"/> <Filename Value="umainform.pas"/>
<Caret Line="352" Column="13" TopLine="308"/> <Caret Line="537" Column="25" TopLine="533"/>
</Position16> </Position16>
<Position17> <Position17>
<Filename Value="umainform.pas"/> <Filename Value="umainform.pas"/>
<Caret Line="333" Column="28" TopLine="306"/> <Caret Line="41" Column="58" TopLine="31"/>
</Position17> </Position17>
<Position18> <Position18>
<Filename Value="umainform.pas"/> <Filename Value="umainform.pas"/>
<Caret Line="348" Column="43" TopLine="306"/> <Caret Line="538" TopLine="536"/>
</Position18> </Position18>
<Position19> <Position19>
<Filename Value="umainform.pas"/> <Filename Value="umainform.pas"/>
<Caret Line="333" Column="20" TopLine="306"/> <Caret Line="556" Column="54" TopLine="550"/>
</Position19> </Position19>
<Position20> <Position20>
<Filename Value="umainform.pas"/> <Filename Value="umainform.pas"/>
<Caret Line="345" Column="33" TopLine="317"/> <Caret Line="10" Column="25"/>
</Position20> </Position20>
<Position21> <Position21>
<Filename Value="umainform.pas"/> <Filename Value="umainform.pas"/>
<Caret Line="348" Column="37" TopLine="320"/> <Caret Line="831" Column="18" TopLine="793"/>
</Position21> </Position21>
<Position22> <Position22>
<Filename Value="umainform.pas"/> <Filename Value="..\foobot_utility.pas"/>
<Caret Line="352" Column="13" TopLine="325"/> <Caret Line="637" Column="41" TopLine="604"/>
</Position22> </Position22>
<Position23> <Position23>
<Filename Value="umainform.pas"/> <Filename Value="..\foobot_utility.pas"/>
<Caret Line="2" Column="21"/> <Caret Line="127" Column="45" TopLine="88"/>
</Position23> </Position23>
<Position24> <Position24>
<Filename Value="umainform.pas"/> <Filename Value="..\foobot_utility.pas"/>
<Caret Line="544" Column="44" TopLine="497"/> <Caret Line="639" Column="30" TopLine="606"/>
</Position24> </Position24>
<Position25> <Position25>
<Filename Value="umainform.pas"/> <Filename Value="..\foobot_utility.pas"/>
<Caret Line="596" Column="44" TopLine="549"/> <Caret Line="640" Column="9" TopLine="606"/>
</Position25> </Position25>
<Position26> <Position26>
<Filename Value="umainform.pas"/> <Filename Value="..\foobot_utility.pas"/>
<Caret Line="838" Column="48" TopLine="791"/> <Caret Line="86" TopLine="59"/>
</Position26> </Position26>
<Position27> <Position27>
<Filename Value="umainform.pas"/> <Filename Value="umainform.pas"/>
<Caret Line="828" Column="42" TopLine="774"/> <Caret Line="831" Column="40" TopLine="800"/>
</Position27> </Position27>
<Position28> <Position28>
<Filename Value="..\foobot_utility.pas"/> <Filename Value="..\foobot_utility.pas"/>
<Caret Line="141" Column="16" TopLine="89"/> <Caret Line="666" Column="41" TopLine="612"/>
</Position28> </Position28>
<Position29> <Position29>
<Filename Value="..\foobot_utility.pas"/> <Filename Value="..\foobot_utility.pas"/>
<Caret Line="190" Column="16" TopLine="141"/> <Caret Line="500" Column="13" TopLine="461"/>
</Position29> </Position29>
<Position30>
<Filename Value="..\foobot_utility.pas"/>
<Caret Line="364" Column="14" TopLine="337"/>
</Position30>
</JumpHistory> </JumpHistory>
</ProjectSession> </ProjectSession>
</CONFIG> </CONFIG>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 58 KiB

After

Width:  |  Height:  |  Size: 64 KiB

View File

@ -492,6 +492,20 @@ object mainform: Tmainform
Caption = 'Reset All-time Highs/Lows' Caption = 'Reset All-time Highs/Lows'
OnClick = mnu_optionsResetHighsLowsClick OnClick = mnu_optionsResetHighsLowsClick
end end
object mnu_optionsFoobotTriggers: TMenuItem
Caption = 'Foobot Triggers...'
OnClick = mnu_optionsFoobotTriggersClick
object mnu_options_triggersSetTriggers: TMenuItem
Caption = 'Set Trigger Values...'
OnClick = mnu_options_triggersSetTriggersClick
end
object mnu_options_triggersActivateTriggers: TMenuItem
Caption = 'Set Triggers On'
Enabled = False
RadioItem = True
OnClick = mnu_options_triggersActivateTriggersClick
end
end
end end
object mnu_foobot: TMenuItem object mnu_foobot: TMenuItem
Caption = '&Foobot' Caption = '&Foobot'

View File

@ -40,7 +40,7 @@ interface
uses uses
SysUtils, TAGraph, TAIntervalSources, TASeries, foobot_sensors, SysUtils, TAGraph, TAIntervalSources, TASeries, foobot_sensors,
Forms, Controls, Graphics, Dialogs, ExtCtrls, StdCtrls, Menus, lclIntf, Forms, Controls, Graphics, Dialogs, ExtCtrls, StdCtrls, Menus, lclIntf,
foobot_utility, uCryptIni, dateutils, uconfigform; foobot_utility, uCryptIni, dateutils, uconfigform,utriggersform, Classes;
const const
// Timer milliseconds // Timer milliseconds
@ -123,6 +123,9 @@ type
lbl_voclow: TLabel; lbl_voclow: TLabel;
lbl_allpollulow: TLabel; lbl_allpollulow: TLabel;
MainMenu1: TMainMenu; MainMenu1: TMainMenu;
mnu_options_triggersActivateTriggers: TMenuItem;
mnu_options_triggersSetTriggers: TMenuItem;
mnu_optionsFoobotTriggers: TMenuItem;
mnu_foobot: TMenuItem; mnu_foobot: TMenuItem;
mnu_optionsDisplayRedLines: TMenuItem; mnu_optionsDisplayRedLines: TMenuItem;
mnu_optionsDisplayYellowLines: TMenuItem; mnu_optionsDisplayYellowLines: TMenuItem;
@ -166,7 +169,10 @@ type
procedure mnu_optionsOnlineHelpClick(Sender: TObject); procedure mnu_optionsOnlineHelpClick(Sender: TObject);
procedure mnu_optionsResetHighsLowsClick(Sender: TObject); procedure mnu_optionsResetHighsLowsClick(Sender: TObject);
procedure mnu_optionsSaveHighLowsClick(Sender: TObject); procedure mnu_optionsSaveHighLowsClick(Sender: TObject);
procedure mnu_optionsFoobotTriggersClick(Sender: TObject);
procedure mnu_optionsTakeReadingNowClick(Sender: TObject); procedure mnu_optionsTakeReadingNowClick(Sender: TObject);
procedure mnu_options_triggersActivateTriggersClick(Sender: TObject);
procedure mnu_options_triggersSetTriggersClick(Sender: TObject);
procedure mnu_SampleEvery1HourClick(Sender: TObject); procedure mnu_SampleEvery1HourClick(Sender: TObject);
procedure mnu_SampleEvery24HoursClick(Sender: TObject); procedure mnu_SampleEvery24HoursClick(Sender: TObject);
procedure mnu_SampleEvery2HoursClick(Sender: TObject); procedure mnu_SampleEvery2HoursClick(Sender: TObject);
@ -240,6 +246,7 @@ begin
TrayIcon1.Hint := Application.Title; TrayIcon1.Hint := Application.Title;
DateTimeIntervalChartSource1.DateTimeFormat := 'hh:nn'; DateTimeIntervalChartSource1.DateTimeFormat := 'hh:nn';
LoadConfig; LoadConfig;
{$IFDEF DEBUGMODE}UseTriggers:=FALSE;{$ENDIF}
end; end;
procedure Tmainform.FormActivate(Sender: TObject); procedure Tmainform.FormActivate(Sender: TObject);
@ -517,7 +524,7 @@ begin
exit; exit;
ResetHighLows; ResetHighLows;
SaveHighLows; SaveHighLows;
for iCount := 1 to 6 do for iCount := C_PM to C_ALLPOLLU do
UpdateHighLow(iCount); UpdateHighLow(iCount);
end; end;
@ -527,6 +534,10 @@ begin
INI.WriteBool('Foobot', 'SaveLoadHighLows', SaveLoadHighLows); INI.WriteBool('Foobot', 'SaveLoadHighLows', SaveLoadHighLows);
end; end;
procedure Tmainform.mnu_optionsFoobotTriggersClick(Sender: TObject);
begin
end;
procedure Tmainform.mnu_optionsTakeReadingNowClick(Sender: TObject); procedure Tmainform.mnu_optionsTakeReadingNowClick(Sender: TObject);
begin begin
mainform.Cursor := crHourGlass; mainform.Cursor := crHourGlass;
@ -537,6 +548,25 @@ begin
mainform.Cursor := crDefault; mainform.Cursor := crDefault;
end; end;
procedure Tmainform.mnu_options_triggersActivateTriggersClick(Sender: TObject);
begin
mnu_options_triggersActivateTriggers.Checked:= NOT mnu_options_triggersActivateTriggers.Checked;
UseTriggers:=mnu_options_triggersActivateTriggers.Checked;
If UseTriggers then
mnu_options_triggersActivateTriggers.Caption:='Set Triggers Off'
else
mnu_options_triggersActivateTriggers.Caption:='Set Triggers On';
end;
procedure Tmainform.mnu_options_triggersSetTriggersClick(Sender: TObject);
begin
triggersform.ShowModal;
If triggersform.ModalResult = mrCancel then
ShowMessage('Cancel')
else
mnu_options_triggersActivateTriggers.Enabled:=TRUE;
end;
procedure Tmainform.mnu_SampleEveryHalfHourClick(Sender: TObject); procedure Tmainform.mnu_SampleEveryHalfHourClick(Sender: TObject);
begin begin
tmr_foobot.Enabled := False; tmr_foobot.Enabled := False;
@ -650,7 +680,7 @@ end;
procedure Tmainform.UpdateHighLow(SensorNumber: integer); procedure Tmainform.UpdateHighLow(SensorNumber: integer);
begin begin
case SensorNumber of case SensorNumber of
1: C_PM:
begin begin
lbl_pmhigh.Caption := Format('High: %f %s', lbl_pmhigh.Caption := Format('High: %f %s',
[double(FoobotDataHighs[SensorNumber]), FoobotDataObject.Units[SensorNumber]]) + [double(FoobotDataHighs[SensorNumber]), FoobotDataObject.Units[SensorNumber]]) +
@ -661,7 +691,7 @@ begin
LineEnding + 'on ' + FormatDateTime('dd/mm tt', TDateTime( LineEnding + 'on ' + FormatDateTime('dd/mm tt', TDateTime(
FoobotDataLowTimes[SensorNumber])); FoobotDataLowTimes[SensorNumber]));
end; end;
2: C_TMP:
begin begin
lbl_tmphigh.Caption := Format('High: %f %s', lbl_tmphigh.Caption := Format('High: %f %s',
[double(FoobotDataHighs[SensorNumber]), FoobotDataObject.Units[SensorNumber]]) + [double(FoobotDataHighs[SensorNumber]), FoobotDataObject.Units[SensorNumber]]) +
@ -672,7 +702,7 @@ begin
LineEnding + 'on ' + FormatDateTime('dd/mm tt', TDateTime( LineEnding + 'on ' + FormatDateTime('dd/mm tt', TDateTime(
FoobotDataLowTimes[SensorNumber])); FoobotDataLowTimes[SensorNumber]));
end; end;
3: C_HUM:
begin begin
lbl_humhigh.Caption := Format('High: %f %s', lbl_humhigh.Caption := Format('High: %f %s',
[double(FoobotDataHighs[SensorNumber]), FoobotDataObject.Units[SensorNumber]]) + [double(FoobotDataHighs[SensorNumber]), FoobotDataObject.Units[SensorNumber]]) +
@ -683,7 +713,7 @@ begin
LineEnding + 'on ' + FormatDateTime('dd/mm tt', TDateTime( LineEnding + 'on ' + FormatDateTime('dd/mm tt', TDateTime(
FoobotDataLowTimes[SensorNumber])); FoobotDataLowTimes[SensorNumber]));
end; end;
4: C_CO2:
begin begin
lbl_co2high.Caption := Format('High: %f %s', lbl_co2high.Caption := Format('High: %f %s',
[double(FoobotDataHighs[SensorNumber]), FoobotDataObject.Units[SensorNumber]]) + [double(FoobotDataHighs[SensorNumber]), FoobotDataObject.Units[SensorNumber]]) +
@ -694,7 +724,7 @@ begin
LineEnding + 'on ' + FormatDateTime('dd/mm tt', TDateTime( LineEnding + 'on ' + FormatDateTime('dd/mm tt', TDateTime(
FoobotDataLowTimes[SensorNumber])); FoobotDataLowTimes[SensorNumber]));
end; end;
5: C_VOC:
begin begin
lbl_vochigh.Caption := Format('High: %f %s', lbl_vochigh.Caption := Format('High: %f %s',
[double(FoobotDataHighs[SensorNumber]), FoobotDataObject.Units[SensorNumber]]) + [double(FoobotDataHighs[SensorNumber]), FoobotDataObject.Units[SensorNumber]]) +
@ -705,7 +735,7 @@ begin
LineEnding + 'on ' + FormatDateTime('dd/mm tt', TDateTime( LineEnding + 'on ' + FormatDateTime('dd/mm tt', TDateTime(
FoobotDataLowTimes[SensorNumber])); FoobotDataLowTimes[SensorNumber]));
end; end;
6: C_ALLPOLLU:
begin begin
lbl_allpolluhigh.Caption := lbl_allpolluhigh.Caption :=
Format('High: %f %s', [double(FoobotDataHighs[SensorNumber]), Format('High: %f %s', [double(FoobotDataHighs[SensorNumber]),
@ -724,32 +754,32 @@ begin
with Sender do with Sender do
begin begin
case SensorNumber of case SensorNumber of
1: C_PM:
begin begin
Value := FoobotData_pm[0]; Value := FoobotData_pm[0];
Caption := Format('PM (%s): ', [FoobotDataObject.Units[SensorNumber]]); Caption := Format('PM (%s): ', [FoobotDataObject.Units[SensorNumber]]);
end; end;
2: C_TMP:
begin begin
Value := FoobotData_tmp[0]; Value := FoobotData_tmp[0];
Caption := Format('Temp (%s): ', [FoobotDataObject.Units[SensorNumber]]); Caption := Format('Temp (%s): ', [FoobotDataObject.Units[SensorNumber]]);
end; end;
3: C_HUM:
begin begin
Value := FoobotData_hum[0]; Value := FoobotData_hum[0];
Caption := Format('Hum. (%s): ', [FoobotDataObject.Units[SensorNumber]]); Caption := Format('Hum. (%s): ', [FoobotDataObject.Units[SensorNumber]]);
end; end;
4: C_CO2:
begin begin
Value := FoobotData_co2[0]; Value := FoobotData_co2[0];
Caption := Format('CO2 (%s): ', [FoobotDataObject.Units[SensorNumber]]); Caption := Format('CO2 (%s): ', [FoobotDataObject.Units[SensorNumber]]);
end; end;
5: C_VOC:
begin begin
Value := FoobotData_voc[0]; Value := FoobotData_voc[0];
Caption := Format('VOC (%s): ', [FoobotDataObject.Units[SensorNumber]]); Caption := Format('VOC (%s): ', [FoobotDataObject.Units[SensorNumber]]);
end; end;
6: C_ALLPOLLU:
begin begin
Value := FoobotData_allpollu[0]; Value := FoobotData_allpollu[0];
Caption := Format('All (%s): ', [FoobotDataObject.Units[SensorNumber]]); Caption := Format('All (%s): ', [FoobotDataObject.Units[SensorNumber]]);
@ -774,18 +804,33 @@ begin
mainform.Caption := Format('Foobot "%s" - Last reading: ', mainform.Caption := Format('Foobot "%s" - Last reading: ',
[FoobotIdentityObject.FoobotIdentityList[0].Name]) + [FoobotIdentityObject.FoobotIdentityList[0].Name]) +
FormatDateTime('dd/mm/yyyy - tt', FoobotData_time[0]); FormatDateTime('dd/mm/yyyy - tt', FoobotData_time[0]);
UpdateGuage(as_pm, 1); UpdateGuage(as_pm, C_PM);
UpdateGuage(as_tmp, 2); UpdateGuage(as_tmp, C_TMP);
UpdateGuage(as_hum, 3); UpdateGuage(as_hum, C_HUM);
UpdateGuage(as_co2, 4); UpdateGuage(as_co2, C_CO2);
UpdateGuage(as_voc, 5); UpdateGuage(as_voc, C_VOC);
UpdateGuage(as_allpollu, 6); UpdateGuage(as_allpollu, C_ALLPOLLU);
if not bDisplayGuagesOnly then if not bDisplayGuagesOnly then
begin begin
for iCount := 1 to 6 do for iCount := 1 to 6 do
UpdateHighLow(iCount); UpdateHighLow(iCount);
end; end;
GraphCurrentReading; GraphCurrentReading;
// Process Trigger Alerts
If UseTriggers then
For iCount:=C_PM to C_ALLPOLLU do
If AlertRec[iCount].AlertTriggered then
If AlertRec[iCount].AlertType = at_high then
begin
ShowMessageFmt('High alert member %d (value %f) exceeded',
[iCount,Double(AlertRec[iCount].AlertValue)]);
end
else
begin
ShowMessageFmt('Low alert member %d (value %f) exceeded',
[iCount,Double(AlertRec[iCount].AlertValue)]);
end;
end; end;
end; end;
@ -799,6 +844,7 @@ end;
procedure Tmainform.GraphCurrentReading; procedure Tmainform.GraphCurrentReading;
begin begin
{$IFDEF DEBUGMODE}Exit;{$ENDIF}
lineseries_pm.AddXY(FoobotData_time[0], lineseries_pm.AddXY(FoobotData_time[0],
AsPercent(FoobotData_pm[0], as_pm.ValueMin, as_pm.ValueMax)); AsPercent(FoobotData_pm[0], as_pm.ValueMin, as_pm.ValueMax));
lineseries_tmp.AddXY(FoobotData_time[0], AsPercent(FoobotData_tmp[0], lineseries_tmp.AddXY(FoobotData_time[0], AsPercent(FoobotData_tmp[0],
@ -820,6 +866,7 @@ var
iCount: integer; iCount: integer;
iStartSeconds, iEndSeconds: int64; iStartSeconds, iEndSeconds: int64;
begin begin
{$IFDEF DEBUGMODE}Exit;{$ENDIF}
iEndSeconds := DateTimeToUnix(Now) - 3600; iEndSeconds := DateTimeToUnix(Now) - 3600;
iStartSeconds := iEndSeconds - (2 * (24 * 3600)); // 49 hours before Now iStartSeconds := iEndSeconds - (2 * (24 * 3600)); // 49 hours before Now
grp_chart.Caption := Format('History from %s', grp_chart.Caption := Format('History from %s',

View File

@ -1,12 +1,12 @@
object splashform: Tsplashform object splashform: Tsplashform
Left = 596 Left = 596
Height = 480 Height = 484
Top = 136 Top = 136
Width = 790 Width = 794
BorderStyle = bsNone BorderStyle = bsNone
Caption = 'splashform' Caption = 'splashform'
ClientHeight = 480 ClientHeight = 484
ClientWidth = 790 ClientWidth = 794
DefaultMonitor = dmDesktop DefaultMonitor = dmDesktop
FormStyle = fsStayOnTop FormStyle = fsStayOnTop
OnCreate = FormCreate OnCreate = FormCreate
@ -16,9 +16,9 @@ object splashform: Tsplashform
Scaled = True Scaled = True
object img: TImage object img: TImage
Left = 0 Left = 0
Height = 480 Height = 484
Top = 0 Top = 0
Width = 790 Width = 794
Align = alClient Align = alClient
Stretch = True Stretch = True
Transparent = True Transparent = True

View File

@ -35,7 +35,7 @@ begin
jpg:=TJPEGImage.Create; jpg:=TJPEGImage.Create;
try try
jpg.LoadFromResourceName(HInstance,'SPLASHIMAGE'); jpg.LoadFromResourceName(HInstance,'SPLASHIMAGE');
Img.Canvas.Draw(0,0,jpg); img.Canvas.Draw(0,0,jpg);
finally finally
jpg.Free; jpg.Free;
end; end;

View File

@ -0,0 +1,49 @@
object triggersform: Ttriggersform
Left = 546
Height = 484
Top = 142
Width = 794
BorderIcons = [biSystemMenu]
BorderStyle = bsSingle
Caption = 'triggersform'
ClientHeight = 484
ClientWidth = 794
DefaultMonitor = dmDesktop
FormStyle = fsStayOnTop
OnCreate = FormCreate
Position = poWorkAreaCenter
ShowInTaskBar = stNever
LCLVersion = '1.7'
Scaled = True
object grp_main: TGroupBox
Left = 0
Height = 424
Top = 0
Width = 794
Align = alTop
Caption = 'Foobot Triggers'
TabOrder = 0
end
object cmd_OK: TBitBtn
Left = 360
Height = 30
Top = 440
Width = 75
Default = True
DefaultCaption = True
Kind = bkOK
ModalResult = 1
TabOrder = 1
end
object cmd_cancel: TBitBtn
Left = 704
Height = 30
Top = 440
Width = 75
Cancel = True
DefaultCaption = True
Kind = bkCancel
ModalResult = 2
TabOrder = 2
end
end

View File

@ -0,0 +1,42 @@
unit utriggersform;
{$mode objfpc}{$H+}
interface
uses
Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, StdCtrls,
Buttons;
type
{ Ttriggersform }
Ttriggersform = class(TForm)
cmd_cancel: TBitBtn;
cmd_OK: TBitBtn;
grp_main: TGroupBox;
procedure FormCreate(Sender: TObject);
private
public
end;
var
triggersform: Ttriggersform;
implementation
Uses umainform;
{$R *.lfm}
{ Ttriggersform }
procedure Ttriggersform.FormCreate(Sender: TObject);
begin
Icon:=Application.Icon;
Caption:=Application.Title + ' - Set Triggers';
end;
end.