- .NET API: Fixed bug in IedConnection.GetFileAsync

pull/374/head
Michael Zillgith 4 years ago
parent 824c9ad5dd
commit 5d1f66d7e6

@ -1681,8 +1681,8 @@ namespace IEC61850
[UnmanagedFunctionPointer(CallingConvention.Cdecl)] [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
[return: MarshalAs(UnmanagedType.I1)] [return: MarshalAs(UnmanagedType.I1)]
private delegate bool IedConnection_GetFileAsyncHandler(UInt32 invokeId,IntPtr parameter,int err,UInt32 originalInvokeId, private delegate bool IedConnection_GetFileAsyncHandler(UInt32 invokeId, IntPtr parameter, int err, UInt32 originalInvokeId,
IntPtr buffer,UInt32 bytesRead,bool moreFollows); IntPtr buffer, UInt32 bytesRead, [MarshalAs(UnmanagedType.I1)] bool moreFollows);
/// <summary> /// <summary>
/// Callback handler for the asynchronous get file service. Will be invoked for each chunk of received data /// Callback handler for the asynchronous get file service. Will be invoked for each chunk of received data
@ -1693,7 +1693,8 @@ namespace IEC61850
/// <param name="originalInvokeId">the invokeId of the first (file open) request</param> /// <param name="originalInvokeId">the invokeId of the first (file open) request</param>
/// <param name="buffer">the file data received with the last response, or null if no file data available</param> /// <param name="buffer">the file data received with the last response, or null if no file data available</param>
/// <param name="moreFollows">indicates that more file data follows</param> /// <param name="moreFollows">indicates that more file data follows</param>
public delegate bool GetFileAsyncHandler(UInt32 invokeId,object parameter,IedClientError err,UInt32 originalInvokeId,byte[] buffer,bool moreFollows); /// <returns>true, continue the file download when moreFollows is true, false, stop file download</returns>
public delegate bool GetFileAsyncHandler(UInt32 invokeId, object parameter, IedClientError err, UInt32 originalInvokeId, byte[] buffer, bool moreFollows);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern UInt32 static extern UInt32
@ -1703,7 +1704,6 @@ namespace IEC61850
private bool nativeGetFileAsyncHandler(UInt32 invokeId, IntPtr parameter, int err, UInt32 originalInvokeId, private bool nativeGetFileAsyncHandler(UInt32 invokeId, IntPtr parameter, int err, UInt32 originalInvokeId,
IntPtr buffer, UInt32 bytesRead, bool moreFollows) IntPtr buffer, UInt32 bytesRead, bool moreFollows)
{ {
GCHandle handle = GCHandle.FromIntPtr(parameter); GCHandle handle = GCHandle.FromIntPtr(parameter);
Tuple<GetFileAsyncHandler, object> callbackInfo = handle.Target as Tuple<GetFileAsyncHandler, object>; Tuple<GetFileAsyncHandler, object> callbackInfo = handle.Target as Tuple<GetFileAsyncHandler, object>;
@ -1711,8 +1711,6 @@ namespace IEC61850
GetFileAsyncHandler handler = callbackInfo.Item1; GetFileAsyncHandler handler = callbackInfo.Item1;
object handlerParameter = callbackInfo.Item2; object handlerParameter = callbackInfo.Item2;
handle.Free();
IedClientError clientError = (IedClientError)err; IedClientError clientError = (IedClientError)err;
byte[] bytes = null; byte[] bytes = null;
@ -1724,7 +1722,28 @@ namespace IEC61850
Marshal.Copy(buffer, bytes, 0, (int)bytesRead); Marshal.Copy(buffer, bytes, 0, (int)bytesRead);
} }
return handler(invokeId, handlerParameter, clientError, originalInvokeId, bytes, moreFollows); bool retVal = handler(invokeId, handlerParameter, clientError, originalInvokeId, bytes, moreFollows);
if (clientError != IedClientError.IED_ERROR_OK)
{
handle.Free();
}
else
{
if (moreFollows == false)
{
handle.Free();
}
else
{
if (retVal == false)
{
handle.Free();
}
}
}
return retVal;
} }
/// <summary> /// <summary>

@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> <Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup> <PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration> <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
@ -7,7 +7,8 @@
<OutputType>Exe</OutputType> <OutputType>Exe</OutputType>
<RootNamespace>client_example_async</RootNamespace> <RootNamespace>client_example_async</RootNamespace>
<AssemblyName>client_example_async</AssemblyName> <AssemblyName>client_example_async</AssemblyName>
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion> <TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
<TargetFrameworkProfile />
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "> <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols> <DebugSymbols>true</DebugSymbols>
@ -18,6 +19,7 @@
<ErrorReport>prompt</ErrorReport> <ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel> <WarningLevel>4</WarningLevel>
<Externalconsole>true</Externalconsole> <Externalconsole>true</Externalconsole>
<Prefer32Bit>false</Prefer32Bit>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' "> <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>full</DebugType> <DebugType>full</DebugType>
@ -41,4 +43,7 @@
<Name>IEC61850.NET</Name> <Name>IEC61850.NET</Name>
</ProjectReference> </ProjectReference>
</ItemGroup> </ItemGroup>
<ItemGroup>
<None Include="app.config" />
</ItemGroup>
</Project> </Project>

@ -4,6 +4,7 @@ using System.Collections.Generic;
using IEC61850.Client; using IEC61850.Client;
using IEC61850.Common; using IEC61850.Common;
using System.IO; using System.IO;
using System.Threading;
namespace files namespace files
{ {
@ -13,18 +14,20 @@ namespace files
/// </summary> /// </summary>
class MainClass class MainClass
{ {
public static void printFiles (IedConnection con, string prefix, string parent) public static void printFiles(IedConnection con, string prefix, string parent)
{ {
bool moreFollows = false; bool moreFollows = false;
List<FileDirectoryEntry> files = con.GetFileDirectoryEx (parent, null, out moreFollows); List<FileDirectoryEntry> files = con.GetFileDirectoryEx(parent, null, out moreFollows);
foreach (FileDirectoryEntry file in files) { foreach (FileDirectoryEntry file in files)
Console.WriteLine (prefix + file.GetFileName () + "\t" + file.GetFileSize () + "\t" + {
MmsValue.MsTimeToDateTimeOffset (file.GetLastModified ())); Console.WriteLine(prefix + file.GetFileName() + "\t" + file.GetFileSize() + "\t" +
MmsValue.MsTimeToDateTimeOffset(file.GetLastModified()));
if (file.GetFileName ().EndsWith ("/")) { if (file.GetFileName().EndsWith("/"))
printFiles (con, prefix + " ", parent + file.GetFileName ()); {
printFiles(con, prefix + " ", parent + file.GetFileName());
} }
} }
@ -32,65 +35,100 @@ namespace files
Console.WriteLine("-- MORE FILES AVAILABLE --"); Console.WriteLine("-- MORE FILES AVAILABLE --");
} }
static bool getFileHandler (object parameter, byte[] data) static bool getFileHandler(object parameter, byte[] data)
{ {
Console.WriteLine ("received " + data.Length + " bytes"); Console.WriteLine("received " + data.Length + " bytes");
BinaryWriter binWriter = (BinaryWriter)parameter; BinaryWriter binWriter = (BinaryWriter)parameter;
binWriter.Write (data); binWriter.Write(data);
return true; return true;
} }
public static void Main (string[] args) public static void Main(string[] args)
{ {
IedConnection con = new IedConnection (); IedConnection con = new IedConnection();
string hostname; string hostname;
if (args.Length > 0) if (args.Length > 0)
hostname = args [0]; hostname = args[0];
else else
hostname = "127.0.0.1"; hostname = "127.0.0.1";
Console.WriteLine ("Connect to " + hostname); Console.WriteLine("Connect to " + hostname);
try { try
con.Connect (hostname, 102); {
con.Connect(hostname, 102);
Console.WriteLine ("Files in server root directory:"); Console.WriteLine("Files in server root directory:");
List<string> serverDirectory = con.GetServerDirectory (true); List<string> serverDirectory = con.GetServerDirectory(true);
foreach (string entry in serverDirectory) { foreach (string entry in serverDirectory)
Console.WriteLine (entry); {
Console.WriteLine(entry);
} }
Console.WriteLine (); Console.WriteLine();
Console.WriteLine ("File directory tree at server:"); Console.WriteLine("File directory tree at server:");
printFiles (con, "", ""); printFiles(con, "", "");
Console.WriteLine (); Console.WriteLine();
string filename = "IEDSERVER.BIN"; string filename = "IEDSERVER.BIN";
Console.WriteLine ("Download file " + filename); Console.WriteLine("Download file " + filename);
/* Download file from server and write it to a new local file */ /* Download file from server and write it to a new local file */
FileStream fs = new FileStream (filename, FileMode.Create); FileStream fs = new FileStream(filename, FileMode.Create);
BinaryWriter w = new BinaryWriter (fs); BinaryWriter w = new BinaryWriter(fs);
bool fileDownloadFinished = false;
//con.GetFile (filename, new IedConnection.GetFileHandler (getFileHandler), w);
con.GetFile (filename, new IedConnection.GetFileHandler (getFileHandler), w); /// COMMENT SECTION WHEN USING SYNC VERSION -->
fs.Close (); con.GetFileAsync(filename, delegate (UInt32 invokeId, object parameter, IedClientError err, UInt32 originalInvokeId, byte[] buffer, bool moreFollows)
{
if (err == IedClientError.IED_ERROR_OK)
{
Console.WriteLine("Received new file segment with " + buffer.Length.ToString() + " bytes, more-follows: " + moreFollows.ToString());
w.Write(buffer);
con.Abort (); if (moreFollows == false)
} catch (IedConnectionException e) { fileDownloadFinished = true;
Console.WriteLine (e.Message); }
else
{
Console.WriteLine("File download error: " + err.ToString());
fileDownloadFinished = true;
}
return true;
}, w);
while (fileDownloadFinished == false)
{
Thread.Sleep(500);
}
/// <-- COMMENT SECTION WHEN USING SYNC VERSION
fs.Close();
con.Abort();
}
catch (IedConnectionException e)
{
Console.WriteLine(e.Message);
} }
// release all resources - do NOT use the object after this call!! // release all resources - do NOT use the object after this call!!
con.Dispose (); con.Dispose();
} }
} }
} }

@ -2969,6 +2969,8 @@ IedConnection_getFile(IedConnection self, IedClientError* error, const char* fil
* \param buffer the buffer that contains the received file data * \param buffer the buffer that contains the received file data
* \param bytesRead the number of bytes read into the buffer * \param bytesRead the number of bytes read into the buffer
* \param moreFollows indicates that more file data is following * \param moreFollows indicates that more file data is following
*
* \return true, continue the file download when moreFollows is true, false, stop file download
*/ */
typedef bool typedef bool
(*IedConnection_GetFileAsyncHandler) (uint32_t invokeId, void* parameter, IedClientError err, uint32_t originalInvokeId, (*IedConnection_GetFileAsyncHandler) (uint32_t invokeId, void* parameter, IedClientError err, uint32_t originalInvokeId,

Loading…
Cancel
Save