Connecting CODESYS PLC Tags to a Custom HTML Front End

Patricia Callen7 min read
HMI / SCADAOther ManufacturerTechnical Reference
Licensed PE Working through this on a live machine? A Maine-licensed engineer can take it from here — included with IMD hardware, by the hour for everything else. Book an engineer

A custom HTML front end for a CODESYS controller does not need your visualization objects rebuilt inside the runtime. It needs three things. The Symbol Configuration exports the variables. A protocol server, usually the runtime's OPC UA server, serves them. A small gateway translates that protocol into something a browser can open, such as a WebSocket or a REST endpoint. The symbol configuration file you mentioned is the right source for tag names. Parse it to generate the tag list and data bindings instead of retyping them.

Why can't the browser read the PLC variables directly?

WebVisu works because the runtime's web server and the WebVisu client share a protocol that CODESYS owns and does not publish for your own pages. A browser page can only open HTTP(S) and WebSocket connections. It cannot open raw TCP sockets, so it cannot speak OPC UA binary over opc.tcp, Modbus TCP, or the CODESYS gateway protocol. The signal chain for a custom page is therefore:

  1. The Symbol Configuration publishes that variable with a name, a data type and access rights.
  2. The OPC UA server in the runtime exposes it as a node.
  3. A gateway process runs on an edge PC, on a server, or on the controller's OS if it permits. It subscribes to the nodes and pushes changes over WebSocket.
  4. JavaScript in the page updates the DOM and sends write requests back through the gateway.

Each hop can lose, delay or corrupt the value. Diagnose one hop at a time, starting from the PLC and working outward. Do not start by rewriting the page.

Signal Source Wrong-value symptom
Variable exists and updates PLC online monitoring Frozen at init value: logic not executing or the wrong instance is being watched
Symbol published Symbol Configuration object, downloaded with the application Node missing in the OPC UA browse tree
Access right Symbol Configuration access column Reads work but writes return a bad status or are silently ignored
Data type mapping OPC UA node attributes vs gateway decoding Garbled strings, wrong scaling, TIME shown as a large integer
Subscription rate Gateway publishing and sampling settings Page lags or skips transitions that the PLC clearly makes
WebSocket delivery Browser developer tools, network frames Correct value in the gateway log, stale value on screen

Check 1: Does the tag appear when you browse the OPC UA server?

Connect a generic OPC UA client from the machine that will run the gateway. Browse to the application's variables and read the variable in question.

  • Node missing: the variable is not in the Symbol Configuration, or the configuration changed but the application was not rebuilt and downloaded. The symbol set only updates on download. Open the Symbol Configuration object and tick the variable or its whole GVL or program. If your version shows an OPC UA feature option in that editor, enable it. Build, download, then browse again.
  • No connection at all: this is a network or security fault, not a tag fault. Check that the OPC UA server is enabled on the device. Check the endpoint address and the firewall. Check the certificate trust on both sides. Most first-connection failures are a rejected certificate that nobody moved into the trusted list.
  • Node present, value matches PLC online monitoring: the controller side is correct. Go to Check 2.

Check 2: Does the gateway log the same value the client reads?

Log every data-change notification in the gateway with a timestamp and the raw value. Compare the log against the OPC UA client for the same node.

  • Values differ: the gateway is decoding the type wrongly or subscribed to the wrong node. Node identifiers are built from the device and application path. Renaming the device or the application breaks them. Generate node IDs from the current symbol file or by browsing, never from hand-typed strings.
  • Values match but update slowly or miss pulses: the sampling or publishing interval is longer than the event. A one-scan boolean pulse will never survive an OPC UA subscription. Latch the event in PLC logic and have the HMI acknowledge it, or expose a counter instead of a pulse.
  • Values match and arrive promptly: go to Check 3.

Check 3: Does the browser receive and render each change?

Open the browser developer tools and watch the WebSocket frames.

  • Frames arrive but the screen is wrong: the fault is in the page. Look for a binding keyed to the wrong tag name, number formatting, or a render that throws on null.
  • No frames arrive: check the gateway's client list, the reverse proxy WebSocket upgrade headers, and mixed-content blocking. An HTTPS page cannot open an unencrypted ws:// socket.
  • Frames stop after a network blip: the page has no reconnect logic. Add reconnect with backoff. Grey out every value while the socket is down so an operator never acts on stale data.

Writes travel the same chain in reverse. If a write shows in the gateway log with a good status but the value snaps back, the PLC logic is overwriting it every scan. That is a program-structure problem. Write to a command variable and let the logic consume it, rather than writing straight into a variable the logic owns.

How do you build the bridge so the tag list maintains itself?

  1. In the Symbol Configuration, publish only the variables the HMI needs. Set operator setpoints and commands to read/write and everything else to read-only.
  2. Build and download. Keep the generated symbol XML file as the single source of the tag list.
  3. Write a build step that parses the XML into a JSON tag map: name, type, access, and node ID. The page and the gateway both load this map, so adding a tag means one checkbox and one rebuild.
  4. In the gateway, create one OPC UA subscription with monitored items for the mapped tags. Set sampling intervals to match process dynamics, not to the fastest the server allows.
  5. Push only changes to the browser. Send a full snapshot when a client connects.
  6. Route writes through the gateway. Check each write against the map's access field and a range limit before forwarding it.
  7. Put the gateway behind HTTPS with authentication. The OPC UA session should use its own least-privilege user, not an anonymous login.

The tag names above are placeholders. Substitute the names from your own symbol file.

Confirm the page tracks the PLC under fault conditions

  1. Put PLC online monitoring and the HTML page side by side. Force a variable through its range and confirm both show the same value, sign and scaling.
  2. Toggle a slow boolean and a latched event. Confirm the page shows both transitions.
  3. Write a setpoint from the page. Confirm it lands in the PLC and holds for several scans.
  4. Try to write a read-only tag. The gateway must reject it and the PLC value must not change.
  5. Pull the gateway's network cable. The page must flag stale data within your chosen timeout. Reconnect and confirm a fresh snapshot replaces every value.
  6. Download a modified application to the PLC. Confirm the gateway re-subscribes, and that renamed tags fail visibly rather than showing old values.

Frequently asked questions

Can I read CODESYS tags directly from JavaScript in the browser without a gateway?

Not over OPC UA binary or Modbus TCP, because browsers cannot open raw TCP sockets. You need an intermediate process that speaks the PLC protocol on one side and WebSocket or HTTP on the other. That process can be a small custom service or an existing flow-based integration tool.

Does the CODESYS symbol configuration file list every variable in the project?

No. It lists only the variables selected in the Symbol Configuration object, with their types and access rights. It reflects the last build, so rebuild and download after every change before regenerating your tag map from it.

Can I keep WebVisu running while I migrate to a custom HTML page?

Yes. WebVisu and an OPC UA server run on the same application, so you can migrate screen by screen and compare both displays against online monitoring. Watch controller CPU load while both run, and route writes to any given variable from only one front end.

If the OPC UA server cannot be enabled on your device, or published symbols never appear after a clean download, stop and contact the controller vendor or CODESYS support. Have the runtime version, the device description, and the runtime log ready. These faults are license or runtime-configuration issues, and gateway code cannot work around them.

Back to blog