wie muss ich den Pfad auf einem Raspberry Pi korrekt angeben, damit ich (zunächst einmal) die Größe der Datei Test.tft im Verzeichnis /tmp ermitteln kann?
<?
// Übertragung Projektfile *.tft zum Display via IPS und serieller Schnittstelle
// Version 0.1 vom 18.09.2016
// Thomas Unger (elektroniktommy)
// tommyunger@freenet.de
//
//
//
// Quelle: https://www.itead.cc/blog/nextion-hmi-upload-protocol
//
// Step 1. Find your serial port
// In order to set up a serial connection between Nextion and your MCU, first you have to find which serial port is Nextion connected to, and figure out the connection parameters. If you know it, skip step 1.
// Send an instruction string in different connection parameters.
//
// connect
//
// Nextion will return data If you choose right serial port and connection parameters.
// For example, NX4024T032_011R will return below 8 groups datas. The datas are separated by comma.
// comok 1,101,NX4024T032_011R,52,61488 /*[Objekt #61488 existiert nicht]*/,D264B8204F0E1828,16777216
//
// Here’s the explanation.
// comok: handshaking protocol is setup.
//
// 1: Nextion model with touch panel
// 0: Nextion model without touch panel
// 101: Reseved
// NX4024T032_011R: Nextoin device model
// 52: Firmware version
// 61488: MCU code
// D264B8204F0E1828: Nextion device serial number
// 16777216: FLASH Size(byte)
//
// Note 1: It’s suggested to send an empty instruction before the connect instruction.
// Note 2: Delay (1000000/baud rate)+30ms between each attempt. If you try 9600bps, you should delay 1000000/9600+30=134ms
//
// Step 2. Upload firmware
//
// Now you know the serial port and current baud rate, you can send the upload command.
//
// whmi-wri filesize,baud,res0
//
// filesize: fileszie of the tft file (byte)
// baud: baud rate
// res0: reserved, you can fill with any ASCII character
//
//Nextion device will return 0x05 in 500ms, you can send tft bin file to the serial port after you receive it. You should split the data in 4096 byte each packet. And send all the remains data (<4096byte) in the last packet. Nextion device will return 0x05 when all data received.
//
//SPRT_SendText(30767 /*[Serial Port]*/, "\x00\x00\xFF\xFF\xFF"); // Empty Command
//SPRT_SendText(30767 /*[Serial Port]*/, "\xFF"); // Empty Command
//return;
//SPRT_SendText(30767 /*[Serial Port]*/, "connect"."\xFF\xFF\xFF" ); // Display ermitteln
//
// Dateigrösse feststellen
$Nametft = "Raumdisplay.tft";
$localDir = IPS_GetKernelDir()."\\Daten_Nextion\\";
$Datei = $localDir.$Nametft;
$Blockposition = GetValue(56354 /*[Nextion Display\Firmware_Upload_Nextion\Block Position]*/);
$Dateigroesse = filesize($Datei);
$Blockgroesse = 4096;
//
// Erster Start manuell
// Dateigröße ermitteln und Variablen auf Start initialisieren
// Display Kommando senden
//
if($_IPS['SENDER'] == "Execute")
{
SetValue(43305 /*[Nextion Display\Firmware_Upload_Nextion\Dateigroesse]*/,$Dateigroesse);
SetValue(56354 /*[Nextion Display\Firmware_Upload_Nextion\Block Position]*/,0);
SPRT_SendText(30767 /*[Serial Port]*/, "whmi-wri ".$Dateigroesse.",9600,0"."\xFF\xFF\xFF" ); // Kommando zum senden des TFT-Files
}
//
// Wenn über Registervariable getriggert wird dann senden der einzelnen Blöcke
//
if ($_IPS['SENDER'] == "RegisterVariable")
{
// bereits im Puffer der Instanz vorhandene Daten in $data kopieren
$data = RegVar_GetBuffer($_IPS['INSTANCE']);
// neu empfangene Daten an $data anhängen
$data .= $_IPS['VALUE'];
if ((strtohex($data[0])=="05")) // Ack vom Display wenn Block im Flash gespeichert wurde oder Display Ready!!
{
// $data = "";
// RegVar_SetBuffer($_IPS['INSTANCE'], $data);
If (($Blockposition + $Blockgroesse) > $Dateigroesse )
{
$Blockgroesse = $Dateigroesse - $Blockposition;
}
$handle = fopen ($Datei, "rb");
fseek($handle, $Blockposition);
$inhalt = fread($handle, $Blockgroesse);
SetValue(56354 /*[Nextion Display\Firmware_Upload_Nextion\Block Position]*/,$Blockposition+$Blockgroesse);
SPRT_SendText(30767 /*[Serial Port]*/, $inhalt);
fclose($handle);
}
}
function strToHex($string)
{
$hex='';
for ($i=0; $i < strlen($string); $i++)
{
$hex .= dechex(ord($string[$i]));
}
return $hex;
}
?>
IPS läuft da wo es nun mal läuft, der Raspberry Pi läuft irgendwo anders (lediglich das aktuelle Jessie + PIGPIO in der aktuellen Version erforderlich), alles wird vom zentralen IPS gesteuert.
Viele der aufgezählten Funktion laufen aktuell in meinem Projekt „Mein Bett bekommt eine IP“…
Möglicher Grund: Ich habe sehr viele Meldungen (IPS_LogMessage) in den Code integriert, um zu sehen was passiert. Ich habe zwischen die einzelnen Datensendungen - die ich auf 1024 Bytes begrenzt habe - inzwischen ein IPS-Sleep von 750 gesetzt.
Ein Anfang ist gemacht. Muss jetzt mal sehen, was man da noch verbessern könnte.
Hier mal der relevante Codeausschnitt:
If (($this->GetBuffer("Update") == true) AND ($ByteResponse[1] == "05")) {
// Update starten
// Datei öffnen und einlesen
IPS_LogMessage("IPS2GPIO Display","Öffnen der Update-Datei");
$handle = fopen($this->GetBuffer("FileName"), "r");
$contents = fread($handle, $this->GetBuffer("FileSize"));
fclose($handle);
// Datei in Einheiten <4096 Bytes teilen
$contentarray = str_split($contents, 512);
for($i=0; $i<Count($contentarray); $i++) {
$Message = utf8_encode($contentarray[$i]);
IPS_LogMessage("IPS2GPIO Display","Senden Datenpaket ".$i." von ".Count($contentarray));
$this->SendDataToParent(json_encode(Array("DataID"=> "{A0DAAF26-4A2D-4350-963E-CC02E74BD414}", "Function" => "write_bytes_serial", "Command" => $Message)));
IPS_Sleep(750);
}
$this->SetBuffer("Update", false);
}
Darum SendDebug… Dann verliert sie die Verbindung nur wenn der Debug-Reiter offen ist.
Habe ich auch sehr oft. Aber ein Sleep solltest du auf keinen Fall einbauen, dann bremst du ja im Datenaustausch alles aus.
Michael
gestern war mein Ziel, das Ganze überhaupt erst einmal zum Laufen zu bekommen. Weil es so nicht funktionierte, habe ich mit dem IPS_Sleep und der Datenpaketgröße experimentiert.
Der Weg ist ja etwas „länger“:
Die Daten werden in der Instanz geteilt,
dann per JSON zur Splitter-Instanz,
von da aus über den „eigenen“ Client Socket über WLAN an den PIGPIO-Server
und dann endlich über die seriellen Schnittstelle zum Nextion Display.
Neben dem Problem das sich die Konsole immer im Laufe der Übertragung abmeldete, sah ich in den Meldungen dass es nach kurzer Zeit eine Fehlermeldung vom PIGPIO-Server gab. Da kann ich nur vermuten, dass die Daten viel schneller ankamen, als er sie zum Display übertragen konnte.
Auf dem Display war aber ersichtlich, das weiterhin Daten ankamen, jedoch brach der Prozess irgendwann unvollendet ab.
Da das Datenpaket nur geteilt wird, kommt eine Bestätigung der erfolgreichen Datenübertragung vom Display erst nach Ankunft der gesamten Daten.
Insgesamt muss also auch an der Baustelle noch gearbeitet werden, das Prinzip funktioniert aber. Es ist m.E. an wichtiger Meilenstein, um das Display im Betrieb mit neuer Software zu versehen ohne es an den Windows-Rechner auf dem der Editor läuft anzuschließen oder die Micro-SD-Karte zu nutzen. Wenn das Display erst einmal formschön eingebaut ist, kann das beliebig kompliziert und zeitaufwendig sein…
Aus Unkenntnis hatte ich zunächst angefangen an allen für mich wichtigen Stellen einen Eintrag bei den Meldungen zu programmieren (kommentiere die „Positiv-Meldungen“ aber nach erfolgreichem Test aus). In der Dokumentation hatte ich zu dem Hinweis mit SendDebug nichts gefunden (habe es gerade noch mal probiert, fehlt wohl noch in der Dokumentation). Werde mich aber bei Gelegenheit mal dieser Fleißaufgabe widmen…
Hallo Joachim, hast du schon erfolgreich ein gesamtes File zum Display übertragen? Sendest du alles in einer Schleife, oder triggerst du nach jedem 4096 Byte-Block auf „05“? Ich musste die Datei zusätzlich mit der Option „b“ öffnen, sonst fehlt immer ein Byte pro Block! Das wundert mich jetzt!
…ja, das Update wurde vollständig übertragen und lief selbständig los. Die „05“ kommt nur einmal als Startsignal, danach kann es offensichtlich in beliebig kleine Blöcke <4096 Bytes geteilt werden - ohne eine besondere Kennung.
Probleme gab es wie schon oben beschrieben mit der Konsole und das die Datenflut möglicherweise PIGPIO etwas überfordert hat.
Den relevanten Codeausschnitt habe ich ja schon gepostet.
Und das Display sagt am Ende 100% und Fehlerfrei? Also bei mir kommt nach jedem Block ein „05“. Das Display speichert jeden Block in seinen Flash nach dem Empfang ab und erst dann sendet es „05“! Wenn es geht, okay! Wundere mich halt, da es bei mir so nicht funktioniert hat!
Tommy
…was am Ende im Display stand, kann ich nicht sagen - war irgendwann dann wieder „online“ und das Update war da.
Wenn er nach jedem Block (woher soll das Display wissen, dass dieser jetzt abgeschlossen ist?) ein „05“ senden würde, dann würde mein Skript ja nach jedem Block-Abschluss einen neuen Trigger (Trigger ist die „05“ und dass das Update durchgeführt werden soll) bekommen. Da dieses so nicht zu beobachten war, würde ich das mal ausschließen…
Steht so ja auch nicht in der Dokumentation von Nextion.
Ich habe das Protokoll von meinem Programm und das vom Editor im Vergleich mit einem Portsniffer angesehen und kann bestätigen, dass die Kennung, bei beiden nach jedem 4096 Byte Block kommt! Wenn man genau aufs Display schaut flackert es kurz beim Flashen nach jedem Block. Das Display weiß wann der Block zu Ende ist, es zählt mit! Die Doku ist meiner Meinung nach nicht ganz Exakt da der Originale Editor zum Beispiel vor und zwischen den Befehlen „connect“ und Update immer noch ein „Empty“ -> „\x00\x00\xFF\xFF\xFF“ sendet! Schau dir einfach mal die Antworten des Displays an! Wie gesagt wenn es geht ist es okay, nur das du später nicht doch noch Timingprobleme bekommst! Tommy