Merge branch 'develop' of https://bitbucket.org/ncarminati/cms_core_library into develop
This commit is contained in:
@@ -103,8 +103,8 @@
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>libs\CndexLinkDotNet.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="S7.Net">
|
||||
<HintPath>..\..\..\..\..\Workspace\CMS_CORE_LIBRARY\CMS_CORE_Application\bin\x86\Debug\S7.Net.dll</HintPath>
|
||||
<Reference Include="S7.Net, Version=0.8.1.0, Culture=neutral, PublicKeyToken=d5812d469e84c693, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\S7netplus.0.8.1\lib\net452\S7.Net.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Siemens.Sinumerik.Operate.Services, Version=4.7.3.2, Culture=neutral, PublicKeyToken=bdd90fa02fd1c4ee, processorArchitecture=x86">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
|
||||
@@ -27,6 +27,7 @@ namespace CMS_CORE_Library.Demo
|
||||
private DemoEdgesConfiguration DemoEdgesConfiguration = new DemoEdgesConfiguration();
|
||||
private const string PART_PROGRAM_FOLDER = "C:/CMS/Active/DEMO/part_program/";
|
||||
private const string JOB_PROGRAM_FOLDER = PART_PROGRAM_FOLDER + "\\job\\";
|
||||
private Random rand = new Random();
|
||||
|
||||
// Magazine config parameters
|
||||
private List<SiemensMagazineConfigModel> MagazineConfig = new List<SiemensMagazineConfigModel>()
|
||||
@@ -1142,6 +1143,12 @@ namespace CMS_CORE_Library.Demo
|
||||
return NO_ERROR;
|
||||
}
|
||||
|
||||
public override CmsError PROC_RFeed(ushort ProcNumber, ref float Feed)
|
||||
{
|
||||
Feed = Convert.ToSingle(rand.NextDouble() * 100);
|
||||
return NO_ERROR;
|
||||
}
|
||||
|
||||
private CmsError ResetStrobe(int bitId, int strobeByte, int ackByte, MEMORY_TYPE memType)
|
||||
{
|
||||
int n = 5;
|
||||
@@ -1419,6 +1426,7 @@ namespace CMS_CORE_Library.Demo
|
||||
// Populate response structure
|
||||
processData.Type = bits[3] ? "AUX" : "WORK";
|
||||
processData.CanLoadProgram = bits[6];
|
||||
processData.IsInPieceWork = rand.NextDouble() > 0.5f;
|
||||
|
||||
// Choose process status
|
||||
if (bits[4])
|
||||
|
||||
@@ -1620,6 +1620,7 @@ namespace CMS_CORE_Library.Fanuc
|
||||
// Get process part program data
|
||||
public override CmsError PROC_RStatusAndData(ushort procNumber, ref ProcessDataModel processData)
|
||||
{
|
||||
Boolean Cut = false;
|
||||
processData.Id = procNumber;
|
||||
// Read part program name
|
||||
CmsError cmsError = PROC_RSelectedPPName(procNumber, ref processData.PartProgramName);
|
||||
@@ -1632,6 +1633,15 @@ namespace CMS_CORE_Library.Fanuc
|
||||
if (cmsError.IsError())
|
||||
return cmsError;
|
||||
|
||||
//Read CUT variable
|
||||
byte CutRaw = 0;
|
||||
int address = (1000 * (procNumber - 1)) + 2;
|
||||
cmsError = MEM_RWByte(R, 0, MEMORY_TYPE.Fanuc_F, address, 0, ref CutRaw);
|
||||
if (cmsError.IsError())
|
||||
return cmsError;
|
||||
|
||||
Cut = (CutRaw & 0x40) == 0x40;
|
||||
|
||||
byte[] bytes = BitConverter.GetBytes(readValue);
|
||||
|
||||
// Convert Byte into true/false array
|
||||
@@ -1645,6 +1655,7 @@ namespace CMS_CORE_Library.Fanuc
|
||||
processData.IsSelected = bits[2];
|
||||
processData.IsInAlarm = bits[3];
|
||||
processData.CanLoadProgram = bits[4];
|
||||
processData.IsInPieceWork = Cut;
|
||||
|
||||
// Choose process status
|
||||
if (bytes[1] == 1)
|
||||
@@ -2009,6 +2020,28 @@ namespace CMS_CORE_Library.Fanuc
|
||||
return NO_ERROR;
|
||||
}
|
||||
|
||||
|
||||
|
||||
public override CmsError PROC_RFeed(ushort ProcNumber, ref float Feed)
|
||||
{
|
||||
CmsError cmsError = CheckConnection();
|
||||
if (cmsError.IsError())
|
||||
return cmsError;
|
||||
|
||||
if (ProcNumber <= 0)
|
||||
return PROC_NOT_FOUND_ERROR;
|
||||
|
||||
|
||||
ODBACT feedRaw = new ODBACT();
|
||||
short nReturn = Focas1.cnc_actf(nLibHandle[ProcNumber - 1], feedRaw);
|
||||
// Check return value
|
||||
if (nReturn != 0)
|
||||
return GetNcError(nReturn);
|
||||
|
||||
Feed = feedRaw.data / 10.0f;
|
||||
return NO_ERROR;
|
||||
}
|
||||
|
||||
#endregion PROCESS (PATH) High-level data
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@@ -86,7 +86,8 @@ namespace CMS_CORE_Library.Models
|
||||
LOADING = 2,
|
||||
UNLOADING = 3,
|
||||
EXCHANGE = 5,
|
||||
START_NEEDED = 7
|
||||
START_NEEDED = 7,
|
||||
TOOL_MANAGER_ERROR = 99
|
||||
}
|
||||
|
||||
public enum SIEMENS_MAGAZINE_TYPE
|
||||
@@ -285,6 +286,7 @@ namespace CMS_CORE_Library.Models
|
||||
public bool Visible;
|
||||
public ushort Reps;
|
||||
public bool IsSelected;
|
||||
public bool IsInPieceWork;
|
||||
public bool CanLoadProgram;
|
||||
}
|
||||
|
||||
|
||||
@@ -219,7 +219,7 @@ namespace CMS_CORE_Library.Models
|
||||
return false;
|
||||
if (EstimatedDuration != item.EstimatedDuration)
|
||||
return false;
|
||||
if (PrecedingId != item.PrecedingId)
|
||||
if (!PrecedingId.Equals(PrecedingId))
|
||||
return false;
|
||||
if (Visible != item.Visible)
|
||||
return false;
|
||||
@@ -387,6 +387,119 @@ namespace CMS_CORE_Library.Models
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Represent IO Channel visibility
|
||||
/// </summary>
|
||||
public class ChanIOVis
|
||||
{
|
||||
public Dictionary<int, bool> DI { get; set; } = new Dictionary<int, bool>();
|
||||
public Dictionary<int, bool> DO { get; set; } = new Dictionary<int, bool>();
|
||||
public Dictionary<int, bool> AI { get; set; } = new Dictionary<int, bool>();
|
||||
public Dictionary<int, bool> AO { get; set; } = new Dictionary<int, bool>();
|
||||
|
||||
public override bool Equals(object obj)
|
||||
{
|
||||
if (!(obj is ChanIOVis item))
|
||||
return false;
|
||||
|
||||
if (!DI.Equals(item.DI))
|
||||
return false;
|
||||
if (!DO.Equals(item.DO))
|
||||
return false;
|
||||
if (!AI.Equals(item.AI))
|
||||
return false;
|
||||
if (!AO.Equals(item.AO))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
public override int GetHashCode()
|
||||
{
|
||||
return base.GetHashCode();
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// Represent IO Channel Values
|
||||
/// </summary>
|
||||
public class ChanIOVal
|
||||
{
|
||||
public Dictionary<int, bool> DI { get; set; } = new Dictionary<int, bool>();
|
||||
public Dictionary<int, bool> DO { get; set; } = new Dictionary<int, bool>();
|
||||
public Dictionary<int, int> AI { get; set; } = new Dictionary<int, int>();
|
||||
public Dictionary<int, int> AO { get; set; } = new Dictionary<int, int>();
|
||||
|
||||
public override bool Equals(object obj)
|
||||
{
|
||||
if (!(obj is ChanIOVal item))
|
||||
return false;
|
||||
|
||||
if (!DI.Equals(item.DI))
|
||||
return false;
|
||||
if (!DO.Equals(item.DO))
|
||||
return false;
|
||||
if (!AI.Equals(item.AI))
|
||||
return false;
|
||||
if (!AO.Equals(item.AO))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
public override int GetHashCode()
|
||||
{
|
||||
return base.GetHashCode();
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// Represent IO Channel FORCED by UI
|
||||
/// </summary>
|
||||
public class ChanIOFor
|
||||
{
|
||||
public Dictionary<int, bool> DO { get; set; } = new Dictionary<int, bool>();
|
||||
public Dictionary<int, bool> AO { get; set; } = new Dictionary<int, bool>();
|
||||
|
||||
public override bool Equals(object obj)
|
||||
{
|
||||
if (!(obj is ChanIOVis item))
|
||||
return false;
|
||||
|
||||
if (!DO.Equals(item.DO))
|
||||
return false;
|
||||
if (!AO.Equals(item.AO))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
public override int GetHashCode()
|
||||
{
|
||||
return base.GetHashCode();
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// Represent IO Channel FORCED values
|
||||
/// </summary>
|
||||
public class ChanIOValFor
|
||||
{
|
||||
public Dictionary<int, bool> DO { get; set; } = new Dictionary<int, bool>();
|
||||
public Dictionary<int, int> AO { get; set; } = new Dictionary<int, int>();
|
||||
|
||||
public override bool Equals(object obj)
|
||||
{
|
||||
if (!(obj is ChanIOVal item))
|
||||
return false;
|
||||
|
||||
if (!DO.Equals(item.DO))
|
||||
return false;
|
||||
if (!AO.Equals(item.AO))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
public override int GetHashCode()
|
||||
{
|
||||
return base.GetHashCode();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Recipe Parameters
|
||||
/// </summary>
|
||||
|
||||
@@ -775,6 +775,20 @@ namespace CMS_CORE_Library
|
||||
|
||||
public abstract CmsError PLC_WTerminateAssistedToolingProcedure();
|
||||
|
||||
/**
|
||||
* <summary>
|
||||
* Read the actual feed of the Process "ProcNumber"
|
||||
* <para>
|
||||
* Compatibility: Fanuc | Osai | Demo | Siemens
|
||||
* </para>
|
||||
* </summary>
|
||||
* <returns cref="CmsError">Returns an error when an internal or a library error occours</returns>
|
||||
* <param name="ProcNumber">Process number which the data refer</param>
|
||||
* <param name="Feed">Feed of the Process in mm/min</param>
|
||||
* */
|
||||
|
||||
public abstract CmsError PROC_RFeed(ushort ProcNumber, ref float Feed);
|
||||
|
||||
#endregion PROCESS (PATH, CHANNEL) data (to override)
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@@ -796,6 +796,15 @@ namespace CMS_CORE_Library
|
||||
/// <param name="mode">1: MAN, 2: AUTO, 3: SETUP</param>
|
||||
/// <returns></returns>
|
||||
public abstract CmsError PLC_WModeSel(int mode);
|
||||
/// <summary>
|
||||
/// Read PLC current IO hannels data
|
||||
/// </summary>
|
||||
/// <param name="onlyVal">updates only VALUE readout</param>
|
||||
/// <param name="currThermoIOVis">Visibility status for all channels</param>
|
||||
/// <param name="currThermoIOVal">Values for channels</param>
|
||||
/// <param name="currThermoIOFor">Indicates if values are forced by UI</param>
|
||||
/// <param name="currThermoIOValFor">Values forced by UI</param>
|
||||
public abstract CmsError PLC_RIOChannels(bool onlyVal, ref ThermoModels.ChanIOVis currThermoIOVis, ref ThermoModels.ChanIOVal currThermoIOVal, ref ThermoModels.ChanIOFor currThermoIOFor, ref ThermoModels.ChanIOValFor currThermoIOValFor);
|
||||
|
||||
#endregion THERMO high level data
|
||||
|
||||
|
||||
@@ -1954,9 +1954,18 @@ namespace CMS_CORE_Library.Osai
|
||||
cmsError = MEM_RWInteger(R, 0, PROCESS_STATUS.MemType, PROCESS_STATUS.Address + ((procNumber - 1) * 2), ref readValue);
|
||||
if (cmsError.IsError())
|
||||
return cmsError;
|
||||
|
||||
byte[] bytes = BitConverter.GetBytes(readValue);
|
||||
|
||||
|
||||
// Read processes status from memory
|
||||
int index = (20 * procNumber) + 2;
|
||||
ushort readWord = 0;
|
||||
bool isInPiece = false;
|
||||
cmsError = MEM_RWWord(R, 0, MEMORY_TYPE.Osai_SW, PROCESS_STATUS.Address + ((procNumber - 1) * 2), ref readWord);
|
||||
if (cmsError.IsError())
|
||||
return cmsError;
|
||||
isInPiece = (readWord & 0x1) != 0x1; //Bit 1
|
||||
|
||||
// Convert Byte into true/false array
|
||||
BitArray bits = new BitArray(new byte[] { bytes[0] }); //1st byte -> 0 : Proccess type (AUX-WORK), 1: Process in alarm status, 2: Run, 3: Hold, 4: Read, 5: PartProgramVisible
|
||||
|
||||
@@ -1968,6 +1977,7 @@ namespace CMS_CORE_Library.Osai
|
||||
processData.IsSelected = bits[2];
|
||||
processData.IsInAlarm = bits[3];
|
||||
processData.CanLoadProgram = bits[4];
|
||||
processData.IsInPieceWork = isInPiece;
|
||||
|
||||
// Choose process status
|
||||
if (bytes[1] == 1)
|
||||
@@ -2095,6 +2105,17 @@ namespace CMS_CORE_Library.Osai
|
||||
|
||||
}
|
||||
|
||||
|
||||
public override CmsError PROC_RFeed(ushort ProcNumber, ref float Feed)
|
||||
{
|
||||
ushort nReturn = OpenNC.GetNcInfo1((ushort)ProcNumber, out GETINFO1DATA info, out uint errorClass, out uint errorNum);
|
||||
if (errorClass != 0 || errorNum != 0 || nReturn == 0)
|
||||
return GetNCError(errorClass, errorNum);
|
||||
|
||||
Feed = Convert.ToSingle(info.realfeed);
|
||||
return NO_ERROR;
|
||||
}
|
||||
|
||||
#endregion PROCESS (PATH) High-level data
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@@ -62,6 +62,10 @@ namespace CMS_CORE_Library.S7Net
|
||||
private static ThermoModels.ProdInfoModel ThermoProdInfo = new ThermoModels.ProdInfoModel();
|
||||
private static ThermoModels.ProdCycleModel ThermoProdCycle = new ThermoModels.ProdCycleModel();
|
||||
private static ThermoModels.ThermoCam ThermoCamData = new ThermoModels.ThermoCam();
|
||||
private static ThermoModels.ChanIOVis ThermoIOVis = new ThermoModels.ChanIOVis();
|
||||
private static ThermoModels.ChanIOVal ThermoIOVal = new ThermoModels.ChanIOVal();
|
||||
private static ThermoModels.ChanIOFor ThermoIOFor = new ThermoModels.ChanIOFor();
|
||||
private static ThermoModels.ChanIOValFor ThermoIOValFor = new ThermoModels.ChanIOValFor();
|
||||
|
||||
// connessione S7
|
||||
private CpuType tipoCpu = CpuType.S71500;
|
||||
@@ -2597,6 +2601,7 @@ namespace CMS_CORE_Library.S7Net
|
||||
|
||||
return NO_ERROR;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Refresh recipE parameters RT
|
||||
@@ -3731,6 +3736,284 @@ namespace CMS_CORE_Library.S7Net
|
||||
return NO_ERROR;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Read PLC current IO hannels data
|
||||
/// </summary>
|
||||
/// <param name="onlyVal">updates only RT parameters (false = update all)</param>
|
||||
/// <param name="currThermoIOVis">Visibility status for all channels</param>
|
||||
/// <param name="currThermoIOVal">Values for channels</param>
|
||||
/// <param name="currThermoIOFor">Indicates if values are forced by UI</param>
|
||||
/// <param name="currThermoIOValFor">Values forced by UI</param>
|
||||
/// <returns></returns>
|
||||
public override CmsError PLC_RIOChannels(bool onlyVal, ref ThermoModels.ChanIOVis currThermoIOVis, ref ThermoModels.ChanIOVal currThermoIOVal, ref ThermoModels.ChanIOFor currThermoIOFor, ref ThermoModels.ChanIOValFor currThermoIOValFor)
|
||||
{
|
||||
CmsError currError = NO_ERROR;
|
||||
// refresh dati veloci (valori)
|
||||
refreshChIOVal();
|
||||
// se richiesto NON SOLO RT faccio refresh anche dati "lenti"
|
||||
if (!onlyVal)
|
||||
{
|
||||
refreshChIOVisib();
|
||||
refreshChIOForced();
|
||||
refreshChIOForcedVal();
|
||||
}
|
||||
|
||||
// copio liste in output...
|
||||
currThermoIOVis = ThermoIOVis;
|
||||
currThermoIOVal = ThermoIOVal;
|
||||
currThermoIOFor = ThermoIOFor;
|
||||
currThermoIOValFor = ThermoIOValFor;
|
||||
|
||||
// esco
|
||||
return currError;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Refresh IO channels actual value
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
protected CmsError refreshChIOVal()
|
||||
{
|
||||
CmsError libraryError = NO_ERROR;
|
||||
#if false
|
||||
List<byte> currMem = new List<byte>();
|
||||
int packSize = 8;
|
||||
|
||||
// leggo da PLC a array di byte di appoggio...
|
||||
libraryError = MEM_RWByteList(R, 0, PARAMETER_RT_DATA.MemType, PARAMETER_RT_DATA.Address, PARAMETER_RT_DATA.SubAddress, 0, PARAMETER_RT_DATA.Size, ref currMem);
|
||||
if (libraryError.IsError())
|
||||
return libraryError;
|
||||
|
||||
// controllo SE ho dati...
|
||||
if (currMem.Count > 0)
|
||||
{
|
||||
// converto a blocchi di 8 byte...
|
||||
byte[] memArray = currMem.ToArray();
|
||||
for (int i = 0; i < PARAMETER_RT_DATA.Size / packSize; i++)
|
||||
{
|
||||
PlcParamRT currParam = new PlcParamRT(memArray.Skip(i * packSize).Take(packSize).ToArray());
|
||||
// solo se ID > 0...
|
||||
if (currParam.Id > 0)
|
||||
{
|
||||
// update oggetto thermoParamList...
|
||||
if (ThermoParamList.ContainsKey(currParam.Id))
|
||||
{
|
||||
try
|
||||
{
|
||||
ThermoParamList[currParam.Id].Enabled = currParam.Enabled;
|
||||
ThermoParamList[currParam.Id].HasError = currParam.HasError;
|
||||
ThermoParamList[currParam.Id].Visible = currParam.Visible;
|
||||
ThermoParamList[currParam.Id].ValueAct = currParam.ValueAct;
|
||||
}
|
||||
catch
|
||||
{ }
|
||||
}
|
||||
else
|
||||
{
|
||||
try
|
||||
{
|
||||
ThermoParamList.Add(currParam.Id, new ThermoModels.RecipeParam() { Id = currParam.Id, Enabled = currParam.Enabled, HasError = currParam.HasError, Visible = currParam.Visible, ValueAct = currParam.ValueAct });
|
||||
}
|
||||
catch
|
||||
{ }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
return libraryError;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Refresh recipe parameters
|
||||
/// </summary>
|
||||
protected CmsError refreshChIOVisib()
|
||||
{
|
||||
CmsError libraryError = NO_ERROR;
|
||||
Byte[] byteArray = null;
|
||||
List<ushort> readValuesDI = new List<ushort>();
|
||||
List<ushort> readValuesDO = new List<ushort>();
|
||||
List<ushort> readValuesAI = new List<ushort>();
|
||||
List<ushort> readValuesAO = new List<ushort>();
|
||||
|
||||
// leggo da PLC a array di byte di appoggio x visibilità DI...
|
||||
libraryError = MEM_RWWordList(R, 0, IO_DI_VISIB.MemType, IO_DI_VISIB.Address, IO_DI_VISIB.SubAddress, IO_DI_VISIB.Size, ref readValuesDI);
|
||||
if (libraryError.IsError())
|
||||
return libraryError;
|
||||
// leggo da PLC a array di byte di appoggio x visibilità DO...
|
||||
libraryError = MEM_RWWordList(R, 0, IO_DO_VISIB.MemType, IO_DO_VISIB.Address, IO_DO_VISIB.SubAddress, IO_DO_VISIB.Size, ref readValuesDO);
|
||||
if (libraryError.IsError())
|
||||
return libraryError;
|
||||
// leggo da PLC a array di byte di appoggio x visibilità AI...
|
||||
libraryError = MEM_RWWordList(R, 0, IO_AI_VISIB.MemType, IO_AI_VISIB.Address, IO_AI_VISIB.SubAddress, IO_AI_VISIB.Size, ref readValuesAI);
|
||||
if (libraryError.IsError())
|
||||
return libraryError;
|
||||
// leggo da PLC a array di byte di appoggio x visibilità AO...
|
||||
libraryError = MEM_RWWordList(R, 0, IO_AO_VISIB.MemType, IO_AO_VISIB.Address, IO_AO_VISIB.SubAddress, IO_AO_VISIB.Size, ref readValuesAO);
|
||||
if (libraryError.IsError())
|
||||
return libraryError;
|
||||
|
||||
ThermoIOVis.DI = convShortToDict(readValuesDI);
|
||||
ThermoIOVis.DO = convShortToDict(readValuesDO);
|
||||
ThermoIOVis.AI = convShortToDict(readValuesAI);
|
||||
ThermoIOVis.AO = convShortToDict(readValuesAO);
|
||||
|
||||
return libraryError;
|
||||
}
|
||||
|
||||
internal static Dictionary<int, bool> convShortToDict(List<ushort> origVal)
|
||||
{
|
||||
Byte[] byteArray = null;
|
||||
// Convert List<int16> into Byte Array
|
||||
byteArray = origVal.SelectMany(j => BitConverter.GetBytes(j)).ToArray();
|
||||
// converto a bit
|
||||
BitArray bitArr = new BitArray(byteArray);
|
||||
Dictionary<int, bool> answ = new Dictionary<int, bool>();
|
||||
for (int i = 0; i < bitArr.Count; i++)
|
||||
{
|
||||
answ.Add(i, bitArr[i]);
|
||||
}
|
||||
return answ;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Refresh recipe parameters
|
||||
/// </summary>
|
||||
protected CmsError refreshChIOForcedVal()
|
||||
{
|
||||
CmsError libraryError = NO_ERROR;
|
||||
#if false
|
||||
List<byte> currMem = new List<byte>();
|
||||
int packSize = 20;
|
||||
|
||||
// leggo da PLC a array di byte di appoggio...
|
||||
libraryError = MEM_RWByteList(R, 0, PARAMETER_DATA.MemType, PARAMETER_DATA.Address, PARAMETER_DATA.SubAddress, 0, PARAMETER_DATA.Size, ref currMem);
|
||||
if (libraryError.IsError())
|
||||
return libraryError;
|
||||
|
||||
|
||||
|
||||
// controllo SE ho dati...
|
||||
if (currMem.Count > 0)
|
||||
{
|
||||
// converto a blocchi di 8 byte...
|
||||
byte[] memArray = currMem.ToArray();
|
||||
|
||||
for (int i = 0; i < PARAMETER_DATA.Size / packSize; i++)
|
||||
{
|
||||
PlcParam currParam = new PlcParam(memArray.Skip(i * packSize).Take(packSize).ToArray());
|
||||
// solo se ID > 0...
|
||||
if (currParam.Id > 0)
|
||||
{
|
||||
// update oggetto thermoParamList...
|
||||
if (ThermoParamList.ContainsKey(currParam.Id))
|
||||
{
|
||||
try
|
||||
{
|
||||
ThermoParamList[currParam.Id].SetpointHMI = currParam.SetpointHMI;
|
||||
ThermoParamList[currParam.Id].SetpointPLC = currParam.SetpointPLC;
|
||||
ThermoParamList[currParam.Id].ValMax = currParam.ValMax;
|
||||
ThermoParamList[currParam.Id].ValMin = currParam.ValMin;
|
||||
ThermoParamList[currParam.Id].UnitMeasure = currParam.UnitMeasure;
|
||||
}
|
||||
catch
|
||||
{ }
|
||||
}
|
||||
else
|
||||
{
|
||||
try
|
||||
{
|
||||
ThermoParamList.Add(currParam.Id, new ThermoModels.RecipeParam() { Id = currParam.Id, SetpointHMI = currParam.SetpointHMI, SetpointPLC = currParam.SetpointPLC, ValMax = currParam.ValMax, ValMin = currParam.ValMin, UnitMeasure = currParam.UnitMeasure });
|
||||
}
|
||||
catch
|
||||
{ }
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
libraryError = S7_PLC_WRONG_DATA;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
libraryError = S7_PLC_EMPTY_READ;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
return libraryError;
|
||||
}
|
||||
/// <summary>
|
||||
/// Refresh recipe parameters
|
||||
/// </summary>
|
||||
protected CmsError refreshChIOForced()
|
||||
{
|
||||
CmsError libraryError = NO_ERROR;
|
||||
#if false
|
||||
List<byte> currMem = new List<byte>();
|
||||
int packSize = 20;
|
||||
|
||||
// leggo da PLC a array di byte di appoggio...
|
||||
libraryError = MEM_RWByteList(R, 0, PARAMETER_DATA.MemType, PARAMETER_DATA.Address, PARAMETER_DATA.SubAddress, 0, PARAMETER_DATA.Size, ref currMem);
|
||||
if (libraryError.IsError())
|
||||
return libraryError;
|
||||
|
||||
|
||||
|
||||
// controllo SE ho dati...
|
||||
if (currMem.Count > 0)
|
||||
{
|
||||
// converto a blocchi di 8 byte...
|
||||
byte[] memArray = currMem.ToArray();
|
||||
|
||||
for (int i = 0; i < PARAMETER_DATA.Size / packSize; i++)
|
||||
{
|
||||
PlcParam currParam = new PlcParam(memArray.Skip(i * packSize).Take(packSize).ToArray());
|
||||
// solo se ID > 0...
|
||||
if (currParam.Id > 0)
|
||||
{
|
||||
// update oggetto thermoParamList...
|
||||
if (ThermoParamList.ContainsKey(currParam.Id))
|
||||
{
|
||||
try
|
||||
{
|
||||
ThermoParamList[currParam.Id].SetpointHMI = currParam.SetpointHMI;
|
||||
ThermoParamList[currParam.Id].SetpointPLC = currParam.SetpointPLC;
|
||||
ThermoParamList[currParam.Id].ValMax = currParam.ValMax;
|
||||
ThermoParamList[currParam.Id].ValMin = currParam.ValMin;
|
||||
ThermoParamList[currParam.Id].UnitMeasure = currParam.UnitMeasure;
|
||||
}
|
||||
catch
|
||||
{ }
|
||||
}
|
||||
else
|
||||
{
|
||||
try
|
||||
{
|
||||
ThermoParamList.Add(currParam.Id, new ThermoModels.RecipeParam() { Id = currParam.Id, SetpointHMI = currParam.SetpointHMI, SetpointPLC = currParam.SetpointPLC, ValMax = currParam.ValMax, ValMin = currParam.ValMin, UnitMeasure = currParam.UnitMeasure });
|
||||
}
|
||||
catch
|
||||
{ }
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
libraryError = S7_PLC_WRONG_DATA;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
libraryError = S7_PLC_EMPTY_READ;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
return libraryError;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
@@ -5306,6 +5589,22 @@ namespace CMS_CORE_Library.S7Net
|
||||
internal static MEMORY_CELL RISC_OVP_DATA = new MEMORY_CELL(MEMORY_TYPE.Siemens_DB, 514, 10752, 1024);
|
||||
internal static MEMORY_CELL RISC_ICH_DATA = new MEMORY_CELL(MEMORY_TYPE.Siemens_DB, 514, 11776, 4096);
|
||||
|
||||
// gestione canali IO
|
||||
internal static MEMORY_CELL IO_STATW_DATA = new MEMORY_CELL(MEMORY_TYPE.Siemens_DB, 628, 0, 2);
|
||||
internal static MEMORY_CELL IO_COMMW_DATA = new MEMORY_CELL(MEMORY_TYPE.Siemens_DB, 628, 2, 2);
|
||||
internal static MEMORY_CELL IO_DI_VAL_ACT = new MEMORY_CELL(MEMORY_TYPE.Siemens_DB, 628, 4, 64);
|
||||
internal static MEMORY_CELL IO_DO_VAL_ACT = new MEMORY_CELL(MEMORY_TYPE.Siemens_DB, 628, 68, 64);
|
||||
internal static MEMORY_CELL IO_AI_VAL_ACT = new MEMORY_CELL(MEMORY_TYPE.Siemens_DB, 628, 132, 64);
|
||||
internal static MEMORY_CELL IO_AO_VAL_ACT = new MEMORY_CELL(MEMORY_TYPE.Siemens_DB, 628, 196, 64);
|
||||
internal static MEMORY_CELL IO_DI_VISIB = new MEMORY_CELL(MEMORY_TYPE.Siemens_DB, 628, 260, 64);
|
||||
internal static MEMORY_CELL IO_DO_VISIB = new MEMORY_CELL(MEMORY_TYPE.Siemens_DB, 628, 324, 64);
|
||||
internal static MEMORY_CELL IO_AI_VISIB = new MEMORY_CELL(MEMORY_TYPE.Siemens_DB, 628, 388, 4);
|
||||
internal static MEMORY_CELL IO_AO_VISIB = new MEMORY_CELL(MEMORY_TYPE.Siemens_DB, 628, 392, 4);
|
||||
internal static MEMORY_CELL IO_DO_FORCE = new MEMORY_CELL(MEMORY_TYPE.Siemens_DB, 628, 396, 64);
|
||||
internal static MEMORY_CELL IO_DO_VAL_FOR = new MEMORY_CELL(MEMORY_TYPE.Siemens_DB, 628, 460, 64);
|
||||
internal static MEMORY_CELL IO_AO_FORCE = new MEMORY_CELL(MEMORY_TYPE.Siemens_DB, 628, 524, 4);
|
||||
internal static MEMORY_CELL IO_AO_VAL_FOR = new MEMORY_CELL(MEMORY_TYPE.Siemens_DB, 628, 528, 64);
|
||||
|
||||
// ThermoCamera
|
||||
internal static MEMORY_CELL TCAM_STATW_DATA = new MEMORY_CELL(MEMORY_TYPE.Siemens_DB, 626, 0, 2);
|
||||
internal static MEMORY_CELL TCAM_COMMW_DATA = new MEMORY_CELL(MEMORY_TYPE.Siemens_DB, 626, 2, 2);
|
||||
|
||||
@@ -58,6 +58,7 @@ namespace CMS_CORE_Library.Siemens
|
||||
// TOOLS
|
||||
private const string NC_TOOL_FILE_PATH = "//NC/ACT.DIR/TO.DIR/TO_INI.INI";
|
||||
private const string LOCALE_TOOL_FILE_PATH = "C:\\CMS\\Active\\TMP\\TO_INI.INI";
|
||||
private const string LOCALE_TOOL_ERR_PATH = "C:\\CMS\\Active\\TMP\\TOOLS_ERR.LOG";
|
||||
|
||||
// Global Variables
|
||||
private static DateTime Last_Static_Read;
|
||||
@@ -71,6 +72,7 @@ namespace CMS_CORE_Library.Siemens
|
||||
private static uint MaxChannelNo;
|
||||
private static uint SiemensLanguage;
|
||||
private static string UnitOfMeasure;
|
||||
private static Boolean ErrorDuringToolsReading;
|
||||
|
||||
// Alarms data
|
||||
private static AlarmSvc SiemensAlmSvc = null;
|
||||
@@ -2327,6 +2329,7 @@ namespace CMS_CORE_Library.Siemens
|
||||
processData.IsSelected = bits[2];
|
||||
processData.IsInAlarm = bits[3];
|
||||
processData.CanLoadProgram = bits[4];
|
||||
processData.IsInPieceWork = false;
|
||||
|
||||
// Choose process status
|
||||
if (bytes[1] == 1)
|
||||
@@ -2516,6 +2519,28 @@ namespace CMS_CORE_Library.Siemens
|
||||
return NO_ERROR;
|
||||
}
|
||||
|
||||
|
||||
|
||||
public override CmsError PROC_RFeed(ushort ProcNumber, ref float Feed)
|
||||
{
|
||||
if (ProcNumber <= 0)
|
||||
return PROC_NOT_FOUND_ERROR;
|
||||
try
|
||||
{
|
||||
Item item = new Item { Path = "/Channel/State/actFeedRateIpo[u" + ProcNumber + ", 1]" };
|
||||
// Read data
|
||||
DataSvc dataSvc = new DataSvc();
|
||||
dataSvc.Read(item);
|
||||
Feed = Convert.ToSingle(item.Value);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
return ManageException(ex);
|
||||
}
|
||||
|
||||
return NO_ERROR;
|
||||
}
|
||||
|
||||
private CmsError PROC_ReadActiveLine(uint processId, ref string line)
|
||||
{
|
||||
try
|
||||
@@ -5119,6 +5144,24 @@ namespace CMS_CORE_Library.Siemens
|
||||
|
||||
public override CmsError TOOLS_RMagazineAction(ref MagazineActionModel magazineAction)
|
||||
{
|
||||
//To test it
|
||||
/*
|
||||
if (ErrorDuringToolsReading)
|
||||
{
|
||||
magazineAction = new MagazineActionModel()
|
||||
{
|
||||
Action = MAGAZINE_ACTIONS.TOOL_MANAGER_ERROR,
|
||||
Tool = null,
|
||||
SecondTool = null,
|
||||
OriginMagazine = 0,
|
||||
OriginPosition = 0,
|
||||
DestinationMagazine = 0,
|
||||
DestinationPosition = 0
|
||||
};
|
||||
return NO_ERROR;
|
||||
}
|
||||
*/
|
||||
|
||||
magazineAction = MagazineAction;
|
||||
return NO_ERROR;
|
||||
}
|
||||
@@ -5747,7 +5790,7 @@ namespace CMS_CORE_Library.Siemens
|
||||
}
|
||||
}
|
||||
|
||||
private void PopulateToolsTableFromFileStrings(string[] toolsStrings)
|
||||
public void PopulateToolsTableFromFileStrings(string[] toolsStrings)
|
||||
{
|
||||
SiemensEdgesConfiguration toolEdgesConfig = new SiemensEdgesConfiguration();
|
||||
|
||||
@@ -5755,6 +5798,7 @@ namespace CMS_CORE_Library.Siemens
|
||||
int lastSecondId = 0;
|
||||
int toolIndex = 0;
|
||||
int edgeIndex = 0;
|
||||
ErrorDuringToolsReading = true;
|
||||
// int multitoolIndex = 0;
|
||||
|
||||
// Foreach string
|
||||
@@ -5783,7 +5827,7 @@ namespace CMS_CORE_Library.Siemens
|
||||
ToolTableData.Add(new SiemensToolModel()
|
||||
{
|
||||
Id = firstId,
|
||||
ChildId = Convert.ToInt32(actualString.Split('=').LastOrDefault())
|
||||
ChildId = ConvertToSiemensInt32(actualString.Split('=').LastOrDefault())
|
||||
});
|
||||
// Update Index
|
||||
toolIndex = ToolTableData.Count - 1;
|
||||
@@ -5808,13 +5852,13 @@ namespace CMS_CORE_Library.Siemens
|
||||
break;
|
||||
|
||||
case "$TC_TP7":
|
||||
ToolTableData[toolIndex].MagazinePositionType = Convert.ToInt32(actualString.Split('=').LastOrDefault());
|
||||
ToolTableData[toolIndex].MagazinePositionType = ConvertToSiemensInt32(actualString.Split('=').LastOrDefault());
|
||||
break;
|
||||
|
||||
case "$TC_TP8":
|
||||
{
|
||||
// Get tool status and read each bit
|
||||
int toolStatus = Convert.ToInt32(actualString.Split('=').LastOrDefault());
|
||||
int toolStatus = ConvertToSiemensInt32(actualString.Split('=').LastOrDefault());
|
||||
|
||||
ToolTableData[toolIndex].IsActive = GetBitValue(toolStatus, 0);
|
||||
ToolTableData[toolIndex].IsEnabled = GetBitValue(toolStatus, 1);
|
||||
@@ -5828,7 +5872,7 @@ namespace CMS_CORE_Library.Siemens
|
||||
break;
|
||||
|
||||
case "$TC_TP9":
|
||||
ToolTableData[toolIndex].LifeType = (SIEMENS_LIFE_TYPE)Convert.ToInt32(actualString.Split('=').LastOrDefault());
|
||||
ToolTableData[toolIndex].LifeType = (SIEMENS_LIFE_TYPE)ConvertToSiemensInt32(actualString.Split('=').LastOrDefault());
|
||||
break;
|
||||
|
||||
case "$TC_TP_MAX_VELO":
|
||||
@@ -5840,23 +5884,23 @@ namespace CMS_CORE_Library.Siemens
|
||||
// break;
|
||||
// Custom CMS fields
|
||||
case "$TC_TPC1":
|
||||
ToolTableData[toolIndex].Load = Convert.ToInt32(actualString.Split('=').LastOrDefault(), numberFormat);
|
||||
ToolTableData[toolIndex].Load = ConvertToSiemensInt32(actualString.Split('=').LastOrDefault());
|
||||
break;
|
||||
|
||||
case "$TC_TPC2":
|
||||
ToolTableData[toolIndex].Gamma = Convert.ToInt32(actualString.Split('=').LastOrDefault(), numberFormat);
|
||||
ToolTableData[toolIndex].Gamma = ConvertToSiemensInt32(actualString.Split('=').LastOrDefault());
|
||||
break;
|
||||
|
||||
case "$TC_TPC3":
|
||||
ToolTableData[toolIndex].MaxLoadPctAutoload = Convert.ToInt32(actualString.Split('=').LastOrDefault(), numberFormat);
|
||||
ToolTableData[toolIndex].MaxLoadPctAutoload = ConvertToSiemensInt32(actualString.Split('=').LastOrDefault());
|
||||
break;
|
||||
|
||||
case "$TC_TPC4":
|
||||
ToolTableData[toolIndex].MinLoadPctAutoload = Convert.ToInt32(actualString.Split('=').LastOrDefault(), numberFormat);
|
||||
ToolTableData[toolIndex].MinLoadPctAutoload = ConvertToSiemensInt32(actualString.Split('=').LastOrDefault());
|
||||
break;
|
||||
|
||||
case "$TC_TPC5":
|
||||
ToolTableData[toolIndex].ToolTypeCode = Convert.ToInt32(actualString.Split('=').LastOrDefault(), numberFormat);
|
||||
ToolTableData[toolIndex].ToolTypeCode = ConvertToSiemensInt32(actualString.Split('=').LastOrDefault());
|
||||
break;
|
||||
|
||||
//*SHANK FIX*case "$TC_MTPN":
|
||||
@@ -5908,19 +5952,19 @@ namespace CMS_CORE_Library.Siemens
|
||||
if (mag == null)
|
||||
{
|
||||
bool active = true;
|
||||
SIEMENS_MAGAZINE_TYPE type = (SIEMENS_MAGAZINE_TYPE)Convert.ToInt32(actualString.Split('=').LastOrDefault());
|
||||
SIEMENS_MAGAZINE_TYPE type = (SIEMENS_MAGAZINE_TYPE)ConvertToSiemensInt32(actualString.Split('=').LastOrDefault());
|
||||
if (type == SIEMENS_MAGAZINE_TYPE.MAGAZINE_LOADING_STATION || type == SIEMENS_MAGAZINE_TYPE.MAGAZINE_TOOL_BUFFER)
|
||||
active = false;
|
||||
|
||||
MagazineConfig.Add(new SiemensMagazineConfigModel()
|
||||
{
|
||||
Id = (short)firstId,
|
||||
Type = (SIEMENS_MAGAZINE_TYPE)Convert.ToInt32(actualString.Split('=').LastOrDefault()),
|
||||
Type = (SIEMENS_MAGAZINE_TYPE)ConvertToSiemensInt32(actualString.Split('=').LastOrDefault()),
|
||||
LoadingIsActive = active
|
||||
});
|
||||
}
|
||||
else
|
||||
mag.Type = (SIEMENS_MAGAZINE_TYPE)Convert.ToInt32(actualString.Split('=').LastOrDefault());
|
||||
mag.Type = (SIEMENS_MAGAZINE_TYPE)ConvertToSiemensInt32(actualString.Split('=').LastOrDefault());
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -5938,7 +5982,7 @@ namespace CMS_CORE_Library.Siemens
|
||||
// Add max number of magazine positions
|
||||
SiemensMagazineConfigModel mag = MagazineConfig.Where(x => x.Id == firstId).FirstOrDefault();
|
||||
if (mag != null)
|
||||
mag.MaxPositions = Convert.ToInt32(actualString.Split('=').LastOrDefault());
|
||||
mag.MaxPositions = ConvertToSiemensInt32(actualString.Split('=').LastOrDefault());
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -5954,7 +5998,7 @@ namespace CMS_CORE_Library.Siemens
|
||||
case "$TC_DP1":
|
||||
{
|
||||
if (secondId == 1) // Read tool type from first edge type
|
||||
ToolTableData[toolIndex].ToolType = Convert.ToInt32(actualString.Split('=').LastOrDefault());
|
||||
ToolTableData[toolIndex].ToolType = ConvertToSiemensInt32(actualString.Split('=').LastOrDefault());
|
||||
// Add new edge
|
||||
ToolTableData[toolIndex].EdgesData.Add(new EdgeModel() { Id = secondId });
|
||||
edgeIndex = ToolTableData[toolIndex].EdgesData.Count - 1; // Update Index
|
||||
@@ -6130,7 +6174,7 @@ namespace CMS_CORE_Library.Siemens
|
||||
if (tool.EdgesData[edgeIndex].Id == 1)
|
||||
{
|
||||
// Get tool general information
|
||||
var toolInfo = Convert.ToInt32(actualString.Split('=').LastOrDefault());
|
||||
var toolInfo = ConvertToSiemensInt32(actualString.Split('=').LastOrDefault());
|
||||
|
||||
// Convert rotation data
|
||||
ROTATION rotation = ROTATION.NONE;
|
||||
@@ -6153,7 +6197,7 @@ namespace CMS_CORE_Library.Siemens
|
||||
{
|
||||
PositionId = secondId,
|
||||
MagazineId = firstId,
|
||||
PhysicalType = (POSITION_TYPE)Convert.ToInt32(actualString.Split('=').LastOrDefault())
|
||||
PhysicalType = (POSITION_TYPE)ConvertToSiemensInt32(actualString.Split('=').LastOrDefault())
|
||||
});
|
||||
}
|
||||
break;
|
||||
@@ -6162,7 +6206,7 @@ namespace CMS_CORE_Library.Siemens
|
||||
{
|
||||
int index = MagazinePositionsData.FindIndex(x => x.PositionId == secondId && x.MagazineId == firstId);
|
||||
if (index >= 0)
|
||||
MagazinePositionsData[index].Type = Convert.ToInt32(actualString.Split('=').LastOrDefault());
|
||||
MagazinePositionsData[index].Type = ConvertToSiemensInt32(actualString.Split('=').LastOrDefault());
|
||||
//*SHANK FIX*MagazinePositionsData.Add(new PositionModel()
|
||||
//{
|
||||
// PositionId = secondId,
|
||||
@@ -6177,15 +6221,15 @@ namespace CMS_CORE_Library.Siemens
|
||||
int index = MagazinePositionsData.FindIndex(x => x.PositionId == secondId && x.MagazineId == firstId);
|
||||
if (index >= 0)
|
||||
{
|
||||
MagazinePositionsData[index].Disabled = GetBitValue(Convert.ToInt32(actualString.Split('=').LastOrDefault()), 0);
|
||||
MagazinePositionsData[index].Occupied = GetBitValue(Convert.ToInt32(actualString.Split('=').LastOrDefault()), 2);
|
||||
MagazinePositionsData[index].Disabled = GetBitValue(ConvertToSiemensInt32(actualString.Split('=').LastOrDefault()), 0);
|
||||
MagazinePositionsData[index].Occupied = GetBitValue(ConvertToSiemensInt32(actualString.Split('=').LastOrDefault()), 2);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case "$TC_MPP6":
|
||||
{
|
||||
int toolId = Convert.ToInt32(actualString.Split('=').LastOrDefault());
|
||||
int toolId = ConvertToSiemensInt32(actualString.Split('=').LastOrDefault());
|
||||
if (toolId != 0)
|
||||
{
|
||||
MoveToolInMagazineList(toolId, firstId, secondId);
|
||||
@@ -6945,6 +6989,32 @@ namespace CMS_CORE_Library.Siemens
|
||||
}
|
||||
}
|
||||
|
||||
private int ConvertToSiemensInt32(string str)
|
||||
{
|
||||
//Replace with Standard Exponent
|
||||
String intr = str.Replace("EX", "E");
|
||||
|
||||
//Convert
|
||||
if(!float.TryParse(intr, NumberStyles.Float, CultureInfo.InvariantCulture, out float number))
|
||||
{
|
||||
using (StreamWriter w = File.AppendText(LOCALE_TOOL_ERR_PATH))
|
||||
w.WriteLine($"{DateTime.Now.ToString("yyyy_MM_dd:hh_mm_ss")}\t\tERR: Read incorrect format while parsing: {str}");
|
||||
|
||||
ErrorDuringToolsReading = true;
|
||||
return Int32.MaxValue;
|
||||
}
|
||||
|
||||
//Check error
|
||||
if (Math.Abs(number % 1) > (Double.Epsilon * 100))
|
||||
{
|
||||
ErrorDuringToolsReading = true;
|
||||
using (StreamWriter w = File.AppendText(LOCALE_TOOL_ERR_PATH))
|
||||
w.WriteLine($"{DateTime.Now.ToString("yyyy_MM_dd:hh_mm_ss")}\t\tERR: Read Float and not Int value: {str}");
|
||||
}
|
||||
|
||||
return (int) Math.Floor(number);
|
||||
}
|
||||
|
||||
#endregion Siemens Tool private functions
|
||||
|
||||
#region Multitool Private region
|
||||
|
||||
@@ -203,7 +203,7 @@ namespace CMS_CORE_Library.Utils
|
||||
.Cast<bool>()
|
||||
.ToArray();
|
||||
}
|
||||
|
||||
|
||||
// Convert a byte into an array of bools
|
||||
public static bool[] ByteToBits(byte val)
|
||||
{
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<packages>
|
||||
<package id="S7netplus" version="0.4.0" targetFramework="net462" />
|
||||
<package id="S7netplus" version="0.8.1" targetFramework="net462" />
|
||||
</packages>
|
||||
Reference in New Issue
Block a user