154 lines
4.5 KiB
C#
154 lines
4.5 KiB
C#
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.Threading;
|
|
using ln.http.api;
|
|
|
|
namespace ln.ethercat.service
|
|
{
|
|
public delegate void RecordingWindowCompleted(EthercatProcessDataRecorder dataRecorder, EthercatProcessDataRecorder.RecordingWindow recordingWindow);
|
|
public delegate void ProcessDataRecordingStartStopDelegate(EthercatProcessDataRecorder dataRecorder);
|
|
|
|
public class EthercatProcessDataRecorder : IDisposable
|
|
{
|
|
public ECMaster ECMaster { get; }
|
|
public event RecordingWindowCompleted OnRecordingWindowCompleted;
|
|
public event ProcessDataRecordingStartStopDelegate OnStartRecording;
|
|
public event ProcessDataRecordingStartStopDelegate OnStopRecording;
|
|
|
|
public int RecordingWindowSize { get; set; } = 256;
|
|
public int RecordingWindowCount { get; set; } = 10;
|
|
|
|
|
|
PDO[] pdoMap;
|
|
public PDO[] CurrentPDOMap => pdoMap;
|
|
RecordingWindow[] recordingWindows;
|
|
int currentWindow;
|
|
|
|
public EthercatProcessDataRecorder(ECMaster ecMaster)
|
|
{
|
|
ECMaster = ecMaster;
|
|
}
|
|
|
|
[ESMethod]
|
|
public void Start()
|
|
{
|
|
lock (this)
|
|
{
|
|
pdoMap = ECMaster.GetPDOMap();
|
|
SetupRamStorage();
|
|
}
|
|
|
|
OnStartRecording?.Invoke(this);
|
|
|
|
ECMaster.OnStateChange += MasterStateChanged;
|
|
ECMaster.OnProcessDataExchanged += ProcessDataExchanged;
|
|
}
|
|
|
|
[ESMethod]
|
|
public void Stop()
|
|
{
|
|
lock (this)
|
|
{
|
|
if (pdoMap != null)
|
|
{
|
|
ECMaster.OnProcessDataExchanged -= ProcessDataExchanged;
|
|
ECMaster.OnStateChange -= MasterStateChanged;
|
|
|
|
OnStopRecording?.Invoke(this);
|
|
|
|
pdoMap = null;
|
|
recordingWindows = null;
|
|
}
|
|
}
|
|
}
|
|
|
|
void SetupRamStorage()
|
|
{
|
|
currentWindow = 0;
|
|
recordingWindows = new RecordingWindow[RecordingWindowCount];
|
|
for (int window=0; window < RecordingWindowCount; window++)
|
|
recordingWindows[window] = new RecordingWindow(RecordingWindowSize, pdoMap.Length);
|
|
}
|
|
|
|
|
|
void ProcessDataExchanged(ECMaster ecMaster)
|
|
{
|
|
lock (this)
|
|
{
|
|
if (pdoMap != null)
|
|
{
|
|
RecordingWindow recordingWindow = recordingWindows[currentWindow];
|
|
if (recordingWindow.GetNextRecordBuffer(out object[] currentRecord))
|
|
{
|
|
for (int n = 0; n < pdoMap.Length; n++)
|
|
currentRecord[n] = pdoMap[n].SDOValue.GetValue();
|
|
}
|
|
|
|
if (recordingWindow.Completed)
|
|
{
|
|
currentWindow++;
|
|
if (currentWindow >= recordingWindows.Length)
|
|
currentWindow = 0;
|
|
|
|
ThreadPool.QueueUserWorkItem((s)=>{
|
|
OnRecordingWindowCompleted?.Invoke(this, recordingWindow);
|
|
});
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void MasterStateChanged(ECMaster ecMaster, ECSlaveState newState)
|
|
{
|
|
if (newState != ECSlaveState.OPERATIONAL)
|
|
Stop();
|
|
}
|
|
|
|
public void Dispose()
|
|
{
|
|
Stop();
|
|
}
|
|
|
|
public class RecordingWindow
|
|
{
|
|
object[][] recordedData;
|
|
int nextRecord;
|
|
|
|
public bool Completed => nextRecord >= recordedData.Length;
|
|
|
|
public RecordingWindow(int windowSize,int pdomapSize)
|
|
{
|
|
recordedData = new object[windowSize][];
|
|
for (int pos=0 ; pos < windowSize ; pos++)
|
|
{
|
|
recordedData[pos] = new object[pdomapSize];
|
|
}
|
|
|
|
Reset();
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
nextRecord = 0;
|
|
}
|
|
|
|
public object[][] GetRecords() => recordedData;
|
|
public object[] GetRecords(int record) => recordedData[record];
|
|
|
|
public bool GetNextRecordBuffer(out object[] recordBuffer)
|
|
{
|
|
if (nextRecord < recordedData.Length)
|
|
{
|
|
recordBuffer = recordedData[nextRecord++];
|
|
return true;
|
|
}
|
|
recordBuffer = null;
|
|
return false;
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} |