A Rule is essentialy an interface with which the Logger can notify your code that some task needs to be done. In the case of the Logger, rules allow the programmer to have complete control over what is sent to the ecu, manipulations on the data recieved back from the ecu, and the data output to the screen and to the log file. In the case of the LogAnalyzer, the programmer has control over the data being displayed and analyzed through rules.
child.addLoggerRule()
There is an example below in the Examples section.
//These functions must be used at each iteration of the datalogger. //self explanatory void setAfr(float afr) void setMapIndex(int index) void setCurrentColumn(int x) void setCurrentFuelRow(int fy) void setCurrentIgnitionRow(int iy) //This sets a cells weight based on the interpolation. //index [0,0] is the current cell, index [1,0] //is the east cell, [0,1] is the south cell, etc. //The weights should always add up to 1. void setCellWeight(int col, int row, float value)
The same functions are provided in the AutoEdit class where the values are stored. They are only in the Logger class for convenience. The get counterparts to these functions are in the AutoEdit class as well.
public object ScriptMain(params object[] args) { romWind = (child)args[1]; romWind.subscribeToEvent("OnDataloggerCreated", "BensScripts.NewO2Def.log_Opened"); return null; }
Then define a function that adds an object of type AfrRule to the Logger:
public object log_Opened(params object[] args) { if(args[2] == null) return null; ((Logger)args[2]).addO2Type(new NewO2Rule("My New O2")); return null; }
You obviously need to create the object that extends AfrRule. But the key to it is the executeRule function:
public bool executeRule(Form frm) { Logger lo = ((Logger)frm); //is it our o2 type? if not return false if(index != lo.getO2Type()) return false; //get value from the hash table Integer val = lo.getLoggerData().getHashtable()["o2afr"]; //if its null, return false if(val == null) return false; //do calc stuff here: float afr = (float)(val.Value)/2.0f+9.0f; //set the value for the output afrKey->Value = afr.ToString("0.00"); //set the afr for the rest of the Logger lo.setAfr(afr); return true; }
The full example is down in the Examples section.
LoggerKey rpmKey = new LoggerKey("Rpm",true,true); datalogger.getLoggerData().addLoggerKey(rpmKey); //... rpmKey.Value = rpm.ToString();
Logger.getLoggerData()
).
executeRule()
is executed on each Rule. You will recieve the Logger (cast it as a Logger object) through which you can get the results data from the hash table.
//This adds a new o2 sensor definition to BRE using System; using System.Windows.Forms; using bre20; //css_reference ..\bre20.exe; namespace BensScripts { public class NewO2Def { public static object AppliesTo(){return "all";} public static object ScriptTitle(){return "New O2 Def by Ben Ogle";} //args[1] = child window of type bre20.child public object ScriptMain(params object[] args) { romWind = (child)args[1]; romWind.subscribeToEvent("OnDataloggerCreated", "BensScripts.NewO2Def.log_Opened"); return null; } public object log_Opened(params object[] args) { if(args[2] == null) return null; ((Logger)args[2]).addO2Type(new NewO2Rule("My New O2")); return null; } }//end class public class NewO2Rule: AfrRule { //stuff we can use: //afrKey //index public NewO2Rule(string name){base(name);} public bool executeRule(Form frm) { Logger lo = ((Logger)frm); //is it our o2 type? if not return false if(index != lo.getO2Type()) return false; //get value from the hash table Integer val = lo.getLoggerData().getHashtable()["o2afr"]; //if its null, return false if(val == null) return false; //do calc stuff here: float afr = (float)(val.Value)/2.0f+9.0f; //set the value for the output afrKey->Value = afr.ToString("0.00"); //set the afr for the rest of the Logger lo.setAfr(afr); return true; } } }//end namespace
//This adds a Datlogger definition definition to BRE using System; using System.Windows.Forms; using System.Collections; using bre20; //css_reference ..\bre20.exe; namespace BensScripts { public class Vt0Logger { child romWind; public static object AppliesTo(){return "pr3:pw0";} public static object ScriptTitle(){return "Obd0 Vtec Logger Defn by Ben Ogle";} //args[1] = child window of type bre20.child public object ScriptMain(params object[] args) { romWind = (child)args[1]; //subscribe to the event romWind.subscribeToEvent("OnDataloggerOpened", "BensScripts.Vt0Logger.log_Opened"); return null; } public object log_Opened(params object[] args) { //when the logger is opened, then we add our rule romWind.addLoggerRule(new Vt0LoggerDef()); return null; } }//end class public class Vt0LoggerDef: Rule { Logger log; //save a reference to our key LoggerKey rpm; public Vt0LoggerDef(){} public override void setupRule(Form frm) { log = ((Logger)frm); //here we set up the rpm LoggerKey rpm = new LoggerKey("Rpm",true,true); //add it to the logger log.getLoggerData().addLoggerKey(rpm); } public override bool executeRule(Form frm) { //get the results values from the hash table //the names/labels/keys are from loggerCmd.ini Hashtable hash = log.getLoggerData().getHashtable(); Integer val = (Integer)hash["rpm low"]; int tmp = val.Value + 256*(((Integer)hash["rpm high"]).Value); //set the value for the output rpm.Value = tmp.ToString(); return true; } //when a log file is being replayed this gets called. If you create //LoggerKeys which are not put in the csv file or gauges, you will //need to update those objects in this method. BRE automatically //matches the values in the csv file with their LoggerKey object; //those values will be put in the output grid for you. But BRE does //not update gauges. public override bool executeReplay(string[] keys, Hashtable values) { return true; } //this is what we are modifying public override string modifiedFields(){return "rpm";} } }//end namespace