BajaScript

BajaScript is the bridge between the browser and the live station. It is the JavaScript API that lets HTML5 interfaces read points, subscribe to changes, and invoke actions in Niagara – the engine behind every modern, responsive Niagara dashboard. Software Pile builds interfaces on it that stay live and stay fast.

What BajaScript Makes Possible

  • Live data binding: browser widgets that reflect station values in real time via subscriptions, not polling
  • Interactive control: operators adjusting setpoints and invoking actions with proper permission checks
  • Custom HTML5 dashboards that go beyond what stock PX and Hx views allow
  • Efficient subscription handling so many widgets and sessions do not overload the station

Modern Interfaces, Real Data

BajaScript paired with a proper build pipeline and WebSocket transport is how we deliver Niagara UX that feels like a modern web app rather than an embedded control screen – without losing the live connection to the station that makes it useful.

Describe the interface you want and your Niagara version. We will build it on BajaScript with performance in mind from the first line.

What Is BajaScript?

BajaScript is the JavaScript client library that lets code running in a browser talk to a live Niagara station. It exposes the Niagara object model — components, properties, actions and permissions — to the browser, so a web interface can resolve an ORD, read a point, subscribe to changes, and invoke an action without the page having to poll a server for updates.

It is the reason a modern Niagara interface can behave like a web application rather than a refreshing page. Everything responsive in an HTML5 Niagara UX module is ultimately going through BajaScript.

How Is BajaScript Different from the Baja API?

They model the same thing from opposite sides of the connection. The Baja API is the Java API used inside the station and inside Workbench — it is where server-side module logic, drivers and components live. BajaScript is the browser-side counterpart, giving JavaScript access to a similar component and subscription model over the network.

The practical consequence: work that must run whether or not anyone is looking at a screen belongs in a Java module built on the Baja API. Work that exists to present and interact belongs in BajaScript. Putting control logic in the browser is a recurring design mistake — it stops the moment the operator closes the tab.

How Do BajaScript Subscriptions Work?

Rather than repeatedly asking the station for values, a BajaScript client subscribes to the components it cares about and the station pushes changes as they occur. This is what keeps a dashboard live without generating constant request traffic.

Subscriptions are also where most performance problems originate. Each subscribed component costs the station resources, and those costs multiply by the number of concurrent sessions. A dashboard that subscribes to several hundred points and is left open on a dozen workstations is a meaningfully different load than the same dashboard viewed once.

What Are the Common BajaScript Performance Mistakes?

  • Subscribing to everything on page load. Subscribe what is visible; subscribe the rest when it becomes visible.
  • Never unsubscribing. Views that are navigated away from but never torn down leave subscriptions alive and accumulate load over a shift.
  • Resolving ORDs in a loop. Batch resolution instead of issuing one request per point.
  • Ignoring the station under load. An interface that feels fine on a lab station can degrade badly on a production Supervisor already serving alarms, histories and other clients.
  • Treating the browser as trusted. Permissions are enforced by the station, not the interface. Hiding a button is presentation, not security.

Which Niagara Versions Support BajaScript?

BajaScript is the client library behind Niagara HTML5 UX work and is used across current N4 development. The exact version and packaging matter: the library, the build tooling around it, and the module format all move between Niagara releases, so an interface written against one N4 version is not automatically portable to another. Scope any interface work against your specific Niagara version rather than against “N4” in general, and expect retesting as part of a station upgrade.

When Should You Use BajaScript Instead of Px?

Px remains the fastest way to produce conventional operator graphics, and for many stations it is the right answer. BajaScript earns its extra effort when you need something Px was not designed to produce:

  • Interfaces that must work well on phones and tablets, not just a workstation.
  • Custom visualizations — charts, floor plans, or aggregations that combine station data with an external source.
  • Public or tenant-facing views where the look must match a brand rather than look like a control system.
  • Screens that pull from several stations or from a system outside Niagara entirely.
  • Workflows with multi-step interaction and validation rather than a single setpoint adjustment.

If the requirement is a conventional equipment graphic for an operator on a desktop, Px is usually the cheaper and more maintainable choice. We will say so.

How We Build BajaScript Interfaces

Interfaces are scoped against your Niagara version, station architecture and expected concurrency, then built with a proper module structure and a Webpack and Babel build pipeline so the result is a signed, versioned Niagara module rather than loose files dropped on a station. Subscription behaviour is load-tested against realistic point counts and session numbers before handover, and the code is yours.

Related services: Niagara graphics and operator dashboards · custom Niagara module and driver development.

Values, Status and the Asynchronous Model

BajaScript is asynchronous end to end. Resolving an ORD, reading a property and invoking an action all return promises that settle after a network round trip, so nothing is available on the following line. Code that resolves a component and reads its value in the next statement gets undefined, and the usual symptom is a widget that renders blank on first paint and correct after any later change. Teardown has the same shape: a view destroyed while a resolve is still in flight has to handle the callback arriving against a DOM that no longer exists.

Values also arrive without their presentation. A numeric point's value is a raw number in the point's own units, and the unit, the precision and the enumeration text live in the point's facets. Reading the value and appending a hard-coded degree symbol produces a display that is wrong as soon as the point is reconfigured or a station is engineered in different units. Enumerated and boolean points are worse, because the active and inactive text is site specific: a BooleanWritable that reads "On" and "Off" in one station is "Occupied" and "Unoccupied" in the next. Ask the object for its display string when what you want is the display string.

Every value also carries status, and the two are read separately. getValue() returns a number; getStatus() returns the flags that say whether the number means anything. A point that has lost its device still holds the last value it received, and nothing about that number indicates the device stopped answering an hour ago. An interface that renders only the value cannot distinguish a stable space temperature from a dead one, which is the failure operators notice last and forgive least.

  • down: the device or network behind the point is not communicating, and what is displayed is the last value received.
  • fault: the station could not produce a usable value at all. Mapping and configuration errors surface here rather than as missing data.
  • stale: the value has not refreshed inside its configured tolerance, so it is current only by assumption.
  • disabled: the point or a parent has been taken out of service and is no longer being updated.
  • overridden: something is holding the value at a commanded level rather than the normal one, which an operator needs to see before acting on it.
  • null: no value has ever been received. Distinct from zero, and worth rendering as its own state rather than as a number.

How the Browser Actually Reaches the Station

The live part of BajaScript rides on a WebSocket opened back to the station's web service after the page has authenticated. The ordinary HTTP request that loads the page and the socket that keeps it live are separate things, which is why transport failures are confusing to diagnose: the interface loads, the layout renders, the labels are right, and only the values are frozen. The page scheme constrains the socket as well. A page served over HTTPS cannot open a plain ws:// connection, and the browser blocks it as mixed content with nothing visible in the interface to say so. Where a station presents a self signed certificate, the exception a user clicks through for the page does not reliably carry to the socket, so the page loads and the socket is refused.

Anything in the path that does not forward the upgrade fails the same way. A reverse proxy has to pass the Upgrade and Connection headers through to the station rather than handling the request as a normal HTTP proxy pass, and default configurations frequently do not.

Idle timeouts are the other half of it. A subscription that is quiet because nothing has changed looks exactly like an abandoned connection to an intermediate hop, which closes it. nginx defaults proxy_read_timeout to 60 seconds, and corporate VPN concentrators and load balancers apply idle limits of their own, so an interface can work for a minute and then stop updating with no error anywhere. The diagnostic is quick: filter the browser network panel to WS and check whether the handshake returned 101 Switching Protocols or a normal HTTP status, then watch whether the socket closes on a fixed interval, which points at a timeout rather than a configuration error. Two things are worth ruling out before blaming the path at all.

  • Confirm in Workbench that the point is actually changing. From the browser, a genuinely static value is indistinguishable from a subscription that is not delivering.
  • Check whether the web session itself expired. When the session times out the socket goes with it, and a page left open overnight shows a complete interface holding values from whenever that happened.

Where a Subscription Actually Lands

A subscription that costs the station also costs the field bus. Subscribing to a proxy point is not a read of something already sitting in memory; it tells the driver that someone is watching. Under the Niagara driver model a proxy point is polled while something is subscribed to it, at the rate its poll frequency and tuning policy specify, and it falls out of the poll cycle once the last subscriber is gone. Opening a dashboard therefore changes traffic on the trunk, not only load inside the station.

What that costs depends on the bus underneath. A BACnet MS/TP segment shares one serial line across every device on it, and a Modbus serial trunk works through register blocks one request at a time; both have a ceiling on requests per second that no amount of station CPU moves. Two hundred newly subscribed points on a segment that was comfortable at its normal poll rate can stretch scan times far enough that unrelated points on the same trunk start going stale.

The practical response is to decide the required update rate per value rather than per page. A discharge air temperature someone is watching during commissioning and a monthly runtime total do not need the same treatment, and a screen that treats every value on it as equally urgent asks the trunk for work nobody reads. Fast polling for the handful of values that drive a decision, normal or slow for the context around them.

Histories, BQL and Data Volume

Live values and historical values reach the browser by different paths, and only the first one is a subscription. History data is queried: an ORD against a history, usually carrying a BQL query, returns a record set and then it is done. Nothing pushes, and asking again is a new query. That is why a trend chart and a live gauge on the same screen behave differently under load and have to be reasoned about separately.

The cost of a history query is the record count, and it is easy to ask for far more than can be shown. A year of 15 minute data for one point is about 35,000 records, and a chart 600 pixels wide can resolve a few hundred. Sending all 35,000 to the browser so JavaScript can average them down spends station time, network time and browser memory to draw the same picture a rolled up query would have returned. Ask the station for the span and the resolution you are actually going to render, and let the query do the aggregation.

What can be queried at all was fixed long before the interface existed. A point with no history extension has nothing to query, and the collection interval on that extension sets the finest granularity anyone will ever see; adding an extension today does not create last year. Collection type matters too. An interval history has evenly spaced timestamps while a change of value history records only changes, so charting code that assumes regular spacing will misdraw one of the two. Two further decisions sit with the chart rather than with the history.

  • Whether the chart updates live, refreshes on a timer, or loads once when the view opens. Each is a different amount of work for the station and a different meaning for the word current.
  • How gaps are drawn. A station that was offline, or an extension that was disabled for a while, leaves a hole in the record set, and a line interpolated straight across two missing days reads to an operator as data.

Where BajaScript Is the Wrong Tool

When the consumer is a system rather than a person, a browser API is the wrong shape for the problem. Niagara exposes oBIX over HTTP, and a station side export or a driver can hand data to another server with no browser session in the path at all. Pointing a headless browser at a dashboard to harvest the numbers it displays is the version of this that tends to get built anyway, and it inherits the entire presentation stack: session handling, render timing, layout. A cosmetic change to a widget breaks the integration.

The same applies when a third party defines the format the data has to arrive in. A utility, an analytics platform or an incentive program that specifies a layout, a cadence and an endpoint has described a station side job, and the mapping to that specification belongs where the data is rather than in the layer that draws it.

There is also a floor under the effort. A BajaScript interface is a module: a project structure, a build, signing, a version, and a path onto every station expected to serve it. That overhead is the same whether the view shows two values or two hundred, and it does not shrink as the requirement does.

Frequently Asked Questions

What has to exist on the station before a BajaScript interface can run?

A station reachable over the network with its web service enabled, users and roles carrying the permissions the interface will need, and the points themselves already present and named. BajaScript reads the object model that is there; it does not create points, drivers or histories. If the data is not in the station yet, or exists under names that only mean something to the engineer who typed them, that is integration and naming work that comes first.

How does a finished interface get onto a station?

As a Niagara module, installed the way any other module is. The module file goes onto the platform, the station is restarted, and the views inside it are reached through an ORD or added to the nav tree. Recent N4 platforms enforce module signing, and where they do the signing certificate has to be trusted by the platform, so certificate handling is part of deployment rather than something discovered at the end. Every station that serves the interface needs the module, which matters when the same views run on a Supervisor and on several JACEs.

Can the interface be reached from outside the building network?

Yes, by the same routes as any other Niagara web access: a VPN into the network, or a reverse proxy published for the station. Which of those to use is an IT decision rather than a Niagara one, and it carries its own authentication and certificate questions. Whichever route is chosen, every hop added to the path has to satisfy the same upgrade and idle timeout constraints described above.

Do existing Px graphics have to be replaced?

No. Px views and a BajaScript module live on the same station at the same time, and either can link to the other, so a Px nav can open a custom view and a custom view can hand an operator back to a Px equipment graphic. Adoption can be one screen at a time.

Can a BajaScript interface show data that does not come from Niagara?

Yes, but where the join happens matters more than whether it is possible. The browser can call an outside API directly, which keeps the station out of it but subjects the interface to CORS rules and requires that service to be reachable from wherever the operator is sitting. Bringing the data into the station instead, as points or through a driver, makes it available to alarms, histories, control logic and every other client rather than to this one page. If the value only ever gets looked at, the browser can fetch it; if anything else in the system has to react to it, it belongs in the station.

What does the customer have to provide or decide?

A point list with the names the interface will bind to, and a test account carrying the roles operators will actually have rather than an admin account, since a view built and demonstrated under admin permissions can fail on the floor when the station refuses an action. The decisions are which devices and browsers have to work, and what the interface should show when a value is down, stale or overridden rather than simply present. That last one goes undecided more often than any other and shapes a surprising amount of the design.

Which browsers does a BajaScript interface have to support?

That is set by the build rather than by BajaScript. The transpile targets in the pipeline decide which browsers the shipped bundle runs on, so the practical answer is whatever the project was configured for. The constraint worth naming early is any fixed panel, kiosk or embedded WebView on site, because those often run an engine years behind the phones and laptops everyone tests on and are usually the screens left open the longest. Test on the actual panel, not on a desktop browser resized to its dimensions.