-->
Page 1 of 1

A VNC server for Lua on NodeMCU

PostPosted: Wed Dec 28, 2016 5:35 am
by devsaurus
This is a VNC server framework for Lua on NodeMCU. It implements a basic subset of the RFB protocol and enables Lua scripts to send graphics via TCP connection to a VNC client on PC or smartphone. It was inspired by pylotron which demonstrates the simplicity of graphical interaction between an embedded system and a smart client via VNC.

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.

Code: Select allvncsrv = 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()


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:

Code: Select allvncsrv.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:

Code: Select allvncsrv.rre_subrectangle( rel_x, rel_y, width, height, color )

Example from rectangles.lua:

Code: Select allfunction 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):

Code: Select alldisp = u8g.fb_rle( drv_cb, srv_width, srv_height )