HomeCase studiesA Field Operator Mobile Application for Metered...

Case study · Dublin, Ireland

A Field Operator Mobile Application for Metered Fuel Dispensing

Fleet and site fuel management — the operational point where fuel is physically transferred into a vehicle or plant asset

Fuel leaves the tank whether or not anyone writes it down accurately. Our team built a cross-platform mobile application that puts the fuel transfer itself under the operator's phone: the asset is identified and its meter reading captured before dispensing can begin, the volume recorded is the metered volume reported by the equipment rather than a figure entered afterwards, and an unfinished transfer survives the app being closed. Because refuelling happens where signal does not reach, the application also talks to the dispensing controller directly over Bluetooth Low Energy, so the operator's job completes with no network at all.

Industry
Fleet and site fuel management — the operational point where fuel is physically transferred into a vehicle or plant asset
Solution
A cross-platform mobile application for field operators, built from a single codebase for native mobile and web delivery, consuming a REST backend and integrating directly with dispensing hardware over Bluetooth Low Energy.
Platforms
Web & API
Stack
Vue · TypeScript
Location
Dublin, Ireland · delivered remotely
Role
Engineering, with the team behind for mobile and QA

Delivered remotely for a business based in Dublin, Ireland. Names withheld by agreement.

Project Overview

Industry: Fleet and site fuel management — the operational point where fuel is physically transferred into a vehicle or plant asset.

Type of solution: A cross-platform mobile application for field operators, built from a single codebase for native mobile and web delivery, consuming a REST backend and integrating directly with dispensing hardware over Bluetooth Low Energy.

Business context: Fuel is among the largest controllable costs in any fleet or site operation, and most of what is lost is lost in the recording rather than in the tank. Three facts have to be captured at the moment of transfer — which asset received the fuel, how much went in, and what that asset's odometer or engine-hour reading was at the time. Captured on paper, or from memory at the end of a shift, they drift apart. Once they have drifted, consumption per asset is unusable, which means maintenance intervals are guesses and cost allocation is fiction.

General users: Field operators — fuel-truck drivers, depot attendants and site refuellers. Administrative and reporting users work in the backend platform rather than in this application.

General purpose: To make the fuel transfer itself the recording event. Nothing can be dispensed until the asset and its meter reading are captured, and the quantity recorded comes from the equipment rather than from a person.

The Business Challenge

The record is made after the fact, so it is wrong. An operator fuelling a dozen assets across a shift is reconstructing details at the end of it. The volume is approximate, the meter reading is estimated, and occasionally the asset is simply the wrong one.

Consumption data is only as good as the meter reading beside it. Litres alone say nothing. Litres against a distance or engine-hour reading is the number the business actually needs, and it is the half most likely to be missing or invented.

Different assets are measured differently. A road vehicle is measured in distance; a generator, excavator or pump is measured in engine hours. The application cannot assume one, and asking the operator to know which is asking them to get it wrong.

Refuelling happens where there is no signal. Depots, quarries, remote sites, yards between buildings. An application that requires connectivity to do its job will be worked around within a week, and the paper process comes straight back.

The transfer takes minutes, and phones do not always survive them. Fuel flows for as long as it flows. If the application is closed, backgrounded out of memory or the phone dies mid-transfer, the transaction cannot be lost — fuel has physically moved and something must account for it.

Physical equipment does not respond on a software timescale. A start command may take a long time to be acknowledged, or may never be. The interface has to remain honest and recoverable when the equipment does not answer.

The environment is hostile to interfaces. Sunlight, gloves, one hand on a nozzle, noise. Anything requiring precision or attention will be skipped.

Operational rules differ between deployments. Whether a work-order reference is required, and which dispensing points a given operator may use, vary by site and by customer — and cannot require a new release each time.

Our Approach

Make the workflow gate the equipment, not follow it. The sequence is deliberate: authenticate, choose a dispensing point, identify the asset, capture its meter reading, and only then start the transfer. The gate is the point of the product. By the time fuel moves, everything the business needs to attribute it has already been captured, and the operator has not been asked to remember anything afterwards.

Take the quantity from the equipment. Dispensed volume and flow-meter telemetry are read from the dispensing controller and displayed live during the transfer. The recorded figure is the metered figure. There is no field in which a person types how much they think went in.

Treat no-signal as a supported mode, not a failure. The application checks connectivity at the moment the operator signs in and, finding none, routes directly into a Bluetooth path that talks to the dispensing controller without any server involvement. This is deliberately not offline queueing: the operator's actual task completes rather than being recorded for later reconciliation.

Hold transaction state on the server so the client can be disposable. The dispensing transaction is owned by the backend. When an operator authenticates, any unfinished transfer comes back with their session and the application re-enters the live screen and resumes following it. A phone that crashed mid-transfer recovers by being unlocked and reopened.

Bound every operation against physical equipment. Both starting and stopping a transfer are wrapped in explicit timeouts with a defined outcome. Equipment that never answers produces a recoverable state and a clear message rather than a spinner the operator eventually force-quits.

Build the form from the server's requirements. Whether an asset needs a distance or an engine-hours reading, and whether a work-order reference is mandatory, are both returned by the backend. The operator is asked for exactly the right thing without knowing why, and a customer with different rules is a configuration change rather than a release.

Reduce each screen to one action. A single large primary button, colour-coded and re-labelled as the state changes, with the current asset, meter reading and live volume above it. Nothing else on the screen during a transfer, and back navigation disabled while fuel is flowing.

One codebase, every target. The application is built with a cross-platform framework that compiles the same source to native mobile applications and to web, so a device fleet is served from a single release cycle.

The Solution

Operator sign-in with assigned dispensing points. Authentication returns the operator's identity, session and the specific dispensing points they are permitted to use, with unavailable points shown but not selectable.

Consent gate. A privacy agreement is presented and must be accepted before first use, with the full agreement readable in the application.

Multilingual interface. Language can be changed at any point from any screen, with the choice persisted across sessions — a practical necessity for a mixed field workforce.

Asset identification. The operator enters the asset number, which is confirmed against the backend. The response carries the asset's identity, its current and previous meter values, and which class of meter reading it requires.

Adaptive meter reading capture. The form renders a distance reading or an engine-hours reading according to the asset's requirement, with validation to match, plus an optional work-order reference where the deployment requires one.

Live dispensing session. Starting the transfer opens a monitored session showing dispensed volume and flow-meter telemetry updating throughout, with the asset and meter reading held on screen for confirmation and a clear safety instruction and caution notice.

Automatic and manual completion. The session ends automatically when the equipment signals that the transfer is complete, or immediately when the operator stops it. Both paths close the transaction the same way.

Transfer resumption. An unfinished transfer is returned at the operator's next sign-in and the application re-enters the live session and resumes following it, on the same device or another.

Direct equipment control without connectivity. Where there is no signal, the application discovers the dispensing controller over Bluetooth Low Energy, connects to it, subscribes to its telemetry and controls the transfer directly through a binary protocol, showing fill progress from the controller's own reporting.

On-site receipt printing. A thermal printing capability over the same Bluetooth transport, with formatted text, barcode and QR code output, so a paper record can be produced at the point of transfer.

Session integrity. Session expiry is detected centrally, clearing local state and returning the operator to sign-in with an explanation rather than failing silently mid-workflow.

Key Features

Enforced capture-before-dispense workflow The transfer cannot begin until the asset is identified and its meter reading captured, making the recording a precondition of the physical act rather than a task that follows it.

Metered volume from the equipment Dispensed volume and flow-meter telemetry are read live from the dispensing controller during the transfer, so the recorded quantity is measured rather than reported.

Adaptive meter capture by asset class Distance or engine-hours capture is selected by a requirement returned with the asset, so each asset is measured correctly without the operator having to know which applies.

Offline direct equipment control Where there is no network, the application connects to the dispensing controller over Bluetooth Low Energy and drives the transfer directly, so the operator's task completes rather than being deferred.

Server-held transactions with client resumption An unfinished transfer is returned at the next sign-in and the application resumes following it, so a crashed or dead phone does not lose fuel that has physically moved.

Watchdog-bounded equipment operations Start and stop are both bounded by explicit timeouts with defined outcomes, so unresponsive equipment produces a recoverable state rather than an indefinite wait.

Single-action field interface Each screen reduces to one large primary action, colour-coded and re-labelled as the state changes, with back navigation disabled during an active transfer.

Server-driven operational configuration Permitted dispensing points, meter requirements and optional work-order capture are all returned by the backend, so deployments with different rules are configured rather than rebuilt.

Runtime language switching The interface language can be changed at any point and is remembered, supporting a mixed workforce without separate builds.

On-site thermal receipt printing Formatted receipts including barcode and QR output can be produced over the same Bluetooth transport at the point of transfer.

Technical Architecture

Client application. A cross-platform mobile client built with a modern reactive JavaScript framework and typed throughout, compiled from a single source to native mobile applications and to web delivery. Screens are organised as a linear workflow with file-based routing and shared layouts.

Workflow state layer. Each step's output is written into a small, single-purpose state store rather than passed through navigation parameters — session and identity, workflow selections, active transaction handle, and interface language held separately. Session and language are persisted to device storage; workflow state deliberately is not.

Network layer. A single HTTP wrapper behind a global request interceptor that attaches the API base address, query serialisation, request timeout, session token and client platform. Responses are classified into three distinct outcomes — transport failure, application-level business rejection and session expiry — each producing different behaviour rather than a single generic error.

Access control layer. A navigation interceptor enforces authentication on any screen that declares it requires one, applied uniformly across every navigation method rather than per-screen.

Live session layer. The dispensing screen runs three request lifecycles against one transaction — start, periodic telemetry poll and stop — deriving the entire interface state from polled telemetry through a reactive effect, with independent watchdog timers bounding the start and stop operations.

Direct equipment layer. An independent control path that bypasses the API entirely: a promise-based wrapper over the platform's Bluetooth Low Energy interface handling adapter initialisation, device discovery with signal strength, connection, service and characteristic enumeration, telemetry subscription with binary frame parsing, and command transmission. Device identifiers are persisted so reconnection skips rediscovery.

Printing layer. A thermal printer command builder with text styling, alignment, barcode and cut control, multi-codepage text encoding, and QR code rendering, sharing the Bluetooth transport.

Localisation layer. Message catalogues with runtime locale switching and a non-component translation helper so network and interceptor code can produce localised messages outside the component tree.

Flow: Operator sign-in → assigned dispensing point → asset identification → adaptive meter capture → transfer start → periodic telemetry → automatic or manual stop, with a parallel path of connectivity check → direct Bluetooth connection → controller telemetry and command → on-site receipt.

Technology Stack

Category Technology
Application framework Vue 3 with the composition API, TypeScript
Cross-platform framework uni-app, targeting native mobile and web from one codebase
Build tooling Vite with per-environment configuration and production minification
State management Pinia with a persisted-state plugin bound to device storage
Internationalisation vue-i18n with runtime locale switching
Styling UnoCSS atomic CSS with platform-specific presets, SCSS
UI components Cross-platform component library for forms, inputs, overlays and notifications
Request lifecycle Composable request hooks with polling and manual-trigger modes
Hardware integration Bluetooth Low Energy through the platform API, wrapped in a promise-based device class
Peripheral output ESC/POS thermal printer command builder with multi-codepage encoding and QR generation
Routing File-based routing with layouts and declarative authentication requirements
Code quality ESLint, Prettier, Stylelint, commitlint with staged-file hooks, static type checking
Backend interface REST API with token-based session authentication

Technical Challenges & Solutions

Challenge Our Approach
Refuelling happens where there is no mobile signal, and an application that stops working there gets abandoned Connectivity is checked at sign-in and, where absent, the application routes into a direct Bluetooth path that controls the dispensing controller with no server involvement — the operator's task completes rather than being queued for later reconciliation.
Fuel keeps flowing even if the phone does not The dispensing transaction is owned by the backend and returned with the operator's session at next sign-in, so the application re-enters the live screen and resumes following an unfinished transfer — on the same device or a different one.
The client sees a continuous physical process only as periodic snapshots The live screen derives its entire state — started, running, complete — from polled telemetry through a single reactive effect combining volume, flow-meter readings, fill progress and the equipment's own completion signal, rather than from local assumptions about timing.
Physical equipment does not respond on a software timescale Both start and stop are bounded by explicit watchdog timers with defined fallback states, so unresponsive equipment degrades into a recoverable, clearly labelled UI state instead of an indefinite wait.
Different assets must be measured in different units, and operators should not have to know which The meter requirement is returned with the asset and the capture form is constructed from it, rendering either a distance or an engine-hours field with matching validation.
Operational rules differ between deployments and cannot require a release each time Permitted dispensing points, meter requirements and optional work-order capture are all server-returned configuration delivered with the session, so a new deployment's rules are configured rather than coded.
Interfaces used outdoors, in gloves, one-handed, holding a nozzle Each screen reduces to a single large primary action, colour-coded and re-labelled by state, with the safety instruction and live figures above it and back navigation disabled while fuel is flowing.
Driving a hardware controller through a callback-based, device-inconsistent platform API The Bluetooth interface is isolated behind a promise-based device class handling adapter state, discovery, service and characteristic enumeration, subscription and transmission, with identifiers persisted for silent reconnection.
One workforce, multiple languages, one build Message catalogues with runtime switching from any screen and a persisted preference, plus a translation helper usable outside the component tree so network-layer messages are localised too.

Security & Reliability

Token-based sessions. Authentication returns a session token attached to every subsequent request by a single global interceptor rather than per call, so no request path can accidentally omit it.

Centralised session-expiry handling. Expiry is detected in one place in the network layer, which clears local state and returns the operator to sign-in with an explanation — rather than surfacing as an unexplained failure part-way through a workflow.

Declarative route protection. Screens declare whether they require authentication, and a navigation interceptor enforces it across every navigation method uniformly.

Explicit consent. A privacy agreement is presented and must be accepted before first authentication, with the full text readable in the application.

Server-held transaction state. Because the transaction lives on the backend rather than on the device, a lost, broken or replaced phone does not lose a record of fuel that has physically moved.

Bounded physical operations. Watchdog timers around start and stop guarantee that the interface reaches a defined, recoverable state regardless of whether the equipment responds.

Interference protection during a transfer. Back navigation is disabled at the platform level while fuel is flowing, so a transfer cannot be abandoned by accident mid-operation.

Separated error semantics. Transport failure, application-level business rejection and session expiry are handled as three distinct outcomes, so operators are told what actually happened rather than being shown one generic message.

Scalability & Performance

Small by construction. Few dependencies, no heavy client-side libraries, atomic CSS generated only for what is used, and production builds minified with development logging stripped — appropriate for devices that are often not new.

Bounded network behaviour. The client holds one active transaction and no list data of any size, and telemetry polling runs at a fixed interval independent of load, so per-session request volume is predictable and capacity planning is a simple function of concurrent dispensing sessions.

Disciplined timer and lifecycle management. All timers are cleared on unmount and polling is cancelled on completion, so a long shift of consecutive transfers does not accumulate background work.

Minimal persistence. Only session and language preference are written to device storage; workflow state is held in memory, keeping storage access infrequent.

Fast Bluetooth reconnection. Device, service and characteristic identifiers are persisted after first pairing, so subsequent connections skip discovery entirely — meaningful when an operator reconnects to the same controller many times a day.

Single release cycle across platforms. Because native and web targets build from one codebase, rolling an update to a device fleet is one release rather than several.

Compatibility with older devices. A runtime polyfill for missing platform methods is applied selectively at startup instead of shipping a broad compatibility bundle, keeping the payload small while supporting older hardware still in service.

Business Outcomes

  • The record is created at the moment of transfer, not reconstructed at the end of a shift, because dispensing cannot begin until the asset and meter reading are captured.
  • Recorded volumes are metered volumes, read from the dispensing equipment rather than entered by a person afterwards.
  • Every transfer carries a usable meter reading, in the unit appropriate to that asset, which is the pairing that makes consumption-per-asset analysis possible at all.
  • Refuelling continues where there is no signal, through direct equipment control, so the paper fallback does not need to exist.
  • Interrupted transfers are not lost, because the transaction is held server-side and resumed at the operator's next sign-in.
  • Operators are asked for exactly what each asset requires, with the form determined by server-returned configuration rather than by operator knowledge.
  • New deployments with different operational rules are configured rather than rebuilt, since permitted dispensing points and capture requirements arrive with the session.
  • A mixed-language workforce uses one application, with language switchable at any point and remembered.

Why it worked

Software that controls physical equipment is a different discipline from software that manages records. The failure modes are not exceptions to be caught — they are a valve that did not answer, a phone that died with fuel flowing, a depot with no coverage, a pair of gloves that cannot hit a small button. None of those are edge cases in this environment. They are Tuesday.

Our team builds for that reality. We put the recording before the physical act rather than after it, because a workflow that asks for data once the fuel is already in the tank is a workflow that gets skipped. We treated no-connectivity as a supported mode with its own control path rather than as an error state with a queue, because operators judge a tool by whether their job finished. We put the transaction on the server so the device could be disposable. And we bounded every operation against physical equipment with an explicit timeout and a defined outcome, because the fastest way to lose a field workforce is to show them a spinner they cannot escape.

Our teams work across cross-platform mobile development, hardware integration over Bluetooth Low Energy and serial protocols, REST API integration, offline-capable architectures and multilingual field applications — with the operational judgement to know which parts of a physical process the software must control and which it should only observe.

Final Summary

Fuel management fails at the last metre. Whatever the reporting platform can do, the numbers reaching it are only as good as what an operator recorded standing next to a running nozzle — and standing next to a running nozzle, with a clipboard, at the end of a long shift, is where accuracy goes.

Our team built the mobile application that closes that gap. The operator signs in, selects a dispensing point they are permitted to use, identifies the asset and enters its meter reading — in distance or engine hours, whichever that asset requires, determined by the system rather than the operator — and only then can fuel move. Throughout the transfer the screen shows the volume and flow-meter telemetry reported by the equipment itself, and the session ends when the equipment says it has, or when the operator stops it. The figure that reaches the business is measured, not remembered.

Two decisions carry the product beyond that. The transaction is owned by the backend, so a phone that crashes mid-transfer is recovered by unlocking it — the unfinished transfer comes back with the next sign-in and the application picks it up where it stopped. And because refuelling happens in quarries, depots and yards where signal does not reach, the application can abandon the network entirely and drive the dispensing controller directly over Bluetooth, complete the transfer and print a receipt on the spot. Delivered from a single cross-platform codebase, with a multilingual single-action interface built for sunlight and gloves, it makes the accurate record the easiest available path — which, for a field tool, is the only way one ever gets used.

01 — Questions

asked about this kind of project

How do you build a mobile app that controls physical equipment?

Start from the failure modes rather than the happy path. Equipment does not respond on a software timescale, so every command needs an explicit timeout with a defined outcome. State should be derived from what the equipment reports rather than from what the app assumes after sending a command. And the interface has to remain honest when the equipment is silent — a bounded, recoverable state with a clear message, never an indefinite spinner.

How should a field application handle no connectivity?

It depends on what the user is actually trying to finish. Offline queueing is the right answer when the task is recording something. When the task is operating equipment, queueing does not help — the operator still cannot do their job. Where the hardware supports it, a direct local control path over Bluetooth lets the work complete with no network at all, which is a materially stronger answer than deferred synchronisation.

What happens if the app is closed during a long-running physical operation?

Nothing should be lost, and the way to guarantee that is to not hold the transaction on the device. Where the server owns the transaction, any client that authenticates can be handed the unfinished operation and resume following it — on the same device or a different one. That is simpler and far more reliable than a local recovery journal, and it survives a phone that is dropped rather than merely closed.

Why capture a meter reading before dispensing rather than after?

Because after does not happen. A workflow that asks for data once the physical task is complete is a workflow that gets abandoned under time pressure, and the data is reconstructed later, inaccurately. Making the capture a precondition of the equipment starting is the difference between a system that has readings and one that has gaps.

How do you support different measurement requirements across an asset fleet?

Return the requirement with the asset and build the form from it. Road vehicles are measured in distance and plant equipment in engine hours, and asking the operator to know which applies is asking for errors. When the requirement is server-side configuration, the operator is simply asked the right question, and a customer with different rules is a configuration change rather than a release.

What makes a mobile interface work in field conditions?

Ruthless reduction. Sunlight, gloves, noise and one free hand mean anything requiring precision gets skipped. One large primary action per screen, colour and label changing with state, the critical information directly above it, and nothing else competing for attention. During a hazardous operation, remove the ability to navigate away at all.

Is cross-platform development appropriate for hardware-integrated apps?

Often, yes. Modern cross-platform frameworks expose Bluetooth, device information, connectivity and storage well enough for most industrial integrations, and a single codebase serving a mixed device fleet from one release cycle is a substantial operational advantage for the customer. The judgement call is whether the hardware protocol needs platform-specific behaviour the framework cannot reach — worth establishing early, because it is expensive to discover late.

How do you decide between polling and push for live telemetry?

Polling is the right starting point when sessions are short, concurrency is low and the backend already holds the state — it is simple, predictable and easy to reason about under failure. The cost is linear: every concurrent session is a fixed request rate. The signal to move to push or long-polling is concurrency growth, not elegance, and designing the client so the state is derived from telemetry rather than from the transport makes that migration straightforward later.

03 — Similar project?

describe what is different about yours

Build yours.

Tell me what exists, what you need and the deadline. Fixed price for a defined scope, or hourly from $10 with a written estimate first.

Ahmedabad, India · IST (UTC+5:30) · --:-- IST · Mon–Fri 09:00–18:00 IST · US & EU overlap daily

No newsletter, no CRM. Just a reply.