///<summary>
/// Handle write request.
///</summary>
public static void HandleWriteRequest(GXDLMSSettings settings, GXDLMSServer server, GXByteBuffer data,
GXByteBuffer replyData, GXDLMSTranslatorStructure xml)
{
//Return error if connection is not established.
if (xml == null && !settings.Connected)
{
replyData.Add(GXDLMSServer.GenerateConfirmedServiceError(ConfirmedServiceError.InitiateError,
ServiceError.Service, (byte)Service.Unsupported));
return;
}
short type;
object value;
// Get object count.
List <GXSNInfo> targets = new List <GXSNInfo>();
int cnt = GXCommon.GetObjectCount(data);
if (xml != null)
{
xml.AppendStartTag(Command.WriteRequest);
xml.AppendStartTag(
TranslatorTags.ListOfVariableAccessSpecification, "Qty",
xml.IntegerToHex(cnt, 2));
if (xml.OutputType == TranslatorOutputType.StandardXml)
{
xml.AppendStartTag(
TranslatorTags.VariableAccessSpecification);
}
}
GXByteBuffer results = new GXByteBuffer((ushort)cnt);
for (int pos = 0; pos != cnt; ++pos)
{
type = data.GetUInt8();
if (type == (byte)VariableAccessSpecification.VariableName)
{
int sn = data.GetUInt16();
if (xml != null)
{
xml.AppendLine(
(int)Command.WriteRequest << 8
| (int)VariableAccessSpecification.VariableName,
"Value", xml.IntegerToHex(sn, 4));
}
else
{
GXSNInfo info = FindSNObject(server, sn);
targets.Add(info);
// If target is unknown.
if (info == null)
{
// Device reports a undefined object.
results.SetUInt8(ErrorCode.UndefinedObject);
}
else
{
results.SetUInt8(ErrorCode.Ok);
}
}
}
else if (type == (byte)VariableAccessSpecification.WriteDataBlockAccess)
{
HandleReadDataBlockAccess(settings, server, Command.WriteResponse, data, cnt, replyData, xml);
if (xml == null)
{
return;
}
}
else
{
// Device reports a HW error.
results.SetUInt8(ErrorCode.HardwareFault);
}
}
if (xml != null)
{
if (xml.OutputType == TranslatorOutputType.StandardXml)
{
xml.AppendEndTag(TranslatorTags.VariableAccessSpecification);
}
xml.AppendEndTag(
TranslatorTags.ListOfVariableAccessSpecification);
}
// Get data count.
cnt = GXCommon.GetObjectCount(data);
GXDataInfo di = new GXDataInfo();
di.xml = xml;
if (xml != null)
{
xml.AppendStartTag(TranslatorTags.ListOfData, "Qty", xml.IntegerToHex(cnt, 2));
}
for (int pos = 0; pos != cnt; ++pos)
{
di.Clear();
if (xml != null)
{
if (xml.OutputType == TranslatorOutputType.StandardXml)
{
xml.AppendStartTag(Command.WriteRequest,
SingleReadResponse.Data);
}
value = GXCommon.GetData(settings, data, di);
if (!di.Complete)
{
value = GXCommon.ToHex(data.Data, false,
data.Position, data.Size - data.Position);
xml.AppendLine(
GXDLMS.DATA_TYPE_OFFSET + (int)di.Type,
"Value", value.ToString());
}
if (xml.OutputType == TranslatorOutputType.StandardXml)
{
xml.AppendEndTag(Command.WriteRequest, SingleReadResponse.Data);
}
GXCommon.GetData(settings, data, di);
}
else if (results.GetUInt8(pos) == 0)
{
// If object has found.
GXSNInfo target = targets[pos];
value = GXCommon.GetData(settings, data, di);
if (value is byte[])
{
DataType dt = target.Item.GetDataType(target.Index);
if (dt != DataType.None && dt != DataType.OctetString)
{
value = GXDLMSClient.ChangeType((byte[])value, dt, settings.UseUtc2NormalTime);
}
}
ValueEventArgs e = new ValueEventArgs(server, target.Item, target.Index, 0, null);
AccessMode am = server.NotifyGetAttributeAccess(e);
// If write is denied.
if (am != AccessMode.Write && am != AccessMode.ReadWrite)
{
results.SetUInt8((byte)pos, (byte)ErrorCode.ReadWriteDenied);
}
else
{
e.Value = value;
server.NotifyWrite(new ValueEventArgs[] { e });
if (e.Error != 0)
{
results.SetUInt8((byte)pos, (byte)e.Error);
}
else if (!e.Handled)
{
(target.Item as IGXDLMSBase).SetValue(settings, e);
server.NotifyPostWrite(new ValueEventArgs[] { e });
}
}
}
}
if (xml != null)
{
xml.AppendEndTag(TranslatorTags.ListOfData);
xml.AppendEndTag(Command.WriteRequest);
return;
}
GenerateWriteResponse(settings, results, replyData);
}