Problems with my Unity App on Android not receiving data -- I'm so lost

Please forgive me if this is the wrong place to post this. If this is wrong, I will repost it elsewhere! Thank you.

My son has Cerebral Palsy and I’m working on an AR project to help him see his feet in motion as he learns to walk. It has sensors in his feet which are controlled by two esp32s. One of them is USB cabled to an Android phone. Everything works fine on the computer and the data is coming into the phone correctly over Serial USB Terminal…but I can’t get it to drive my Unity App on the phone. I think it is an Android permissions problem but have no idea what to do…where to go.

The code is as follows: the serialReader receives the data. The DataParser does that and drives the two feet game objects.

Eeeeeekkkk I’m going crazy. To the point that if anyone lives in the UK—-ANYWHERE!—-I will drive to you and pay to have this done with!!!

Thank you very much in advance,
Marc

//serialReader
using System;
using System.IO.Ports;
using UnityEngine;

public class serialReader : MonoBehaviour
{
//    private string portName = "/dev/ttyACM0"; 
    private string portName = "/dev/cu.usbmodem59090306541"; 
    private int baudRate = 115200; 
    private SerialPort serialPort;

    public delegate void OnSerialDataReceived(string data);
    public static event OnSerialDataReceived DataReceived;

    void Start()
    {
        serialPort = new SerialPort(portName, baudRate);
        try
        {
            serialPort.Open();
            serialPort.ReadTimeout = 100;
        }
        catch (System.Exception ex)
        {
            Debug.LogError($"Failed to open serial port: {ex.Message}");
        } 
    }
    void Update()
    {
        if (serialPort != null && serialPort.IsOpen)
        {
            try
            {
                string data = serialPort.ReadLine();
                DataReceived?.Invoke(data);
                Debug.Log($"Raw Data Received from Serial: {data}");
            } 
            catch (TimeoutException) { }
        }
    }
    void OnDestroy()
    {
        if (serialPort != null && serialPort.IsOpen)
        {
            serialPort.Close();
        }
    }
}
//DataParser
using UnityEngine;
using System;

public class DataParser : MonoBehaviour
{

    private float scalingFactorAngles = 1f;    
    private float scalingFactorDistanceFromGround = 1f;
    public GameObject objectToMove;
    private float objectHeight;
    public GameObject leftObject; // Assign in the inspector
    public GameObject rightObject; // Assign in the inspector


    void Start()
    {
    Debug.Log("Unity logging test.");
    } 


    void OnEnable()
    {
        serialReader.DataReceived += ParseData;
    }

    void OnDisable()
    {
        serialReader.DataReceived -= ParseData;
    }

void ParseData(string data)
{
    // Debugging: Log the raw incoming data
     Debug.Log($"Raw Data Received: {data}");

    // Validate the input to avoid null or empty strings
    if (string.IsNullOrEmpty(data))
    {
        Debug.LogWarning("Received null or empty data.");
        return;
    }

    // Skip irrelevant or debug-like messages
    if (data.StartsWith("load:") || data.Contains("len:"))
    {
//      Debug.LogWarning($"Skipping irrelevant debug message: {data}");
        return;
    }

    // Split the data by '|'
    string[] parts = data.Split('|');
    if (parts.Length == 2)
    {
        // Split the left and right data
        string[] leftData = parts[0].Split(',');
        string[] rightData = parts[1].Split(',');

        // Ensure both left and right data have the expected number of elements
        if (leftData.Length == 5 && rightData.Length == 5)
        {
            UpdateLeftObject(leftData);
            UpdateRightObject(rightData);
        }
        else
        {
            Debug.LogWarning($"Unexpected data format in parts: LeftData({leftData.Length}), RightData({rightData.Length}).");
        }
    }
    else
    {
        Debug.LogError($"Invalid data format: {data}");
    }
}

    void UpdateLeftObject(string[] data)
    { 
 

            //  transform.position = new Vector3(300f, unityHeight*100, -560f);
                leftObject.transform.position = new Vector3(-40f, (unityLeftHeight*90)-75, 50f);
    }
    void UpdateRightObject(string[] data)
    {

        }
  

    float MapValue(float input, float inputMin, float inputMax, float outputMin, float outputMax)
        {
           return outputMin + (input - inputMin) * (outputMax - outputMin) / (inputMax - inputMin);
        }
}

Do you see any errors? You could use Android Logcat package to analyse what’s happening on the device.

Thank you! I tried this and don’t understand how to use it…or what I’m looking at. I know the data is coming into the phone because I can see it in the USB terminal app…(which asks me for permission to be used!) and yet I can’t see what I’m doing wrong because my unity App doesn’t ask.

Here is the manifest.xml in assets/plugins/Android/

<?xml version="1.0" encoding="utf-8"?>
<manifest
    

    xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.ARFeetGOD">

    <uses-feature android:name="android.hardware.usb.host" />

    <application>
            <receiver android:name=".UsbBroadcastReceiver"
                android:exported="true">
            <intent-filter>
                <action android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED" />
            </intent-filter>
        </receiver>
        <!--Used when Application Entry is set to Activity, otherwise remove this activity block-->
        <activity android:name="com.unity3d.player.UnityPlayerActivity"
                  android:theme="@style/UnityThemeSelector">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
            <meta-data android:name="unityplayer.UnityActivity" android:value="true" />
        </activity>
        <!--Used when Application Entry is set to GameActivity, otherwise remove this activity block-->
        <activity android:name="com.unity3d.player.UnityPlayerGameActivity"
                  android:theme="@style/BaseUnityGameActivityTheme">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
            <meta-data android:name="unityplayer.UnityActivity" android:value="true" />
            <meta-data android:name="android.app.lib_name" android:value="game" />
        </activity>
    </application>
</manifest>   

And here is the USBPermissionHandler in the same place…

using UnityEngine;

public class USBPermissionHandler : MonoBehaviour
{
    private const string ACTION_USB_PERMISSION = "com.ARFeetGOD.USB_PERMISSION";

    void Start()
    {
        RequestUSBPermission();
    }

    void RequestUSBPermission()
    {
        try
        {
            // Get the Android Context
            using (AndroidJavaObject activity = new AndroidJavaClass("com.unity3d.player.UnityPlayer")
                                                    .GetStatic<AndroidJavaObject>("currentActivity"))
            using (AndroidJavaObject usbManager = activity.Call<AndroidJavaObject>("getSystemService", "usb"))
            {
                // Get a list of attached USB devices (simplified for example purposes)
                AndroidJavaObject[] devices = usbManager.Call<AndroidJavaObject[]>("getDeviceList");

                if (devices.Length > 0)
                {
                    AndroidJavaObject device = devices[0]; // Use the first connected USB device

                    // Check if permission is already granted
                    bool hasPermission = usbManager.Call<bool>("hasPermission", device);
                    if (!hasPermission)
                    {
                        // Request permission
                        AndroidJavaObject intent = new AndroidJavaObject("android.content.Intent", ACTION_USB_PERMISSION);
                        AndroidJavaClass pendingIntentClass = new AndroidJavaClass("android.app.PendingIntent");
                        AndroidJavaObject pendingIntent = pendingIntentClass.CallStatic<AndroidJavaObject>(
                        "getBroadcast", activity, 0, intent, 0);

                        usbManager.Call("requestPermission", device, pendingIntent);
                    }
                }
            }
        }
        catch (System.Exception e)
        {
            Debug.LogError($"Error requesting USB permission: {e.Message}");
        }
    }
}

Thank you very much for any help possible!
Marc