using CommunityToolkit.Mvvm.ComponentModel; using CommunityToolkit.Mvvm.Input; using Siemens.Simatic.Simulation.Runtime; using Newtonsoft.Json; using System.Text.RegularExpressions; using System.Text.RegularExpressions; using System.Threading.Tasks; using Siemens.Simatic.Simulation.Runtime; namespace LibS7Adv { public partial class PLCViewModel : ObservableObject { [JsonIgnore] private IInstance Instance { get; set; } private bool IsConfigured { get; set; } public PLCViewModel() { } public void ucLoaded() { IsConnected = false; lastError = ""; connectionStatus = "offline"; } [ObservableProperty] string iP = "10.1.30.11"; [ObservableProperty] string name = "PLC Name"; [ObservableProperty] string cpuTime; [ObservableProperty] string connectionStatus; [ObservableProperty] string lastError; [ObservableProperty] [property: JsonIgnore] bool isConnected; [RelayCommand] [property: JsonIgnore] public void Connect() { try { // Implementa la conexión utilizando PLCModel Instance = SimulationRuntimeManager.CreateInterface(Name); Instance.OnSoftwareConfigurationChanged += Instance_OnSoftwareConfigurationChanged; //_plcModel.Instance.CommunicationInterface = ECommunicationInterface.Softbus; if (Instance != null) { UpdateTagList(); ConnectionStatus = Instance.OperatingState.ToString(); IsConnected = true; } } catch (Exception ex) { LastError = ex.Message; ConnectionStatus = "offline"; } } private void Instance_OnSoftwareConfigurationChanged(IInstance instance, SOnSoftwareConfigChangedParameter event_param) { UpdateTagList(); } [RelayCommand] [property: JsonIgnore] public void Disconnect() { IsConnected = false; ConnectionStatus = "offline"; Instance = null; } public void UpdateTagList() { IsConfigured = false; try { Instance?.UpdateTagList(ETagListDetails.IO | ETagListDetails.DB | ETagListDetails.M, true); // ETagListDetails.IO | ETagListDetails.DB IsConfigured = true; } catch (Exception ex) { LastError = ex.Message; } } public bool? LeerBool(string sTag) { try { if (!isConnected) { LastError = "Not Connected"; return false; } if (sTag == null) { return false; } var tag = ParseTagAddress(sTag); if (tag.tagType == EDataType.Unknown) // Normal Tag? { return Instance?.ReadBool(sTag); } else if (tag.tagType == EDataType.Bool) { // Read not Work for ImputArea if (tag.areaType == EArea.Output) return Instance?.OutputArea.ReadBit(tag.word_offset, tag.bit); if (tag.areaType == EArea.Marker) return Instance?.MarkerArea.ReadBit(tag.word_offset, tag.bit); } return false; } catch (Exception ex) { LastError = sTag + ":" + ex.Message; return false; } } public bool? EscribirBool(string sTag, bool Value) { try { if (!isConnected) { LastError = "Not Connected"; return false; } if (sTag == null) { return false; } var tag = ParseTagAddress(sTag); if (tag.tagType == EDataType.Unknown) // Normal Tag? { Instance?.WriteBool(sTag, Value); } else if (tag.tagType == EDataType.Bool) { if (tag.areaType == EArea.Input) Instance?.OutputArea.WriteBit(tag.word_offset, tag.bit, Value); if (tag.areaType == EArea.Output) Instance?.OutputArea.WriteBit(tag.word_offset, tag.bit, Value); if (tag.areaType == EArea.Marker) Instance?.MarkerArea.WriteBit(tag.word_offset, tag.bit, Value); } return false; } catch (Exception ex) { LastError = sTag + ":" + ex.Message; return false; } } public string? LeerNumber(string sTag) { try { if (!isConnected) { LastError = "Not Connected"; return ""; } if (sTag == null) { return ""; } var tag = ParseTagAddress(sTag.Trim()); if (tag.tagType == EDataType.Unknown) // Normal Tag? { var data = Instance?.Read(sTag); return data.Value.ToString(); } else if (tag.tagType == EDataType.Byte) { // Read not Work for ImputArea if (tag.areaType == EArea.Output) return Instance?.OutputArea.ReadByte(tag.word_offset).ToString(); if (tag.areaType == EArea.Marker) return Instance?.MarkerArea.ReadByte(tag.word_offset).ToString(); } else if (tag.tagType == EDataType.Word) { // Read not Work for ImputArea if (tag.areaType == EArea.Output) return Instance?.OutputArea.ReadBytes(tag.word_offset,2).ToString(); if (tag.areaType == EArea.Marker) { byte[] bytes = Instance?.MarkerArea.ReadBytes(tag.word_offset, 2); return (bytes[0] + bytes[1]*256).ToString(); } } return ""; } catch (Exception ex) { LastError = sTag + ":" + ex.Message; return ""; } } public bool LeerSalidaBool(byte pByte, int pBit) { try { return Instance?.OutputArea.ReadBit(pByte, (byte)pBit) ?? false; } catch (Exception ex) { LastError = ex.Message; return false; } } public void EscribirInputBool(byte pByte, int pBit, bool pValue) { try { Instance?.InputArea.WriteBit(pByte, (byte)pBit, pValue); } catch (Exception ex) { LastError = ex.Message; } } public void EscribirTag(string pTag, SDataValue Value) { try { Instance?.Write(pTag, Value); } catch (Exception ex) { LastError = pTag + ":" + ex.Message; } } public SDataValue LeerTag(string pTag) { try { return Instance.Read(pTag); } catch (Exception ex) { LastError = pTag + ":" + ex.Message; return new SDataValue(); } } public void EscribirTagBool(string pTag, bool pValue) { try { Instance?.WriteBool(pTag, pValue); } catch (Exception ex) { LastError = pTag + ":" + ex.Message; } } public void EscribirTagInt16(string pTag, int pValue) { try { Instance?.WriteInt16(pTag, (short)pValue); } catch (Exception ex) { LastError = pTag + ":" + ex.Message; } } public bool LeerTagBool(string pTag) { try { return Instance?.ReadBool(pTag) ?? false; } catch (Exception ex) { LastError = pTag + ":" + ex.Message; return false; } } public int? LeerTagInt16(string pTag) { try { return Instance?.ReadInt16(pTag); } catch (Exception ex) { LastError = pTag + ":" + ex.Message; return 0; } } public static TagAddress ParseTagAddress(string tag) { TagAddress tagAddress = new TagAddress(); if (tag==null) return null; if (tag.StartsWith("%")) { if (tag.StartsWith("%DB")) { tagAddress.areaType = EArea.DataBlock; var match = Regex.Match(tag, @"^%DB(\d+)\.DB([X|B|W|D])(\d+)\.(\d+)$"); if (match.Success) { tagAddress.DB = int.Parse(match.Groups[1].Value); char dataTypeChar = match.Groups[2].Value[0]; tagAddress.word_offset = uint.Parse(match.Groups[3].Value); tagAddress.bit = byte.Parse(match.Groups[4].Value); switch (dataTypeChar) { case 'X': tagAddress.tagType = EDataType.Bool; break; case 'B': tagAddress.tagType = EDataType.Byte; break; case 'W': tagAddress.tagType = EDataType.Word; break; case 'D': tagAddress.tagType = EDataType.DWord; break; default: tagAddress.tagType = EDataType.Unknown; break; } } } else if (tag.StartsWith("%M")) { tagAddress.areaType = EArea.Marker; ParseNonDBAddress(tag, tagAddress); } else if (tag.StartsWith("%E")) { tagAddress.areaType = EArea.Input; ParseNonDBAddress(tag, tagAddress); } else if (tag.StartsWith("%A")) { tagAddress.areaType = EArea.Output; ParseNonDBAddress(tag, tagAddress); } else { tagAddress.areaType = EArea.InvalidArea; } } else { // If it's not a direct address, treat it as a tag name tagAddress.areaType = EArea.InvalidArea; tagAddress.tagType = EDataType.Unknown; } return tagAddress; } private static void ParseNonDBAddress(string tag, TagAddress tagAddress) { var match = Regex.Match(tag, @"^%[EMA](\d+)\.(\d+)$"); if (match.Success) { tagAddress.word_offset = uint.Parse(match.Groups[1].Value); tagAddress.bit = byte.Parse(match.Groups[2].Value); tagAddress.tagType = EDataType.Bool; } else { match = Regex.Match(tag, @"^%[EMA]([XBWDF])(\d+)$"); if (match.Success) { char dataTypeChar = match.Groups[1].Value[0]; tagAddress.word_offset = uint.Parse(match.Groups[2].Value); switch (dataTypeChar) { case 'X': tagAddress.tagType = EDataType.Bool; break; case 'B': tagAddress.tagType = EDataType.Byte; break; case 'W': tagAddress.tagType = EDataType.Word; break; case 'D': tagAddress.tagType = EDataType.DWord; break; default: tagAddress.tagType = EDataType.Unknown; break; } } } } } public class TagAddress { public EArea areaType; public EDataType tagType; public int DB; public uint word_offset; public byte bit; } }