Zum Thema Hyundai: https://stackoverflow.com/questions/57306799/how-to-decode-obd-2-data-from-hyundai-ioniq-ev
Die Ausgabe aus meinem Tool passt wohl so. Nur kommt da als Rückgabe nicht "41" sondern die IDs der Steuergeräte "7EC" und dann die Nutzdaten.
Ich habe das Gefühl die Jungs bei Hyundai wollen nicht dass man "rumschnüffelt" und selbst irgendwas "baut" für den OBD Port.
Gruß
trekki
@trib...
Ich bin jetzt schlauer. Ich habe das eben an dem gewünschten anderen Auto ausprobiert. Da funktioniert alles wie es soll!
Ich gebe ein: 01 5C (Öltemperatur °C)
und erhalte: 41 5C XX
Ich gebe ein: 01 2f (Tankinhalt %)
und erhalte: 41 2f XX
Ich gebe ein: 01 46 (Außentemperatur °C)
und erhalte: 41 46 XX
Die bei Hyundai müssen irgendwas anders machen... Keine Ahnung.
Da ich die Werte nicht im Millisekundenbereich abfragen will, reicht mir hier alle 10 Sekunden. Ich verbinde das einfach mit einem Timer. Für meine kleine "Quick and Dirty" Lösung reicht mir das.
Danke an alle, für den letzten Denkanstoß. 😉
Bzgl. Puffer werde ich mir dann noch mal ansehen.
VG
trekki
Hallo Trib,
danke für deine ausführliche Nachricht!
In der Zwischenzeit (vor deinem Post) habe ich ein wenig rumprobiert.
Als ich das Thread.Sleep eingebaut hab, wurden die Daten nicht mehr zerstückelt und ich kann die einzelnen Einträge als items in einer Liste speichern wo man dann das Analysieren anfangen könnte:
Thread.Sleep(500);
var serialPort = (SerialPort)sender;
int buffSize = 4096;
byte[] bff = new byte[buffSize];
string data = string.Empty;
data += System.Text.Encoding.Default.GetString(bff, 0, serialPort.Read(bff, 0, buffSize));
data_list = data.Split(new char[] { '\r' }, StringSplitOptions.RemoveEmptyEntries);
foreach (string d in data_list)
{
if (txt_filter.Text != "")
{
if (d.Contains(txt_filter.Text)) txt_receive.AppendText(d + "\n");
}
else
{
txt_receive.AppendText(d + "\n");
}
}
txt_receive.SelectionStart = txt_receive.Text.Length;
txt_receive.ScrollToCaret();
}
Habe jetzt nach deinem Post die einzelnen AT Kommandos mal ausprobiert.
Ich habe jetzt alles ausgeschaltet, also AT x0 und erhalte diese Nachrichten wie im hier zu sehen. Woher kommen denn immer noch diese 0:, 1:, 2: usw.?
15:59:53 - Befehl: 2101
7F2112
016
0:6101FFE00000
01E
0:6101000003FF
03D
0:6101FFFFFFFF
033
0:6101FFFFFBC0
1:09215A06061103
1:0C38004299D538
2:00000000E37534
1:BB172426480300
1:00023202320204
2:0000000A002502
3:04200000000000
2:040F530E0E0E0E
2:00007D003501BC
3:3D041939D0FFD0
3:05C04100000000
3:0E0E0E000FCC44
4:FF610000000000
4:00000000600000
4:CC010000900002
5:000001F4000001
5:3BEC00023AA900
6:A5000000000000
6:00D4300000CCD4
7:05BD0000000000
7:008371D60D0188
8:0000000003E800
>
Die PID 2101 - 2105 werden dazu genutzt um die einzelnen Batteriezellenspannungen auszulesen (sollte halt mir nur als Beispiel dienen um die Thematik grundsätzlich zu verstehen). Als Testobjekt nutze ich meinen Hyundai IONIQ electric. Der kann nämlich die ganze Zeit ohne Probleme eingeschaltet in der Garage stehen. 😄
Das ATH1 hatte ich mit Absicht gesetzt, da ohne die Header nicht ersichtlich ist von welchem Steuergerät die Daten kommen, so viel mir das Filtern leichter.
Gruß
trekki
Hallo Martin, ach Gott ist das peinlich X(
Ich haue ja bei Putty schön auf ENTER... Danke. dafür!
Jetzt kommen die Ergebnisse. Ich habe anscheinend jetzt noch ein Formatierungsproblem. Wie bekomme ich denn jetzt die CAN Messages als Byte Array in eine Liste um die zu analysieren? Er spuckt mir die ja teilweise zerhackt oder an einem Stück aus...
Liegt es eventuell an der Methode wie ich die Daten hole?
serialPort.ReadExisting();
Muss ich hier wie bei der Eingabe prüfen ob ein CRLF dazwischen liegt?
VG
trekki
Hallo und guten Morgen!
Ich habe mir mal wieder ein kleines Hobbyprojekt auferlegt.
Ziel ist es, mir eine eigene Multimediaoberfläche im Star Trek Stil (LCARS) zu bauen. Eingebaut wird das ganze im Doppel-DIN Schacht meines Kfz (Subaru BRZ, BJ. 2016).
Ich möchte auch weiterhin einige Live Werte meines Kfz über die OBD Schnittstelle auslesen. Dabei ist mir inzwischen bewusst wie das mit dem CAN BUS funktioniert. Ich schicke einen Request und das entsprechende Steuergerät antwortet.
Folgende Werte möchte ich dann auf meiner eigenen Oberfläche darstellen (Balkendiagramme usw.):- Außentemperatur (°C)
Am OBD Port meines Kfz steckt ein OBDII Bluetooth Modul, dass bereits mit einer Android App aus dem Playstore wunderbar zusammenarbeitet und ich bekomme auch die oben genannten Werte ausgelesen. Also grundsätzlich funktionell.
Ich habe dann den OBD Adapter mit meinem PC verbunden. Registriert hat sich der Dongle auf COM4. Habe mir eine kleine Test GUI geschrieben, die mir serielle Kommunikation ermöglicht. An der Stelle habe ich jetzt mein Problem. Wenn ich das Ganze mit Putty steuere, bekomme ich entsprechend korrekte Antworten zurück. Gebe ich beispielsweise den Befehl "ATZ" ein bekomme ich die ELM Version zurückgeliefert. Mache ich das mit meinem Tool, dann bekomme ich nur "?>". Wenn ich jedoch mit einem COM Port Emulator zwei Ports paare und schicke in Putty etwas los, kommt es in meinem Tool ohne Probleme an.
Anbei meine Methoden zum Senden und Empfangen:
private void btn_send_Click(object sender, EventArgs e)
{
if (port.IsOpen == true) port.Write(txt_send.Text);
else txt_receive.AppendText(DateTime.Now.ToLongTimeString() + " - Port ist nicht geöffnet!\r\n");
}
private void port_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
var serialPort = (SerialPort)sender;
var data = serialPort.ReadExisting();
txt_receive.AppendText(DateTime.Now.ToLongTimeString() + " - " + data + "\r\n");
}
Anbei habe ich noch einen Screenshot um zu verdeutlichen was ich meine. Wäre über einen Denkanstoß sehr dankbar.
VG
trekki
Danke für eure guten Tipps!
Konnte es jetzt zu meiner Zufriedenheit lösen.
Das Pattern sieht folgendermaßen aus:
(STRING) - |((U_|U_TEW-)STRING)$
VG
trekki
Hallo liebe Gemeinde,
es ist gar nicht so leicht einen Titel für einen RegEx Thread zu finden 😉
Habe folgende Konstellation an Daten (AD-Gruppen):
DBG_Q-A - Abteilung ABCDEFGH DBG_Q-A-F - Abteilung ABCDEFGH DBG_Q-A-F1 - Abteilung ABCDEFGH DBG_Q-A-M - Abteilung ABCDEFGH U_Q-A U_Q-A-F U_Q-A-F1
Suchstring ist: Q-A-F
Pattern ist: (Q-A-F)\W|(Q-A-F)$
Herauskommen die Gruppen:
DBG_Q-A-F - Abteilung ABCDEFGH U_Q-A-F
Soweit so gut. Suche ich jetzt aber nach "Q-A" um diese Gruppen zu bekommen:
DBG_Q-A - Abteilung ABCDEFGH U_Q-A
Zeigt er mir ALLE die "Q-A" im Namen haben und nicht nur die zwei die ich eigentlich will.
Habe mit dem RegEx Tester von https://regex101.com/ schon ewig rumprobiert, aber komme zu keiner Lösung. Ist meine Anforderung überhaupt umzusetzen? Geht's vielleicht auch ohne RegEx?
Wäre für Denkanstöße dankbar.
PS: Ich prüfe immer nur einen Gruppennamen mit dem Pattern. Ich habe eine Liste aus Strings mit den ganzen AD-Gruppennamen. Iteriere die mit foreach durch und prüfe mit dem String ob die meinen Kriterien entspricht. Ist also nicht Multiline.
VG
trekki
@pinki: Exit Befehl hört sich schon mal gut an... Ich rufe mit dem Process.Start ja cmd.exe und die Argumente auf. Da steht kein exit dann irgendwo. Der Befehl, wie z.B. mkdir wird ja abgesendet und gleich umgesetzt. Ich kenn das aus Skriptdateien mit dem Exit damit die Konsolenfenster sich schließt. Muss ich mal näher untersuchen.
@Abt: Was spricht dagegen wenn es nur eine Intranetanwendung ist? Außerdem kann ich doch dem IIS App Pool jeden Nutzer zuweisen den ich will? Wird dann in diesem Nutzerkontext ausgeführt.
Gruß
trekki
Ich habe es noch mal etwas umgeschrieben, aber das Ergebnis ist genau das Gleiche, außer dass er nun bei
p.WaitForExit();
hängt.
Hier die andere Version:
protected void btn_execute_Click(object sender, EventArgs e)
{
try
{
var command = (from TOOLBOX
in ADWM_DB_SETTINGS.TOOLBOX
where TOOLBOX.AKTION == ddl_command.SelectedValue.ToString()
select TOOLBOX).First();
string ex_command = command.ARGUMENTE;
if (txt_host.Text != "") ex_command = ex_command.Replace("%HOST%", txt_host.Text);
if (txt_arguments.Text != "") ex_command = ex_command.Replace("%PARAMETER%", txt_arguments.Text);
ex_command = ex_command.Replace("%USERNAME%", adw.GET_SETTING("EWS_USER"));
ex_command = ex_command.Replace("%PASSWORD%", adw.GET_SETTING("EWS_PASSWORD"));
Process p = new Process();
p.StartInfo.UseShellExecute = false;
if (File.Exists(Path.Combine(HttpContext.Current.Request.PhysicalApplicationPath, @"Scripts\PStools\", command.PROGRAMM)))
{
p.StartInfo.FileName = Path.Combine(HttpContext.Current.Request.PhysicalApplicationPath, @"Scripts\PStools\", command.PROGRAMM);
}
else
{
p.StartInfo.FileName = command.PROGRAMM;
}
p.StartInfo.Arguments = ex_command;
p.StartInfo.RedirectStandardOutput = true;
p.StartInfo.RedirectStandardError = true;
p.StartInfo.CreateNoWindow = true;
p.OutputDataReceived += new DataReceivedEventHandler(proc_OutputDataReceived);
p.ErrorDataReceived += new DataReceivedEventHandler(proc_OutputDataReceived);
p.Start();
p.BeginOutputReadLine();
p.WaitForExit();
/*StreamReader sr = p.StandardOutput;
StreamReader sr_err = p.StandardError;
string output = sr.ReadToEnd();
string output_err = sr_err.ReadToEnd();
p.WaitForExit();*/
/*if (output != "") txt_console_ouput.Text = output;
else txt_console_ouput.Text = output_err;*/
}
catch (Exception ex)
{
outputData.Append(ex.Message);
}
finally { txt_console_ouput.Text = outputData.ToString(); }
}
protected void proc_OutputDataReceived(object sender, DataReceivedEventArgs e)
{
if (e.Data != null)
{
outputData.AppendLine(e.Data.ToString());
}
}
Gruß
trekki
[ASP.NET]
[C#]
Hallo liebes Forum,
ich habe eine interne Webanwendung die verschiedene Prozesse starten kann.
Ich nutze hier die PStools für z.B. Abfragen welche Benutzer gerade an einem Host angemeldet sind etc.
Nun soll das Ganze flexibel sein, sodass man eigene Skripts zur Datenbank hinzufügen kann und eine Art Script Sammlung bekommt. Soll uns Admins die Arbeit ein wenig abnehmen.
Solange ich das mit den PStools mache funktioniert alles wie gewünscht. Ich erhalte nach dem abgesetzten Befehl auch den Output. Gebe ich nun das Programm "cmd.exe" an und übergebe Parameter bekomme ich von meiner Website keinen Response mehr und die Ladeanimation dreht sich zu Tode. Er hängt genau bei
string output = sr.ReadToEnd();
fest.
Ich hoffe ihr habt eine Idee.
Ich steige nicht ganz dahinter warum die CMD sich so anders verhält... Probiere schon seit Stunden 😦
Hier mein Code wie ich die Prozesse starte:
protected void btn_execute_Click(object sender, EventArgs e)
{
try
{
var command = (from TOOLBOX
in ADWM_DB_SETTINGS.TOOLBOX
where TOOLBOX.AKTION == ddl_command.SelectedValue.ToString()
select TOOLBOX).First();
string ex_command = command.ARGUMENTE;
if (txt_host.Text != "") ex_command = ex_command.Replace("%HOST%", txt_host.Text);
if (txt_arguments.Text != "") ex_command = ex_command.Replace("%PARAMETER%", txt_arguments.Text);
ex_command = ex_command.Replace("%USERNAME%", adw.GET_SETTING("EWS_USER"));
ex_command = ex_command.Replace("%PASSWORD%", adw.GET_SETTING("EWS_PASSWORD"));
Process p = new Process();
p.StartInfo.UseShellExecute = false;
if (File.Exists(Path.Combine(HttpContext.Current.Request.PhysicalApplicationPath, @"Scripts\PStools\", command.PROGRAMM)))
{
p.StartInfo.FileName = Path.Combine(HttpContext.Current.Request.PhysicalApplicationPath, @"Scripts\PStools\", command.PROGRAMM);
}
else
{
p.StartInfo.FileName = command.PROGRAMM;
}
p.StartInfo.Arguments = ex_command;
p.StartInfo.RedirectStandardOutput = true;
p.StartInfo.RedirectStandardError = true;
p.StartInfo.CreateNoWindow = true;
p.Start();
StreamReader sr = p.StandardOutput;
StreamReader sr_err = p.StandardError;
string output = sr.ReadToEnd();
string output_err = sr_err.ReadToEnd();
p.WaitForExit();
if (output != "") txt_console_ouput.Text = output;
else txt_console_ouput.Text = output_err;
}
catch (Exception ex)
{
txt_console_ouput.Text = ex.Message;
}
}
Grüße
trekki