Browse Source

DDE-Abgleich hinzu

FloKra 3 years ago
parent
commit
77fbf6148c

+ 354 - 0
DDE-Abgleich/DDEAbgleich_D50M47A.ccpage

@@ -0,0 +1,354 @@
+<?xml version="1.0" encoding="utf-8"?>
+<fragment xmlns="http://www.holeschak.de/BmwDeepObd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.holeschak.de/BmwDeepObd BmwDeepObd.xsd">
+  <page name="DDE5Abgleich" display-mode="list" fontsize="medium" gauges-portrait="2" gauges-landscape="4" logfile="DDE5A1_Abgleich.log">
+    <strings>
+      <string name="DDE5Abgleich">DDE5 adjustment</string>
+      <string name="!JOB#AGR_ABGLEICH_LESEN_WERT"> EGR (fresh air rate)</string>
+      <string name="!JOB#LLA_ABGLEICH_LESEN_WERT"> increase idle speed [rpm]</string>
+    </strings>
+	<strings lang="de">
+      <string name="DDE5Abgleich">DDE5 Abgleich</string>
+      <string name="!JOB#AGR_ABGLEICH_LESEN_WERT"> AGR (Frischluftrate)</string>
+      <string name="!JOB#LLA_ABGLEICH_LESEN_WERT"> Anhebung Leerlaufdrehzahl [u/min]</string>
+    </strings>
+    <display name="!JOB#AGR_ABGLEICH_LESEN_WERT" result="AGR_ABGLEICH_LESEN_WERT" format="L" display-order="0" grid-type="text" min-value="0" max-value="100" log_tag="AGR" />
+    <display name="!JOB#LLA_ABGLEICH_LESEN_WERT" result="LLA_ABGLEICH_LESEN_WERT" format="L" display-order="0" grid-type="text" min-value="0" max-value="100" log_tag="LLA" />
+    <jobs sgbd="D50M47A" />
+    <code show_warnings="true">
+    <![CDATA[
+    class PageClass
+    {
+        // Button deklarieren
+        private Button buttonAGRserie;
+        private Button buttonAGRred;
+        private Button buttonLLA0;
+        private Button buttonLLA50;
+        private Button buttonLLA70;
+        private Button buttonLLA100;
+        
+        // Ablaufvariable deklarieren und initialisieren
+        // diese boolsche Variable wird vom Button auf true gesetzt und in der ExecuteJob Methode ausgewertet
+        // wo dann ggf. der eigentliche Befehl ans Steuergerät ausgeführt wird
+        private bool set_AGR_serie = false;
+        private bool set_AGR_red = false;
+        private bool set_LLA_0 = false;
+        private bool set_LLA_50 = false;
+        private bool set_LLA_70 = false;
+        private bool set_LLA_100 = false;
+        
+        // Seitenaufbau: 
+        // <display... tags müssen direkt unter <page... stehen und result="RESULT_NAME" (ohne job name) enthalten
+        // diese werden unterhalb von der Funktion ExecuteJob befüllt
+        // <job... tags wie normalerweise gibt es nicht
+        // Es darf nur ein <jobs> tag in dieser form vorhanden sein: <jobs sgbg="sgbdname" />
+        // Jedenfalls wurde bei meinen Tests die ExecuteJobs Funktion niemals aufgerufen wenn in der ccpage 
+        // jobs im normalen Format enthalten waren. Ob das wirklich so ist oder ich einen anderen Fehler hatte 
+        // muss ich erst noch rausfinden. 
+        
+        public void CreateLayout(ActivityMain activity, JobReader.PageInfo pageInfo, LinearLayout pageLayout)
+        {
+            LinearLayout buttonLayout = new LinearLayout(activity);
+            buttonLayout.Orientation = Orientation.Horizontal;
+		
+            LinearLayout.LayoutParams buttonLayoutParams = new LinearLayout.LayoutParams(
+                ViewGroup.LayoutParams.MatchParent,
+                ViewGroup.LayoutParams.WrapContent);
+            buttonLayoutParams.Weight = 1;
+			
+			
+			// Button AGR Serie
+            buttonAGRserie = new Button(activity);
+            buttonAGRserie.Text = "AGR Serie";
+            buttonAGRserie.Click += delegate
+            {
+                // button setzt klassenweite variable auf true, diese wird beim durchlauf von ExecuteJob ausgewertet
+                set_AGR_serie = true;
+                
+                //// Benachrichtung anzeigen wenn man will
+                //ActivityMain.ShowNotification(activity, 0, 2,
+                //    "DDE Abgleich",
+                //    "AGR 0");
+            };
+            buttonLayout.AddView(buttonAGRserie, buttonLayoutParams);
+			
+			
+			// Button AGR Reduziert
+            buttonAGRred = new Button(activity);
+            buttonAGRred.Text = "AGR min.";
+            buttonAGRred.Click += delegate
+            {
+                // button setzt klassenweite variable auf true, diese wird beim durchlauf von ExecuteJob ausgewertet
+                set_AGR_red = true;
+                
+                //// Benachrichtung anzeigen wenn man will
+                //ActivityMain.ShowNotification(activity, 0, 2,
+                //    "DDE Abgleich",
+                //    "AGR 87");
+            };
+            buttonLayout.AddView(buttonAGRred, buttonLayoutParams);
+			
+			
+			// Button Leerlauf Serie
+            buttonLLA0 = new Button(activity);
+            buttonLLA0.Text = "LL +0";
+            buttonLLA0.Click += delegate
+            {
+                // button setzt klassenweite variable auf true, diese wird beim durchlauf von ExecuteJob ausgewertet
+                set_LLA_0 = true;
+                
+                //// Benachrichtung anzeigen wenn man will
+				//ActivityMain.ShowNotification(activity, 0, 2,
+				//    "DDE Abgleich",
+                //    "Leerlaufdrehzahl +0");
+            };
+            buttonLayout.AddView(buttonLLA0, buttonLayoutParams);
+			
+			
+			// Button Leerlauf +50
+            buttonLLA50 = new Button(activity);
+            buttonLLA50.Text = "LL +50";
+            buttonLLA50.Click += delegate
+            {
+                // button setzt klassenweite variable auf true, diese wird beim durchlauf von ExecuteJob ausgewertet
+                set_LLA_50 = true;
+                
+                //// Benachrichtung anzeigen wenn man will
+                //ActivityMain.ShowNotification(activity, 0, 2,
+                //    "DDE Abgleich",
+                //    "Leerlaufdrehzahl +50");
+            };
+            buttonLayout.AddView(buttonLLA50, buttonLayoutParams);
+			
+			
+			// Button Leerlauf +70
+            buttonLLA70 = new Button(activity);
+            buttonLLA70.Text = "LL +70";
+            buttonLLA70.Click += delegate
+            {
+                // button setzt klassenweite variable auf true, diese wird beim durchlauf von ExecuteJob ausgewertet
+                set_LLA_70 = true;
+                
+                //// Benachrichtung anzeigen wenn man will
+                //ActivityMain.ShowNotification(activity, 0, 2,
+                //    "DDE Abgleich",
+                //    "Leerlaufdrehzahl +70");
+            };
+            buttonLayout.AddView(buttonLLA70, buttonLayoutParams);
+			
+			
+			// Button Leerlauf +100
+            buttonLLA100 = new Button(activity);
+            buttonLLA100.Text = "LL +100";
+            buttonLLA100.Click += delegate
+            {
+                // button setzt klassenweite variable auf true, diese wird beim durchlauf von ExecuteJob ausgewertet
+                set_LLA_100 = true;
+                
+                //// Benachrichtung anzeigen wenn man will
+                //ActivityMain.ShowNotification(activity, 0, 2,
+                //    "DDE Abgleich",
+                //    "Leerlaufdrehzahl +100");
+            };
+            buttonLayout.AddView(buttonLLA100, buttonLayoutParams);
+			
+			
+		
+            LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(
+                ViewGroup.LayoutParams.MatchParent,
+                ViewGroup.LayoutParams.WrapContent);
+            pageLayout.AddView(buttonLayout, layoutParams);
+        }
+		
+        public void DestroyLayout(JobReader.PageInfo pageInfo)
+        {
+            buttonAGRserie = null;
+            buttonAGRred = null;
+            buttonLLA0 = null;
+            buttonLLA50 = null;
+            buttonLLA70 = null;
+            buttonLLA100 = null;
+        }
+
+        public void ExecuteJob(EdiabasNet ediabas, ref MultiMap<string, EdiabasNet.ResultData> resultDict, bool firstCall)
+        {
+            List<Dictionary<string, EdiabasNet.ResultData>> resultSets;  // hier werden die job results zwischengespeichert
+            
+            // unterhalb der/die JOB(s) zur Datenanzeige
+			
+			
+            ediabas.ArgString = "agr";
+            ediabas.ArgBinaryStd = null;
+            ediabas.ResultsRequests = string.Empty;
+            ediabas.ExecuteJob("ABGLEICH_LESEN");
+            
+            resultSets = ediabas.ResultSets;
+            if (resultSets != null && resultSets.Count >= 2)
+            {
+                // results der aktuellen Abfrage mit unveränderten result namen übernehmen
+                EdiabasThread.MergeResultDictionarys(ref resultDict, resultSets[1], "AGR_");
+            }
+			
+			
+			ediabas.ArgString = "lla";
+            ediabas.ArgBinaryStd = null;
+            ediabas.ResultsRequests = string.Empty;
+            ediabas.ExecuteJob("ABGLEICH_LESEN");
+            
+            resultSets = ediabas.ResultSets;
+            if (resultSets != null && resultSets.Count >= 2)
+            {
+                // results der aktuellen Abfrage mit unveränderten result namen übernehmen
+                EdiabasThread.MergeResultDictionarys(ref resultDict, resultSets[1], "LLA_");
+            }
+						
+            
+            // ENDE JOBs
+			
+			
+            
+            // Button JOBs
+			
+			if (set_AGR_serie) {
+                ediabas.ArgString = "agr;0";
+                ediabas.ArgBinaryStd = null;
+                ediabas.ResultsRequests = "JOB_STATUS";
+                ediabas.ExecuteJob("ABGLEICH_VERSTELLEN");
+				
+				ediabas.ArgString = "agr;0";
+                ediabas.ArgBinaryStd = null;
+                ediabas.ResultsRequests = "JOB_STATUS";
+                ediabas.ExecuteJob("ABGLEICH_PROG");
+                
+                // JOB RESULT ermitteln (wird derzeit nicht weiter verwendet weil man es anhand der geänderten Daten 
+                // und den blinkenden LEDs im KOMBI eh sofort sieht)
+                //resultSets = ediabas.ResultSets;
+                //if (resultSets != null && resultSets.Count >= 2)
+                //{
+                //  EdiabasThread.MergeResultDictionarys(ref resultDict, resultSets[1]);
+                //}
+                
+                // Ablaufvariable wieder zurücksetzen, sonst würde dieser Befehl nun bei jedem weiteren Durchlauf ausgeführt werden...
+                set_AGR_serie = false;
+            }
+			
+			if (set_AGR_red) {
+                ediabas.ArgString = "agr;87";
+                ediabas.ArgBinaryStd = null;
+                ediabas.ResultsRequests = "JOB_STATUS";
+                ediabas.ExecuteJob("ABGLEICH_VERSTELLEN");
+				
+				ediabas.ArgString = "agr;87";
+                ediabas.ArgBinaryStd = null;
+                ediabas.ResultsRequests = "JOB_STATUS";
+                ediabas.ExecuteJob("ABGLEICH_PROG");
+                
+                // JOB RESULT ermitteln (wird derzeit nicht weiter verwendet weil man es anhand der geänderten Daten 
+                // und den blinkenden LEDs im KOMBI eh sofort sieht)
+                //resultSets = ediabas.ResultSets;
+                //if (resultSets != null && resultSets.Count >= 2)
+                //{
+                //  EdiabasThread.MergeResultDictionarys(ref resultDict, resultSets[1]);
+                //}
+                
+                // Ablaufvariable wieder zurücksetzen, sonst würde dieser Befehl nun bei jedem weiteren Durchlauf ausgeführt werden...
+                set_AGR_red = false;
+            }
+			
+            if (set_LLA_0) {
+                ediabas.ArgString = "lla;0";
+                ediabas.ArgBinaryStd = null;
+                ediabas.ResultsRequests = "JOB_STATUS";
+                ediabas.ExecuteJob("ABGLEICH_VERSTELLEN");
+				
+				ediabas.ArgString = "lla;0";
+                ediabas.ArgBinaryStd = null;
+                ediabas.ResultsRequests = "JOB_STATUS";
+                ediabas.ExecuteJob("ABGLEICH_PROG");
+                
+                // JOB RESULT ermitteln (wird derzeit nicht weiter verwendet weil man es anhand der geänderten Daten 
+                // und den blinkenden LEDs im KOMBI eh sofort sieht)
+                //resultSets = ediabas.ResultSets;
+                //if (resultSets != null && resultSets.Count >= 2)
+                //{
+                //  EdiabasThread.MergeResultDictionarys(ref resultDict, resultSets[1]);
+                //}
+                
+                // Ablaufvariable wieder zurücksetzen, sonst würde dieser Befehl nun bei jedem weiteren Durchlauf ausgeführt werden...
+                set_LLA_0 = false;
+            }
+			
+			if (set_LLA_50) {
+                ediabas.ArgString = "lla;50";
+                ediabas.ArgBinaryStd = null;
+                ediabas.ResultsRequests = "JOB_STATUS";
+                ediabas.ExecuteJob("ABGLEICH_VERSTELLEN");
+				
+				ediabas.ArgString = "lla;50";
+                ediabas.ArgBinaryStd = null;
+                ediabas.ResultsRequests = "JOB_STATUS";
+                ediabas.ExecuteJob("ABGLEICH_PROG");
+                
+                // JOB RESULT ermitteln (wird derzeit nicht weiter verwendet weil man es anhand der geänderten Daten 
+                // und den blinkenden LEDs im KOMBI eh sofort sieht)
+                //resultSets = ediabas.ResultSets;
+                //if (resultSets != null && resultSets.Count >= 2)
+                //{
+                //  EdiabasThread.MergeResultDictionarys(ref resultDict, resultSets[1]);
+                //}
+                
+                // Ablaufvariable wieder zurücksetzen, sonst würde dieser Befehl nun bei jedem weiteren Durchlauf ausgeführt werden...
+                set_LLA_50 = false;
+            }
+			
+			if (set_LLA_70) {
+                ediabas.ArgString = "lla;70";
+                ediabas.ArgBinaryStd = null;
+                ediabas.ResultsRequests = "JOB_STATUS";
+                ediabas.ExecuteJob("ABGLEICH_VERSTELLEN");
+				
+				ediabas.ArgString = "lla;70";
+                ediabas.ArgBinaryStd = null;
+                ediabas.ResultsRequests = "JOB_STATUS";
+                ediabas.ExecuteJob("ABGLEICH_PROG");
+                
+                // JOB RESULT ermitteln (wird derzeit nicht weiter verwendet weil man es anhand der geänderten Daten 
+                // und den blinkenden LEDs im KOMBI eh sofort sieht)
+                //resultSets = ediabas.ResultSets;
+                //if (resultSets != null && resultSets.Count >= 2)
+                //{
+                //  EdiabasThread.MergeResultDictionarys(ref resultDict, resultSets[1]);
+                //}
+                
+                // Ablaufvariable wieder zurücksetzen, sonst würde dieser Befehl nun bei jedem weiteren Durchlauf ausgeführt werden...
+                set_LLA_70 = false;
+            }
+			
+			if (set_LLA_100) {
+                ediabas.ArgString = "lla;100";
+                ediabas.ArgBinaryStd = null;
+                ediabas.ResultsRequests = "JOB_STATUS";
+                ediabas.ExecuteJob("ABGLEICH_VERSTELLEN");
+				
+				ediabas.ArgString = "lla;100";
+                ediabas.ArgBinaryStd = null;
+                ediabas.ResultsRequests = "JOB_STATUS";
+                ediabas.ExecuteJob("ABGLEICH_PROG");
+                
+                // JOB RESULT ermitteln (wird derzeit nicht weiter verwendet weil man es anhand der geänderten Daten 
+                // und den blinkenden LEDs im KOMBI eh sofort sieht)
+                //resultSets = ediabas.ResultSets;
+                //if (resultSets != null && resultSets.Count >= 2)
+                //{
+                //  EdiabasThread.MergeResultDictionarys(ref resultDict, resultSets[1]);
+                //}
+                
+                // Ablaufvariable wieder zurücksetzen, sonst würde dieser Befehl nun bei jedem weiteren Durchlauf ausgeführt werden...
+                set_LLA_100 = false;
+            }
+			
+        }
+    }
+    ]]>
+    </code>
+  </page>
+</fragment>

+ 354 - 0
DDE-Abgleich/DDEAbgleich_D50M47B1.ccpage

@@ -0,0 +1,354 @@
+<?xml version="1.0" encoding="utf-8"?>
+<fragment xmlns="http://www.holeschak.de/BmwDeepObd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.holeschak.de/BmwDeepObd BmwDeepObd.xsd">
+  <page name="DDE5Abgleich" display-mode="list" fontsize="medium" gauges-portrait="2" gauges-landscape="4" logfile="DDE5A1_Abgleich.log">
+    <strings>
+      <string name="DDE5Abgleich">DDE5 adjustment</string>
+      <string name="!JOB#AGR_ABGLEICH_LESEN_WERT"> EGR (fresh air rate)</string>
+      <string name="!JOB#LLA_ABGLEICH_LESEN_WERT"> increase idle speed [rpm]</string>
+    </strings>
+	<strings lang="de">
+      <string name="DDE5Abgleich">DDE5 Abgleich</string>
+      <string name="!JOB#AGR_ABGLEICH_LESEN_WERT"> AGR (Frischluftrate)</string>
+      <string name="!JOB#LLA_ABGLEICH_LESEN_WERT"> Anhebung Leerlaufdrehzahl [u/min]</string>
+    </strings>
+    <display name="!JOB#AGR_ABGLEICH_LESEN_WERT" result="AGR_ABGLEICH_LESEN_WERT" format="L" display-order="0" grid-type="text" min-value="0" max-value="100" log_tag="AGR" />
+    <display name="!JOB#LLA_ABGLEICH_LESEN_WERT" result="LLA_ABGLEICH_LESEN_WERT" format="L" display-order="0" grid-type="text" min-value="0" max-value="100" log_tag="LLA" />
+    <jobs sgbd="D50M47B1" />
+    <code show_warnings="true">
+    <![CDATA[
+    class PageClass
+    {
+        // Button deklarieren
+        private Button buttonAGRserie;
+        private Button buttonAGRred;
+        private Button buttonLLA0;
+        private Button buttonLLA50;
+        private Button buttonLLA70;
+        private Button buttonLLA100;
+        
+        // Ablaufvariable deklarieren und initialisieren
+        // diese boolsche Variable wird vom Button auf true gesetzt und in der ExecuteJob Methode ausgewertet
+        // wo dann ggf. der eigentliche Befehl ans Steuergerät ausgeführt wird
+        private bool set_AGR_serie = false;
+        private bool set_AGR_red = false;
+        private bool set_LLA_0 = false;
+        private bool set_LLA_50 = false;
+        private bool set_LLA_70 = false;
+        private bool set_LLA_100 = false;
+        
+        // Seitenaufbau: 
+        // <display... tags müssen direkt unter <page... stehen und result="RESULT_NAME" (ohne job name) enthalten
+        // diese werden unterhalb von der Funktion ExecuteJob befüllt
+        // <job... tags wie normalerweise gibt es nicht
+        // Es darf nur ein <jobs> tag in dieser form vorhanden sein: <jobs sgbg="sgbdname" />
+        // Jedenfalls wurde bei meinen Tests die ExecuteJobs Funktion niemals aufgerufen wenn in der ccpage 
+        // jobs im normalen Format enthalten waren. Ob das wirklich so ist oder ich einen anderen Fehler hatte 
+        // muss ich erst noch rausfinden. 
+        
+        public void CreateLayout(ActivityMain activity, JobReader.PageInfo pageInfo, LinearLayout pageLayout)
+        {
+            LinearLayout buttonLayout = new LinearLayout(activity);
+            buttonLayout.Orientation = Orientation.Horizontal;
+		
+            LinearLayout.LayoutParams buttonLayoutParams = new LinearLayout.LayoutParams(
+                ViewGroup.LayoutParams.MatchParent,
+                ViewGroup.LayoutParams.WrapContent);
+            buttonLayoutParams.Weight = 1;
+			
+			
+			// Button AGR Serie
+            buttonAGRserie = new Button(activity);
+            buttonAGRserie.Text = "AGR Serie";
+            buttonAGRserie.Click += delegate
+            {
+                // button setzt klassenweite variable auf true, diese wird beim durchlauf von ExecuteJob ausgewertet
+                set_AGR_serie = true;
+                
+                //// Benachrichtung anzeigen wenn man will
+                //ActivityMain.ShowNotification(activity, 0, 2,
+                //    "DDE Abgleich",
+                //    "AGR 0");
+            };
+            buttonLayout.AddView(buttonAGRserie, buttonLayoutParams);
+			
+			
+			// Button AGR Reduziert
+            buttonAGRred = new Button(activity);
+            buttonAGRred.Text = "AGR min.";
+            buttonAGRred.Click += delegate
+            {
+                // button setzt klassenweite variable auf true, diese wird beim durchlauf von ExecuteJob ausgewertet
+                set_AGR_red = true;
+                
+                //// Benachrichtung anzeigen wenn man will
+                //ActivityMain.ShowNotification(activity, 0, 2,
+                //    "DDE Abgleich",
+                //    "AGR 87");
+            };
+            buttonLayout.AddView(buttonAGRred, buttonLayoutParams);
+			
+			
+			// Button Leerlauf Serie
+            buttonLLA0 = new Button(activity);
+            buttonLLA0.Text = "LL +0";
+            buttonLLA0.Click += delegate
+            {
+                // button setzt klassenweite variable auf true, diese wird beim durchlauf von ExecuteJob ausgewertet
+                set_LLA_0 = true;
+                
+                //// Benachrichtung anzeigen wenn man will
+				//ActivityMain.ShowNotification(activity, 0, 2,
+				//    "DDE Abgleich",
+                //    "Leerlaufdrehzahl +0");
+            };
+            buttonLayout.AddView(buttonLLA0, buttonLayoutParams);
+			
+			
+			// Button Leerlauf +50
+            buttonLLA50 = new Button(activity);
+            buttonLLA50.Text = "LL +50";
+            buttonLLA50.Click += delegate
+            {
+                // button setzt klassenweite variable auf true, diese wird beim durchlauf von ExecuteJob ausgewertet
+                set_LLA_50 = true;
+                
+                //// Benachrichtung anzeigen wenn man will
+                //ActivityMain.ShowNotification(activity, 0, 2,
+                //    "DDE Abgleich",
+                //    "Leerlaufdrehzahl +50");
+            };
+            buttonLayout.AddView(buttonLLA50, buttonLayoutParams);
+			
+			
+			// Button Leerlauf +70
+            buttonLLA70 = new Button(activity);
+            buttonLLA70.Text = "LL +70";
+            buttonLLA70.Click += delegate
+            {
+                // button setzt klassenweite variable auf true, diese wird beim durchlauf von ExecuteJob ausgewertet
+                set_LLA_70 = true;
+                
+                //// Benachrichtung anzeigen wenn man will
+                //ActivityMain.ShowNotification(activity, 0, 2,
+                //    "DDE Abgleich",
+                //    "Leerlaufdrehzahl +70");
+            };
+            buttonLayout.AddView(buttonLLA70, buttonLayoutParams);
+			
+			
+			// Button Leerlauf +100
+            buttonLLA100 = new Button(activity);
+            buttonLLA100.Text = "LL +100";
+            buttonLLA100.Click += delegate
+            {
+                // button setzt klassenweite variable auf true, diese wird beim durchlauf von ExecuteJob ausgewertet
+                set_LLA_100 = true;
+                
+                //// Benachrichtung anzeigen wenn man will
+                //ActivityMain.ShowNotification(activity, 0, 2,
+                //    "DDE Abgleich",
+                //    "Leerlaufdrehzahl +100");
+            };
+            buttonLayout.AddView(buttonLLA100, buttonLayoutParams);
+			
+			
+		
+            LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(
+                ViewGroup.LayoutParams.MatchParent,
+                ViewGroup.LayoutParams.WrapContent);
+            pageLayout.AddView(buttonLayout, layoutParams);
+        }
+		
+        public void DestroyLayout(JobReader.PageInfo pageInfo)
+        {
+            buttonAGRserie = null;
+            buttonAGRred = null;
+            buttonLLA0 = null;
+            buttonLLA50 = null;
+            buttonLLA70 = null;
+            buttonLLA100 = null;
+        }
+
+        public void ExecuteJob(EdiabasNet ediabas, ref MultiMap<string, EdiabasNet.ResultData> resultDict, bool firstCall)
+        {
+            List<Dictionary<string, EdiabasNet.ResultData>> resultSets;  // hier werden die job results zwischengespeichert
+            
+            // unterhalb der/die JOB(s) zur Datenanzeige
+			
+			
+            ediabas.ArgString = "agr";
+            ediabas.ArgBinaryStd = null;
+            ediabas.ResultsRequests = string.Empty;
+            ediabas.ExecuteJob("ABGLEICH_LESEN");
+            
+            resultSets = ediabas.ResultSets;
+            if (resultSets != null && resultSets.Count >= 2)
+            {
+                // results der aktuellen Abfrage mit unveränderten result namen übernehmen
+                EdiabasThread.MergeResultDictionarys(ref resultDict, resultSets[1], "AGR_");
+            }
+			
+			
+			ediabas.ArgString = "lla";
+            ediabas.ArgBinaryStd = null;
+            ediabas.ResultsRequests = string.Empty;
+            ediabas.ExecuteJob("ABGLEICH_LESEN");
+            
+            resultSets = ediabas.ResultSets;
+            if (resultSets != null && resultSets.Count >= 2)
+            {
+                // results der aktuellen Abfrage mit unveränderten result namen übernehmen
+                EdiabasThread.MergeResultDictionarys(ref resultDict, resultSets[1], "LLA_");
+            }
+						
+            
+            // ENDE JOBs
+			
+			
+            
+            // Button JOBs
+			
+			if (set_AGR_serie) {
+                ediabas.ArgString = "agr;0";
+                ediabas.ArgBinaryStd = null;
+                ediabas.ResultsRequests = "JOB_STATUS";
+                ediabas.ExecuteJob("ABGLEICH_VERSTELLEN");
+				
+				ediabas.ArgString = "agr;0";
+                ediabas.ArgBinaryStd = null;
+                ediabas.ResultsRequests = "JOB_STATUS";
+                ediabas.ExecuteJob("ABGLEICH_PROG");
+                
+                // JOB RESULT ermitteln (wird derzeit nicht weiter verwendet weil man es anhand der geänderten Daten 
+                // und den blinkenden LEDs im KOMBI eh sofort sieht)
+                //resultSets = ediabas.ResultSets;
+                //if (resultSets != null && resultSets.Count >= 2)
+                //{
+                //  EdiabasThread.MergeResultDictionarys(ref resultDict, resultSets[1]);
+                //}
+                
+                // Ablaufvariable wieder zurücksetzen, sonst würde dieser Befehl nun bei jedem weiteren Durchlauf ausgeführt werden...
+                set_AGR_serie = false;
+            }
+			
+			if (set_AGR_red) {
+                ediabas.ArgString = "agr;87";
+                ediabas.ArgBinaryStd = null;
+                ediabas.ResultsRequests = "JOB_STATUS";
+                ediabas.ExecuteJob("ABGLEICH_VERSTELLEN");
+				
+				ediabas.ArgString = "agr;87";
+                ediabas.ArgBinaryStd = null;
+                ediabas.ResultsRequests = "JOB_STATUS";
+                ediabas.ExecuteJob("ABGLEICH_PROG");
+                
+                // JOB RESULT ermitteln (wird derzeit nicht weiter verwendet weil man es anhand der geänderten Daten 
+                // und den blinkenden LEDs im KOMBI eh sofort sieht)
+                //resultSets = ediabas.ResultSets;
+                //if (resultSets != null && resultSets.Count >= 2)
+                //{
+                //  EdiabasThread.MergeResultDictionarys(ref resultDict, resultSets[1]);
+                //}
+                
+                // Ablaufvariable wieder zurücksetzen, sonst würde dieser Befehl nun bei jedem weiteren Durchlauf ausgeführt werden...
+                set_AGR_red = false;
+            }
+			
+            if (set_LLA_0) {
+                ediabas.ArgString = "lla;0";
+                ediabas.ArgBinaryStd = null;
+                ediabas.ResultsRequests = "JOB_STATUS";
+                ediabas.ExecuteJob("ABGLEICH_VERSTELLEN");
+				
+				ediabas.ArgString = "lla;0";
+                ediabas.ArgBinaryStd = null;
+                ediabas.ResultsRequests = "JOB_STATUS";
+                ediabas.ExecuteJob("ABGLEICH_PROG");
+                
+                // JOB RESULT ermitteln (wird derzeit nicht weiter verwendet weil man es anhand der geänderten Daten 
+                // und den blinkenden LEDs im KOMBI eh sofort sieht)
+                //resultSets = ediabas.ResultSets;
+                //if (resultSets != null && resultSets.Count >= 2)
+                //{
+                //  EdiabasThread.MergeResultDictionarys(ref resultDict, resultSets[1]);
+                //}
+                
+                // Ablaufvariable wieder zurücksetzen, sonst würde dieser Befehl nun bei jedem weiteren Durchlauf ausgeführt werden...
+                set_LLA_0 = false;
+            }
+			
+			if (set_LLA_50) {
+                ediabas.ArgString = "lla;50";
+                ediabas.ArgBinaryStd = null;
+                ediabas.ResultsRequests = "JOB_STATUS";
+                ediabas.ExecuteJob("ABGLEICH_VERSTELLEN");
+				
+				ediabas.ArgString = "lla;50";
+                ediabas.ArgBinaryStd = null;
+                ediabas.ResultsRequests = "JOB_STATUS";
+                ediabas.ExecuteJob("ABGLEICH_PROG");
+                
+                // JOB RESULT ermitteln (wird derzeit nicht weiter verwendet weil man es anhand der geänderten Daten 
+                // und den blinkenden LEDs im KOMBI eh sofort sieht)
+                //resultSets = ediabas.ResultSets;
+                //if (resultSets != null && resultSets.Count >= 2)
+                //{
+                //  EdiabasThread.MergeResultDictionarys(ref resultDict, resultSets[1]);
+                //}
+                
+                // Ablaufvariable wieder zurücksetzen, sonst würde dieser Befehl nun bei jedem weiteren Durchlauf ausgeführt werden...
+                set_LLA_50 = false;
+            }
+			
+			if (set_LLA_70) {
+                ediabas.ArgString = "lla;70";
+                ediabas.ArgBinaryStd = null;
+                ediabas.ResultsRequests = "JOB_STATUS";
+                ediabas.ExecuteJob("ABGLEICH_VERSTELLEN");
+				
+				ediabas.ArgString = "lla;70";
+                ediabas.ArgBinaryStd = null;
+                ediabas.ResultsRequests = "JOB_STATUS";
+                ediabas.ExecuteJob("ABGLEICH_PROG");
+                
+                // JOB RESULT ermitteln (wird derzeit nicht weiter verwendet weil man es anhand der geänderten Daten 
+                // und den blinkenden LEDs im KOMBI eh sofort sieht)
+                //resultSets = ediabas.ResultSets;
+                //if (resultSets != null && resultSets.Count >= 2)
+                //{
+                //  EdiabasThread.MergeResultDictionarys(ref resultDict, resultSets[1]);
+                //}
+                
+                // Ablaufvariable wieder zurücksetzen, sonst würde dieser Befehl nun bei jedem weiteren Durchlauf ausgeführt werden...
+                set_LLA_70 = false;
+            }
+			
+			if (set_LLA_100) {
+                ediabas.ArgString = "lla;100";
+                ediabas.ArgBinaryStd = null;
+                ediabas.ResultsRequests = "JOB_STATUS";
+                ediabas.ExecuteJob("ABGLEICH_VERSTELLEN");
+				
+				ediabas.ArgString = "lla;100";
+                ediabas.ArgBinaryStd = null;
+                ediabas.ResultsRequests = "JOB_STATUS";
+                ediabas.ExecuteJob("ABGLEICH_PROG");
+                
+                // JOB RESULT ermitteln (wird derzeit nicht weiter verwendet weil man es anhand der geänderten Daten 
+                // und den blinkenden LEDs im KOMBI eh sofort sieht)
+                //resultSets = ediabas.ResultSets;
+                //if (resultSets != null && resultSets.Count >= 2)
+                //{
+                //  EdiabasThread.MergeResultDictionarys(ref resultDict, resultSets[1]);
+                //}
+                
+                // Ablaufvariable wieder zurücksetzen, sonst würde dieser Befehl nun bei jedem weiteren Durchlauf ausgeführt werden...
+                set_LLA_100 = false;
+            }
+			
+        }
+    }
+    ]]>
+    </code>
+  </page>
+</fragment>

+ 354 - 0
DDE-Abgleich/DDEAbgleich_D50M57A1.ccpage

@@ -0,0 +1,354 @@
+<?xml version="1.0" encoding="utf-8"?>
+<fragment xmlns="http://www.holeschak.de/BmwDeepObd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.holeschak.de/BmwDeepObd BmwDeepObd.xsd">
+  <page name="DDE5Abgleich" display-mode="list" fontsize="medium" gauges-portrait="2" gauges-landscape="4" logfile="DDE5A1_Abgleich.log">
+    <strings>
+      <string name="DDE5Abgleich">DDE5 adjustment</string>
+      <string name="!JOB#AGR_ABGLEICH_LESEN_WERT"> EGR (fresh air rate)</string>
+      <string name="!JOB#LLA_ABGLEICH_LESEN_WERT"> increase idle speed [rpm]</string>
+    </strings>
+	<strings lang="de">
+      <string name="DDE5Abgleich">DDE5 Abgleich</string>
+      <string name="!JOB#AGR_ABGLEICH_LESEN_WERT"> AGR (Frischluftrate)</string>
+      <string name="!JOB#LLA_ABGLEICH_LESEN_WERT"> Anhebung Leerlaufdrehzahl [u/min]</string>
+    </strings>
+    <display name="!JOB#AGR_ABGLEICH_LESEN_WERT" result="AGR_ABGLEICH_LESEN_WERT" format="L" display-order="0" grid-type="text" min-value="0" max-value="100" log_tag="AGR" />
+    <display name="!JOB#LLA_ABGLEICH_LESEN_WERT" result="LLA_ABGLEICH_LESEN_WERT" format="L" display-order="0" grid-type="text" min-value="0" max-value="100" log_tag="LLA" />
+    <jobs sgbd="D50M57A1" />
+    <code show_warnings="true">
+    <![CDATA[
+    class PageClass
+    {
+        // Button deklarieren
+        private Button buttonAGRserie;
+        private Button buttonAGRred;
+        private Button buttonLLA0;
+        private Button buttonLLA50;
+        private Button buttonLLA70;
+        private Button buttonLLA100;
+        
+        // Ablaufvariable deklarieren und initialisieren
+        // diese boolsche Variable wird vom Button auf true gesetzt und in der ExecuteJob Methode ausgewertet
+        // wo dann ggf. der eigentliche Befehl ans Steuergerät ausgeführt wird
+        private bool set_AGR_serie = false;
+        private bool set_AGR_red = false;
+        private bool set_LLA_0 = false;
+        private bool set_LLA_50 = false;
+        private bool set_LLA_70 = false;
+        private bool set_LLA_100 = false;
+        
+        // Seitenaufbau: 
+        // <display... tags müssen direkt unter <page... stehen und result="RESULT_NAME" (ohne job name) enthalten
+        // diese werden unterhalb von der Funktion ExecuteJob befüllt
+        // <job... tags wie normalerweise gibt es nicht
+        // Es darf nur ein <jobs> tag in dieser form vorhanden sein: <jobs sgbg="sgbdname" />
+        // Jedenfalls wurde bei meinen Tests die ExecuteJobs Funktion niemals aufgerufen wenn in der ccpage 
+        // jobs im normalen Format enthalten waren. Ob das wirklich so ist oder ich einen anderen Fehler hatte 
+        // muss ich erst noch rausfinden. 
+        
+        public void CreateLayout(ActivityMain activity, JobReader.PageInfo pageInfo, LinearLayout pageLayout)
+        {
+            LinearLayout buttonLayout = new LinearLayout(activity);
+            buttonLayout.Orientation = Orientation.Horizontal;
+		
+            LinearLayout.LayoutParams buttonLayoutParams = new LinearLayout.LayoutParams(
+                ViewGroup.LayoutParams.MatchParent,
+                ViewGroup.LayoutParams.WrapContent);
+            buttonLayoutParams.Weight = 1;
+			
+			
+			// Button AGR Serie
+            buttonAGRserie = new Button(activity);
+            buttonAGRserie.Text = "AGR Serie";
+            buttonAGRserie.Click += delegate
+            {
+                // button setzt klassenweite variable auf true, diese wird beim durchlauf von ExecuteJob ausgewertet
+                set_AGR_serie = true;
+                
+                //// Benachrichtung anzeigen wenn man will
+                //ActivityMain.ShowNotification(activity, 0, 2,
+                //    "DDE Abgleich",
+                //    "AGR 0");
+            };
+            buttonLayout.AddView(buttonAGRserie, buttonLayoutParams);
+			
+			
+			// Button AGR Reduziert
+            buttonAGRred = new Button(activity);
+            buttonAGRred.Text = "AGR min.";
+            buttonAGRred.Click += delegate
+            {
+                // button setzt klassenweite variable auf true, diese wird beim durchlauf von ExecuteJob ausgewertet
+                set_AGR_red = true;
+                
+                //// Benachrichtung anzeigen wenn man will
+                //ActivityMain.ShowNotification(activity, 0, 2,
+                //    "DDE Abgleich",
+                //    "AGR 87");
+            };
+            buttonLayout.AddView(buttonAGRred, buttonLayoutParams);
+			
+			
+			// Button Leerlauf Serie
+            buttonLLA0 = new Button(activity);
+            buttonLLA0.Text = "LL +0";
+            buttonLLA0.Click += delegate
+            {
+                // button setzt klassenweite variable auf true, diese wird beim durchlauf von ExecuteJob ausgewertet
+                set_LLA_0 = true;
+                
+                //// Benachrichtung anzeigen wenn man will
+				//ActivityMain.ShowNotification(activity, 0, 2,
+				//    "DDE Abgleich",
+                //    "Leerlaufdrehzahl +0");
+            };
+            buttonLayout.AddView(buttonLLA0, buttonLayoutParams);
+			
+			
+			// Button Leerlauf +50
+            buttonLLA50 = new Button(activity);
+            buttonLLA50.Text = "LL +50";
+            buttonLLA50.Click += delegate
+            {
+                // button setzt klassenweite variable auf true, diese wird beim durchlauf von ExecuteJob ausgewertet
+                set_LLA_50 = true;
+                
+                //// Benachrichtung anzeigen wenn man will
+                //ActivityMain.ShowNotification(activity, 0, 2,
+                //    "DDE Abgleich",
+                //    "Leerlaufdrehzahl +50");
+            };
+            buttonLayout.AddView(buttonLLA50, buttonLayoutParams);
+			
+			
+			// Button Leerlauf +70
+            buttonLLA70 = new Button(activity);
+            buttonLLA70.Text = "LL +70";
+            buttonLLA70.Click += delegate
+            {
+                // button setzt klassenweite variable auf true, diese wird beim durchlauf von ExecuteJob ausgewertet
+                set_LLA_70 = true;
+                
+                //// Benachrichtung anzeigen wenn man will
+                //ActivityMain.ShowNotification(activity, 0, 2,
+                //    "DDE Abgleich",
+                //    "Leerlaufdrehzahl +70");
+            };
+            buttonLayout.AddView(buttonLLA70, buttonLayoutParams);
+			
+			
+			// Button Leerlauf +100
+            buttonLLA100 = new Button(activity);
+            buttonLLA100.Text = "LL +100";
+            buttonLLA100.Click += delegate
+            {
+                // button setzt klassenweite variable auf true, diese wird beim durchlauf von ExecuteJob ausgewertet
+                set_LLA_100 = true;
+                
+                //// Benachrichtung anzeigen wenn man will
+                //ActivityMain.ShowNotification(activity, 0, 2,
+                //    "DDE Abgleich",
+                //    "Leerlaufdrehzahl +100");
+            };
+            buttonLayout.AddView(buttonLLA100, buttonLayoutParams);
+			
+			
+		
+            LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(
+                ViewGroup.LayoutParams.MatchParent,
+                ViewGroup.LayoutParams.WrapContent);
+            pageLayout.AddView(buttonLayout, layoutParams);
+        }
+		
+        public void DestroyLayout(JobReader.PageInfo pageInfo)
+        {
+            buttonAGRserie = null;
+            buttonAGRred = null;
+            buttonLLA0 = null;
+            buttonLLA50 = null;
+            buttonLLA70 = null;
+            buttonLLA100 = null;
+        }
+
+        public void ExecuteJob(EdiabasNet ediabas, ref MultiMap<string, EdiabasNet.ResultData> resultDict, bool firstCall)
+        {
+            List<Dictionary<string, EdiabasNet.ResultData>> resultSets;  // hier werden die job results zwischengespeichert
+            
+            // unterhalb der/die JOB(s) zur Datenanzeige
+			
+			
+            ediabas.ArgString = "agr";
+            ediabas.ArgBinaryStd = null;
+            ediabas.ResultsRequests = string.Empty;
+            ediabas.ExecuteJob("ABGLEICH_LESEN");
+            
+            resultSets = ediabas.ResultSets;
+            if (resultSets != null && resultSets.Count >= 2)
+            {
+                // results der aktuellen Abfrage mit unveränderten result namen übernehmen
+                EdiabasThread.MergeResultDictionarys(ref resultDict, resultSets[1], "AGR_");
+            }
+			
+			
+			ediabas.ArgString = "lla";
+            ediabas.ArgBinaryStd = null;
+            ediabas.ResultsRequests = string.Empty;
+            ediabas.ExecuteJob("ABGLEICH_LESEN");
+            
+            resultSets = ediabas.ResultSets;
+            if (resultSets != null && resultSets.Count >= 2)
+            {
+                // results der aktuellen Abfrage mit unveränderten result namen übernehmen
+                EdiabasThread.MergeResultDictionarys(ref resultDict, resultSets[1], "LLA_");
+            }
+						
+            
+            // ENDE JOBs
+			
+			
+            
+            // Button JOBs
+			
+			if (set_AGR_serie) {
+                ediabas.ArgString = "agr;0";
+                ediabas.ArgBinaryStd = null;
+                ediabas.ResultsRequests = "JOB_STATUS";
+                ediabas.ExecuteJob("ABGLEICH_VERSTELLEN");
+				
+				ediabas.ArgString = "agr;0";
+                ediabas.ArgBinaryStd = null;
+                ediabas.ResultsRequests = "JOB_STATUS";
+                ediabas.ExecuteJob("ABGLEICH_PROG");
+                
+                // JOB RESULT ermitteln (wird derzeit nicht weiter verwendet weil man es anhand der geänderten Daten 
+                // und den blinkenden LEDs im KOMBI eh sofort sieht)
+                //resultSets = ediabas.ResultSets;
+                //if (resultSets != null && resultSets.Count >= 2)
+                //{
+                //  EdiabasThread.MergeResultDictionarys(ref resultDict, resultSets[1]);
+                //}
+                
+                // Ablaufvariable wieder zurücksetzen, sonst würde dieser Befehl nun bei jedem weiteren Durchlauf ausgeführt werden...
+                set_AGR_serie = false;
+            }
+			
+			if (set_AGR_red) {
+                ediabas.ArgString = "agr;87";
+                ediabas.ArgBinaryStd = null;
+                ediabas.ResultsRequests = "JOB_STATUS";
+                ediabas.ExecuteJob("ABGLEICH_VERSTELLEN");
+				
+				ediabas.ArgString = "agr;87";
+                ediabas.ArgBinaryStd = null;
+                ediabas.ResultsRequests = "JOB_STATUS";
+                ediabas.ExecuteJob("ABGLEICH_PROG");
+                
+                // JOB RESULT ermitteln (wird derzeit nicht weiter verwendet weil man es anhand der geänderten Daten 
+                // und den blinkenden LEDs im KOMBI eh sofort sieht)
+                //resultSets = ediabas.ResultSets;
+                //if (resultSets != null && resultSets.Count >= 2)
+                //{
+                //  EdiabasThread.MergeResultDictionarys(ref resultDict, resultSets[1]);
+                //}
+                
+                // Ablaufvariable wieder zurücksetzen, sonst würde dieser Befehl nun bei jedem weiteren Durchlauf ausgeführt werden...
+                set_AGR_red = false;
+            }
+			
+            if (set_LLA_0) {
+                ediabas.ArgString = "lla;0";
+                ediabas.ArgBinaryStd = null;
+                ediabas.ResultsRequests = "JOB_STATUS";
+                ediabas.ExecuteJob("ABGLEICH_VERSTELLEN");
+				
+				ediabas.ArgString = "lla;0";
+                ediabas.ArgBinaryStd = null;
+                ediabas.ResultsRequests = "JOB_STATUS";
+                ediabas.ExecuteJob("ABGLEICH_PROG");
+                
+                // JOB RESULT ermitteln (wird derzeit nicht weiter verwendet weil man es anhand der geänderten Daten 
+                // und den blinkenden LEDs im KOMBI eh sofort sieht)
+                //resultSets = ediabas.ResultSets;
+                //if (resultSets != null && resultSets.Count >= 2)
+                //{
+                //  EdiabasThread.MergeResultDictionarys(ref resultDict, resultSets[1]);
+                //}
+                
+                // Ablaufvariable wieder zurücksetzen, sonst würde dieser Befehl nun bei jedem weiteren Durchlauf ausgeführt werden...
+                set_LLA_0 = false;
+            }
+			
+			if (set_LLA_50) {
+                ediabas.ArgString = "lla;50";
+                ediabas.ArgBinaryStd = null;
+                ediabas.ResultsRequests = "JOB_STATUS";
+                ediabas.ExecuteJob("ABGLEICH_VERSTELLEN");
+				
+				ediabas.ArgString = "lla;50";
+                ediabas.ArgBinaryStd = null;
+                ediabas.ResultsRequests = "JOB_STATUS";
+                ediabas.ExecuteJob("ABGLEICH_PROG");
+                
+                // JOB RESULT ermitteln (wird derzeit nicht weiter verwendet weil man es anhand der geänderten Daten 
+                // und den blinkenden LEDs im KOMBI eh sofort sieht)
+                //resultSets = ediabas.ResultSets;
+                //if (resultSets != null && resultSets.Count >= 2)
+                //{
+                //  EdiabasThread.MergeResultDictionarys(ref resultDict, resultSets[1]);
+                //}
+                
+                // Ablaufvariable wieder zurücksetzen, sonst würde dieser Befehl nun bei jedem weiteren Durchlauf ausgeführt werden...
+                set_LLA_50 = false;
+            }
+			
+			if (set_LLA_70) {
+                ediabas.ArgString = "lla;70";
+                ediabas.ArgBinaryStd = null;
+                ediabas.ResultsRequests = "JOB_STATUS";
+                ediabas.ExecuteJob("ABGLEICH_VERSTELLEN");
+				
+				ediabas.ArgString = "lla;70";
+                ediabas.ArgBinaryStd = null;
+                ediabas.ResultsRequests = "JOB_STATUS";
+                ediabas.ExecuteJob("ABGLEICH_PROG");
+                
+                // JOB RESULT ermitteln (wird derzeit nicht weiter verwendet weil man es anhand der geänderten Daten 
+                // und den blinkenden LEDs im KOMBI eh sofort sieht)
+                //resultSets = ediabas.ResultSets;
+                //if (resultSets != null && resultSets.Count >= 2)
+                //{
+                //  EdiabasThread.MergeResultDictionarys(ref resultDict, resultSets[1]);
+                //}
+                
+                // Ablaufvariable wieder zurücksetzen, sonst würde dieser Befehl nun bei jedem weiteren Durchlauf ausgeführt werden...
+                set_LLA_70 = false;
+            }
+			
+			if (set_LLA_100) {
+                ediabas.ArgString = "lla;100";
+                ediabas.ArgBinaryStd = null;
+                ediabas.ResultsRequests = "JOB_STATUS";
+                ediabas.ExecuteJob("ABGLEICH_VERSTELLEN");
+				
+				ediabas.ArgString = "lla;100";
+                ediabas.ArgBinaryStd = null;
+                ediabas.ResultsRequests = "JOB_STATUS";
+                ediabas.ExecuteJob("ABGLEICH_PROG");
+                
+                // JOB RESULT ermitteln (wird derzeit nicht weiter verwendet weil man es anhand der geänderten Daten 
+                // und den blinkenden LEDs im KOMBI eh sofort sieht)
+                //resultSets = ediabas.ResultSets;
+                //if (resultSets != null && resultSets.Count >= 2)
+                //{
+                //  EdiabasThread.MergeResultDictionarys(ref resultDict, resultSets[1]);
+                //}
+                
+                // Ablaufvariable wieder zurücksetzen, sonst würde dieser Befehl nun bei jedem weiteren Durchlauf ausgeführt werden...
+                set_LLA_100 = false;
+            }
+			
+        }
+    }
+    ]]>
+    </code>
+  </page>
+</fragment>

+ 354 - 0
DDE-Abgleich/DDEAbgleich_D50M57E1.ccpage

@@ -0,0 +1,354 @@
+<?xml version="1.0" encoding="utf-8"?>
+<fragment xmlns="http://www.holeschak.de/BmwDeepObd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.holeschak.de/BmwDeepObd BmwDeepObd.xsd">
+  <page name="DDE5Abgleich" display-mode="list" fontsize="medium" gauges-portrait="2" gauges-landscape="4" logfile="DDE5E1_Abgleich.log">
+    <strings>
+      <string name="DDE5Abgleich">DDE5 adjustment</string>
+      <string name="!JOB#AGR_ABGLEICH_LESEN_WERT"> EGR (fresh air rate)</string>
+      <string name="!JOB#LLA_ABGLEICH_LESEN_WERT"> increase idle speed [rpm]</string>
+    </strings>
+	<strings lang="de">
+      <string name="DDE5Abgleich">DDE5 Abgleich</string>
+      <string name="!JOB#AGR_ABGLEICH_LESEN_WERT"> AGR (Frischluftrate)</string>
+      <string name="!JOB#LLA_ABGLEICH_LESEN_WERT"> Anhebung Leerlaufdrehzahl [u/min]</string>
+    </strings>
+    <display name="!JOB#AGR_ABGLEICH_LESEN_WERT" result="AGR_ABGLEICH_LESEN_WERT" format="L" display-order="0" grid-type="text" min-value="0" max-value="100" log_tag="AGR" />
+    <display name="!JOB#LLA_ABGLEICH_LESEN_WERT" result="LLA_ABGLEICH_LESEN_WERT" format="L" display-order="0" grid-type="text" min-value="0" max-value="100" log_tag="LLA" />
+    <jobs sgbd="D50M57E1" />
+    <code show_warnings="true">
+    <![CDATA[
+    class PageClass
+    {
+        // Button deklarieren
+        private Button buttonAGRserie;
+        private Button buttonAGRred;
+        private Button buttonLLA0;
+        private Button buttonLLA50;
+        private Button buttonLLA70;
+        private Button buttonLLA100;
+        
+        // Ablaufvariable deklarieren und initialisieren
+        // diese boolsche Variable wird vom Button auf true gesetzt und in der ExecuteJob Methode ausgewertet
+        // wo dann ggf. der eigentliche Befehl ans Steuergerät ausgeführt wird
+        private bool set_AGR_serie = false;
+        private bool set_AGR_red = false;
+        private bool set_LLA_0 = false;
+        private bool set_LLA_50 = false;
+        private bool set_LLA_70 = false;
+        private bool set_LLA_100 = false;
+        
+        // Seitenaufbau: 
+        // <display... tags müssen direkt unter <page... stehen und result="RESULT_NAME" (ohne job name) enthalten
+        // diese werden unterhalb von der Funktion ExecuteJob befüllt
+        // <job... tags wie normalerweise gibt es nicht
+        // Es darf nur ein <jobs> tag in dieser form vorhanden sein: <jobs sgbg="sgbdname" />
+        // Jedenfalls wurde bei meinen Tests die ExecuteJobs Funktion niemals aufgerufen wenn in der ccpage 
+        // jobs im normalen Format enthalten waren. Ob das wirklich so ist oder ich einen anderen Fehler hatte 
+        // muss ich erst noch rausfinden. 
+        
+        public void CreateLayout(ActivityMain activity, JobReader.PageInfo pageInfo, LinearLayout pageLayout)
+        {
+            LinearLayout buttonLayout = new LinearLayout(activity);
+            buttonLayout.Orientation = Orientation.Horizontal;
+		
+            LinearLayout.LayoutParams buttonLayoutParams = new LinearLayout.LayoutParams(
+                ViewGroup.LayoutParams.MatchParent,
+                ViewGroup.LayoutParams.WrapContent);
+            buttonLayoutParams.Weight = 1;
+			
+			
+			// Button AGR Serie
+            buttonAGRserie = new Button(activity);
+            buttonAGRserie.Text = "AGR Serie";
+            buttonAGRserie.Click += delegate
+            {
+                // button setzt klassenweite variable auf true, diese wird beim durchlauf von ExecuteJob ausgewertet
+                set_AGR_serie = true;
+                
+                //// Benachrichtung anzeigen wenn man will
+                //ActivityMain.ShowNotification(activity, 0, 2,
+                //    "DDE Abgleich",
+                //    "AGR 0");
+            };
+            buttonLayout.AddView(buttonAGRserie, buttonLayoutParams);
+			
+			
+			// Button AGR Reduziert
+            buttonAGRred = new Button(activity);
+            buttonAGRred.Text = "AGR min.";
+            buttonAGRred.Click += delegate
+            {
+                // button setzt klassenweite variable auf true, diese wird beim durchlauf von ExecuteJob ausgewertet
+                set_AGR_red = true;
+                
+                //// Benachrichtung anzeigen wenn man will
+                //ActivityMain.ShowNotification(activity, 0, 2,
+                //    "DDE Abgleich",
+                //    "AGR 87");
+            };
+            buttonLayout.AddView(buttonAGRred, buttonLayoutParams);
+			
+			
+			// Button Leerlauf Serie
+            buttonLLA0 = new Button(activity);
+            buttonLLA0.Text = "LL +0";
+            buttonLLA0.Click += delegate
+            {
+                // button setzt klassenweite variable auf true, diese wird beim durchlauf von ExecuteJob ausgewertet
+                set_LLA_0 = true;
+                
+                //// Benachrichtung anzeigen wenn man will
+				//ActivityMain.ShowNotification(activity, 0, 2,
+				//    "DDE Abgleich",
+                //    "Leerlaufdrehzahl +0");
+            };
+            buttonLayout.AddView(buttonLLA0, buttonLayoutParams);
+			
+			
+			// Button Leerlauf +50
+            buttonLLA50 = new Button(activity);
+            buttonLLA50.Text = "LL +50";
+            buttonLLA50.Click += delegate
+            {
+                // button setzt klassenweite variable auf true, diese wird beim durchlauf von ExecuteJob ausgewertet
+                set_LLA_50 = true;
+                
+                //// Benachrichtung anzeigen wenn man will
+                //ActivityMain.ShowNotification(activity, 0, 2,
+                //    "DDE Abgleich",
+                //    "Leerlaufdrehzahl +50");
+            };
+            buttonLayout.AddView(buttonLLA50, buttonLayoutParams);
+			
+			
+			// Button Leerlauf +70
+            buttonLLA70 = new Button(activity);
+            buttonLLA70.Text = "LL +70";
+            buttonLLA70.Click += delegate
+            {
+                // button setzt klassenweite variable auf true, diese wird beim durchlauf von ExecuteJob ausgewertet
+                set_LLA_70 = true;
+                
+                //// Benachrichtung anzeigen wenn man will
+                //ActivityMain.ShowNotification(activity, 0, 2,
+                //    "DDE Abgleich",
+                //    "Leerlaufdrehzahl +70");
+            };
+            buttonLayout.AddView(buttonLLA70, buttonLayoutParams);
+			
+			
+			// Button Leerlauf +100
+            buttonLLA100 = new Button(activity);
+            buttonLLA100.Text = "LL +100";
+            buttonLLA100.Click += delegate
+            {
+                // button setzt klassenweite variable auf true, diese wird beim durchlauf von ExecuteJob ausgewertet
+                set_LLA_100 = true;
+                
+                //// Benachrichtung anzeigen wenn man will
+                //ActivityMain.ShowNotification(activity, 0, 2,
+                //    "DDE Abgleich",
+                //    "Leerlaufdrehzahl +100");
+            };
+            buttonLayout.AddView(buttonLLA100, buttonLayoutParams);
+			
+			
+		
+            LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(
+                ViewGroup.LayoutParams.MatchParent,
+                ViewGroup.LayoutParams.WrapContent);
+            pageLayout.AddView(buttonLayout, layoutParams);
+        }
+		
+        public void DestroyLayout(JobReader.PageInfo pageInfo)
+        {
+            buttonAGRserie = null;
+            buttonAGRred = null;
+            buttonLLA0 = null;
+            buttonLLA50 = null;
+            buttonLLA70 = null;
+            buttonLLA100 = null;
+        }
+
+        public void ExecuteJob(EdiabasNet ediabas, ref MultiMap<string, EdiabasNet.ResultData> resultDict, bool firstCall)
+        {
+            List<Dictionary<string, EdiabasNet.ResultData>> resultSets;  // hier werden die job results zwischengespeichert
+            
+            // unterhalb der/die JOB(s) zur Datenanzeige
+			
+			
+            ediabas.ArgString = "agr";
+            ediabas.ArgBinaryStd = null;
+            ediabas.ResultsRequests = string.Empty;
+            ediabas.ExecuteJob("ABGLEICH_LESEN");
+            
+            resultSets = ediabas.ResultSets;
+            if (resultSets != null && resultSets.Count >= 2)
+            {
+                // results der aktuellen Abfrage mit unveränderten result namen übernehmen
+                EdiabasThread.MergeResultDictionarys(ref resultDict, resultSets[1], "AGR_");
+            }
+			
+			
+			ediabas.ArgString = "lla";
+            ediabas.ArgBinaryStd = null;
+            ediabas.ResultsRequests = string.Empty;
+            ediabas.ExecuteJob("ABGLEICH_LESEN");
+            
+            resultSets = ediabas.ResultSets;
+            if (resultSets != null && resultSets.Count >= 2)
+            {
+                // results der aktuellen Abfrage mit unveränderten result namen übernehmen
+                EdiabasThread.MergeResultDictionarys(ref resultDict, resultSets[1], "LLA_");
+            }
+						
+            
+            // ENDE JOBs
+			
+			
+            
+            // Button JOBs
+			
+			if (set_AGR_serie) {
+                ediabas.ArgString = "agr;0";
+                ediabas.ArgBinaryStd = null;
+                ediabas.ResultsRequests = "JOB_STATUS";
+                ediabas.ExecuteJob("ABGLEICH_VERSTELLEN");
+				
+				ediabas.ArgString = "agr;0";
+                ediabas.ArgBinaryStd = null;
+                ediabas.ResultsRequests = "JOB_STATUS";
+                ediabas.ExecuteJob("ABGLEICH_PROG");
+                
+                // JOB RESULT ermitteln (wird derzeit nicht weiter verwendet weil man es anhand der geänderten Daten 
+                // und den blinkenden LEDs im KOMBI eh sofort sieht)
+                //resultSets = ediabas.ResultSets;
+                //if (resultSets != null && resultSets.Count >= 2)
+                //{
+                //  EdiabasThread.MergeResultDictionarys(ref resultDict, resultSets[1]);
+                //}
+                
+                // Ablaufvariable wieder zurücksetzen, sonst würde dieser Befehl nun bei jedem weiteren Durchlauf ausgeführt werden...
+                set_AGR_serie = false;
+            }
+			
+			if (set_AGR_red) {
+                ediabas.ArgString = "agr;87";
+                ediabas.ArgBinaryStd = null;
+                ediabas.ResultsRequests = "JOB_STATUS";
+                ediabas.ExecuteJob("ABGLEICH_VERSTELLEN");
+				
+				ediabas.ArgString = "agr;87";
+                ediabas.ArgBinaryStd = null;
+                ediabas.ResultsRequests = "JOB_STATUS";
+                ediabas.ExecuteJob("ABGLEICH_PROG");
+                
+                // JOB RESULT ermitteln (wird derzeit nicht weiter verwendet weil man es anhand der geänderten Daten 
+                // und den blinkenden LEDs im KOMBI eh sofort sieht)
+                //resultSets = ediabas.ResultSets;
+                //if (resultSets != null && resultSets.Count >= 2)
+                //{
+                //  EdiabasThread.MergeResultDictionarys(ref resultDict, resultSets[1]);
+                //}
+                
+                // Ablaufvariable wieder zurücksetzen, sonst würde dieser Befehl nun bei jedem weiteren Durchlauf ausgeführt werden...
+                set_AGR_red = false;
+            }
+			
+            if (set_LLA_0) {
+                ediabas.ArgString = "lla;0";
+                ediabas.ArgBinaryStd = null;
+                ediabas.ResultsRequests = "JOB_STATUS";
+                ediabas.ExecuteJob("ABGLEICH_VERSTELLEN");
+				
+				ediabas.ArgString = "lla;0";
+                ediabas.ArgBinaryStd = null;
+                ediabas.ResultsRequests = "JOB_STATUS";
+                ediabas.ExecuteJob("ABGLEICH_PROG");
+                
+                // JOB RESULT ermitteln (wird derzeit nicht weiter verwendet weil man es anhand der geänderten Daten 
+                // und den blinkenden LEDs im KOMBI eh sofort sieht)
+                //resultSets = ediabas.ResultSets;
+                //if (resultSets != null && resultSets.Count >= 2)
+                //{
+                //  EdiabasThread.MergeResultDictionarys(ref resultDict, resultSets[1]);
+                //}
+                
+                // Ablaufvariable wieder zurücksetzen, sonst würde dieser Befehl nun bei jedem weiteren Durchlauf ausgeführt werden...
+                set_LLA_0 = false;
+            }
+			
+			if (set_LLA_50) {
+                ediabas.ArgString = "lla;50";
+                ediabas.ArgBinaryStd = null;
+                ediabas.ResultsRequests = "JOB_STATUS";
+                ediabas.ExecuteJob("ABGLEICH_VERSTELLEN");
+				
+				ediabas.ArgString = "lla;50";
+                ediabas.ArgBinaryStd = null;
+                ediabas.ResultsRequests = "JOB_STATUS";
+                ediabas.ExecuteJob("ABGLEICH_PROG");
+                
+                // JOB RESULT ermitteln (wird derzeit nicht weiter verwendet weil man es anhand der geänderten Daten 
+                // und den blinkenden LEDs im KOMBI eh sofort sieht)
+                //resultSets = ediabas.ResultSets;
+                //if (resultSets != null && resultSets.Count >= 2)
+                //{
+                //  EdiabasThread.MergeResultDictionarys(ref resultDict, resultSets[1]);
+                //}
+                
+                // Ablaufvariable wieder zurücksetzen, sonst würde dieser Befehl nun bei jedem weiteren Durchlauf ausgeführt werden...
+                set_LLA_50 = false;
+            }
+			
+			if (set_LLA_70) {
+                ediabas.ArgString = "lla;70";
+                ediabas.ArgBinaryStd = null;
+                ediabas.ResultsRequests = "JOB_STATUS";
+                ediabas.ExecuteJob("ABGLEICH_VERSTELLEN");
+				
+				ediabas.ArgString = "lla;70";
+                ediabas.ArgBinaryStd = null;
+                ediabas.ResultsRequests = "JOB_STATUS";
+                ediabas.ExecuteJob("ABGLEICH_PROG");
+                
+                // JOB RESULT ermitteln (wird derzeit nicht weiter verwendet weil man es anhand der geänderten Daten 
+                // und den blinkenden LEDs im KOMBI eh sofort sieht)
+                //resultSets = ediabas.ResultSets;
+                //if (resultSets != null && resultSets.Count >= 2)
+                //{
+                //  EdiabasThread.MergeResultDictionarys(ref resultDict, resultSets[1]);
+                //}
+                
+                // Ablaufvariable wieder zurücksetzen, sonst würde dieser Befehl nun bei jedem weiteren Durchlauf ausgeführt werden...
+                set_LLA_70 = false;
+            }
+			
+			if (set_LLA_100) {
+                ediabas.ArgString = "lla;100";
+                ediabas.ArgBinaryStd = null;
+                ediabas.ResultsRequests = "JOB_STATUS";
+                ediabas.ExecuteJob("ABGLEICH_VERSTELLEN");
+				
+				ediabas.ArgString = "lla;100";
+                ediabas.ArgBinaryStd = null;
+                ediabas.ResultsRequests = "JOB_STATUS";
+                ediabas.ExecuteJob("ABGLEICH_PROG");
+                
+                // JOB RESULT ermitteln (wird derzeit nicht weiter verwendet weil man es anhand der geänderten Daten 
+                // und den blinkenden LEDs im KOMBI eh sofort sieht)
+                //resultSets = ediabas.ResultSets;
+                //if (resultSets != null && resultSets.Count >= 2)
+                //{
+                //  EdiabasThread.MergeResultDictionarys(ref resultDict, resultSets[1]);
+                //}
+                
+                // Ablaufvariable wieder zurücksetzen, sonst würde dieser Befehl nun bei jedem weiteren Durchlauf ausgeführt werden...
+                set_LLA_100 = false;
+            }
+			
+        }
+    }
+    ]]>
+    </code>
+  </page>
+</fragment>

+ 354 - 0
DDE-Abgleich/DDEAbgleich_DDE30DS0.ccpage

@@ -0,0 +1,354 @@
+<?xml version="1.0" encoding="utf-8"?>
+<fragment xmlns="http://www.holeschak.de/BmwDeepObd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.holeschak.de/BmwDeepObd BmwDeepObd.xsd">
+  <page name="DDE3Abgleich" display-mode="list" fontsize="medium" gauges-portrait="2" gauges-landscape="4" logfile="DDE3_Abgleich.log">
+    <strings>
+      <string name="DDE3Abgleich">DDE3 adjustment</string>
+      <string name="!JOB#ABGLEICH_LESEN_AGR_RUECK#ABGLEICH_LESEN_AGR_RUECK_WERT"> EGR (fresh air rate)</string>
+      <string name="!JOB#ABGLEICH_LESEN_LL_REGELUNG#ABGLEICH_LESEN_LL_REGELUNG_WERT"> increase idle speed [rpm]</string>
+    </strings>
+	<strings lang="de">
+      <string name="DDE3Abgleich">DDE3 Abgleich</string>
+      <string name="!JOB#ABGLEICH_LESEN_AGR_RUECK#ABGLEICH_LESEN_AGR_RUECK_WERT"> AGR (Frischluftrate)</string>
+      <string name="!JOB#ABGLEICH_LESEN_LL_REGELUNG#ABGLEICH_LESEN_LL_REGELUNG_WERT"> Anhebung Leerlaufdrehzahl [u/min]</string>
+    </strings>
+    <display name="!JOB#ABGLEICH_LESEN_AGR_RUECK#ABGLEICH_LESEN_AGR_RUECK_WERT" result="ABGLEICH_LESEN_AGR_RUECK_WERT" format="L" display-order="0" grid-type="text" min-value="0" max-value="100" log_tag="AGR" />
+    <display name="!JOB#ABGLEICH_LESEN_LL_REGELUNG#ABGLEICH_LESEN_LL_REGELUNG_WERT" result="ABGLEICH_LESEN_LL_REGELUNG_WERT" format="L" display-order="0" grid-type="text" min-value="0" max-value="100" log_tag="LLA" />
+    <jobs sgbd="DDE30DS0" />
+    <code show_warnings="true">
+    <![CDATA[
+    class PageClass
+    {
+        // Button deklarieren
+        private Button buttonAGRserie;
+        private Button buttonAGRred;
+        private Button buttonLLA0;
+        private Button buttonLLA50;
+        private Button buttonLLA70;
+        private Button buttonLLA100;
+        
+        // Ablaufvariable deklarieren und initialisieren
+        // diese boolsche Variable wird vom Button auf true gesetzt und in der ExecuteJob Methode ausgewertet
+        // wo dann ggf. der eigentliche Befehl ans Steuergerät ausgeführt wird
+        private bool set_AGR_serie = false;
+        private bool set_AGR_red = false;
+        private bool set_LLA_0 = false;
+        private bool set_LLA_50 = false;
+        private bool set_LLA_70 = false;
+        private bool set_LLA_100 = false;
+        
+        // Seitenaufbau: 
+        // <display... tags müssen direkt unter <page... stehen und result="RESULT_NAME" (ohne job name) enthalten
+        // diese werden unterhalb von der Funktion ExecuteJob befüllt
+        // <job... tags wie normalerweise gibt es nicht
+        // Es darf nur ein <jobs> tag in dieser form vorhanden sein: <jobs sgbg="sgbdname" />
+        // Jedenfalls wurde bei meinen Tests die ExecuteJobs Funktion niemals aufgerufen wenn in der ccpage 
+        // jobs im normalen Format enthalten waren. Ob das wirklich so ist oder ich einen anderen Fehler hatte 
+        // muss ich erst noch rausfinden. 
+        
+        public void CreateLayout(ActivityMain activity, JobReader.PageInfo pageInfo, LinearLayout pageLayout)
+        {
+            LinearLayout buttonLayout = new LinearLayout(activity);
+            buttonLayout.Orientation = Orientation.Horizontal;
+		
+            LinearLayout.LayoutParams buttonLayoutParams = new LinearLayout.LayoutParams(
+                ViewGroup.LayoutParams.MatchParent,
+                ViewGroup.LayoutParams.WrapContent);
+            buttonLayoutParams.Weight = 1;
+			
+			
+			// Button AGR Serie
+            buttonAGRserie = new Button(activity);
+            buttonAGRserie.Text = "AGR Serie";
+            buttonAGRserie.Click += delegate
+            {
+                // button setzt klassenweite variable auf true, diese wird beim durchlauf von ExecuteJob ausgewertet
+                set_AGR_serie = true;
+                
+                //// Benachrichtung anzeigen wenn man will
+                //ActivityMain.ShowNotification(activity, 0, 2,
+                //    "DDE Abgleich",
+                //    "AGR 0");
+            };
+            buttonLayout.AddView(buttonAGRserie, buttonLayoutParams);
+			
+			
+			// Button AGR Reduziert
+            buttonAGRred = new Button(activity);
+            buttonAGRred.Text = "AGR min.";
+            buttonAGRred.Click += delegate
+            {
+                // button setzt klassenweite variable auf true, diese wird beim durchlauf von ExecuteJob ausgewertet
+                set_AGR_red = true;
+                
+                //// Benachrichtung anzeigen wenn man will
+                //ActivityMain.ShowNotification(activity, 0, 2,
+                //    "DDE Abgleich",
+                //    "AGR 87");
+            };
+            buttonLayout.AddView(buttonAGRred, buttonLayoutParams);
+			
+			
+			// Button Leerlauf Serie
+            buttonLLA0 = new Button(activity);
+            buttonLLA0.Text = "LL +0";
+            buttonLLA0.Click += delegate
+            {
+                // button setzt klassenweite variable auf true, diese wird beim durchlauf von ExecuteJob ausgewertet
+                set_LLA_0 = true;
+                
+                //// Benachrichtung anzeigen wenn man will
+				//ActivityMain.ShowNotification(activity, 0, 2,
+				//    "DDE Abgleich",
+                //    "Leerlaufdrehzahl +0");
+            };
+            buttonLayout.AddView(buttonLLA0, buttonLayoutParams);
+			
+			
+			// Button Leerlauf +50
+            buttonLLA50 = new Button(activity);
+            buttonLLA50.Text = "LL +50";
+            buttonLLA50.Click += delegate
+            {
+                // button setzt klassenweite variable auf true, diese wird beim durchlauf von ExecuteJob ausgewertet
+                set_LLA_50 = true;
+                
+                //// Benachrichtung anzeigen wenn man will
+                //ActivityMain.ShowNotification(activity, 0, 2,
+                //    "DDE Abgleich",
+                //    "Leerlaufdrehzahl +50");
+            };
+            buttonLayout.AddView(buttonLLA50, buttonLayoutParams);
+			
+			
+			// Button Leerlauf +70
+            buttonLLA70 = new Button(activity);
+            buttonLLA70.Text = "LL +70";
+            buttonLLA70.Click += delegate
+            {
+                // button setzt klassenweite variable auf true, diese wird beim durchlauf von ExecuteJob ausgewertet
+                set_LLA_70 = true;
+                
+                //// Benachrichtung anzeigen wenn man will
+                //ActivityMain.ShowNotification(activity, 0, 2,
+                //    "DDE Abgleich",
+                //    "Leerlaufdrehzahl +70");
+            };
+            buttonLayout.AddView(buttonLLA70, buttonLayoutParams);
+			
+			
+			// Button Leerlauf +100
+            buttonLLA100 = new Button(activity);
+            buttonLLA100.Text = "LL +100";
+            buttonLLA100.Click += delegate
+            {
+                // button setzt klassenweite variable auf true, diese wird beim durchlauf von ExecuteJob ausgewertet
+                set_LLA_100 = true;
+                
+                //// Benachrichtung anzeigen wenn man will
+                //ActivityMain.ShowNotification(activity, 0, 2,
+                //    "DDE Abgleich",
+                //    "Leerlaufdrehzahl +100");
+            };
+            buttonLayout.AddView(buttonLLA100, buttonLayoutParams);
+			
+			
+		
+            LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(
+                ViewGroup.LayoutParams.MatchParent,
+                ViewGroup.LayoutParams.WrapContent);
+            pageLayout.AddView(buttonLayout, layoutParams);
+        }
+		
+        public void DestroyLayout(JobReader.PageInfo pageInfo)
+        {
+            buttonAGRserie = null;
+            buttonAGRred = null;
+            buttonLLA0 = null;
+            buttonLLA50 = null;
+            buttonLLA70 = null;
+            buttonLLA100 = null;
+        }
+
+        public void ExecuteJob(EdiabasNet ediabas, ref MultiMap<string, EdiabasNet.ResultData> resultDict, bool firstCall)
+        {
+            List<Dictionary<string, EdiabasNet.ResultData>> resultSets;  // hier werden die job results zwischengespeichert
+            
+            // unterhalb der/die JOB(s) zur Datenanzeige
+			
+			
+            ediabas.ArgString = string.Empty;
+            ediabas.ArgBinaryStd = null;
+            ediabas.ResultsRequests = string.Empty;
+            ediabas.ExecuteJob("ABGLEICH_LESEN_AGR_RUECK");
+            
+            resultSets = ediabas.ResultSets;
+            if (resultSets != null && resultSets.Count >= 2)
+            {
+                // results der aktuellen Abfrage mit unveränderten result namen übernehmen
+                EdiabasThread.MergeResultDictionarys(ref resultDict, resultSets[1]);
+            }
+			
+			
+			ediabas.ArgString = string.Empty;
+            ediabas.ArgBinaryStd = null;
+            ediabas.ResultsRequests = string.Empty;
+            ediabas.ExecuteJob("ABGLEICH_LESEN_LL_REGELUNG");
+            
+            resultSets = ediabas.ResultSets;
+            if (resultSets != null && resultSets.Count >= 2)
+            {
+                // results der aktuellen Abfrage mit unveränderten result namen übernehmen
+                EdiabasThread.MergeResultDictionarys(ref resultDict, resultSets[1]);
+            }
+						
+            
+            // ENDE JOBs
+			
+			
+            
+            // Button JOBs
+			
+			if (set_AGR_serie) {
+                ediabas.ArgString = "0";
+                ediabas.ArgBinaryStd = null;
+                ediabas.ResultsRequests = "JOB_STATUS";
+                ediabas.ExecuteJob("ABGLEICH_VERSTELLEN_AGR_RUECK");
+				
+				ediabas.ArgString = "0";
+                ediabas.ArgBinaryStd = null;
+                ediabas.ResultsRequests = "JOB_STATUS";
+                ediabas.ExecuteJob("ABGLEICH_PROG_AGR_RUECK");
+                
+                // JOB RESULT ermitteln (wird derzeit nicht weiter verwendet weil man es anhand der geänderten Daten 
+                // und den blinkenden LEDs im KOMBI eh sofort sieht)
+                //resultSets = ediabas.ResultSets;
+                //if (resultSets != null && resultSets.Count >= 2)
+                //{
+                //  EdiabasThread.MergeResultDictionarys(ref resultDict, resultSets[1]);
+                //}
+                
+                // Ablaufvariable wieder zurücksetzen, sonst würde dieser Befehl nun bei jedem weiteren Durchlauf ausgeführt werden...
+                set_AGR_serie = false;
+            }
+			
+			if (set_AGR_red) {
+                ediabas.ArgString = "87";
+                ediabas.ArgBinaryStd = null;
+                ediabas.ResultsRequests = "JOB_STATUS";
+                ediabas.ExecuteJob("ABGLEICH_VERSTELLEN_AGR_RUECK");
+				
+				ediabas.ArgString = "87";
+                ediabas.ArgBinaryStd = null;
+                ediabas.ResultsRequests = "JOB_STATUS";
+                ediabas.ExecuteJob("ABGLEICH_PROG_AGR_RUECK");
+                
+                // JOB RESULT ermitteln (wird derzeit nicht weiter verwendet weil man es anhand der geänderten Daten 
+                // und den blinkenden LEDs im KOMBI eh sofort sieht)
+                //resultSets = ediabas.ResultSets;
+                //if (resultSets != null && resultSets.Count >= 2)
+                //{
+                //  EdiabasThread.MergeResultDictionarys(ref resultDict, resultSets[1]);
+                //}
+                
+                // Ablaufvariable wieder zurücksetzen, sonst würde dieser Befehl nun bei jedem weiteren Durchlauf ausgeführt werden...
+                set_AGR_red = false;
+            }
+			
+            if (set_LLA_0) {
+                ediabas.ArgString = "0";
+                ediabas.ArgBinaryStd = null;
+                ediabas.ResultsRequests = "JOB_STATUS";
+                ediabas.ExecuteJob("ABGLEICH_VERSTELLEN_LL_REGELUNG");
+				
+				ediabas.ArgString = "0";
+                ediabas.ArgBinaryStd = null;
+                ediabas.ResultsRequests = "JOB_STATUS";
+                ediabas.ExecuteJob("ABGLEICH_PROG_LL_REGELUNG");
+                
+                // JOB RESULT ermitteln (wird derzeit nicht weiter verwendet weil man es anhand der geänderten Daten 
+                // und den blinkenden LEDs im KOMBI eh sofort sieht)
+                //resultSets = ediabas.ResultSets;
+                //if (resultSets != null && resultSets.Count >= 2)
+                //{
+                //  EdiabasThread.MergeResultDictionarys(ref resultDict, resultSets[1]);
+                //}
+                
+                // Ablaufvariable wieder zurücksetzen, sonst würde dieser Befehl nun bei jedem weiteren Durchlauf ausgeführt werden...
+                set_LLA_0 = false;
+            }
+			
+			if (set_LLA_50) {
+                ediabas.ArgString = "50";
+                ediabas.ArgBinaryStd = null;
+                ediabas.ResultsRequests = "JOB_STATUS";
+                ediabas.ExecuteJob("ABGLEICH_VERSTELLEN_LL_REGELUNG");
+				
+				ediabas.ArgString = "50";
+                ediabas.ArgBinaryStd = null;
+                ediabas.ResultsRequests = "JOB_STATUS";
+                ediabas.ExecuteJob("ABGLEICH_PROG_LL_REGELUNG");
+                
+                // JOB RESULT ermitteln (wird derzeit nicht weiter verwendet weil man es anhand der geänderten Daten 
+                // und den blinkenden LEDs im KOMBI eh sofort sieht)
+                //resultSets = ediabas.ResultSets;
+                //if (resultSets != null && resultSets.Count >= 2)
+                //{
+                //  EdiabasThread.MergeResultDictionarys(ref resultDict, resultSets[1]);
+                //}
+                
+                // Ablaufvariable wieder zurücksetzen, sonst würde dieser Befehl nun bei jedem weiteren Durchlauf ausgeführt werden...
+                set_LLA_50 = false;
+            }
+			
+			if (set_LLA_70) {
+                ediabas.ArgString = "70";
+                ediabas.ArgBinaryStd = null;
+                ediabas.ResultsRequests = "JOB_STATUS";
+                ediabas.ExecuteJob("ABGLEICH_VERSTELLEN_LL_REGELUNG");
+				
+				ediabas.ArgString = "70";
+                ediabas.ArgBinaryStd = null;
+                ediabas.ResultsRequests = "JOB_STATUS";
+                ediabas.ExecuteJob("ABGLEICH_PROG_LL_REGELUNG");
+                
+                // JOB RESULT ermitteln (wird derzeit nicht weiter verwendet weil man es anhand der geänderten Daten 
+                // und den blinkenden LEDs im KOMBI eh sofort sieht)
+                //resultSets = ediabas.ResultSets;
+                //if (resultSets != null && resultSets.Count >= 2)
+                //{
+                //  EdiabasThread.MergeResultDictionarys(ref resultDict, resultSets[1]);
+                //}
+                
+                // Ablaufvariable wieder zurücksetzen, sonst würde dieser Befehl nun bei jedem weiteren Durchlauf ausgeführt werden...
+                set_LLA_70 = false;
+            }
+			
+			if (set_LLA_100) {
+                ediabas.ArgString = "100";
+                ediabas.ArgBinaryStd = null;
+                ediabas.ResultsRequests = "JOB_STATUS";
+                ediabas.ExecuteJob("ABGLEICH_VERSTELLEN_LL_REGELUNG");
+				
+				ediabas.ArgString = "100";
+                ediabas.ArgBinaryStd = null;
+                ediabas.ResultsRequests = "JOB_STATUS";
+                ediabas.ExecuteJob("ABGLEICH_PROG_LL_REGELUNG");
+                
+                // JOB RESULT ermitteln (wird derzeit nicht weiter verwendet weil man es anhand der geänderten Daten 
+                // und den blinkenden LEDs im KOMBI eh sofort sieht)
+                //resultSets = ediabas.ResultSets;
+                //if (resultSets != null && resultSets.Count >= 2)
+                //{
+                //  EdiabasThread.MergeResultDictionarys(ref resultDict, resultSets[1]);
+                //}
+                
+                // Ablaufvariable wieder zurücksetzen, sonst würde dieser Befehl nun bei jedem weiteren Durchlauf ausgeführt werden...
+                set_LLA_100 = false;
+            }
+			
+        }
+    }
+    ]]>
+    </code>
+  </page>
+</fragment>

+ 354 - 0
DDE-Abgleich/DDEAbgleich_DDE40KW0.ccpage

@@ -0,0 +1,354 @@
+<?xml version="1.0" encoding="utf-8"?>
+<fragment xmlns="http://www.holeschak.de/BmwDeepObd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.holeschak.de/BmwDeepObd BmwDeepObd.xsd">
+  <page name="DDE4Abgleich" display-mode="list" fontsize="medium" gauges-portrait="2" gauges-landscape="4" logfile="DDE4_Abgleich.log">
+    <strings>
+      <string name="DDE4Abgleich">DDE4 adjustment</string>
+      <string name="!JOB#ABGLEICH_LESEN_AGR_RUECK#ABGLEICH_LESEN_AGR_RUECK_WERT"> EGR (fresh air rate)</string>
+      <string name="!JOB#ABGLEICH_LESEN_LL_REGELUNG#ABGLEICH_LESEN_LL_REGELUNG_WERT"> increase idle speed [rpm]</string>
+    </strings>
+	<strings lang="de">
+      <string name="DDE4Abgleich">DDE4 Abgleich</string>
+      <string name="!JOB#ABGLEICH_LESEN_AGR_RUECK#ABGLEICH_LESEN_AGR_RUECK_WERT"> AGR (Frischluftrate)</string>
+      <string name="!JOB#ABGLEICH_LESEN_LL_REGELUNG#ABGLEICH_LESEN_LL_REGELUNG_WERT"> Anhebung Leerlaufdrehzahl [u/min]</string>
+    </strings>
+    <display name="!JOB#ABGLEICH_LESEN_AGR_RUECK#ABGLEICH_LESEN_AGR_RUECK_WERT" result="ABGLEICH_LESEN_AGR_RUECK_WERT" format="L" display-order="0" grid-type="text" min-value="0" max-value="100" log_tag="AGR" />
+    <display name="!JOB#ABGLEICH_LESEN_LL_REGELUNG#ABGLEICH_LESEN_LL_REGELUNG_WERT" result="ABGLEICH_LESEN_LL_REGELUNG_WERT" format="L" display-order="0" grid-type="text" min-value="0" max-value="100" log_tag="LLA" />
+    <jobs sgbd="DDE40KW0" />
+    <code show_warnings="true">
+    <![CDATA[
+    class PageClass
+    {
+        // Button deklarieren
+        private Button buttonAGRserie;
+        private Button buttonAGRred;
+        private Button buttonLLA0;
+        private Button buttonLLA50;
+        private Button buttonLLA70;
+        private Button buttonLLA100;
+        
+        // Ablaufvariable deklarieren und initialisieren
+        // diese boolsche Variable wird vom Button auf true gesetzt und in der ExecuteJob Methode ausgewertet
+        // wo dann ggf. der eigentliche Befehl ans Steuergerät ausgeführt wird
+        private bool set_AGR_serie = false;
+        private bool set_AGR_red = false;
+        private bool set_LLA_0 = false;
+        private bool set_LLA_50 = false;
+        private bool set_LLA_70 = false;
+        private bool set_LLA_100 = false;
+        
+        // Seitenaufbau: 
+        // <display... tags müssen direkt unter <page... stehen und result="RESULT_NAME" (ohne job name) enthalten
+        // diese werden unterhalb von der Funktion ExecuteJob befüllt
+        // <job... tags wie normalerweise gibt es nicht
+        // Es darf nur ein <jobs> tag in dieser form vorhanden sein: <jobs sgbg="sgbdname" />
+        // Jedenfalls wurde bei meinen Tests die ExecuteJobs Funktion niemals aufgerufen wenn in der ccpage 
+        // jobs im normalen Format enthalten waren. Ob das wirklich so ist oder ich einen anderen Fehler hatte 
+        // muss ich erst noch rausfinden. 
+        
+        public void CreateLayout(ActivityMain activity, JobReader.PageInfo pageInfo, LinearLayout pageLayout)
+        {
+            LinearLayout buttonLayout = new LinearLayout(activity);
+            buttonLayout.Orientation = Orientation.Horizontal;
+		
+            LinearLayout.LayoutParams buttonLayoutParams = new LinearLayout.LayoutParams(
+                ViewGroup.LayoutParams.MatchParent,
+                ViewGroup.LayoutParams.WrapContent);
+            buttonLayoutParams.Weight = 1;
+			
+			
+			// Button AGR Serie
+            buttonAGRserie = new Button(activity);
+            buttonAGRserie.Text = "AGR Serie";
+            buttonAGRserie.Click += delegate
+            {
+                // button setzt klassenweite variable auf true, diese wird beim durchlauf von ExecuteJob ausgewertet
+                set_AGR_serie = true;
+                
+                //// Benachrichtung anzeigen wenn man will
+                //ActivityMain.ShowNotification(activity, 0, 2,
+                //    "DDE Abgleich",
+                //    "AGR 0");
+            };
+            buttonLayout.AddView(buttonAGRserie, buttonLayoutParams);
+			
+			
+			// Button AGR Reduziert
+            buttonAGRred = new Button(activity);
+            buttonAGRred.Text = "AGR min.";
+            buttonAGRred.Click += delegate
+            {
+                // button setzt klassenweite variable auf true, diese wird beim durchlauf von ExecuteJob ausgewertet
+                set_AGR_red = true;
+                
+                //// Benachrichtung anzeigen wenn man will
+                //ActivityMain.ShowNotification(activity, 0, 2,
+                //    "DDE Abgleich",
+                //    "AGR 87");
+            };
+            buttonLayout.AddView(buttonAGRred, buttonLayoutParams);
+			
+			
+			// Button Leerlauf Serie
+            buttonLLA0 = new Button(activity);
+            buttonLLA0.Text = "LL +0";
+            buttonLLA0.Click += delegate
+            {
+                // button setzt klassenweite variable auf true, diese wird beim durchlauf von ExecuteJob ausgewertet
+                set_LLA_0 = true;
+                
+                //// Benachrichtung anzeigen wenn man will
+				//ActivityMain.ShowNotification(activity, 0, 2,
+				//    "DDE Abgleich",
+                //    "Leerlaufdrehzahl +0");
+            };
+            buttonLayout.AddView(buttonLLA0, buttonLayoutParams);
+			
+			
+			// Button Leerlauf +50
+            buttonLLA50 = new Button(activity);
+            buttonLLA50.Text = "LL +50";
+            buttonLLA50.Click += delegate
+            {
+                // button setzt klassenweite variable auf true, diese wird beim durchlauf von ExecuteJob ausgewertet
+                set_LLA_50 = true;
+                
+                //// Benachrichtung anzeigen wenn man will
+                //ActivityMain.ShowNotification(activity, 0, 2,
+                //    "DDE Abgleich",
+                //    "Leerlaufdrehzahl +50");
+            };
+            buttonLayout.AddView(buttonLLA50, buttonLayoutParams);
+			
+			
+			// Button Leerlauf +70
+            buttonLLA70 = new Button(activity);
+            buttonLLA70.Text = "LL +70";
+            buttonLLA70.Click += delegate
+            {
+                // button setzt klassenweite variable auf true, diese wird beim durchlauf von ExecuteJob ausgewertet
+                set_LLA_70 = true;
+                
+                //// Benachrichtung anzeigen wenn man will
+                //ActivityMain.ShowNotification(activity, 0, 2,
+                //    "DDE Abgleich",
+                //    "Leerlaufdrehzahl +70");
+            };
+            buttonLayout.AddView(buttonLLA70, buttonLayoutParams);
+			
+			
+			// Button Leerlauf +100
+            buttonLLA100 = new Button(activity);
+            buttonLLA100.Text = "LL +100";
+            buttonLLA100.Click += delegate
+            {
+                // button setzt klassenweite variable auf true, diese wird beim durchlauf von ExecuteJob ausgewertet
+                set_LLA_100 = true;
+                
+                //// Benachrichtung anzeigen wenn man will
+                //ActivityMain.ShowNotification(activity, 0, 2,
+                //    "DDE Abgleich",
+                //    "Leerlaufdrehzahl +100");
+            };
+            buttonLayout.AddView(buttonLLA100, buttonLayoutParams);
+			
+			
+		
+            LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(
+                ViewGroup.LayoutParams.MatchParent,
+                ViewGroup.LayoutParams.WrapContent);
+            pageLayout.AddView(buttonLayout, layoutParams);
+        }
+		
+        public void DestroyLayout(JobReader.PageInfo pageInfo)
+        {
+            buttonAGRserie = null;
+            buttonAGRred = null;
+            buttonLLA0 = null;
+            buttonLLA50 = null;
+            buttonLLA70 = null;
+            buttonLLA100 = null;
+        }
+
+        public void ExecuteJob(EdiabasNet ediabas, ref MultiMap<string, EdiabasNet.ResultData> resultDict, bool firstCall)
+        {
+            List<Dictionary<string, EdiabasNet.ResultData>> resultSets;  // hier werden die job results zwischengespeichert
+            
+            // unterhalb der/die JOB(s) zur Datenanzeige
+			
+			
+            ediabas.ArgString = string.Empty;
+            ediabas.ArgBinaryStd = null;
+            ediabas.ResultsRequests = string.Empty;
+            ediabas.ExecuteJob("ABGLEICH_LESEN_AGR_RUECK");
+            
+            resultSets = ediabas.ResultSets;
+            if (resultSets != null && resultSets.Count >= 2)
+            {
+                // results der aktuellen Abfrage mit unveränderten result namen übernehmen
+                EdiabasThread.MergeResultDictionarys(ref resultDict, resultSets[1]);
+            }
+			
+			
+			ediabas.ArgString = string.Empty;
+            ediabas.ArgBinaryStd = null;
+            ediabas.ResultsRequests = string.Empty;
+            ediabas.ExecuteJob("ABGLEICH_LESEN_LL_REGELUNG");
+            
+            resultSets = ediabas.ResultSets;
+            if (resultSets != null && resultSets.Count >= 2)
+            {
+                // results der aktuellen Abfrage mit unveränderten result namen übernehmen
+                EdiabasThread.MergeResultDictionarys(ref resultDict, resultSets[1]);
+            }
+						
+            
+            // ENDE JOBs
+			
+			
+            
+            // Button JOBs
+			
+			if (set_AGR_serie) {
+                ediabas.ArgString = "0";
+                ediabas.ArgBinaryStd = null;
+                ediabas.ResultsRequests = "JOB_STATUS";
+                ediabas.ExecuteJob("ABGLEICH_VERSTELLEN_AGR_RUECK");
+				
+				ediabas.ArgString = "0";
+                ediabas.ArgBinaryStd = null;
+                ediabas.ResultsRequests = "JOB_STATUS";
+                ediabas.ExecuteJob("ABGLEICH_PROG_AGR_RUECK");
+                
+                // JOB RESULT ermitteln (wird derzeit nicht weiter verwendet weil man es anhand der geänderten Daten 
+                // und den blinkenden LEDs im KOMBI eh sofort sieht)
+                //resultSets = ediabas.ResultSets;
+                //if (resultSets != null && resultSets.Count >= 2)
+                //{
+                //  EdiabasThread.MergeResultDictionarys(ref resultDict, resultSets[1]);
+                //}
+                
+                // Ablaufvariable wieder zurücksetzen, sonst würde dieser Befehl nun bei jedem weiteren Durchlauf ausgeführt werden...
+                set_AGR_serie = false;
+            }
+			
+			if (set_AGR_red) {
+                ediabas.ArgString = "87";
+                ediabas.ArgBinaryStd = null;
+                ediabas.ResultsRequests = "JOB_STATUS";
+                ediabas.ExecuteJob("ABGLEICH_VERSTELLEN_AGR_RUECK");
+				
+				ediabas.ArgString = "87";
+                ediabas.ArgBinaryStd = null;
+                ediabas.ResultsRequests = "JOB_STATUS";
+                ediabas.ExecuteJob("ABGLEICH_PROG_AGR_RUECK");
+                
+                // JOB RESULT ermitteln (wird derzeit nicht weiter verwendet weil man es anhand der geänderten Daten 
+                // und den blinkenden LEDs im KOMBI eh sofort sieht)
+                //resultSets = ediabas.ResultSets;
+                //if (resultSets != null && resultSets.Count >= 2)
+                //{
+                //  EdiabasThread.MergeResultDictionarys(ref resultDict, resultSets[1]);
+                //}
+                
+                // Ablaufvariable wieder zurücksetzen, sonst würde dieser Befehl nun bei jedem weiteren Durchlauf ausgeführt werden...
+                set_AGR_red = false;
+            }
+			
+            if (set_LLA_0) {
+                ediabas.ArgString = "0";
+                ediabas.ArgBinaryStd = null;
+                ediabas.ResultsRequests = "JOB_STATUS";
+                ediabas.ExecuteJob("ABGLEICH_VERSTELLEN_LL_REGELUNG");
+				
+				ediabas.ArgString = "0";
+                ediabas.ArgBinaryStd = null;
+                ediabas.ResultsRequests = "JOB_STATUS";
+                ediabas.ExecuteJob("ABGLEICH_PROG_LL_REGELUNG");
+                
+                // JOB RESULT ermitteln (wird derzeit nicht weiter verwendet weil man es anhand der geänderten Daten 
+                // und den blinkenden LEDs im KOMBI eh sofort sieht)
+                //resultSets = ediabas.ResultSets;
+                //if (resultSets != null && resultSets.Count >= 2)
+                //{
+                //  EdiabasThread.MergeResultDictionarys(ref resultDict, resultSets[1]);
+                //}
+                
+                // Ablaufvariable wieder zurücksetzen, sonst würde dieser Befehl nun bei jedem weiteren Durchlauf ausgeführt werden...
+                set_LLA_0 = false;
+            }
+			
+			if (set_LLA_50) {
+                ediabas.ArgString = "50";
+                ediabas.ArgBinaryStd = null;
+                ediabas.ResultsRequests = "JOB_STATUS";
+                ediabas.ExecuteJob("ABGLEICH_VERSTELLEN_LL_REGELUNG");
+				
+				ediabas.ArgString = "50";
+                ediabas.ArgBinaryStd = null;
+                ediabas.ResultsRequests = "JOB_STATUS";
+                ediabas.ExecuteJob("ABGLEICH_PROG_LL_REGELUNG");
+                
+                // JOB RESULT ermitteln (wird derzeit nicht weiter verwendet weil man es anhand der geänderten Daten 
+                // und den blinkenden LEDs im KOMBI eh sofort sieht)
+                //resultSets = ediabas.ResultSets;
+                //if (resultSets != null && resultSets.Count >= 2)
+                //{
+                //  EdiabasThread.MergeResultDictionarys(ref resultDict, resultSets[1]);
+                //}
+                
+                // Ablaufvariable wieder zurücksetzen, sonst würde dieser Befehl nun bei jedem weiteren Durchlauf ausgeführt werden...
+                set_LLA_50 = false;
+            }
+			
+			if (set_LLA_70) {
+                ediabas.ArgString = "70";
+                ediabas.ArgBinaryStd = null;
+                ediabas.ResultsRequests = "JOB_STATUS";
+                ediabas.ExecuteJob("ABGLEICH_VERSTELLEN_LL_REGELUNG");
+				
+				ediabas.ArgString = "70";
+                ediabas.ArgBinaryStd = null;
+                ediabas.ResultsRequests = "JOB_STATUS";
+                ediabas.ExecuteJob("ABGLEICH_PROG_LL_REGELUNG");
+                
+                // JOB RESULT ermitteln (wird derzeit nicht weiter verwendet weil man es anhand der geänderten Daten 
+                // und den blinkenden LEDs im KOMBI eh sofort sieht)
+                //resultSets = ediabas.ResultSets;
+                //if (resultSets != null && resultSets.Count >= 2)
+                //{
+                //  EdiabasThread.MergeResultDictionarys(ref resultDict, resultSets[1]);
+                //}
+                
+                // Ablaufvariable wieder zurücksetzen, sonst würde dieser Befehl nun bei jedem weiteren Durchlauf ausgeführt werden...
+                set_LLA_70 = false;
+            }
+			
+			if (set_LLA_100) {
+                ediabas.ArgString = "100";
+                ediabas.ArgBinaryStd = null;
+                ediabas.ResultsRequests = "JOB_STATUS";
+                ediabas.ExecuteJob("ABGLEICH_VERSTELLEN_LL_REGELUNG");
+				
+				ediabas.ArgString = "100";
+                ediabas.ArgBinaryStd = null;
+                ediabas.ResultsRequests = "JOB_STATUS";
+                ediabas.ExecuteJob("ABGLEICH_PROG_LL_REGELUNG");
+                
+                // JOB RESULT ermitteln (wird derzeit nicht weiter verwendet weil man es anhand der geänderten Daten 
+                // und den blinkenden LEDs im KOMBI eh sofort sieht)
+                //resultSets = ediabas.ResultSets;
+                //if (resultSets != null && resultSets.Count >= 2)
+                //{
+                //  EdiabasThread.MergeResultDictionarys(ref resultDict, resultSets[1]);
+                //}
+                
+                // Ablaufvariable wieder zurücksetzen, sonst würde dieser Befehl nun bei jedem weiteren Durchlauf ausgeführt werden...
+                set_LLA_100 = false;
+            }
+			
+        }
+    }
+    ]]>
+    </code>
+  </page>
+</fragment>