- .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,93 +4,131 @@ 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
{ {
/// <summary> /// <summary>
/// This example connects to an IEC 61850 device, list the available files, and then /// This example connects to an IEC 61850 device, list the available files, and then
/// tries to read the file "IEDSERVER.BIN" from the server. /// tries to read the file "IEDSERVER.BIN" from the server.
/// </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());
} }
}
if (moreFollows) if (moreFollows)
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);
con.GetFile (filename, new IedConnection.GetFileHandler (getFileHandler), w); bool fileDownloadFinished = false;
fs.Close (); //con.GetFile (filename, new IedConnection.GetFileHandler (getFileHandler), w);
con.Abort (); /// COMMENT SECTION WHEN USING SYNC VERSION -->
} catch (IedConnectionException e) {
Console.WriteLine (e.Message);
}
// release all resources - do NOT use the object after this call!! con.GetFileAsync(filename, delegate (UInt32 invokeId, object parameter, IedClientError err, UInt32 originalInvokeId, byte[] buffer, bool moreFollows)
con.Dispose (); {
} if (err == IedClientError.IED_ERROR_OK)
} {
Console.WriteLine("Received new file segment with " + buffer.Length.ToString() + " bytes, more-follows: " + moreFollows.ToString());
w.Write(buffer);
if (moreFollows == false)
fileDownloadFinished = true;
}
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!!
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