NumCachedImages 0 for live WebVisu bitmap updates

7 min read · Published November 4, 2026

A WebVisu client draws the images it has already loaded, so a replaced bitmap on the controller never reaches the screen. Set NumCachedImages to 0 in /visu/webvisu.cfg.json and keep the edit alive across downloads. The article gives the JSON line, the network arithmetic for a live-swapped bitmap, and both persistence options.

Replace the bitmap file on the controller and the WebVisu page keeps showing the old frame. The path is right and the file really changed; what holds the old picture back is the web client's image store. NumCachedImages in /visu/webvisu.cfg.json sets how many images that client keeps, and the fix is to set it to 0. One edit, then a replaced file reaches the screen within one visualization refresh, with no runtime restart. The second half of the job is keeping the edit alive, because an application download rewrites that configuration file. Below are the exact JSON, the network arithmetic for a live-swapped bitmap, and both ways to keep the setting in place.

Why the replaced bitmap never reaches the screen

NumCachedImages sets how many images the web visualization client holds after loading them, so it does not have to fetch them again. While the client holds an image, a new file at the same path never reaches the display: the client draws from its store.

That is why the registration calls do nothing here. BmpPoolRegister and BmpPoolUnRegister, called with an image ID such as IMAGE_POOL_ID and a path such as IMAGE_FILE_LOCATION, manage the mapping between an image ID and a file on disk. The stored copy is untouched by that mapping, so a register-unregister cycle around a file swap changes nothing. Registering the new file under a new image ID fails the same way, and so does switching pages: registration and navigation both leave the client's store alone.

A runtime restart empties the store, which is why the picture is correct after every reboot and stale after every live swap. A restart also stops the runtime and every client with it, so the working fix is to switch the caching off at the client instead: NumCachedImages 0.

Symptoms and what each points to

  • File changed on the controller, screen still shows the old bitmap, no error anywhere: the web client's image store. This is the case NumCachedImages 0 fixes.
  • Unregister and register around the swap changes nothing: those calls manage ID-to-path registration; the client never re-reads.
  • New file under a new image ID still stale: same store. The image ID was never the problem.
  • Changing to another page and back still stale: page navigation leaves the store alone.
  • Picture correct after a runtime restart, stale after a live swap: the store again; the restart emptied it.
  • The file on the controller never changes: the write landed somewhere else, usually the engineering PC or a wrong directory. Fix the delivery first, because no configuration change helps until the file on the controller really changes.
  • The visualization will not send or deploy after a compile: a deployment problem, a different one; see fixing a WebVisu file that will not send after a compile.
  • Bitmap refreshes only at runtime start on a CoDeSys 2.3 system: an older runtime with a different cause; see why a CoDeSys 2.3 bitmap only refreshes at runtime start.

Set NumCachedImages to 0 in webvisu.cfg.json

What you need: file access to the controller, the same access a deployment uses; the current webvisu.cfg.json; a backup copy of it; and a replacement bitmap that is valid and obviously different from the old one.

  1. Open /visu/webvisu.cfg.json on the controller and save a backup copy beside it.
  2. Find NumCachedImages and set it to the number 0, without quotation marks. If the key is missing, add it inside the existing JSON object, with a comma after the entry before it and no duplicate key anywhere in the file.
  3. Leave every other key as the controller generated it. UpdateRate, StartVisu, CommBufferSize and the rest belong to the running setup.
  4. Check the JSON before saving: matching braces, quotes on every text value, a comma between entries, none after the last one. A broken file leaves operators without the page, so this check is the safety step.
  5. Reload the client from a fresh browser session so it reads the edited configuration, and confirm it connects to the intended application and start visualization.
  6. Test the live swap: write the new bitmap to the path the pool entry points to, on the controller, and watch the page change with no restart.

A working file with the change in place looks like this, shown with the values from the 3.5.4.x setup this fix comes from. Your own UpdateRate, PlcAddress and StartVisu stay as your controller generated them:

{
 "UpdateRate": 200,
 "PlcAddress": "0000.9ED4.C1D5",
 "UseLocalHost": true,
 "Application": "Application",
 "StartVisu": "SendTweetVisu",
 "NumCachedImages": 0,
 "BestFit": true,
 "LogLevel": "INFO",
 "CommBufferSize": 50000,
 "HasKeyboard": false
}

NumCachedImages 0 is one property inside that object, a JSON number, and it is the only line this job changes.

Scenario: a status bitmap swapped every 30 seconds

A packaging line keeps its andon-style status image on the WebVisu start page. A line PC writes a fresh bitmap to the controller every 30 s. The bitmap is 640 × 480 and comes out at 150 kB; both values are this example's inputs, so weigh your own file the same way. Three browser clients on the floor show the page, and the configuration keeps UpdateRate at 200, in milliseconds.

With caching off, the page refreshes 1000 ms ÷ 200 ms = 5 times per second. Budget the worst case, where every refresh re-reads the bitmap: 5 reads/s × 150 kB = 750 kB per second per client. Three clients together: 3 × 750 kB/s = 2250 kB/s = 2.25 MB/s, and at 8 bits per byte, 2.25 MB/s × 8 = 18 Mbit/s. On the line's 100 Mbit/s network that is 18 percent of the wire, so the setting stays at 0 and no network change is needed.

The same arithmetic shows when to keep live bitmaps small. A 2 MB picture at 5 reads/s is 10 MB/s = 80 Mbit/s for one client alone, which crowds a 100 Mbit/s network. Keep live-swapped files in the tens or low hundreds of kB.

Timing: the new file lands within the 30 s write cycle, and the screen picks it up on the next refresh, so the swap shows about 200 ms after the write completes. Before the change, the same swap never appeared until someone reloaded the client or the runtime restarted.

If that page should also sit on a wall screen beside the line, that is a signage decision of its own; the web page signage player article covers what to check there.

Keep the setting alive across downloads

An application download rewrites webvisu.cfg.json and takes NumCachedImages 0 with it, so persistence belongs to commissioning, not to a later maintenance visit. Two ways keep the value in place:

  • Read-only file. Make webvisu.cfg.json read-only on the controller and the download leaves it in place. Clear the read-only flag whenever you need to edit the settings again, and after every download open the file and confirm the 0 is still there.
  • Rename the visualization in the project. Change the WebVisu object's name in CODESYS; webvisu_my is the example name for this. The project then supplies its own configuration, the file stays writable, and the setting travels with every download and with a controller swap.

Either way, close the loop after the next normal download: read the deployed webvisu.cfg.json and confirm NumCachedImages is 0, then launch the operator's entry point, the page named in StartVisu, and swap a bitmap live in front of it.

Recommendation: set NumCachedImages to 0 in /visu/webvisu.cfg.json and rename the visualization to webvisu_my in the project, so the setting survives every download and travels with the application. Use the read-only flag only as the fast stopgap on a controller you rarely download to. Keep live-swapped bitmaps small: at UpdateRate 200 the scenario above puts a 150 kB file at 18 Mbit/s for three clients, while a 2 MB file at the same rate takes 80 Mbit/s on its own.

Checks when the bitmap still does not change

Work down this order; each step rules one layer in or out.

  1. Confirm the file changed where the visualization reads it: the path the pool entry points to, IMAGE_FILE_LOCATION in the pool call, on the controller that serves the page. A copy updated on the engineering workstation changes nothing until it reaches that location.
  2. Open the new bitmap in an image viewer before deploying it, and finish the write completely before exposing it at the referenced path. A half-written file fails to display and can read as a cache problem.
  3. Confirm the visualization element on the page displays the intended image ID and not another static resource.
  4. Reload the client and watch the browser's network tools: did an image request go out, and did the new bytes come back? No new request points at the reload behavior; the old bytes coming back point at the served file or the browser's own store, and a hard reload rules the browser out. browser-cache fix for a WebVisu dynamic bitmap that will not reload goes deeper on that layer.
  5. Confirm which client the operators watch. The file edited here configures the WebVisu browser client; the native target visualization on the controller's own screen is a different component with its own configuration, so identify the client before changing anything else.

Questions

Does NumCachedImages 0 survive a runtime restart?

Yes. The value lives in webvisu.cfg.json on the controller, so every client start reads it again. What removes it is an application download that rewrites the file, which is why the read-only flag or the webvisu_my rename matters. After any download, open the deployed file and confirm the 0 is still there before the operators need a live swap.

Does the zero value affect other images on the page?

NumCachedImages is one client-level count of stored images, so 0 changes the store for the whole WebVisu client, all images on the page and every browser client that loads it. That is the trade for live updates: images are fetched again instead of held. Budget for it with the per-client arithmetic in this article before rolling the change out.

Does this apply on other CODESYS versions besides 3.5.4.x?

The file name, the setting and the example values here come from a 3.5.4.x setup. On any other release, open the /visu folder on the controller first and confirm webvisu.cfg.json exists and carries the NumCachedImages key. If the folder or the key is missing, that release keeps its web visualization settings elsewhere and the edit has no target.

Planning information, not legal or engineering advice. Rules differ by place: check codes and permits with your local authority and your licensed trades.

Keep reading

Build your signAsk for a quote