操控平台后端代码
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.

295 lines
10 KiB

3 months ago
using Bodk.Device.Storage.Attributes;
using Bodk.Device.Storage.EventArgs;
using Bodk.Extensions.Modbus;
namespace Bodk.Device.Storage.Modules;
public abstract class ModuleBase : IModule
{
[Ignore]
public abstract string Name { get; }
[Ignore]
public abstract string Descirption { get; }
[Ignore]
public abstract int Id { get; }
public float? CurrentPosition =>
CurrentPositionAddress is null ? null : ReadFloat(CurrentPositionAddress.Value).Result;
public float? ManualSpeed
{
get
{
if (ManualSpeedAddress is null)
throw new Exception($"Current module [{Name}] has not [manual speed] property");
return _manualSpeed ??= ReadFloat(ManualSpeedAddress.Value).Result;
}
set
{
if (ManualSpeedAddress is null || value is null)
throw new Exception($"Current module [{Name}] has not [manual speed] property");
_manualSpeed = value;
WriteFloat(ManualSpeedAddress.Value, value.Value).Wait();
_manualSpeed = ReadFloat(ManualSpeedAddress.Value).Result;
}
}
public float? AutoSpeed
{
get
{
if (AutoSpeedAddress is null)
throw new Exception($"Current module [{Name}] has not [manual speed] property");
return _autoSpeed ??= ReadFloat(AutoSpeedAddress.Value).Result;
}
set
{
if (AutoSpeedAddress is null || value is null)
throw new Exception($"Current module [{Name}] has not [auto speed] property");
_autoSpeed = value;
WriteFloat(AutoSpeedAddress.Value, value.Value).Wait();
_autoSpeed = ReadFloat(AutoSpeedAddress.Value).Result;
}
}
public float? AccDec
{
get
{
if (AccDecAddress is null)
throw new Exception($"Current module [{Name}] has not [acc/dec speed] property");
return _accDec ??= ReadFloat(AccDecAddress.Value).Result;
}
set
{
if (AccDecAddress is null || value is null)
throw new Exception($"Current module [{Name}] has not [acc/dec speed] property");
_accDec = value;
WriteFloat(AccDecAddress.Value, value.Value).Wait();
_accDec = ReadFloat(AccDecAddress.Value).Result;
}
}
public float? GotoOriginHighSpeed
{
get
{
if (GotoOriginHighSpeedAddress is null)
throw new Exception($"Current module [{Name}] has not [goto origin high speed] property");
return _gotoOriginHighSpeed ??= ReadFloat(GotoOriginHighSpeedAddress.Value).Result;
}
set
{
if (GotoOriginHighSpeedAddress is null || value is null)
throw new Exception($"Current module [{Name}] has not [goto origin high speed] property");
_gotoOriginHighSpeed = value;
WriteFloat(GotoOriginHighSpeedAddress.Value, value.Value).Wait();
_gotoOriginHighSpeed = ReadFloat(GotoOriginHighSpeedAddress.Value).Result;
}
}
public float? GotoOriginLowSpeed
{
get
{
if (GotoOriginLowSpeedAddress is null)
throw new Exception($"Current module [{Name}] has not [goto origin low speed] property");
return _gotoOriginLowSpeed ??= ReadFloat(GotoOriginLowSpeedAddress.Value).Result;
}
set
{
if (GotoOriginLowSpeedAddress is null || value is null)
throw new Exception($"Current module [{Name}] has not [goto origin low speed] property");
_gotoOriginLowSpeed = value;
WriteFloat(GotoOriginLowSpeedAddress.Value, value.Value).Wait();
_gotoOriginLowSpeed = ReadFloat(GotoOriginLowSpeedAddress.Value).Result;
}
}
private float? _manualSpeed;
private float? _autoSpeed;
private float? _accDec;
private float? _gotoOriginHighSpeed;
private float? _gotoOriginLowSpeed;
public event EventHandler<MotionTimeoutAlarmChangedEventArg>? MotionTimeoutAlarmEvent;
public event EventHandler<AlarmChangedEventArg>? AlarmEvent;
public bool MotionTimeoutAlarm { get; private set; }
public bool Alarm { get; private set; }
public bool IsEnabled { get; internal set; }
private readonly Func<ushort, bool[], Task> _writeCoilRegisterFunc;
private readonly Func<ushort, ushort, Task<bool[]>> _readCoilRegisterFunc;
private readonly Func<ushort, ushort, Task<ushort[]>> _readHoldingRegistersFunc;
private readonly Func<ushort, ushort[], Task> _writeHoldingRegistersFunc;
public virtual Task EnableAsync(bool enable)
{
return EnableAddress is null
? Task.FromException(new Exception($"current module [{Name}] does not support [enable] function"))
: _writeCoilRegisterFunc.Invoke(EnableAddress.Value, new[] { enable });
}
public Task ResetAsync()
{
return ResetAddress is null
? Task.FromException(new Exception($"current module [{Name}] does not support [reset] function"))
: _writeCoilRegisterFunc.Invoke(ResetAddress.Value, new[] { true });
}
public Task CleanAsync()
{
return CleanAddress is null
? Task.FromException(new Exception($"current module [{Name}] does not support [clean] function"))
: _writeCoilRegisterFunc.Invoke(CleanAddress.Value, new[] { true });
}
public async Task GotoOriginAsync()
{
if (GotoOriginAddress is null)
throw new Exception($"current module [{Name}] does not support [goto origin] function");
while (!(await _readCoilRegisterFunc.Invoke(OriginFlagAddress.Value, 1))[0])
{
await Task.Delay(100);
}
if (!(await _readCoilRegisterFunc.Invoke(OriginFlagAddress.Value, 1))[0])
{
await _writeCoilRegisterFunc(2, new[] { true });
throw new Exception($"current module [{Name}] goto origin failed");
}
}
public Task ForwardAsync(bool open)
{
return ForwardAddress is null
? Task.FromException(new Exception($"current module [{Name}] does not support [forward] function"))
: _writeCoilRegisterFunc.Invoke(ForwardAddress.Value, new[] { open });
}
public Task BackwardAsync(bool open)
{
return BackwardAddress is null
? Task.FromException(new Exception($"current module [{Name}] does not support [backward] function"))
: _writeCoilRegisterFunc.Invoke(BackwardAddress.Value, new[] { open });
}
public async Task RelativeMoveAsync(float destination)
{
if (MoveDistanceAddress is null)
throw new Exception($"current module [{Name}] does not support [relative move] function");
await WriteFloat(MoveDistanceAddress.Value, destination);
if (RelativeMoveAddress is null)
throw new Exception($"current module [{Name}] does not support [relative move] function");
await _writeCoilRegisterFunc.Invoke(RelativeMoveAddress.Value, new[] { true });
}
public async Task AbsoluteMoveAsync(float destination)
{
if (MoveDistanceAddress is null)
throw new Exception($"current module [{Name}] does not support [absolute move] function");
await WriteFloat(MoveDistanceAddress.Value, destination);
if (AbsoluteMoveAddress is null)
throw new Exception($"current module [{Name}] does not support [absolute move] function");
await _writeCoilRegisterFunc.Invoke(AbsoluteMoveAddress.Value, new[] { true });
}
protected ModuleBase(Action<object?, AlarmChangedEventArg> alarmEventHandler,
Action<object?, MotionTimeoutAlarmChangedEventArg> motionTimeoutAlarmEventHandler,
Func<ushort, bool[], Task> writeCoilRegisterFunc, Func<ushort, ushort, Task<bool[]>> readCoilRegisterFunc,
Func<ushort, ushort, Task<ushort[]>> readHoldingRegistersFunc,
Func<ushort, ushort[], Task> writeHoldingRegistersFunc)
{
_writeCoilRegisterFunc = writeCoilRegisterFunc;
_readCoilRegisterFunc = readCoilRegisterFunc;
_readHoldingRegistersFunc = readHoldingRegistersFunc;
_writeHoldingRegistersFunc = writeHoldingRegistersFunc;
MotionTimeoutAlarmEvent += (sender, e) => motionTimeoutAlarmEventHandler(sender, e);
AlarmEvent += (sender, e) => alarmEventHandler(sender, e);
}
internal Task WriteFloat(ushort address, float value)
{
var shorts = value.ConvertToUShort();
return _writeHoldingRegistersFunc.Invoke(address, shorts);
}
internal async Task<float> ReadFloat(ushort address)
{
var shorts = await _readHoldingRegistersFunc.Invoke(address, 2);
var value = shorts.ConvertToFloat();
return value[0];
}
internal void OnMotionTimeoutAlarmChanged(MotionTimeoutAlarmChangedEventArg e)
{
MotionTimeoutAlarm = e.Status;
MotionTimeoutAlarmEvent?.Invoke(this, e);
}
internal void OnAlarmChanged(AlarmChangedEventArg e)
{
Alarm = e.Status;
AlarmEvent?.Invoke(this, e);
}
internal virtual ushort? MotionTimeoutAlarmAddress => null;
internal virtual ushort? AlarmAddress => null;
internal virtual ushort? IsEnabledAddress => null;
internal virtual ushort? EnableAddress => null;
internal virtual ushort? ResetAddress => null;
internal virtual ushort? CleanAddress => null;
internal virtual ushort? GotoOriginAddress => null;
internal virtual ushort? OriginFlagAddress => null;
internal virtual ushort? ForwardAddress => null;
internal virtual ushort? BackwardAddress => null;
internal virtual ushort? AbsoluteMoveAddress => null;
internal virtual ushort? RelativeMoveAddress => null;
internal virtual ushort? MoveDistanceAddress => null;
internal virtual ushort? CurrentPositionAddress => null;
internal virtual ushort? ManualSpeedAddress => null;
internal virtual ushort? AutoSpeedAddress => null;
internal virtual ushort? AccDecAddress => null;
internal virtual ushort? GotoOriginHighSpeedAddress => null;
internal virtual ushort? GotoOriginLowSpeedAddress => null;
internal ModuleDescription GetDescription()
{
return new ModuleDescription
{
Name = Name,
Id = Id,
Description = Descirption
};
}
}