# ASCOM Dome 驱动开发完整指南
## 使用 ASCOM 7.0 和 VB.NET 2022

---

## 目录

1. [准备工作](#准备工作)
2. [创建驱动项目](#创建驱动项目)
3. [实现驱动功能](#实现驱动功能)
4. [测试驱动](#测试驱动)
5. [打包安装程序](#打包安装程序)
6. [发布和分发](#发布和分发)

---

## 准备工作

### Step 1: 安装 ASCOM Platform 7

#### 1.1 下载 ASCOM Platform
- **官方下载地址：** https://ascom-standards.org/Downloads/Index.htm
- **推荐版本：** ASCOM Platform 7.1.3 或更高版本
- **文件名：** `ASCOMPlatform71.exe`（约 60 MB）

#### 1.2 安装步骤
```
1. 双击安装程序
2. 接受许可协议
3. 选择 "Complete" 完整安装（重要！）
4. 必须勾选：
   ✅ Platform Components（平台组件）
   ✅ Developer Components（开发者组件）
   ✅ Omni Simulators（模拟器）
   ✅ Diagnostics Tools（诊断工具）
5. 安装路径默认即可
6. 等待安装完成（约 5-10 分钟）
```

#### 1.3 验证安装
```
开始菜单 → ASCOM → ASCOM Diagnostics
应该能看到诊断工具界面
```

---

### Step 2: 安装 Visual Studio 2022

#### 2.1 下载 Visual Studio 2022
- **官方下载：** https://visualstudio.microsoft.com/downloads/
- **推荐版本：** Community Edition（免费）

#### 2.2 安装工作负载
在安装程序中勾选：
```
✅ .NET desktop development（.NET 桌面开发）
✅ Desktop development with C++（可选，用于高级调试）
```

安装完成后重启计算机。

---

### Step 3: 安装 ASCOM Driver Templates

#### 3.1 在 Visual Studio 中安装模板

**方法一：通过扩展管理器**
```
1. 打开 Visual Studio 2022
2. 菜单：扩展 → 管理扩展
3. 搜索："ASCOM"
4. 找到 "ASCOM Device Driver Templates"
5. 点击"下载"并安装
6. 重启 Visual Studio
```

**方法二：通过 NuGet**
```
工具 → NuGet 包管理器 → 管理解决方案的 NuGet 程序包
搜索：ASCOM.Templates
安装到项目
```

---

## 创建驱动项目

### Step 4: 创建新的 Dome 驱动项目

#### 4.1 启动新项目向导
```
1. Visual Studio 2022 → 文件 → 新建 → 项目
2. 搜索模板："ASCOM"
3. 选择："ASCOM Device Driver (VB.NET)"
4. 点击"下一步"
```

#### 4.2 配置项目信息
```
项目名称：MyDome（替换为你的驱动名称）
位置：选择合适的保存位置
解决方案名称：MyDome
框架：.NET Framework 4.8（推荐）
```

#### 4.3 选择设备类型
```
设备类型选择：Dome
驱动程序 ID：ASCOM.MyDome.Dome
描述：My Custom Dome Driver
```

#### 4.4 项目结构说明
```
MyDome/
├── Driver.vb              # 主驱动类（实现 ASCOM 接口）
├── DriverHardware.vb      # 硬件通信类
├── SetupDialogForm.vb     # 设置对话框
├── SetupDialogForm.Designer.vb
└── My Project/
    ├── AssemblyInfo.vb    # 程序集信息
    └── Settings.settings   # 配置设置
```

---

### Step 5: 配置项目属性

#### 5.1 设置程序集信息
```vb
' 打开 My Project/AssemblyInfo.vb
<Assembly: AssemblyTitle("MyDome ASCOM Driver")>
<Assembly: AssemblyDescription("ASCOM Dome Driver for MyDome")>
<Assembly: AssemblyCompany("Your Company Name")>
<Assembly: AssemblyProduct("MyDome")>
<Assembly: AssemblyCopyright("Copyright © 2025 Your Name")>
<Assembly: AssemblyVersion("1.0.0.0")>
<Assembly: AssemblyFileVersion("1.0.0.0")>
```

#### 5.2 设置为 COM 可见
```
项目属性 → 应用程序 → 程序集信息
✅ 使程序集 COM 可见
```

#### 5.3 配置签名（重要）
```
项目属性 → 签名
✅ 为程序集签名
选择密钥文件：<新建>
密钥文件名：MyDome_Key.snk
✅ 取消勾选"使用密码保护密钥文件"（除非需要）
```

---

## 实现驱动功能

### Step 6: 实现 Driver.vb 主驱动类

#### 6.1 必须实现的属性

在 `Driver.vb` 中实现以下核心属性：

```vbnet
Public Class Dome
    Implements ASCOM.DeviceInterface.IDomeV2
    
    ' ===== 连接状态 =====
    Public Property Connected() As Boolean Implements IDomeV2.Connected
        Get
            Return connectedState
        End Get
        Set(value As Boolean)
            If value Then
                ' 建立连接
                objHardware.Connect(comPort, baudRate)
                connectedState = True
            Else
                ' 断开连接
                objHardware.Disconnect()
                connectedState = False
            End If
        End Set
    End Property
    
    ' ===== 位置信息 =====
    Public ReadOnly Property Altitude() As Double Implements IDomeV2.Altitude
        Get
            ' 返回圆顶海拔高度（度，0-90）
            CheckConnected("Altitude")
            Return objHardware.Altitude
        End Get
    End Property
    
    Public ReadOnly Property Azimuth() As Double Implements IDomeV2.Azimuth
        Get
            ' 返回圆顶方位角（度，0-360）
            CheckConnected("Azimuth")
            Return objHardware.Azimuth
        End Get
    End Property
    
    ' ===== 状态属性 =====
    Public ReadOnly Property AtHome() As Boolean Implements IDomeV2.AtHome
        Get
            ' 圆顶是否在原位
            CheckConnected("AtHome")
            Return objHardware.AtHome
        End Get
    End Property
    
    Public ReadOnly Property AtPark() As Boolean Implements IDomeV2.AtPark
        Get
            ' 圆顶是否已停靠
            CheckConnected("AtPark")
            Return objHardware.AtPark
        End Get
    End Property
    
    Public ReadOnly Property Slewing() As Boolean Implements IDomeV2.Slewing
        Get
            ' 圆顶是否正在转动
            CheckConnected("Slewing")
            Return objHardware.Slewing
        End Get
    End Property
    
    ' ===== 快门状态 =====
    Public ReadOnly Property ShutterStatus() As ShutterState Implements IDomeV2.ShutterStatus
        Get
            ' 返回快门状态
            ' shutterOpen = 0（打开）
            ' shutterClosed = 1（关闭）
            ' shutterOpening = 2（正在打开）
            ' shutterClosing = 3（正在关闭）
            ' shutterError = 4（错误）
            CheckConnected("ShutterStatus")
            Return objHardware.ShutterStatus
        End Get
    End Property
    
    ' ===== 能力属性 =====
    Public ReadOnly Property CanFindHome() As Boolean Implements IDomeV2.CanFindHome
        Get
            Return True ' 如果支持归位功能
        End Get
    End Property
    
    Public ReadOnly Property CanPark() As Boolean Implements IDomeV2.CanPark
        Get
            Return True ' 如果支持停靠功能
        End Get
    End Property
    
    Public ReadOnly Property CanSetAzimuth() As Boolean Implements IDomeV2.CanSetAzimuth
        Get
            Return True ' 如果可以设置方位角
        End Get
    End Property
    
    Public ReadOnly Property CanSetShutter() As Boolean Implements IDomeV2.CanSetShutter
        Get
            Return True ' 如果有快门控制
        End Get
    End Property
    
    Public ReadOnly Property CanSlave() As Boolean Implements IDomeV2.CanSlave
        Get
            Return True ' 如果支持跟随望远镜
        End Get
    End Property
    
    Public ReadOnly Property CanSyncAzimuth() As Boolean Implements IDomeV2.CanSyncAzimuth
        Get
            Return True ' 如果支持同步方位角
        End Get
    End Property
    
    ' ===== 辅助方法 =====
    Private Sub CheckConnected(propertyOrMethod As String)
        If Not connectedState Then
            Throw New ASCOM.NotConnectedException(propertyOrMethod & " - Device is not connected")
        End If
    End Sub
End Class
```

#### 6.2 必须实现的方法

```vbnet
Public Class Dome
    ' ===== 控制方法 =====
    
    Public Sub AbortSlew() Implements IDomeV2.AbortSlew
        ' 立即停止圆顶转动
        CheckConnected("AbortSlew")
        objHardware.AbortSlew()
    End Sub
    
    Public Sub CloseShutter() Implements IDomeV2.CloseShutter
        ' 关闭快门
        CheckConnected("CloseShutter")
        If Not CanSetShutter Then
            Throw New ASCOM.MethodNotImplementedException("CloseShutter")
        End If
        objHardware.CloseShutter()
    End Sub
    
    Public Sub FindHome() Implements IDomeV2.FindHome
        ' 执行归位操作
        CheckConnected("FindHome")
        If Not CanFindHome Then
            Throw New ASCOM.MethodNotImplementedException("FindHome")
        End If
        objHardware.FindHome()
    End Sub
    
    Public Sub OpenShutter() Implements IDomeV2.OpenShutter
        ' 打开快门
        CheckConnected("OpenShutter")
        If Not CanSetShutter Then
            Throw New ASCOM.MethodNotImplementedException("OpenShutter")
        End If
        objHardware.OpenShutter()
    End Sub
    
    Public Sub Park() Implements IDomeV2.Park
        ' 停靠圆顶
        CheckConnected("Park")
        If Not CanPark Then
            Throw New ASCOM.MethodNotImplementedException("Park")
        End If
        objHardware.Park()
    End Sub
    
    Public Sub SetPark() Implements IDomeV2.SetPark
        ' 设置当前位置为停靠位置
        CheckConnected("SetPark")
        If Not CanPark Then
            Throw New ASCOM.MethodNotImplementedException("SetPark")
        End If
        objHardware.SetPark()
    End Sub
    
    Public Sub SlewToAzimuth(Azimuth As Double) Implements IDomeV2.SlewToAzimuth
        ' 转动圆顶到指定方位角
        CheckConnected("SlewToAzimuth")
        If Not CanSetAzimuth Then
            Throw New ASCOM.MethodNotImplementedException("SlewToAzimuth")
        End If
        
        ' 验证方位角范围
        If Azimuth < 0 Or Azimuth >= 360 Then
            Throw New ASCOM.InvalidValueException("SlewToAzimuth", Azimuth.ToString(), "0 to 359.99")
        End If
        
        objHardware.SlewToAzimuth(Azimuth)
    End Sub
    
    Public Sub SyncToAzimuth(Azimuth As Double) Implements IDomeV2.SyncToAzimuth
        ' 同步当前方位角
        CheckConnected("SyncToAzimuth")
        If Not CanSyncAzimuth Then
            Throw New ASCOM.MethodNotImplementedException("SyncToAzimuth")
        End If
        
        ' 验证方位角范围
        If Azimuth < 0 Or Azimuth >= 360 Then
            Throw New ASCOM.InvalidValueException("SyncToAzimuth", Azimuth.ToString(), "0 to 359.99")
        End If
        
        objHardware.SyncToAzimuth(Azimuth)
    End Sub
    
    ' ===== 从属模式 =====
    Public Property Slaved() As Boolean Implements IDomeV2.Slaved
        Get
            CheckConnected("Slaved")
            Return objHardware.Slaved
        End Get
        Set(value As Boolean)
            CheckConnected("Slaved")
            If Not CanSlave Then
                Throw New ASCOM.PropertyNotImplementedException("Slaved", True)
            End If
            objHardware.Slaved = value
        End Set
    End Property
    
    Public Sub SlewToAltitude(Altitude As Double) Implements IDomeV2.SlewToAltitude
        ' 部分圆顶支持仰角控制
        Throw New ASCOM.MethodNotImplementedException("SlewToAltitude")
    End Sub
End Class
```

---

### Step 7: 实现 DriverHardware.vb 硬件通信类

#### 7.1 串口通信框架

```vbnet
Imports System.IO.Ports

Public Class DomeHardware
    ' ===== 私有字段 =====
    Private serialPort As SerialPort
    Private _azimuth As Double
    Private _slewing As Boolean
    Private _shutterStatus As ShutterState
    Private _atHome As Boolean
    Private _atPark As Boolean
    Private _slaved As Boolean
    
    ' 配置参数
    Private _comPort As String
    Private _baudRate As Integer
    Private _timeout As Integer = 2000 ' 毫秒
    
    ' ===== 连接管理 =====
    Public Sub Connect(portName As String, baudRate As Integer)
        Try
            serialPort = New SerialPort()
            serialPort.PortName = portName
            serialPort.BaudRate = baudRate
            serialPort.DataBits = 8
            serialPort.Parity = Parity.None
            serialPort.StopBits = StopBits.One
            serialPort.Handshake = Handshake.None
            serialPort.ReadTimeout = _timeout
            serialPort.WriteTimeout = _timeout
            
            serialPort.Open()
            
            ' 初始化硬件
            InitializeHardware()
            
        Catch ex As Exception
            Throw New ASCOM.DriverException("无法连接到设备: " & ex.Message)
        End Try
    End Sub
    
    Public Sub Disconnect()
        Try
            If serialPort IsNot Nothing AndAlso serialPort.IsOpen Then
                ' 发送关闭命令（如果需要）
                SendCommand("DISCONNECT")
                serialPort.Close()
            End If
        Catch ex As Exception
            ' 忽略断开时的错误
        End Try
    End Sub
    
    Private Sub InitializeHardware()
        ' 初始化硬件，读取当前状态
        Try
            ' 示例：请求当前位置
            Dim response As String = SendCommand("GET_STATUS")
            ParseStatus(response)
        Catch ex As Exception
            Throw New ASCOM.DriverException("硬件初始化失败: " & ex.Message)
        End Try
    End Sub
    
    ' ===== 命令发送 =====
    Private Function SendCommand(command As String) As String
        If serialPort Is Nothing OrElse Not serialPort.IsOpen Then
            Throw New ASCOM.NotConnectedException("设备未连接")
        End If
        
        Try
            ' 清空缓冲区
            serialPort.DiscardInBuffer()
            serialPort.DiscardOutBuffer()
            
            ' 发送命令（根据你的硬件协议调整）
            serialPort.WriteLine(command & vbCr)
            
            ' 读取响应
            Dim response As String = serialPort.ReadLine()
            Return response.Trim()
            
        Catch ex As TimeoutException
            Throw New ASCOM.DriverException("命令超时: " & command)
        Catch ex As Exception
            Throw New ASCOM.DriverException("通信错误: " & ex.Message)
        End Try
    End Function
    
    ' ===== 位置控制 =====
    Public Sub SlewToAzimuth(targetAzimuth As Double)
        Try
            ' 发送转动命令（根据你的硬件协议）
            Dim command As String = String.Format("GA{0:000.0}", targetAzimuth)
            SendCommand(command)
            
            _slewing = True
            _azimuth = targetAzimuth
            
            ' 可选：启动后台线程监控转动状态
            StartSlewMonitor()
            
        Catch ex As Exception
            Throw New ASCOM.DriverException("转动失败: " & ex.Message)
        End Try
    End Sub
    
    Public Sub AbortSlew()
        Try
            SendCommand("ABORT")
            _slewing = False
        Catch ex As Exception
            Throw New ASCOM.DriverException("停止转动失败: " & ex.Message)
        End Try
    End Sub
    
    Public Sub SyncToAzimuth(azimuth As Double)
        ' 同步当前方位角（不实际移动）
        _azimuth = azimuth
    End Sub
    
    ' ===== 快门控制 =====
    Public Sub OpenShutter()
        Try
            SendCommand("SO") ' Shutter Open
            _shutterStatus = ShutterState.shutterOpening
            
            ' 启动后台线程监控快门状态
            StartShutterMonitor()
            
        Catch ex As Exception
            _shutterStatus = ShutterState.shutterError
            Throw New ASCOM.DriverException("打开快门失败: " & ex.Message)
        End Try
    End Sub
    
    Public Sub CloseShutter()
        Try
            SendCommand("SC") ' Shutter Close
            _shutterStatus = ShutterState.shutterClosing
            
            StartShutterMonitor()
            
        Catch ex As Exception
            _shutterStatus = ShutterState.shutterError
            Throw New ASCOM.DriverException("关闭快门失败: " & ex.Message)
        End Try
    End Sub
    
    ' ===== 归位和停靠 =====
    Public Sub FindHome()
        Try
            SendCommand("HOME")
            _slewing = True
            _atHome = False
        Catch ex As Exception
            Throw New ASCOM.DriverException("归位失败: " & ex.Message)
        End Try
    End Sub
    
    Public Sub Park()
        Try
            SendCommand("PARK")
            _slewing = True
            _atPark = False
        Catch ex As Exception
            Throw New ASCOM.DriverException("停靠失败: " & ex.Message)
        End Try
    End Sub
    
    Public Sub SetPark()
        ' 设置当前位置为停靠位置
        Try
            SendCommand("SET_PARK")
        Catch ex As Exception
            Throw New ASCOM.DriverException("设置停靠位置失败: " & ex.Message)
        End Try
    End Sub
    
    ' ===== 状态监控 =====
    Private Sub StartSlewMonitor()
        ' 在后台线程中监控转动状态
        Dim monitorThread As New Threading.Thread(AddressOf MonitorSlewing)
        monitorThread.IsBackground = True
        monitorThread.Start()
    End Sub
    
    Private Sub MonitorSlewing()
        While _slewing
            Try
                Dim status As String = SendCommand("GET_AZIMUTH")
                ' 解析状态，更新 _azimuth 和 _slewing
                ParseAzimuthStatus(status)
                Threading.Thread.Sleep(500) ' 每 500ms 查询一次
            Catch ex As Exception
                ' 错误处理
                _slewing = False
                Exit While
            End Try
        End While
    End Sub
    
    Private Sub ParseAzimuthStatus(status As String)
        ' 根据你的硬件协议解析状态
        ' 示例：status = "AZ:123.5,SLEWING:0"
        Try
            Dim parts() As String = status.Split(","c)
            _azimuth = Double.Parse(parts(0).Split(":"c)(1))
            _slewing = (parts(1).Split(":"c)(1) = "1")
        Catch ex As Exception
            ' 解析错误
        End Try
    End Sub
    
    ' ===== 属性读取 =====
    Public ReadOnly Property Azimuth() As Double
        Get
            ' 如果需要实时读取，可以发送查询命令
            ' Dim response As String = SendCommand("GET_AZIMUTH")
            ' ParseAzimuthStatus(response)
            Return _azimuth
        End Get
    End Property
    
    Public ReadOnly Property Slewing() As Boolean
        Get
            Return _slewing
        End Get
    End Property
    
    Public ReadOnly Property ShutterStatus() As ShutterState
        Get
            Return _shutterStatus
        End Get
    End Property
    
    Public ReadOnly Property AtHome() As Boolean
        Get
            Return _atHome
        End Get
    End Property
    
    Public ReadOnly Property AtPark() As Boolean
        Get
            Return _atPark
        End Get
    End Property
    
    Public ReadOnly Property Altitude() As Double
        Get
            ' 如果圆顶不支持仰角，返回 0
            Return 0
        End Get
    End Property
    
    Public Property Slaved() As Boolean
        Get
            Return _slaved
        End Get
        Set(value As Boolean)
            _slaved = value
        End Set
    End Property
End Class
```

---

### Step 8: 实现设置对话框

#### 8.1 设计 SetupDialogForm 界面

打开 `SetupDialogForm.vb`（双击在设计器中打开）：

```
控件布局：
┌────────────────────────────┐
│ COM Port:  [ComboBox▼]    │
│ Baud Rate: [ComboBox▼]    │
│ Dome Radius (m): [TextBox]│
│                            │
│  [Test Connection] [OK] [Cancel] │
└────────────────────────────┘
```

#### 8.2 实现设置对话框代码

```vbnet
Public Class SetupDialogForm
    Private Sub SetupDialogForm_Load(sender As Object, e As EventArgs) Handles MyBase.Load
        ' 加载保存的设置
        txtDomeRadius.Text = Dome.domeRadius.ToString()
        
        ' 填充可用 COM 口
        cboComPort.Items.Clear()
        For Each portName As String In System.IO.Ports.SerialPort.GetPortNames()
            cboComPort.Items.Add(portName)
        Next
        
        ' 设置当前选择
        If Dome.comPort <> "" Then
            cboComPort.SelectedItem = Dome.comPort
        End If
        
        ' 填充波特率选项
        cboBaudRate.Items.Clear()
        cboBaudRate.Items.AddRange(New Object() {2400, 4800, 9600, 19200, 38400, 57600, 115200})
        cboBaudRate.SelectedItem = Dome.baudRate
    End Sub
    
    Private Sub btnOK_Click(sender As Object, e As EventArgs) Handles btnOK.Click
        ' 验证输入
        If cboComPort.SelectedItem Is Nothing Then
            MessageBox.Show("请选择 COM 端口", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error)
            Return
        End If
        
        ' 保存设置
        Dome.comPort = cboComPort.SelectedItem.ToString()
        Dome.baudRate = CInt(cboBaudRate.SelectedItem)
        Dome.domeRadius = CDbl(txtDomeRadius.Text)
        
        Me.DialogResult = DialogResult.OK
        Me.Close()
    End Sub
    
    Private Sub btnCancel_Click(sender As Object, e As EventArgs) Handles btnCancel.Click
        Me.DialogResult = DialogResult.Cancel
        Me.Close()
    End Sub
    
    Private Sub btnTest_Click(sender As Object, e As EventArgs) Handles btnTest.Click
        ' 测试连接
        Try
            Dim testPort As New System.IO.Ports.SerialPort()
            testPort.PortName = cboComPort.SelectedItem.ToString()
            testPort.BaudRate = CInt(cboBaudRate.SelectedItem)
            testPort.Open()
            testPort.Close()
            
            MessageBox.Show("连接测试成功！", "成功", MessageBoxButtons.OK, MessageBoxIcon.Information)
        Catch ex As Exception
            MessageBox.Show("连接测试失败: " & ex.Message, "错误", MessageBoxButtons.OK, MessageBoxIcon.Error)
        End Try
    End Sub
End Class
```

---

### Step 9: 配置驱动参数（Profile 存储）

在 `Driver.vb` 中添加配置存储：

```vbnet
Public Class Dome
    ' ===== ASCOM Profile 存储 =====
    Private Shared driverID As String = "ASCOM.MyDome.Dome"
    Private Shared driverDescription As String = "My Custom Dome Driver"
    
    Public Shared Property comPort() As String
        Get
            Return GetProfile("COM Port", "COM1")
        End Get
        Set(value As String)
            WriteProfile("COM Port", value)
        End Set
    End Property
    
    Public Shared Property baudRate() As Integer
        Get
            Return CInt(GetProfile("Baud Rate", "9600"))
        End Get
        Set(value As Integer)
            WriteProfile("Baud Rate", value.ToString())
        End Set
    End Property
    
    Public Shared Property domeRadius() As Double
        Get
            Return CDbl(GetProfile("Dome Radius", "2000.0"))
        End Get
        Set(value As Double)
            WriteProfile("Dome Radius", value.ToString())
        End Set
    End Property
    
    ' ===== Profile 读写方法 =====
    Private Shared Function GetProfile(key As String, defaultValue As String) As String
        Using profile As New ASCOM.Utilities.Profile()
            profile.DeviceType = "Dome"
            Return profile.GetValue(driverID, key, "", defaultValue)
        End Using
    End Function
    
    Private Shared Sub WriteProfile(key As String, value As String)
        Using profile As New ASCOM.Utilities.Profile()
            profile.DeviceType = "Dome"
            profile.WriteValue(driverID, key, value)
        End Using
    End Sub
End Class
```

---

## 测试驱动

### Step 10: 编译驱动

#### 10.1 设置编译配置
```
生成 → 配置管理器
平台：x86（32位）或 Any CPU
配置：Release
```

#### 10.2 编译项目
```
生成 → 生成解决方案（Ctrl+Shift+B）

确保编译成功：
========== 生成: 成功 1 个，失败 0 个，最新 0 个，跳过 0 个 ==========
```

---

### Step 11: 注册驱动（COM 注册）

#### 11.1 以管理员身份打开命令提示符
```
开始菜单 → 搜索 "cmd" → 右键 → 以管理员身份运行
```

#### 11.2 注册 DLL
```batch
cd C:\Your\Project\Path\MyDome\bin\Release
regasm MyDome.dll /codebase /tlb
```

**成功提示：**
```
RegAsm : warning RA0000 : Registering an unsigned assembly with /codebase can cause
your assembly to interfere with other applications that may be installed on the same
computer. The /codebase switch is intended to be used only with signed assemblies.
Please give your assembly a strong name and re-register it.
Types registered successfully
```

---

### Step 12: 使用 ASCOM Diagnostics 测试

#### 12.1 打开诊断工具
```
开始菜单 → ASCOM → ASCOM Diagnostics
```

#### 12.2 选择驱动
```
1. 点击 "Choose..." 按钮
2. 从列表中选择：ASCOM.MyDome.Dome
3. 点击 "OK"
```

#### 12.3 测试功能
```
基本测试：
✅ Properties → 打开设置对话框
✅ Connect → 建立连接
✅ 测试各项功能（如果有硬件）
✅ Disconnect → 断开连接

高级测试：
- 使用 Conform Universal 进行符合性测试
```

---

### Step 13: 使用天文软件测试

#### 13.1 测试软件推荐
- **Cartes du Ciel (免费)：** https://www.ap-i.net/skychart/
- **TheSky X Professional Edition**
- **MaxIm DL**

#### 13.2 在软件中配置驱动
```
1. 打开天文软件
2. 设备设置 → Dome
3. ASCOM 设备列表 → 选择 "MyDome"
4. 连接并测试控制功能
```

---

## 打包安装程序

### Step 14: 安装 Inno Setup

#### 14.1 下载 Inno Setup
- **官方地址：** https://jrsoftware.org/isdl.php
- **推荐版本：** Inno Setup 6.x Unicode

#### 14.2 下载文件
```
主程序：innosetup-6.3.3-unicode.exe（约 3 MB）
QuickStart Pack：is-qsp-6.3.3.exe（必须安装）
```

#### 14.3 安装步骤
```
1. 运行 innosetup-6.3.3-unicode.exe
2. 接受许可协议
3. 选择安装路径（默认即可）
4. ✅ Install Inno Setup Preprocessor
5. 完成主程序安装

6. 运行 is-qsp-6.3.3.exe
7. 自动识别 Inno Setup 路径
8. 确认安装 QuickStart Pack
```

---

### Step 15: 使用 ASCOM 脚本生成器

#### 15.1 启动脚本生成器
```
开始菜单 → ASCOM → Driver Installer Script Generator
```

#### 15.2 填写应用信息
```
Application Name: MyDome
Version: 1.0.0
Publisher: Your Name or Company
Publisher URL: http://yourwebsite.com

Device Type: Dome
Driver ProgID: ASCOM.MyDome.Dome
```

#### 15.3 添加驱动文件
```
Main Files:
- Source: C:\YourPath\MyDome\bin\Release\MyDome.dll
  Flags: regserver sharedfile

Dependencies (如果需要):
- ASCOM.Utilities.dll
- ASCOM.Exceptions.dll
```

#### 15.4 设置平台要求
```
最低 ASCOM Platform 版本：
Platform 6.x 兼容：6.0
Platform 7.x 专用：7.0

推荐设置：6.0（最大兼容性）
```

#### 15.5 生成脚本
```
点击 "Generate Script"
保存为：MyDome_Setup.iss
```

---

### Step 16: 编辑安装脚本

#### 16.1 打开脚本文件
```
右键 MyDome_Setup.iss → 编辑（用 Inno Setup 编译器打开）
```

#### 16.2 完整脚本示例

```ini
; ASCOM Dome Driver Installer Script
; Generated by ASCOM Driver Installer Script Generator

#define REQUIRED_PLATFORM_VERSION "6.0"

[Setup]
AppId={{生成的GUID，不要修改}}
AppName=MyDome ASCOM Driver
AppVersion=1.0.0
AppPublisher=Your Name
AppPublisherURL=http://yourwebsite.com
AppSupportURL=http://yourwebsite.com/support
AppUpdatesURL=http://yourwebsite.com/updates
DefaultDirName={pf}\ASCOM\Dome
DefaultGroupName=ASCOM Dome Drivers
OutputDir=.\Output
OutputBaseFilename=MyDome_Setup_v1.0.0
Compression=lzma2
SolidCompression=yes
MinVersion=6.1
PrivilegesRequired=admin
UninstallDisplayIcon={app}\MyDome.dll

[Languages]
Name: "english"; MessagesFile: "compiler:Default.isl"
Name: "chinese"; MessagesFile: "compiler:Languages\ChineseSimplified.isl"

[Files]
; 主驱动 DLL
Source: "C:\YourPath\MyDome\bin\Release\MyDome.dll"; \
  DestDir: "{app}"; \
  Flags: regserver sharedfile ignoreversion

; 依赖库（如果需要）
Source: "C:\YourPath\MyDome\bin\Release\MyDome.tlb"; \
  DestDir: "{app}"; \
  Flags: sharedfile ignoreversion

; 文档
Source: "C:\YourPath\MyDome\README.txt"; \
  DestDir: "{app}"; \
  Flags: isreadme

[Registry]
Root: HKCR; Subkey: "ASCOM.MyDome.Dome"; \
  ValueType: string; ValueName: ""; \
  ValueData: "MyDome ASCOM Driver"

Root: HKLM; Subkey: "Software\ASCOM\Dome Drivers\MyDome.Dome"; \
  ValueType: string; ValueName: ""; \
  ValueData: "MyDome ASCOM Driver"

[Code]
// ASCOM Platform 版本检查
function InitializeSetup(): Boolean;
var
  PlatformVersion: String;
  RequiredVersion: String;
begin
  Result := True;
  RequiredVersion := '{#REQUIRED_PLATFORM_VERSION}';
  
  // 检查 Platform 6.x
  if RegQueryStringValue(HKLM, 
    'Software\ASCOM\Platform', 
    'PlatformVersion', 
    PlatformVersion) then
  begin
    if CompareStr(PlatformVersion, RequiredVersion) >= 0 then
      Exit;
  end;
  
  // 检查 Platform 7.x
  if RegQueryStringValue(HKLM, 
    'Software\ASCOM\Platform 7', 
    'PlatformVersion', 
    PlatformVersion) then
  begin
    if CompareStr(PlatformVersion, RequiredVersion) >= 0 then
      Exit;
  end;
  
  // 未找到合适版本
  MsgBox('ASCOM Platform ' + RequiredVersion + ' or later is required.' + #13#10 + 
         'Please install it from https://ascom-standards.org', 
         mbError, MB_OK);
  Result := False;
end;
```

---

### Step 17: 编译安装包

#### 17.1 使用 Inno Setup 编译
```
Inno Setup Compiler:
1. 打开 MyDome_Setup.iss
2. Build → Compile（或按 F9）
3. 等待编译完成
```

**编译输出：**
```
Successful compile (5.2 sec). Resulting Setup program filename is:
C:\YourPath\Output\MyDome_Setup_v1.0.0.exe
```

#### 17.2 测试安装包
```
1. 双击 MyDome_Setup_v1.0.0.exe
2. 按照向导完成安装
3. 验证驱动在 ASCOM Chooser 中可见
4. 测试卸载功能
```

---

## 发布和分发

### Step 18: 准备发布材料

#### 18.1 必须文件
```
✅ MyDome_Setup_v1.0.0.exe（安装程序）
✅ README.md（说明文档）
✅ LICENSE.txt（许可协议）
✅ CHANGELOG.md（版本历史）
```

#### 18.2 README.md 模板

```markdown
# MyDome ASCOM Driver v1.0.0

## 概述
这是一个用于 MyDome 圆顶的 ASCOM 驱动程序。

## 系统要求
- Windows 7 或更高版本
- ASCOM Platform 6.0 或更高版本
- .NET Framework 4.8

## 安装步骤
1. 安装 ASCOM Platform（如果尚未安装）
2. 运行 MyDome_Setup_v1.0.0.exe
3. 按照向导完成安装

## 连接设置
1. 打开任意 ASCOM 兼容软件
2. 选择 Dome 设备 → ASCOM.MyDome.Dome
3. 配置 COM 口和波特率
4. 点击"连接"

## 支持的功能
- ✅ 方位角控制（0-360°）
- ✅ 快门开关控制
- ✅ 归位功能
- ✅ 停靠功能
- ✅ 望远镜跟随模式

## 技术支持
- Email: support@yourwebsite.com
- Website: http://yourwebsite.com
```

---

### Step 19: 数字签名（可选但推荐）

#### 19.1 获取代码签名证书
```
购买途径：
- Sectigo (原 Comodo)
- DigiCert
- GlobalSign

证书类型：Code Signing Certificate
价格：约 $100-300/年
```

#### 19.2 签名工具配置
```
Inno Setup:
Tools → Configure Sign Tools
Name: signtool
Command: "C:\Program Files (x86)\Windows Kits\10\bin\x64\signtool.exe" 
  sign /f "C:\MyCert.pfx" /p "password" 
  /t http://timestamp.digicert.com $f
```

#### 19.3 在脚本中启用签名
```ini
[Setup]
SignTool=signtool
SignedUninstaller=yes
```

---

### Step 20: 发布驱动

#### 20.1 发布渠道

**官方渠道：**
```
ASCOM 驱动仓库：
提交到：https://github.com/ASCOMInitiative/ASCOMPlatform
```

**个人渠道：**
```
✅ 个人网站
✅ GitHub Releases
✅ 天文论坛（如 Cloudy Nights）
✅ 制造商网站
```

#### 20.2 GitHub Release 示例
```bash
# 创建 Release
1. 在 GitHub 仓库创建新 Tag：v1.0.0
2. 上传文件：
   - MyDome_Setup_v1.0.0.exe
   - README.md
   - CHANGELOG.md
3. 填写 Release Notes
4. 发布 Release
```

---

## 附录

### A. 常见问题排查

#### A.1 注册失败
```
问题：regasm 返回错误
解决：
1. 以管理员身份运行命令提示符
2. 确保 .NET Framework 已安装
3. 检查 DLL 路径是否正确
```

#### A.2 驱动在 Chooser 中不显示
```
问题：ASCOM Chooser 找不到驱动
解决：
1. 运行 ASCOM Diagnostics 检查注册
2. 检查注册表：HKLM\Software\ASCOM\Dome Drivers
3. 重新注册 DLL
```

#### A.3 连接失败
```
问题：无法连接到硬件
排查：
1. 检查 COM 口是否被占用
2. 验证波特率设置
3. 测试串口通信（用串口工具）
4. 检查硬件是否上电
```

---

### B. 调试技巧

#### B.1 启用日志记录
```vbnet
' 在 DriverHardware.vb 中添加
Private Sub Log(message As String)
    Dim logPath As String = "C:\ASCOM_Logs\MyDome.log"
    System.IO.File.AppendAllText(logPath, 
        DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") & " - " & message & vbCrLf)
End Sub
```

#### B.2 使用断点调试
```
Visual Studio:
1. 设置断点（F9）
2. 附加到进程：调试 → 附加到进程
3. 选择调用驱动的应用程序进程
4. 触发驱动功能，断点会命中
```

---

### C. 性能优化建议

#### C.1 减少串口通信延迟
```vbnet
' 使用异步读写
serialPort.ReadTimeout = 1000
serialPort.WriteTimeout = 1000

' 批量发送命令
Private commandQueue As New Queue(Of String)
```

#### C.2 缓存状态
```vbnet
' 避免频繁查询硬件
Private _lastAzimuthUpdate As DateTime
Private _azimuthCache As Double

Public ReadOnly Property Azimuth() As Double
    Get
        If (DateTime.Now - _lastAzimuthUpdate).TotalSeconds > 1 Then
            _azimuthCache = QueryHardwareAzimuth()
            _lastAzimuthUpdate = DateTime.Now
        End If
        Return _azimuthCache
    End Get
End Property
```

---

### D. 兼容性说明

#### D.1 Platform 版本兼容
```
Platform 6.x：
- 需要 .NET Framework 4.0+
- 接口：IDomeV2

Platform 7.x：
- 需要 .NET Framework 4.8+
- 接口：IDomeV2（相同）
- 新增：异步方法支持
```

#### D.2 操作系统兼容
```
✅ Windows 7 SP1
✅ Windows 8/8.1
✅ Windows 10
✅ Windows 11
❌ Windows XP（不支持 .NET 4.x）
```

---

### E. 资源链接

#### E.1 官方文档
- **ASCOM 标准：** https://ascom-standards.org/
- **IDomeV2 接口：** https://ascom-standards.org/Help/Developer/html/T_ASCOM_DeviceInterface_IDomeV2.htm
- **驱动开发指南：** https://ascom-standards.org/COMDeveloper/Index.htm

#### E.2 开发工具
- **Visual Studio：** https://visualstudio.microsoft.com/
- **Inno Setup：** https://jrsoftware.org/
- **NuGet ASCOM：** https://www.nuget.org/packages?q=ASCOM

#### E.3 社区资源
- **ASCOM 论坛：** https://ascomtalk.groups.io/
- **GitHub：** https://github.com/ASCOMInitiative/
- **Stack Overflow：** 标签 `ascom`

---

## 结语

恭喜你完成了 ASCOM Dome 驱动的完整开发流程！

**后续建议：**
1. 持续测试和优化性能
2. 收集用户反馈
3. 定期更新驱动版本
4. 参与 ASCOM 社区交流

**技术支持：**
如有问题，请访问 ASCOM 论坛或查阅官方文档。

---

*文档版本：1.0*  
*最后更新：2025-10-26*
