EDGE COMPUTING & LBH PROTOCOL

Building Resilient Edge Agents with LBH: A PWA Heartbeat System Running on Android

Two hands reaching toward each other, one digital, one human
Keeping the channel alive between human and edge node

Most edge demos look great on a laptop. They tend to fall apart the moment you put them on a real Android phone, switch apps, or lock the screen.

I'm currently building HormigasAIS, a lightweight edge architecture designed to run agents and services from constrained devices. One of the core pieces is a binary protocol called LBH (Lenguaje Binario HormigasAIS) and a small WebSocket client that keeps the channel alive under real mobile conditions.

This post shows the current state of that client — specifically the heartbeat + telemetry layer — a recent resilience improvement for Android background behavior, and what happened when I moved from a browser demo to an actual installed app on the phone.

The Core: LBHHeartbeatAnt

The client is a single class that manages:

Key design decisions:

Here's the essential part of the heartbeat emission:

emitHeartbeatPheromone() {
  if (!this.ws || this.ws.readyState !== WebSocket.OPEN) return;

  const buffer = new ArrayBuffer(16);
  const view = new DataView(buffer);
  view.setUint8(0, 0x4C); // L
  view.setUint8(1, 0x41); // A
  view.setUint8(2, 0x02); // Heartbeat / Feromona
  view.setUint8(3, 0x01); // Standby flag
  view.setUint32(4, 9999);
  view.setUint32(8, 0);
  view.setUint32(12, Math.floor(Date.now() / 1000));

  this.ws.send(buffer);
}

Telemetry frames follow the same structure (type 0x01) and carry a sensor ID + value.

Real Runtime Behavior

From the Edge Node logs you can see the system working:

🐜 Trama 0x01 | Sensor=1001 | Val=600 | TS=1789366095
⚠️  [AGENTE AUTÓNOMO] Alerta Sensor 1001 → Val=600
🐜 Respuesta LBH enviada

🐜 Trama 0x01 | Sensor=1001 | Val=400 | TS=1789366395
🐜 Respuesta LBH enviada

And the continuous heartbeat ACKs:

❄️  Feromona 0x02 ACK (socket preservado)

The UI on the phone simply shows a telemetry input and a green "Enviar Trama LBH" button. When the channel is healthy it displays "Canal Activo (Descongelado)".

The Android Problem and the Fix

Android browsers are aggressive. When the PWA goes to the background, the WebSocket is often killed without a clean onclose event. The normal 3-second reconnect timer is too slow for a good user experience.

I added a visibilitychange listener:

setupVisibilityListener() {
  document.addEventListener("visibilitychange", () => {
    if (document.hidden) return;

    const isDead = !this.ws ||
      this.ws.readyState === WebSocket.CLOSED ||
      this.ws.readyState === WebSocket.CLOSING;

    if (isDead) {
      this._setState("OFFLINE", "🟡 Verificando canal tras reanudar...");
    }
    this.connect(); // safe to call repeatedly
  });
}

Now, as soon as the user returns to the app, the client checks the socket state and reconnects immediately if needed.

Update — tested as a real installed app, not just a browser tab:

After writing the piece above, I installed the PWA directly on the Android device (using the browser's install prompt, not just a localhost tab) and tested it with split-screen: the app running in one pane, the Edge Node's live log in the other. With the screen locked or the app pushed to the background, the log kept showing Feromona 0x02 ACK entries continuously — confirming the socket survives backgrounding as an installed app, not only as an open tab.

A known rough edge, still open: switching visibility very quickly and repeatedly (fast app-switching) can occasionally log a "cliente conectado" entry before its matching "cliente desconectado" from the previous socket. The server handles both cleanly — no leaked connections, no corrupted frames — but the log ordering isn't strictly sequential in that edge case. It comes from a small gap in the connect() guard (it currently checks for OPEN/CONNECTING but not CLOSING). Tightening that is on the list.

Also worth being upfront about: the current WebSocket server has no authentication layer. Any client on the same local network can send LBH frames to it. Fine for a local dev/demo node — not something to expose on a public network as-is.

Current Focus

This is still early-stage infrastructure. The goal is to turn these lightweight LBH agents into injectable services that universities and small/medium businesses (Pymes) can use without depending on heavy cloud stacks.

The entire development loop (coding, testing, sealing, deploying) happens from an Android device running Termux.

What's Next

If you're working on edge systems, constrained devices, or protocol design and want to exchange notes, feel free to reach out.

Firma de validación LBH:
VALIDADO_ARTICULO_LBH_HEARTBEAT_20260915_CLHQ
Tags: HormigasAIS, LBH Protocol, Edge Computing, Android, PWA, JavaScript, WebSocket

Built and tested on Node A16-SanMiguel-SV | Protocol + client: HormigasAIS

Volver al blog