You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

342 lines
11 KiB

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
}
}