/// <summary> /// Асинхронно изменить значение переменной без подтверждения успеха внесения изменений. /// </summary> /// <param name="target">Адрес устройства, на котором требуется изменить значение переменной.</param> /// <param name="id">Идентификатор переменной.</param> /// <param name="valueType">Тип значения.</param> /// <param name="value">Записываемое значение.</param> public async Task WriteValueAsync(Address target, int id, NmsValueType valueType, object value) { //Contract.Requires(!IsDisposed); //Contract.Requires(target != null); //Contract.Requires(value != null); var write = new NmsWrite(target, id, valueType, value, false); await OutgoingMessages.SendAsync(write); }
/// <summary> /// Изменить значение переменной без подтверждения успеха внесения изменений. /// </summary> /// <param name="target">Адрес устройства, на котором требуется изменить значение переменной.</param> /// <param name="id">Идентификатор переменной.</param> /// <param name="valueType">Тип значения.</param> /// <param name="value">Записываемое значение.</param> public void WriteValue(Address target, int id, NmsValueType valueType, object value) { Contract.Requires(!IsDisposed); Contract.Requires(target != null); Contract.Requires(value != null); var write = new NmsWrite(target, id, valueType, value, false); OutgoingMessages.Post(write); }
/// <summary> /// Initializes a new instance of the <see cref="NmsWrite"/> class. /// </summary> /// <param name="destanation">Адрес получателя сообщения.</param> /// <param name="id">Идентификатор переменной.</param> /// <param name="valueType">Тип значения.</param> /// <param name="value">Записываемое значение.</param> /// <param name="waitResponse"><c>true</c> - если требуется подтверждение записи.</param> /// <param name="priority">Приоритет.</param> public NmsWrite( Address destanation, int id, NmsValueType valueType, object value, bool waitResponse = true, PriorityType priority = PriorityType.Normal) : this(Address.Empty, destanation, id, valueType, value, waitResponse, priority) { Contract.Requires(destanation != null); Contract.Requires(value != null); }
/// <summary> /// Асинхронно изменить значение переменной с подтверждением успеха внесения изменений. /// </summary> /// <param name="target">Адрес устройства, на котором требуется изменить значение переменной.</param> /// <param name="id">Идентификатор переменной.</param> /// <param name="valueType">Тип значения.</param> /// <param name="value">Записываемое значение.</param> /// <param name="options">Параметры NiBUS-операции.</param> /// <returns> /// <see cref="Task"/> асинхронная операция. /// </returns> public async Task WriteValueConfirmedAsync( Address target, int id, NmsValueType valueType, object value, NibusOptions options = null) { Contract.Requires(!IsDisposed); Contract.Requires(target != null); Contract.Requires(target.Type == AddressType.Hardware || target.Type == AddressType.Net); Contract.Requires(value != null); var write = new NmsWrite(target, id, valueType, value); await WaitForNmsResponseAsync(write, options); }
/// <summary> /// Initializes a new instance of the <see cref="NmsInformationReport"/> class. /// </summary> /// <param name="source">Адрес источника сообщения.</param> /// <param name="id">Идентификатор информационного сообщения. <seealso cref="GameReports"/></param> /// <param name="valueType">Тип значения информационного сообщения.</param> /// <param name="value">Значение информационного сообщения.</param> /// <param name="priority">Приоритет.</param> public NmsInformationReport( Address source, int id, NmsValueType valueType, object value, PriorityType priority = PriorityType.Normal) { Contract.Ensures(!IsResponse); Contract.Ensures(ServiceType == NmsServiceType.InformationReport); Initialize( source, Address.Broadcast, priority, NmsServiceType.InformationReport, false, id, false, WriteValue(valueType, value)); }
/// <summary> /// Initializes a new instance of the <see cref="NmsWrite"/> class. /// </summary> /// <param name="source">Адрес источника сообщения.</param> /// <param name="destanation">Адрес получателя сообщения.</param> /// <param name="id">Идентификатор переменной.</param> /// <param name="valueType">Тип значения.</param> /// <param name="value">Записываемое значение.</param> /// <param name="waitResponse"><c>true</c> - если требуется подтверждение записи.</param> /// <param name="priority">Приоритет.</param> public NmsWrite(Address source, Address destanation, int id, NmsValueType valueType, object value, bool waitResponse = true, PriorityType priority = PriorityType.Normal) { Contract.Requires(source != null); Contract.Requires(destanation != null); Contract.Requires(value != null); Initialize( source, destanation, priority, NmsServiceType.Write, waitResponse, id, false, WriteValue(valueType, value)); }
/// <summary> /// Возвращает размер данных указанного типа и возможно значения для массива или строки. /// </summary> /// <param name="vt">Тип данных.</param> /// <param name="value">Значение данных в случае массива или строки.</param> /// <returns>Занимаемый размер.</returns> public static int GetSizeOf(NmsValueType vt, object value = null) { switch (vt) { case NmsValueType.Boolean: case NmsValueType.Int8: case NmsValueType.UInt8: return(1); case NmsValueType.Int16: case NmsValueType.UInt16: return(2); case NmsValueType.Int32: case NmsValueType.UInt32: case NmsValueType.Real32: return(4); case NmsValueType.Int64: case NmsValueType.UInt64: case NmsValueType.Real64: return(8); case NmsValueType.DateTime: return(10); case NmsValueType.String: return(Math.Min(NmsMaxDataLength - 1, (value != null ? ((string)value).Length : 0) + 1)); } if (((byte)vt & (byte)NmsValueType.Array) == 0) { throw new ArgumentException("Invalid ValueType"); } var arrayType = (NmsValueType)((byte)vt & ((byte)NmsValueType.Array - 1)); var itemSize = GetSizeOf(arrayType); return(value != null ? ((ICollection)value).Count * itemSize : itemSize); }
/// <summary> /// Конструктор создания NMS-сообщения сервиса <see cref="NmsServiceType.Read"/> /// из низлежащего сообщения <see cref="NibusDatagram"/>. /// </summary> /// <param name="datagram">Датаграмма.</param> /// <remarks> /// Минимальный размер длины данных <paramref name="datagram"/> должен быть не меньше размера /// заголовка <see cref="NmsMessage.NmsHeaderLength"/> плюс размер NMS-данных. /// </remarks> /// <seealso cref="NmsMessage.CreateFrom"/> /// <exception cref="InvalidNibusDatagram"></exception> internal NmsRead(NibusDatagram datagram) : base(datagram) { Contract.Requires(datagram != null); Contract.Requires(datagram.ProtocolType == ProtocolType.Nms); Contract.Requires(datagram.Data.Count >= NmsHeaderLength); Contract.Ensures(ServiceType == NmsServiceType.Read); Contract.Assume(ServiceType == NmsServiceType.Read); if (!IsResponse) { return; } if (datagram.Data.Count < NmsHeaderLength + 3) { throw new InvalidNibusDatagram("Invalid NMS message length"); } _errorCode = datagram.Data[NmsHeaderLength + 0]; _valueType = (NmsValueType)datagram.Data[NmsHeaderLength + 1]; _value = ReadValue(_valueType, datagram.Data.ToArray(), NmsHeaderLength + 2); }
/// <summary> /// Записывает тип значения и само значение в буфер. /// </summary> /// <param name="valueType">Тип значения.</param> /// <param name="value">Значение.</param> /// <returns>Массив байт максимальной длины <see cref="NmsMaxDataLength"/> с данными.</returns> /// <exception cref="ArgumentException">Неверный тип значения.</exception> /// <exception cref="FormatException">Ошибка преобразования.</exception> /// <exception cref="InvalidCastException">Ошибка преобразования.</exception> /// <exception cref="OverflowException">Ошибка преобразования.</exception> protected static byte[] WriteValue(NmsValueType valueType, object value) { Contract.Requires(value != null); Contract.Ensures(Contract.Result <byte[]>().Length <= NmsMaxDataLength); var data = new List <byte>(NmsMaxDataLength) { (byte)valueType }; switch (valueType) { case NmsValueType.Boolean: data.Add(Convert.ToBoolean(value) ? (byte)1 : (byte)0); break; case NmsValueType.Int8: data.Add((byte)Convert.ToSByte(value)); break; case NmsValueType.Int16: data.AddRange(BitConverter.GetBytes(Convert.ToInt16(value))); break; case NmsValueType.Int32: data.AddRange(BitConverter.GetBytes(Convert.ToInt32(value))); break; case NmsValueType.Int64: data.AddRange(BitConverter.GetBytes(Convert.ToInt64(value))); break; case NmsValueType.UInt8: data.Add(Convert.ToByte(value)); break; case NmsValueType.UInt16: data.AddRange(BitConverter.GetBytes(Convert.ToUInt16(value))); break; case NmsValueType.UInt32: data.AddRange(BitConverter.GetBytes(Convert.ToUInt32(value))); break; case NmsValueType.UInt64: data.AddRange(BitConverter.GetBytes(Convert.ToUInt64(value))); break; case NmsValueType.Real32: data.AddRange(BitConverter.GetBytes(Convert.ToSingle(value))); break; case NmsValueType.Real64: data.AddRange(BitConverter.GetBytes(Convert.ToDouble(value))); break; case NmsValueType.String: data.AddRange(Encoding.Default.GetBytes(value.ToString()).Take(NmsMaxDataLength - 1)); if (value.ToString().Length < NmsMaxDataLength - 1) { data.Add(0); } break; case NmsValueType.DateTime: var dt = Convert.ToDateTime(value); data.AddRange( new[] { PackByte(dt.Day), PackByte(dt.Month), PackByte(dt.Year % 100), PackByte(dt.Year / 100), PackByte(dt.Hour), PackByte(dt.Minute), PackByte(dt.Second), (byte)(dt.Millisecond / 100 & 0x0f), PackByte(dt.Millisecond % 100), (byte)(dt.DayOfWeek + 1) }); break; } if (((byte)valueType & (byte)NmsValueType.Array) != 0) { var arrayType = (NmsValueType)((byte)valueType & ((byte)NmsValueType.Array - 1)); foreach (var item in (IEnumerable)value) { data.AddRange(WriteValue(arrayType, item)); } } Contract.Assert(data.Count <= NmsMaxDataLength); return(data.Take(NmsMaxDataLength).ToArray()); }
/// <summary> /// Чтение значения NMS из буфера. /// </summary> /// <param name="valueType">Тип значения.</param> /// <param name="buffer">Буфер.</param> /// <param name="startIndex">Начальный индекс в буфере, с которого хранится непосредственно значение.</param> /// <returns>Значение NMS.</returns> protected static object ReadValue(NmsValueType valueType, byte[] buffer, int startIndex) { Contract.Requires(buffer != null); Contract.Requires(startIndex >= 0); switch (valueType) { case NmsValueType.Boolean: return(buffer[startIndex] != 0); case NmsValueType.Int8: return((sbyte)buffer[startIndex]); case NmsValueType.Int16: return(BitConverter.ToInt16(buffer, startIndex)); case NmsValueType.Int32: return(BitConverter.ToInt32(buffer, startIndex)); case NmsValueType.Int64: return(BitConverter.ToInt64(buffer, startIndex)); case NmsValueType.UInt8: return(buffer[startIndex]); case NmsValueType.UInt16: return(BitConverter.ToUInt16(buffer, startIndex)); case NmsValueType.UInt32: return(BitConverter.ToInt32(buffer, startIndex)); case NmsValueType.UInt64: return(BitConverter.ToUInt64(buffer, startIndex)); case NmsValueType.Real32: return(BitConverter.ToSingle(buffer, startIndex)); case NmsValueType.Real64: return(BitConverter.ToDouble(buffer, startIndex)); case NmsValueType.String: return(Encoding.Default.GetString( buffer.Skip(startIndex).Take(NmsMaxDataLength - 1).TakeWhile(b => b != 0).ToArray())); case NmsValueType.DateTime: return(GetDateTime(buffer, startIndex)); } if (((byte)valueType & (byte)NmsValueType.Array) == 0) { throw new ArgumentException("Invalid ValueType"); } var arrayType = (NmsValueType)((byte)valueType & ((byte)NmsValueType.Array - 1)); var arraySize = buffer.Length - startIndex /* - 1*/; var itemSize = GetSizeOf(arrayType); var arrayLength = arraySize / itemSize; var array = new object[arrayLength]; for (var i = 0; i < arrayLength; i++) { array[i] = ReadValue(arrayType, buffer, startIndex); startIndex += itemSize; } switch (arrayType) { case NmsValueType.Boolean: return(array.Cast <bool>().ToArray()); case NmsValueType.Int8: return(array.Cast <sbyte>().ToArray()); case NmsValueType.Int16: return(array.Cast <short>().ToArray()); case NmsValueType.Int32: return(array.Cast <int>().ToArray()); case NmsValueType.Int64: return(array.Cast <long>().ToArray()); case NmsValueType.UInt8: return(array.Cast <byte>().ToArray()); case NmsValueType.UInt16: return(array.Cast <ushort>().ToArray()); case NmsValueType.UInt32: return(array.Cast <uint>().ToArray()); case NmsValueType.UInt64: return(array.Cast <ulong>().ToArray()); case NmsValueType.Real32: return(array.Cast <float>().ToArray()); case NmsValueType.Real64: return(array.Cast <double>().ToArray()); case NmsValueType.String: return(array.Cast <string>().ToArray()); case NmsValueType.DateTime: return(array.Cast <DateTime>().ToArray()); } return(array); }