using System; using System.Text.RegularExpressions; namespace StandardScene.Signal.Plc { /// 西门子 DB 字节/位地址拼装与缓冲区位操作。 internal static class PlcAddress { private static readonly Regex Addr = new Regex( @"^DB(\d+)\.(?:DBB|DBX|DBW)?(\d+)(?:\.(\d+))?$", RegexOptions.IgnoreCase | RegexOptions.Compiled); public static string Bit(int db, int absByte, int bit) => $"DB{Math.Max(1, db)}.DBX{Math.Max(0, absByte)}.{ClampBit(bit)}"; public static string Byte(int db, int absByte) => $"DB{Math.Max(1, db)}.DBB{Math.Max(0, absByte)}"; public static int ClampBit(int bit) { if (bit < 0) return 0; if (bit > 7) return 7; return bit; } public static bool TryParse(string address, out int db, out int absByte, out int bit) { db = 0; absByte = 0; bit = 0; if (string.IsNullOrWhiteSpace(address)) return false; var m = Addr.Match(address.Trim()); if (!m.Success) return false; db = int.Parse(m.Groups[1].Value); absByte = int.Parse(m.Groups[2].Value); if (m.Groups[3].Success) bit = ClampBit(int.Parse(m.Groups[3].Value)); return true; } public static bool GetBit(byte[] buffer, int originByte, int absByte, int bit) { var i = absByte - originByte; if (buffer == null || i < 0 || i >= buffer.Length) return false; return (buffer[i] & (1 << ClampBit(bit))) != 0; } public static void SetBit(byte[] buffer, int originByte, int absByte, int bit, bool value) { var i = absByte - originByte; if (buffer == null || i < 0 || i >= buffer.Length) return; var mask = (byte)(1 << ClampBit(bit)); if (value) buffer[i] |= mask; else buffer[i] = (byte)(buffer[i] & ~mask); } } }