diff --git a/AstroMath.UnitTests/AstroMath.UnitTests.csproj b/AstroMath.UnitTests/AstroMath.UnitTests.csproj
index ad41f58..14292b4 100644
--- a/AstroMath.UnitTests/AstroMath.UnitTests.csproj
+++ b/AstroMath.UnitTests/AstroMath.UnitTests.csproj
@@ -68,8 +68,8 @@
..\packages\System.Runtime.CompilerServices.Unsafe.4.5.2\lib\netstandard2.0\System.Runtime.CompilerServices.Unsafe.dll
-
- ..\packages\System.Threading.Tasks.Extensions.4.5.2\lib\netstandard2.0\System.Threading.Tasks.Extensions.dll
+
+ ..\packages\System.Threading.Tasks.Extensions.4.5.3\lib\netstandard2.0\System.Threading.Tasks.Extensions.dll
@@ -89,6 +89,7 @@
+
diff --git a/AstroMath.UnitTests/app.config b/AstroMath.UnitTests/app.config
new file mode 100644
index 0000000..8d5ec5f
--- /dev/null
+++ b/AstroMath.UnitTests/app.config
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/AstroMath.UnitTests/packages.config b/AstroMath.UnitTests/packages.config
index 605fe2b..b50b126 100644
--- a/AstroMath.UnitTests/packages.config
+++ b/AstroMath.UnitTests/packages.config
@@ -4,5 +4,5 @@
-
+
\ No newline at end of file
diff --git a/Meade.net.Focuser.UnitTests/BootstrapAscomProfileStore.ps1 b/Meade.net.Focuser.UnitTests/BootstrapAscomProfileStore.ps1
new file mode 100644
index 0000000..213c64d
--- /dev/null
+++ b/Meade.net.Focuser.UnitTests/BootstrapAscomProfileStore.ps1
@@ -0,0 +1,36 @@
+<#
+This script initializes a bare minimum set of registry entries required for ASCOM.Utilities.Profile to work
+without throwing any exceptions. When building on a build server, or on a computer without the ASCOM Platform installed,
+it may be useful to execute this script as a build step prior to running any unit tests, or calling any code that relies on
+ASCOM.Utilities.Profile. The alternative is to install the ASCOM Platform on the build agent.
+
+NOTE: This script equires elevated permissions because it creates registry keys in the LocalMachine hive.
+#>
+
+$wow = Test-Path HKLM:\SOFTWARE\Wow6432Node
+if ($wow)
+ {
+ $root = "HKLM:\SOFTWARE\Wow6432Node"
+ }
+else
+ {
+ $root = "HKLM:\SOFTWARE"
+ }
+$ascomRoot = $root + "\ASCOM"
+
+if (Test-Path $ascomRoot)
+ {
+ <# Don't upset an already-existing ASCOM registry #>
+ exit
+ }
+
+<# Create the ASCOM root key and set it's ACL to allow all users read/write access #>
+New-Item -Path $root -Name ASCOM –Force
+$ascomAcl = Get-Acl $ascomRoot
+$aclRule = New-Object System.Security.AccessControl.RegistryAccessRule ("Users","FullControl","Allow")
+$ascomAcl.SetAccessRule($aclRule)
+$ascomAcl | Set-Acl -Path $ascomRoot
+
+<# Now create the bare minimum keys required so that ASCOM.Utilities.Profile doesn't crash and burn #>
+New-ItemProperty -Path $ascomRoot -Name PlatformVersion -Value "6.1" -PropertyType String –Force
+New-ItemProperty -Path $ascomRoot -Name SerTraceFile -Value "C:\SerialTraceAuto.txt" -PropertyType String –Force
diff --git a/Meade.net.Focuser.UnitTests/FocuserUnitTests.cs b/Meade.net.Focuser.UnitTests/FocuserUnitTests.cs
new file mode 100644
index 0000000..9dfd50b
--- /dev/null
+++ b/Meade.net.Focuser.UnitTests/FocuserUnitTests.cs
@@ -0,0 +1,455 @@
+using System;
+using ASCOM;
+using ASCOM.DeviceInterface;
+using ASCOM.Meade.net;
+using ASCOM.Meade.net.Wrapper;
+using ASCOM.Utilities.Interfaces;
+using Moq;
+using NUnit.Framework;
+using NotImplementedException = System.NotImplementedException;
+
+namespace Meade.net.Focuser.UnitTests
+{
+ [TestFixture]
+ public class FocuserUnitTests
+ {
+ private Mock _utilMock;
+ private Mock _sharedResourcesWrapperMock;
+
+ private ProfileProperties _profileProperties;
+
+ private ASCOM.Meade.net.Focuser _focuser;
+
+ [SetUp]
+ public void Setup()
+ {
+ _profileProperties = new ProfileProperties();
+ _profileProperties.TraceLogger = false;
+ _profileProperties.ComPort = "TestCom1";
+ _profileProperties.GuideRateArcSecondsPerSecond = 1.23;
+ _profileProperties.Precision = "Unchanged";
+
+ _utilMock = new Mock();
+
+ _sharedResourcesWrapperMock = new Mock();
+
+ _sharedResourcesWrapperMock.Setup(x => x.Lock(It.IsAny())).Callback(action => { action(); });
+
+ _sharedResourcesWrapperMock.Setup(x => x.ReadProfile()).Returns(() => _profileProperties);
+
+ _focuser = new ASCOM.Meade.net.Focuser(_utilMock.Object, _sharedResourcesWrapperMock.Object);
+ }
+
+ private void ConnectFocuser()
+ {
+ _sharedResourcesWrapperMock.Setup(x => x.ProductName).Returns(() => TelescopeList.Autostar497);
+ _sharedResourcesWrapperMock.Setup(x => x.FirmwareVersion).Returns(() => TelescopeList.Autostar497_31Ee);
+ _focuser.Connected = true;
+ }
+
+ [Test]
+ public void CheckThatClassCreatedProperly()
+ {
+ Assert.That(_focuser, Is.Not.Null);
+ }
+
+ [Test]
+ public void NotConnectedByDefault()
+ {
+ Assert.That(_focuser.Connected, Is.False);
+ }
+
+ [Test]
+ public void SetupDialog()
+ {
+ _sharedResourcesWrapperMock.Verify(x => x.ReadProfile(), Times.Once);
+
+ _focuser.SetupDialog();
+
+ _sharedResourcesWrapperMock.Verify(x => x.SetupDialog(), Times.Once);
+ _sharedResourcesWrapperMock.Verify(x => x.ReadProfile(), Times.Exactly(2));
+ }
+
+ [Test]
+ public void SupportedActions()
+ {
+ var supportedActions = _focuser.SupportedActions;
+
+ Assert.That(supportedActions, Is.Not.Null);
+ Assert.That(supportedActions.Count, Is.EqualTo(0));
+ }
+
+ [Test]
+ public void Action_WhenNotConnected_ThrowsNotConnectedException()
+ {
+ var actionName = "Action";
+
+ var exception = Assert.Throws(() => { var actualResult = _focuser.Action(actionName, string.Empty); });
+ }
+
+ [Test]
+ public void CommandBlind_WhenNotConnected_ThenThrowsNotConnectedException()
+ {
+ string expectedMessage = "test blind Message";
+ var exception = Assert.Throws(() => { _focuser.CommandBlind(expectedMessage, true); });
+
+ Assert.That(exception.Message, Is.EqualTo("Not connected to focuser when trying to execute: CommandBlind"));
+ }
+
+ [Test]
+ public void CommandBlind_WhenConnected_ThenSendsExpectedMessage()
+ {
+ string expectedMessage = "test blind Message";
+
+ ConnectFocuser();
+
+ _focuser.CommandBlind(expectedMessage, true);
+
+ _sharedResourcesWrapperMock.Verify(x => x.SendBlind(expectedMessage), Times.Once);
+ }
+
+ [Test]
+ public void CommandBool_WhenNotConnected_ThenThrowsNotConnectedException()
+ {
+ string expectedMessage = "test blind Message";
+ var exception = Assert.Throws(() => { _focuser.CommandBool(expectedMessage, true); });
+
+ Assert.That(exception.Message, Is.EqualTo("Not connected to focuser when trying to execute: CommandBool"));
+ }
+
+ [Test]
+ public void CommandBool_WhenConnected_ThenSendsExpectedMessage()
+ {
+ string expectedMessage = "test blind Message";
+
+ ConnectFocuser();
+
+ var exception = Assert.Throws(() => { _focuser.CommandBool(expectedMessage, true); });
+
+ Assert.That(exception.Message, Is.EqualTo("Method CommandBool is not implemented in this driver."));
+ }
+
+ [Test]
+ public void CommandString_WhenNotConnected_ThenThrowsNotConnectedException()
+ {
+ string expectedMessage = "test blind Message";
+ var exception = Assert.Throws(() => { _focuser.CommandString(expectedMessage, true); });
+
+ Assert.That(exception.Message, Is.EqualTo("Not connected to focuser when trying to execute: CommandString"));
+ }
+
+ [Test]
+ public void CommandString_WhenConnected_ThenSendsExpectedMessage()
+ {
+ string expectedMessage = "expected result message";
+ string sendMessage = "test blind Message";
+
+ ConnectFocuser();
+
+ _sharedResourcesWrapperMock.Setup(x => x.SendString(sendMessage)).Returns(() => expectedMessage);
+
+ var actualMessage = _focuser.CommandString(sendMessage, true);
+
+ _sharedResourcesWrapperMock.Verify(x => x.SendString(sendMessage), Times.Once);
+ Assert.That(actualMessage, Is.EqualTo(expectedMessage));
+ }
+
+ [TestCase(true)]
+ [TestCase(false)]
+ public void Connected_Get_ReturnsExpectedValue(bool expectedConnected)
+ {
+ _sharedResourcesWrapperMock.Setup(x => x.ProductName).Returns(() => TelescopeList.Autostar497);
+ _sharedResourcesWrapperMock.Setup(x => x.FirmwareVersion).Returns(() => TelescopeList.Autostar497_31Ee);
+ _focuser.Connected = expectedConnected;
+
+ Assert.That(_focuser.Connected, Is.EqualTo(expectedConnected));
+ }
+
+ [Test]
+ public void Connected_Set_WhenConnecting_Then_ConnectsToSerialDevice()
+ {
+ var productName = "LX2001";
+ var firmware = string.Empty;
+
+ _sharedResourcesWrapperMock.Setup(x => x.ProductName).Returns(productName);
+ _sharedResourcesWrapperMock.Setup(x => x.FirmwareVersion).Returns(firmware);
+ _focuser.Connected = true;
+
+ _sharedResourcesWrapperMock.Verify(x => x.Connect("Serial", It.IsAny()), Times.Once);
+ }
+
+
+ [Test]
+ public void Connected_Set_SettingTrueWhenTrue_ThenDoesNothing()
+ {
+ ConnectFocuser();
+ _sharedResourcesWrapperMock.Verify(x => x.Connect(It.IsAny(), It.IsAny()), Times.Once);
+
+ //act
+ _focuser.Connected = true;
+
+ //assert
+ _sharedResourcesWrapperMock.Verify(x => x.Connect(It.IsAny(), It.IsAny()), Times.Once);
+ }
+
+ [Test]
+ public void Connected_Set_SettingFalseWhenTrue_ThenDisconnects()
+ {
+ ConnectFocuser();
+ _sharedResourcesWrapperMock.Verify(x => x.Connect(It.IsAny(), It.IsAny()), Times.Once);
+
+ //act
+ _focuser.Connected = false;
+
+ //assert
+ _sharedResourcesWrapperMock.Verify(x => x.Disconnect(It.IsAny(), It.IsAny()), Times.Once());
+ }
+
+ //Commented out for now as the catch after connect is currently unreachable code.
+ //[Test]
+ //public void Connected_Set_WhenFailsToConnect_ThenDisconnects()
+ //{
+ // _sharedResourcesWrapperMock.Setup(x => x.ProductName).Returns(() => TelescopeList.Autostar497);
+ // _sharedResourcesWrapperMock.Setup(x => x.FirmwareVersion).Returns(() => TelescopeList.Autostar497_31Ee);
+
+ // _sharedResourcesWrapperMock.Setup(x => x.SendString(It.IsAny())).Throws(new Exception("TestFailed"));
+
+ // //act
+ // _focuser.Connected = true;
+
+ // //assert
+ // _sharedResourcesWrapperMock.Verify(x => x.Disconnect(It.IsAny(), It.IsAny()), Times.Once());
+ //}
+
+ [Test]
+ public void Description_Get()
+ {
+ var expectedDescription = "Meade Generic";
+
+ var description = _focuser.Description;
+
+ Assert.That(description, Is.EqualTo(expectedDescription));
+ }
+
+ [Test]
+ public void DriverVersion_Get()
+ {
+ Version version = System.Reflection.Assembly.GetAssembly(typeof(ASCOM.Meade.net.Focuser)).GetName().Version;
+
+ string exptectedDriverInfo = $"{version.Major}.{version.Minor}.{version.Build}.{version.Revision}";
+
+ var driverVersion = _focuser.DriverVersion;
+
+ Assert.That(driverVersion, Is.EqualTo(exptectedDriverInfo));
+ }
+
+ [Test]
+ public void DriverInfo_Get()
+ {
+ Version version = System.Reflection.Assembly.GetAssembly(typeof(ASCOM.Meade.net.Focuser)).GetName().Version;
+
+ string exptectedDriverInfo = $"{_focuser.Description} .net driver. Version: {_focuser.DriverVersion}";
+
+ var driverInfo = _focuser.DriverInfo;
+
+ Assert.That(driverInfo, Is.EqualTo(exptectedDriverInfo));
+ }
+
+ [Test]
+ public void InterfaceVersion_Get()
+ {
+ var interfaceVersion = _focuser.InterfaceVersion;
+ Assert.That(interfaceVersion, Is.EqualTo(3));
+
+ Assert.That(_focuser, Is.AssignableTo());
+ }
+
+ [Test]
+ public void Name_Get()
+ {
+ string expectedName = "Meade Generic";
+
+ var name = _focuser.Name;
+
+ Assert.That(name, Is.EqualTo(expectedName));
+ }
+
+ [Test]
+ public void Absolute_Get_WhenNotConnected_ThenThrowsException()
+ {
+ var exception = Assert.Throws(() => { var result = _focuser.Absolute; });
+ Assert.That(exception.Message, Is.EqualTo("Not connected to focuser when trying to execute: Absolute Get"));
+ }
+
+ [Test]
+ public void Absolute_Get_WhenConnected_ThenReturnsFalse()
+ {
+ ConnectFocuser();
+ var result = _focuser.Absolute;
+
+ Assert.That(result, Is.False);
+ }
+
+ [Test]
+ public void Halt_WhenNotConnected_ThenThrowsException()
+ {
+ var exception = Assert.Throws(() => { _focuser.Halt(); });
+ Assert.That(exception.Message, Is.EqualTo("Not connected to focuser when trying to execute: Halt"));
+ }
+
+ [Test]
+ public void Halt_WhenConnected_ThenSendsHaltCommand()
+ {
+ ConnectFocuser();
+
+ _focuser.Halt();
+
+ _sharedResourcesWrapperMock.Verify( x => x.SendBlind(":FQ#"), Times.AtLeastOnce);
+ _utilMock.Verify( x => x.WaitForMilliseconds(250), Times.AtLeastOnce);
+ }
+
+ [Test]
+ public void IsMoving_WhenCalled_ThenReturnsFalse()
+ {
+ ConnectFocuser();
+
+ var result = _focuser.IsMoving;
+
+ Assert.That(result, Is.False);
+ }
+
+ [TestCase(false)]
+ [TestCase(true)]
+ public void Link_Get_ReturnsSameValueAsConnected( bool connected)
+ {
+ _sharedResourcesWrapperMock.Setup(x => x.ProductName).Returns(() => TelescopeList.Autostar497);
+ _sharedResourcesWrapperMock.Setup(x => x.FirmwareVersion).Returns(() => TelescopeList.Autostar497_31Ee);
+ _focuser.Connected = connected;
+
+ Assert.That( _focuser.Link, Is.EqualTo(connected));
+ }
+
+ [TestCase(false)]
+ [TestCase(true)]
+ public void Link_Set_WhenSet_ThenSetsConnectedState(bool connected)
+ {
+ _sharedResourcesWrapperMock.Setup(x => x.ProductName).Returns(() => TelescopeList.Autostar497);
+ _sharedResourcesWrapperMock.Setup(x => x.FirmwareVersion).Returns(() => TelescopeList.Autostar497_31Ee);
+ _focuser.Link = connected;
+
+ Assert.That(_focuser.Link, Is.EqualTo(connected));
+ }
+
+ [Test]
+ public void MaxIncrement_WhenCalled_ThenReturnsExpectedValue()
+ {
+ var result = _focuser.MaxIncrement;
+
+ Assert.That(result, Is.EqualTo(7000));
+ }
+
+ [Test]
+ public void MaxStep_WhenCalled_ThenReturnsExpectedValue()
+ {
+ var result = _focuser.MaxStep;
+
+ Assert.That(result, Is.EqualTo(7000));
+ }
+
+ [Test]
+ public void Move_WhenNotConnected_ThenThrowsException()
+ {
+ var exception = Assert.Throws(() => { _focuser.Move(0); });
+ Assert.That(exception.Message, Is.EqualTo("Not connected to focuser when trying to execute: Move"));
+ }
+
+ [TestCase(-7001)]
+ [TestCase(7001)]
+ public void Move_WhenLargerThanMaxIncrement_ThenThrowsException(int position)
+ {
+ ConnectFocuser();
+
+ var exception = Assert.Throws(() => { _focuser.Move(position); });
+ Assert.That(exception.Message, Is.EqualTo($"position out of range -{_focuser.MaxIncrement} < {position} < {_focuser.MaxIncrement}"));
+ }
+
+ [Test]
+ public void Move_WhenIncrementIs0_ThenDoesNothing()
+ {
+ ConnectFocuser();
+
+ _focuser.Move(0);
+
+ _utilMock.Verify( x => x.WaitForMilliseconds(It.IsAny()), Times.Never);
+ }
+
+ [TestCase(200)]
+ [TestCase(-200)]
+ public void Move_WhenIncrementIsNot0_ThenMovesFocuserAndStopsFocuser( int position)
+ {
+ ConnectFocuser();
+
+ _focuser.Move(position);
+
+ if (position < 0)
+ {
+ _sharedResourcesWrapperMock.Verify( x => x.SendBlind(":F-#"), Times.AtLeastOnce);
+ _sharedResourcesWrapperMock.Verify(x => x.SendBlind(":F+#"), Times.Never);
+ }
+ else
+ {
+ _sharedResourcesWrapperMock.Verify(x => x.SendBlind(":F-#"), Times.Never);
+ _sharedResourcesWrapperMock.Verify(x => x.SendBlind(":F+#"), Times.AtLeastOnce);
+ }
+
+ _sharedResourcesWrapperMock.Verify( x => x.Lock(It.IsAny()), Times.Once);
+
+ _utilMock.Verify(x => x.WaitForMilliseconds(250), Times.AtLeastOnce);
+
+ _utilMock.Verify(x => x.WaitForMilliseconds(100), Times.Once());
+ _utilMock.Verify(x => x.WaitForMilliseconds(1000), Times.Once());
+ }
+
+ [Test]
+ public void Position_WhenCalled_ThenThrowsException()
+ {
+ var exception = Assert.Throws(() => { var result = _focuser.Position; });
+ Assert.That(exception.Message, Is.EqualTo("Property read Position is not implemented in this driver."));
+ }
+
+ [Test]
+ public void StepSize_WhenCalled_ThenThrowsException()
+ {
+ var exception = Assert.Throws(() => { var result = _focuser.StepSize; });
+ Assert.That(exception.Message, Is.EqualTo("Property read StepSize is not implemented in this driver."));
+ }
+
+ [Test]
+ public void TempComp_WhenRead_ThenReturnsFalse()
+ {
+ var result = _focuser.TempComp;
+ Assert.That(result, Is.False);
+ }
+
+ [Test]
+ public void TempComp_WhenWrite_ThenThrowsException()
+ {
+ var exception = Assert.Throws(() => { _focuser.TempComp = false; });
+ Assert.That(exception.Message, Is.EqualTo("Property read TempComp is not implemented in this driver."));
+ }
+
+ [Test]
+ public void TempCompAvailable_WhenRead_ThenReturnsFalse()
+ {
+ var result = _focuser.TempCompAvailable;
+ Assert.That(result, Is.False);
+ }
+
+ [Test]
+ public void Temperature_WhenCalled_ThenThrowsException()
+ {
+ var exception = Assert.Throws(() => { var result = _focuser.Temperature; });
+ Assert.That(exception.Message, Is.EqualTo("Property read Temperature is not implemented in this driver."));
+ }
+ }
+}
diff --git a/Meade.net.Focuser.UnitTests/Meade.net.Focuser.UnitTests.csproj b/Meade.net.Focuser.UnitTests/Meade.net.Focuser.UnitTests.csproj
new file mode 100644
index 0000000..8181584
--- /dev/null
+++ b/Meade.net.Focuser.UnitTests/Meade.net.Focuser.UnitTests.csproj
@@ -0,0 +1,122 @@
+
+
+
+
+
+ Debug
+ AnyCPU
+ {A3991FA7-23C3-405A-96F9-5AB03AC58F30}
+ Library
+ Properties
+ Meade.net.Focuser.UnitTests
+ Meade.net.Focuser.UnitTests
+ v4.7.2
+ 512
+ true
+
+
+
+
+ true
+ full
+ false
+ bin\Debug\
+ DEBUG;TRACE
+ prompt
+ 4
+ x86
+
+
+ pdbonly
+ true
+ bin\Release\
+ TRACE
+ prompt
+ 4
+
+
+
+ ..\packages\ASCOM.Platform.6.4.2\lib\net40\ASCOM.Astrometry.dll
+
+
+ ..\packages\ASCOM.Platform.6.4.2\lib\net40\ASCOM.Attributes.dll
+
+
+ ..\packages\ASCOM.Platform.6.4.2\lib\net40\ASCOM.Cache.dll
+
+
+ ..\packages\ASCOM.Platform.6.4.2\lib\net40\ASCOM.Controls.dll
+
+
+ ..\packages\ASCOM.Platform.6.4.2\lib\net40\ASCOM.DeviceInterfaces.dll
+
+
+ ..\packages\ASCOM.Platform.6.4.2\lib\net40\ASCOM.DriverAccess.dll
+
+
+ ..\packages\ASCOM.Platform.6.4.2\lib\net40\ASCOM.Exceptions.dll
+
+
+ ..\packages\ASCOM.Platform.6.4.2\lib\net40\ASCOM.Internal.Extensions.dll
+
+
+ ..\packages\ASCOM.Platform.6.4.2\lib\net40\ASCOM.SettingsProvider.dll
+
+
+ ..\packages\ASCOM.Platform.6.4.2\lib\net40\ASCOM.Utilities.dll
+
+
+ ..\packages\ASCOM.Platform.6.4.2\lib\net40\ASCOM.Utilities.Video.dll
+
+
+ ..\packages\Castle.Core.4.4.0\lib\net45\Castle.Core.dll
+
+
+ ..\packages\Moq.4.12.0\lib\net45\Moq.dll
+
+
+ ..\packages\NUnit.3.12.0\lib\net45\nunit.framework.dll
+
+
+
+
+
+ ..\packages\System.Runtime.CompilerServices.Unsafe.4.5.2\lib\netstandard2.0\System.Runtime.CompilerServices.Unsafe.dll
+
+
+ ..\packages\System.Threading.Tasks.Extensions.4.5.3\lib\netstandard2.0\System.Threading.Tasks.Extensions.dll
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {a97e3aec-f11d-49da-b259-de99da813a86}
+ Meade.net.focuser
+
+
+ {3689a2cb-94c5-4012-a5cf-7e7d1dd27143}
+ Meade.net
+
+
+
+
+
+ This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.
+
+
+
+
\ No newline at end of file
diff --git a/Meade.net.Focuser.UnitTests/Properties/AssemblyInfo.cs b/Meade.net.Focuser.UnitTests/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..61a9edd
--- /dev/null
+++ b/Meade.net.Focuser.UnitTests/Properties/AssemblyInfo.cs
@@ -0,0 +1,36 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("Meade.net.Focuser.UnitTests")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("Meade.net.Focuser.UnitTests")]
+[assembly: AssemblyCopyright("Copyright © 2019")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible
+// to COM components. If you need to access a type in this assembly from
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("a3991fa7-23c3-405a-96f9-5ab03ac58f30")]
+
+// Version information for an assembly consists of the following four values:
+//
+// Major Version
+// Minor Version
+// Build Number
+// Revision
+//
+// You can specify all the values or you can default the Build and Revision Numbers
+// by using the '*' as shown below:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/Meade.net.Focuser.UnitTests/app.config b/Meade.net.Focuser.UnitTests/app.config
new file mode 100644
index 0000000..8d5ec5f
--- /dev/null
+++ b/Meade.net.Focuser.UnitTests/app.config
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Meade.net.Focuser.UnitTests/packages.config b/Meade.net.Focuser.UnitTests/packages.config
new file mode 100644
index 0000000..1330573
--- /dev/null
+++ b/Meade.net.Focuser.UnitTests/packages.config
@@ -0,0 +1,9 @@
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Meade.net.Telescope.UnitTests/Meade.net.Telescope.UnitTests.csproj b/Meade.net.Telescope.UnitTests/Meade.net.Telescope.UnitTests.csproj
index 23613aa..930def6 100644
--- a/Meade.net.Telescope.UnitTests/Meade.net.Telescope.UnitTests.csproj
+++ b/Meade.net.Telescope.UnitTests/Meade.net.Telescope.UnitTests.csproj
@@ -104,8 +104,8 @@
..\packages\System.Runtime.CompilerServices.Unsafe.4.5.2\lib\netstandard1.0\System.Runtime.CompilerServices.Unsafe.dll
-
- ..\packages\System.Threading.Tasks.Extensions.4.5.2\lib\portable-net45+win8+wp8+wpa81\System.Threading.Tasks.Extensions.dll
+
+ ..\packages\System.Threading.Tasks.Extensions.4.5.3\lib\netstandard2.0\System.Threading.Tasks.Extensions.dll
diff --git a/Meade.net.Telescope.UnitTests/TelescopeUnitTests.cs b/Meade.net.Telescope.UnitTests/TelescopeUnitTests.cs
index 6f0f5d0..3fb595c 100644
--- a/Meade.net.Telescope.UnitTests/TelescopeUnitTests.cs
+++ b/Meade.net.Telescope.UnitTests/TelescopeUnitTests.cs
@@ -23,6 +23,7 @@ namespace Meade.net.Telescope.UnitTests
private Mock _astroMathsMock;
private ProfileProperties _profileProperties;
+ private ConnectionInfo _connectionInfo;
[SetUp]
public void Setup()
@@ -40,11 +41,15 @@ namespace Meade.net.Telescope.UnitTests
_sharedResourcesWrapperMock = new Mock();
_sharedResourcesWrapperMock.Setup(x => x.SendString(":GZ#")).Returns("DDD*MM’SS");
- _sharedResourcesWrapperMock.Setup(x => x.ReadProfile()).Returns(_profileProperties);
+ _sharedResourcesWrapperMock.Setup(x => x.ReadProfile()).Returns(() =>_profileProperties);
_sharedResourcesWrapperMock.Setup(x => x.Lock(It.IsAny())).Callback(action => { action(); });
_sharedResourcesWrapperMock.Setup(x => x.Lock(It.IsAny>())).Returns>( (func) => func());
_sharedResourcesWrapperMock.Setup(x => x.Lock(It.IsAny>())).Returns>((func) => func());
+ _connectionInfo = new ConnectionInfo {Connections = 1, SameDevice = 1};
+
+ _sharedResourcesWrapperMock.Setup(x => x.Connect("Serial", It.IsAny())).Returns( () => _connectionInfo );
+
_sharedResourcesWrapperMock.Setup(x => x.ReadProfile()).Returns(_profileProperties);
@@ -341,7 +346,7 @@ namespace Meade.net.Telescope.UnitTests
}
[Test]
- public void Connected_Set_WhenConnecting_Then()
+ public void Connected_Set_WhenConnecting_Then_ConnectsToSerialDevice()
{
var productName = "LX2001";
var firmware = string.Empty;
@@ -350,7 +355,7 @@ namespace Meade.net.Telescope.UnitTests
_sharedResourcesWrapperMock.Setup(x => x.FirmwareVersion).Returns(firmware);
_telescope.Connected = true;
- _sharedResourcesWrapperMock.Verify( x => x.Connect("Serial"), Times.Once);
+ _sharedResourcesWrapperMock.Verify( x => x.Connect("Serial", It.IsAny()), Times.Once);
_sharedResourcesWrapperMock.Verify(x => x.SendString(":GZ#"), Times.Once);
_sharedResourcesWrapperMock.Verify(x => x.SendBlind($":Rg{_profileProperties.GuideRateArcSecondsPerSecond:00.0}#"),Times.Once);
@@ -361,26 +366,26 @@ namespace Meade.net.Telescope.UnitTests
public void Connected_Set_SettingTrueWhenTrue_ThenDoesNothing()
{
ConnectTelescope();
- _sharedResourcesWrapperMock.Verify( x => x.Connect(It.IsAny()),Times.Once);
+ _sharedResourcesWrapperMock.Verify( x => x.Connect(It.IsAny(), It.IsAny()),Times.Once);
//act
_telescope.Connected = true;
//assert
- _sharedResourcesWrapperMock.Verify(x => x.Connect(It.IsAny()), Times.Once);
+ _sharedResourcesWrapperMock.Verify(x => x.Connect(It.IsAny(), It.IsAny()), Times.Once);
}
[Test]
public void Connected_Set_SettingFalseWhenTrue_ThenDisconnects()
{
ConnectTelescope();
- _sharedResourcesWrapperMock.Verify(x => x.Connect(It.IsAny()), Times.Once);
+ _sharedResourcesWrapperMock.Verify(x => x.Connect(It.IsAny(), It.IsAny()), Times.Once);
//act
_telescope.Connected = false;
//assert
- _sharedResourcesWrapperMock.Verify(x => x.Disconnect(It.IsAny()), Times.Once());
+ _sharedResourcesWrapperMock.Verify(x => x.Disconnect(It.IsAny(), It.IsAny()), Times.Once());
}
[Test]
@@ -395,7 +400,7 @@ namespace Meade.net.Telescope.UnitTests
_telescope.Connected = true;
//assert
- _sharedResourcesWrapperMock.Verify(x => x.Disconnect(It.IsAny()), Times.Once());
+ _sharedResourcesWrapperMock.Verify(x => x.Disconnect(It.IsAny(), It.IsAny()), Times.Once());
}
[TestCase("Autostar", "30Ab", false)]
@@ -771,6 +776,22 @@ namespace Meade.net.Telescope.UnitTests
_sharedResourcesWrapperMock.Verify(x => x.SendChar(":P#"), 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)
+ {
+ _profileProperties.Precision = desiredPresision;
+
+ _connectionInfo.SameDevice = 2;
+ _connectionInfo.Connections = 2;
+
+ _telescope.Connected = true;
+
+ _sharedResourcesWrapperMock.Verify(x => x.SendChar(":P#"), Times.Never);
+ }
+
[Test]
public void CanSetPark_Get_ReturnsFalse()
{
diff --git a/Meade.net.Telescope.UnitTests/app.config b/Meade.net.Telescope.UnitTests/app.config
index 312e994..ea6ff10 100644
--- a/Meade.net.Telescope.UnitTests/app.config
+++ b/Meade.net.Telescope.UnitTests/app.config
@@ -1,11 +1,15 @@
-
+
-
-
+
+
+
+
+
+
-
+
diff --git a/Meade.net.Telescope.UnitTests/packages.config b/Meade.net.Telescope.UnitTests/packages.config
index b360f81..4c380c0 100644
--- a/Meade.net.Telescope.UnitTests/packages.config
+++ b/Meade.net.Telescope.UnitTests/packages.config
@@ -5,5 +5,5 @@
-
+
\ No newline at end of file
diff --git a/Meade.net.Telescope/Telescope.cs b/Meade.net.Telescope/Telescope.cs
index 913033e..0ddd71b 100644
--- a/Meade.net.Telescope/Telescope.cs
+++ b/Meade.net.Telescope/Telescope.cs
@@ -277,7 +277,6 @@ namespace ASCOM.Meade.net
$"Site {actionParameters} not allowed, must be between 1 and 4");
}
- break;
case "setname":
switch (parames[1])
{
@@ -374,12 +373,11 @@ namespace ASCOM.Meade.net
ReadProfile();
LogMessage("Connected Set", "Connecting to port {0}", _comPort);
- _sharedResourcesWrapper.Connect("Serial");
+ var connectionInfo = _sharedResourcesWrapper.Connect("Serial", DriverId);
try
{
LogMessage("Connected Set", $"Connected to port {_comPort}. Product: {_sharedResourcesWrapper.ProductName} Version:{_sharedResourcesWrapper.FirmwareVersion}");
- SetLongFormat(true);
_userNewerPulseGuiding = IsNewPulseGuidingSupported();
_targetDeclination = InvalidParameter;
_targetRightAscension = InvalidParameter;
@@ -388,16 +386,22 @@ namespace ASCOM.Meade.net
LogMessage("Connected Set", $"New Pulse Guiding Supported: {_userNewerPulseGuiding}");
IsConnected = true;
- if (CanSetGuideRates)
+ if (connectionInfo.SameDevice == 1)
{
- SetNewGuideRate( _guideRate, "Connect" );
- }
+ //These settings are applied only when the first device connects to the telescope.
+ SetLongFormat(true);
- SetTelescopePrecision("Connect");
+ if (CanSetGuideRates)
+ {
+ SetNewGuideRate(_guideRate, "Connect");
+ }
+
+ SetTelescopePrecision("Connect");
+ }
}
catch (Exception)
{
- _sharedResourcesWrapper.Disconnect("Serial");
+ _sharedResourcesWrapper.Disconnect("Serial", DriverId);
throw;
}
}
@@ -409,7 +413,7 @@ namespace ASCOM.Meade.net
else
{
LogMessage("Connected Set", "Disconnecting from port {0}", _comPort);
- _sharedResourcesWrapper.Disconnect("Serial");
+ _sharedResourcesWrapper.Disconnect("Serial", DriverId);
IsConnected = false;
}
}
diff --git a/Meade.net.focuser/Focuser.cs b/Meade.net.focuser/Focuser.cs
index cbd9ad2..81362d9 100644
--- a/Meade.net.focuser/Focuser.cs
+++ b/Meade.net.focuser/Focuser.cs
@@ -5,7 +5,6 @@ using System.Diagnostics;
using System.Runtime.InteropServices;
using ASCOM.Utilities;
using ASCOM.DeviceInterface;
-using System.Globalization;
using System.Collections;
using System.Reflection;
using ASCOM.Meade.net.Wrapper;
@@ -66,12 +65,21 @@ namespace ASCOM.Meade.net
public Focuser()
{
//todo move this out to IOC
- _utilities = new Util(); //Initialise util object
+ var util = new Util(); //Initialise util object
+ _utilities = util;
_sharedResourcesWrapper = new SharedResourcesWrapper();
Initialise();
}
+ public Focuser(IUtil util, ISharedResourcesWrapper sharedResourcesWrapper)
+ {
+ _utilities = util;
+ _sharedResourcesWrapper = sharedResourcesWrapper;
+
+ Initialise();
+ }
+
private void Initialise()
{
//todo move the TraceLogger out to a factory class.
@@ -118,7 +126,7 @@ namespace ASCOM.Meade.net
public string Action(string actionName, string actionParameters)
{
LogMessage("", "Action {0}, parameters {1} not implemented", actionName, actionParameters);
- throw new ActionNotImplementedException("Action " + actionName + " is not implemented by this driver");
+ throw new ActionNotImplementedException();
}
public void CommandBlind(string command, bool raw)
@@ -149,8 +157,7 @@ namespace ASCOM.Meade.net
// 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);
-
- throw new MethodNotImplementedException("CommandString");
+ //throw new ASCOM.MethodNotImplementedException("CommandString");
}
public void Dispose()
@@ -179,17 +186,14 @@ namespace ASCOM.Meade.net
try
{
ReadProfile();
- _sharedResourcesWrapper.Connect("Serial");
+ _sharedResourcesWrapper.Connect("Serial", DriverId);
try
{
- SelectSite(1);
- SetLongFormat(true);
-
IsConnected = true;
}
catch (Exception)
{
- _sharedResourcesWrapper.Disconnect("Serial");
+ _sharedResourcesWrapper.Disconnect("Serial", DriverId);
throw;
}
}
@@ -201,43 +205,12 @@ namespace ASCOM.Meade.net
else
{
LogMessage("Connected Set", "Disconnecting from port {0}", _comPort);
- _sharedResourcesWrapper.Disconnect("Serial");
+ _sharedResourcesWrapper.Disconnect("Serial", DriverId);
IsConnected = false;
}
}
}
- private void SetLongFormat(bool setLongFormat)
- {
- _sharedResourcesWrapper.Lock(() =>
- {
- var result = _sharedResourcesWrapper.SendString(":GZ#");
- //:GZ# Get telescope azimuth
- //Returns: DDD*MM#T or DDD*MM’SS#
- //The current telescope Azimuth depending on the selected precision.
-
- bool isLongFormat = result.Length > 6;
-
- if (isLongFormat != setLongFormat)
- {
- _utilities.WaitForMilliseconds(500);
- _sharedResourcesWrapper.SendBlind(":U#");
- //:U# Toggle between low/hi precision positions
- //Low - RA displays and messages HH:MM.T sDD*MM
- //High - Dec / Az / El displays and messages HH:MM: SS sDD*MM:SS
- // Returns Nothing
- }
- });
- }
-
- private void SelectSite(int site)
- {
- _sharedResourcesWrapper.SendBlind($":W{site}#");
- //:W#
- //Set current site to, an ASCII digit in the range 1..4
- //Returns: Nothing
- }
-
public string Description
{
// TODO customise this device description
@@ -252,10 +225,9 @@ namespace ASCOM.Meade.net
{
get
{
- Version version = Assembly.GetExecutingAssembly().GetName().Version;
// TODO customise this driver description
- string driverInfo = "Information about the driver itself. Version: " + String.Format(CultureInfo.InvariantCulture, "{0}.{1}", version.Major, version.Minor);
- Tl.LogMessage("DriverInfo Get", driverInfo);
+ string driverInfo = $"{Description} .net driver. Version: {DriverVersion}";
+ LogMessage("DriverInfo Get", driverInfo);
return driverInfo;
}
}
@@ -265,8 +237,8 @@ namespace ASCOM.Meade.net
get
{
Version version = Assembly.GetExecutingAssembly().GetName().Version;
- string driverVersion = String.Format(CultureInfo.InvariantCulture, "{0}.{1}", version.Major, version.Minor);
- Tl.LogMessage("DriverVersion Get", driverVersion);
+ string driverVersion = $"{version.Major}.{version.Minor}.{version.Build}.{version.Revision}";
+ LogMessage("DriverVersion Get", driverVersion);
return driverVersion;
}
}
@@ -300,6 +272,8 @@ namespace ASCOM.Meade.net
{
get
{
+ CheckConnected("Absolute Get");
+
Tl.LogMessage("Absolute Get", false.ToString());
return false; // This is a relative focuser
}
@@ -312,6 +286,7 @@ namespace ASCOM.Meade.net
CheckConnected("Halt");
//A single halt command is sometimes missed by the #909 apm, so let's do it a few times to be safe.
+ //todo make this mockable
Stopwatch stopwatch = Stopwatch.StartNew();
while (stopwatch.ElapsedMilliseconds < 1000)
{
@@ -412,6 +387,7 @@ namespace ASCOM.Meade.net
_utilities.WaitForMilliseconds(100);
//A Single focus command sometimes gets lost on the #909, so sending lots of them solves the issue.
+ //todo make this mockable
Stopwatch stopwatch = Stopwatch.StartNew();
while (stopwatch.ElapsedMilliseconds < steps)
{
@@ -568,7 +544,7 @@ namespace ASCOM.Meade.net
{
if (!IsConnected)
{
- throw new NotConnectedException(message);
+ throw new NotConnectedException($"Not connected to focuser when trying to execute: {message}");
}
}
diff --git a/Meade.net.sln b/Meade.net.sln
index a77a62d..e916044 100644
--- a/Meade.net.sln
+++ b/Meade.net.sln
@@ -23,6 +23,8 @@ Project("{930C7802-8A8C-48F9-8165-68863BCCD9DD}") = "Meade.net.Setup", "Meade.ne
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Meade.net.Telescope.UnitTests", "Meade.net.Telescope.UnitTests\Meade.net.Telescope.UnitTests.csproj", "{B7EEEEFD-5BFF-443D-981C-7B8AB5DFDE33}"
EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Meade.net.Focuser.UnitTests", "Meade.net.Focuser.UnitTests\Meade.net.Focuser.UnitTests.csproj", "{A3991FA7-23C3-405A-96F9-5AB03AC58F30}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -120,6 +122,18 @@ Global
{B7EEEEFD-5BFF-443D-981C-7B8AB5DFDE33}.Release|x64.Build.0 = Release|Any CPU
{B7EEEEFD-5BFF-443D-981C-7B8AB5DFDE33}.Release|x86.ActiveCfg = Release|x86
{B7EEEEFD-5BFF-443D-981C-7B8AB5DFDE33}.Release|x86.Build.0 = Release|x86
+ {A3991FA7-23C3-405A-96F9-5AB03AC58F30}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {A3991FA7-23C3-405A-96F9-5AB03AC58F30}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {A3991FA7-23C3-405A-96F9-5AB03AC58F30}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {A3991FA7-23C3-405A-96F9-5AB03AC58F30}.Debug|x64.Build.0 = Debug|Any CPU
+ {A3991FA7-23C3-405A-96F9-5AB03AC58F30}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {A3991FA7-23C3-405A-96F9-5AB03AC58F30}.Debug|x86.Build.0 = Debug|Any CPU
+ {A3991FA7-23C3-405A-96F9-5AB03AC58F30}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {A3991FA7-23C3-405A-96F9-5AB03AC58F30}.Release|Any CPU.Build.0 = Release|Any CPU
+ {A3991FA7-23C3-405A-96F9-5AB03AC58F30}.Release|x64.ActiveCfg = Release|Any CPU
+ {A3991FA7-23C3-405A-96F9-5AB03AC58F30}.Release|x64.Build.0 = Release|Any CPU
+ {A3991FA7-23C3-405A-96F9-5AB03AC58F30}.Release|x86.ActiveCfg = Release|Any CPU
+ {A3991FA7-23C3-405A-96F9-5AB03AC58F30}.Release|x86.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@@ -129,6 +143,7 @@ Global
{AABC96B8-C462-4B3A-9B5F-2929E3CB7A49} = {BF650D97-AF98-4638-9C55-21311C6D88DA}
{AD4959DD-33D7-4C3F-8DB0-7361D8E74A95} = {0958D817-269C-44BE-BEFB-F3E6A409DE91}
{B7EEEEFD-5BFF-443D-981C-7B8AB5DFDE33} = {0958D817-269C-44BE-BEFB-F3E6A409DE91}
+ {A3991FA7-23C3-405A-96F9-5AB03AC58F30} = {0958D817-269C-44BE-BEFB-F3E6A409DE91}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {3C0509DC-C7F5-48DC-920D-DCFD9C879BD2}
diff --git a/Meade.net/ConnectionInfo.cs b/Meade.net/ConnectionInfo.cs
new file mode 100644
index 0000000..4da4c7f
--- /dev/null
+++ b/Meade.net/ConnectionInfo.cs
@@ -0,0 +1,8 @@
+namespace ASCOM.Meade.net
+{
+ public class ConnectionInfo
+ {
+ public int Connections { get; set; }
+ public int SameDevice { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/Meade.net/Meade.net.csproj b/Meade.net/Meade.net.csproj
index eb6cc79..d8277ba 100644
--- a/Meade.net/Meade.net.csproj
+++ b/Meade.net/Meade.net.csproj
@@ -122,6 +122,7 @@
+
Form
@@ -134,6 +135,7 @@
+
Designer
diff --git a/Meade.net/SetupDialogForm.cs b/Meade.net/SetupDialogForm.cs
index 874ecbc..645ca81 100644
--- a/Meade.net/SetupDialogForm.cs
+++ b/Meade.net/SetupDialogForm.cs
@@ -1,6 +1,8 @@
using System;
using System.ComponentModel;
+using System.Diagnostics;
using System.Runtime.InteropServices;
+using System.Text;
using System.Windows.Forms;
namespace ASCOM.Meade.net
@@ -53,7 +55,7 @@ namespace ASCOM.Meade.net
{
cboPrecision.SelectedItem = profileProperties.Precision;
}
- catch (Exception e)
+ catch (Exception)
{
cboPrecision.SelectedItem = "Unchanged";
}
@@ -74,6 +76,7 @@ namespace ASCOM.Meade.net
private void SetupDialogForm_Shown(object sender, EventArgs e)
{
+ Win32Utilities.BringWindowToFront(Handle);
Activate();
}
@@ -92,7 +95,7 @@ namespace ASCOM.Meade.net
lblPercentOfSiderealRate.Text = $"({percentOfSideReal:00.0}% of sidereal rate)";
_guideRateValid = true;
}
- catch (Exception exception)
+ catch (Exception)
{
//Surpressing this exception as if the value is not valid then it's not useful.
_guideRateValid = false;
diff --git a/Meade.net/SetupDialogForm.designer.cs b/Meade.net/SetupDialogForm.designer.cs
index 0f875dd..af1859b 100644
--- a/Meade.net/SetupDialogForm.designer.cs
+++ b/Meade.net/SetupDialogForm.designer.cs
@@ -152,6 +152,7 @@ namespace ASCOM.Meade.net
this.MinimizeBox = false;
this.Name = "SetupDialogForm";
this.SizeGripStyle = System.Windows.Forms.SizeGripStyle.Hide;
+ this.TopMost = true;
this.Shown += new System.EventHandler(this.SetupDialogForm_Shown);
((System.ComponentModel.ISupportInitialize)(this.picASCOM)).EndInit();
this.ResumeLayout(false);
diff --git a/Meade.net/SharedResources.cs b/Meade.net/SharedResources.cs
index 8d27adb..cd5209f 100644
--- a/Meade.net/SharedResources.cs
+++ b/Meade.net/SharedResources.cs
@@ -260,12 +260,15 @@ namespace ASCOM.Meade.net
///
private static readonly Dictionary _connectedDevices = new Dictionary();
+ private static readonly Dictionary _connectedDeviceIds = new Dictionary();
+
+
///
/// This is called in the driver Connect(true) property,
/// it add the device id to the list of devices if it's not there and increments the device count.
///
///
- public static void Connect(string deviceId)
+ public static ConnectionInfo Connect(string deviceId, string driverId)
{
lock (LockObject)
{
@@ -273,6 +276,10 @@ namespace ASCOM.Meade.net
_connectedDevices.Add(deviceId, new DeviceHardware());
_connectedDevices[deviceId].Count++; // increment the value
+ if (!_connectedDeviceIds.ContainsKey(driverId))
+ _connectedDeviceIds.Add(driverId, new DeviceHardware());
+ _connectedDeviceIds[driverId].Count++; // increment the value
+
if (deviceId == "Serial")
{
if (_connectedDevices[deviceId].Count == 1)
@@ -292,10 +299,16 @@ namespace ASCOM.Meade.net
FirmwareVersion = SendString(":GVN#");
}
}
+
+ return new ConnectionInfo
+ {
+ Connections = _connectedDevices[deviceId].Count,
+ SameDevice = _connectedDeviceIds[driverId].Count
+ };
}
}
- public static void Disconnect(string deviceId)
+ public static void Disconnect(string deviceId, string driverId)
{
lock (LockObject)
{
@@ -311,6 +324,11 @@ namespace ASCOM.Meade.net
}
}
}
+
+ if (_connectedDeviceIds.ContainsKey(driverId))
+ {
+ _connectedDeviceIds[driverId].Count--;
+ }
}
}
diff --git a/Meade.net/Win32Utilities.cs b/Meade.net/Win32Utilities.cs
new file mode 100644
index 0000000..2be80b3
--- /dev/null
+++ b/Meade.net/Win32Utilities.cs
@@ -0,0 +1,106 @@
+using System;
+using System.Runtime.InteropServices;
+using System.Text;
+
+namespace ASCOM.Meade.net
+{
+ internal static class Win32Utilities
+ {
+ //Win32 API calls necesary to raise an unowned processs main window
+
+ [DllImport("user32.dll")]
+
+ private static extern bool SetForegroundWindow(IntPtr hWnd);
+
+ [DllImport("user32.dll")]
+ private static extern bool ShowWindowAsync(IntPtr hWnd, int nCmdShow);
+
+ [DllImport("user32.dll")]
+ private static extern bool IsIconic(IntPtr hWnd);
+
+ [DllImport("user32.dll", SetLastError = true)]
+ private static extern bool SystemParametersInfo(uint uiAction, uint uiParam, IntPtr pvParam, uint fWinIni);
+
+ [DllImport("user32.dll", SetLastError = true)]
+ private static extern uint GetWindowThreadProcessId(IntPtr hWnd, IntPtr lpdwProcessId);
+
+ [DllImport("user32.dll")]
+ private static extern IntPtr GetForegroundWindow();
+
+ [DllImport("user32.dll")]
+ private static extern bool AttachThreadInput(uint idAttach, uint idAttachTo, bool fAttach);
+
+ [DllImport("user32.dll")]
+ static extern bool BringWindowToTop(IntPtr hWnd);
+
+ [DllImport("user32.dll")]
+ private static extern int GetWindowText(IntPtr hWnd, StringBuilder lpString, Int32 nMaxCount);
+
+ [DllImport("user32.dll")]
+ private static extern int GetWindowThreadProcessId(IntPtr hWnd, ref Int32 lpdwProcessId);
+
+ [DllImport("User32.dll")]
+ public static extern IntPtr GetParent(IntPtr hWnd);
+
+ private const int SW_HIDE = 0;
+ private const int SW_SHOWNORMAL = 1;
+ private const int SW_NORMAL = 1;
+ private const int SW_SHOWMINIMIZED = 2;
+ private const int SW_SHOWMAXIMIZED = 3;
+ private const int SW_MAXIMIZE = 3;
+ private const int SW_SHOWNOACTIVATE = 4;
+ private const int SW_SHOW = 5;
+ private const int SW_MINIMIZE = 6;
+ private const int SW_SHOWMINNOACTIVE = 7;
+ private const int SW_SHOWNA = 8;
+ private const int SW_RESTORE = 9;
+ private const int SW_SHOWDEFAULT = 10;
+ private const int SW_MAX = 10;
+
+ private const uint SPI_GETFOREGROUNDLOCKTIMEOUT = 0x2000;
+ private const uint SPI_SETFOREGROUNDLOCKTIMEOUT = 0x2001;
+
+ private const int SPIF_SENDCHANGE = 0x2;
+
+
+ public static void BringWindowToFront(IntPtr hWnd)
+ {
+ if (IsIconic(hWnd))
+ ShowWindowAsync(hWnd, SW_RESTORE);
+
+ ShowWindowAsync(hWnd, SW_SHOW);
+
+ SetForegroundWindow(hWnd);
+
+ // Code from Karl E. Peterson, www.mvps.org/vb/sample.htm
+ // Converted to Delphi by Ray Lischner
+ // Published in The Delphi Magazine 55, page 16
+ // Converted to C# by Kevin Gale
+ IntPtr foregroundWindow = GetForegroundWindow();
+ IntPtr Dummy = IntPtr.Zero;
+
+ uint foregroundThreadId = GetWindowThreadProcessId(foregroundWindow, Dummy);
+
+ uint thisThreadId = GetWindowThreadProcessId(hWnd, Dummy);
+
+ if (AttachThreadInput(thisThreadId, foregroundThreadId, true))
+ {
+ BringWindowToTop(hWnd); // IE 5.5 related hack
+ SetForegroundWindow(hWnd);
+ AttachThreadInput(thisThreadId, foregroundThreadId, false);
+ }
+
+ if (GetForegroundWindow() != hWnd)
+ {
+ // Code by Daniel P. Stasinski
+ // Converted to C# by Kevin Gale
+ IntPtr Timeout = IntPtr.Zero;
+ SystemParametersInfo(SPI_GETFOREGROUNDLOCKTIMEOUT, 0, Timeout, 0);
+ SystemParametersInfo(SPI_SETFOREGROUNDLOCKTIMEOUT, 0, Dummy, SPIF_SENDCHANGE);
+ BringWindowToTop(hWnd); // IE 5.5 related hack
+ SetForegroundWindow(hWnd);
+ SystemParametersInfo(SPI_SETFOREGROUNDLOCKTIMEOUT, 0, Timeout, SPIF_SENDCHANGE);
+ }
+ }
+ }
+}
diff --git a/Meade.net/Wrapper/SharedResourcesWrapper.cs b/Meade.net/Wrapper/SharedResourcesWrapper.cs
index 3417ce6..edb1232 100644
--- a/Meade.net/Wrapper/SharedResourcesWrapper.cs
+++ b/Meade.net/Wrapper/SharedResourcesWrapper.cs
@@ -4,8 +4,8 @@ namespace ASCOM.Meade.net.Wrapper
{
public interface ISharedResourcesWrapper
{
- void Connect(string deviceId);
- void Disconnect(string deviceId);
+ ConnectionInfo Connect(string deviceId, string driverId);
+ void Disconnect(string deviceId, string driverId);
string ProductName { get; }
@@ -29,14 +29,14 @@ namespace ASCOM.Meade.net.Wrapper
public class SharedResourcesWrapper : ISharedResourcesWrapper
{
- public void Connect(string deviceId)
+ public ConnectionInfo Connect(string deviceId, string driverId)
{
- SharedResources.Connect( deviceId);
+ return SharedResources.Connect(deviceId, driverId);
}
- public void Disconnect(string deviceId)
+ public void Disconnect(string deviceId, string driverId)
{
- SharedResources.Disconnect(deviceId);
+ SharedResources.Disconnect(deviceId, driverId);
}
public string ProductName => SharedResources.ProductName;