Änderungen

VNC Server Protokoll verstehen

3.033 Byte hinzugefügt, 01:27, 20. Nov. 2023
== Hintergrund ==
Das VNC Protokoll eignet sich gut, um es auch bei Microcontrollern mit Netzwerkzugang wie z.B. den ESP32 / ESP8266 zu nutzen. Damit lassen sich Bildschirminhalte von Displays in Echtzeit übertragen, was bei der Entwicklung von Nutzen sein kann. Sogar "Headless" Anwendungen sind denkbar, also grafische Anwendungen auf dem ESP laufen lassen, der selbst kein Display hat, wo die Steuerung dann ausschließlich über VNC erfolgt.
 
[https://github.com/hackffm/ESP32_VNCServer Arduino/PlattformIO Beispiel auf Github]
== Protokoll ==
Im Fernsteuerungsmodus sind die Nachrichten über das erste Byte, das Type-Byte kodiert. Es gibt allerdings keine direkte Info, wie lang ein Paket ist. Damit der Server die Nachrichten auseinander nehmen kann, muss er auch für die einfachste Implementierung zumindest die folgenden Nachrichtentypen soweit parsen können, dass er die Längen richtig einliest:
==== Client-Server Nachrichten ====
{| class="wikitable"
|-
| ClientCutEvent
| variable Länge
|}
 
==== Server-Client Nachrichten ====
Für den Server ist die Sache einfacher, es gibt zwar 4 verschiedene Nachrichten (FramebufferUpdate, SetColorMapEntries (nur bei Paletten Farbformat), Bell und ServerCutText), aber eigentlich macht '''FramebufferUpdate''' die ganze Arbeit.
 
Die FramebufferUpdate-Nachricht kann verschiedene rechteckige Bereiche mit neuen Bilddaten auffrischen und dazu verschiene Codierungen nutzen. Die Kodierungen werden über SetEncodings abgeglichen, aber für die Einfachstimplementierung geht immer die RAW-Kodierung, die einfach die Rohdaten ohne Kompression allerdings im jeweils aktuellen PIXEL_FORMAT überträgt.
 
=== PIXEL_FORMAT ===
Wie schon oben erwähnt kann der Client jederzeit über eine SetPixelFormat-Nachricht das aktuelle PIXEL_FORMAT verändern - und zumindest RealVNC macht davon auch Gebrauch. Daher muss auch eine Einfachimplementation hier adequat reagieren.
 
==== Bits-per-Pixel ====
Die Zahl in diesem Byte bestimmt, wie viele Bytes pro Pixel übertragen werden. Lauf RFC sind hier genau die folgenden drei Werte erlaubt:
# 8 (true-color-flag beachten)
# 16 (big-endian-flag beachten)
# 32 (big-endian-flag beachten)
 
Obwohl eine Farbtiefe von 24 Bit nicht unüblich ist, werden hierzu immer 32 Bit (= 4 Byte) übertragen. Eine 3 Byte Übertragung ist nicht vorgesehen.
 
==== Depth ====
In diesem Byte wird die echte Farbtiefe übertragen. Allerdings scheint das den Client nicht soviel zu interessieren...
 
==== Big-Endian-Flag ====
Ist Bits-per-Pixel größer als 8 bestimmt das Flag die Reihenfolge mit der die Bytes übertragen werden. Da der Client hier freie Wahl hat, muss auch der Einfach-Server hier beide Varianten unterstützen.
 
==== True-Color-Flag ====
Wenn dieses Flag gesetzt ist, wird nicht mit Farbpaletten gearbeitet sondern mit MAX und SHIFT-Werten für die Farben. Ich habe zumindest nicht beobachet, dass der Client dieses Bit anders setzt als bei der initialen Aushandlung vom Server vorgegeben. Für die einfache Implementation setze ich daher dieses Bit in der Server-Nachricht und benötige dann keine Farbpaletten-Nachrichten mehr.
 
==== Max und Shift Werte ====
Im True-Color-Modus werden diese Werte vom Client für alle drei Farbkomponenten übergeben und bestimmen, wie die Farbe übertragen wird. Für 24 Bit Farbtiefe werden je 8 Bits pro Farbe genommen. In der Einstellung "LOW" bei RealVNC wurde die Farbtiefe auf 2 Bit pro Farbe vom Client reduziert. Die PIXEL_FORMAT Nachricht wurde in diesen Fällen wie folgt bestückt:
{| class="wikitable"
|-
! Type
! Description
! Je 8 Bit pro Farbe
! Je 2 Bit pro Farbe
|-
| U8
| bits-per-pixel
| 32
| 8
|-
| U8
| depth
| 24
| 6
|-
| U8
| big-endian-flag
| 0
| 0
|-
| U8
| true-color-flag
| 1
| 1
|-
| U16
| red-max
| 255
| 3
|-
| U16
| green-max
| 255
| 3
|-
| U16
| blue-max
| 255
| 3
|-
| U8
| red-shift
| 16
| 4
|-
| U8
| green-shift
| 8
| 2
|-
| U8
| blue-shift
| 0
| 0
|}
1.955
Bearbeitungen