Merged in develop (pull request #36)

Develop
This commit is contained in:
2021-07-03 12:35:42 +00:00
20 changed files with 1174 additions and 327 deletions
+2 -1
View File
@@ -123,7 +123,8 @@ namespace AstroMath.UnitTests
var altAz = _astroMath.ConvertEqToHoz(hourAngle, latitude, equatorialCoordinates); var altAz = _astroMath.ConvertEqToHoz(hourAngle, latitude, equatorialCoordinates);
Assert.That(altAz.Altitude, Is.EqualTo(20.958562421092779)); Assert.That(altAz.Altitude, Is.GreaterThan(20.958562421092770));
Assert.That(altAz.Altitude, Is.LessThanOrEqualTo(20.958562421092779));
Assert.That(altAz.Azimuth, Is.EqualTo(281.2728706962269)); Assert.That(altAz.Azimuth, Is.EqualTo(281.2728706962269));
} }
@@ -2,6 +2,7 @@
using System.Globalization; using System.Globalization;
using System.Reflection; using System.Reflection;
using ASCOM; using ASCOM;
using ASCOM.Astrometry;
using ASCOM.Astrometry.AstroUtils; using ASCOM.Astrometry.AstroUtils;
using ASCOM.Astrometry.NOVAS; using ASCOM.Astrometry.NOVAS;
using ASCOM.DeviceInterface; using ASCOM.DeviceInterface;
@@ -17,20 +18,23 @@ namespace Meade.net.Telescope.UnitTests
{ {
public class TestProperties public class TestProperties
{ {
internal string telescopeRaResult = "HH:MM:SS"; internal string telescopeRaResult { get; set; } = "HH:MM:SS";
internal double rightAscension = 1.2; //todo rename to declination; internal double rightAscension { get; set; } = 1.2; //todo rename to declination;
internal double declination = 45; internal double declination { get; set; } = 45;
internal string SiteLatitudeString = "testLatString"; internal string SiteLatitudeString { get; set; } = "testLatString";
internal double SiteLatitudeValue = 123.45; internal double SiteLatitudeValue { get; set; } = 123.45;
internal string telescopeDate = "10/15/20"; internal string telescopeDate { get; set; } = "10/15/20";
internal string telescopeTime = "20:15:10"; internal string telescopeTime { get; set; } = "20:15:10";
internal string telescopeUtcCorrection = "-1.0"; internal string telescopeUtcCorrection { get; set; } = "-1.0";
internal double hourAngle; internal double hourAngle { get; set; }
internal int telescopeAltitude = 45; internal int telescopeAltitude { get; set; } = 45;
internal int telescopeAzimuth = 200; internal int telescopeAzimuth { get; set; } = 200;
internal char[] AlignmentStatus { get; set; }
internal string TrackingRate { get; set; }
} }
[TestFixture] [TestFixture]
@@ -99,10 +103,17 @@ namespace Meade.net.Telescope.UnitTests
SameDevice = 1 SameDevice = 1
}; };
_sharedResourcesWrapperMock.Setup(x => x.Connect("Serial", It.IsAny<string>(), It.IsAny<ITraceLogger>())).Returns( () => _connectionInfo ); _sharedResourcesWrapperMock.Setup(x => x.Connect("Serial", It.IsAny<string>(), It.IsAny<ITraceLogger>())).Returns( () => _connectionInfo);
_sharedResourcesWrapperMock.Setup(x => x.ReadProfile()).Returns(_profileProperties); _sharedResourcesWrapperMock.Setup(x => x.ReadProfile()).Returns(_profileProperties);
_sharedResourcesWrapperMock
.SetupProperty(x => x.SideOfPier)
.SetupProperty(x => x.TargetRightAscension)
.SetupProperty(x => x.TargetDeclination)
.SetupProperty(x => x.SlewSettleTime)
.SetupProperty(x => x.IsLongFormat);
_astroMathsMock = new Mock<IAstroMaths>(); _astroMathsMock = new Mock<IAstroMaths>();
_clockMock = new Mock<IClock>(); _clockMock = new Mock<IClock>();
@@ -113,8 +124,14 @@ namespace Meade.net.Telescope.UnitTests
_sharedResourcesWrapperMock.Object, _astroMathsMock.Object, _clockMock.Object, _novasMock.Object); _sharedResourcesWrapperMock.Object, _astroMathsMock.Object, _clockMock.Object, _novasMock.Object);
} }
private void ConnectTelescope(string productName = TelescopeList.Autostar497, string firmwareVersion = TelescopeList.Autostar497_31Ee) private void ConnectTelescope(string productName = TelescopeList.Autostar497, string firmwareVersion = TelescopeList.Autostar497_31Ee, string alignmentStatus = "GT0")
{ {
_testProperties.AlignmentStatus = alignmentStatus.ToCharArray();
_sharedResourcesWrapperMock.Setup(x => x.SendChars("GW", false, 3)).Returns(() => new string(_testProperties.AlignmentStatus));
_sharedResourcesWrapperMock.Setup(x => x.SendBlind("AP", false)).Callback(() => _testProperties.AlignmentStatus[1] = 'T');
_sharedResourcesWrapperMock.Setup(x => x.SendBlind("AL", false)).Callback(() => _testProperties.AlignmentStatus[1] = 'N');
_sharedResourcesWrapperMock.Setup(x => x.SendString("Gt", false)).Returns( () => _testProperties.SiteLatitudeString); _sharedResourcesWrapperMock.Setup(x => x.SendString("Gt", false)).Returns( () => _testProperties.SiteLatitudeString);
_utilMock.Setup(x => x.DMSToDegrees(_testProperties.SiteLatitudeString)).Returns( () => _testProperties.SiteLatitudeValue); _utilMock.Setup(x => x.DMSToDegrees(_testProperties.SiteLatitudeString)).Returns( () => _testProperties.SiteLatitudeValue);
@@ -125,6 +142,12 @@ namespace Meade.net.Telescope.UnitTests
_sharedResourcesWrapperMock.Setup(x => x.SendString("GL", false)).Returns(() => _testProperties.telescopeTime); _sharedResourcesWrapperMock.Setup(x => x.SendString("GL", false)).Returns(() => _testProperties.telescopeTime);
_sharedResourcesWrapperMock.Setup(x => x.SendString("GG", false)).Returns(() => _testProperties.telescopeUtcCorrection); _sharedResourcesWrapperMock.Setup(x => x.SendString("GG", false)).Returns(() => _testProperties.telescopeUtcCorrection);
const string siderealTrackingRate = "+60.1";
_testProperties.TrackingRate = siderealTrackingRate;
_sharedResourcesWrapperMock.Setup(x => x.SendString("GT", false)).Returns(() => _testProperties.TrackingRate);
_sharedResourcesWrapperMock.Setup(x => x.SendBlind("TL", false)).Callback(() => _testProperties.TrackingRate = "lunar");
_sharedResourcesWrapperMock.Setup(x => x.SendBlind("TQ", false)).Callback(() => _testProperties.TrackingRate = siderealTrackingRate);
_sharedResourcesWrapperMock.Setup(x => x.ProductName).Returns(() => productName); _sharedResourcesWrapperMock.Setup(x => x.ProductName).Returns(() => productName);
_sharedResourcesWrapperMock.Setup(x => x.FirmwareVersion).Returns(() => firmwareVersion); _sharedResourcesWrapperMock.Setup(x => x.FirmwareVersion).Returns(() => firmwareVersion);
@@ -136,6 +159,8 @@ namespace Meade.net.Telescope.UnitTests
_sharedResourcesWrapperMock.SetupGet(x => x.IsParked).Returns(() => _isParked); _sharedResourcesWrapperMock.SetupGet(x => x.IsParked).Returns(() => _isParked);
_sharedResourcesWrapperMock.SetupGet(x => x.ParkedPosition).Returns(() => _parkedPosition); _sharedResourcesWrapperMock.SetupGet(x => x.ParkedPosition).Returns(() => _parkedPosition);
_sharedResourcesWrapperMock.SetupProperty(x => x.IsGuiding);
_astroMathsMock _astroMathsMock
.Setup(x => x.ConvertHozToEq(It.IsAny<DateTime>(), It.IsAny<double>(), It.IsAny<double>(), .Setup(x => x.ConvertHozToEq(It.IsAny<DateTime>(), It.IsAny<double>(), It.IsAny<double>(),
It.IsAny<HorizonCoordinates>())).Returns(() => new EquatorialCoordinates { Declination = _testProperties.declination, RightAscension = _testProperties.rightAscension }); It.IsAny<HorizonCoordinates>())).Returns(() => new EquatorialCoordinates { Declination = _testProperties.declination, RightAscension = _testProperties.rightAscension });
@@ -761,15 +786,17 @@ namespace Meade.net.Telescope.UnitTests
} }
[TestCase("A", AlignmentModes.algAltAz)] [TestCase("A", AlignmentModes.algAltAz, TelescopeList.Autostar497, TelescopeList.Autostar497_31Ee)]
[TestCase("P", AlignmentModes.algPolar)] [TestCase("P", AlignmentModes.algPolar, TelescopeList.Autostar497, TelescopeList.Autostar497_31Ee)]
[TestCase("G", AlignmentModes.algGermanPolar)] [TestCase("A", AlignmentModes.algAltAz, TelescopeList.Autostar497, TelescopeList.Autostar497_43Eg)]
public void AlignmentMode_Get_WhenScopeInAltAz_ReturnsAltAz(string telescopeMode, AlignmentModes alignmentMode) [TestCase("P", AlignmentModes.algPolar, TelescopeList.Autostar497, TelescopeList.Autostar497_43Eg)]
[TestCase("G", AlignmentModes.algGermanPolar, TelescopeList.Autostar497, TelescopeList.Autostar497_43Eg)]
public void AlignmentMode_Get_WhenScopeInAltAz_ReturnsAltAz(string telescopeMode, AlignmentModes alignmentMode, string productName, string firmware)
{ {
const char ack = (char)6; const char ack = (char)6;
_sharedResourcesWrapperMock.Setup(x => x.SendChar(ack.ToString(), true)).Returns(telescopeMode); _sharedResourcesWrapperMock.Setup(x => x.SendChar(ack.ToString(), false)).Returns(telescopeMode);
ConnectTelescope(); ConnectTelescope(productName, firmware, $"{telescopeMode}N0");
var actualResult = _telescope.AlignmentMode; var actualResult = _telescope.AlignmentMode;
@@ -996,20 +1023,85 @@ namespace Meade.net.Telescope.UnitTests
_sharedResourcesWrapperMock.Verify(x => x.SendChar("P", false), Times.AtLeastOnce); _sharedResourcesWrapperMock.Verify(x => x.SendChar("P", false), Times.AtLeastOnce);
} }
[TestCase("High", false, true)] [TestCase("High")]
[TestCase("High", true, true)] [TestCase("Low")]
[TestCase("Low", false, false)] public void Precision_Set_WhenSecondConnectionMade_ThenTelescopePrecisionNotChanged(string desiredPresision)
[TestCase("Low", true, false)]
public void Precision_Set_WhenSecondConnectionMade_ThenTelescopePrecisionNotChanged(string desiredPresision, bool telescopePrecision, bool finalPrecision)
{ {
var isLongFormat = desiredPresision == "High"
|| (desiredPresision == "Low"
? false
: throw new ArgumentOutOfRangeException(nameof(desiredPresision), desiredPresision, "Should be High or Low"));
_sharedResourcesWrapperMock.SetupProperty(x => x.IsLongFormat, isLongFormat);
_sharedResourcesWrapperMock.Setup(x => x.SendString("GR", false)).Returns(() => _testProperties.telescopeRaResult);
_utilMock.Setup(x => x.HMSToHours(_testProperties.telescopeRaResult)).Returns(() => _testProperties.rightAscension);
_profileProperties.Precision = desiredPresision; _profileProperties.Precision = desiredPresision;
_connectionInfo.SameDevice = 2; _connectionInfo.SameDevice = 2;
//_connectionInfo.Connections = 2; //_connectionInfo.Connections = 2;
_telescope.Connected = true; _telescope.Connected = true;
_sharedResourcesWrapperMock.Verify(x => x.SendChar("P", false), Times.Never); _sharedResourcesWrapperMock.Verify(x => x.SendChar("P", false), Times.Never);
_sharedResourcesWrapperMock.Verify(x => x.IsLongFormat, Times.Once);
}
[Test]
public void IsLongFormat_WhenHighPrecisionNotSupportedAndSecondConnectionMade_ThenDigitPrecisionValuesArePreserved()
{
var ra = 12d;
var dec = 34d;
_utilMock.Setup(x => x.HoursToHM(ra, ":", "", 1)).Returns(ra + "HM");
_utilMock.Setup(x => x.DegreesToDM(dec, "*", "", 0)).Returns(dec + "DM");
ConnectTelescope(TelescopeList.LX200CLASSIC);
_telescope.TargetRightAscension = ra;
_telescope.TargetDeclination = dec;
Assert.That(_connectionInfo.SameDevice, Is.EqualTo(1));
var secondTelescopeInstance =
new ASCOM.Meade.net.Telescope(_utilMock.Object, _utilExtraMock.Object, _astroUtilsMock.Object,
_sharedResourcesWrapperMock.Object, _astroMathsMock.Object, _clockMock.Object, _novasMock.Object);
Assert.That(secondTelescopeInstance.Connected, Is.False);
_connectionInfo.SameDevice = 2;
secondTelescopeInstance.Connected = true;
secondTelescopeInstance.TargetRightAscension = ra;
secondTelescopeInstance.TargetDeclination = dec;
_utilMock.Verify(x => x.HoursToHM(ra, ":", "", 1), Times.Exactly(2));
_utilMock.Verify(x => x.DegreesToDM(dec, "*", "", 0), Times.Exactly(2));
_utilMock.Verify(x => x.HoursToHMS(It.IsAny<double>(), It.IsAny<string>(), It.IsAny<string>(), It.IsAny<string>(), 2), Times.Never);
_utilMock.Verify(x => x.DegreesToDMS(It.IsAny<double>(), It.IsAny<string>(), It.IsAny<string>(), It.IsAny<string>(), 2), Times.Never);
}
[TestCase(0)]
[TestCase(1)]
[TestCase(2)]
public void SlewSettleTime_WhenSecondConnectionMade_ThenSlewSettleTimeIsPreserved(short slewSettleTime)
{
ConnectTelescope();
_telescope.SlewSettleTime = slewSettleTime;
Assert.That(_connectionInfo.SameDevice, Is.EqualTo(1));
var secondTelescopeInstance =
new ASCOM.Meade.net.Telescope(_utilMock.Object, _utilExtraMock.Object, _astroUtilsMock.Object,
_sharedResourcesWrapperMock.Object, _astroMathsMock.Object, _clockMock.Object, _novasMock.Object);
Assert.That(secondTelescopeInstance.Connected, Is.False);
_connectionInfo.SameDevice = 2;
secondTelescopeInstance.Connected = true;
Assert.That(secondTelescopeInstance.SlewSettleTime, Is.EqualTo(slewSettleTime));
} }
[Test] [Test]
@@ -1036,12 +1128,15 @@ namespace Meade.net.Telescope.UnitTests
Assert.That(result, Is.False); Assert.That(result, Is.False);
} }
[Test] [TestCase(TelescopeList.Autostar497_30Ee, false)]
public void CanSetTracking_Get_ReturnsTrue() [TestCase(TelescopeList.Autostar497_43Eg, true)]
public void CanSetTracking_Get_ReturnsTrueIffGWCommandIsSupported(string firmware, bool supported)
{ {
ConnectTelescope(firmwareVersion: firmware);
var result = _telescope.CanSetTracking; var result = _telescope.CanSetTracking;
Assert.That(result, Is.True); Assert.That(result, Is.EqualTo(supported));
} }
[Test] [Test]
@@ -1229,10 +1324,15 @@ namespace Meade.net.Telescope.UnitTests
public void DestinationSideOfPier_WhenHASiderealTimeDiffIsNotNull_ThenSideOfPierIsCalculated(double ra, double dec, double siderealTime, PierSide expectedDSOP) public void DestinationSideOfPier_WhenHASiderealTimeDiffIsNotNull_ThenSideOfPierIsCalculated(double ra, double dec, double siderealTime, PierSide expectedDSOP)
{ {
// given // given
// SideralTime uses ConditionRA to normalize to 0..24h, so we use it to mock the property
// deterministic start
_sharedResourcesWrapperMock.Object.SideOfPier = PierSide.pierUnknown;
// SideralTime uses ConditionRA to normalize to [0..24h), so we use it to mock the property
_astroUtilsMock.Setup(x => x.ConditionRA(It.IsAny<double>())).Returns(siderealTime); _astroUtilsMock.Setup(x => x.ConditionRA(It.IsAny<double>())).Returns(siderealTime);
var ha = siderealTime - ra; var ha = siderealTime - ra;
// normalized hour angle range is [-12h..12h]
var normalisedHA = ha > 12 ? ha - 24 : ha < -12 ? ha + 24 : ha; var normalisedHA = ha > 12 ? ha - 24 : ha < -12 ? ha + 24 : ha;
_astroUtilsMock.Setup(x => x.ConditionHA(It.Is<double>(v => v == ha))).Returns(normalisedHA); _astroUtilsMock.Setup(x => x.ConditionHA(It.Is<double>(v => v == ha))).Returns(normalisedHA);
@@ -1242,7 +1342,7 @@ namespace Meade.net.Telescope.UnitTests
var actualDSOP = _telescope.DestinationSideOfPier(ra, dec); var actualDSOP = _telescope.DestinationSideOfPier(ra, dec);
// then // then
Assert.That(siderealTime, Is.InRange(0, 24 + double.Epsilon)); Assert.That(siderealTime, Is.InRange(0, 24));
Assert.That(normalisedHA, Is.InRange(-12, 12 + double.Epsilon)); Assert.That(normalisedHA, Is.InRange(-12, 12 + double.Epsilon));
Assert.That(actualDSOP, Is.EqualTo(expectedDSOP)); Assert.That(actualDSOP, Is.EqualTo(expectedDSOP));
@@ -1617,6 +1717,9 @@ namespace Meade.net.Telescope.UnitTests
[TestCase(GuideDirections.guideSouth, TelescopeAxes.axisSecondary)] [TestCase(GuideDirections.guideSouth, TelescopeAxes.axisSecondary)]
public void PulseGuide_WhenMovingAxisAndPulseGuideAttempted_ThenThrowsExpectedException(GuideDirections direction, TelescopeAxes axes) public void PulseGuide_WhenMovingAxisAndPulseGuideAttempted_ThenThrowsExpectedException(GuideDirections direction, TelescopeAxes axes)
{ {
_sharedResourcesWrapperMock.SetupProperty(x => x.MovingPrimary);
_sharedResourcesWrapperMock.SetupProperty(x => x.MovingSecondary);
_sharedResourcesWrapperMock.SetupProperty(x => x.EarliestNonSlewingTime, DateTime.MinValue);
_sharedResourcesWrapperMock.Setup(x => x.SendString("D", false)).Returns(""); _sharedResourcesWrapperMock.Setup(x => x.SendString("D", false)).Returns("");
var duration = 0; var duration = 0;
@@ -1627,6 +1730,8 @@ namespace Meade.net.Telescope.UnitTests
var exception = Assert.Throws<InvalidOperationException>(() => _telescope.PulseGuide(direction, duration)); var exception = Assert.Throws<InvalidOperationException>(() => _telescope.PulseGuide(direction, duration));
Assert.That(exception.Message, Is.EqualTo("Unable to PulseGuide while moving same axis.")); Assert.That(exception.Message, Is.EqualTo("Unable to PulseGuide while moving same axis."));
Assert.That(_sharedResourcesWrapperMock.Object.MovingPrimary, Is.EqualTo(axes == TelescopeAxes.axisPrimary));
Assert.That(_sharedResourcesWrapperMock.Object.MovingSecondary, Is.EqualTo(axes == TelescopeAxes.axisSecondary));
} }
[TestCase(GuideDirections.guideEast)] [TestCase(GuideDirections.guideEast)]
@@ -1845,6 +1950,173 @@ namespace Meade.net.Telescope.UnitTests
Assert.That(excpetion.AccessorSet, Is.True); Assert.That(excpetion.AccessorSet, Is.True);
} }
[TestCase(0, 34, PierSide.pierEast)]
[TestCase(12, 34, PierSide.pierEast)]
[TestCase(23.4, 34, PierSide.pierWest)]
public void SideOfPier_WhenSecondConnectionMade_ThenValueIsPreserved(double ra, double dec, PierSide expectedPierSide)
{
_sharedResourcesWrapperMock.Setup(x => x.SendChar("MS", false)).Returns("0");
_utilMock.Setup(x => x.HMSToHours(null)).Returns(ra);
_utilMock.Setup(x => x.DMSToDegrees(null)).Returns(dec);
_astroUtilsMock.Setup(x => x.ConditionHA(It.IsAny<double>())).Returns<double>(pHA => pHA < -12 ? pHA + 12 : pHA > 12 ? pHA - 12 : pHA);
_astroUtilsMock.Setup(x => x.ConditionRA(It.IsAny<double>())).Returns<double>(pRA => pRA < 0 ? pRA + 24 : pRA >= 24 ? pRA - 24 : pRA);
ConnectTelescope(firmwareVersion: TelescopeList.Autostar497_43Eg);
Assert.That(_connectionInfo.SameDevice, Is.EqualTo(1));
_telescope.SlewToCoordinates(ra, dec);
var sideOfPierAfterSlew = _telescope.SideOfPier;
Assert.That(sideOfPierAfterSlew, Is.EqualTo(expectedPierSide));
var secondTelescopeInstance =
new ASCOM.Meade.net.Telescope(_utilMock.Object, _utilExtraMock.Object, _astroUtilsMock.Object,
_sharedResourcesWrapperMock.Object, _astroMathsMock.Object, _clockMock.Object, _novasMock.Object);
Assert.That(secondTelescopeInstance.Connected, Is.False);
_connectionInfo.SameDevice = 2;
secondTelescopeInstance.Connected = true;
Assert.That(secondTelescopeInstance.SideOfPier, Is.EqualTo(sideOfPierAfterSlew));
_sharedResourcesWrapperMock.Verify(x => x.SendChar("MS", false), Times.Once);
_utilMock.Verify(x => x.HMSToHours(null), Times.Once);
_utilMock.Verify(x => x.DMSToDegrees(null), Times.AtLeast(2));
_astroUtilsMock.Verify(x => x.ConditionHA(It.IsAny<double>()), Times.Once);
_astroUtilsMock.Verify(x => x.ConditionRA(It.IsAny<double>()), Times.Once);
}
delegate void NovasSiderealTimeDelegate(double jdHigh, double jdLow, double jdDelta, GstType gstType, Method method, Accuracy accuracy, ref double sideralTime);
/// <summary>
/// Test cases obtained via .NET telescope simulator
/// </summary>
[TestCase(9.4337648353882, -76.7178112042103, "2021-06-07T05:23:41.7610000Z", 8.13556526999591, 145.166333333333, 2d, PierSide.pierWest, PierSide.pierEast)]
[TestCase(10.1581570159006, 11.8639491368916, "2021-06-07T10:59:19.7000000Z", 9.72726050605156, 145.166333333333, 1d, PierSide.pierWest, PierSide.pierEast)]
[TestCase(9.66583199112222, 81.2310578173083, "2021-06-07T11:19:24.5540000Z", 7.73744116673785, 110.285166666667, 2d, PierSide.pierWest, PierSide.pierEast)]
[TestCase(8.32978972808615, -29.816491813155, "2021-06-07T11:29:33.7040000Z", 7.90712206850482, 110.285166666667, 1d, PierSide.pierWest, PierSide.pierEast)]
[TestCase(1.76405553984887, 60.7756226366989, "2021-06-07T11:34:07.5270000Z", 0.214893775091689, -6.24266666666667, 2d, PierSide.pierWest, PierSide.pierEast)]
[TestCase(0.523375885742411, -33.1288722052936, "2021-06-07T11:38:25.1670000Z", 0.286661722506396, -6.24266666666667, 0.5d, PierSide.pierWest, PierSide.pierEast)]
public void SideOfPier_WhenTrackingThroughMeridianAfterSubsequentGoto_ThenAMeridianFlipIsPerformed(
double ra,
double dec,
string jnowTimeStr, /* JNOW of object before transit */
double jnowSiderealTime,
double siteLongitude,
double trackingTimeHours,
PierSide pierSideBeforeTransit,
PierSide pierSideAfterRetargeting
)
{
// given
var jnowTime = DateTimeOffset.ParseExact(jnowTimeStr, "o", CultureInfo.InvariantCulture).UtcDateTime;
var trackingTimeDiff = TimeSpan.FromHours(trackingTimeHours);
var timeAfterTracking = jnowTime + trackingTimeDiff;
var raAsHMS = ra + "HMS";
var decAsDMS = dec + "DMS";
var currentTime = jnowTime;
_clockMock.Setup(x => x.UtcNow).Returns(() => currentTime);
_sharedResourcesWrapperMock.Setup(x => x.SendChar("MS", false)).Returns("0");
// setup for RA
_utilMock.Setup(x => x.HoursToHMS(ra, ":", ":", ":", 2)).Returns(raAsHMS);
_utilMock.Setup(x => x.HMSToHours(raAsHMS)).Returns(ra);
// setup for DEC
_utilMock.Setup(x => x.DMSToDegrees(decAsDMS)).Returns(dec);
_utilMock.Setup(x => x.DegreesToDMS(dec, "*", ":", ":", 2)).Returns(decAsDMS);
// setup for SiteLongitude
var siteLongitudeResult = siteLongitude + "Gg";
_sharedResourcesWrapperMock.Setup(x => x.SendString("Gg", false)).Returns(siteLongitudeResult);
// remember to invert longitude
_utilMock.Setup(x => x.DMSToDegrees(siteLongitudeResult)).Returns(-siteLongitude);
// setup for SideralTime
var siteLongitudeAdj = siteLongitude / 360.0 * 24.0;
var jnowSiderealTimeWithoutLongAdj = jnowSiderealTime - siteLongitudeAdj;
var afterTrackingSiderealTimeWithoutLongAdj = jnowSiderealTimeWithoutLongAdj + trackingTimeHours;
_utilMock.Setup(x => x.DateUTCToJulian(It.IsAny<DateTime>())).Returns<DateTime>(pDateTime => pDateTime.Ticks);
_novasMock
.Setup(x => x.SiderealTime(
It.IsAny<double>(),
0d,
0d,
GstType.GreenwichApparentSiderealTime,
Method.EquinoxBased,
Accuracy.Reduced,
ref It.Ref<double>.IsAny))
.Callback(new NovasSiderealTimeDelegate(NovasSiderealTime))
.Returns(0);
_astroUtilsMock.Setup(x => x.ConditionRA(It.IsAny<double>())).Returns<double>(pRA => pRA < 0 ? pRA + 24 : pRA >= 24 ? pRA - 24 : pRA);
void NovasSiderealTime(double pJDHigh, double pJDLow, double pJDDelta, GstType pGSTType, Method pMethod, Accuracy pAccuracy, ref double pSideralTime)
{
if (pJDHigh == jnowTime.Ticks)
{
pSideralTime = jnowSiderealTimeWithoutLongAdj;
}
else if (pJDHigh == timeAfterTracking.Ticks)
{
pSideralTime = afterTrackingSiderealTimeWithoutLongAdj;
}
else
{
Assert.Fail($"No sideral time defined for {pJDHigh}");
}
}
// Setup DestinationSideOfPier
_astroUtilsMock.Setup(x => x.ConditionHA(It.IsAny<double>())).Returns<double>(pHA => pHA < -12 ? pHA + 12 : pHA > 12 ? pHA - 12 : pHA);
// Use firmware that supports GW
ConnectTelescope(firmwareVersion: TelescopeList.Autostar497_43Eg);
// when
_telescope.SlewToCoordinatesAsync(ra, dec);
var actualSideOfPierAfterSlew = _telescope.SideOfPier;
// simulate tracking time
currentTime += trackingTimeDiff;
var actualSideOfPierAfterTracking = _telescope.SideOfPier;
_telescope.SlewToTargetAsync();
var actualSideOfPierAfterRetargeting = _telescope.SideOfPier;
// then
Assert.That(_telescope.TargetRightAscension, Is.EqualTo(ra));
Assert.That(_telescope.TargetDeclination, Is.EqualTo(dec));
Assert.That(actualSideOfPierAfterSlew, Is.EqualTo(pierSideBeforeTransit));
Assert.That(actualSideOfPierAfterTracking, Is.EqualTo(pierSideBeforeTransit));
Assert.That(actualSideOfPierAfterRetargeting, Is.EqualTo(pierSideAfterRetargeting));
_clockMock.Verify(x => x.UtcNow, Times.AtLeast(2));
foreach (var time in new[] { jnowTime, timeAfterTracking })
{
_utilMock.Verify(x => x.DateUTCToJulian(time));
_novasMock
.Verify(x => x.SiderealTime(
time.Ticks,
0d,
0d,
GstType.GreenwichApparentSiderealTime,
Method.EquinoxBased,
Accuracy.Reduced,
ref It.Ref<double>.IsAny),
Times.Once);
}
_sharedResourcesWrapperMock.Verify(x => x.SendString("Gg", false), Times.Exactly(3));
_sharedResourcesWrapperMock.Verify(x => x.SendChar("MS", false), Times.Exactly(2));
_sharedResourcesWrapperMock.Verify(x => x.SendString("D", false), Times.Exactly(3));
}
[Test] [Test]
public void SiteElevation_Get_WhenNotConnectedThrowsException() public void SiteElevation_Get_WhenNotConnectedThrowsException()
{ {
@@ -2229,6 +2501,46 @@ namespace Meade.net.Telescope.UnitTests
Assert.That(result, Is.EqualTo(declination)); Assert.That(result, Is.EqualTo(declination));
} }
[TestCase(-90d)]
[TestCase(-45d)]
[TestCase(0d)]
[TestCase(45d)]
[TestCase(90d)]
public void TargetDeclination_Set_WhenSecondConnectionMade_ThenValueIsPreserved(double targetDeclination)
{
var targetDeclinationDMS = targetDeclination + "DMS";
var sign = targetDeclination >= 0 ? "+" : string.Empty;
var command = $"Sd{sign}{targetDeclinationDMS}";
_utilMock.Setup(x => x.DegreesToDMS(targetDeclination, "*", ":", ":", 2)).Returns(targetDeclinationDMS);
_utilMock.Setup(x => x.DMSToDegrees(targetDeclinationDMS)).Returns(targetDeclination);
_sharedResourcesWrapperMock.Setup(x => x.SendChar(command, false)).Returns("1");
ConnectTelescope();
Assert.That(_connectionInfo.SameDevice, Is.EqualTo(1));
Assert.That(_sharedResourcesWrapperMock.Object.IsLongFormat, Is.True);
_telescope.TargetDeclination = targetDeclination;
Assert.That(_telescope.TargetDeclination, Is.EqualTo(targetDeclination));
var secondTelescopeInstance =
new ASCOM.Meade.net.Telescope(_utilMock.Object, _utilExtraMock.Object, _astroUtilsMock.Object,
_sharedResourcesWrapperMock.Object, _astroMathsMock.Object, _clockMock.Object, _novasMock.Object);
Assert.That(secondTelescopeInstance.Connected, Is.False);
_connectionInfo.SameDevice = 2;
secondTelescopeInstance.Connected = true;
Assert.That(_sharedResourcesWrapperMock.Object.IsLongFormat, Is.True);
Assert.That(secondTelescopeInstance.TargetDeclination, Is.EqualTo(targetDeclination));
_utilMock.Verify(x => x.DegreesToDMS(targetDeclination, "*", ":", ":", 2), Times.Once);
_utilMock.Verify(x => x.DMSToDegrees(targetDeclinationDMS), Times.Once);
_sharedResourcesWrapperMock.Verify(x => x.SendChar(command, false), Times.Once);
}
[Test] [Test]
public void TargetRightAscension_Set_WhenNotConnected_ThenThrowsException() public void TargetRightAscension_Set_WhenNotConnected_ThenThrowsException()
{ {
@@ -2311,6 +2623,44 @@ namespace Meade.net.Telescope.UnitTests
Assert.That(result, Is.EqualTo(rightAscension)); Assert.That(result, Is.EqualTo(rightAscension));
} }
[TestCase(0d)]
[TestCase(6d)]
[TestCase(12d)]
[TestCase(23.599d)]
public void TargetRightAscension_Set_WhenSecondConnectionMade_ThenValueIsPreserved(double targetRightAscension)
{
var targetRightAscensionHMS = targetRightAscension + "HMS";
var command = $"Sr{targetRightAscensionHMS}";
_utilMock.Setup(x => x.HoursToHMS(targetRightAscension, ":", ":", ":", 2)).Returns(targetRightAscensionHMS);
_utilMock.Setup(x => x.HMSToHours(targetRightAscensionHMS)).Returns(targetRightAscension);
_sharedResourcesWrapperMock.Setup(x => x.SendChar(command, false)).Returns("1");
ConnectTelescope();
Assert.That(_connectionInfo.SameDevice, Is.EqualTo(1));
Assert.That(_sharedResourcesWrapperMock.Object.IsLongFormat, Is.True);
_telescope.TargetRightAscension = targetRightAscension;
Assert.That(_telescope.TargetRightAscension, Is.EqualTo(targetRightAscension));
var secondTelescopeInstance =
new ASCOM.Meade.net.Telescope(_utilMock.Object, _utilExtraMock.Object, _astroUtilsMock.Object,
_sharedResourcesWrapperMock.Object, _astroMathsMock.Object, _clockMock.Object, _novasMock.Object);
Assert.That(secondTelescopeInstance.Connected, Is.False);
_connectionInfo.SameDevice = 2;
secondTelescopeInstance.Connected = true;
Assert.That(_sharedResourcesWrapperMock.Object.IsLongFormat, Is.True);
Assert.That(secondTelescopeInstance.TargetRightAscension, Is.EqualTo(targetRightAscension));
_utilMock.Verify(x => x.HoursToHMS(targetRightAscension, ":", ":", ":", 2), Times.Once);
_utilMock.Verify(x => x.HMSToHours(targetRightAscensionHMS), Times.Once);
_sharedResourcesWrapperMock.Verify(x => x.SendChar(command, false), Times.Once);
}
[Test] [Test]
public void Tracking_Get_WhenDefault_ThenIsTrue() public void Tracking_Get_WhenDefault_ThenIsTrue()
{ {
@@ -2319,11 +2669,26 @@ namespace Meade.net.Telescope.UnitTests
[TestCase(true)] [TestCase(true)]
[TestCase(false)] [TestCase(false)]
public void Tracking_SetAndGet_WhenValueSet_ThenCanGetNewValue(bool tracking) public void Tracking_Set_WhenCanSetTrackingIsFalse_ThenThrowsNotImplementedException(bool tracking)
{ {
// GW is not supported, so CanSetTracking is false
ConnectTelescope(firmwareVersion: TelescopeList.Autostar497_30Ee);
Assert.Throws<ASCOM.NotImplementedException>( () => { _telescope.Tracking = tracking; } );
}
[TestCase(true, "AP")]
[TestCase(false, "AL")]
public void Tracking_Set_WhenCanSetTrackingIsTrue_ThenValueIsUpdated(bool tracking, string alignmentCommand)
{
// GW is supported, so CanSetTracking is true
ConnectTelescope(firmwareVersion: TelescopeList.Autostar497_43Eg);
_telescope.Tracking = tracking; _telescope.Tracking = tracking;
Assert.That(_telescope.Tracking, Is.EqualTo(tracking)); Assert.That(_telescope.Tracking, Is.EqualTo(tracking));
_sharedResourcesWrapperMock.Verify(x => x.SendBlind(alignmentCommand, false), Times.Once);
} }
[Test] [Test]
@@ -2341,7 +2706,10 @@ namespace Meade.net.Telescope.UnitTests
_telescope.TrackingRate = rate; _telescope.TrackingRate = rate;
Assert.That(_telescope.TrackingRate, Is.EqualTo(rate));
_sharedResourcesWrapperMock.Verify(x => x.SendBlind(commandString, false), Times.Once); _sharedResourcesWrapperMock.Verify(x => x.SendBlind(commandString, false), Times.Once);
_sharedResourcesWrapperMock.Verify(x => x.SendString("GT", false), Times.Once);
} }
[Test] [Test]
@@ -2595,6 +2963,7 @@ namespace Meade.net.Telescope.UnitTests
[TestCase(15, 10, "2021-10-03T20:36:00", "2021-10-03T20:36:25", false)] [TestCase(15, 10, "2021-10-03T20:36:00", "2021-10-03T20:36:25", false)]
public void Slewing_WhenTelescopeIsSlewing_ThenReturnsExpectedValueForSettleTime(short settleTime, short profileSettleTime, string startSlewing, string endSlewing, bool isSlewing) public void Slewing_WhenTelescopeIsSlewing_ThenReturnsExpectedValueForSettleTime(short settleTime, short profileSettleTime, string startSlewing, string endSlewing, bool isSlewing)
{ {
_sharedResourcesWrapperMock.SetupProperty(x => x.EarliestNonSlewingTime, DateTime.MinValue);
_profileProperties.SettleTime = profileSettleTime; _profileProperties.SettleTime = profileSettleTime;
var timescalled = 0; var timescalled = 0;
@@ -2644,7 +3013,7 @@ namespace Meade.net.Telescope.UnitTests
[TestCase(TelescopeList.LX200CLASSIC, "", "[FF][FF][FF][FF][FF][FF][FF][FF][FF][FF][FF][FF][FF][FF] [FF][FF][FF][FF][FF][FF]", false)] //The test case below is this same string encoded to return exactly what the telescope will return. [TestCase(TelescopeList.LX200CLASSIC, "", "[FF][FF][FF][FF][FF][FF][FF][FF][FF][FF][FF][FF][FF][FF] [FF][FF][FF][FF][FF][FF]", false)] //The test case below is this same string encoded to return exactly what the telescope will return.
[TestCase(TelescopeList.LX200CLASSIC, "", "\x00ff\x00ff\x00ff\x00ff\x00ff\x00ff\x00ff\x00ff\x00ff\x00ff\x00ff\x00ff\x00ff\x00ff \x00ff\x00ff\x00ff\x00ff\x00ff\x00ff", false)] [TestCase(TelescopeList.LX200CLASSIC, "", "\x00ff\x00ff\x00ff\x00ff\x00ff\x00ff\x00ff\x00ff\x00ff\x00ff\x00ff\x00ff\x00ff\x00ff \x00ff\x00ff\x00ff\x00ff\x00ff\x00ff", false)]
[TestCase(TelescopeList.Autostar497, TelescopeList.Autostar497_43Eg, "|", true)] [TestCase(TelescopeList.Autostar497, TelescopeList.Autostar497_43Eg, "|", true)]
[TestCase(TelescopeList.Autostar497, TelescopeList.Autostar497_43Eg, "\u007f", true)] [TestCase(TelescopeList.Autostar497, TelescopeList.Autostar497_43Eg, "\x007f", true)]
[TestCase(TelescopeList.Autostar497, TelescopeList.Autostar497_43Eg, "", false)] [TestCase(TelescopeList.Autostar497, TelescopeList.Autostar497_43Eg, "", false)]
public void Slewing_WhenTelescopeNotSlewing_ThenReturnsFalse(string productName, string firmwareVersion, string response, bool isSlewing) public void Slewing_WhenTelescopeNotSlewing_ThenReturnsFalse(string productName, string firmwareVersion, string response, bool isSlewing)
{ {
@@ -2665,6 +3034,10 @@ namespace Meade.net.Telescope.UnitTests
[TestCase(-1, TelescopeAxes.axisSecondary)] [TestCase(-1, TelescopeAxes.axisSecondary)]
public void Slewing_WhenTelescopeIsMoving_ThenDoesNotSendCommandAndReturnsTrue(int rate, TelescopeAxes axis) public void Slewing_WhenTelescopeIsMoving_ThenDoesNotSendCommandAndReturnsTrue(int rate, TelescopeAxes axis)
{ {
_sharedResourcesWrapperMock.SetupProperty(x => x.MovingPrimary);
_sharedResourcesWrapperMock.SetupProperty(x => x.MovingSecondary);
_sharedResourcesWrapperMock.SetupProperty(x => x.EarliestNonSlewingTime, DateTime.MinValue);
ConnectTelescope(); ConnectTelescope();
_telescope.MoveAxis(axis, rate); _telescope.MoveAxis(axis, rate);
@@ -2672,6 +3045,9 @@ namespace Meade.net.Telescope.UnitTests
var result = _telescope.Slewing; var result = _telescope.Slewing;
Assert.That(result, Is.True); Assert.That(result, Is.True);
Assert.That(_sharedResourcesWrapperMock.Object.MovingPrimary, Is.EqualTo(axis == TelescopeAxes.axisPrimary));
Assert.That(_sharedResourcesWrapperMock.Object.MovingSecondary, Is.EqualTo(axis == TelescopeAxes.axisSecondary));
_sharedResourcesWrapperMock.Verify(x => x.SendString("D", false), Times.Never); _sharedResourcesWrapperMock.Verify(x => x.SendString("D", false), Times.Never);
} }
@@ -2691,6 +3067,11 @@ namespace Meade.net.Telescope.UnitTests
[TestCase(-1, TelescopeAxes.axisSecondary, 10, 20, true, true)] [TestCase(-1, TelescopeAxes.axisSecondary, 10, 20, true, true)]
public void Slewing_WhenTelescopeStops_ThenWaitsForSettleTime(int rate, TelescopeAxes axis, short profileSettleTime, short driverSettleTime, bool expectedResultInWaitingPeriod, bool afterProfileSettleTimeUp) public void Slewing_WhenTelescopeStops_ThenWaitsForSettleTime(int rate, TelescopeAxes axis, short profileSettleTime, short driverSettleTime, bool expectedResultInWaitingPeriod, bool afterProfileSettleTimeUp)
{ {
_sharedResourcesWrapperMock.SetupProperty(x => x.MovingPrimary);
_sharedResourcesWrapperMock.SetupProperty(x => x.MovingSecondary);
_sharedResourcesWrapperMock.SetupProperty(x => x.SlewSettleTime);
_sharedResourcesWrapperMock.SetupProperty(x => x.EarliestNonSlewingTime, DateTime.MinValue);
_profileProperties.SettleTime = profileSettleTime; _profileProperties.SettleTime = profileSettleTime;
DateTime currentTime = MakeTime("2021-01-23T22:02:10"); DateTime currentTime = MakeTime("2021-01-23T22:02:10");
@@ -2708,17 +3089,17 @@ namespace Meade.net.Telescope.UnitTests
_telescope.MoveAxis(axis, 0); _telescope.MoveAxis(axis, 0);
currentTime = currentTime + TimeSpan.FromSeconds(profileSettleTime / 2); currentTime += TimeSpan.FromSeconds(profileSettleTime / 2);
result = _telescope.Slewing; result = _telescope.Slewing;
Assert.That(result, Is.EqualTo(expectedResultInWaitingPeriod)); Assert.That(result, Is.EqualTo(expectedResultInWaitingPeriod));
currentTime = currentTime + TimeSpan.FromSeconds(profileSettleTime / 2); currentTime += TimeSpan.FromSeconds(profileSettleTime / 2);
result = _telescope.Slewing; result = _telescope.Slewing;
Assert.That(result, Is.EqualTo(afterProfileSettleTimeUp)); Assert.That(result, Is.EqualTo(afterProfileSettleTimeUp));
currentTime = currentTime + TimeSpan.FromSeconds(driverSettleTime); currentTime += TimeSpan.FromSeconds(driverSettleTime);
result = _telescope.Slewing; result = _telescope.Slewing;
Assert.That(result, Is.False); Assert.That(result, Is.False);
@@ -2842,9 +3223,6 @@ namespace Meade.net.Telescope.UnitTests
[Test] [Test]
public void SlewToTarget_WhenSlewing_ThenWaitsForTheSlewToComplete() public void SlewToTarget_WhenSlewing_ThenWaitsForTheSlewToComplete()
{ {
// avoid calling SideOfPier because it will call Slewing
_astroUtilsMock.Setup(x => x.ConditionHA(It.IsAny<double>())).Returns(+1);
_sharedResourcesWrapperMock.Setup(x => x.SendChar("MS", false)).Returns("0"); _sharedResourcesWrapperMock.Setup(x => x.SendChar("MS", false)).Returns("0");
var slewCounter = 0; var slewCounter = 0;
@@ -2865,7 +3243,6 @@ namespace Meade.net.Telescope.UnitTests
_telescope.SlewToTarget(); _telescope.SlewToTarget();
_utilMock.Verify(x => x.WaitForMilliseconds(It.IsAny<int>()), Times.Exactly(iterations)); _utilMock.Verify(x => x.WaitForMilliseconds(It.IsAny<int>()), Times.Exactly(iterations));
_astroUtilsMock.Verify(x => x.ConditionHA(It.IsAny<double>()), Times.Once);
} }
[Test] [Test]
@@ -2926,9 +3303,6 @@ namespace Meade.net.Telescope.UnitTests
[Test] [Test]
public void SlewToCoordinates_WhenCalled_ThenSetsTargetAndSlews() public void SlewToCoordinates_WhenCalled_ThenSetsTargetAndSlews()
{ {
// avoid calling SideOfPier because it will call Slewing
_astroUtilsMock.Setup(x => x.ConditionHA(It.IsAny<double>())).Returns(+1);
_testProperties.rightAscension = 1; _testProperties.rightAscension = 1;
var declination = 2; var declination = 2;
@@ -2963,7 +3337,6 @@ namespace Meade.net.Telescope.UnitTests
_sharedResourcesWrapperMock.Verify(x => x.SendChar("MS", false), Times.Once); _sharedResourcesWrapperMock.Verify(x => x.SendChar("MS", false), Times.Once);
_utilMock.Verify(x => x.WaitForMilliseconds(It.IsAny<int>()), Times.Exactly(iterations)); _utilMock.Verify(x => x.WaitForMilliseconds(It.IsAny<int>()), Times.Exactly(iterations));
_astroUtilsMock.Verify(x => x.ConditionHA(It.IsAny<double>()), Times.Once);
} }
[Test] [Test]
@@ -3052,9 +3425,6 @@ namespace Meade.net.Telescope.UnitTests
[Test] [Test]
public void SlewToAltAz_WhenCalled_ThenSetsTargetAndSlews() public void SlewToAltAz_WhenCalled_ThenSetsTargetAndSlews()
{ {
// avoid calling SideOfPier because it will call Slewing
_astroUtilsMock.Setup(x => x.ConditionHA(It.IsAny<double>())).Returns(+1);
_testProperties.rightAscension = 10.0; _testProperties.rightAscension = 10.0;
_testProperties.declination = 20; _testProperties.declination = 20;
var azimuth = 30; var azimuth = 30;
@@ -3087,7 +3457,6 @@ namespace Meade.net.Telescope.UnitTests
Assert.That(_telescope.TargetDeclination, Is.EqualTo(_testProperties.declination)); Assert.That(_telescope.TargetDeclination, Is.EqualTo(_testProperties.declination));
_sharedResourcesWrapperMock.Verify(x => x.SendChar("MS", false), Times.Once); _sharedResourcesWrapperMock.Verify(x => x.SendChar("MS", false), Times.Once);
_utilMock.Verify(x => x.WaitForMilliseconds(It.IsAny<int>()), Times.Exactly(iterations)); _utilMock.Verify(x => x.WaitForMilliseconds(It.IsAny<int>()), Times.Exactly(iterations));
_astroUtilsMock.Verify(x => x.ConditionHA(It.IsAny<double>()), Times.Once);
} }
[Test] [Test]
+12
View File
@@ -0,0 +1,12 @@
namespace ASCOM.Meade.net
{
public enum Alignment
{
NeedsAlignment,
OneStarAligned,
TwoStarAligned,
ThreeStarAligned,
AlignedOnHome,
ScopeWasParked,
}
}
+11
View File
@@ -0,0 +1,11 @@
using ASCOM.DeviceInterface;
namespace ASCOM.Meade.net
{
public class AlignmentStatus
{
public AlignmentModes AlignmentMode { get; set; }
public bool Tracking { get; set; }
public Alignment Status { get; set; }
}
}
@@ -62,7 +62,7 @@
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x86'"> <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x86'">
<OutputPath>..\bin\Release\</OutputPath> <OutputPath>..\bin\Release\</OutputPath>
<Prefer32Bit>false</Prefer32Bit> <Prefer32Bit>true</Prefer32Bit>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x86'"> <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x86'">
<OutputPath>..\bin\Debug\</OutputPath> <OutputPath>..\bin\Debug\</OutputPath>
@@ -118,6 +118,8 @@
<Reference Include="System.Xml" /> <Reference Include="System.Xml" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Compile Include="Alignment.cs" />
<Compile Include="AlignmentStatus.cs" />
<Compile Include="AstroMaths\AltitudeData.cs" /> <Compile Include="AstroMaths\AltitudeData.cs" />
<Compile Include="AstroMaths\AstroMathExtensions.cs" /> <Compile Include="AstroMaths\AstroMathExtensions.cs" />
<Compile Include="AstroMaths\AstroMaths.cs" /> <Compile Include="AstroMaths\AstroMaths.cs" />
File diff suppressed because it is too large Load Diff
@@ -98,6 +98,10 @@
<ItemGroup> <ItemGroup>
<Compile Include="SharedResourcesUnitTests.cs" /> <Compile Include="SharedResourcesUnitTests.cs" />
<Compile Include="Properties\AssemblyInfo.cs" /> <Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="ThreadSafeBoolTests.cs" />
<Compile Include="ThreadSafeDateTimeTests.cs" />
<Compile Include="ThreadSafeEnumTests.cs" />
<Compile Include="ThreadSafeNullableDoubleTests.cs" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\Meade.net\Meade.net.csproj"> <ProjectReference Include="..\Meade.net\Meade.net.csproj">
@@ -1,6 +1,7 @@
using System; using System;
using System.Globalization; using System.Globalization;
using ASCOM.DeviceInterface;
using ASCOM.Meade.net; using ASCOM.Meade.net;
using ASCOM.Meade.net.Wrapper; using ASCOM.Meade.net.Wrapper;
using ASCOM.Utilities.Interfaces; using ASCOM.Utilities.Interfaces;
@@ -29,7 +30,7 @@ namespace Meade.net.UnitTests
[Test] [Test]
public void CheckThatSerialPortIsSetToUseMock() public void CheckThatSerialPortIsSetToUseMock()
{ {
Assert.That(SharedResources.SharedSerial,Is.EqualTo(_serialMock.Object)); Assert.That(SharedResources.SharedSerial, Is.EqualTo(_serialMock.Object));
} }
[TestCase(true, "Test")] [TestCase(true, "Test")]
@@ -618,5 +619,41 @@ namespace Meade.net.UnitTests
_traceLoggerMock.Verify( x => x.LogIssue("Connect", "Unable to decode response from the telescope, This is likely a hardware serial communications error."), Times.Once); _traceLoggerMock.Verify( x => x.LogIssue("Connect", "Unable to decode response from the telescope, This is likely a hardware serial communications error."), Times.Once);
} }
[Test]
public void CheckIsParkedIsFalseByDefault() => Assert.That(SharedResources.IsParked, Is.False);
[Test]
public void CheckParkedPositionIsNullByDefault() => Assert.That(SharedResources.ParkedPosition, Is.Null);
[Test]
public void CheckIsLongFormatIsFalseByDefault() => Assert.That(SharedResources.IsLongFormat, Is.False);
[Test]
public void CheckMovingPrimaryIsFalseBydefault() => Assert.That(SharedResources.MovingPrimary, Is.False);
[Test]
public void CheckMovingSecondaryIsFalseBydefault() => Assert.That(SharedResources.MovingSecondary, Is.False);
[Test]
public void CheckSideOfPierIsUnknownByDefault() => Assert.That(SharedResources.SideOfPier, Is.EqualTo(PierSide.pierUnknown));
[Test]
public void CheckSlewSettleTimeIsZeroByDefault() => Assert.That(SharedResources.SlewSettleTime, Is.EqualTo((short)0));
[Test]
public void CheckEarliestNonNonSlewingTimeIsMinValueByDefault() => Assert.That(SharedResources.EarliestNonSlewingTime, Is.EqualTo(DateTime.MinValue));
[Test]
public void CheckTargetDeclinationIsNullByDefault() => Assert.That(SharedResources.TargetDeclination.HasValue, Is.False);
[Test]
public void CheckTargetRightAscensionIsNullByDefault() => Assert.That(SharedResources.TargetRightAscension.HasValue, Is.False);
[Test]
public void CheckIsTargetCoordinateInitRequired() => Assert.That(SharedResources.IsTargetCoordinateInitRequired, Is.True);
[Test]
public void CheckIsGuiding() => Assert.That(SharedResources.IsGuiding, Is.False);
} }
} }
@@ -0,0 +1,39 @@
using ASCOM.Meade.net;
using NUnit.Framework;
namespace Meade.net.UnitTests
{
public class ThreadSafeBoolTests
{
[TestCase(false)]
[TestCase(true)]
public void When_Assigned_ThenValueIsSame(bool value)
{
// given
ThreadSafeValue<bool> sut = value;
// when
bool actual = sut;
// then
Assert.That(actual, Is.EqualTo(value));
}
[TestCase(false, false)]
[TestCase(false, true)]
[TestCase(true, false)]
[TestCase(true, true)]
public void When_SetValue_ThenValueIsUpdated(bool initialValue, bool setValue)
{
// given
ThreadSafeValue<bool> sut = initialValue;
// when
sut.Set(setValue);
bool afterset = sut;
// then
Assert.That(afterset, Is.EqualTo(setValue));
}
}
}
@@ -0,0 +1,61 @@
using ASCOM.Meade.net;
using NUnit.Framework;
using System;
using System.Collections.Generic;
using System.Globalization;
namespace Meade.net.UnitTests
{
public class ThreadSafeDateTimeTests
{
[TestCaseSource(nameof(DateTimeSource))]
public void When_Assigned_ThenValueIsSame(DateTime value)
{
// given
ThreadSafeValue<DateTime> sut = value;
// when
DateTime actual = sut;
// then
Assert.That(actual, Is.EqualTo(value));
}
[TestCaseSource(nameof(DateTimeSetSource))]
public void When_SetValue_ThenValueIsUpdated(DateTime initialValue, DateTime setValue)
{
// given
ThreadSafeValue<DateTime> sut = initialValue;
// when
sut.Set(setValue);
DateTime afterset = sut;
// then
Assert.That(afterset, Is.EqualTo(setValue));
}
static readonly DateTime Example1 = DateTimeOffset.Parse("2012-05-09T02:10:31.296761Z", CultureInfo.InvariantCulture).UtcDateTime;
static readonly DateTime Example2 = DateTimeOffset.Parse("2051-03-09T23:15:11.556081Z", CultureInfo.InvariantCulture).UtcDateTime;
static IEnumerable<DateTime> DateTimeSource => new[]
{
DateTime.MinValue,
Example1,
Example2
};
static IEnumerable<TestCaseData> DateTimeSetSource => new[]
{
new TestCaseData(DateTime.MinValue, Example1),
new TestCaseData(DateTime.MinValue, Example2),
new TestCaseData(DateTime.MinValue, DateTime.MinValue),
new TestCaseData(Example1, Example1),
new TestCaseData(Example1, Example2),
new TestCaseData(Example1, DateTime.MinValue),
new TestCaseData(Example2, Example1),
new TestCaseData(Example2, Example2),
new TestCaseData(Example2, DateTime.MinValue)
};
}
}
@@ -0,0 +1,46 @@
using ASCOM.DeviceInterface;
using ASCOM.Meade.net;
using NUnit.Framework;
namespace Meade.net.UnitTests
{
public class ThreadSafeEnumTests
{
[TestCase(PierSide.pierUnknown)]
[TestCase(PierSide.pierEast)]
[TestCase(PierSide.pierWest)]
public void When_Assigned_ThenValueIsSame(PierSide value)
{
// given
ThreadSafeValue<PierSide> sut = value;
// when
PierSide actual = sut;
// then
Assert.That(actual, Is.EqualTo(value));
}
[TestCase(PierSide.pierUnknown, PierSide.pierUnknown)]
[TestCase(PierSide.pierUnknown, PierSide.pierEast)]
[TestCase(PierSide.pierUnknown, PierSide.pierWest)]
[TestCase(PierSide.pierEast, PierSide.pierUnknown)]
[TestCase(PierSide.pierEast, PierSide.pierEast)]
[TestCase(PierSide.pierEast, PierSide.pierWest)]
[TestCase(PierSide.pierWest, PierSide.pierUnknown)]
[TestCase(PierSide.pierWest, PierSide.pierEast)]
[TestCase(PierSide.pierWest, PierSide.pierWest)]
public void When_SetValue_ThenValueIsUpdated(PierSide initialValue, PierSide setValue)
{
// given
ThreadSafeValue<PierSide> sut = initialValue;
// when
sut.Set(setValue);
PierSide afterset = sut;
// then
Assert.That(afterset, Is.EqualTo(setValue));
}
}
}
@@ -0,0 +1,45 @@
using ASCOM.Meade.net;
using NUnit.Framework;
namespace Meade.net.UnitTests
{
public class ThreadSafeNullableDoubleTests
{
[TestCase(0.1d)]
[TestCase(-12.34d)]
[TestCase(0d)]
[TestCase(null)]
public void When_Assigned_ThenValueIsSame(double? value)
{
// given
ThreadSafeValue<double?> sut = value;
// when
double? actual = sut;
// then
Assert.That(actual, Is.EqualTo(value));
}
[TestCase(0.1d, 0.2d)]
[TestCase(-12.34d, 5d)]
[TestCase(0d, 1d)]
[TestCase(null, 2d)]
[TestCase(0.1d, null)]
[TestCase(-12.34d, null)]
[TestCase(0d, null)]
[TestCase(null, null)]
public void When_SetValue_ThenValueIsUpdated(double? initialValue, double? setValue)
{
// given
ThreadSafeValue<double?> sut = initialValue;
// when
sut.Set(setValue);
double? afterset = sut;
// then
Assert.That(afterset, Is.EqualTo(setValue));
}
}
}
+1
View File
@@ -5,6 +5,7 @@
<package id="JetBrains.Annotations" version="2020.3.0" targetFramework="net472" /> <package id="JetBrains.Annotations" version="2020.3.0" targetFramework="net472" />
<package id="Moq" version="4.15.2" targetFramework="net472" /> <package id="Moq" version="4.15.2" targetFramework="net472" />
<package id="NUnit" version="3.13.0" targetFramework="net472" /> <package id="NUnit" version="3.13.0" targetFramework="net472" />
<package id="NUnit.ConsoleRunner" version="3.12.0" targetFramework="net472" />
<package id="System.Runtime.CompilerServices.Unsafe" version="5.0.0" targetFramework="net472" /> <package id="System.Runtime.CompilerServices.Unsafe" version="5.0.0" targetFramework="net472" />
<package id="System.Threading.Tasks.Extensions" version="4.5.4" targetFramework="net472" /> <package id="System.Threading.Tasks.Extensions" version="4.5.4" targetFramework="net472" />
</packages> </packages>
+2 -2
View File
@@ -343,9 +343,9 @@ namespace ASCOM.Meade.net
//:FS# Set Focus speed to slowest setting //:FS# Set Focus speed to slowest setting
//Returns: Nothing //Returns: Nothing
//:F<n># Autostar, Autostar II set focuser speed to <n> where <n> is an ASCII digit 1..4 //:F<n># Autostar, Autostar II - set focuser speed to <n> where <n> is an ASCII digit 1..4
//Returns: Nothing //Returns: Nothing
//All others Not Supported //All others - Not Supported
_utilities.WaitForMilliseconds(100); _utilities.WaitForMilliseconds(100);
PerformFocuserMove(directionOut); PerformFocuserMove(directionOut);
+1
View File
@@ -146,6 +146,7 @@
<Compile Include="ProfileProperties.cs" /> <Compile Include="ProfileProperties.cs" />
<Compile Include="Properties\AssemblyInfo.cs" /> <Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="TelescopeList.cs" /> <Compile Include="TelescopeList.cs" />
<Compile Include="ThreadSafeValue.cs" />
<Compile Include="Win32Utilities.cs" /> <Compile Include="Win32Utilities.cs" />
<Compile Include="Wrapper\IProfileWrapper.cs" /> <Compile Include="Wrapper\IProfileWrapper.cs" />
<Compile Include="Wrapper\SharedResourcesWrapper.cs" /> <Compile Include="Wrapper\SharedResourcesWrapper.cs" />
+2
View File
@@ -6,5 +6,7 @@ namespace ASCOM.Meade.net
public double Azimuth { get; set; } public double Azimuth { get; set; }
public double RightAscension { get; set; } public double RightAscension { get; set; }
public double Declination { get; set; } public double Declination { get; set; }
public double SiteLongitude { get; set; }
public double SiteLatitude { get; set; }
} }
} }
+99 -12
View File
@@ -19,7 +19,9 @@ using System.Collections.Generic;
using System.Globalization; using System.Globalization;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using System.Security.AccessControl; using System.Security.AccessControl;
using System.Threading;
using System.Windows.Forms; using System.Windows.Forms;
using ASCOM.DeviceInterface;
using ASCOM.Meade.net.Wrapper; using ASCOM.Meade.net.Wrapper;
using ASCOM.Utilities; using ASCOM.Utilities;
using ASCOM.Utilities.Interfaces; using ASCOM.Utilities.Interfaces;
@@ -73,7 +75,7 @@ namespace ASCOM.Meade.net
public static IProfileFactory ProfileFactory public static IProfileFactory ProfileFactory
{ {
get => _profileFactory ?? ( _profileFactory = new ProfileFactory()); get => _profileFactory ?? (_profileFactory = new ProfileFactory());
set => _profileFactory = value; set => _profileFactory = value;
} }
@@ -122,13 +124,17 @@ namespace ASCOM.Meade.net
public static bool SendBool(string command, bool raw = false) public static bool SendBool(string command, bool raw = false)
{ {
var result = SendChar(command, raw); var result = SendChar(command, raw);
return result == "1"; return result == "1";
} }
public static string SendChar(string command, bool raw = false) public static string SendChar(string command, bool raw = false)
{
return SendChars(command, raw, count: 1);
}
public static string SendChars(string command, bool raw = false, int count = 1)
{ {
lock (LockObject) lock (LockObject)
{ {
@@ -139,14 +145,11 @@ namespace ASCOM.Meade.net
try try
{ {
return SharedSerial.ReceiveCounted(1); return SharedSerial.ReceiveCounted(count);
} }
catch (COMException ex) catch (COMException ex) when (ex.Message.Contains("Timed out waiting for received data"))
{ {
if (ex.Message.Contains("Timed out waiting for received data"))
throw new TimeoutException(ex.Message, ex); throw new TimeoutException(ex.Message, ex);
throw;
} }
} }
} }
@@ -244,7 +247,7 @@ namespace ASCOM.Meade.net
private const string HandShakeDefault = "None"; private const string HandShakeDefault = "None";
private const string ParityDefault = "None"; private const string ParityDefault = "None";
private const string SendDateTimeDefault = "false"; private const string SendDateTimeDefault = "false";
private static string ParkedBehaviourDefault = "No Coordinates"; private const string ParkedBehaviourDefault = "No Coordinates";
private const string ParkedAltDefault = "0"; private const string ParkedAltDefault = "0";
private const string ParkedAzimuthDefault = "180"; private const string ParkedAzimuthDefault = "180";
@@ -334,7 +337,7 @@ namespace ASCOM.Meade.net
private static readonly Dictionary<string, DeviceHardware> ConnectedDevices = new Dictionary<string, DeviceHardware>(); private static readonly Dictionary<string, DeviceHardware> ConnectedDevices = new Dictionary<string, DeviceHardware>();
private static readonly Dictionary<string, DeviceHardware> ConnectedDeviceIds = new Dictionary<string, DeviceHardware>(); private static readonly Dictionary<string, DeviceHardware> ConnectedDeviceIds = new Dictionary<string, DeviceHardware>();
private static IProfileFactory _profileFactory ; private static IProfileFactory _profileFactory;
/// <summary> /// <summary>
@@ -363,7 +366,7 @@ namespace ASCOM.Meade.net
SharedSerial.DTREnable = profileProperties.RtsDtrEnabled; SharedSerial.DTREnable = profileProperties.RtsDtrEnabled;
SharedSerial.RTSEnable = profileProperties.RtsDtrEnabled; SharedSerial.RTSEnable = profileProperties.RtsDtrEnabled;
SharedSerial.DataBits = profileProperties.DataBits; SharedSerial.DataBits = profileProperties.DataBits;
SharedSerial.StopBits = (SerialStopBits)Enum.Parse(typeof(SerialStopBits), profileProperties.StopBits ); SharedSerial.StopBits = (SerialStopBits)Enum.Parse(typeof(SerialStopBits), profileProperties.StopBits);
SharedSerial.Parity = (SerialParity)Enum.Parse(typeof(SerialParity), profileProperties.Parity); SharedSerial.Parity = (SerialParity)Enum.Parse(typeof(SerialParity), profileProperties.Parity);
SharedSerial.Speed = (SerialSpeed)profileProperties.Speed; SharedSerial.Speed = (SerialSpeed)profileProperties.Speed;
SharedSerial.Handshake = (SerialHandshake)Enum.Parse(typeof(SerialHandshake), profileProperties.Handshake); SharedSerial.Handshake = (SerialHandshake)Enum.Parse(typeof(SerialHandshake), profileProperties.Handshake);
@@ -500,8 +503,92 @@ namespace ASCOM.Meade.net
ParkedPosition = parkedPosition; ParkedPosition = parkedPosition;
} }
public static bool IsParked { get; private set; } private static readonly ThreadSafeValue<bool> _isParked = false;
public static bool IsParked
{
get => _isParked;
private set => _isParked.Set(value);
}
public static ParkedPosition ParkedPosition { get; private set; } private static ParkedPosition _parkedPosition;
public static ParkedPosition ParkedPosition
{
get => _parkedPosition;
private set => Interlocked.Exchange(ref _parkedPosition, value);
}
private static readonly ThreadSafeValue<PierSide> _sideOfPier = PierSide.pierUnknown;
/// <summary>
/// Start with <see cref="PierSide.pierUnknown"/>.
/// As we do not know the physical declination axis position, we have to keep track manually.
/// </summary>
public static PierSide SideOfPier
{
get => _sideOfPier;
internal set => _sideOfPier.Set(value);
}
private static readonly ThreadSafeValue<double?> _targetRightAscension = null as double?;
public static double? TargetRightAscension
{
get => _targetRightAscension;
internal set => _targetRightAscension.Set(value);
}
private static readonly ThreadSafeValue<double?> _targetDeclination = null as double?;
public static double? TargetDeclination
{
get => _targetDeclination;
internal set => _targetDeclination.Set(value);
}
private static int _slewSettleTime;
public static short SlewSettleTime
{
get => Convert.ToInt16(_slewSettleTime);
internal set => Interlocked.Exchange(ref _slewSettleTime, value);
}
private static readonly ThreadSafeValue<bool> _isLongFormat = false;
public static bool IsLongFormat
{
get => _isLongFormat;
internal set => _isLongFormat.Set(value);
}
private static readonly ThreadSafeValue<bool> _movingPrimary = false;
public static bool MovingPrimary
{
get => _movingPrimary;
internal set => _movingPrimary.Set(value);
}
private static readonly ThreadSafeValue<bool> _movingSecondary = false;
public static bool MovingSecondary
{
get => _movingSecondary;
internal set => _movingSecondary.Set(value);
}
private static readonly ThreadSafeValue<DateTime> _earliestNonSlewingTime = DateTime.MinValue;
public static DateTime EarliestNonSlewingTime
{
get => _earliestNonSlewingTime;
internal set => _earliestNonSlewingTime.Set(value);
}
private static readonly ThreadSafeValue<bool> _isTargetCoordinateInitRequired = true;
public static bool IsTargetCoordinateInitRequired
{
get => _isTargetCoordinateInitRequired;
internal set => _isTargetCoordinateInitRequired.Set(value);
}
private static readonly ThreadSafeValue<bool> _isGuiding = false;
public static bool IsGuiding
{
get => _isGuiding;
internal set => _isGuiding.Set(value);
}
} }
} }
+18
View File
@@ -0,0 +1,18 @@
using JetBrains.Annotations;
using System.Threading;
namespace ASCOM.Meade.net
{
public class ThreadSafeValue<T>
{
private object _value;
public ThreadSafeValue(in T value) => _value = value;
public void Set(in T value) => Interlocked.Exchange(ref _value, value);
public static implicit operator ThreadSafeValue<T>(in T value) => new ThreadSafeValue<T>(value);
public static implicit operator T([NotNull] ThreadSafeValue<T> @this) => (T)(@this?._value ?? default);
}
}
+86 -1
View File
@@ -1,4 +1,5 @@
using System; using System;
using ASCOM.DeviceInterface;
using ASCOM.Utilities.Interfaces; using ASCOM.Utilities.Interfaces;
namespace ASCOM.Meade.net.Wrapper namespace ASCOM.Meade.net.Wrapper
@@ -19,6 +20,7 @@ namespace ASCOM.Meade.net.Wrapper
void SendBlind(string message, bool raw = false); void SendBlind(string message, bool raw = false);
bool SendBool(string command, bool raw = false); bool SendBool(string command, bool raw = false);
string SendChar(string message, bool raw = false); string SendChar(string message, bool raw = false);
string SendChars(string message, bool raw = false, int count = 1);
string ReadTerminated(); string ReadTerminated();
@@ -31,6 +33,24 @@ namespace ASCOM.Meade.net.Wrapper
void SetParked(bool atPark, ParkedPosition parkedPosition); void SetParked(bool atPark, ParkedPosition parkedPosition);
bool IsParked { get; } bool IsParked { get; }
ParkedPosition ParkedPosition { get; } ParkedPosition ParkedPosition { get; }
PierSide SideOfPier { get; set; }
double? TargetRightAscension { get; set; }
double? TargetDeclination { get; set; }
short SlewSettleTime { get; set; }
bool IsLongFormat { get; set; }
bool MovingPrimary { get; set; }
bool MovingSecondary { get; set; }
DateTime EarliestNonSlewingTime { get; set; }
bool IsTargetCoordinateInitRequired { get; set; }
bool IsGuiding { get; set; }
} }
public class SharedResourcesWrapper : ISharedResourcesWrapper public class SharedResourcesWrapper : ISharedResourcesWrapper
@@ -74,11 +94,16 @@ namespace ASCOM.Meade.net.Wrapper
return SharedResources.SendBool(command, raw); return SharedResources.SendBool(command, raw);
} }
public string SendChar(string message,bool raw = false) public string SendChar(string message, bool raw = false)
{ {
return SharedResources.SendChar(message, raw); return SharedResources.SendChar(message, raw);
} }
public string SendChars(string message, bool raw = false, int count = 1)
{
return SharedResources.SendChars(message, raw, count);
}
public string ReadTerminated() public string ReadTerminated()
{ {
return SharedResources.ReadTerminated(); return SharedResources.ReadTerminated();
@@ -112,5 +137,65 @@ namespace ASCOM.Meade.net.Wrapper
public bool IsParked => SharedResources.IsParked; public bool IsParked => SharedResources.IsParked;
public ParkedPosition ParkedPosition => SharedResources.ParkedPosition; public ParkedPosition ParkedPosition => SharedResources.ParkedPosition;
public PierSide SideOfPier
{
get => SharedResources.SideOfPier;
set => SharedResources.SideOfPier = value;
}
public double? TargetRightAscension
{
get => SharedResources.TargetRightAscension;
set => SharedResources.TargetRightAscension = value;
}
public double? TargetDeclination
{
get => SharedResources.TargetDeclination;
set => SharedResources.TargetDeclination = value;
}
public short SlewSettleTime
{
get => SharedResources.SlewSettleTime;
set => SharedResources.SlewSettleTime = value;
}
public bool IsLongFormat
{
get => SharedResources.IsLongFormat;
set => SharedResources.IsLongFormat = value;
}
public bool MovingPrimary
{
get => SharedResources.MovingPrimary;
set => SharedResources.MovingPrimary = value;
}
public bool MovingSecondary
{
get => SharedResources.MovingSecondary;
set => SharedResources.MovingSecondary = value;
}
public DateTime EarliestNonSlewingTime
{
get => SharedResources.EarliestNonSlewingTime;
set => SharedResources.EarliestNonSlewingTime = value;
}
public bool IsTargetCoordinateInitRequired
{
get => SharedResources.IsTargetCoordinateInitRequired;
set => SharedResources.IsTargetCoordinateInitRequired = value;
}
public bool IsGuiding
{
get => SharedResources.IsGuiding;
set => SharedResources.IsGuiding = value;
}
} }
} }