When Niagara does not do the thing you need, the answer is a module. Custom Niagara module and driver development is the deepest form of Niagara work — writing Java against the Baja API to extend the framework itself rather than configuring what is already there.
This is where most integrators reach their limit and where we do a lot of our work: drivers for equipment with no existing Niagara support, custom components that encapsulate logic your team repeats on every job, and tooling that removes manual Workbench effort.
What We Build
- Protocol drivers — connect equipment Niagara does not support natively, built to behave like a first-class driver rather than a workaround.
- Custom components — encapsulate site-specific or company-specific logic as a reusable, testable component.
- Workbench tools and views — extend the engineering environment your team works in daily.
- Web and UX modules — BajaScript and HTML5 interfaces beyond stock widgets.
- Integration modules — bridge Niagara to enterprise systems, cloud services, or messaging such as MQTT.
- Reporting and data modules — BQL-driven exports and structured data for systems downstream.
The Parts That Decide Whether It Lasts
A module that works on one station and one Niagara version is a prototype. Production module work means version compatibility testing, module signing, sensible upgrade behaviour, and documentation that lets someone other than the author maintain it. We treat those as part of delivery, not extras.
Our own module and tooling work is described on the engineering tools page, including the wiresheet security module.
Describe the equipment or capability you need Niagara to reach and we will tell you whether a module is the right answer — and roughly what it involves.
Related services
- Niagara Framework Development — Back to the full Niagara Framework development overview.
- Wiresheet Security and IP Protection — Related: wiresheet security and IP protection.
When a Module Is Not the Answer
A request described as 'we need a custom driver' does not always need one. Before any Java is written, the requirement gets checked against what the framework already provides: whether the equipment speaks a protocol Niagara already drives, whether the manufacturer sells a gateway that converts it to one, and whether the logic in question can be built from stock components, a Program object, or a template applied across stations. If one of those covers it, that is the better outcome, because it leaves nothing extra to maintain.
A module earns its place in the opposite conditions: no native protocol support and no gateway worth buying, a serial or proprietary protocol that has to be spoken directly, the same logic copied by hand into station after station until the copies drift apart, a view or engineering tool Workbench does not have, or data that has to leave the station in a shape stock exports do not produce.
- A reporting requirement that a BQL query and a scheduled export can satisfy does not need a module.
- A graphics requirement belongs in Px and BajaScript inside a view, not in compiled code.
- A calculation that applies to one site is usually a Program object, not a component type.
- Equipment with a proprietary native protocol may still ship a BACnet or Modbus interface that removes the problem entirely.
How a Module Project Is Structured
Work starts with the requirement and the target, not with code. The target means a specific Niagara version and a specific place the module will run: a controller station, a Supervisor station, or Workbench itself. That choice is made first because the build toolchain, the APIs available, and the memory the module can reasonably consume all follow from it.
For a driver, the next step is proving communication before modeling anything. Reading and writing a handful of points against the actual device, outside the framework, settles whether the protocol documentation matches the device's behavior. Only after that does the protocol get modeled into Baja: network, device, and point types carrying the slots, actions, and tuning policies an engineer would expect to find, so the result is configured the same way the rest of the station is.
Custom components and Workbench tools skip the protocol stage and gain a different one: agreeing on the boundary. A component that absorbs too much turns into a private framework of its own, and the site ends up depending on behavior that is not visible anywhere an engineer looks. A component scoped to one job, with its inputs and outputs on the wiresheet, is the version that survives being handed to someone who was not part of the project.
What the Work Depends On From Your Side
What a module project needs from the customer is mostly access and information, and those are the parts that hold projects up.
- Protocol information. A register map, a point list, a published specification, or a device whose traffic can be captured. If the manufacturer's documentation is under NDA, that agreement has to be in place before the work can rely on it.
- A device to work against. Bench hardware, a spare controller, a simulator, or remote access to a station that has one. Development runs against something out of service wherever possible, and anything that writes to equipment in service happens in a window you agree to in advance.
- A target platform and version. The controller model or Supervisor it runs on, and the Niagara version the fleet is actually on, which is often not the newest one. If stations are spread across versions, that needs to be known at the start rather than discovered at installation.
- A convention to follow. Point naming, tagging, unit handling, and alarm practice already exist on your sites. A module that invents its own creates work for every engineer who touches it afterward.
- Ownership decisions. Who holds the source, how the module is signed, who installs it, and whether it is meant for one site or a portfolio.
Where Module Projects Go Wrong
The failure modes are predictable enough to plan around, and most of them are not coding problems.
- Documentation that does not match the device. A specification describes intended behavior while the firmware does something slightly different. The response is to code against observed traffic from the actual unit and to leave undocumented fields out of scope instead of guessing at them.
- Framework upgrades. When the station moves to a new Niagara release, the module gets rebuilt and retested against it. That is a recurring cost for the life of the site, and it is worth understanding before the first module exists rather than after the fifth.
- Load that only appears at scale. A driver polling one device on a bench says nothing about the same driver polling hundreds on a controller with limited memory. Tuning policies, batched reads, and testing at realistic device counts belong in the project, not in commissioning.
- Scope drift into graphics. A driver's job ends when the points are exposed correctly. Dashboards, Px views, and reporting built on those points are separate work, and folding them into a driver project makes both harder to finish.
- Being the only site that runs it. Custom code written for one unusual case has no other installations pushing its bugs to the surface. That is an argument for keeping custom code small and solving as much as possible with what the framework already does.
Frequently Asked Questions
What is custom Niagara module development, and what is it not?
It is not station configuration or point mapping, not Px graphics work, and not an outside application that talks to a station over an API. The deliverable is a module installed on the platform, whose types show up in the Workbench palette and get configured like any other component. If a stock driver, a template, or a Program object meets the requirement, the work is not module development and should not be scheduled as though it were.
What has to already exist before a driver project can start?
A device the driver can talk to, information about how that device talks, a decision on which Niagara version and platform the module targets, and a station to install into. The device can be bench hardware, a spare controller, or remote access to a live one. The information can be a published specification, a register map, or captured traffic, though capture alone limits support to what the unit happens to do while it is being watched.
How does a module project proceed, in order?
It opens with a review of the requirement against what the framework already provides, and that review can end the project before any code exists. If a module is warranted, communication or logic is proven against the real device or the real condition first, then modeled into Baja types, then built against the agreed Niagara version. It finishes on a pilot station, followed by handoff to the people who will run and maintain it after the project closes.
How does a custom module integrate with the stations we already run?
Inside the station it behaves like the rest of the framework: components on the wiresheet, points that can be trended, alarmed, tagged, and queried with BQL, and configuration through Workbench rather than a separate console. That is the reason for building it as a module instead of as an outside service. Anything that reaches past the station rides on transport the site already runs, authenticating with credentials you issue and can revoke.
Does the module run on a JACE, on a Supervisor, or in Workbench?
Wherever the function belongs, and the answer changes the design. On a controller the module lives with limited memory and CPU, so polling behavior, history writes, and what is held in memory matter more. A Supervisor has more headroom but is usually carrying many stations at once, which changes what is worth doing per point. Some work is Workbench-side only, such as views and engineering tools, and never installs on a controller at all.
What do we have to decide, rather than you?
The target Niagara version and how willing you are to move it later, the naming and tagging convention the module's points follow, who holds the source and how the module is signed, and who installs it on production stations. Those are site and portfolio decisions whose consequences outlast the code. We can recommend on each, but a recommendation is not a decision, and leaving them open until installation causes rework.
What happens to our data, and who has access during development?
Station data stays in your stations. Development runs against bench hardware, a simulator, or a copy of a station wherever that is possible, so the work does not depend on standing access to a live site. Where access to a real station is required, it is access you issue, scope, and revoke, over your VPN or your remote tool rather than a channel of ours. Source and build output go wherever the ownership decision puts them.
Can you take over a module someone else wrote?
Yes, if the source and a working build environment come with it, since a Niagara module's build is tied to a particular version and toolchain. If only a compiled and signed module exists with no source, the realistic options are writing a replacement or wrapping it and working around its behavior, both of which cost more than continuing from source. The original author's license terms govern either way, and that gets checked before the work starts rather than during it.