Guías prácticas HMIx

Crea un pie chart con un Custom Web Control en WinCC Unified

Un gráfico circular permite comparar la producción de varias líneas de un vistazo. Vamos a crear uno con HTML, CSS y JavaScript, añadirlo a TIA Portal y probarlo con tres variables internas.

Equipo HMIx10 min de lecturaRevisado
Ilustración de un panel HMI con un gráfico circular de tres series: 45, 35 y 20
Ilustración creada con IA para HMIx. El ejemplo descargable utiliza el mismo reparto de tres valores, con un gráfico de anillo y una leyenda.

Entorno de la guía: TIA Portal / WinCC Unified V21.1. Comprueba la importación y la ejecución del ejemplo en tu dispositivo de destino.

01

¿Qué es un Custom Web Control?

Un Custom Web Control, o CWC, es un pequeño componente web que se coloca dentro de una pantalla de WinCC Unified. HTML define el contenido, CSS el aspecto y JavaScript hace que reaccione. Sirve cuando los objetos HMI estándar no ofrecen la presentación o la interacción que necesitas.

Piensa en un panel de producción, una tabla o un gráfico circular. El control expone propiedades: entradas con nombre, como ValueA. En TIA Portal conectas cada propiedad a una variable HMI; el CWC recibe los valores y actualiza el gráfico. Por sí solo no se conecta directamente al PLC.

  • Elige un CWC para interacciones propias, varios valores coordinados o una composición especial.
  • Para un símbolo que cambia de color, posición o nivel de llenado, un SVG dinámico suele ser más sencillo.
  • Para reutilizar un conjunto de objetos HMI estándar, considera un faceplate.

En HMIx puedes descargar cientos de recursos HMI gratuitos. Empieza con un control del catálogo o describe tu idea al generador de IA de HMIx para crear un recurso que puedas adaptar a tu proyecto.

Pie Chart de HMIx con cinco sectores, leyenda y detalle de una serie
Pie Chart – Dashboard Widget, publicado en HMIx: un gráfico de anillo con cinco elementos y títulos configurables. Puedes descargarlo desde su ficha. Más abajo construiremos una versión de tres entradas para comprender el mecanismo. Ver este recurso en HMIx

Siemens · Programación de Custom Web Controls

02

Antes de empezar

Utiliza un proyecto de prueba con un dispositivo WinCC Unified y una pantalla vacía. Necesitas TIA Portal con WinCC Unified Engineering y los componentes compatibles de Runtime o simulación instalados. Un proyecto Comfort convencional y uno Unified son destinos distintos.

  • Para la primera prueba, utiliza Unified PC Runtime o la simulación admitida por tu dispositivo Unified.
  • Si quieres modificar el ejemplo, ten a mano un editor de texto y una herramienta ZIP. Visual Studio Code es cómodo, pero no obligatorio.
  • No necesitas un PLC: tres variables HMI internas y tres campos E/S proporcionarán los valores de prueba.

La vista previa del navegador comprueba el dibujo. La conexión WebCC y el enlace a la variable se verifican dentro de Unified.

03

Construye un pie chart de tres valores

Nuestro pie chart tiene forma de anillo: deja el total en el centro y muestra cada serie en una leyenda. Sus entradas son ValueA, ValueB y ValueC, con valores iniciales 45, 35 y 20. Son cantidades; no tienen que sumar 100. El control calcula qué parte del total ocupa cada una.

  1. Prepara los archivos

    Crea manifest.json en la raíz y dos carpetas: assets y control. Dentro de control, crea index.html y code.js. Obtén webcc.min.js de Siemens desde el ejemplo oficial enlazado más abajo y colócalo también en control. Cada archivo tiene una función; no necesitas ningún framework web.

  2. Define las tres entradas

    En manifest.json, declara ValueA, ValueB y ValueC como números, con valores iniciales 45, 35 y 20. El manifiesto también indica el nombre HMIx Pie Chart, su identidad y el archivo de inicio.

  3. Dibuja el gráfico y la leyenda

    En control/index.html, coloca un anillo de tres segmentos, el total y la leyenda A, B y C. En code.js, calcula cada proporción dividiendo el valor entre la suma. Si todos son cero, muestra un anillo vacío. El ejemplo utiliza SVG dentro del HTML y no necesita una librería de gráficos.

  4. Conéctalo con Unified

    Carga webcc.min.js de Siemens sin modificarlo. Inicia WebCC con las mismas tres propiedades, lee sus valores al conectar y vuelve a dibujar cuando onPropertyChanged comunique un cambio. Así se ve el dato actual al abrir la pantalla.

  5. Empaqueta el contenido

    Coloca manifest.json, assets y control en la raíz del ZIP, sin una carpeta adicional que los envuelva. Nombra el ZIP con el GUID del control entre llaves. Si editas nuestros archivos, reconstruye el ZIP con esa estructura; cambiar solo su nombre no crea una identidad de control nueva.

Los nombres ValueA, ValueB y ValueC deben coincidir en el manifiesto y en JavaScript. La descarga de esta guía es un ejemplo propio de tres entradas; el Pie Chart del catálogo utiliza Apache ECharts y cinco elementos con Value y Title.

Descargar el pie chart de ejemplo

ZIP completo con tres entradas numéricas y WebCC. Código y estructura comprobados; la importación y la conexión deben verificarse en WinCC Unified V21.1.

Ver el código del ejemplo

Opcional: la descarga contiene el ejemplo completo. No necesitas escribir este código para seguir la prueba.

manifest.json

{
  "mver": "1.2.0",
  "control": {
    "identity": {
      "name": "HmixPieChart",
      "version": "1.0",
      "displayname": "HMIx Pie Chart",
      "type": "guid://8D821B43-4EF5-4BF1-A31D-931D283C7C04",
      "start": "./control/index.html"
    },
    "metadata": {
      "author": "HMIx",
      "description": "Educational read-only three-value pie chart"
    },
    "contracts": {
      "api": {
        "methods": {},
        "events": {},
        "properties": {
          "ValueA": { "type": "number", "default": 45 },
          "ValueB": { "type": "number", "default": 35 },
          "ValueC": { "type": "number", "default": 20 }
        }
      }
    },
    "types": {}
  }
}

control/index.html

<!doctype html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <title>HMIx Pie Chart</title>
    <style>
      * {
        box-sizing: border-box;
      }
      body {
        margin: 0;
        padding: 20px;
        background: #171e26;
        color: #f3f5f6;
        font:
          14px system-ui,
          sans-serif;
      }
      header {
        display: flex;
        justify-content: space-between;
        color: #bac5ce;
        font-size: 11px;
        letter-spacing: 0.14em;
      }
      main {
        display: flex;
        align-items: center;
        justify-content: center;
        gap: 24px;
        min-height: 240px;
      }
      svg {
        width: 55%;
        max-width: 300px;
        flex-shrink: 0;
      }
      ul {
        list-style: none;
        padding: 0;
        min-width: 110px;
      }
      li {
        display: grid;
        grid-template-columns: 10px 1fr auto;
        align-items: center;
        gap: 10px;
        padding: 14px 0;
        border-bottom: 1px solid #35404a;
      }
      .dot {
        width: 8px;
        height: 8px;
        border-radius: 50%;
      }
      small {
        display: block;
        margin-top: 4px;
        color: #bac5ce;
        font-variant-numeric: tabular-nums;
      }
      strong {
        font-variant-numeric: tabular-nums;
      }
      @media (max-width: 360px) {
        body {
          padding: 12px;
        }
        main {
          gap: 12px;
        }
      }
    </style>
  </head>
  <body>
    <header><span>HMIx</span><span>PIE CHART</span></header>
    <main>
      <svg viewBox="0 0 220 220" role="img" aria-labelledby="chart-title">
        <title id="chart-title">Distribution of A, B and C</title>
        <circle
          cx="110"
          cy="110"
          r="76"
          fill="none"
          stroke="#35404a"
          stroke-width="28"
        />
        <g transform="rotate(-90 110 110)" fill="none" stroke-width="28">
          <circle id="ValueA" cx="110" cy="110" r="76" stroke="#47d2c8" />
          <circle id="ValueB" cx="110" cy="110" r="76" stroke="#79a9ed" />
          <circle id="ValueC" cx="110" cy="110" r="76" stroke="#f5c16c" />
        </g>
        <text
          id="total"
          x="110"
          y="115"
          text-anchor="middle"
          fill="#f3f5f6"
          font-size="30"
          font-weight="600"
        >
          100
        </text>
        <text
          x="110"
          y="139"
          text-anchor="middle"
          fill="#bac5ce"
          font-size="10"
          letter-spacing="2"
        >
          A + B + C
        </text>
      </svg>
      <ul aria-label="Values and shares">
        <li>
          <i class="dot" style="background: #47d2c8"></i
          ><span>A<small id="ValueA-amount">45</small></span
          ><strong id="ValueA-percent">45%</strong>
        </li>
        <li>
          <i class="dot" style="background: #79a9ed"></i
          ><span>B<small id="ValueB-amount">35</small></span
          ><strong id="ValueB-percent">35%</strong>
        </li>
        <li>
          <i class="dot" style="background: #f5c16c"></i
          ><span>C<small id="ValueC-amount">20</small></span
          ><strong id="ValueC-percent">20%</strong>
        </li>
      </ul>
    </main>
    <script src="webcc.min.js"></script>
    <script src="code.js"></script>
  </body>
</html>

control/code.js

/* HMIx educational pie chart. Values are amounts, not required percentages. */
var values = { ValueA: 45, ValueB: 35, ValueC: 20 };
var keys = ['ValueA', 'ValueB', 'ValueC'];
var circumference = 2 * Math.PI * 76;

function drawChart() {
  // Normalize before adding to avoid overflow for very large finite values.
  var maximum = Math.max(values.ValueA, values.ValueB, values.ValueC, 1);
  var sum = keys.reduce(function (n, key) {
    return n + values[key] / maximum;
  }, 0);
  var offset = 0;
  keys.forEach(function (key) {
    var fraction = sum ? values[key] / maximum / sum : 0;
    var arc = document.getElementById(key);
    var length = fraction * circumference;
    arc.setAttribute('stroke-dasharray', length + ' ' + circumference);
    arc.setAttribute('stroke-dashoffset', String(-offset));
    arc.setAttribute('visibility', fraction ? 'visible' : 'hidden');
    document.getElementById(key + '-amount').textContent = String(values[key]);
    document.getElementById(key + '-percent').textContent =
      Math.round(fraction * 100) + '%';
    offset += length;
  });
  var total = values.ValueA + values.ValueB + values.ValueC;
  document.getElementById('total').textContent = isFinite(total)
    ? String(total)
    : '—';
}

function setValue(key, value) {
  if (keys.indexOf(key) === -1 || typeof value !== 'number' || !isFinite(value))
    return;
  values[key] = Math.max(0, value);
}

drawChart();
if (typeof WebCC !== 'undefined') {
  WebCC.start(
    function (connected) {
      if (!connected) return;
      keys.forEach(function (key) {
        setValue(key, WebCC.Properties[key]);
      });
      drawChart();
      WebCC.onPropertyChanged.subscribe(function (change) {
        setValue(change.key, change.value);
        drawChart();
      });
    },
    {
      methods: {},
      events: [],
      properties: { ValueA: 45, ValueB: 35, ValueC: 20 },
    },
    ['HMI'],
    10000,
  );
}

Siemens · Estructura del manifiestoSiemens · WebCC e interfaz con RuntimeSiemens · Archivos de ejemplo y biblioteca WebCC

04

Añade el ZIP a tu proyecto de TIA Portal

  1. Localiza la carpeta del proyecto

    Abre la carpeta que contiene tu proyecto de TIA Portal. Dentro de UserFiles, crea CustomControls si no existe.

  2. Copia el paquete CWC

    Coloca el {GUID}.zip importable en UserFiles\CustomControls. Este ZIP debe permanecer comprimido. No copies únicamente index.html ni el paquete exterior de descarga.

  3. Actualiza e inserta el control

    Abre la pantalla Unified. En Herramientas → Controles propios (Tools → My controls), pulsa Actualizar y arrastra HMIx Pie Chart a la pantalla. Dale espacio al anillo y a su leyenda, por ejemplo 480 × 300 píxeles.

  4. Comprueba su interfaz

    Selecciona el control y abre Propiedades → Propiedades → Interfaz. Busca ValueA, ValueB y ValueC y asigna valores estáticos 45, 35 y 20. El siguiente paso los conectará a variables.

Ejemplo de Siemens con Controles propios, un indicador en una pantalla Unified y sus propiedades de Interfaz
Captura de ingeniería de Siemens: Controles propios → pantalla → Interfaz. Siemens muestra GaugeMeter; en nuestra prueba selecciona HMIx Pie Chart y sus propiedades ValueA, ValueB y ValueC. Referencia · © Siemens AG · Licencia y atribución

Siemens · Instalación y uso de CWC

05

Pruébalo con tres variables internas, sin PLC

  1. Crea tres variables internas

    En la tabla de variables HMI, añade ProductionA, ProductionB y ProductionC, de un tipo numérico como Real y sin conexión a PLC.

  2. Enlaza cada entrada con su variable

    En la interfaz del CWC, elige Variable como dinamización: ValueA → ProductionA, ValueB → ProductionB y ValueC → ProductionC. Mantén Solo lectura activado; los campos E/S cambiarán los datos.

  3. Añade tres campos E/S

    Coloca un campo E/S en modo entrada/salida para cada variable. Identifícalos como A, B y C. Para esta prueba utiliza cantidades entre 0 y 100 y configura los límites de entrada cuando estén disponibles.

  4. Compila y ejecuta

    Establece esta pantalla como inicial, compila la HMI y corrige los errores indicados. Inicia la simulación HMI compatible, o carga y arranca el proyecto de prueba en Unified PC Runtime. Abre el cliente Runtime e inicia sesión con el usuario configurado en el proyecto si se solicita.

  5. Prueba dos repartos y el estado vacío

    Introduce 45, 35 y 20 y confirma cada entrada. Después cambia A a 90: su segmento crecerá y el total será 145. Por último, pon las tres entradas a cero; debe quedar un anillo vacío. Vuelve a abrir la pantalla para comprobar que conserva la lectura actual.

Captura de Siemens de una propiedad CWC enlazada a una variable con Solo lectura activado
Enlace de una propiedad en el ejemplo de Siemens. En nuestro gráfico, sustituye GaugeValue / Motor_Speed por ValueA / ProductionA y repite para B y C, con Solo lectura activado. Referencia · © Siemens AG · Licencia y atribución

Primero, observa qué debería ocurrir

Cambia A, B o C y observa cómo se reparten los segmentos. Los valores son cantidades: el gráfico calcula sus porcentajes.

100Total
45 / 45%
35 / 35%
20 / 20%
Explicación interactiva de esta guía. No es una sesión de WinCC Runtime.

La prueba funciona cuando…

45 / 35 / 20 muestra un total de 100. Con A = 90, el total pasa a 145 y A ocupa aproximadamente el 62 %. Tres ceros dejan el anillo vacío. Al reabrir la pantalla deben aparecer los valores actuales.

Siemens · Instalación y uso de CWCSiemens · Ejemplo de ingeniería y capturas originales

06

Si algo no funciona

  • No aparece el control: revisa UserFiles\CustomControls, la raíz del ZIP, la sintaxis JSON del manifiesto y el nombre GUID; después actualiza Controles propios.
  • El gráfico aparece pero no cambia: revisa los nombres ValueA, ValueB y ValueC, sus variables y la conexión WebCC. Abrir el HTML localmente comprueba el aspecto, no la conexión con Unified.
  • Funciona en PC pero falla en un Unified Comfort Panel: incluye las dependencias dentro del paquete. Siemens documenta restricciones para enlaces externos y para obtener datos con fetch o XMLHttpRequest.
  • No ves una modificación: reconstruye el ZIP, utiliza el procedimiento de actualización de controles de TIA Portal, compila y vuelve a cargar el proyecto de prueba. Conserva una copia de la versión que funcionaba.

Cuando esta pequeña prueba funcione, añade una mejora cada vez. Valida el control final en el dispositivo de destino antes de conectarlo a un proceso real.

Siemens · Restricciones de CWC en Unified Comfort Panels

Preguntas frecuentes

¿Necesito saber JavaScript?

Puedes importar y enlazar un CWC existente sin escribir JavaScript. Para modificar su comportamiento a mano, ayudan unas nociones de HTML, CSS y JavaScript. La IA de HMIx puede preparar los archivos; el resultado se revisa y se prueba en Unified.

¿Puedo reutilizarlo en otro proyecto?

Copia el ZIP importable a UserFiles\CustomControls del otro proyecto y configura sus variables. Conserva el paquete y su versión juntos; no des por hecho que funciona como un tipo de faceplate versionado en biblioteca.

¿Una vista previa correcta significa que está listo?

Confirma el aspecto, pero no toda la integración con Runtime. Comprueba también el arranque, los cambios de propiedades, el dispositivo de destino y los tamaños de pantalla previstos.

Fuentes y lecturas complementarias