I have a windows service which has in function
- call API service and get location data and Timestamp off vehicles
- write the timestamp and the location name to OPC-objects in the same server using OpcDA
The service is running with 15-secunds interval. it's about 7 objects that the service is looping over and write the timestamp and the location into it.
Problem: The problem is that the update of the OPC-objects takes long time, The cycle it self run with 15 seconds interval men the objects got updated within 3,4 and 8 minutes interval.
here is my code
public void OnTimer(object sender, ElapsedEventArgs args)
{
ConnectToOpc();
Task.Run(RunCoreFunction);
Task.Run(ImportData);
}
private async Task RunCoreFunction()
{
keepRunning = true;
try
{
await PopulateDevices();
_ = PopulateParalellOpcAsync();
Heartbeat();
}
catch (Exception ex)
{
_logger.Log(ex.Message + ex.StackTrace.ToString(), "RunCoreFunction", LogType.Error);
}
}
// Bings location name and timestamp from external API and but it inside a list of objects called currCallsResult
private async Task PopulateDevices()
{
try
{
string _restApiUrl = restApiUrl;
currCallsResult = await APIProcessor.LoadDeviceInfoFromPBE(_restApiUrl);
foreach (PBEResult obj in currCallsResult)
{
int result = GetMacInMacArray(obj.SystemId);
if (result == -1)
{
obj.location = null;
}
else
{
_logger.Log("Updated entries on " + obj.SystemId + " that is on index: " + result, functionName, LogType.Vehicle);
}
}
}
catch (Exception ex)
{
BreakCoreFunction(ex.Message + " Something wrong with the REST-API");
_logger.Log(ex.Message + " " + ex.InnerException + " " + ex.StackTrace.ToString(), functionName, LogType.Error);
}
_logger.Log("PopluateDevices Finished, Fetch vehicleData from API", functionName, LogType.Main);
}
private async Task PopulateParalellOpcAsync()
{
ConnectToOpc(); // Connects to the OPC
_logger.Log(" PopulateParalellOpcAsync Begins", "PopulateParalellOpcAsync", LogType.Main);
if (currCallsResult != null && currCallsResult.Count > 0)
{
var nrOfItems = macArray.Count(x => x != null && x != "EMPTY");
if (nrOfItems > 0)
{
List<Task> tasks = new List<Task>();
foreach (PBEResult _obj in currCallsResult)
{
if (_obj.SystemId != null)
{
//Write data into OPC Object
tasks.Add(Task.Run(() => PopulateOpc(_obj)));
}
}
await Task.WhenAll(tasks);
}
}
else
{
_logger.Log(" Can't populate OPC, currCallsResult from the API is empty", "PopulateParalellOpcAsync", LogType.Main);
}
}
private async Task<string> PopulateOpc(PBEResult obj) // Writes to the objects.
{
int assetID = 0;
string _checkTag2 = "";
if (obj.SystemId != null)
{
assetID = GetMacInMacArray(obj.SystemId);
if (assetID > 0)
{
try
{
ConnectToOpc();
_checkTag2 = await opcMngr.ReadTagAsync(opcTag + assetID + ".LocationData" + ".MacAddress");
if (!(String.IsNullOrEmpty(_checkTag2)))
{
opcMngr.WriteStringTagAsync(opcTag + assetID + ".LocationData" + ".Timestamp", obj.TimeStamp.ToString());
opcMngr.WriteStringTagAsync(opcTag + assetID + ".LocationData" + ".LocationName", obj.location);
_logger.Log(" OPC Tags Updated AssetName: " + obj.AssetName, functionName, LogType.Main);
}
else
{
_logger.Log("Error, Look att Error log file ", functionName, LogType.Main);
}
catch (Exception e)
{
_logger.Log("Error, Look att Error log file ", functionName, LogType.Main);
}
}
}
else
{
_logger.Log(", SystemId is null " + obj.AssetName, functionName, LogType.Main);
}
return null;
}
private void ConnectToOpc()
{
if ((opcMngr == null) || (opcMngr.Status != "Connected")) // Checks if opcMngr exist and/or is connected
{
_logger.Log("Connecting to OPC", "ConnectToOPC", LogType.Main);
opcMngr = new OpcManager(opcUri);
_logger.Log("Connected!", "ConnectToOPC", LogType.Main);
}
}