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.
 
 
 
 
 

307 lines
11 KiB

using Mirle.Component.MPLC.DataBlocks.DeviceRange.Interfaces;
using System;
using System.Collections;
using System.Diagnostics;
using System.IO;
using System.IO.MemoryMappedFiles;
namespace Mirle.Component.MPLC.DataBlocks
{
/// <summary>
/// SM 資料區塊 (Int32)
/// </summary>
public class SMDataBlockInt32 : SMDataBlock
{
/// <summary>
/// 建構式
/// </summary>
/// <param name="deviceRange">設備範圍介面</param>
/// <param name="sharedMemoryName">共享記憶體名稱</param>
public SMDataBlockInt32(ITypeDeviceRange deviceRange, string sharedMemoryName) : base(deviceRange, sharedMemoryName) { }
/// <summary>
/// 起始偏移量
/// </summary>
private readonly int _startOffset = 4;
/// <summary>
/// 初始化
/// </summary>
protected override void Initial()
{
_mmfLength = DeviceRange.ByteArrayLength;
#if NET5_0 || NET6_0
if (OperatingSystem.IsWindows())
{
_mmf = MemoryMappedFile.CreateOrOpen(_mmfName, _startOffset + (_mmfLength * 2));
}
else
{
_mmf = MemoryMappedFile.CreateFromFile(_mmfName);
}
#elif NETFRAMEWORK
_mmf = MemoryMappedFile.CreateOrOpen(_mmfName, _startOffset + (_mmfLength * 2));
#else
_mmf = MemoryMappedFile.CreateFromFile(_mmfName);
#endif
}
/// <summary>
/// 設置原始資料
/// </summary>
/// <param name="newRawData">原始資料</param>
public override void SetRawData(byte[] newRawData)
{
try
{
_rwLock.EnterWriteLock();
MemoryMappedViewStream stream = _mmf.CreateViewStream();
using BinaryWriter writer = new BinaryWriter(stream);
stream.Seek(_startOffset, SeekOrigin.Begin);
for (int i = 0; i < Math.Min(newRawData.Length, _mmfLength); i += 2)
{
writer.Write(newRawData[i]);
writer.Write(newRawData[i + 1]);
stream.Seek(2, SeekOrigin.Current);
}
}
finally
{
_rwLock.ExitWriteLock();
}
}
/// <summary>
/// 取得原始資料
/// </summary>
/// <returns>原始資料</returns>
public override byte[] GetRawData()
{
byte[] data = new byte[_mmfLength];
try
{
_rwLock.EnterReadLock();
MemoryMappedViewStream stream = _mmf.CreateViewStream();
using BinaryReader reader = new BinaryReader(stream);
stream.Seek(_startOffset, SeekOrigin.Begin);
for (int i = 0; i < _mmfLength; i += 2)
{
data[i] = reader.ReadByte();
data[i + 1] = reader.ReadByte();
stream.Seek(2, SeekOrigin.Current);
}
}
finally
{
_rwLock.ExitReadLock();
}
return data;
}
/// <summary>
/// 取得位元
/// </summary>
/// <param name="address">位置</param>
/// <param name="value">是否成功取得</param>
/// <returns>True/False</returns>
public override 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))
{
MemoryMappedViewStream stream = _mmf.CreateViewStream();
using BinaryReader reader = new BinaryReader(stream);
stream.Seek(_startOffset + offset * 2, SeekOrigin.Begin);
ushort word = reader.ReadUInt16();
BitArray bitArray = new BitArray(BitConverter.GetBytes(word));
value = bitArray.Get(index);
return true;
}
}
catch (Exception ex)
{
Debug.WriteLine($"{ex.Message}-{ex.StackTrace}");
}
finally
{
_rwLock.ExitReadLock();
}
return false;
}
/// <summary>
/// 設置位元
/// </summary>
/// <param name="address">位置</param>
/// <param name="IsOn">是否開啟</param>
/// <returns>True/False</returns>
protected override bool SetBit(string address, bool IsOn)
{
try
{
_rwLock.EnterWriteLock();
if (DeviceRange.TryGetByteArrayOffset(address, out int offset) && DeviceRange.TryGetByteArrayBitIndex(address, out int index))
{
int startOffset = _startOffset + offset * 2;
MemoryMappedViewStream stream = _mmf.CreateViewStream();
using BinaryReader reader = new BinaryReader(stream);
stream.Seek(startOffset, SeekOrigin.Begin);
ushort word = reader.ReadUInt16();
BitArray bitArray = new BitArray(BitConverter.GetBytes(word));
bitArray.Set(index, IsOn);
byte[] tmpBytes = new byte[2];
bitArray.CopyTo(tmpBytes, 0);
stream = _mmf.CreateViewStream();
using BinaryWriter writer = new BinaryWriter(stream);
stream.Seek(startOffset, SeekOrigin.Begin);
writer.Write(tmpBytes[0]);
writer.Write(tmpBytes[1]);
return true;
}
}
catch (Exception ex)
{
Debug.WriteLine($"{ex.Message}-{ex.StackTrace}");
}
finally
{
_rwLock.ExitWriteLock();
}
return false;
}
/// <summary>
/// 取得字元
/// </summary>
/// <param name="address">位置</param>
/// <param name="value">值</param>
/// <returns>True/False</returns>
public override bool TryGetWord(string address, out int value)
{
value = 0;
try
{
_rwLock.EnterReadLock();
if (DeviceRange.TryGetByteArrayOffset(address, out int offset))
{
MemoryMappedViewStream stream = _mmf.CreateViewStream();
using BinaryReader reader = new BinaryReader(stream);
stream.Seek(_startOffset + offset * 2, SeekOrigin.Begin);
value = reader.ReadUInt16();
return true;
}
}
catch (Exception ex)
{
Debug.WriteLine($"{ex.Message}-{ex.StackTrace}");
}
finally
{
_rwLock.ExitReadLock();
}
return false;
}
/// <summary>
/// 設置字元
/// </summary>
/// <param name="address">位置</param>
/// <param name="value">值</param>
/// <returns>True/False</returns>
public override bool TrySetWord(string address, int value)
{
try
{
_rwLock.EnterWriteLock();
if (DeviceRange.TryGetByteArrayOffset(address, out int offset))
{
MemoryMappedViewStream stream = _mmf.CreateViewStream();
using var writer = new BinaryWriter(stream);
stream.Seek(_startOffset + offset * 2, SeekOrigin.Begin);
byte[] tmpBytes = BitConverter.GetBytes(value);
writer.Write(tmpBytes[0]);
writer.Write(tmpBytes[1]);
return true;
}
}
catch (Exception ex)
{
Debug.WriteLine($"{ex.Message}-{ex.StackTrace}");
}
finally
{
_rwLock.ExitWriteLock();
}
return false;
}
/// <summary>
/// 取得多個字元
/// </summary>
/// <param name="address">位置</param>
/// <param name="data">資料及</param>
/// <param name="length">長度</param>
/// <returns>True/False</returns>
public override bool TryGetWords(string address, out int[] data, int length)
{
data = new int[length];
try
{
_rwLock.EnterReadLock();
if (DeviceRange.TryGetByteArrayOffset(address, out int offset))
{
MemoryMappedViewStream stream = _mmf.CreateViewStream();
using BinaryReader reader = new BinaryReader(stream);
stream.Seek(_startOffset + offset * 2, SeekOrigin.Begin);
for (int i = 0; i < length; i++)
{
data[i] = reader.ReadUInt16();
stream.Seek(2, SeekOrigin.Current);
}
return true;
}
}
catch (Exception ex)
{
Debug.WriteLine($"{ex.Message}-{ex.StackTrace}");
}
finally
{
_rwLock.ExitReadLock();
}
return false;
}
/// <summary>
/// 設置多個字元
/// </summary>
/// <param name="address">位置</param>
/// <param name="data">資料集</param>
/// <returns>True/False</returns>
public override bool TrySetWords(string address, int[] data)
{
try
{
_rwLock.EnterWriteLock();
if (DeviceRange.TryGetByteArrayOffset(address, out int offset))
{
MemoryMappedViewStream stream = _mmf.CreateViewStream();
using BinaryWriter writer = new BinaryWriter(stream);
stream.Seek(_startOffset + offset * 2, SeekOrigin.Begin);
for (int i = 0; i < data.Length; i++)
{
byte[] tmpBytes = BitConverter.GetBytes(data[i]);
writer.Write(tmpBytes[0]);
writer.Write(tmpBytes[1]);
stream.Seek(2, SeekOrigin.Current);
}
return true;
}
}
catch (Exception ex)
{
Debug.WriteLine($"{ex.Message}-{ex.StackTrace}");
}
finally
{
_rwLock.ExitWriteLock();
}
return false;
}
}
}