Car GPS Tracker API

descrition of the available commands

The system has 3 ways to communicate with the end user.

  • Serial/telnet connexion, establishing a telnet session routes the serial messages to IP and back when disconnecting.
  • Web page, pages are stored on the SD card allowing for pages upload.
  • Web socket, providing that the browser can connect to the device on WS, command can be sent to the device.

API Websocket

Web Socket on ws://IP_AdDRESS/ws

  • gps returns a json with gpstate On/Off and gpsreading valid/invalid
  • valid returns a json with gps reading status valid/invalid
  • GPS return a json with the last GPS readings
  • connect connect modem via serial (in case it disconnects)
  • del:fname delete file fname from SD card
  • ATxxx send command ATxxx to modem, modem response is returned to the client as a string

Serial/Telnet commands:

  • AT+cmd execute AT command on modem
  • gps read GPS
  • ping Issue a GPRS/4G ping
  • printgps printgps toggle, when GPS data is display, more information is provided
  • testgps CGPFTM toggle, dumps GPS messages from module (NMEA GAGSV messages), beware this can lock up the device
  • printhex hex flag toggle
  • serialreset reset Modem
  • reset restart module
  • bye disconnect telnet session
  • status state to mqtt
  • dir get SD dirlist
  • del:/filename delete file /fname from SD card

Sample web page to control the unit from a button:

Basically, this webpage holds div containers that can ba loaded from json data provided by websocket transactions from javascript called from a button action.

<!DOCTYPE html>
<html lang="en" class="js csstransforms3d">
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta name="generator" content=""VSCode editor">
    <meta name="description" content="Kialex T-Sim esp32 module">
<meta name="author" content="JP Coenen">
    <title>Kialex T-Sim esp32 module</title>
</head>
<body>
    <header>
    <h1>T-Sim esp32 module</h1>
    </header>
    <main>
    <div id='status'>
        <button id='gpsreading'>GPS Reading</button>
    </div>
    <BR>
    <div id='boutons'>
    <button id='location'>Location (gps)</button>
    <button id='state'>Get State</button>
    <button id='upload'>Upload to SD</button>
    <button id='files'>SD DIr</button>
    <button id='gps-ws'>WS gps</button>
    <button id='gpsquery'>is GPS Valid ?</button>
    <button id='Rconnect'>Reconnect modem</button>
    <button id='OTA'>OTA</button>
    <button id='home'>Home</button><br>
    </div>
    <H2>Called HTML pages</H2>
    <div id='box' style="border: thin solid black"></div>
    <H3>Websocket message</H3>
    <div id='ws-data' style="border: thin solid black"></div>
    <script> 

    const socket = new WebSocket('ws://kialex.local/ws');




    socket.onopen = function(event) {
        // Handle connection open
    };

    socket.onmessage = function(event) {
        document.getElementById('ws-data').innerHTML = "<pre>"+JSON.stringify(JSON.parse(event.data),null,2)+"</pre>";
        const wsmsg = JSON.parse(event.data);
        if (Object.hasOwn(wsmsg, 'gpsreading') ) {
        document.getElementById('gpsreading').innerHTML = wsmsg.gpsreading;
        if (wsmsg.gpsreading == 'valid') {
            document.getElementById('gpsreading').style.backgroundColor = 'lightgreen';
            document.getElementById('gpsreading').removeAttribute("disabled");
        } else {
            document.getElementById('gpsreading').style.backgroundColor = 'red';
            document.getElementById('gpsreading').setAttribute("disabled", "disabled");
        }
        }
    };

    socket.onclose = function(event) {
        // Handle connection close
    };

    function sendMessage(message) {
        console.log('Sending message: ' + message);
        socket.send(message);
    }

        async function getData(url) {
        console.log('getData '+url)
        try {
            const response = await fetch(url);
            if (!response.ok) {
            throw new Error(`Response status: ${response.status}`);
            }

            const result = await response.text();
            console.log(result);
            document.getElementById('box').innerHTML = result;
        } catch (error) {
            console.error(error.message);
        }
    }
        document.getElementById('location').onclick = function() { console.log('calling getdata'); getData('gps'); };
        document.getElementById('state').onclick = function() { console.log('calling getdata'); getData('status'); };
        document.getElementById('upload').onclick = function() {console.log('calling getdata'); getData('upload')}; 
        document.getElementById('files').onclick = function() {console.log('calling getdata'); getData('files')};
        document.getElementById('gps-ws').onclick = function() {console.log('Sending gps to ws'); sendMessage("gps");};
        document.getElementById('gpsquery').onclick = function() {console.log('Sending gps to ws'); sendMessage("valid");};
        document.getElementById('gpsreading').onclick = function() { console.log('Sending GPS to ws'); sendMessage("GPS");};
        document.getElementById('Rconnect').onclick = function() { console.log('Reconnecting modem'); sendMessage("connect");};
        document.getElementById('OTA').onclick = function() {location.replace('/update');}; 

        document.getElementById('home').onclick = function() {location.replace('');}; 
        function delfile(fichier) {alert("del:/"+fichier.name); sendMessage("del:/"+fichier.name);};
    </script>
    </main>
    <footer>
    <p>&copy; 2025 JP Coenen</p>
    </footer>
</body>
</html>