У меня есть система Unity, которая подключается к одному из этих адаптеров на базе Bluetooth ELM327, которые возвращают данные, в моем случае это спидометр, моя проблема в следующем: если я попробую ее на SEAT Ibiza Mk-4 (2008-2017), она работает нормально, только когда я попробую ее на Audi A3 8L (1996-2000), у которой есть порт OBD-II, но я предполагаю он работает по системе K-Line, а не по CAN-шине, как в новых автомобилях, и то, что он делает, очень странно, адаптер запускается, в тот момент, когда я начинаю читать, он получает немного данных обратно, то есть скорость, обороты, нагрузку двигателя 1 или 2 раза, а затем просто зависает со всеми сигналами: XX XX НЕТ ДАННЫХ, это то, что меня сбивает с толку, тот факт, что он работает в течение 2 секунд, затем он выходит из строя, я попробовал инициализировать его для K-линии Я попробовал систему, которая ожидает ответа перед отправкой другого, попробовал получить только скорость и обороты, так как у некоторых автомобилей нет некоторых значений, таких как уровень топлива, положение дроссельной заслонки и т. д., все равно делает то же самое. Если кто-нибудь знает, что может происходить, я бы хотел вашей помощи, моя реальная система работает с библиотекой Java aab, подключенной к сценарию, и я предполагаю, что код в порядке, так как он отлично работает на новой машине, но все же посмотрите, в чем может быть проблема, (и еще одна вещь: у меня есть читалка с качеством PDF плюс адаптер, я понятия не имею об этом, но вот ссылка, чтобы увидеть продукт самостоятельно: https://www.emag.ro/tester-auto-interfa ... /D01R19BBM):
using System;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.SceneManagement;
using System.Collections.Generic;
public class OBDIIManage : MonoBehaviour
{
public static OBDIIManage _instance;
private AndroidJavaObject obd;
private bool isConnected = false;
private bool isReading = false;
public float rpm;
public float speed;
public float throttle;
public float engineLoad;
public float fuelLevel;
public float coolantTemp;
public string lastsend;
private string pattern = "SRTSRLSRTSRLSRTSRLSRCSRLSRTSRLSRTSRLSRTSRLSRFSRC";
private int patternIndex = 0;
private char lastCommand;
public Action ontick;
public string[] devs;
public RectTransform deviceList;
public GameObject deviceLObj;
public Button refBt;
public Image ConnectBox;
public Text CBText;
public GameObject MMenu;
public GameObject MMenu2;
public List MBts;
public List Textures;
float nextSendTime = 0f;
float sendInterval = 0.01f;
bool usingKLine = false;
void Awake()
{
if (_instance == null) {
_instance = this;
DontDestroyOnLoad(gameObject);
SceneManager.sceneLoaded += OnSceneLoaded;
} else {
Destroy(gameObject);
}
}
void Start()
{
#if UNITY_ANDROID && !UNITY_EDITOR
AndroidJavaClass unityPlayer =
new AndroidJavaClass("com.unity3d.player.UnityPlayer");
AndroidJavaObject activity =
unityPlayer.GetStatic("currentActivity");
obd = new AndroidJavaObject(
"com.example.obdplugin.BluetoothOBD",
activity
);
#endif
int useK = PlayerPrefs.GetInt("KLINEMODE", 0);
ToggleKMode(useK == 1, true);
}
public string[] GetPairedDevices()
{
#if UNITY_ANDROID && !UNITY_EDITOR
return obd.Call("getAvailableDevices");
#else
return new string[0];
#endif
}
public bool Connect(string mac)
{
#if UNITY_ANDROID && !UNITY_EDITOR
isConnected = obd.Call("connect", mac);
return isConnected;
#else
return false;
#endif
}
public void InitELM(int uK) {
usingKLine = (uK == 1);
nextSendTime = Time.time;
Send("ATZ");
Send("ATE0");
Send("ATL0");
Send("ATS0");
Send("ATH0");
if (usingKLine) {
sendInterval = 0.15f;
Send("ATAT0");
Send("ATSTFF");
Send("ATSP5");
} else {
sendInterval = 0.01f;
Send("ATAT2");
Send("ATSP0");
}
}
public void ToggleKMode(bool tr, bool realconnect) {
if(tr) { pattern = "SRSRSRSR";
MBts[0].GetComponent().sprite = Textures[0];
MBts[1].GetComponent().sprite = Textures[1];
PlayerPrefs.SetInt("KLINEMODE", 1); if (realconnect) { InitELM(1); }
} else { pattern = "SRTSRLSRTSRLSRTSRLSRCSRLSRTSRLSRTSRLSRTSRLSRFSRC";
MBts[1].GetComponent().sprite = Textures[0];
MBts[0].GetComponent().sprite = Textures[1];
PlayerPrefs.SetInt("KLINEMODE", 0); if (realconnect) { InitELM(0); }
}
}
void Update() {
if (!isReading) return;
string res = obd.Call("getAndClearResponse");
if (!string.IsNullOrEmpty(res)) {
lastsend = res;
ParseByLastCommand(res);
ontick?.Invoke();
} if (Time.time >= nextSendTime) {
SendNext(); nextSendTime = Time.time + sendInterval;
}
}
void SendNext()
{
char p = pattern[patternIndex];
patternIndex = (patternIndex + 1) % pattern.Length;
lastCommand = p;
switch (p)
{
case 'R': Send("010C"); break;
case 'S': Send("010D"); break;
case 'T': Send("0111"); break;
case 'L': Send("0104"); break;
case 'F': Send("012F"); break;
case 'C': Send("0105"); break;
}
}
void Send(string cmd) {
if (obd != null) obd.Call("sendCommand", cmd);
}
public void StartReading()
{
if (!isConnected || isReading) return;
isReading = true;
}
public void StopReading()
{
isReading = false;
}
void ParseByLastCommand(string res)
{
float val;
switch (lastCommand)
{
case 'R':
val = ParseRPM(res);
if (!float.IsNaN(val)) rpm = val;
break;
case 'S':
val = ParseSpeed(res);
if (!float.IsNaN(val)) speed = val;
break;
case 'T':
val = ParseThrottle(res);
if (!float.IsNaN(val)) throttle = val;
break;
case 'L':
val = ParseLoad(res);
if (!float.IsNaN(val)) engineLoad = val;
break;
case 'F':
val = ParseFuel(res);
if (!float.IsNaN(val)) fuelLevel = val;
break;
case 'C':
val = ParseCoolant(res);
if (!float.IsNaN(val)) coolantTemp = val;
break;
}
}
private string Clean(string res)
{
res = res.Replace("\r", "")
.Replace("\n", "")
.Replace(">", "")
.Trim();
if (!res.Contains(" ") && res.Length % 2 == 0)
{
System.Text.StringBuilder sb = new System.Text.StringBuilder();
for (int i = 0; i < res.Length; i += 2)
{
sb.Append(res.Substring(i, 2));
sb.Append(" ");
}
res = sb.ToString().Trim();
}
return res;
}
float ParseRPM(string res)
{
try
{
string[] p = Clean(res).Split(' ');
if (p.Length < 4) return float.NaN;
int A = Convert.ToInt32(p[2], 16);
int B = Convert.ToInt32(p[3], 16);
return ((A * 256) + B) / 4f;
}
catch { return float.NaN; }
}
float ParseSpeed(string res)
{
try
{
string[] p = Clean(res).Split(' ');
if (p.Length < 3) return float.NaN;
int A = Convert.ToInt32(p[2], 16);
return A;
}
catch { return float.NaN; }
}
float ParseThrottle(string res)
{
try
{
string[] p = Clean(res).Split(' ');
if (p.Length < 3) return float.NaN;
int A = Convert.ToInt32(p[2], 16);
return (A * 100f) / 255f;
}
catch { return float.NaN; }
}
float ParseLoad(string res)
{
try
{
string[] p = Clean(res).Split(' ');
if (p.Length < 3) return float.NaN;
int A = Convert.ToInt32(p[2], 16);
return (A * 100f) / 255f;
}
catch { return float.NaN; }
}
float ParseFuel(string res)
{
try
{
string[] p = Clean(res).Split(' ');
if (p.Length < 3) return float.NaN;
int A = Convert.ToInt32(p[2], 16);
return (A * 100f) / 255f;
}
catch { return float.NaN; }
}
float ParseCoolant(string res)
{
try
{
string[] p = Clean(res).Split(' ');
if (p.Length < 3) return float.NaN;
int A = Convert.ToInt32(p[2], 16);
return A - 40f;
}
catch { return float.NaN; }
}
void OnSceneLoaded(Scene scene, LoadSceneMode mode) {
MBts.Clear(); MMenu = GameObject.Find("SettingMenu");
MMenu2 = GameObject.Find("(OBDMENU");
deviceList = GameObject.Find("DVL").GetComponent();
deviceLObj = GameObject.Find("DVLCL");
refBt = GameObject.Find("rfbt").GetComponent();
ConnectBox = GameObject.Find("DB").GetComponent();
CBText = ConnectBox.transform.GetChild(0).GetComponent();
MBts.Add(GameObject.Find("KLBTN1").GetComponent());
MBts.Add(GameObject.Find("KLBTN2").GetComponent());
MBts[0].onClick.AddListener(() => { ToggleKMode(false, isReading); });
MBts[1].onClick.AddListener(() => { ToggleKMode(true, isReading); });
refBt.onClick.AddListener(() => { RefList(); });
MMenu2.SetActive(false);
MMenu.SetActive(false);
deviceLObj.SetActive(false);
RefList();
}
public void RefList()
{
devs = GetPairedDevices();
foreach (Transform fs in deviceList)
Destroy(fs);
for (int f = 0; f < devs.Length; f++)
{
GameObject newBtn = Instantiate(deviceLObj, deviceList);
newBtn.SetActive(true);
newBtn.GetComponent().anchoredPosition =
new Vector2(0f, -10f + (-120f * f));
int splitpos = devs[f].IndexOf('|');
int lbf = f;
newBtn.transform.GetChild(0).GetComponent().text =
devs[f].Remove(splitpos);
newBtn.GetComponent().onClick.AddListener(() =>
{
StartCoroutine(AttemptConnect(devs[lbf]));
});
}
deviceList.sizeDelta =
new Vector2(deviceList.sizeDelta.x, 20f + (120f * devs.Length));
}
public System.Collections.IEnumerator AttemptConnect(string full)
{
ConnectBox.color = Color.white;
CBText.fontSize = 38;
CBText.text = "Connecting...";
string[] split = full.Split('|');
yield return null;
bool connct = Connect(split[1]);
if (connct) {
ConnectBox.color = new Color(0.45f, 1f, 0.5f);
CBText.fontSize = 60;
CBText.text = split[0];
nextSendTime = Time.time;
int useK = PlayerPrefs.GetInt("KLINEMODE", 0);
obd.Call("getAndClearResponse");
StartReading(); ToggleKMode(useK == 1, true);
}
else
{
ConnectBox.color = Color.red;
CBText.text = "Connection Failed";
}
}
}