WIP
parent
2dbdf5fbb9
commit
15b6cbe418
|
@ -0,0 +1,154 @@
|
|||
|
||||
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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -34,11 +34,18 @@ namespace ln.ethercat.service
|
|||
|
||||
System.Timers.Timer timerWebsockets;
|
||||
|
||||
|
||||
public EthercatService(string interfaceName)
|
||||
{
|
||||
EthercatProcessDataRecorder processDataRecorder;
|
||||
public EthercatProcessDataRecorder ProcessDataRecorder {
|
||||
get {
|
||||
if (processDataRecorder == null)
|
||||
processDataRecorder = new EthercatProcessDataRecorder(ECMaster);
|
||||
return processDataRecorder;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public EthercatService(){}
|
||||
|
||||
public void Initialize()
|
||||
{
|
||||
if (EthercatInterfaceName == null)
|
||||
|
|
|
@ -1,13 +1,7 @@
|
|||
using System;
|
||||
using System.Data;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Text;
|
||||
using ln.application;
|
||||
using ln.ethercat.controller;
|
||||
using ln.ethercat.controller.drives;
|
||||
using ln.ethercat.controller.remote;
|
||||
using ln.logging;
|
||||
using ln.type;
|
||||
|
||||
namespace ln.ethercat.service
|
||||
{
|
||||
|
@ -25,7 +19,7 @@ namespace ln.ethercat.service
|
|||
|
||||
Logging.Log(LogLevel.INFO, "ECMBind version: {0}", versionString.ToString());
|
||||
|
||||
EthercatService ethercatService = new EthercatService(args[0]);
|
||||
EthercatService ethercatService = new EthercatService();
|
||||
|
||||
ArgumentContainer argumentContainer = new ArgumentContainer();
|
||||
argumentContainer.AddStaticOptions<Program>();
|
||||
|
|
|
@ -88,6 +88,12 @@ namespace ln.ethercat.service.api.v1
|
|||
|
||||
[GET("/socket")]
|
||||
HttpResponse OpenWebSocket(HttpRequest httpRequest) => new EthercatWebSocket(EthercatService);
|
||||
|
||||
[GET("")]
|
||||
HttpResponse OpenRecorderSocket(HttpRequest httpRequest) => new RecorderWebSocket(EthercatService.ProcessDataRecorder);
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,64 @@
|
|||
using System.Net.Http;
|
||||
using ln.http.api;
|
||||
using ln.http.websocket;
|
||||
using ln.json;
|
||||
using ln.json.mapping;
|
||||
|
||||
namespace ln.ethercat.service.api.v1
|
||||
{
|
||||
public class RecorderWebSocket : JSONEventWebSocketResponse
|
||||
{
|
||||
EthercatProcessDataRecorder DataRecorder;
|
||||
|
||||
public RecorderWebSocket(EthercatProcessDataRecorder dataRecorder)
|
||||
{
|
||||
OnWebSocketStateChanged += (s,state)=>{
|
||||
switch (state)
|
||||
{
|
||||
case WebSocketState.OPEN:
|
||||
dataRecorder.OnRecordingWindowCompleted += RecordingWindowCompleted;
|
||||
dataRecorder.OnStartRecording += RecordingStarted;
|
||||
dataRecorder.OnStopRecording += RecordingStopped;
|
||||
break;
|
||||
case WebSocketState.CLOSED:
|
||||
dataRecorder.OnStartRecording -= RecordingStarted;
|
||||
dataRecorder.OnStopRecording -= RecordingStopped;
|
||||
dataRecorder.OnRecordingWindowCompleted -= RecordingWindowCompleted;
|
||||
break;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
void RecordingStarted(EthercatProcessDataRecorder recorder)
|
||||
{
|
||||
JSONObject jsonMessage = new JSONObject();
|
||||
jsonMessage.Add("event","start");
|
||||
if (JSONMapper.DefaultMapper.Serialize(recorder.CurrentPDOMap, out JSONValue jsonValue))
|
||||
jsonMessage.Add("value", jsonValue);
|
||||
|
||||
Send(jsonMessage);
|
||||
}
|
||||
|
||||
void RecordingStopped(EthercatProcessDataRecorder recorder)
|
||||
{
|
||||
JSONObject jsonMessage = new JSONObject();
|
||||
jsonMessage.Add("event","stop");
|
||||
jsonMessage.Add("value", JSONNull.Instance);
|
||||
|
||||
Send(jsonMessage);
|
||||
}
|
||||
|
||||
void RecordingWindowCompleted(EthercatProcessDataRecorder recorder, EthercatProcessDataRecorder.RecordingWindow recordingWindow)
|
||||
{
|
||||
JSONObject jsonMessage = new JSONObject();
|
||||
jsonMessage.Add("event","window");
|
||||
if (JSONMapper.DefaultMapper.Serialize(recordingWindow.GetRecords(), out JSONValue jsonRecords))
|
||||
jsonMessage.Add("value", jsonRecords);
|
||||
|
||||
Send(jsonMessage);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
|
@ -2,17 +2,18 @@
|
|||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
|
||||
<TargetFramework>netcoreapp3.1</TargetFramework>
|
||||
<Version>0.1.1</Version>
|
||||
<Version>0.1.2</Version>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="ln.type" Version="0.1.7-ci" />
|
||||
<PackageReference Include="ln.type" Version="0.1.7" />
|
||||
<PackageReference Include="ln.logging" Version="1.0.2" />
|
||||
<PackageReference Include="ln.json" Version="1.0.7" />
|
||||
<PackageReference Include="ln.http" Version="0.4.1" />
|
||||
<!--PackageReference Include="ln.http.api" Version="0.0.6-ci" /-->
|
||||
<ProjectReference Include="../../ln.http.api/ln.http.api/ln.http.api.csproj" />
|
||||
<PackageReference Include="ln.http.api" Version="0.0.6" />
|
||||
<!--ProjectReference Include="../../ln.http.api/ln.http.api/ln.http.api.csproj" /-->
|
||||
|
||||
<ProjectReference Include="../ln.ethercat/ln.ethercat.csproj" />
|
||||
</ItemGroup>
|
||||
|
|
|
@ -39,6 +39,7 @@ namespace ln.ethercat
|
|||
}
|
||||
|
||||
public delegate void ECStateChange(ECMaster sender,ECSlaveState newState);
|
||||
public delegate void ProcessDataExchanged(ECMaster ecMaster);
|
||||
|
||||
public class ECMaster
|
||||
{
|
||||
|
@ -50,6 +51,7 @@ namespace ln.ethercat
|
|||
|
||||
|
||||
public event ECStateChange OnStateChange;
|
||||
public event ProcessDataExchanged OnProcessDataExchanged;
|
||||
|
||||
public string InterfaceName { get; }
|
||||
|
||||
|
@ -270,6 +272,8 @@ namespace ln.ethercat
|
|||
ScheduleRestart();
|
||||
stopProcessData = true;
|
||||
}
|
||||
} else {
|
||||
OnProcessDataExchanged?.Invoke(this);
|
||||
}
|
||||
}
|
||||
Thread.Sleep(INTERVALL_PROCESSDATA);
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
<PropertyGroup>
|
||||
<TargetFramework>netcoreapp3.1</TargetFramework>
|
||||
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
|
||||
<Version>0.1.0-ci</Version>
|
||||
<Version>0.1.2</Version>
|
||||
<Authors>Harald Wolff-Thobaben</Authors>
|
||||
<Company>l--n.de</Company>
|
||||
<Description>A simple ethercat master based on SOEM (https://openethercatsociety.github.io/) </Description>
|
||||
|
@ -17,12 +17,12 @@
|
|||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="System.IO.Ports" Version="5.0.0" />
|
||||
<PackageReference Include="ln.type" Version="0.1.7-ci" />
|
||||
<PackageReference Include="ln.type" Version="0.1.7" />
|
||||
<PackageReference Include="ln.logging" Version="1.0.2" />
|
||||
<PackageReference Include="ln.json" Version="1.0.7" />
|
||||
<PackageReference Include="ln.collections" Version="0.1.3-ci" />
|
||||
<!--PackageReference Include="ln.http.api" Version="0.0.6-ci" /-->
|
||||
<ProjectReference Include="../../ln.http.api/ln.http.api/ln.http.api.csproj" />
|
||||
<PackageReference Include="ln.collections" Version="0.1.3" />
|
||||
<PackageReference Include="ln.http.api" Version="0.0.6" />
|
||||
<!--ProjectReference Include="../../ln.http.api/ln.http.api/ln.http.api.csproj" /-->
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
|
Loading…
Reference in New Issue