Skip to content

Instantly share code, notes, and snippets.

@INTERNALINTERFERENCE
Created November 29, 2022 23:21
Show Gist options
  • Save INTERNALINTERFERENCE/22a29c142908a87fd1a5756c3f17ad9d to your computer and use it in GitHub Desktop.
Save INTERNALINTERFERENCE/22a29c142908a87fd1a5756c3f17ad9d to your computer and use it in GitHub Desktop.
for test
// запускать можно вот так:
/*
LedStateTimedProcessor buzzerStateTimedProcessor = new( OutputLedColorType.Green);
buzzerStateTimedProcessor.StateChanged += type => Console.WriteLine( type );
buzzerStateTimedProcessor.DurationOn( arguments: new OutputLedOnArguments
{
Duration = TimeSpan.FromSeconds(30),
Alternating = new OutputLedAlternatingState()
{
Color = OutputLedColorType.Red,
DurationAlternating = TimeSpan.FromSeconds( 2 ),
DurationPrimary = TimeSpan.FromSeconds( 4 )
}
});
*/
internal class LedStateTimedProcessor
{
private readonly Timer _timer;
private OutputLedColorType _color;
public LedStateTimedProcessor( OutputLedColorType color )
{
_color = color;
_timer = new( OnTimer );
}
public OutputLedColorType State
{
get => _color;
private set
{
if ( _color == value )
return;
_color = value;
StateChanged?.Invoke( _color );
}
}
public Action<OutputLedColorType> StateChanged { get; set; }
public void DurationOff(
TimeSpan? durationOffValue )
{
var cancel = !durationOffValue.HasValue;
if ( cancel )
{
State = OutputLedColorType.None;
_timer.Change( Timeout.InfiniteTimeSpan, Timeout.InfiniteTimeSpan );
}
else
{
State = OutputLedColorType.None;
_cycles += durationOffValue.Value;
_timer.Change( durationOffValue.Value, Timeout.InfiniteTimeSpan );
}
}
private TimeSpan _cycles;
private TimeSpan _repeatCount;
private TimeSpan _durationPrimary;
private TimeSpan _durationAlternating;
private OutputLedColorType _primaryColor;
private OutputLedColorType _alternatingColor;
private bool _isAlternating;
public void DurationOn( OutputLedOnArguments arguments )
{
_cycles = TimeSpan.Zero;
_repeatCount = arguments.Duration ?? TimeSpan.MaxValue;
_primaryColor = arguments.Color ?? OutputLedColorType.Default;
_isAlternating = arguments.Alternating.IsNotNull();
if ( !_isAlternating )
{
OnTimer( null );
return;
}
_durationAlternating = arguments.Alternating.DurationAlternating;
_durationPrimary = arguments.Alternating.DurationPrimary;
_alternatingColor = arguments.Alternating.Color;
OnTimer( null );
}
private void OnTimer( object state )
{
if ( _isAlternating )
{
if ( State != _primaryColor )
{
State = _primaryColor;
_timer.Change( _durationPrimary, Timeout.InfiniteTimeSpan );
}
else
{
if ( _cycles >= _repeatCount )
{
_timer.Change( Timeout.InfiniteTimeSpan, Timeout.InfiniteTimeSpan );
return;
}
State = _alternatingColor;
_timer.Change( _durationAlternating, Timeout.InfiniteTimeSpan );
_cycles += _durationPrimary + _durationAlternating;
}
}
else
{
if ( _repeatCount == TimeSpan.MaxValue )
{
State = _primaryColor;
_timer.Change( Timeout.InfiniteTimeSpan, Timeout.InfiniteTimeSpan );
}
else
{
if ( State != _primaryColor )
{
State = _primaryColor;
_timer.Change( _repeatCount, Timeout.InfiniteTimeSpan );
}
else
State = OutputLedColorType.None;
}
}
}
}
public enum OutputLedColorType
{
[EnumMember( Value = "undefined" )]
Undefined,
[EnumMember( Value = "none" )]
None,
[EnumMember( Value = "default" )]
Default,
[EnumMember( Value = "red" )]
Red,
[EnumMember( Value = "green" )]
Green,
[EnumMember( Value = "amber" )]
Amber,
[EnumMember( Value = "blue" )]
Blue,
[EnumMember( Value = "magenta" )]
Magenta,
[EnumMember( Value = "cyan" )]
Cyan,
[EnumMember( Value = "white" )]
White
}
public class OutputLedOnArguments
{
public OutputLedOnArguments()
{
}
public OutputLedOnArguments(
OutputLedColorType? color = default,
TimeSpan? duration = default )
{
Color = color;
Duration = duration;
}
public OutputLedOnArguments(
TimeSpan durationPrimary,
OutputLedColorType? colorPrimary = default,
TimeSpan? durationAlternating = default,
OutputLedColorType? colorAlternating = default,
TimeSpan? duration = default )
{
Color = colorPrimary;
Alternating = new()
{
Color = colorAlternating ?? OutputLedColorType.Default,
DurationPrimary = durationPrimary,
DurationAlternating = durationAlternating ?? durationPrimary
};
Duration = duration;
}
/// <summary>
/// led color to set
/// </summary>
/// <remarks>
/// unspecified value means 'use <see cref="OutputLedColorType.Default"/>'
/// </remarks>
[JsonProperty( PropertyName = "color" )]
public OutputLedColorType? Color { get; set; }
/// <summary>
/// optional alternating state
/// </summary>
/// <remarks>
/// <para>
/// unspecified value means 'set led to <see cref="Color"/>'
/// </para>
/// <para>
/// specified value means 'set led to <see cref="Color"/> and alternate it as specified'
/// </para>
/// </remarks>
[JsonProperty( PropertyName = "alt" )]
public OutputLedAlternatingState Alternating { get; set; }
/// <summary>
/// optional duration to set led on for
/// </summary>
/// <remarks>
/// <para>
/// unspecified value means 'cancel any temporary state and set permanent state as specified'
/// </para>
/// specified value means 'cancel and set new temporary state as specified for specified duration, then return to permanent state'
/// </remarks>
[JsonProperty( PropertyName = "duration" )]
[JsonConverter( typeof( TimeSpanAsMillisecondsJsonConverter ) )]
public TimeSpan? Duration { get; set; }
}
public class OutputLedAlternatingState
{
/// <summary>
/// alternaing color to set
/// </summary>
[JsonProperty( PropertyName = "color" )]
[JsonRequired]
public OutputLedColorType Color { get; set; }
/// <summary>
/// duration to apply primary color for
/// </summary>
[JsonProperty( PropertyName = "duration" )]
[JsonRequired]
[JsonConverter( typeof( TimeSpanAsMillisecondsJsonConverter ) )]
public TimeSpan DurationPrimary { get; set; }
/// <summary>
/// duration to apply alternating color for
/// </summary>
[JsonProperty( PropertyName = "duration_alt" )]
[JsonRequired]
[JsonConverter( typeof( TimeSpanAsMillisecondsJsonConverter ) )]
public TimeSpan DurationAlternating { get; set; }
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment