LilyGO + ASI Biont: Build a LoRa GPS Tracker with AI-Powered Alerts in Minutes

Introduction

You’ve got a LilyGO board—maybe a T-Beam, T3-S3, or TTGO LoRa32—with built-in LoRa radio, GPS module, and an ESP32 brain. It’s perfect for outdoor tracking, meshtastic nodes, or remote sensor nodes. But turning raw GPS coordinates and sensor data into actionable alerts (like “send me a Telegram message when the tracker enters a geofence”) usually means writing custom server code, setting up a database, and building a notification pipeline. That’s where ASI Biont changes the game.

ASI Biont is an AI agent that connects to any device—including LilyGO—through chat. You describe what you want, and it writes the integration code, runs it in a cloud sandbox, and talks to your hardware via MQTT, COM port (via Hardware Bridge), or HTTP. No dashboards, no “add device” buttons—just a conversation. In this guide, I’ll show you how to connect a LilyGO T-Beam (with GPS and LoRa) to ASI Biont, stream live coordinates, and get Telegram alerts when the tracker enters a predefined zone. All using real protocols and libraries that ASI Biont supports.

Why Connect LilyGO to an AI Agent?

LilyGO boards are powerful IoT devices, but they lack native cloud AI. By connecting to ASI Biont, you gain:

  • Real-time AI analysis: The agent can process GPS data, detect anomalies (e.g., sudden speed changes), and trigger actions.
  • Natural language control: Say “turn on the LED when I’m near the office” and AI configures the logic.
  • No coding required for logic: AI writes the Python glue code for MQTT, Modbus, or serial communication.
  • Multi-protocol support: MQTT, HTTP, CoAP, or direct serial—whichever your LilyGO firmware uses.

How ASI Biont Connects to LilyGO

ASI Biont does not have a built-in LilyGO driver. Instead, it uses execute_python—a sandboxed Python environment that runs on ASI Biont’s cloud servers (Railway). The AI agent writes a Python script that uses paho-mqtt (or pyserial via Hardware Bridge) to communicate with your LilyGO board. You provide the connection parameters (MQTT broker address, topic, or COM port) in the chat, and AI generates the code on the fly.

For this guide, we’ll use MQTT because:
- LilyGO ESP32 runs MicroPython or Arduino firmware with MQTT support.
- MQTT is lightweight, works over Wi-Fi, and supports bidirectional messaging.
- ASI Biont’s sandbox has paho-mqtt pre-installed.

If your LilyGO is not Wi-Fi enabled (e.g., it’s a stand-alone LoRa node without Wi-Fi), you can use Hardware Bridge—a bridge.py script that runs on your PC, connects to ASI Biont via WebSocket, and relays serial commands to the LilyGO over USB. For this article, we’ll assume Wi-Fi connectivity.

Use Case: GPS Tracker with Geofence Alerts via Telegram

Scenario: You have a LilyGO T-Beam (ESP32 + NEO-6M GPS + LoRa) mounted on a delivery bike. It sends GPS coordinates every 10 seconds over MQTT. You want ASI Biont to:
1. Receive the MQTT messages.
2. Parse latitude and longitude.
3. Compare against a geofence circle (center: your warehouse, radius: 500 m).
4. If the tracker enters or leaves the geofence, send a Telegram message to your phone.

Step 1: LilyGO Firmware (MicroPython)

Flash your LilyGO with MicroPython firmware (we’ll use a simple script).

from machine import Pin, UART
import time
import ujson
from umqtt.simple import MQTTClient

# WiFi and MQTT config
WIFI_SSID = "your_wifi"
WIFI_PASS = "your_password"
MQTT_BROKER = "192.168.1.100"  # your broker IP
MQTT_TOPIC = b"lilygo/gps"
CLIENT_ID = "lilygo_tbeam"

def connect_wifi():
    import network
    wlan = network.WLAN(network.STA_IF)
    wlan.active(True)
    wlan.connect(WIFI_SSID, WIFI_PASS)
    while not wlan.isconnected():
        time.sleep(1)
    print("WiFi connected")

def read_gps(uart):
    line = uart.readline()
    if line and line.startswith(b"$GPGGA"):
        parts = line.decode().split(",")
        if parts[2] and parts[4]:
            lat = float(parts[2][:2]) + float(parts[2][2:])/60.0
            lon = float(parts[4][:3]) + float(parts[4][3:])/60.0
            return {"lat": lat, "lon": lon}
    return None

def main():
    connect_wifi()
    uart = UART(1, baudrate=9600, tx=12, rx=13)
    client = MQTTClient(CLIENT_ID, MQTT_BROKER)
    client.connect()
    print("Connected to MQTT broker")
    while True:
        gps = read_gps(uart)
        if gps:
            payload = ujson.dumps(gps)
            client.publish(MQTT_TOPIC, payload)
            print("Sent:", payload)
        time.sleep(10)

main()

Note: Adjust UART pins for your specific LilyGO board (T-Beam uses TX=12, RX=13). Upload via ampy or Thonny.

Step 2: ASI Biont Integration via Chat

Open ASI Biont chat and tell the AI:

“Connect to MQTT broker at 192.168.1.100, topic lilygo/gps. Subscribe to messages, parse latitude and longitude. Define a geofence center at 40.7128°N, 74.0060°W with radius 500 meters. If the GPS point is inside, publish to MQTT topic ‘lilygo/inside’ with message ‘inside’. If outside, publish ‘outside’. Also send me a Telegram alert when state changes. My Telegram chat ID is 123456789, bot token is YOUR_BOT_TOKEN.”

ASI Biont will generate and execute the following sandboxed Python script:

import paho.mqtt.client as mqtt
import json
import asyncio
from math import radians, sin, cos, sqrt, atan2

# Configuration
BROKER = "192.168.1.100"
TOPIC_IN = "lilygo/gps"
TOPIC_OUT = "lilygo/inside"
TELEGRAM_BOT_TOKEN = "YOUR_BOT_TOKEN"
TELEGRAM_CHAT_ID = "123456789"

# Geofence: center (lat, lon) in degrees, radius in meters
CENTER_LAT = 40.7128
CENTER_LON = -74.0060
RADIUS_M = 500.0

previous_state = None  # None, "inside", "outside"

def haversine(lat1, lon1, lat2, lon2):
    R = 6371000
    phi1, phi2 = radians(lat1), radians(lat2)
    dphi = radians(lat2 - lat1)
    dlambda = radians(lon2 - lon1)
    a = sin(dphi/2)**2 + cos(phi1)*cos(phi2)*sin(dlambda/2)**2
    return R * 2 * atan2(sqrt(a), sqrt(1-a))

def send_telegram(message):
    import requests
    url = f"https://api.telegram.org/bot{TELEGRAM_BOT_TOKEN}/sendMessage"
    data = {"chat_id": TELEGRAM_CHAT_ID, "text": message}
    try:
        requests.post(url, json=data, timeout=5)
    except Exception as e:
        print("Telegram error:", e)

def on_connect(client, userdata, flags, rc):
    print("Connected to broker")
    client.subscribe(TOPIC_IN)

def on_message(client, userdata, msg):
    global previous_state
    try:
        data = json.loads(msg.payload)
        lat = data["lat"]
        lon = data["lon"]
        distance = haversine(lat, lon, CENTER_LAT, CENTER_LON)
        state = "inside" if distance <= RADIUS_M else "outside"
        if state != previous_state:
            previous_state = state
            client.publish(TOPIC_OUT, state)
            send_telegram(f"Tracker state changed to {state} (distance: {distance:.1f}m)")
            print(f"State: {state}, distance: {distance:.1f}m")
    except Exception as e:
        print("Error processing message:", e)

client = mqtt.Client()
client.on_connect = on_connect
client.on_message = on_message
client.connect(BROKER, 1883, 60)
client.loop_forever()

Important: The script runs in ASI Biont’s sandbox with a 30-second timeout. For long-running MQTT subscriptions, ASI Biont keeps the script alive as a background task (the AI manages this automatically). The script uses loop_forever(), which is allowed for background tasks.

Step 3: Results

  • Every 10 seconds, LilyGO sends GPS data to lilygo/gps.
  • ASI Biont processes the message, calculates distance to the geofence center.
  • When the tracker crosses the 500 m boundary, it publishes the new state to lilygo/inside.
  • A Telegram message is sent: “Tracker state changed to inside (distance: 320.5m)”.

You can also ask the AI: “What is the current location of the tracker?” — the AI will query the last received MQTT message and respond in chat.

Alternative: Connect via Hardware Bridge (Serial)

If your LilyGO does not have Wi-Fi (e.g., it’s a LoRa-only node), you can connect it via USB to a PC running bridge.py. The AI uses the serial:// protocol.

  1. Download bridge.py from ASI Biont dashboard (Devices → Create API Key → Download bridge).
  2. Run: python bridge.py --token=YOUR_TOKEN --ports=COM3 --baud=115200
  3. In chat, tell the AI: “Connect to serial port COM3 at 115200 baud. Read GPS data in NMEA format. Alert me if the device sends $GPGGA with latitude > 50.”

The AI will use industrial_command(protocol='serial://', command='serial_write_and_read', data='...') to communicate.

Benefits of AI-Driven Integration

  • Zero boilerplate: No need to write MQTT subscriber scripts, state machines, or notification logic manually.
  • Natural language control: Change geofence radius, add new alerts, or switch protocols by just talking to the AI.
  • Multi-protocol: ASI Biont supports MQTT, Modbus, BACnet, OPC UA, CoAP, HTTP, and more—all from the same chat interface.
  • Real-time: The AI agent runs continuously in the background, reacting to device data instantly.

Pitfalls to Avoid

  1. MQTT broker security: If your broker is public, use TLS and authentication. ASI Biont supports paho-mqtt with TLS.
  2. GPS accuracy: NEO-6M modules have ~2.5 m accuracy. Geofence radius should be >10 m to avoid false triggers.
  3. Sandbox timeout: Long-running scripts (like MQTT subscribers) are handled as background tasks—don’t use while True in execute_python; the AI manages the loop for you.
  4. NMEA parsing: The example uses $GPGGA. Ensure your GPS module outputs this sentence (enable via UBX commands or use a library like micropyGPS).

Conclusion

Connecting a LilyGO board to ASI Biont unlocks powerful AI-driven automation without writing server infrastructure. In this guide, you turned a GPS tracker into a geofence-aware system that sends Telegram alerts—all through a chat conversation. The same approach works for temperature sensors, LoRa nodes, or any IoT device that speaks MQTT, serial, or HTTP.

Try it yourself: Go to asibiont.com, create an account, and tell the AI: “Connect to my LilyGO T-Beam over MQTT at 192.168.1.100, topic lilygo/gps, and warn me when the battery is low.” No coding—just chat. The future of IoT automation is conversational.

← All posts

Comments