Compare commits

...

42 Commits

Author SHA1 Message Date
ColinD a605a3ed9d Merged in develop (pull request #38)
Develop
2021-09-26 16:18:18 +00:00
ColinD ad9169a48d Modified so that the driver supports either +60.1 or 60.1 for tracking rate 2021-09-26 16:50:46 +01:00
ColinD 3b056ef7f8 Fixed bug in tracking rate get where it always returns lunar when it should be sidereal 2021-09-17 09:38:35 +01:00
ColinD 710ae0420a Added left, right as sysonyms of back and forward for the handbox commands.
Added scrollup and scrolldown handbox commands as well.
2021-09-09 12:14:15 +01:00
ColinD 2a6b74c6fd Merged in develop (pull request #37)
version 1.3.1
2021-08-04 18:48:01 +00:00
ColinD 49c43358de Added check to ensure that the Lunar Tracking rate cannot be selected on the LX200 Classic. 2021-08-04 18:48:24 +01:00
ColinD 27a0f54b07 Added check to make sure that the tracking rate cannot be set for an LX200. 2021-08-04 17:01:06 +01:00
ColinD a562b848c0 Corrected the expected result of the GT command. 2021-08-04 09:22:31 +01:00
ColinD f4c26d777b Added more logging around the tracking rates.
Corrected the Command logged messages to use the correct info.
Added a try catch to the setup dialog to see if an error occurs to give a better message.
2021-08-03 21:55:06 +01:00
ColinD 8d8b50957c Merged in develop (pull request #36)
Develop
2021-07-03 12:35:42 +00:00
Sebastian Godelet faa6ad757e Merged in feature/GWSupport-update (pull request #35)
Feature/GWSupport update
2021-07-03 11:23:32 +00:00
Sebastian Godelet 64df8282a0 Support Set Tracking when GW is supported 2021-06-29 15:31:57 +10:00
Sebastian Godelet 8478af26bf Implemented TrackingRate via GT 2021-06-28 16:06:15 +10:00
Sebastian Godelet 77c87a51fa Moved IsGuiding to SharedResourcesWrapper 2021-06-28 13:03:07 +10:00
Sebastian Godelet 631aa91d94 Moved IsTargetCoordinateInitRequired to SharedResourcesWrapper 2021-06-28 12:53:05 +10:00
Sebastian Godelet 90713de34b Moved parked SiteLat/Long to ParkedPosition data 2021-06-28 12:45:26 +10:00
Sebastian Godelet a3408a86c3 Update unit tests to support GW command
SideOfPier also supports German EQ
2021-06-27 19:16:39 +10:00
Sebastian Godelet 74440b6b3b Merge branch 'develop' into feature/GWSupport 2021-06-25 15:34:58 +10:00
ColinD f1d100892b Removed nunit3 Test adapter 2021-06-23 13:18:30 +01:00
ColinD c6baab2b12 Added tolerance in unit test to allow for rounding error. 2021-06-23 13:11:33 +01:00
Sebastian Godelet f47b205025 Merged in feature/preserve-sop-target-radec-across-connections (pull request #34)
Preserve SideOfPier, Target{RA,DEC}, SlewSettleTime, Move axis across connections

Approved-by: Colin Dawson
2021-06-23 08:53:31 +00:00
Sebastian Godelet 6c27499769 Create generic ThreadSafeValue 2021-06-23 16:21:08 +10:00
Sebastian Godelet 6dff32505e Clarify thread-safe value test intention 2021-06-23 11:09:22 +10:00
Sebastian Godelet 7afd364efa Add tests for SharedResources properties
Ensure that default values are correct and no error appears
2021-06-22 17:43:25 +10:00
Sebastian Godelet 6fc476b031 Make further properties multi-client and thread-safe
Move MovingPrimary, MovingSecondary, EarliestNonSlewingTime to
SharedResources, make all new properties thread-safe (atomic)
operations.
2021-06-22 17:21:21 +10:00
Sebastian Godelet af750549fe Test that low-precision digit values are preserved across connections 2021-06-13 17:36:42 +10:00
Sebastian Godelet 2e3572375f Test that SideralTime is preserved across connections 2021-06-13 17:24:09 +10:00
Sebastian Godelet b23da15022 Make Focuser.cs ASCII compatible 2021-06-13 16:30:55 +10:00
Sebastian Godelet 0b75b8d2cd Remove now unneeded Setup for DestinationSideOfPier
DestinationSideOfPier will not call Slewing anymore,
since it reads the property from SharedResourcesWrapper directly.
2021-06-13 09:59:17 +10:00
Sebastian Godelet 036a9d7116 Add multi-connection test for TargetRightAscension 2021-06-13 09:45:07 +10:00
Sebastian Godelet 6c769f3649 Add SlewSettleTime and IsLongFormat to SharedResources interface
Also ensure that digit precision is set during initialisation
2021-06-12 20:09:51 +10:00
Sebastian Godelet bdbd206a54 Avoid possible data race condition when calculating DSOP 2021-06-12 16:22:38 +10:00
Sebastian Godelet 1684bd60bd Move SideOfPier, TargetRA/DEC properties to SharedResourcesWrapper
This change allows several instances of the driver to be in sync
w.r.t. TargetRightAscension, TargetDeclination and SideOfPier
2021-06-12 15:47:34 +10:00
Sebastian Godelet 8c4b08d0c6 Merged in feature/side-of-pier-unit-tests (pull request #33)
Add unit test around meridian flip detection

Approved-by: Colin Dawson
2021-06-07 10:30:52 +00:00
Sebastian Godelet fe3c106954 Add unit test around meridian flip detection 2021-06-07 17:58:20 +10:00
ColinD 3d0464f379 Merged in develop (pull request #32)
Develop
2021-06-06 13:44:33 +00:00
Sebastian Godelet d1b5652228 Merged in feature/add-side-of-pier (pull request #31)
Implemented SideOfPier and DestinationSideOfPier

Approved-by: Colin Dawson
2021-06-06 13:23:49 +00:00
Sebastian Godelet 65e06f2d6c Implemented SideOfPier and DestinationSideOfPier
For telescopes that automatically perform a meridian flip we can
implement the SideOfPier property by updating the current side of pier
after a telescope slew (via DestinationSideOfPier)
2021-06-06 19:44:40 +10:00
ColinD b27e50275d Added extra logging for CommandBlind, CommandBool, and CommandString. 2021-05-09 15:20:45 +01:00
ColinD 8c94fd6b71 Merge branch 'develop' into feature/GWSupport 2021-04-25 20:28:48 +01:00
ColinD a2abbbb3d0 Working on a possible side of pier implementation 2021-04-21 17:24:40 +01:00
ColinD 21e7bcd530 Added support for the GW Command.
Removed the implementation of Tracking Set as this does not do anything in the code.
Set Can Set Tracking to false.
Get tracking always returns true is the GW command is not supported.
2021-03-10 19:25:27 +00:00
21 changed files with 1463 additions and 354 deletions
+2 -1
View File
@@ -123,7 +123,8 @@ namespace AstroMath.UnitTests
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));
}
@@ -2,7 +2,9 @@
using System.Globalization;
using System.Reflection;
using ASCOM;
using ASCOM.Astrometry;
using ASCOM.Astrometry.AstroUtils;
using ASCOM.Astrometry.NOVAS;
using ASCOM.DeviceInterface;
using ASCOM.Meade.net;
using ASCOM.Meade.net.AstroMaths;
@@ -16,20 +18,23 @@ namespace Meade.net.Telescope.UnitTests
{
public class TestProperties
{
internal string telescopeRaResult = "HH:MM:SS";
internal double rightAscension = 1.2; //todo rename to declination;
internal double declination = 45;
internal string telescopeRaResult { get; set; } = "HH:MM:SS";
internal double rightAscension { get; set; } = 1.2; //todo rename to declination;
internal double declination { get; set; } = 45;
internal string SiteLatitudeString = "testLatString";
internal double SiteLatitudeValue = 123.45;
internal string SiteLatitudeString { get; set; } = "testLatString";
internal double SiteLatitudeValue { get; set; } = 123.45;
internal string telescopeDate = "10/15/20";
internal string telescopeTime = "20:15:10";
internal string telescopeUtcCorrection = "-1.0";
internal string telescopeDate { get; set; } = "10/15/20";
internal string telescopeTime { get; set; } = "20:15:10";
internal string telescopeUtcCorrection { get; set; } = "-1.0";
internal double hourAngle;
internal int telescopeAltitude = 45;
internal int telescopeAzimuth = 200;
internal double hourAngle { get; set; }
internal int telescopeAltitude { get; set; } = 45;
internal int telescopeAzimuth { get; set; } = 200;
internal char[] AlignmentStatus { get; set; }
internal string TrackingRate { get; set; }
}
[TestFixture]
@@ -42,6 +47,7 @@ namespace Meade.net.Telescope.UnitTests
private Mock<ISharedResourcesWrapper> _sharedResourcesWrapperMock;
private Mock<IAstroMaths> _astroMathsMock;
private Mock<IClock> _clockMock;
private Mock<INOVAS31> _novasMock;
private ProfileProperties _profileProperties;
private ConnectionInfo _connectionInfo;
@@ -50,12 +56,14 @@ namespace Meade.net.Telescope.UnitTests
private bool _isParked;
private ParkedPosition _parkedPosition;
private string _siderealTrackingRate;
[SetUp]
public void Setup()
{
_isParked = false;
_parkedPosition = null;
_siderealTrackingRate = "+60.1";
_testProperties = new TestProperties();
@@ -97,20 +105,35 @@ namespace Meade.net.Telescope.UnitTests
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
.SetupProperty(x => x.SideOfPier)
.SetupProperty(x => x.TargetRightAscension)
.SetupProperty(x => x.TargetDeclination)
.SetupProperty(x => x.SlewSettleTime)
.SetupProperty(x => x.IsLongFormat);
_astroMathsMock = new Mock<IAstroMaths>();
_clockMock = new Mock<IClock>();
_novasMock = new Mock<INOVAS31>();
_telescope = new ASCOM.Meade.net.Telescope(_utilMock.Object, _utilExtraMock.Object, _astroUtilsMock.Object,
_sharedResourcesWrapperMock.Object, _astroMathsMock.Object, _clockMock.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);
_utilMock.Setup(x => x.DMSToDegrees(_testProperties.SiteLatitudeString)).Returns( () => _testProperties.SiteLatitudeValue);
@@ -121,6 +144,11 @@ namespace Meade.net.Telescope.UnitTests
_sharedResourcesWrapperMock.Setup(x => x.SendString("GL", false)).Returns(() => _testProperties.telescopeTime);
_sharedResourcesWrapperMock.Setup(x => x.SendString("GG", false)).Returns(() => _testProperties.telescopeUtcCorrection);
_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.FirmwareVersion).Returns(() => firmwareVersion);
@@ -132,6 +160,8 @@ namespace Meade.net.Telescope.UnitTests
_sharedResourcesWrapperMock.SetupGet(x => x.IsParked).Returns(() => _isParked);
_sharedResourcesWrapperMock.SetupGet(x => x.ParkedPosition).Returns(() => _parkedPosition);
_sharedResourcesWrapperMock.SetupProperty(x => x.IsGuiding);
_astroMathsMock
.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 });
@@ -191,7 +221,7 @@ namespace Meade.net.Telescope.UnitTests
_sharedResourcesWrapperMock.Setup(x => x.SendString("ED", false)).Returns(expectedResult);
_telescope.Connected = true;
var actualResult = _telescope.Action("handbox", "readdisplay");
@@ -217,6 +247,10 @@ namespace Meade.net.Telescope.UnitTests
[TestCase("down", "EK118")]
[TestCase("back", "EK87")]
[TestCase("forward", "EK69")]
[TestCase("left", "EK87")]
[TestCase("right", "EK69")]
[TestCase("scrollup", "EK85")]
[TestCase("scrolldown", "EK68")]
[TestCase("?", "EK63")]
public void Action_Handbox_WhenCalling_ThenSendsAppropriateBlindCommands(string action, string expectedString)
{
@@ -402,7 +436,7 @@ namespace Meade.net.Telescope.UnitTests
_sharedResourcesWrapperMock.Verify(x => x.SendBool(expectedMessage, raw), Times.Once);
Assert.That(result, Is.True);
}
[Test]
public void CommandString_WhenNotConnected_ThenThrowsNotConnectedException()
{
@@ -757,15 +791,17 @@ namespace Meade.net.Telescope.UnitTests
}
[TestCase("A", AlignmentModes.algAltAz)]
[TestCase("P", AlignmentModes.algPolar)]
[TestCase("G", AlignmentModes.algGermanPolar)]
public void AlignmentMode_Get_WhenScopeInAltAz_ReturnsAltAz(string telescopeMode, AlignmentModes alignmentMode)
[TestCase("A", AlignmentModes.algAltAz, TelescopeList.Autostar497, TelescopeList.Autostar497_31Ee)]
[TestCase("P", AlignmentModes.algPolar, TelescopeList.Autostar497, TelescopeList.Autostar497_31Ee)]
[TestCase("A", AlignmentModes.algAltAz, TelescopeList.Autostar497, TelescopeList.Autostar497_43Eg)]
[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;
_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;
@@ -791,9 +827,9 @@ namespace Meade.net.Telescope.UnitTests
Assert.That(exception.Message, Is.EqualTo("Not connected to telescope when trying to execute: AlignmentMode Set"));
}
[TestCase("AUTOSTAR", "43Eg", AlignmentModes.algAltAz, "AA")]
[TestCase("AUTOSTAR", "43Eg", AlignmentModes.algPolar, "AP")]
[TestCase("AUTOSTAR", "43Eg", AlignmentModes.algGermanPolar, "AP")]
[TestCase(TelescopeList.Autostar497, TelescopeList.Autostar497_43Eg, AlignmentModes.algAltAz, "AA")]
[TestCase(TelescopeList.Autostar497, TelescopeList.Autostar497_43Eg, AlignmentModes.algPolar, "AP")]
[TestCase(TelescopeList.Autostar497, TelescopeList.Autostar497_43Eg, AlignmentModes.algGermanPolar, "AP")]
public void AlignmentMode_Set_WhenConnected_ThenSendsExpectedCommand(string productName, string firmware, AlignmentModes alignmentMode, string expectedCommand)
{
_sharedResourcesWrapperMock.Setup(x => x.ProductName).Returns(productName);
@@ -992,20 +1028,85 @@ namespace Meade.net.Telescope.UnitTests
_sharedResourcesWrapperMock.Verify(x => x.SendChar("P", false), Times.AtLeastOnce);
}
[TestCase("High", false, true)]
[TestCase("High", true, true)]
[TestCase("Low", false, false)]
[TestCase("Low", true, false)]
public void Precision_Set_WhenSecondConnectionMade_ThenTelescopePrecisionNotChanged(string desiredPresision, bool telescopePrecision, bool finalPrecision)
[TestCase("High")]
[TestCase("Low")]
public void Precision_Set_WhenSecondConnectionMade_ThenTelescopePrecisionNotChanged(string desiredPresision)
{
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;
_connectionInfo.SameDevice = 2;
//_connectionInfo.Connections = 2;
_telescope.Connected = true;
_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]
@@ -1032,12 +1133,15 @@ namespace Meade.net.Telescope.UnitTests
Assert.That(result, Is.False);
}
[Test]
public void CanSetTracking_Get_ReturnsTrue()
[TestCase(TelescopeList.Autostar497_30Ee, false)]
[TestCase(TelescopeList.Autostar497_43Eg, true)]
public void CanSetTracking_Get_ReturnsTrueIffGWCommandIsSupported(string firmware, bool supported)
{
ConnectTelescope(firmwareVersion: firmware);
var result = _telescope.CanSetTracking;
Assert.That(result, Is.True);
Assert.That(result, Is.EqualTo(supported));
}
[Test]
@@ -1199,15 +1303,94 @@ namespace Meade.net.Telescope.UnitTests
}
[Test]
public void DestinationSideOfPier_ThenThrowsException()
public void DestinationSideOfPier_WhenNotConnected_ThenThrowsException()
{
var excpetion = Assert.Throws<MethodNotImplementedException>(() =>
var excpetion = Assert.Throws<NotConnectedException>(() =>
{
var result = _telescope.DestinationSideOfPier(0, 0);
Assert.Fail($"{result} should not have returned");
});
Assert.That(excpetion.Method, Is.EqualTo("DestinationSideOfPier"));
Assert.That(excpetion.Message, Is.EqualTo("Not connected to telescope when trying to execute: DestinationSideOfPier"));
}
[TestCase(1, 1, 4, PierSide.pierEast)]
[TestCase(1, -1, 4, PierSide.pierEast)]
[TestCase(4, 1, 1, PierSide.pierWest)]
[TestCase(4, -1, 1, PierSide.pierWest)]
[TestCase(0, 0, 0, PierSide.pierUnknown)]
[TestCase(5, 0, 5, PierSide.pierUnknown)]
[TestCase(23.8, 1, 23.9, PierSide.pierEast)]
[TestCase(23.8, -1, 23.9, PierSide.pierEast)]
[TestCase(23.9, 1, 1, PierSide.pierEast)]
[TestCase(23.9, -1, 1, PierSide.pierEast)]
[TestCase(1, 1, 23.9, PierSide.pierWest)]
[TestCase(1, -1, 23.9, PierSide.pierWest)]
public void DestinationSideOfPier_WhenHASiderealTimeDiffIsNotNull_ThenSideOfPierIsCalculated(double ra, double dec, double siderealTime, PierSide expectedDSOP)
{
// given
// 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);
var ha = siderealTime - ra;
// normalized hour angle range is [-12h..12h]
var normalisedHA = ha > 12 ? ha - 24 : ha < -12 ? ha + 24 : ha;
_astroUtilsMock.Setup(x => x.ConditionHA(It.Is<double>(v => v == ha))).Returns(normalisedHA);
ConnectTelescope();
// when
var actualDSOP = _telescope.DestinationSideOfPier(ra, dec);
// then
Assert.That(siderealTime, Is.InRange(0, 24));
Assert.That(normalisedHA, Is.InRange(-12, 12 + double.Epsilon));
Assert.That(actualDSOP, Is.EqualTo(expectedDSOP));
_astroUtilsMock.Verify(x => x.ConditionRA(It.IsAny<double>()), Times.Once);
_astroUtilsMock.Verify(x => x.ConditionHA(It.Is<double>(v => v == ha)), Times.Once);
}
[Test]
public void SiderealTime_Get_WhenNotConnected_ThenThrowsException()
{
// when
var exception = Assert.Throws<NotConnectedException>(() =>
{
var result = _telescope.SiderealTime;
Assert.Fail($"{result} should not have returned");
});
// then
Assert.That(exception.Message, Is.EqualTo("Not connected to telescope when trying to execute: SiderealTime Get"));
}
[Test]
public void SiderealTime_Get_WhenNOVASErrors_ThenThrowsException()
{
// given
double gst = 0.0;
_novasMock
.Setup(x => x.SiderealTime(It.IsAny<double>(), It.IsAny<double>(), It.IsAny<double>(), ASCOM.Astrometry.GstType.GreenwichApparentSiderealTime, ASCOM.Astrometry.Method.EquinoxBased, ASCOM.Astrometry.Accuracy.Reduced, ref gst))
.Returns(3)
.Verifiable();
ConnectTelescope();
// when
var exception = Assert.Throws<InvalidOperationException>(() =>
{
var result = _telescope.SiderealTime;
Assert.Fail($"{result} should not have returned");
});
// then
Assert.That(exception.Message, Is.EqualTo("NOVAS 3.1 SiderealTime returned: 3 in SiderealTime"));
_novasMock.Verify();
}
[Test]
@@ -1470,7 +1653,7 @@ namespace Meade.net.Telescope.UnitTests
Assert.That(_telescope.AtPark, Is.True);
//act
//act
_telescope.Park();
//no change from previous state.
@@ -1539,6 +1722,9 @@ namespace Meade.net.Telescope.UnitTests
[TestCase(GuideDirections.guideSouth, TelescopeAxes.axisSecondary)]
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("");
var duration = 0;
@@ -1549,6 +1735,8 @@ namespace Meade.net.Telescope.UnitTests
var exception = Assert.Throws<InvalidOperationException>(() => _telescope.PulseGuide(direction, duration));
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)]
@@ -1743,8 +1931,11 @@ namespace Meade.net.Telescope.UnitTests
}
[Test]
public void SideOfPier_Get_ThenThrowsException()
public void SideOfPier_Get_WhenMeridianFlipNotSupported_ThenThrowsException()
{
// LX200 classic is a fork mounted scope so it does not support meridian flips
_sharedResourcesWrapperMock.Setup(x => x.ProductName).Returns(TelescopeList.LX200CLASSIC);
var excpetion = Assert.Throws<PropertyNotImplementedException>(() =>
{
var result = _telescope.SideOfPier;
@@ -1764,6 +1955,173 @@ namespace Meade.net.Telescope.UnitTests
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]
public void SiteElevation_Get_WhenNotConnectedThrowsException()
{
@@ -2148,6 +2506,46 @@ namespace Meade.net.Telescope.UnitTests
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]
public void TargetRightAscension_Set_WhenNotConnected_ThenThrowsException()
{
@@ -2230,6 +2628,44 @@ namespace Meade.net.Telescope.UnitTests
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]
public void Tracking_Get_WhenDefault_ThenIsTrue()
{
@@ -2238,11 +2674,26 @@ namespace Meade.net.Telescope.UnitTests
[TestCase(true)]
[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;
Assert.That(_telescope.Tracking, Is.EqualTo(tracking));
_sharedResourcesWrapperMock.Verify(x => x.SendBlind(alignmentCommand, false), Times.Once);
}
[Test]
@@ -2256,25 +2707,35 @@ namespace Meade.net.Telescope.UnitTests
[TestCase(DriveRates.driveLunar, "TL")]
public void TrackingRate_Set_WhenConnected_ThenSendsCommandToTelescope(DriveRates rate, string commandString)
{
ConnectTelescope();
string productName = TelescopeList.Autostar497;
string firmwareVersion = TelescopeList.Autostar497_43Eg;
ConnectTelescope(productName, firmwareVersion);
_telescope.TrackingRate = rate;
Assert.That(_telescope.TrackingRate, Is.EqualTo(rate));
_sharedResourcesWrapperMock.Verify(x => x.SendBlind(commandString, false), Times.Once);
_sharedResourcesWrapperMock.Verify(x => x.SendString("GT", false), Times.Once);
}
[Test]
public void TrackingRate_Set_WhenUnSupportedRateSet_ThenThrowsException()
{
ConnectTelescope();
string productName = TelescopeList.Autostar497;
string firmwareVersion = TelescopeList.Autostar497_43Eg;
ConnectTelescope(productName, firmwareVersion);
var exception = Assert.Throws<ArgumentOutOfRangeException>(() => _telescope.TrackingRate = DriveRates.driveKing);
Assert.That(exception.Message, Is.EqualTo("Exception of type 'System.ArgumentOutOfRangeException' was thrown.\r\nParameter name: value\r\nActual value was driveKing."));
}
[Test]
public void TrackingRage_Get_WhenReadongDefaultValue_ThenAssumesSidereal()
[TestCase("60.1")]
[TestCase("+60.1")]
public void TrackingRage_Get_WhenReadingDefaultValue_ThenAssumesSidereal(string trackingRate)
{
ConnectTelescope();
@@ -2283,11 +2744,18 @@ namespace Meade.net.Telescope.UnitTests
Assert.That(result, Is.EqualTo(DriveRates.driveSidereal));
}
[TestCase(DriveRates.driveSidereal)]
[TestCase(DriveRates.driveLunar)]
public void TrackingRate_Get_WhenConnected_ThenSendsCommandToTelescope(DriveRates rate)
[TestCase(DriveRates.driveSidereal, "60.1")]
[TestCase(DriveRates.driveLunar, "60.1")]
[TestCase(DriveRates.driveSidereal, "+60.1")]
[TestCase(DriveRates.driveLunar, "+60.1")]
public void TrackingRate_Get_WhenConnected_ThenSendsCommandToTelescope(DriveRates rate, string trackingRate)
{
ConnectTelescope();
_siderealTrackingRate = trackingRate;
string productName = TelescopeList.Autostar497;
string firmwareVersion = TelescopeList.Autostar497_43Eg;
ConnectTelescope(productName, firmwareVersion);
_telescope.TrackingRate = rate;
@@ -2296,13 +2764,41 @@ namespace Meade.net.Telescope.UnitTests
Assert.That(result, Is.EqualTo(rate));
}
[Test]
public void TrackingRates_Get_ReturnsExpectedType()
[TestCase(DriveRates.driveSidereal, "60.1")]
[TestCase(DriveRates.driveLunar, "60.1")]
[TestCase(DriveRates.driveSidereal, "+60.1")]
[TestCase(DriveRates.driveLunar, "+60.1")]
public void TrackingRate_Set_WhenConnectedToLX200_ThenThrowsException(DriveRates rate, string trackingRate)
{
string productName = TelescopeList.LX200CLASSIC;
string firmwareVersion = string.Empty;
ConnectTelescope(productName, firmwareVersion);
var result = Assert.Throws<ASCOM.NotImplementedException>( () => _telescope.TrackingRate = rate );
Assert.That(result.Message, Is.EqualTo("TrackingRate Set is not implemented in this driver."));
}
[TestCase(TelescopeList.Autostar497, TelescopeList.Autostar497_43Eg, true )]
[TestCase(TelescopeList.LX200CLASSIC, "", false)]
public void TrackingRates_Get_ReturnsExpectedType(string productName, string firmwareVersion, bool supportsLunar)
{
ConnectTelescope(productName, firmwareVersion);
var result = _telescope.TrackingRates;
Assert.That(result, Is.Not.Null);
Assert.That(result, Is.AssignableTo<TrackingRates>());
if (supportsLunar)
{
Assert.That(result.Count, Is.EqualTo(2));
}
else
{
Assert.That(result.Count, Is.EqualTo(1));
}
}
[Test]
@@ -2514,6 +3010,7 @@ namespace Meade.net.Telescope.UnitTests
[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)
{
_sharedResourcesWrapperMock.SetupProperty(x => x.EarliestNonSlewingTime, DateTime.MinValue);
_profileProperties.SettleTime = profileSettleTime;
var timescalled = 0;
@@ -2563,7 +3060,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, "", "\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, "\u007f", true)]
[TestCase(TelescopeList.Autostar497, TelescopeList.Autostar497_43Eg, "\x007f", true)]
[TestCase(TelescopeList.Autostar497, TelescopeList.Autostar497_43Eg, "", false)]
public void Slewing_WhenTelescopeNotSlewing_ThenReturnsFalse(string productName, string firmwareVersion, string response, bool isSlewing)
{
@@ -2584,6 +3081,10 @@ namespace Meade.net.Telescope.UnitTests
[TestCase(-1, TelescopeAxes.axisSecondary)]
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();
_telescope.MoveAxis(axis, rate);
@@ -2591,6 +3092,9 @@ namespace Meade.net.Telescope.UnitTests
var result = _telescope.Slewing;
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);
}
@@ -2610,6 +3114,11 @@ namespace Meade.net.Telescope.UnitTests
[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)
{
_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;
DateTime currentTime = MakeTime("2021-01-23T22:02:10");
@@ -2627,17 +3136,17 @@ namespace Meade.net.Telescope.UnitTests
_telescope.MoveAxis(axis, 0);
currentTime = currentTime + TimeSpan.FromSeconds(profileSettleTime / 2);
currentTime += TimeSpan.FromSeconds(profileSettleTime / 2);
result = _telescope.Slewing;
Assert.That(result, Is.EqualTo(expectedResultInWaitingPeriod));
currentTime = currentTime + TimeSpan.FromSeconds(profileSettleTime / 2);
currentTime += TimeSpan.FromSeconds(profileSettleTime / 2);
result = _telescope.Slewing;
Assert.That(result, Is.EqualTo(afterProfileSettleTimeUp));
currentTime = currentTime + TimeSpan.FromSeconds(driverSettleTime);
currentTime += TimeSpan.FromSeconds(driverSettleTime);
result = _telescope.Slewing;
Assert.That(result, Is.False);
@@ -3021,8 +3530,8 @@ namespace Meade.net.Telescope.UnitTests
_sharedResourcesWrapperMock.Setup(x => x.SendString("GG", false)).Returns("-1.0");
_sharedResourcesWrapperMock.Setup(x => x.SendString("Gg", false)).Returns(telescopeLongitude);
_utilMock.Setup(x => x.DMSToDegrees(telescopeLongitude)).Returns(telescopeLongitudeValue);
_utilMock.Setup(x => x.DMSToDegrees(telescopeLongitude)).Returns(telescopeLongitudeValue);
ConnectTelescope();
+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 Condition="'$(Configuration)|$(Platform)' == 'Release|x86'">
<OutputPath>..\bin\Release\</OutputPath>
<Prefer32Bit>false</Prefer32Bit>
<Prefer32Bit>true</Prefer32Bit>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x86'">
<OutputPath>..\bin\Debug\</OutputPath>
@@ -118,6 +118,8 @@
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="Alignment.cs" />
<Compile Include="AlignmentStatus.cs" />
<Compile Include="AstroMaths\AltitudeData.cs" />
<Compile Include="AstroMaths\AstroMathExtensions.cs" />
<Compile Include="AstroMaths\AstroMaths.cs" />
@@ -190,7 +192,7 @@
<PreBuildEvent>
</PreBuildEvent>
</PropertyGroup>
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
+7 -3
View File
@@ -149,15 +149,19 @@ namespace ASCOM.Meade.net
// Default constructor - Internal prevents public creation
// of instances. Returned by Telescope.AxisRates.
//
internal TrackingRates()
internal TrackingRates(bool supportsLunar)
{
//
// This array must hold ONE or more DriveRates values, indicating
// the tracking rates supported by your telescope. The one value
// (tracking rate) that MUST be supported is driveSidereal!
//
_trackingRates = new[] { DriveRates.driveSidereal, DriveRates.driveLunar };
// TODO Initialize this array with any additional tracking rates that your driver may provide
if (supportsLunar)
{
_trackingRates = new[] {DriveRates.driveSidereal, DriveRates.driveLunar};
}
else
_trackingRates = new[] { DriveRates.driveSidereal };
}
#region ITrackingRates Members
File diff suppressed because it is too large Load Diff
@@ -98,6 +98,10 @@
<ItemGroup>
<Compile Include="SharedResourcesUnitTests.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="ThreadSafeBoolTests.cs" />
<Compile Include="ThreadSafeDateTimeTests.cs" />
<Compile Include="ThreadSafeEnumTests.cs" />
<Compile Include="ThreadSafeNullableDoubleTests.cs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Meade.net\Meade.net.csproj">
@@ -1,6 +1,7 @@
using System;
using System.Globalization;
using ASCOM.DeviceInterface;
using ASCOM.Meade.net;
using ASCOM.Meade.net.Wrapper;
using ASCOM.Utilities.Interfaces;
@@ -29,7 +30,7 @@ namespace Meade.net.UnitTests
[Test]
public void CheckThatSerialPortIsSetToUseMock()
{
Assert.That(SharedResources.SharedSerial,Is.EqualTo(_serialMock.Object));
Assert.That(SharedResources.SharedSerial, Is.EqualTo(_serialMock.Object));
}
[TestCase(true, "Test")]
@@ -160,7 +161,7 @@ namespace Meade.net.UnitTests
string GuideRateProfileNameDefault = "10.077939"; //67% of sidereal rate
string PrecisionDefault = "Unchanged";
string GuidingStyleDefault = "Auto";
string BacklashCompensationDefault = "3000";
string ReverseFocuserDiectionDefault = "true";
@@ -239,15 +240,15 @@ namespace Meade.net.UnitTests
SharedResources.ProfileFactory = profileFactoryMock.Object;
var profileProperties = SharedResources.ReadProfile();
Assert.That(profeWrapper.DeviceType, Is.EqualTo("Telescope"));
Assert.That(profileProperties.TraceLogger, Is.EqualTo(bool.Parse(TraceStateDefault)));
Assert.That(profileProperties.ComPort, Is.EqualTo(ComPortDefault));
Assert.That(profileProperties.GuideRateArcSecondsPerSecond,
Is.EqualTo(double.Parse(GuideRateProfileNameDefault)));
Is.EqualTo(double.Parse(GuideRateProfileNameDefault)));
Assert.That(profileProperties.Precision, Is.EqualTo(PrecisionDefault));
Assert.That(profileProperties.GuidingStyle, Is.EqualTo(GuidingStyleDefault));
@@ -423,7 +424,7 @@ namespace Meade.net.UnitTests
string serialPortReturn = string.Empty;
_serialMock.Setup(x => x.Transmit("#:GVP#")).Callback(() => {
_serialMock.Setup(x => x.Transmit("#:GVP#")).Callback(() => {
serialPortReturn = string.Empty;
throw new Exception("Testerror");
});
@@ -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);
}
[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="Moq" version="4.15.2" 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.Threading.Tasks.Extensions" version="4.5.4" targetFramework="net472" />
</packages>
+17 -11
View File
@@ -43,7 +43,7 @@ namespace ASCOM.Meade.net
/// Private variable to hold an ASCOM Utilities object
/// </summary>
private readonly IUtil _utilities;
/// <summary>
/// Initializes a new instance of the <see cref="Meade.net"/> class.
/// Must be public for COM registration.
@@ -101,6 +101,7 @@ namespace ASCOM.Meade.net
public void CommandBlind(string command, bool raw)
{
LogMessage("CommandBlind", "raw: {0} command {0}", raw, command);
CheckConnected("CommandBlind");
// Call CommandString and return as soon as it finishes
//this.CommandString(command, raw);
@@ -108,14 +109,16 @@ namespace ASCOM.Meade.net
// or
//throw new ASCOM.MethodNotImplementedException("CommandBlind");
// DO NOT have both these sections! One or the other
LogMessage("CommandBlind", "Completed");
}
public bool CommandBool(string command, bool raw)
{
LogMessage("CommandBool", "raw: {0} command {0}", raw, command);
CheckConnected("CommandBool");
//string ret = CommandString(command, raw);
return SharedResourcesWrapper.SendBool(command, raw);
// decode the return string and return true or false
var result = SharedResourcesWrapper.SendBool(command, raw);
LogMessage("CommandBool", "Completed: {0}", result);
return result;
// or
//throw new MethodNotImplementedException("CommandBool");
// DO NOT have both these sections! One or the other
@@ -123,11 +126,14 @@ namespace ASCOM.Meade.net
public string CommandString(string command, bool raw)
{
LogMessage("CommandString", "raw: {0} command {0}", raw, command);
CheckConnected("CommandString");
// it's a good idea to put all the low level communication with the device here,
// then all communication calls this function
// you need something to ensure that only one command is in progress at a time
return SharedResourcesWrapper.SendString(command, raw);
var result = SharedResourcesWrapper.SendString(command, raw);
LogMessage("CommandBool", "Completed: {0}", result);
return result;
//throw new ASCOM.MethodNotImplementedException("CommandString");
}
@@ -298,7 +304,7 @@ namespace ASCOM.Meade.net
var backlashCompensationSteps = direction ? Math.Abs(BacklashCompensation) : 0;
var steps = Math.Abs(position) + backlashCompensationSteps;
MoveFocuser(direction, steps);
@@ -337,11 +343,11 @@ namespace ASCOM.Meade.net
//:FS# Set Focus speed to slowest setting
//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
//All others Not Supported
//All others - Not Supported
_utilities.WaitForMilliseconds(100);
PerformFocuserMove(directionOut);
_utilities.WaitForMilliseconds(steps);
@@ -412,7 +418,7 @@ namespace ASCOM.Meade.net
#region ASCOM Registration
// Register or unregister driver for ASCOM. This is harmless if already
// registered or unregistered.
// registered or unregistered.
//
/// <summary>
/// Register or unregister the driver with the ASCOM Platform.
@@ -482,7 +488,7 @@ namespace ASCOM.Meade.net
}
#endregion
/// <summary>
/// Use this function to throw an exception if we aren't connected to the hardware
/// </summary>
+1
View File
@@ -146,6 +146,7 @@
<Compile Include="ProfileProperties.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="TelescopeList.cs" />
<Compile Include="ThreadSafeValue.cs" />
<Compile Include="Win32Utilities.cs" />
<Compile Include="Wrapper\IProfileWrapper.cs" />
<Compile Include="Wrapper\SharedResourcesWrapper.cs" />
+2 -2
View File
@@ -33,7 +33,7 @@ namespace ASCOM.Meade.net
protected ParkedBehaviour ParkedBehaviour;
protected HorizonCoordinates ParkedAltAz;
protected readonly ISharedResourcesWrapper SharedResourcesWrapper;
protected readonly ISharedResourcesWrapper SharedResourcesWrapper;
public MeadeTelescopeBase()
{
@@ -81,7 +81,7 @@ namespace ASCOM.Meade.net
Altitude = profileProperties.ParkedAlt,
Azimuth = profileProperties.ParkedAz
};
LogMessage("ReadProfile", $"Trace logger enabled: {Tl.Enabled}");
LogMessage("ReadProfile", $"Com Port: {ComPort}");
LogMessage("ReadProfile", $"Backlash Steps: {BacklashCompensation}");
+2
View File
@@ -6,5 +6,7 @@ namespace ASCOM.Meade.net
public double Azimuth { get; set; }
public double RightAscension { get; set; }
public double Declination { get; set; }
public double SiteLongitude { get; set; }
public double SiteLatitude { get; set; }
}
}
+127 -31
View File
@@ -4,7 +4,7 @@
// ================
//
// This class is a container for all shared resources that may be needed
// by the drivers served by the Local Server.
// by the drivers served by the Local Server.
//
// NOTES:
//
@@ -19,7 +19,9 @@ using System.Collections.Generic;
using System.Globalization;
using System.Runtime.InteropServices;
using System.Security.AccessControl;
using System.Threading;
using System.Windows.Forms;
using ASCOM.DeviceInterface;
using ASCOM.Meade.net.Wrapper;
using ASCOM.Utilities;
using ASCOM.Utilities.Interfaces;
@@ -49,7 +51,7 @@ namespace ASCOM.Meade.net
#region single serial port connector
//
// this region shows a way that a single serial port could be connected to by multiple
// this region shows a way that a single serial port could be connected to by multiple
// drivers.
//
// Connected is used to handle the connections to the port.
@@ -73,7 +75,7 @@ namespace ASCOM.Meade.net
public static IProfileFactory ProfileFactory
{
get => _profileFactory ?? ( _profileFactory = new ProfileFactory());
get => _profileFactory ?? (_profileFactory = new ProfileFactory());
set => _profileFactory = value;
}
@@ -122,13 +124,17 @@ namespace ASCOM.Meade.net
public static bool SendBool(string command, bool raw = false)
{
var result = SendChar(command, raw);
return result == "1";
}
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)
{
@@ -139,14 +145,11 @@ namespace ASCOM.Meade.net
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;
throw new TimeoutException(ex.Message, ex);
}
}
}
@@ -244,7 +247,7 @@ namespace ASCOM.Meade.net
private const string HandShakeDefault = "None";
private const string ParityDefault = "None";
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 ParkedAzimuthDefault = "180";
@@ -273,7 +276,7 @@ namespace ASCOM.Meade.net
profileProperties.Speed = Convert.ToInt32(driverProfile.GetValue(DriverId, SpeedName, string.Empty, SpeedDefault));
profileProperties.Parity = driverProfile.GetValue(DriverId, ParityName, string.Empty, ParityDefault);
profileProperties.SendDateTime = Convert.ToBoolean(driverProfile.GetValue(DriverId, SendDateTimeName, string.Empty, SendDateTimeDefault));
profileProperties.ParkedBehaviour = EnumExtensionMethods.GetValueFromDescription<ParkedBehaviour>(driverProfile.GetValue(DriverId, ParkedBehaviourName, string.Empty, ParkedBehaviourDefault));
profileProperties.ParkedAlt = double.Parse(driverProfile.GetValue(DriverId, ParkedAltName, string.Empty, ParkedAltDefault), NumberFormatInfo.InvariantInfo);
profileProperties.ParkedAz = double.Parse(driverProfile.GetValue(DriverId, ParkedAzimuthName, string.Empty, ParkedAzimuthDefault), NumberFormatInfo.InvariantInfo);
@@ -289,29 +292,38 @@ namespace ASCOM.Meade.net
public static void SetupDialog()
{
var profileProperties = ReadProfile();
using (SetupDialogForm f = new SetupDialogForm())
try
{
f.SetProfile(profileProperties);
var profileProperties = ReadProfile();
if (IsConnected())
using (SetupDialogForm f = new SetupDialogForm())
{
f.SetReadOnlyMode();
}
f.SetProfile(profileProperties);
var result = f.ShowDialog();
if (result == DialogResult.OK)
{
profileProperties = f.GetProfile();
if (IsConnected())
{
f.SetReadOnlyMode();
}
WriteProfile(profileProperties); // Persist device configuration values to the ASCOM Profile store
var result = f.ShowDialog();
if (result == DialogResult.OK)
{
profileProperties = f.GetProfile();
WriteProfile(
profileProperties); // Persist device configuration values to the ASCOM Profile store
}
}
}
catch (Exception e)
{
Console.WriteLine(e);
throw;
}
}
#endregion
#region Multi Driver handling
public static string ProductName { get; private set; } = string.Empty;
@@ -334,7 +346,7 @@ namespace ASCOM.Meade.net
private static readonly Dictionary<string, DeviceHardware> ConnectedDevices = new Dictionary<string, DeviceHardware>();
private static readonly Dictionary<string, DeviceHardware> ConnectedDeviceIds = new Dictionary<string, DeviceHardware>();
private static IProfileFactory _profileFactory ;
private static IProfileFactory _profileFactory;
/// <summary>
@@ -350,7 +362,7 @@ namespace ASCOM.Meade.net
{
if (!ConnectedDevices.ContainsKey(deviceId))
ConnectedDevices.Add(deviceId, new DeviceHardware());
if (!ConnectedDeviceIds.ContainsKey(driverId))
ConnectedDeviceIds.Add(driverId, new DeviceHardware());
@@ -363,7 +375,7 @@ namespace ASCOM.Meade.net
SharedSerial.DTREnable = profileProperties.RtsDtrEnabled;
SharedSerial.RTSEnable = profileProperties.RtsDtrEnabled;
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.Speed = (SerialSpeed)profileProperties.Speed;
SharedSerial.Handshake = (SerialHandshake)Enum.Parse(typeof(SerialHandshake), profileProperties.Handshake);
@@ -493,15 +505,99 @@ namespace ASCOM.Meade.net
Count = 0;
}
}
public static void SetParked(bool atPark, ParkedPosition parkedPosition)
{
IsParked = atPark;
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 ASCOM.DeviceInterface;
using ASCOM.Utilities.Interfaces;
namespace ASCOM.Meade.net.Wrapper
@@ -19,6 +20,7 @@ namespace ASCOM.Meade.net.Wrapper
void SendBlind(string message, bool raw = false);
bool SendBool(string command, bool raw = false);
string SendChar(string message, bool raw = false);
string SendChars(string message, bool raw = false, int count = 1);
string ReadTerminated();
@@ -31,6 +33,24 @@ namespace ASCOM.Meade.net.Wrapper
void SetParked(bool atPark, ParkedPosition parkedPosition);
bool IsParked { 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
@@ -74,11 +94,16 @@ namespace ASCOM.Meade.net.Wrapper
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);
}
public string SendChars(string message, bool raw = false, int count = 1)
{
return SharedResources.SendChars(message, raw, count);
}
public string ReadTerminated()
{
return SharedResources.ReadTerminated();
@@ -112,5 +137,65 @@ namespace ASCOM.Meade.net.Wrapper
public bool IsParked => SharedResources.IsParked;
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;
}
}
}