我们在设计AT Command,需要把期望AT Response是什么样的信息放进去,这样在底层进行AT通讯的时候就可以自动加入Retry功能。
定义ResultCode枚举变量
public enum ResultCode
{
OK,
ERROR
}
定义ResponseExpectation类
- 告知AT Response需不需要包含期望的Result Code
- 告知AT Response中对于总体Data Lines有什么期许
- 告知AT Response中对于某一行Data Line有什么期许
public class ResponseExpectation
{
public ResultCode? ExpectedResultCode { get; set; }
public Predicate<string[]> AllDataLinesPredicate { get; set; }
public Predicate<string>[] AnyDataLinePredicates { get; set; }
public bool Accepts(ResultCode? resultCode, string[] dataLines)
{
return Accepts(resultCode) && Accepts(dataLines);
}
private bool Accepts(ResultCode? resultCode)
{
if (!ExpectedResultCode.HasValue)
return true;
return ExpectedResultCode == resultCode;
}
private bool Accepts(string[] dataLines)
{
if (!AllDataLinesPredicateAccepts(dataLines))
return false;
if (!AnyDataLinePredicatesAccept(dataLines))
return false;
return true;
}
private bool AllDataLinesPredicateAccepts(string[] dataLines)
{
return AllDataLinesPredicate == null || AllDataLinesPredicate(dataLines);
}
private bool AnyDataLinePredicatesAccept(string[] dataLines)
{
return AnyDataLinePredicates.All(
dataLinePredicate => dataLines.Any(line => dataLinePredicate(line)));
}
}
定义AtCommand类
public class AtCommand
{
public string RawCommand { get; set; }
public string SuffixedRawCommand
{
get
{
const string suffix = "\r";
return RawCommand + suffix;
}
}
public ResponseExpectation ResponseExpectation { get; set; }
public override string ToString()
{
return RawCommand;
}
}
定义AtCommandBuilder类
因为AtCommand对象在构造的时候相对有些复杂,于是我们用一个单独的AtCommandBuilder类去帮助构造AtCommand对象。
public class AtCommandBuilder
{
private string _rawCommand;
private ResultCode? _expectedResultCode;
private Predicate<string[]> _allDataLinesPredicate;
private readonly List<Predicate<string>> _anyDataLinePredicates = new List<Predicate<string>>();
public AtCommandBuilder WithRawCommand(string rawCommand)
{
if (string.IsNullOrWhiteSpace(rawCommand))
throw new ArgumentException("Raw command can't be Null or WhiteSpace.", "rawCommand");
_rawCommand = rawCommand.Trim();
return this;
}
public AtCommandBuilder WithExpectedResultCode(ResultCode expectedResultCode)
{
_expectedResultCode = expectedResultCode;
return this;
}
public AtCommandBuilder WithExpectedOkResultCode()
{
return WithExpectedResultCode(ResultCode.OK);
}
public AtCommandBuilder WithAllDataLinesPredicate(Predicate<string[]> predicate)
{
_allDataLinesPredicate = predicate;
return this;
}
public AtCommandBuilder WithAnyDataLinePredicate(Predicate<string> predicate)
{
_anyDataLinePredicates.Add(predicate);
return this;
}
public AtCommandBuilder WithAnyDataLinePredicateStartsWith(string startCriterion)
{
return WithAnyDataLinePredicate(
dateLine => dateLine.StartsWith(startCriterion, StringComparison.CurrentCultureIgnoreCase));
}
public AtCommand Build()
{
return new AtCommand
{
RawCommand = _rawCommand,
ResponseExpectation = new ResponseExpectation
{
ExpectedResultCode = _expectedResultCode,
AllDataLinesPredicate = _allDataLinesPredicate,
AnyDataLinePredicates = _anyDataLinePredicates.ToArray()
}
};
}
}