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; /// /// 初始化七段数码管控制器 /// /// 七段数码管控制器IP地址 /// 七段数码管控制器端口 /// 任务ID /// 超时时间(毫秒) 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> 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> 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; } }