master
Harald Wolff 2021-04-14 10:02:35 +02:00
parent 2dbdf5fbb9
commit 15b6cbe418
8 changed files with 250 additions and 20 deletions

View File

@ -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;
}
}
}
}

View File

@ -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)

View File

@ -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>();

View File

@ -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);
}
}

View File

@ -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);
}
}
}

View File

@ -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>

View File

@ -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);

View File

@ -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>