|
|
using Mirle.Component.MPLC.DataBlocks.DeviceRange.Interfaces; using Mirle.Component.MPLC.DataBlocks.Interfaces; using System; using System.Collections; using System.Diagnostics; using System.Threading;
namespace Mirle.Component.MPLC.DataBlocks { /// <summary>
/// 檔案資料區塊
/// </summary>
public class FileDataBlock : IDataBlock, IDisposable { /// <summary>
/// 建構式
/// </summary>
/// <param name="deviceRange">設備範圍介面</param>
/// <param name="columnIndex">欄位索引</param>
public FileDataBlock(ITypeDeviceRange deviceRange, int columnIndex) { DeviceRange = deviceRange; _rawData = new byte[deviceRange.ByteArrayLength]; ColumnIndex = columnIndex; } /// <summary>
/// 原始資料
/// </summary>
private byte[] _rawData = new byte[1]; /// <summary>
/// 原始資料物件鎖定
/// </summary>
private readonly ReaderWriterLockSlim _rwLock = new ReaderWriterLockSlim(); /// <summary>
/// 設備範圍介面
/// </summary>
public ITypeDeviceRange DeviceRange { get; } /// <summary>
/// 欄位索引
/// </summary>
public int ColumnIndex { get; } /// <summary>
/// 設置原始資料
/// </summary>
/// <param name="newRawData">原始資料</param>
public void SetRawData(byte[] newRawData) { try { _rwLock.EnterWriteLock(); _rawData = newRawData; } catch (Exception ex) { Debug.WriteLine($"{ex}"); } finally { _rwLock.ExitWriteLock(); } } /// <summary>
/// 取得原始資料
/// </summary>
/// <returns>原始資料</returns>
public byte[] GetRawData() { byte[] data = new byte[DeviceRange.ByteArrayLength]; try { _rwLock.EnterReadLock(); if (_rawData != null) Array.Copy(_rawData, data, Math.Min(_rawData.Length, data.Length)); } catch (Exception ex) { Debug.WriteLine($"{ex}"); } finally { _rwLock.ExitReadLock(); } return data; } /// <summary>
/// 取得位元
/// </summary>
/// <param name="address">位置</param>
/// <param name="value">是否成功取得</param>
/// <returns>True/False</returns>
public bool TryGetBit(string address, out bool value) { value = false; try { _rwLock.EnterReadLock(); if (DeviceRange.TryGetByteArrayOffset(address, out int offset) && DeviceRange.TryGetByteArrayBitIndex(address, out int index)) { if (_rawData != null && _rawData.Length > offset) { ushort word = BitConverter.ToUInt16(_rawData, offset); BitArray bitArray = new BitArray(BitConverter.GetBytes(word)); value = bitArray.Get(index); return true; } } } catch (Exception ex) { Debug.WriteLine($"{ex}"); } finally { _rwLock.ExitReadLock(); } return false; } /// <summary>
/// 設置位元開啟
/// </summary>
/// <param name="address">位置</param>
/// <returns>True/False</returns>
public bool TrySetBitOn(string address) { return SetBit(address, true); } /// <summary>
/// 設置位元
/// </summary>
/// <param name="address">位置</param>
/// <param name="IsOn">是否開啟</param>
/// <returns>True/False</returns>
private bool SetBit(string address, bool IsOn) { try { _rwLock.EnterWriteLock(); if (DeviceRange.TryGetByteArrayOffset(address, out int offset) && DeviceRange.TryGetByteArrayBitIndex(address, out int index)) { if (_rawData != null && _rawData.Length > offset + 1) { ushort word = BitConverter.ToUInt16(_rawData, offset); BitArray bitArray = new BitArray(BitConverter.GetBytes(word)); bitArray.Set(index, IsOn); byte[] tmpBytes = new byte[2]; bitArray.CopyTo(tmpBytes, 0); _rawData[offset] = tmpBytes[0]; _rawData[offset + 1] = tmpBytes[1]; return true; } } } catch (Exception ex) { Debug.WriteLine($"{ex}"); } finally { _rwLock.ExitWriteLock(); } return false; } /// <summary>
/// 設置位元關閉
/// </summary>
/// <param name="address">位置</param>
/// <returns>True/False</returns>
public bool TrySetBitOff(string address) { return SetBit(address, false); } /// <summary>
/// 取得字元
/// </summary>
/// <param name="address">位置</param>
/// <param name="value">值</param>
/// <returns>True/False</returns>
public bool TryGetWord(string address, out int value) { value = 0; try { _rwLock.EnterReadLock(); if (DeviceRange.TryGetByteArrayOffset(address, out int offset)) { if (_rawData != null && _rawData.Length > offset) { value = BitConverter.ToUInt16(_rawData, offset); return true; } } } catch (Exception ex) { Debug.WriteLine($"{ex}"); } finally { _rwLock.ExitReadLock(); } return false; } /// <summary>
/// 設置字元
/// </summary>
/// <param name="address">位置</param>
/// <param name="value">值</param>
/// <returns>True/False</returns>
public bool TrySetWord(string address, int value) { try { _rwLock.EnterWriteLock(); if (DeviceRange.TryGetByteArrayOffset(address, out int offset)) { if (_rawData != null && _rawData.Length > offset + 1) { byte[] tmpBytes = BitConverter.GetBytes(value); _rawData[offset] = tmpBytes[0]; _rawData[offset + 1] = tmpBytes[1]; return true; } } } catch (Exception ex) { Debug.WriteLine($"{ex}"); } finally { _rwLock.ExitWriteLock(); } return false; } /// <summary>
/// 取得多個字元
/// </summary>
/// <param name="address">位置</param>
/// <param name="data">資料集</param>
/// <param name="length">長度</param>
/// <returns>True/False</returns>
public bool TryGetWords(string address, out int[] data, int length) { data = new int[length]; try { _rwLock.EnterReadLock(); if (DeviceRange.TryGetByteArrayOffset(address, out int offset)) { if (_rawData != null && _rawData.Length > offset + length) { for (int i = 0; i < length; i++) { data[i] = BitConverter.ToUInt16(_rawData, offset + i * 2); } return true; } } } catch (Exception ex) { Debug.WriteLine($"{ex}"); } finally { _rwLock.ExitReadLock(); } return false; } /// <summary>
/// 設置多個字元
/// </summary>
/// <param name="address">位置</param>
/// <param name="data">資料集</param>
/// <returns>True/False</returns>
public bool TrySetWords(string address, int[] data) { try { _rwLock.EnterWriteLock(); if (DeviceRange.TryGetByteArrayOffset(address, out int offset)) { if (_rawData != null && _rawData.Length > offset + data.Length) { for (int i = 0; i < data.Length; i++) { byte[] tmpBytes = BitConverter.GetBytes(data[i]); _rawData[offset + i * 2] = tmpBytes[0]; _rawData[offset + i * 2 + 1] = tmpBytes[1]; } return true; } } } catch (Exception ex) { Debug.WriteLine($"{ex}"); } finally { _rwLock.ExitWriteLock(); } return false; }
#region IDisposable Support
private bool disposedValue = false; /// <summary>
/// 釋放資源
/// </summary>
/// <param name="disposing"></param>
protected virtual void Dispose(bool disposing) { if (!disposedValue) { if (disposing) { _rwLock?.Dispose(); } disposedValue = true; } } /// <summary>
/// 解構式
/// </summary>
~FileDataBlock() { Dispose(false); } /// <summary>
/// 釋放資源
/// </summary>
public void Dispose() { Dispose(true); GC.SuppressFinalize(this); }
#endregion
} }
|