## 3 Materials and Methods
### Framework Architecture  
In Figure 10, the architecture of the developed framework is illustrated. The client computer, designed to send requests, create new firmware versions, and edit and compile user code, utilizes two main services. The first is an IDE created with JavaScript, consisting of a primary view/scene for reviewing the loaded code/file, a window for viewing the decompiled code, and registered constants before execution. Code compilation is performed using the standard Stella compiler, and within the IDE, messages and bytecode are displayed and loaded via a \"pipe\" between these two processes. The code can be forwarded to an emulator that includes additional support for modifying the display and defining input components, such as buttons, sliders, and text entry fields. Bytecode transfer is conducted via the HTTP protocol, either sent directly in the request body or using a form with a file field. The user is also offered the option to exchange messages over a UDP port for device discovery on the network, logging, and device status transmission in case of an error or interruption.  
The PlatformIO project for the customized virtual machine can be active on any device intended for code transfer to a development board. The most common and reliable method is serial connection via USB, but after the initial firmware transfer, OTA (Over-the-Air) updates are also available, requiring only an IP address, port, and access credentials without any physical connection. The structure and initial contents of the file system are also defined in this project and are sent separately, not being part of the OTA process. The source code for firmware compilation relies on three main artifacts: \"ESPSTC\" as a library for the virtual machine and native interface, \"ArduinoJson\" for serializing and deserializing incoming HTTP requests in JSON format, and \"platformio.ini\", a configuration file for defining the target platform, board, and additional compilation and execution parameters. The main program, implemented as a single-threaded Round Robin architecture with a request queue, consists of two main functions: \"setup\", which sets up constants, access credentials, initializes I/O and network interfaces, and configures the network server; and \"loop\", which for each available active module executes the method for request checking  
Figure 9: Diagram of the program serialization process (authors’ contribution).  
and handling. This design not only allows for an even temporal distribution of all services, creating an apparent effect of concurrency, but also enables more efficient request responses without dropping them in cases of resource occupation or the temporary inability to respond due to processing.  
The available system libraries on ESP-based development boards serve as the basis for running identical procedures and memory manipulations as on the computer version of the compiler and interpreter. They also form the foundation for integrating user-accessible services, which, through a platform-independent connection layer to the native interface, manifest as native objects within the instances of the virtual machine. Additional directives are set via configuration headers, while bytecode deserialization is handled by a separate module connected to the interpreter and the data persistence module. Native classes for file access rely on a file system formatted on flash memory using LittleFS or SPIFFS, providing an additional abstraction layer for securely saving files and binary content for serialized values on the stack, and are used in the HTTP server segment intended for file system status inspection [1]. The UDP connection is configurable; by default it is used for locating the development board and sending logs, and it can also be configured to open a WebSocket connection, which would be useful for real-time content updates for web user interfaces [14].