internal override void Decode(Channel channel, uint nbElements) { Status = (AlarmStatus)channel.DecodeData <ushort>(1, 0); Severity = (AlarmSeverity)channel.DecodeData <ushort>(1, 2); int pos = 4; Type t = typeof(TType); if (t.IsArray) { t = t.GetElementType(); } if (t == typeof(object)) { t = channel.ChannelDefinedType; } if (t == typeof(double) || t == typeof(float)) { Precision = channel.DecodeData <short>(1, pos); pos += 4; // 2 for precision field + 2 padding for "RISC alignment" } if (t != typeof(string)) { EGU = channel.DecodeData <string>(1, pos, 8); pos += 8; int tSize = TypeHandling.EpicsSize(t); //HighDisplayLimit = channel.DecodeData<TType>(1, pos); HighDisplayLimit = Convert.ToDouble(channel.DecodeData(t, 1, pos)); pos += tSize; //LowDisplayLimit = channel.DecodeData<TType>(1, pos); LowDisplayLimit = Convert.ToDouble(channel.DecodeData(t, 1, pos)); pos += tSize; //HighAlertLimit = channel.DecodeData<TType>(1, pos); HighAlertLimit = Convert.ToDouble(channel.DecodeData(t, 1, pos)); pos += tSize; //HighWarnLimit = channel.DecodeData<TType>(1, pos); HighWarnLimit = Convert.ToDouble(channel.DecodeData(t, 1, pos)); pos += tSize; //LowWarnLimit = channel.DecodeData<TType>(1, pos); LowWarnLimit = Convert.ToDouble(channel.DecodeData(t, 1, pos)); pos += tSize; //LowAlertLimit = channel.DecodeData<TType>(1, pos); LowAlertLimit = Convert.ToDouble(channel.DecodeData(t, 1, pos)); pos += tSize; LowControlLimit = Convert.ToDouble(channel.DecodeData(t, 1, pos)); pos += tSize; //HighControlLimit = channel.DecodeData<TType>(1, pos); HighControlLimit = Convert.ToDouble(channel.DecodeData(t, 1, pos)); pos += tSize; } else { EGU = ""; } if (t == typeof(byte)) { pos++; // 1 padding for "RISC alignment" } Value = channel.DecodeData <TType>(nbElements, pos); }
internal object DecodeData(Type t, uint nbElements = 1, int startPost = 0, int maxSize = 40) { if (t.IsSubclassOf(typeof(Decodable)) && !t.IsArray) { Decodable res = (Decodable)t.GetConstructor(System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance, null, new Type[] { }, null).Invoke(new object[] { }); res.Decode(this, nbElements); return(res); } if (t == typeof(object)) { t = channelDefinedType; } Type baseT = t; if (baseT.IsArray) { baseT = t.GetElementType(); } if (t.IsArray) { Type dl = typeof(List <>); Type genList = dl.MakeGenericType(new Type[] { baseT }); System.Collections.IList res = (System.Collections.IList)Activator.CreateInstance(genList); int pos = (int)RawData.HeaderSize + startPost; int elementSize = TypeHandling.EpicsSize(baseT); if (nbElements > RawData.DataCount) { throw new Exception($"Less elements were returned than requested. Returned: {RawData.DataCount}, Requested: {nbElements}"); } for (int i = 0; i < nbElements; i++) { switch (TypeHandling.Lookup[baseT]) { case EpicsType.Int: res.Add(RawData.GetInt32(pos)); break; case EpicsType.Short: res.Add(RawData.GetInt16(pos)); break; case EpicsType.Float: res.Add(RawData.GetFloat(pos)); break; case EpicsType.Double: res.Add(RawData.GetDouble(pos)); break; case EpicsType.Byte: res.Add(RawData.GetByte(pos)); break; default: throw new Exception("Type not supported"); } pos += elementSize; } return(((dynamic)res).ToArray()); } if (baseT == typeof(DateTime)) { long secs = RawData.GetUInt32((int)RawData.HeaderSize + startPost); long nanoSecs = RawData.GetUInt32((int)RawData.HeaderSize + startPost + 4); DateTime d = (new DateTime(timestampBase.Ticks + (secs * 10000000L) + (nanoSecs / 100L))).ToLocalTime(); return(d); } switch (TypeHandling.Lookup[baseT]) { case EpicsType.Internal_UInt: return(RawData.GetUInt32((int)RawData.HeaderSize + startPost)); case EpicsType.Internal_UShort: return(RawData.GetUInt16((int)RawData.HeaderSize + startPost)); case EpicsType.Int: return(RawData.GetInt32((int)RawData.HeaderSize + startPost)); case EpicsType.Short: return(RawData.GetInt16((int)RawData.HeaderSize + startPost)); case EpicsType.Float: return(RawData.GetFloat((int)RawData.HeaderSize + startPost)); case EpicsType.Double: return(RawData.GetDouble((int)RawData.HeaderSize + startPost)); case EpicsType.String: return(RawData.GetDataAsString(startPost, maxSize)); case EpicsType.Byte: return(RawData.GetByte((int)RawData.HeaderSize + startPost)); default: //throw new Exception("Type not supported"); return(new object()); } }
protected DataPacket WritePacket <TType>(TType newValue) { int headerSize = 16; uint nbElem = 1; if (newValue is IEnumerable <object> ) { nbElem = (uint)((IEnumerable <object>)newValue).Count(); } Type t = typeof(TType); if (t.IsArray) { nbElem = (uint)((Array)((object)newValue)).Length; // if too many array elements, use extended header if (nbElem > 0xffff) { headerSize = 24; } t = t.GetElementType(); } else if (t.IsGenericType) { if (t.GetGenericArguments().First() == typeof(object)) { t = t.GetGenericTypeDefinition().MakeGenericType(new Type[] { channelDefinedType }); } } if (t == typeof(object)) { t = channelDefinedType; } int payloadSize = (int)(nbElem * TypeHandling.EpicsSize(t)); if (payloadSize % 8 > 0) { payloadSize += 8 - (payloadSize % 8); } // if payload too large, use extended header if (payloadSize > 0x4000 || nbElem > 30000) { headerSize = 24; } DataPacket packet = DataPacket.Create(headerSize + payloadSize); packet.Command = (ushort)CommandID.CA_PROTO_WRITE_NOTIFY; packet.DataCount = nbElem; packet.DataType = (ushort)TypeHandling.Lookup[t]; packet.Parameter1 = SID; uint ioid = (NextIoId++); packet.Parameter2 = ioid; if (nbElem > 1) { int pos = headerSize; int elementSize = TypeHandling.EpicsSize(t); foreach (var elem in (System.Collections.IEnumerable)newValue) { switch (TypeHandling.Lookup[t]) { case EpicsType.Int: packet.SetInt32(pos, (int)elem); break; case EpicsType.Short: packet.SetInt16(pos, (short)elem); break; case EpicsType.Float: packet.SetFloat(pos, (float)elem); break; case EpicsType.Double: packet.SetDouble(pos, (double)elem); break; case EpicsType.Byte: packet.SetByte(pos, (byte)elem); break; default: throw new Exception("Type not supported"); } pos += elementSize; } } else { switch (TypeHandling.Lookup[t]) { case EpicsType.Int: packet.SetInt32((int)packet.HeaderSize, (int)(object)newValue); break; case EpicsType.Short: packet.SetInt16((int)packet.HeaderSize, (short)(object)newValue); break; case EpicsType.Float: packet.SetFloat((int)packet.HeaderSize, (float)(object)newValue); break; case EpicsType.Double: packet.SetDouble((int)packet.HeaderSize, (double)(object)newValue); break; case EpicsType.String: packet.SetDataAsString((string)(object)newValue); break; case EpicsType.Byte: packet.SetByte((int)packet.HeaderSize, (byte)(object)newValue); break; default: throw new Exception("Type not currently supported."); } } return(packet); }