專案

一般

配置概況

Bug #2903 » 替換MESDefaultMapAction.cs 裡的.txt

莊 施嶔, 04/06/2025 13:28

 
//替換MESDefaultMapAction.cs 裡的
public void Receive_S1F3W(SecsMessage msg, UInt32 SystemByte)
{
UInt32 currentVID = 0; // Used to log VID in case of an error during SetValue
object currentValue = null; // Used to log the original value in case of an error
string currentVidName = "UNKNOWN"; // Used to log VID name
SecsItem.SecsIndexType currentSecsType = default(SecsItem.SecsIndexType); // Used to log SECS type

try
{
SCUtility.jsecsActionRecordMsg(jSecs, true, msg, SystemByte);

Int32 SVID_Count = new Int32();
// Get_List returns the count, ensure it's not an error code itself
if (msg.Body().Get_List(ref SVID_Count) < 0 || SVID_Count < 0)
{
logger_SystemError.Error($"[Receive_S1F3W] Invalid SVID_Count ({SVID_Count}) from S1F3 message. SystemByte: {SystemByte}");
jSecs.UnrecognizedError(UnrecognizedErrorType.InvalidData, ref SystemByte);
return;
}

SecsMessage S1F4 = BodyCreator.Create_S1F4();
S1F4.Body().Set_List(SVID_Count);

Dictionary<int, VID> vidDefinitions = null;
try
{
vidDefinitions = jSecs.Read_VID();
if (vidDefinitions == null)
{
throw new InvalidOperationException("jSecs.Read_VID() returned null.");
}
}
catch (Exception exReadVid)
{
logger_SystemError.Error(exReadVid, $"[Receive_S1F3W] Failed to read VID definitions (jSecs.Read_VID()). SystemByte: {SystemByte}. Exception: {exReadVid.Message}");
//jSecs.UnrecognizedError(UnrecognizedErrorType.SystemError, ref SystemByte);
jSecs.UnrecognizedError(UnrecognizedErrorType.InvalidData, ref SystemByte);

return;
}

for (int i = 0; i < SVID_Count; i++)
{
UInt32[] Request_VID_Array = new UInt32[1]; // SECS U4 is an array of 1 item
if (msg.Body().I((uint)i).Get_U4(ref Request_VID_Array) == -1)
{
logger_SystemError.Error($"[Receive_S1F3W] Failed to get U4 VID at S1F3 body index {i}. SystemByte: {SystemByte}");
jSecs.UnrecognizedError(UnrecognizedErrorType.InvalidData, ref SystemByte);
return;
}
currentVID = Request_VID_Array[0];
currentVidName = vidDefinitions.ContainsKey((int)currentVID) ? vidDefinitions[(int)currentVID].Name : "UNKNOWN_VID_NAME";

logger.Debug($"[Receive_S1F3W] Processing S1F3 item {(i + 1)}/{SVID_Count} - VID: {currentVID} ({currentVidName})");

Dictionary<SecsItem.SecsIndexType, object> VID_Val_Dict = new Dictionary<SecsItem.SecsIndexType, object>();

int queryStatus = -1;
try
{
// Assuming QueryCurrentVID is defined elsewhere in this class or a base class
queryStatus = QueryCurrentVID((int)currentVID, ref VID_Val_Dict);
}
catch (Exception exQuery)
{
logger_SystemError.Error(exQuery, $"[Receive_S1F3W] Exception during QueryCurrentVID for VID: {currentVID} ({currentVidName}). SystemByte: {SystemByte}. Exception: {exQuery.Message}");
//jSecs.UnrecognizedError(UnrecognizedErrorType.SystemError, ref SystemByte);
jSecs.UnrecognizedError(UnrecognizedErrorType.InvalidData, ref SystemByte);
return;
}

if (queryStatus != 0)
{
logger.Warn($"[Receive_S1F3W] QueryCurrentVID failed (returned {queryStatus}) for VID: {currentVID} ({currentVidName}). SystemByte: {SystemByte}");
jSecs.UnrecognizedError(UnrecognizedErrorType.InvalidData, ref SystemByte);
return;
}

if (VID_Val_Dict.Count > 0)
{
foreach (var vobj in VID_Val_Dict)
{
currentValue = vobj.Value;
currentSecsType = vobj.Key;
try
{
logger.Debug($"[Receive_S1F3W] VID: {currentVID} ({currentVidName}), QueryResult Value: '{TruncateValueForLog(currentValue)}' (Type: {currentValue?.GetType().FullName}), TargetSECSDataType: {currentSecsType}");

if (currentSecsType == SecsItem.SecsIndexType.List)
{
if (currentValue is System.Collections.IList listData)
{
int listSize = listData.Count;
S1F4.Body().I((uint)i).Set_List(listSize);
for (int listItemIndex = 0; listItemIndex < listSize; listItemIndex++)
{
object listItem = listData[listItemIndex];
SecsItem.SecsIndexType listItemSecsType = DetermineListItemSecsType(currentVID, listItem, listItemIndex);

if (listItemSecsType == default(SecsItem.SecsIndexType))
{
logger_SystemError.Error($"[Receive_S1F3W] VID: {currentVID} ({currentVidName}), List item at index {listItemIndex} has undetermined SECS type. Value: '{TruncateValueForLog(listItem)}' (Type: {listItem?.GetType().FullName}).");
throw new InvalidOperationException($"Could not determine SECS type for list item of VID {currentVID} at index {listItemIndex}.");
}
S1F4.Body().I((uint)i).I((uint)listItemIndex).SetValue(listItemSecsType, listItem);
}
}
else
{
logger_SystemError.Error($"[Receive_S1F3W] VID: {currentVID} ({currentVidName}), queried value for List type is not an IList. Actual type: {currentValue?.GetType().FullName}. Value: '{TruncateValueForLog(currentValue)}'");
// Potentially set an empty list or error for this item in S1F4
S1F4.Body().I((uint)i).Set_List(0); // Example: send <L 0>
}
}
else
{
S1F4.Body().I((uint)i).SetValue(currentSecsType, currentValue);
}
}
catch (ArgumentException exSetValue)
{
logger_SystemError.Error(exSetValue, $"[Receive_S1F3W] SetValue ArgumentException for VID: {currentVID} ({currentVidName}). OriginalValue: '{TruncateValueForLog(currentValue)}', OriginalValueType: {currentValue?.GetType().FullName}, TargetSECSDataType: {currentSecsType}. Exception: {exSetValue.Message}");
// Handle error for this specific item - e.g., skip or try to set an error if S1F4 allows
// If you skip, S1F4 might be malformed if SVID_Count doesn't match actual items.
// Consider if the entire S1F4 should be aborted.
}
catch (NotSupportedException exNotSupported)
{
logger_SystemError.Error(exNotSupported, $"[Receive_S1F3W] SetValue NotSupportedException for VID: {currentVID} ({currentVidName}). OriginalValue: '{TruncateValueForLog(currentValue)}', OriginalValueType: {currentValue?.GetType().FullName}, TargetSECSDataType: {currentSecsType}. Exception: {exNotSupported.Message}");
}
catch (Exception exGenericSetValue) // Other exceptions during SetValue or list processing
{
logger_SystemError.Error(exGenericSetValue, $"[Receive_S1F3W] SetValue Generic Exception for VID: {currentVID} ({currentVidName}). OriginalValue: '{TruncateValueForLog(currentValue)}', OriginalValueType: {currentValue?.GetType().FullName}, TargetSECSDataType: {currentSecsType}. Exception: {exGenericSetValue.Message}");
}
}
}
else
{
logger.Warn($"[Receive_S1F3W] QueryCurrentVID for VID: {currentVID} ({currentVidName}) returned no data (empty dictionary). SystemByte: {SystemByte}");
// Handle in S1F4: e.g. S1F4.Body().I((uint)i).Set_List(0); if it's supposed to be a list but is empty,
// or set to a default/error value if a single item was expected.
// This depends heavily on your SECS spec for the specific VID.
}
}

if (jSecs.Reply(S1F4, SystemByte) != SendReturnCode.Normal)
{
// Assuming scApp and SCAppConstants are available
// scApp.AlarmBLL.onMainAlarm(SCAppConstants.MainAlarmCode.EAP_REPLY_MSG_ERROR_1, "S1F4", SystemByte.ToString());
logger_SystemError.Error($"[Receive_S1F3W] Failed to send S1F4 reply. SystemByte: {SystemByte}");
}
SCUtility.jsecsActionRecordMsg(jSecs, false, S1F4, SystemByte);
}
catch (Exception ex)
{
logger_SystemError.Error(ex, $"[Receive_S1F3W] Unhandled Exception. SystemByte: {SystemByte}. Last attempted VID: {currentVID} ({currentVidName}). Last Value: '{TruncateValueForLog(currentValue)}'. TargetSECSDataType: {currentSecsType}. Exception: {ex.ToString()}");
// Consider sending a generic error reply to host if appropriate (e.g., SxF0)
// jSecs.UnrecognizedError(UnrecognizedErrorType.SystemError, ref SystemByte); // Example
}
}
// THIS IS A PLACEHOLDER AND MUST BE IMPLEMENTED BASED ON YOUR EQUIPMENT'S SECS SPECIFICATION.
private SecsItem.SecsIndexType DetermineListItemSecsType(UInt32 parentVid, object listItem, int itemIndex)
{
// --- Your specific logic here ---
// This function needs to know, based on 'parentVid' (and potentially 'itemIndex' if the list has a fixed structure),
// what the SECS data type of 'listItem' should be.

// Example:
// if (parentVid == 12345) // VID 12345 is a List of U2 values
// {
// return SecsItem.SecsIndexType.U2;
// }
// else if (parentVid == 67890) // VID 67890 is <L[2] <A string1> <U4 number1>>
// {
// if (itemIndex == 0) return SecsItem.SecsIndexType.A;
// if (itemIndex == 1) return SecsItem.SecsIndexType.U4;
// }

// Fallback or error if type cannot be determined
logger_SystemError.Warn($"[DetermineListItemSecsType] Undetermined SECS type for Parent VID: {parentVid}, Item Index: {itemIndex}, Item Value: '{TruncateValueForLog(listItem)}', Item Type: {listItem?.GetType().FullName}. Implement specific logic.");

// A very generic attempt (likely insufficient for robust SECS implementation)
if (listItem is string) return SecsItem.SecsIndexType.A;
if (listItem is byte || listItem is sbyte) return SecsItem.SecsIndexType.U1; // Or I1 if signed
if (listItem is ushort || listItem is short) return SecsItem.SecsIndexType.U2; // Or I2
if (listItem is uint || listItem is int) return SecsItem.SecsIndexType.U4; // Or I4
if (listItem is ulong || listItem is long) return SecsItem.SecsIndexType.U8; // Or I8
if (listItem is float) return SecsItem.SecsIndexType.F4;
if (listItem is double) return SecsItem.SecsIndexType.F8;
if (listItem is bool) return SecsItem.SecsIndexType.Boolean;
if (listItem is byte[]) return SecsItem.SecsIndexType.B; // Or U1 if it's a single byte conceptually

return default(SecsItem.SecsIndexType); // Indicates type could not be determined
}

private string TruncateValueForLog(object value, int maxLength = 100)
{
if (value == null) return "<null>";

string sValue;
if (value is byte[] bytes)
{
// For byte arrays, show a snippet if too long
if (bytes.Length > (maxLength / 2 - 5)) // Approximation: 2 chars per byte + "0x" + "..."
{
sValue = "0x" + BitConverter.ToString(bytes, 0, Math.Min(bytes.Length, maxLength / 2 - 10)).Replace("-", "") + "...";
}
else
{
sValue = "0x" + BitConverter.ToString(bytes).Replace("-", "");
}
}
else
{
sValue = value.ToString();
}

if (sValue.Length > maxLength)
{
return sValue.Substring(0, maxLength - 3) + "...";
}
return sValue;
}
(2-2/5)