Sfoglia il codice sorgente

西门子通讯库修改

样式分支
pry 2 anni fa
parent
commit
ec9e78f906
17 ha cambiato i file con 1110 aggiunte e 81 eliminazioni
  1. +7
    -7
      BPASmart.Model/CommDeviceModel/AddressConvert.cs
  2. +2
    -1
      BPASmart.Model/PublishModel.cs
  3. +3
    -3
      BPASmart.Model/VariableInfo.cs
  4. +1
    -1
      BPASmart.Server/BPASmart.Server.csproj
  5. +103
    -21
      BPASmart.Server/CommunicationServer.cs
  6. +1
    -1
      BPASmart.VariableManager/BPASmart.VariableManager.csproj
  7. +45
    -13
      BPASmart.VariableManager/ViewModels/VariableConfigViewModel.cs
  8. +2
    -0
      BPASmartClient.S7Net/BPASmartClient.S7Net.csproj
  9. +205
    -0
      BPASmartClient.S7Net/Conversion.cs
  10. +357
    -0
      BPASmartClient.S7Net/EntityClassResolution.cs
  11. +54
    -33
      BPASmartClient.S7Net/SiemensHelper.cs
  12. +20
    -0
      ComputerTestDemo/ComputerTestDemo.csproj
  13. +135
    -0
      ComputerTestDemo/Form1.Designer.cs
  14. +74
    -0
      ComputerTestDemo/Form1.cs
  15. +60
    -0
      ComputerTestDemo/Form1.resx
  16. +17
    -0
      ComputerTestDemo/Program.cs
  17. +24
    -1
      SmartClient.sln

+ 7
- 7
BPASmart.Model/CommDeviceModel/AddressConvert.cs Vedi File

@@ -12,10 +12,10 @@ namespace BPASmart.Model
public static AddressConvert GetInstance => _Instance ?? (_Instance = new AddressConvert());
private AddressConvert() { }

public int PlcConverter(ICommunicationDevice device, string Address)
public string PlcConverter(ICommunicationDevice device, string Address)
{
int address = -1;
if (Address != null && int.TryParse(Address, out int result)) return result;
string address = string.Empty;
//if (Address != null && int.TryParse(Address, out int result)) return result;
if (device != null && Address != null && Address.Length > 0)
{
switch (device)
@@ -24,7 +24,7 @@ namespace BPASmart.Model
if (Address.ToUpper().Contains("LW") && Address.Length >= 3)
{
var res = Address.Substring(2);
if (res != null && int.TryParse(res, out int LwAddress)) return LwAddress;
if (res != null && int.TryParse(res, out int LwAddress)) return LwAddress.ToString();
}
break;
case kinco _tempKinco:
@@ -37,7 +37,7 @@ namespace BPASmart.Model
{
if (ExitAddress >= 0 && ExitAddress <= 7)
{
return (firstAddress * 8) + 320 + ExitAddress;
return ((firstAddress * 8) + 320 + ExitAddress).ToString();
}
}
}
@@ -45,14 +45,14 @@ namespace BPASmart.Model
else if ((Address.ToUpper().Contains("VW") || Address.ToUpper().Contains("VD")) && Address.Length >= 3)
{
var res = Address.Substring(2);
if (res != null && int.TryParse(res, out int tempAddress)) return (tempAddress / 2) + 100;
if (res != null && int.TryParse(res, out int tempAddress)) return ((tempAddress / 2) + 100).ToString();
}
break;
case KincoOneMachine _tempKincoOneMachine:
if (Address.ToUpper().Contains("D") && Address.Length >= 2)
{
var res = Address.Substring(1);
if (res != null && int.TryParse(res, out int LwAddress)) return LwAddress;
if (res != null && int.TryParse(res, out int LwAddress)) return LwAddress.ToString();
}
break;
default:


+ 2
- 1
BPASmart.Model/PublishModel.cs Vedi File

@@ -9,8 +9,9 @@ namespace BPASmart.Model
public class PublishModel
{
public string DeviceName { get; set; }
public string Address { get; set; }
public string RealAddress { get; set; }
public string Value { get; set; }
public EDataType DataType { get; set; }
public int Sleep { get; set; }

}


+ 3
- 3
BPASmart.Model/VariableInfo.cs Vedi File

@@ -56,8 +56,8 @@ namespace BPASmart.Model
{
_mAddress = value;
OnPropertyChanged();
int address = AddressConvert.GetInstance.PlcConverter(DeviceType, value);
if (address >= 0) RealAddress = address;
string address = AddressConvert.GetInstance.PlcConverter(DeviceType, value);
if (address.Length > 0) RealAddress = address;
}
}
private string _mAddress = string.Empty;
@@ -65,7 +65,7 @@ namespace BPASmart.Model
/// <summary>
/// 实际地址
/// </summary>
public int RealAddress { get; set; }
public string RealAddress { get; set; }

/// <summary>
/// 数据类型


+ 1
- 1
BPASmart.Server/BPASmart.Server.csproj Vedi File

@@ -7,7 +7,7 @@
</PropertyGroup>

<ItemGroup>
<PackageReference Include="BPA.Communication" Version="1.0.9" />
<PackageReference Include="BPA.Communication" Version="1.0.10" />
<PackageReference Include="BPA.Helper" Version="1.0.6" />
</ItemGroup>



+ 103
- 21
BPASmart.Server/CommunicationServer.cs Vedi File

@@ -3,17 +3,24 @@ using BPA.Helper;
using BPA.Communication;
using Microsoft.EntityFrameworkCore.Metadata.Conventions;
using Communication;
using System.Collections.Concurrent;
using Newtonsoft.Json;

namespace BPASmart.Server
{
internal class CommunicationServer : IServer
{
ConcurrentDictionary<string, ICommunication> CommunicationDevices = new ConcurrentDictionary<string, ICommunication>();

public void Init()
{
var tt = sizeof(bool);
BPASmartClient.Message.MessageLog.GetInstance.ShowDebugLog("通讯模块初始化");
RedisHelper.GetInstance.ConnectAsync();
MqttInit();
Json<CommunicationPar>.Data.CommunicationDevices.ToList()?.ForEach(item =>
{

ThreadManage.GetInstance().Start(new Action(() =>
{
switch (item.CommDevice)
@@ -24,6 +31,8 @@ namespace BPASmart.Server
BPA.Communication.ModbusTcp modbusTcpMaster = new BPA.Communication.ModbusTcp();
modbusTcpMaster.ConnectOk = new Action(() =>
{
if (!CommunicationDevices.ContainsKey(item.DeviceName))
CommunicationDevices.TryAdd(item.DeviceName, modbusTcpMaster);
ThreadManage.GetInstance().StartLong(new Action(() =>
{
GetReadDataModels(item).ToList()?.ForEach(temp =>
@@ -33,8 +42,8 @@ namespace BPASmart.Server
case EDataType.Bool:
temp.Value?.ForEach(value =>
{
var res = modbusTcpMaster.ReadCoils(value.StartAddress, value.Length);
SetValue(res, item.DeviceName, value, 1);
var res = modbusTcpMaster.ReadBool(value.StartAddress.ToString(), value.Length);
SetValue(res.Content, item.DeviceName, value, 1);
});
break;
case EDataType.Byte:
@@ -44,8 +53,8 @@ namespace BPASmart.Server
case EDataType.Word:
temp.Value?.ForEach(value =>
{
var res = modbusTcpMaster.ReadHoldingRegisters(value.StartAddress, value.Length);
SetValue(res, item.DeviceName, value, 1);
var res = modbusTcpMaster.ReadUshort(value.StartAddress.ToString(), value.Length);
SetValue(res.Content, item.DeviceName, value, 1);
});
break;
case EDataType.Dint:
@@ -53,15 +62,15 @@ namespace BPASmart.Server
case EDataType.Dword:
temp.Value?.ForEach(value =>
{
var res = modbusTcpMaster.ReadHoldingRegisters(value.StartAddress, value.Length);
SetValue(res, item.DeviceName, value, 2);
var res = modbusTcpMaster.ReadUint(value.StartAddress.ToString(), value.Length);
SetValue(res.Content, item.DeviceName, value, 2);
});
break;
case EDataType.Float:
temp.Value?.ForEach(value =>
{
var res = modbusTcpMaster.ReadHoldingRegisters(value.StartAddress, value.Length);
SetValue(res, item.DeviceName, value, 2);
var res = modbusTcpMaster.ReadFloat(value.StartAddress.ToString(), value.Length);
SetValue(res.Content, item.DeviceName, value, 2);
});
break;
default:
@@ -85,6 +94,72 @@ namespace BPASmart.Server
});
}

ConcurrentQueue<string> msg = new ConcurrentQueue<string>();
private void MqttInit()
{
MqttHelper mqttHelper = new MqttHelper();
mqttHelper.Connect("admin", "fengyoufu067101!@#", "124.222.238.75", 61613, $"分布式上位机:{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")}");
mqttHelper.ConnectOk = new Action(() =>
{
mqttHelper.Subscrib("DistributedHostComputer/Control");
ThreadManage.GetInstance().StartLong(new Action(() =>
{
while (msg.Count > 0)
{
DeviceControl();
}
Thread.Sleep(100);
}), "MQTT 消息监听");
});
mqttHelper.MessageRecive = new Action<string>((s) =>
{
msg.Enqueue(s);
});
}

private void DeviceControl()
{
if (msg.TryDequeue(out string s))
{
var res = JsonConvert.DeserializeObject<PublishInfo>(s);
if (res != null)
{
res.PublishModels.ForEach(item =>
{
if (CommunicationDevices.ContainsKey(item.DeviceName))
{
switch (item.DataType)
{
case EDataType.Bool:
CommunicationDevices[item.DeviceName].Write(item.RealAddress, Convert.ToBoolean(item.Value));
break;
case EDataType.Byte:
CommunicationDevices[item.DeviceName].Write(item.RealAddress, Convert.ToByte(item.Value));
break;
case EDataType.Int:
CommunicationDevices[item.DeviceName].Write(item.RealAddress, Convert.ToInt16(item.Value));
break;
case EDataType.Word:
CommunicationDevices[item.DeviceName].Write(item.RealAddress, Convert.ToUInt16(item.Value));
break;
case EDataType.Dint:
CommunicationDevices[item.DeviceName].Write(item.RealAddress, Convert.ToInt32(item.Value));
break;
case EDataType.Dword:
CommunicationDevices[item.DeviceName].Write(item.RealAddress, Convert.ToUInt32(item.Value));
break;
case EDataType.Float:
CommunicationDevices[item.DeviceName].Write(item.RealAddress, Convert.ToSingle(item.Value));
break;
default:
break;
}
}
});
}
}
}

private void SetValue<TArray>(TArray[] arrays, string DeviceName, ReadDataModel readDataModel, ushort by)
{
if (arrays != null)
@@ -95,7 +170,7 @@ namespace BPASmart.Server
var tempArray = Json<CommunicationPar>.Data.CommunicationDevices.ElementAt(index).VarTableModels.ToArray();
for (int i = 0; i < arrays.Length; i++)
{
int varIndex = Array.FindIndex(tempArray, p => p.RealAddress == readDataModel.StartAddress + (i * by));
int varIndex = Array.FindIndex(tempArray, p => p.RealAddress == (readDataModel.StartAddress + (i * by)).ToString());
if (varIndex >= 0 && varIndex < tempArray.Length)
{
Json<CommunicationPar>.Data.CommunicationDevices.ElementAt(index).VarTableModels.ElementAt(varIndex).CurrentValue = arrays[i].ToString();
@@ -126,7 +201,7 @@ namespace BPASmart.Server
{
if (tempVar.Key != null && tempVar.Key.Length > 0)
{
int address = tempVar.Min(p => p.RealAddress);
//int address = tempVar.Min(p => p.RealAddress);
EDataType dataType = (EDataType)Enum.Parse(typeof(EDataType), tempVar.Key);
switch (dataType)
{
@@ -153,25 +228,32 @@ namespace BPASmart.Server
{
List<ReadDataModel> ReturnValue = new List<ReadDataModel>();
var res = variableInfos?.OrderBy(p => p.RealAddress).ToList();
List<int> RealAddresss = new List<int>();
variableInfos.ToList()?.ForEach(item => { if (int.TryParse(item.RealAddress, out int add)) RealAddresss.Add(add); });
int count = 0;
if (res != null)
{
int address = variableInfos.Min(p => p.RealAddress);
//int address = variableInfos.Min(p => p.RealAddress);
int address = RealAddresss.Min();
int startAddress = address;
for (int i = 0; i < res.Count; i++)
{
if (res.ElementAt(i).RealAddress == address)
if (int.TryParse(res.ElementAt(i).RealAddress, out int TempAddress))
{
count++;
address += by;
}
else
{
ReturnValue.Add(new ReadDataModel() { StartAddress = (ushort)startAddress, Length = (ushort)count });
count = 1;
address = res.ElementAt(i).RealAddress + by;
startAddress = res.ElementAt(i).RealAddress;
if (TempAddress == address)
{
count++;
address += by;
}
else
{
ReturnValue.Add(new ReadDataModel() { StartAddress = (ushort)startAddress, Length = (ushort)count });
count = 1;
address = TempAddress + by;
startAddress = TempAddress;
}
}

}
ReturnValue.Add(new ReadDataModel() { StartAddress = (ushort)startAddress, Length = (ushort)count });
}


+ 1
- 1
BPASmart.VariableManager/BPASmart.VariableManager.csproj Vedi File

@@ -29,7 +29,7 @@
</ItemGroup>

<ItemGroup>
<PackageReference Include="BPA.Communication" Version="1.0.9" />
<PackageReference Include="BPA.Communication" Version="1.0.10" />
</ItemGroup>

<ItemGroup>


+ 45
- 13
BPASmart.VariableManager/ViewModels/VariableConfigViewModel.cs Vedi File

@@ -287,7 +287,7 @@ namespace BPASmart.VariableManager.ViewModels
{
for (int i = 0; i < arrays.Length; i++)
{
int varIndex = Array.FindIndex(varialeInfos.ToArray(), p => p.RealAddress == readDataModel.StartAddress + (i * by));
int varIndex = Array.FindIndex(varialeInfos.ToArray(), p => p.RealAddress == (readDataModel.StartAddress + (i * by)).ToString());
if (varIndex >= 0 && varIndex < varialeInfos.Count)
{
varialeInfos.ElementAt(varIndex).CurrentValue = arrays[i].ToString();
@@ -302,7 +302,7 @@ namespace BPASmart.VariableManager.ViewModels
{
if (tempVar.Key != null && tempVar.Key.Length > 0)
{
int address = tempVar.Min(p => p.RealAddress);
//int address = tempVar.Min(p => p.RealAddress);
EDataType dataType = (EDataType)Enum.Parse(typeof(EDataType), tempVar.Key);
switch (dataType)
{
@@ -327,27 +327,59 @@ namespace BPASmart.VariableManager.ViewModels

private List<ReadDataModel> GetDataGroup(IGrouping<string, VariableInfo> variableInfos, int by = 1)
{
//List<ReadDataModel> ReturnValue = new List<ReadDataModel>();
//var res = variableInfos?.OrderBy(p => p.RealAddress).ToList();
//int count = 0;
//if (res != null)
//{
// int address = variableInfos.Min(p => p.RealAddress);
// int startAddress = address;
// for (int i = 0; i < res.Count; i++)
// {
// if (res.ElementAt(i).RealAddress == address)
// {
// count++;
// address += by;
// }
// else
// {
// ReturnValue.Add(new ReadDataModel() { StartAddress = (ushort)startAddress, Length = (ushort)count });
// count = 1;
// address = res.ElementAt(i).RealAddress + by;
// startAddress = res.ElementAt(i).RealAddress;
// }
// }
// ReturnValue.Add(new ReadDataModel() { StartAddress = (ushort)startAddress, Length = (ushort)count });
//}
//return ReturnValue;

List<ReadDataModel> ReturnValue = new List<ReadDataModel>();
var res = variableInfos?.OrderBy(p => p.RealAddress).ToList();
List<int> RealAddresss = new List<int>();
variableInfos.ToList()?.ForEach(item => { if (int.TryParse(item.RealAddress, out int add)) RealAddresss.Add(add); });
int count = 0;
if (res != null)
{
int address = variableInfos.Min(p => p.RealAddress);
int address = RealAddresss.Min();
int startAddress = address;
for (int i = 0; i < res.Count; i++)
{
if (res.ElementAt(i).RealAddress == address)
{
count++;
address += by;
}
else
if (int.TryParse(res.ElementAt(i).RealAddress, out int TempAddress))
{
ReturnValue.Add(new ReadDataModel() { StartAddress = (ushort)startAddress, Length = (ushort)count });
count = 1;
address = res.ElementAt(i).RealAddress + by;
startAddress = res.ElementAt(i).RealAddress;
if (TempAddress == address)
{
count++;
address += by;
}
else
{
ReturnValue.Add(new ReadDataModel() { StartAddress = (ushort)startAddress, Length = (ushort)count });
count = 1;
address = TempAddress + by;
startAddress = TempAddress;
}
}

}
ReturnValue.Add(new ReadDataModel() { StartAddress = (ushort)startAddress, Length = (ushort)count });
}


+ 2
- 0
BPASmartClient.S7Net/BPASmartClient.S7Net.csproj Vedi File

@@ -7,7 +7,9 @@
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
<PackageReference Include="S7netplus" Version="0.14.0" />
<PackageReference Include="System.Text.Encoding.CodePages" Version="6.0.0" />
</ItemGroup>

</Project>

+ 205
- 0
BPASmartClient.S7Net/Conversion.cs Vedi File

@@ -0,0 +1,205 @@
using Newtonsoft.Json.Linq;
using S7.Net.Types;
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace BPASmartClient.S7Net
{
public static class Conversion
{
/// <summary>
/// 将二进制字符串转换为 Int32 值
/// </summary>
/// <param name="txt"></param>
/// <returns></returns>
public static int BinStringToInt32(this string txt)
{
int num = 0;
for (int i = 0; i < txt.Length; i++)
{
num = (num << 1) | ((txt[i] == '1') ? 1 : 0);
}
return num;
}

/// <summary>
/// 将二进制字符串转换为字节。 可以返回空值。
/// </summary>
/// <param name="txt"></param>
/// <returns></returns>
public static byte? BinStringToByte(this string txt)
{
if (txt.Length == 8)
{
return (byte)txt.BinStringToInt32();
}

return null;
}

/// <summary>
/// 将值转换为二进制字符串
/// </summary>
/// <param name="value"></param>
/// <returns></returns>
public static string ValToBinString(this object value)
{
int num = 0;
int num2 = 0;
int num3 = 0;
string text = "";
long num4 = 0L;
try
{
if (value.GetType().Name.IndexOf("[]") < 0)
{
switch (value.GetType().Name)
{
case "Byte":
num3 = 7;
num4 = (byte)value;
break;
case "Int16":
num3 = 15;
num4 = (short)value;
break;
case "Int32":
num3 = 31;
num4 = (int)value;
break;
case "Int64":
num3 = 63;
num4 = (long)value;
break;
default:
throw new Exception();
}

for (num = num3; num >= 0; num += -1)
{
text = (((num4 & (long)Math.Pow(2.0, num)) <= 0) ? (text + "0") : (text + "1"));
}
}
else
{
switch (value.GetType().Name)
{
case "Byte[]":
{
num3 = 7;
byte[] array4 = (byte[])value;
for (num2 = 0; num2 <= array4.Length - 1; num2++)
{
for (num = num3; num >= 0; num += -1)
{
text = (((array4[num2] & (byte)Math.Pow(2.0, num)) <= 0) ? (text + "0") : (text + "1"));
}
}

break;
}
case "Int16[]":
{
num3 = 15;
short[] array2 = (short[])value;
for (num2 = 0; num2 <= array2.Length - 1; num2++)
{
for (num = num3; num >= 0; num += -1)
{
text = (((array2[num2] & (byte)Math.Pow(2.0, num)) <= 0) ? (text + "0") : (text + "1"));
}
}

break;
}
case "Int32[]":
{
num3 = 31;
int[] array3 = (int[])value;
for (num2 = 0; num2 <= array3.Length - 1; num2++)
{
for (num = num3; num >= 0; num += -1)
{
text = (((array3[num2] & (byte)Math.Pow(2.0, num)) <= 0) ? (text + "0") : (text + "1"));
}
}

break;
}
case "Int64[]":
{
num3 = 63;
byte[] array = (byte[])value;
for (num2 = 0; num2 <= array.Length - 1; num2++)
{
for (num = num3; num >= 0; num += -1)
{
text = (((array[num2] & (byte)Math.Pow(2.0, num)) <= 0) ? (text + "0") : (text + "1"));
}
}

break;
}
default:
throw new Exception();
}
}

return text;
}
catch
{
return "";
}
}

/// <summary>
/// 获取字节指定位的值
/// </summary>
/// <param name="data"></param>
/// <param name="bitPosition"></param>
/// <returns></returns>
public static bool SelectBit(this byte data, int bitPosition)
{
int num = 1 << bitPosition;
return (data & num) != 0;
}

public static short ConvertToShort(this ushort input)
{
return short.Parse(input.ToString("X"), NumberStyles.HexNumber);
}

public static ushort ConvertToUshort(this short input)
{
return ushort.Parse(input.ToString("X"), NumberStyles.HexNumber);
}


public static int ConvertToInt(this uint input)
{
return int.Parse(input.ToString("X"), NumberStyles.HexNumber);
}

public static uint ConvertToUInt(this int input)
{
return uint.Parse(input.ToString("X"), NumberStyles.HexNumber);
}

public static uint ConvertToUInt(this float input)
{
return DWord.FromByteArray(Real.ToByteArray(input));
}

public static float ConvertToFloat(this uint input)
{
return Real.FromByteArray(DWord.ToByteArray(input));
}


}
}

+ 357
- 0
BPASmartClient.S7Net/EntityClassResolution.cs Vedi File

@@ -0,0 +1,357 @@
using Newtonsoft.Json.Linq;
using S7.Net.Types;
using System;
using System.Collections.Generic;
using System.ComponentModel.Design;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;

namespace BPASmartClient.S7Net
{
public static class EntityClassResolution
{
private static IEnumerable<PropertyInfo> GetAccessableProperties(Type classType)
{
return from p in classType.GetProperties(BindingFlags.Instance | BindingFlags.Public | BindingFlags.SetProperty)
where p.GetSetMethod() != null
select p;
}

private static double GetIncreasedNumberOfBytes(double numBytes, Type type)
{
switch (type.Name)
{
case "Boolean":
numBytes += 0.125;
break;
case "Byte":
numBytes += 1.0;
break;
case "Int16":
case "UInt16":
case "Ushort":
case "Short":
numBytes += 2.0;
break;
case "Int32":
case "UInt32":
case "Single":
case "float":
numBytes += 4.0;
break;
case "Double":
numBytes += 8.0;
break;
case "String":
numBytes += 256.0;
break;
default:
numBytes = GetClassSize(Activator.CreateInstance(type), numBytes, isInnerProperty: true);
break;
}

return numBytes;
}

/// <summary>
/// 获取实体类的字节大小
/// </summary>
/// <param name="instance"></param>
/// <param name="numBytes"></param>
/// <param name="isInnerProperty"></param>
/// <returns></returns>
/// <exception cref="Exception"></exception>
public static double GetClassSize(object instance, double numBytes = 0.0, bool isInnerProperty = false)
{
foreach (PropertyInfo accessableProperty in GetAccessableProperties(instance.GetType()))
{
if (accessableProperty.PropertyType.IsArray)
{
Type elementType = accessableProperty.PropertyType.GetElementType();
Array array = (Array)accessableProperty.GetValue(instance, null);
if (array.Length <= 0)
{
throw new Exception("Cannot determine size of class, because an array is defined which has no fixed size greater than zero.");
}

IncrementToEven(ref numBytes);
for (int i = 0; i < array.Length; i++)
{
numBytes = GetIncreasedNumberOfBytes(numBytes, elementType);
}
}
else
{
numBytes = GetIncreasedNumberOfBytes(numBytes, accessableProperty.PropertyType);
}
}

if (!isInnerProperty)
{
numBytes = Math.Ceiling(numBytes);
if (numBytes / 2.0 - Math.Floor(numBytes / 2.0) > 0.0)
{
numBytes += 1.0;
}
}

return numBytes;
}

private static object? GetPropertyValue(Type propertyType, byte[] bytes, ref double numBytes)
{
object obj = null;
switch (propertyType.Name)
{
case "Boolean":
{
int num = (int)Math.Floor(numBytes);
int num2 = (int)((numBytes - (double)num) / 0.125);
obj = (((bytes[num] & (int)Math.Pow(2.0, num2)) == 0) ? ((object)false) : ((object)true));
numBytes += 0.125;
break;
}
case "Byte":
numBytes = Math.Ceiling(numBytes);
obj = bytes[(int)numBytes];
numBytes += 1.0;
break;
case "Int16":
numBytes = Math.Ceiling(numBytes);
if (numBytes / 2.0 - Math.Floor(numBytes / 2.0) > 0.0)
{
numBytes += 1.0;
}

obj = Word.FromBytes(bytes[(int)numBytes + 1], bytes[(int)numBytes]).ConvertToShort();
numBytes += 2.0;
break;
case "UInt16":
numBytes = Math.Ceiling(numBytes);
if (numBytes / 2.0 - Math.Floor(numBytes / 2.0) > 0.0)
{
numBytes += 1.0;
}

obj = Word.FromBytes(bytes[(int)numBytes + 1], bytes[(int)numBytes]);
numBytes += 2.0;
break;
case "Int32":
numBytes = Math.Ceiling(numBytes);
if (numBytes / 2.0 - Math.Floor(numBytes / 2.0) > 0.0)
{
numBytes += 1.0;
}

obj = DWord.FromBytes(bytes[(int)numBytes + 3], bytes[(int)numBytes + 2], bytes[(int)numBytes + 1], bytes[(int)numBytes]).ConvertToInt();
numBytes += 4.0;
break;
case "UInt32":
numBytes = Math.Ceiling(numBytes);
if (numBytes / 2.0 - Math.Floor(numBytes / 2.0) > 0.0)
{
numBytes += 1.0;
}

obj = DWord.FromBytes(bytes[(int)numBytes], bytes[(int)numBytes + 1], bytes[(int)numBytes + 2], bytes[(int)numBytes + 3]);
numBytes += 4.0;
break;
case "Single":
numBytes = Math.Ceiling(numBytes);
if (numBytes / 2.0 - Math.Floor(numBytes / 2.0) > 0.0)
{
numBytes += 1.0;
}

obj = Real.FromByteArray(new byte[4]
{
bytes[(int)numBytes],
bytes[(int)numBytes + 1],
bytes[(int)numBytes + 2],
bytes[(int)numBytes + 3]
});
numBytes += 4.0;
break;
case "Double":
{
numBytes = Math.Ceiling(numBytes);
if (numBytes / 2.0 - Math.Floor(numBytes / 2.0) > 0.0)
{
numBytes += 1.0;
}

byte[] array = new byte[8];
Array.Copy(bytes, (int)numBytes, array, 0, 8);
obj = LReal.FromByteArray(array);
numBytes += 8.0;
break;
}
case "String":
byte[] sarray = new byte[256];
Array.Copy(bytes, (int)numBytes, sarray, 0, 256);
obj = GetGb2312()?.GetString(sarray).Trim().Replace(" ", "").Replace("\n", "");
numBytes += 256.0;
break;
default:
{
object obj2 = Activator.CreateInstance(propertyType);
numBytes = FromBytes(obj2, bytes, numBytes);
obj = obj2;
break;
}
}

return obj;
}

private static Encoding GetGb2312()
{
//获取指定的编码不存在的时候需要安装 System.Text.Encoding.CodePages nuget包
Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);
return Encoding.GetEncoding("gb2312");
}

public static double FromBytes(object sourceClass, byte[] bytes, double numBytes = 0.0, bool isInnerClass = false)
{
if (bytes == null)
{
return numBytes;
}

foreach (PropertyInfo accessableProperty in GetAccessableProperties(sourceClass.GetType()))
{
if (accessableProperty.PropertyType.IsArray)
{
Array array = (Array)accessableProperty.GetValue(sourceClass, null);
IncrementToEven(ref numBytes);
Type elementType = accessableProperty.PropertyType.GetElementType();
for (int i = 0; i < array.Length; i++)
{
if (!(numBytes < (double)bytes.Length))
{
break;
}

array.SetValue(GetPropertyValue(elementType, bytes, ref numBytes), i);
}
}
else
{
accessableProperty.SetValue(sourceClass, GetPropertyValue(accessableProperty.PropertyType, bytes, ref numBytes), null);
}
}

return numBytes;
}

private static double SetBytesFromProperty(object propertyValue, byte[] bytes, double numBytes)
{
int num = 0;
int num2 = 0;
byte[] array = null;
switch (propertyValue.GetType().Name)
{
case "Boolean":
num = (int)Math.Floor(numBytes);
num2 = (int)((numBytes - (double)num) / 0.125);
if ((bool)propertyValue)
{
bytes[num] |= (byte)Math.Pow(2.0, num2);
}
else
{
bytes[num] &= (byte)(~(byte)Math.Pow(2.0, num2));
}

numBytes += 0.125;
break;
case "Byte":
numBytes = (int)Math.Ceiling(numBytes);
num = (int)numBytes;
bytes[num] = (byte)propertyValue;
numBytes += 1.0;
break;
case "Int16":
array = Int.ToByteArray((short)propertyValue);
break;
case "UInt16":
array = Word.ToByteArray((ushort)propertyValue);
break;
case "Int32":
array = DInt.ToByteArray((int)propertyValue);
break;
case "UInt32":
array = DWord.ToByteArray((uint)propertyValue);
break;
case "Single":
array = Real.ToByteArray((float)propertyValue);
break;
case "Double":
array = LReal.ToByteArray((double)propertyValue);
break;
case "String":
array = new byte[256];
var res = GetGb2312()?.GetBytes(propertyValue?.ToString());
for (int i = 0; i < res?.Length; i++) { array[i] = res[i]; }
break;
default:
numBytes = ToBytes(propertyValue, bytes, numBytes);
break;
}

if (array != null)
{
IncrementToEven(ref numBytes);
num = (int)numBytes;
for (int i = 0; i < array.Length; i++)
{
bytes[num + i] = array[i];
}

numBytes += (double)array.Length;
}

return numBytes;
}


public static double ToBytes(object sourceClass, byte[] bytes, double numBytes = 0.0)
{
foreach (PropertyInfo accessableProperty in GetAccessableProperties(sourceClass.GetType()))
{
if (accessableProperty.PropertyType.IsArray)
{
Array array = (Array)accessableProperty.GetValue(sourceClass, null);
IncrementToEven(ref numBytes);
accessableProperty.PropertyType.GetElementType();
for (int i = 0; i < array.Length; i++)
{
if (!(numBytes < (double)bytes.Length))
{
break;
}

numBytes = SetBytesFromProperty(array.GetValue(i), bytes, numBytes);
}
}
else
{
numBytes = SetBytesFromProperty(accessableProperty.GetValue(sourceClass, null), bytes, numBytes);
}
}

return numBytes;
}

private static void IncrementToEven(ref double numBytes)
{
numBytes = Math.Ceiling(numBytes);
if (numBytes % 2.0 > 0.0)
{
numBytes += 1.0;
}
}
}
}

+ 54
- 33
BPASmartClient.S7Net/SiemensHelper.cs Vedi File

@@ -29,10 +29,10 @@ namespace BPASmartClient.S7Net
myPlc?.Close();
}

public object Read(string address)
public TResult Read<TResult>(string address)
{
if (!IsConnected) return default;
return myPlc?.Read(address);
return (TResult)myPlc?.Read(address);
}

public bool[] ReadBools(int address, int count)
@@ -43,55 +43,76 @@ namespace BPASmartClient.S7Net
return default;
}

public ushort[] ReadMW(int address, int count)
{
if (!IsConnected) return default;
var res = Read(DataType.Memory, 0, address, VarType.Word, count);
if (res != null && res is ushort[] ReturnValue) return ReturnValue;
return default;
}

public float[] ReadMD(int address, int count)
{
if (!IsConnected) return default;
var res = Read(DataType.Memory, 0, address, VarType.Real, count);
if (res != null && res is float[] ReturnValue) return ReturnValue;
return default;
}

private object Read(DataType dataType, int db, int address, VarType varType, int count)
{
if (!IsConnected) return default;
return myPlc?.Read(dataType, db, address, varType, count);
}

public void Write(string address, object value)
public void Write<TValue>(string address, TValue value)
{
myPlc?.Write(address, value);
}

public ReadT ReadStruct<ReadT>(int db, int startAddress = 0)
public TResult ReadClass<TResult>(int db, int startByteAdr = 0) where TResult : class, new()
{
if (!IsConnected) return default;
return (ReadT)myPlc.ReadStruct(typeof(ReadT), db, startAddress);
TResult sourceClass = new TResult();
int num = (int)EntityClassResolution.GetClassSize(sourceClass);
if (num <= 0) return sourceClass;
byte[] array = myPlc.ReadBytes(DataType.DataBlock, db, startByteAdr, num);
EntityClassResolution.FromBytes(sourceClass, array);
return sourceClass;
}

public void WriteStruct(object structValue, int db, int startAddress = 0)
public void WriteClass<TWriteModel>(TWriteModel sourceClass, int db, int startAddress = 0) where TWriteModel : class, new()
{
myPlc?.WriteStruct(structValue, db, startAddress);
byte[] array = new byte[(int)EntityClassResolution.GetClassSize(sourceClass)];
EntityClassResolution.ToBytes(sourceClass, array);
myPlc.WriteBytes(DataType.DataBlock, db, startAddress, array);
}


public int ReadClass(object sourceClass, int db, int startAddress = 0)
{
if (!IsConnected) return -1;
return myPlc.ReadClass(sourceClass, db, startAddress);
}
//public ushort[] ReadMW(int address, int count)
//{
// if (!IsConnected) return default;
// var res = Read(DataType.Memory, 0, address, VarType.Word, count);
// if (res != null && res is ushort[] ReturnValue) return ReturnValue;
// return default;
//}

public void WriteClass(object sourceClass, int db, int startAddress = 0)
{
myPlc?.WriteClass(sourceClass, db, startAddress);
}
//public float[] ReadMD(int address, int count)
//{
// if (!IsConnected) return default;
// var res = Read(DataType.Memory, 0, address, VarType.Real, count);
// if (res != null && res is float[] ReturnValue) return ReturnValue;
// return default;
//}



//public ReadT ReadStruct<ReadT>(int db, int startAddress = 0)
//{
// if (!IsConnected) return default;
// return (ReadT)myPlc.ReadStruct(typeof(ReadT), db, startAddress);
//}

//public void WriteStruct(object structValue, int db, int startAddress = 0)
//{
// myPlc?.WriteStruct(structValue, db, startAddress);
//}



//public int ReadClass(object sourceClass, int db, int startAddress = 0)
//{
// if (!IsConnected) return -1;
// return myPlc.ReadClass(sourceClass, db, startAddress);
//}

//public void WriteClass(object sourceClass, int db, int startAddress = 0)
//{
// myPlc?.WriteClass(sourceClass, db, startAddress);
//}

}
}

+ 20
- 0
ComputerTestDemo/ComputerTestDemo.csproj Vedi File

@@ -0,0 +1,20 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<OutputType>WinExe</OutputType>
<TargetFramework>net6.0-windows</TargetFramework>
<Nullable>enable</Nullable>
<UseWindowsForms>true</UseWindowsForms>
<ImplicitUsings>enable</ImplicitUsings>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="BPA.Communication" Version="1.0.10" />
<PackageReference Include="BPA.Helper" Version="1.0.6" />
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\BPASmart.Model\BPASmart.Model.csproj" />
</ItemGroup>

</Project>

+ 135
- 0
ComputerTestDemo/Form1.Designer.cs Vedi File

@@ -0,0 +1,135 @@
namespace ComputerTestDemo
{
partial class Form1
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;

/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}

#region Windows Form Designer generated code

/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.button1 = new System.Windows.Forms.Button();
this.label1 = new System.Windows.Forms.Label();
this.comboBox1 = new System.Windows.Forms.ComboBox();
this.comboBox2 = new System.Windows.Forms.ComboBox();
this.label2 = new System.Windows.Forms.Label();
this.label3 = new System.Windows.Forms.Label();
this.textBox1 = new System.Windows.Forms.TextBox();
this.SuspendLayout();
//
// button1
//
this.button1.Location = new System.Drawing.Point(203, 173);
this.button1.Name = "button1";
this.button1.Size = new System.Drawing.Size(121, 37);
this.button1.TabIndex = 0;
this.button1.Text = "设定值";
this.button1.UseVisualStyleBackColor = true;
this.button1.Click += new System.EventHandler(this.button1_Click);
//
// label1
//
this.label1.AutoSize = true;
this.label1.Font = new System.Drawing.Font("华文楷体", 15.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point);
this.label1.Location = new System.Drawing.Point(100, 40);
this.label1.Name = "label1";
this.label1.Size = new System.Drawing.Size(115, 23);
this.label1.TabIndex = 1;
this.label1.Text = "选择设备:";
//
// comboBox1
//
this.comboBox1.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
this.comboBox1.FormattingEnabled = true;
this.comboBox1.Location = new System.Drawing.Point(203, 40);
this.comboBox1.Name = "comboBox1";
this.comboBox1.Size = new System.Drawing.Size(121, 25);
this.comboBox1.TabIndex = 2;
this.comboBox1.SelectedIndexChanged += new System.EventHandler(this.comboBox1_SelectedIndexChanged);
//
// comboBox2
//
this.comboBox2.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
this.comboBox2.FormattingEnabled = true;
this.comboBox2.Location = new System.Drawing.Point(203, 80);
this.comboBox2.Name = "comboBox2";
this.comboBox2.Size = new System.Drawing.Size(121, 25);
this.comboBox2.TabIndex = 3;
//
// label2
//
this.label2.AutoSize = true;
this.label2.Font = new System.Drawing.Font("华文楷体", 15.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point);
this.label2.Location = new System.Drawing.Point(100, 80);
this.label2.Name = "label2";
this.label2.Size = new System.Drawing.Size(115, 23);
this.label2.TabIndex = 4;
this.label2.Text = "选择变量:";
//
// label3
//
this.label3.AutoSize = true;
this.label3.Font = new System.Drawing.Font("华文楷体", 15.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point);
this.label3.Location = new System.Drawing.Point(79, 120);
this.label3.Name = "label3";
this.label3.Size = new System.Drawing.Size(136, 23);
this.label3.TabIndex = 5;
this.label3.Text = "设定变量值:";
//
// textBox1
//
this.textBox1.Location = new System.Drawing.Point(203, 120);
this.textBox1.Name = "textBox1";
this.textBox1.Size = new System.Drawing.Size(121, 23);
this.textBox1.TabIndex = 6;
//
// Form1
//
this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 17F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(500, 263);
this.Controls.Add(this.textBox1);
this.Controls.Add(this.comboBox2);
this.Controls.Add(this.comboBox1);
this.Controls.Add(this.label3);
this.Controls.Add(this.label2);
this.Controls.Add(this.label1);
this.Controls.Add(this.button1);
this.Name = "Form1";
this.Text = "Form1";
this.ResumeLayout(false);
this.PerformLayout();

}

#endregion

private Button button1;
private Label label1;
private ComboBox comboBox1;
private ComboBox comboBox2;
private Label label2;
private Label label3;
private TextBox textBox1;
}
}

+ 74
- 0
ComputerTestDemo/Form1.cs Vedi File

@@ -0,0 +1,74 @@
using BPA.Helper;
using BPASmart.Model;
using BPA.Communication;
using Newtonsoft.Json;

namespace ComputerTestDemo
{
public partial class Form1 : Form
{
List<CommunicationModel> communicationModels = new List<CommunicationModel>();
public Form1()
{
InitializeComponent();
textBox1.Enabled = false;
button1.Enabled = false;
Json<CommunicationPar>.Read();
communicationModels = Json<CommunicationPar>.Data.CommunicationDevices.Where(p => p.DeviceName.Length > 0).ToList();
communicationModels.ForEach(item => { comboBox1.Items.Add(item.DeviceName); });
Task.Run(new Action(() =>
{
MqttInit();
}));
}

MqttHelper mqttHelper = new MqttHelper();
private void MqttInit()
{
mqttHelper.Connect("admin", "fengyoufu067101!@#", "124.222.238.75", 61613, $"·Ö²¼Ê½ÉÏλ»ú:{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")}");
mqttHelper.ConnectOk = new Action(() =>
{
this.Invoke(new Action(() => { textBox1.Enabled = true; button1.Enabled = true; }));
});
}

private void Publish(PublishInfo publishInfo)
{
mqttHelper.Publish("DistributedHostComputer/Control", JsonConvert.SerializeObject(publishInfo));
}

private void button1_Click(object sender, EventArgs e)
{
string DeviceName = comboBox1.Text.Trim();
string VarName = comboBox2.Text.Trim();
var resDevices = communicationModels.FirstOrDefault(p => p.DeviceName == DeviceName);
if (resDevices != null)
{
var resVars = resDevices.VarTableModels.FirstOrDefault(p => p.VarName == VarName);
if (resVars != null)
{
PublishInfo publishInfo = new PublishInfo();
publishInfo.PublishModels.Add(new PublishModel()
{
DataType = (EDataType)Enum.Parse(typeof(EDataType), resVars.DataType),
DeviceName = DeviceName,
RealAddress = resVars.RealAddress,
Value = textBox1.Text.Trim(),
});
Publish(publishInfo);
}
}
}

private void comboBox1_SelectedIndexChanged(object sender, EventArgs e)
{
string selectName = comboBox1.Text.Trim();
var res = communicationModels.FirstOrDefault(p => p.DeviceName == selectName);
if (res != null)
{
comboBox2.Items.Clear();
res.VarTableModels.ToList()?.ForEach(item => { comboBox2.Items.Add(item.VarName); });
}
}
}
}

+ 60
- 0
ComputerTestDemo/Form1.resx Vedi File

@@ -0,0 +1,60 @@
<root>
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
</root>

+ 17
- 0
ComputerTestDemo/Program.cs Vedi File

@@ -0,0 +1,17 @@
namespace ComputerTestDemo
{
internal static class Program
{
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
{
// To customize application configuration such as set high DPI settings or default font,
// see https://aka.ms/applicationconfiguration.
ApplicationConfiguration.Initialize();
Application.Run(new Form1());
}
}
}

+ 24
- 1
SmartClient.sln Vedi File

@@ -164,7 +164,9 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BPASmart.Model", "BPASmart.
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BPASmart.Server", "BPASmart.Server\BPASmart.Server.csproj", "{F67FBFAC-6C80-466D-A596-1B9B10E885FC}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Communication", "Communication\Communication.csproj", "{1062F7C7-0117-413C-A45E-8F9B525FC036}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Communication", "Communication\Communication.csproj", "{1062F7C7-0117-413C-A45E-8F9B525FC036}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ComputerTestDemo", "ComputerTestDemo\ComputerTestDemo.csproj", "{8940F1E2-693D-407E-AD03-722718860609}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
@@ -1520,6 +1522,26 @@ Global
{1062F7C7-0117-413C-A45E-8F9B525FC036}.Release|x64.Build.0 = Release|Any CPU
{1062F7C7-0117-413C-A45E-8F9B525FC036}.Release|x86.ActiveCfg = Release|Any CPU
{1062F7C7-0117-413C-A45E-8F9B525FC036}.Release|x86.Build.0 = Release|Any CPU
{8940F1E2-693D-407E-AD03-722718860609}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{8940F1E2-693D-407E-AD03-722718860609}.Debug|Any CPU.Build.0 = Debug|Any CPU
{8940F1E2-693D-407E-AD03-722718860609}.Debug|ARM.ActiveCfg = Debug|Any CPU
{8940F1E2-693D-407E-AD03-722718860609}.Debug|ARM.Build.0 = Debug|Any CPU
{8940F1E2-693D-407E-AD03-722718860609}.Debug|ARM64.ActiveCfg = Debug|Any CPU
{8940F1E2-693D-407E-AD03-722718860609}.Debug|ARM64.Build.0 = Debug|Any CPU
{8940F1E2-693D-407E-AD03-722718860609}.Debug|x64.ActiveCfg = Debug|Any CPU
{8940F1E2-693D-407E-AD03-722718860609}.Debug|x64.Build.0 = Debug|Any CPU
{8940F1E2-693D-407E-AD03-722718860609}.Debug|x86.ActiveCfg = Debug|Any CPU
{8940F1E2-693D-407E-AD03-722718860609}.Debug|x86.Build.0 = Debug|Any CPU
{8940F1E2-693D-407E-AD03-722718860609}.Release|Any CPU.ActiveCfg = Release|Any CPU
{8940F1E2-693D-407E-AD03-722718860609}.Release|Any CPU.Build.0 = Release|Any CPU
{8940F1E2-693D-407E-AD03-722718860609}.Release|ARM.ActiveCfg = Release|Any CPU
{8940F1E2-693D-407E-AD03-722718860609}.Release|ARM.Build.0 = Release|Any CPU
{8940F1E2-693D-407E-AD03-722718860609}.Release|ARM64.ActiveCfg = Release|Any CPU
{8940F1E2-693D-407E-AD03-722718860609}.Release|ARM64.Build.0 = Release|Any CPU
{8940F1E2-693D-407E-AD03-722718860609}.Release|x64.ActiveCfg = Release|Any CPU
{8940F1E2-693D-407E-AD03-722718860609}.Release|x64.Build.0 = Release|Any CPU
{8940F1E2-693D-407E-AD03-722718860609}.Release|x86.ActiveCfg = Release|Any CPU
{8940F1E2-693D-407E-AD03-722718860609}.Release|x86.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@@ -1596,6 +1618,7 @@ Global
{5083C91F-B23E-445D-8B7F-AF87E636E847} = {CDC1E762-5E1D-4AE1-9DF2-B85761539086}
{F67FBFAC-6C80-466D-A596-1B9B10E885FC} = {CDC1E762-5E1D-4AE1-9DF2-B85761539086}
{1062F7C7-0117-413C-A45E-8F9B525FC036} = {CDC1E762-5E1D-4AE1-9DF2-B85761539086}
{8940F1E2-693D-407E-AD03-722718860609} = {CDC1E762-5E1D-4AE1-9DF2-B85761539086}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {9AEC9B81-0222-4DE9-B642-D915C29222AC}


Caricamento…
Annulla
Salva