Link here

Forth Remote Front Panel Demo for QScreen / QVGA Controller

Create a web-enabled instrument with a clickable remote front panel GUI

This Forth demonstration program is meant for use with the QVGA (Legacy) or QScreen Controller SBC's sold by Mosaic. This source code provides a web enabled remote access control panel for controlling the instrument. This demonstration is compatible with both the WiFi Wildcard and Ethersmart Wildcard. The demonstration serves a pixel-accurate clickable version of the screen image.

 

Forth Source Code

forth remote front panel demo

\ this demonstration code is provided in source form.
\ Top level functions:
\    Ether_GUI_Web_Demo ( -- ) \ no input parameters; runs gui and web page on EtherSmart WC
\    WiFi_GUI_Web_Demo ( -- ) \ no input parameters; runs gui and web page on WiFi WC
 
\ ******************* SET MEMORY MAP HERE (IF IT'S NOT ALREADY SET) ****************
 
 
\ ************** USEFUL CONSTANTS **************
 
HEX        \ rest of file in hex base
400 CONSTANT TASK_SIZE        \ 0x400 = decimal 1024 = 1Kbyte = task size
 
\ 0D0A CONSTANT CRLF_ASCII    \ this is the standard eol sequence for tcp/ip services.
 
\ *************** IMPORTANT: SET MODULENUM TO MATCH HARDWARE JUMPERS ******************
 
\ recall: modulenum 0 is reserved on the QScreen!
 
FIND E_MODULENUM    \ don't redefine if already defined in a prior file
IFTRUE
XDROP
OTHERWISE
4 CONSTANT E_MODULENUM    \ ******** SET THIS TO MATCH HARDWARE JUMPERS J1 AND J2! *****
ENDIFTRUE
\ This specifies the modulenum for the high level functions in this file
\ except for Ether_Monitor_Demo (see its comments).
 
\ If EtherSmart/WiFi is installed on module bus 0, E_MODULENUM = 0, 1, 2, or 3
\ If EtherSmart/WiFi is installed on module bus 1, E_MODULENUM = 4, 5, 6, or 7
\ That is, the bus specifies the top bit of a 3-bit modulenum,
\ and [J2, J1] specifies the remaining 2 bits of the modulenum.
\ Example: On module bus 0, if neither jumper cap is installed: E_MODULENUM = 0
\ Example: On module bus 0, if both jumper caps are installed: E_MODULENUM = 3
\ Example: On module bus 1, if J2 is installed but J1 is not: E_MODULENUM = 6
 
 
\ ************** SETUP ETHERNET TASK TO RUN WEB AND TUNNELING SERVICES **************
 
 
TASK_SIZE V.INSTANCE:     ether_control_task  \ 1 Kbyte per task area
 
: Ether_Task_Setup_Default    ( -- )
\ performs full initialization of the ether_info struct and mailboxes for the
\ specified EtherSmart modulenum, and
\ builds and activates an ethernet control task to service the xport
\    (STATUS) NEXT.TASK ! \ empty the task loop; comment out if other tasks are allowed
    ether_control_task DROP E_MODULENUM    ( taskbase_addr\modulenum -- )
    Ether_Task_Setup                    ( -- )
;
 
: WiFi_Task_Setup_Default    ( -- )
\ performs full initialization of the ether_info struct and mailboxes for the
\ specified WiFi modulenum, and
\ builds and activates an ethernet control task to service the xport
\    (STATUS) NEXT.TASK ! \ empty the task loop; comment out if other tasks are allowed
    ether_control_task DROP E_MODULENUM    ( taskbase_addr\modulenum -- )
    WiFi_Task_Setup                    ( -- )
;
 
\ *********************** WEBSERVER ***************************
 
 
\ REMOTE FRONT PANEL (QVGA benchmark: 11 seconds from mouse click to new screen image)
 
FIND }$        \ define ram location
IFTRUE         \ if V6.xx kernel...
    XDROP
    8000 14
OTHERWISE
    0 2        \ V4.xx..
ENDIFTRUE
XCONSTANT BITMAP_BUFFER
8000 CONSTANT BITMAP_MAXBYTES    \ 32K max, plenty for monochrome displays
 
 
1 CONSTANT BITMAP_SCREEN_FORMAT
 
\ the following is now created using the Image Converter program which creates 2 constants:
\ GUI_RESPONSE_TEXT_HTML_XADDR
\ GUI_RESPONSE_TEXT_HTML_SIZE
 
\ CREATE GUI_RESPONSE_TEXT    \ cfa.for GUI_RESPONSE_TEXT to obtain lbuffer xaddr
\ DP  -1 CRLF_ASCII ASCII $        ( xpointer.to.result.area\max.chars\EOL\delim--)
\ LPARSE
\ <html><head><title>EtherSmart/GUI Remote Front Panel</title></head>
\ <body>
\ <H3>EtherSmart/GUI Remote Front Panel</H3><p>
\ <H4>Click on the screen image to operate the touchscreen remotely</H3><p><p>
\ <a href="/gui_response.cgi"><img src="/screen_image.bmp" ismap></a>
\ </body></html>
\ $        \ end of gui_response_text string
\ XDROP                ( -- ) \ drop x$addr, use cfa.for to get relocatable runtime xl$addr
\ make sure to declare gui_response.cgi as Cache-Control: no-cache (dynamic content).
\ Notes: this works very nicely with Opera, the recommended browser.
 
 
: Screen_Image_Response    ( module -- )
\ handler for /screen_image.bmp url. serves the screen image.
\ assumes that Simulated_Touch_To_Image has run.
\ xbuffer contains 32-bit count (NOTE!) followed by image data.
\ marks as no-cache (always reloads).
\ NOTE: this function is NOT a gui handler; it should be posted by http_add_handler.
    DUP HTTP_Outbuf
    LOCALS{ x&lstring_buf &module }
    x&lstring_buf &module HTTP_Outbufsize
    -1 -1 HTTP_IMAGE_BITMAP_CONTENT     ( xlbuf\maxbufsize\ok\dynamic\content_id--)
    HTTP_Put_Headers                ( -- ) \ dynamic bitmap image content
    x&lstring_buf LCOUNT &module        ( xbuf1\cnt1\mod--) \ http header in xbuf1
    HTTP_Send_Buffer DROP             ( -- ) \ drop numbytes_sent
    BITMAP_BUFFER 2XN+ LCOUNT &module    ( xbuf2\cnt2\mod--) \ 2xn+: 32-bit cnt!
    HTTP_Send_Buffer DROP             ( -- ) \ drop numbytes_sent
;
 
: GUI_Response    ( module -- )
\ a clickable ismap version of the screen image that runs the gui toolkit simulated touch.
\ url = /gui_response.cgi
\ this routine is called via ether_check_gui which runs in the application task
\ that runs Service_GUI_Events.  it is posted using http_gui_add_handler.
    DUP HTTP_Outbuf
    LOCALS{ x&lstring_buf &module }
    &module HTTP_Imagemap SWAP                ( x\y-- ) \ parses query response= ?x,y
    DUP 0<                                     \ returns -1\-1 if ?x,y is not present
    IF    2DROP                 ( -- ) \ invalid coordinates: do nothing (should never happen)
    ELSE                                    ( x\y-- )
        X>R
        BITMAP_BUFFER BITMAP_MAXBYTES BITMAP_SCREEN_FORMAT
        XR>                                 ( xlbuffer\maxbytes\format\x\y--)
        Simulated_Touch_To_Image            ( error -- ) \ if 0, image has changed
        DROP                                ( --) \ we always try to re-serve image
    ENDIF
    x&lstring_buf &module HTTP_Outbufsize
    -1 0 HTTP_TEXT_HTML_CONTENT        ( xlbuf\maxsize\ok\dynamic\content_id--)
    HTTP_Put_Headers            ( -- ) \ static html text content
    x&lstring_buf LCOUNT
    GUI_RESPONSE_TEXT_HTML_XADDR GUI_RESPONSE_TEXT_HTML_SIZE D>S
    &module                            ( xaddr_buf1\count1\xaddr_buf2\count2\module--)
    HTTP_GUI_Send_2Buffers             ( -- ) \ numbytes_sent is not returned
;
 
: Init_Screen_Image    ( -- error )
    BITMAP_BUFFER BITMAP_MAXBYTES BITMAP_SCREEN_FORMAT ( xlbuf\maxbytes\format--)
    Screen_To_Image            ( error -- ) \ if 0, image has been created
;
 
: REMOTE_PANEL_START    ( module -- )
\ serves an initial clickable ismap version of the screen image.
\ url = /remote_panel_start.html
\ puts initial version of screen into bitmap_buffer.
\ this routine is called via ether_check_gui which runs in the application task
\ that runs Service_GUI_Events.  it is posted using http_gui_add_handler
    DUP HTTP_Outbuf
    LOCALS{ x&lstring_buf &module }
    x&lstring_buf &module HTTP_Outbufsize    \ if new image, serve the page
    -1 0 HTTP_TEXT_HTML_CONTENT        ( xlbuf\maxsize\ok\dynamic\content_id--)
    HTTP_Put_Headers            ( -- ) \ static html text content
    x&lstring_buf LCOUNT            ( xbuf1\cnt1--) \ http header
    Init_Screen_Image                ( xbuf1\cnt1\error -- ) \ if 0, image has been created
    DROP                            ( xbuf1\cnt1--) \ ignore error flag
    GUI_RESPONSE_TEXT_HTML_XADDR GUI_RESPONSE_TEXT_HTML_SIZE D>S ( xbuf1\cnt1\xbuf2\cnt2--)
    &module                            ( xaddr_buf1\count1\xaddr_buf2\count2\module--)
    HTTP_GUI_Send_2Buffers             ( -- ) \ numbytes_sent is not returned
;
 
: Install_GUI_Web_Handlers    ( module -- error? )
\ call this after ETHER_Task_Setup_DEFAULT  point browser to raw ip or to
\  ip/index.html to see the home GUI web page = remote front panel.
\ urls are case sensitive.
\ any other url's serve out: page not found.
\ returns nonzero error if too many handlers were added
\ (limited by AUTOSERVE_DEFAULT_ROWS passed to ether_init)
\  Some of the gui web handlers in this example are handled by the application task.
    0 LOCALS{ &error &module }
    " /" COUNT CFA.FOR Remote_Panel_Start &module    ( url_xaddr\count\handler_xcfa\mod--)
    HTTP_Add_GUI_Handler TO &error    ( -- )
    " /index.html" COUNT CFA.FOR Remote_Panel_Start &module ( url_xaddr\count\xcfa\mod--)
    HTTP_Add_GUI_Handler &error OR TO &error    ( -- )
    " /screen_image.bmp" COUNT CFA.FOR Screen_Image_Response
    &module                    ( xadr\cnt\xcfa\mod--)
    HTTP_Add_Handler &error OR TO &error    ( -- )
    " /gui_response.cgi" COUNT CFA.FOR GUI_Response
    &module                    ( xadr\cnt\xcfa\mod--)
    HTTP_Add_GUI_Handler &error OR      ( error -- )
;
 
 
: Ether_GUI_Web_Demo    ( -- error )
    Ether_Task_Setup_Default        ( -- ) \ init EtherSmart WC, start ethernet task
    E_MODULENUM Install_GUI_Web_Handlers DROP    ( -- ) \ setup web; ignore error flag
    Gui_Demo    ( -- ) \ start the gui demo on local touchscreen
;
 
: WiFi_GUI_Web_Demo    ( -- error )
    WiFi_Task_Setup_Default                    ( -- ) \ init WiFi WC, start ethernet task
    E_MODULENUM Install_GUI_Web_Handlers DROP    ( -- ) \ setup web; ignore error flag
    Gui_Demo    ( -- ) \ start the gui demo on local touchscreen
;
 
\ NOTES: place the following function call:
\     E_MODULENUM Ether_Check_GUI DROP
\ in the application task that invokes the GUI Routine
\ (for example, after the call to Service_GUI_Events on a QVGA Controller system).
\ Add a call to Screen_Has_Changed in each GUI handler that changes screen appearance.
\ QScreen Controllers require this in the init function:  TVARS Globalize_TVars
\ When building tasks, do NOT include the statement:   (STATUS) NEXT.TASK !
\  because we want to allow multiple tasks to be built.
\ Type WARM or COLD before re-running the program.


The EtherSmart Wildcard is based on the Lantronix Xport Ethernet device server, and the WiFi Wildcard is based on the Lantronix WiPort wireless device server. Software examples coded in C or Forth let you implement a remote clickable front panel, send emails from the instrument, serve out static and dynamic web pages to your PC-based browser, and perform serial data exchanges with peripheral devices (known as "Serial Tunneling"). These tiny 2" by 2.5" boards are members of the Wildcard™ series that connects to Mosaic's embedded computers to implement web-enabled instrumentation and automation functions.



See also → C Language Remote Front Panel Demo for QScreen / QVGA Controller

 
This page is about: Remote and Web-enabled Instrument Control with Lantronix XPort/WiPort Using Forth Language – Forth language code examples for the EtherSmart and WiFi Wildcards implements a clickable remote front panel for a web-enabled instrument.
 
 
Navigation