176 lines
6.0 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

using System;
using System.Collections.Generic;
using System.Text;
using UnityEngine;
public static class ComPortScanner
{
// Параметры соединения
private const int BaudRate = 115200;
private const int DataBits = 8;
private const int Parity = 0; // 0 = None
private const int StopBits = 1; // 1 = One
private const int ReadTimeoutMs = 5;
private const int WriteTimeoutMs = 10;
// Команды устройств
private const string CmdPrize = "97"; // Для витрины и периферийника2
private const string CmdControllerV1 = "666"; // Только для периферийника1
// Типы устройств
public enum DeviceType
{
None,
ControllerV1, // Периферийник1
ControllerV2, // Периферийник2
PrizeShowcase // Витрина
}
// Префиксы ответов
private const string ControllerV1ResponsePrefix = "ENC:"; // Периферийник1 на 666
private const string ControllerV1NotActivatedPrefix = "NOT_ACTIVATED:"; // Периферийник1 на всё остальное
private const string RolePrefix = "ROLE :"; // Периферийник2 и витрина на 97
private const string PrizeRoleValue = "vitrina"; // Витрина: ROLE : vitrina
/// <summary>
/// Сканирует все доступные COM-порты и возвращает словарь {порт = тип устройства}
/// </summary>
public static Dictionary<string, DeviceType> ScanPorts()
{
var result = new Dictionary<string, DeviceType>();
string[] ports = ComNativeWrapper.ListPorts();
foreach (string port in ports)
{
DeviceType type = CheckPort(port);
if (type != DeviceType.None)
{
result[port] = type;
}
}
return result;
}
/// <summary>
/// Проверяет один порт на наличие известных устройств
/// </summary>
private static DeviceType CheckPort(string port)
{
Debug.Log($"Проверка порта {port}");
// ШАГ 1: Проверяем периферийник1 по команде 666
string response666 = CheckDevice(port, CmdControllerV1);
if (response666 != null)
{
// Если ответ начинается с "ENC:" - это точно периферийник1
if (response666.StartsWith(ControllerV1ResponsePrefix) || response666.StartsWith("ALREADY_ACTIVATED"))
{
return DeviceType.ControllerV1;
}
}
// ШАГ 2: Проверяем по команде 97 (витрина и периферийник2)
string response97 = CheckDevice(port, CmdPrize);
if (response97 != null && response97.StartsWith(RolePrefix))
{
Debug.Log($"Role: {response97}");
// Извлекаем значение после "ROLE : "
string roleValue = response97.Substring(RolePrefix.Length).Trim();
// Если роль = "vitrina" - это витрина
if (string.Equals(roleValue, PrizeRoleValue, StringComparison.OrdinalIgnoreCase))
{
return DeviceType.PrizeShowcase;
}
else
{
return DeviceType.ControllerV2;
}
}
// ШАГ 3: Дополнительная проверка для неактивированного периферийника1
// Если устройство ответило на 97 с "NOT_ACTIVATED:" - это периферийник1
if (response97 != null && response97.StartsWith(ControllerV1NotActivatedPrefix))
{
return DeviceType.ControllerV1;
}
return DeviceType.None;
}
/// <summary>
/// Очищает входной буфер порта
/// </summary>
private static void ClearPortBuffer(int handle)
{
byte[] tempBuffer = new byte[1024];
const float idleTimeout = 0.5f;
const int maxreads = 50;
int reads = 0;
float startTime = Time.unscaledTime;
while (reads < maxreads)
{
int bytesRead = ComNativeWrapper.Serial_ReadLineUTF8_bytes(handle, tempBuffer, tempBuffer.Length);
reads++;
if (bytesRead > 0)
{
startTime = Time.unscaledTime;
continue;
}
else if (bytesRead == 0)
{
float elapsed = Time.unscaledTime - startTime;
if (elapsed >= idleTimeout)
{
break;
}
}
else
{
break;
}
}
}
/// <summary>
/// Проверяет устройство на порту и возвращает ответ
/// </summary>
private static string CheckDevice(string port, string command)
{
int handle = ComNativeWrapper.Serial_Open(port, BaudRate, DataBits, Parity, StopBits, 10, WriteTimeoutMs);
if (handle <= 0)
{
return null;
}
try
{
ClearPortBuffer(handle);
int writeResult = ComNativeWrapper.Serial_WriteStringUTF8(handle, command, 1);
if (writeResult < 0)
{
return null;
}
byte[] buffer = new byte[1024];
int bytesRead = ComNativeWrapper.Serial_ReadLineUTF8_bytes(handle, buffer, buffer.Length);
if (bytesRead <= 0)
{
return null;
}
string line = Encoding.UTF8.GetString(buffer, 0, bytesRead).Trim();
return string.IsNullOrEmpty(line) ? null : line;
}
finally
{
ComNativeWrapper.Serial_CloseAll();
}
}
}