80 lines
2.4 KiB
C#
80 lines
2.4 KiB
C#
using System.Net;
|
|
using DotNext;
|
|
using Common;
|
|
|
|
namespace Peripherals.SevenDigitalTubesClient;
|
|
|
|
static class SevenDigitalTubesAddr
|
|
{
|
|
public const UInt32 BASE = 0xB000_0000;
|
|
}
|
|
|
|
public class SevenDigitalTubesCtrl
|
|
{
|
|
private static readonly NLog.Logger logger = NLog.LogManager.GetCurrentClassLogger();
|
|
|
|
readonly int timeout = 500;
|
|
readonly int taskID;
|
|
readonly int port;
|
|
readonly string address;
|
|
private IPEndPoint ep;
|
|
|
|
/// <summary>
|
|
/// 初始化七段数码管控制器
|
|
/// </summary>
|
|
/// <param name="address">七段数码管控制器IP地址</param>
|
|
/// <param name="port">七段数码管控制器端口</param>
|
|
/// <param name="taskID">任务ID</param>
|
|
/// <param name="timeout">超时时间(毫秒)</param>
|
|
public SevenDigitalTubesCtrl(string address, int port, int taskID, int timeout = 500)
|
|
{
|
|
if (timeout < 0)
|
|
throw new ArgumentException("Timeout couldn't be negative", nameof(timeout));
|
|
this.address = address;
|
|
this.port = port;
|
|
this.ep = new IPEndPoint(IPAddress.Parse(address), port);
|
|
this.taskID = taskID;
|
|
this.timeout = timeout;
|
|
}
|
|
|
|
public async ValueTask<Result<byte>> ReadTube(int num)
|
|
{
|
|
if (num < 0 || num > 31)
|
|
throw new ArgumentOutOfRangeException(nameof(num), "Tube number must be between 0 and 31");
|
|
|
|
var ret = await UDPClientPool.ReadAddrByte(
|
|
this.ep, this.taskID, SevenDigitalTubesAddr.BASE + (UInt32)num, this.timeout);
|
|
if (!ret.IsSuccessful)
|
|
{
|
|
logger.Error($"Read tubes failed: {ret.Error}");
|
|
return new(ret.Error);
|
|
}
|
|
if (ret.Value.Options.Data == null || ret.Value.Options.Data.Length < 4)
|
|
return new(new Exception("Data length is too short"));
|
|
|
|
var data = Number.BytesToUInt32(ret.Value.Options.Data, 0, 4).Value;
|
|
|
|
if ((data >> 8) != num)
|
|
{
|
|
logger.Error($"Read wrong tube number: {num} != {data >> 8}");
|
|
return new(new Exception($"Read wrong tube number: {num} != {data >> 8}"));
|
|
}
|
|
|
|
return (byte)(data & 0xFF);
|
|
}
|
|
|
|
public async ValueTask<Result<byte[]>> ScanAllTubes()
|
|
{
|
|
var tubes = new byte[32];
|
|
for (int i = 0; i < 32; i++)
|
|
{
|
|
var ret = await ReadTube(i);
|
|
if (!ret.IsSuccessful)
|
|
return new(ret.Error);
|
|
tubes[i] = ret.Value;
|
|
}
|
|
return tubes;
|
|
}
|
|
|
|
}
|