/// <summary>
        /// Reads field definitions.
        /// </summary>
        protected FieldDef[] ReadFieldDefs(BinaryReader reader, byte[] buffer, int fieldCount)
        {
            FieldDef[] fieldDefs = new FieldDef[fieldCount];

            for (int i = 0; i < fieldCount; i++)
            {
                ReadData(reader, buffer, 0, FieldDefSize, true);

                if (ScadaUtils.CRC16(buffer, 0, FieldDefSize - 2) != BitConverter.ToUInt16(buffer, FieldDefSize - 2))
                {
                    throw new ScadaException("Field definition CRC error.");
                }

                int    index      = 0;
                int    nameLength = buffer[index++];
                string fieldName  = Encoding.ASCII.GetString(buffer, index, nameLength);
                index += MaxFieldNameLength;

                fieldDefs[i] = new FieldDef(
                    fieldName,
                    GetByte(buffer, ref index),
                    GetBool(buffer, ref index));
            }

            return(fieldDefs);
        }
Beispiel #2
0
        /// <summary>
        /// Copies the event to the buffer.
        /// </summary>
        protected void CopyEvent(Event ev, bool textExists, bool dataExists,
                                 byte[] buffer, out int textSize, out int dataSize)
        {
            textSize = ev.Text == null ? 0 : Math.Min(ev.Text.Length, MaxTextSize);
            dataSize = ev.Data == null ? 0 : Math.Min(ev.Data.Length, MaxDataSize);

            int index = 0;

            CopyUInt16(BlockMarker, buffer, ref index);
            CopyInt64(ev.EventID, buffer, ref index);
            CopyTime(ev.Timestamp, buffer, ref index);
            CopyBool(ev.Hidden, buffer, ref index);
            CopyInt32(ev.CnlNum, buffer, ref index);
            CopyInt32(ev.OutCnlNum, buffer, ref index);
            CopyInt32(ev.ObjNum, buffer, ref index);
            CopyInt32(ev.DeviceNum, buffer, ref index);
            CopyDouble(ev.PrevCnlVal, buffer, ref index);
            CopyUInt16((ushort)ev.PrevCnlStat, buffer, ref index);
            CopyDouble(ev.CnlVal, buffer, ref index);
            CopyUInt16((ushort)ev.CnlStat, buffer, ref index);
            CopyInt32(ev.Severity, buffer, ref index);
            CopyBool(ev.AckRequired, buffer, ref index);
            CopyBool(ev.Ack, buffer, ref index);
            CopyTime(ev.AckTimestamp, buffer, ref index);
            CopyInt32(ev.AckUserID, buffer, ref index);
            CopyByte((byte)ev.TextFormat, buffer, ref index);
            CopyBool(textExists, buffer, ref index);
            CopyByte((byte)textSize, buffer, ref index);
            CopyBool(dataExists, buffer, ref index);
            CopyByte((byte)dataSize, buffer, ref index);
            Array.Clear(buffer, index, EventSize - index - 2);
            ushort crc = ScadaUtils.CRC16(buffer, 0, EventSize - 2);

            CopyUInt16(crc, buffer, EventSize - 2);
        }
        /// <summary>
        /// Writes the field definintion using the specified writer.
        /// </summary>
        protected void WriteFieldDef(BinaryWriter writer, FieldDef fieldDef, byte[] buffer)
        {
            Array.Clear(buffer, 0, FieldDefSize);
            int nameLength = fieldDef.Name.Length;

            buffer[0] = (byte)nameLength;
            Encoding.ASCII.GetBytes(fieldDef.Name).CopyTo(buffer, 1);
            buffer[MaxFieldNameLength + 1] = (byte)fieldDef.DataType;
            buffer[MaxFieldNameLength + 2] = (byte)(fieldDef.AllowNull ? 1 : 0);
            ushort crc = ScadaUtils.CRC16(buffer, 0, FieldDefSize - 2);

            CopyUInt16(crc, buffer, FieldDefSize - 2);
            writer.Write(buffer, 0, FieldDefSize);
        }
Beispiel #4
0
        /// <summary>
        /// Writes the event acknowledgement information in a file or stream.
        /// </summary>
        public void WriteEventAck(Event ev)
        {
            if (ev == null)
            {
                throw new ArgumentNullException(nameof(ev));
            }

            if (ev.Position < 0)
            {
                throw new ScadaException("Event position is undefined.");
            }

            Stream       stream = null;
            BinaryReader reader = null;
            BinaryWriter writer = null;

            try
            {
                stream = Stream ?? new FileStream(FileName, FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.ReadWrite);
                reader = new BinaryReader(stream, Encoding.UTF8, Stream != null);
                writer = new BinaryWriter(stream, Encoding.UTF8, Stream != null);

                // read the existing event into the buffer
                byte[] buffer = new byte[EventSize];

                if (stream.Seek(ev.Position, SeekOrigin.Begin) == ev.Position &&
                    ReadEvent(reader, buffer, out int index) &&
                    GetInt64(buffer, ref index) == ev.EventID)
                {
                    // update the event in the buffer
                    index = 58;
                    CopyBool(ev.Ack, buffer, ref index);
                    CopyTime(ev.AckTimestamp, buffer, ref index);
                    CopyInt32(ev.AckUserID, buffer, ref index);
                    ushort crc = ScadaUtils.CRC16(buffer, 0, EventSize - 2);
                    CopyUInt16(crc, buffer, EventSize - 2);

                    // write the updated buffer
                    stream.Seek(ev.Position, SeekOrigin.Begin);
                    writer.Write(buffer);
                }
            }
            finally
            {
                reader?.Close();
                writer?.Close();
            }
        }
        /// <summary>
        /// Reads a row to the buffer.
        /// </summary>
        protected void ReadRowToBuffer(BinaryReader reader, ref byte[] buffer)
        {
            if (reader.ReadUInt16() != BlockMarker)
            {
                throw new ScadaException("Row marker not found.");
            }

            int rowDataSize = reader.ReadInt32();
            int fullRowSize = rowDataSize + 6;

            ResizeBuffer(ref buffer, fullRowSize, 2);
            ReadData(reader, buffer, 6, rowDataSize, true);

            // copy values to the buffer to calculate CRC
            CopyUInt16(BlockMarker, buffer, 0);
            CopyInt32(rowDataSize, buffer, 2);

            if (ScadaUtils.CRC16(buffer, 0, fullRowSize - 2) != BitConverter.ToUInt16(buffer, fullRowSize - 2))
            {
                throw new ScadaException("Row CRC error.");
            }
        }
Beispiel #6
0
        /// <summary>
        /// Reads an event into the buffer and validates the event.
        /// </summary>
        protected bool ReadEvent(BinaryReader reader, byte[] buffer, out int index)
        {
            index = 0;

            if (reader.Read(buffer, 0, EventSize) == EventSize)
            {
                if (GetUInt16(buffer, ref index) != BlockMarker)
                {
                    throw new ScadaException("Event marker not found.");
                }

                if (ScadaUtils.CRC16(buffer, 0, EventSize - 2) != BitConverter.ToUInt16(buffer, EventSize - 2))
                {
                    throw new ScadaException("Event CRC error.");
                }

                return(true);
            }
            else
            {
                return(false);
            }
        }
        /// <summary>
        /// Updates the configuration database by writing data of the specified table.
        /// </summary>
        public void Update(IBaseTable baseTable)
        {
            if (baseTable == null)
            {
                throw new ArgumentNullException(nameof(baseTable));
            }

            Stream       stream;
            BinaryWriter writer = null;

            try
            {
                stream = Stream ?? new FileStream(FileName, FileMode.Create, FileAccess.Write, FileShare.ReadWrite);
                writer = new BinaryWriter(stream, Encoding.UTF8, Stream != null);

                // write header
                writer.Write(TableType.BaseTable);
                writer.Write(MajorVersion);
                writer.Write(MinorVersion);

                PropertyDescriptorCollection props = TypeDescriptor.GetProperties(baseTable.ItemType);
                int fieldCount = Math.Min(props.Count, ushort.MaxValue);
                writer.Write((ushort)fieldCount);
                writer.Write(ReserveBuffer, 0, 12);

                if (fieldCount > 0)
                {
                    // create and write field definitions
                    FieldDef[] fieldDefs = new FieldDef[fieldCount];
                    byte[]     buffer    = new byte[FieldDefSize];

                    for (int i = 0; i < fieldCount; i++)
                    {
                        PropertyDescriptor prop = props[i];
                        bool isNullable         = prop.PropertyType.IsNullable();

                        FieldDef fieldDef = new FieldDef(
                            prop.Name,
                            isNullable ? Nullable.GetUnderlyingType(prop.PropertyType) : prop.PropertyType,
                            isNullable || prop.PropertyType.IsClass);

                        fieldDefs[i] = fieldDef;
                        WriteFieldDef(writer, fieldDef, buffer);
                    }

                    // write rows
                    byte[][] rowData   = new byte[fieldCount][];
                    bool[]   isNullArr = new bool[fieldCount];

                    foreach (object item in baseTable.EnumerateItems())
                    {
                        // get row data and size
                        int rowDataSize = 2; // CRC

                        for (int i = 0; i < fieldCount; i++)
                        {
                            object value = props[i].GetValue(item);

                            if (value == null)
                            {
                                isNullArr[i] = true;
                            }
                            else
                            {
                                FieldDef fieldDef  = fieldDefs[i];
                                byte[]   fieldData = GetFieldData(fieldDef, value, rowData[i]);
                                rowData[i]   = fieldData;
                                isNullArr[i] = false;
                                rowDataSize += (fieldDef.DataSize <= 0 ? 2 : 0) + fieldData.Length;
                            }

                            rowDataSize++; // null flag
                        }

                        // copy row data to the buffer
                        int fullRowSize = rowDataSize + 6;
                        int copyIndex   = 0;
                        ResizeBuffer(ref buffer, fullRowSize, 2);
                        CopyUInt16(BlockMarker, buffer, ref copyIndex);
                        CopyInt32(rowDataSize, buffer, ref copyIndex);

                        for (int i = 0; i < fieldCount; i++)
                        {
                            if (isNullArr[i])
                            {
                                buffer[copyIndex++] = 1;
                            }
                            else
                            {
                                buffer[copyIndex++] = 0;
                                FieldDef fieldDef  = fieldDefs[i];
                                byte[]   fieldData = rowData[i];

                                if (fieldDef.DataSize <= 0)
                                {
                                    CopyUInt16((ushort)fieldData.Length, buffer, ref copyIndex);
                                }

                                fieldData.CopyTo(buffer, copyIndex);
                                copyIndex += fieldData.Length;
                            }
                        }

                        ushort crc = ScadaUtils.CRC16(buffer, 0, fullRowSize - 2);
                        CopyUInt16(crc, buffer, fullRowSize - 2);

                        // write row data
                        writer.Write(buffer, 0, fullRowSize);
                    }
                }
            }
            finally
            {
                writer?.Close();
            }
        }