The vncserver.lua module and accompanying example scripts are available from nodemcu-vncsever on github.com.
Modules required to be compiled into the firmware:
- net
- bit
- struct
- u8g with fb_rle display
Setting up the server
The vnc server operates on a NodeMCU socket instance which has to be prepared upfront by the user script: Establish a TCP server listening on port 5900 and call the start() function when a client connects.
vncsrv = require("vncserver")
-- Set up TCP server
srv = net.createServer( net.TCP, 120 )
srv:listen( 5900,
function( conn )
-- start VNC server with connected socket
vncsrv.start( conn, 128, 128 )
end
)
All protocol sequences are subsequently handled by the vncserver module.
Hooks for client events
Once the server exchanged all required info, it stands by and waits for messages from the client. It will delegate these to the user script via callbacks. Callback functions for the following events can be registered with vncsrv.on()
- fb_update client sent a FramebufferUpdateRequest
- disconnection client disconnected
- key client sent a KeyEvent
- pointer client sent a PointerEvent
- data_sent all queued data was sent to the client
Sending graphics to the client
Whenever the client requests a framebuffer update, the server should send a FramebufferUpdate message containing a list of rectangles. Note that vncserver only supports RRE encoding at the moment.
A rectangle tells the client which area of the display is affected and what is the background color of this region:
vncsrv.rre_rectangle( base_x, base_y, width, height, num_subrectangles, background )
The following sub-rectangles (if any) define the regions with different colors. They are specified relative to the surrounding rectangle:
vncsrv.rre_subrectangle( rel_x, rel_y, width, height, color )
Example from rectangles.lua:
function draw_rectangles()
-- FramebufferUpdate message indicating that 1 rectangle description follows:
vncsrv.update_fb( 1 )
-- Next is the rectangle in RRE encoding, 4 sub-rectangles will follow:
vncsrv.rre_rectangle( 0, 0, 128, 128, 4, 0 )
-- The sub-rectangles:
vncsrv.rre_subrectangle( 10, 10, 30, 10, red )
vncsrv.rre_subrectangle( 50, 20, 20, 40, green )
vncsrv.rre_subrectangle( 80, 80, 40, 40, blue )
vncsrv.rre_subrectangle( 60, 50, 30, 50, yellow )
end
For more advanced graphics there's an integration with the u8g library. Add the virtual RLE framebuffer display into the firmware and render any u8g script on the VNC client (see u8g_vnc.lua for details):
disp = u8g.fb_rle( drv_cb, srv_width, srv_height )