Skip to content

Custom Page Example ​

Last updated

A live machine monitor that mixes shortcode widgets with a little of your own code. Replace 3 with your CNC's numeric device id (use Tag Snippet to find it) and adjust the tag paths. The table part needs a Data Table named production_log with columns machine, part_count and cycle_time.

HTML ​

html
<div class="container">
  <h1>CNC-001 Monitor</h1>

  <div class="grid">
    <div class="card">
      <scada-widget widget="gauge" title="Spindle Speed" min="0" max="12000" unit="RPM"
                    bind-value="tag:3/spindle_speed"></scada-widget>
    </div>
    <div class="card">
      <scada-widget widget="value" title="Feed Rate" unit="mm/min" precision="1"
                    bind-value="tag:3/feed_rate"></scada-widget>
    </div>
    <div class="card">
      <label>Part Count</label>
      <span id="parts">—</span>
    </div>
    <div class="card">
      <label>Status</label>
      <span id="status">—</span>
    </div>
  </div>

  <h2>Production Log</h2>
  <p id="log-error" class="error"></p>
  <table id="log-table">
    <thead><tr><th>ID</th><th>Machine</th><th>Part #</th><th>Cycle Time</th></tr></thead>
    <tbody></tbody>
  </table>
</div>

CSS ​

css
body { background: #f5f7fa; color: #1f2937; }
.container { max-width: 960px; margin: 0 auto; padding: 20px; }
h1 { font-size: 22px; margin-bottom: 16px; }
h2 { font-size: 16px; margin: 24px 0 8px; }
.grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: 16px; }
.card { background: #fff; border: 1px solid #e5e7eb; border-radius: 12px; padding: 16px; min-height: 180px; }
.card label { display: block; font-size: 12px; color: #6b7280; text-transform: uppercase; margin-bottom: 8px; }
.card > span { display: block; font-size: 32px; font-weight: 700; }
table { width: 100%; border-collapse: collapse; background: #fff; }
th, td { padding: 8px 12px; text-align: left; border-bottom: 1px solid #e5e7eb; font-size: 13px; }
th { color: #6b7280; font-size: 11px; text-transform: uppercase; }
.error { color: #dc2626; font-size: 13px; }

JavaScript ​

javascript
var DEVICE_ID = 3;   // numeric id, not the device name

scadaink.subscribe(DEVICE_ID, 'part_count', function (v) {
  document.getElementById('parts').textContent = v;
});

// MTConnect's execution state: ACTIVE, READY, FEED_HOLD, INTERRUPTED, STOPPED …
scadaink.subscribe(DEVICE_ID, 'execution', function (v) {
  var el = document.getElementById('status');
  el.textContent = v;
  el.style.color = v === 'ACTIVE' ? '#16a34a' : v === 'STOPPED' ? '#dc2626' : '#ca8a04';
});

function loadLog() {
  scadaink.db.query('production_log', { limit: 20, sortBy: 'id', sortDir: 'desc' })
    .then(function (rows) {
      var tbody = document.querySelector('#log-table tbody');
      tbody.textContent = '';
      rows.forEach(function (row) {
        var tr = document.createElement('tr');
        [row.id, row.machine, row.part_count, row.cycle_time + ' s'].forEach(function (text) {
          var td = document.createElement('td');
          td.textContent = text == null ? '' : text;
          tr.appendChild(td);
        });
        tbody.appendChild(tr);
      });
    })
    .catch(function (err) {
      document.getElementById('log-error').textContent = 'Could not load the log: ' + err.message;
    });
}

loadLog();
setInterval(loadLog, 30000);   // the browser has setInterval, unlike server scripts

Notes ​

  • The gauge and value tiles are shortcodes, so they update themselves; only the part count and status use subscribe.
  • Table cells are filled with textContent, not innerHTML, so a value containing < can't inject markup.
  • To add a logo, upload it in the editor's Page files panel and use Insert at the cursor in the HTML tab; it adds an <img> with the file's address.
  • As a Public page without a login, the gauge, feed rate and part count/status still update only if those tags are published — the two shortcode tags are, part_count and execution are not unless another shortcode or public dashboard names them — and the Production Log fails to load, because db.query needs a login. See Custom Page Security.

See also ​

Scada.Ink Help Center