Documentation
¶
Overview ¶
Package unihedron is a pure-Go driver for Unihedron Sky Quality Meter (SQM) devices over their FTDI USB-serial link: the SQM-LU and (over the same ASCII protocol) the SQM-LU-DL and SQM-LE. Like the Pegasus focusers — and unlike the ZWO/Astroasis USB-HID accessories — the SQM-LU presents itself as an FTDI virtual COM port (an OS serial device), and the protocol is plain ASCII: single-character command types (e.g. "rx", "ix", "cx"), each reply terminated with "\r\n".
The command set is Unihedron's published SQM-LU serial protocol (section 8, "Commands and responses", of the SQM-LU Operator's Manual). The transport opens the FTDI virtual COM port at 115200 8N1 and does line I/O via go.bug.st/serial — no vendor library, no raw-USB FTDI reimplementation. It uses only the library's pure-Go paths (port I/O everywhere; the USB-VID enumerator off macOS, device-name matching on macOS), so it builds for any target with CGO_ENABLED=0.
Index ¶
- Constants
- type Calibration
- type DeviceInfo
- type Discovered
- type IntervalSettings
- type Reading
- type SQM
- func (s *SQM) Calibration() (Calibration, error)
- func (s *SQM) Close() error
- func (s *SQM) Command(prefix byte, cmd string) (string, error)
- func (s *SQM) Info() DeviceInfo
- func (s *SQM) IntervalSettings() (IntervalSettings, error)
- func (s *SQM) Reading() (Reading, error)
- func (s *SQM) UnaveragedReading() (Reading, error)
- func (s *SQM) UnitInfo() (UnitInfo, error)
- type Transport
- type UnitInfo
Constants ¶
const ( VID uint16 = 0x0403 Baud = 115200 )
FTDI vendor ID (the SQM-LU's USB-serial bridge) and the SQM-LU line speed.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type Calibration ¶
type Calibration struct {
LightCalOffset float64 // light calibration offset, mag/arcsec²
DarkCalPeriod float64 // dark calibration time period, seconds
LightCalTempC float64 // temperature during light calibration, °C
SensorOffset float64 // factory reference light-source offset (≈8.71), mag/arcsec²
DarkCalTempC float64 // temperature during dark calibration, °C
}
Calibration is a decoded "cx" calibration-information response (SQM-LU manual §8.3.1).
type DeviceInfo ¶
type DeviceInfo struct {
Port string // e.g. /dev/cu.usbserial-XXXX, /dev/ttyUSB0, COM3
Serial string // USB iSerialNumber (from the enumerator); "" if unavailable
Product string // USB iProduct string (from the enumerator); "" if unavailable
}
DeviceInfo identifies an opened serial port plus the USB-descriptor properties the enumerator reports for it before the port is opened. Serial is the FTDI bridge's USB iSerialNumber — a stable per-unit identity that disambiguates several FTDI devices sharing VID 0x0403 and survives replug / port renumbering. Note this is the USB bridge's serial, not the SQM's own serial number (which UnitInfo returns).
func Enumerate ¶
func Enumerate() ([]DeviceInfo, error)
Enumerate lists attached FTDI serial ports (the raw candidate list, not yet identified as SQMs). Matching is per-OS: enum_other.go uses the USB VID via the pure-Go enumerator; enum_darwin.go matches the FTDI device-name convention, deliberately avoiding the enumerator's macOS cgo (IOKit) path so the driver builds for any target with CGO_ENABLED=0. Use Discover to get only the ports that are actually Unihedron SQMs.
type Discovered ¶
type Discovered struct {
DeviceInfo
Unit UnitInfo
}
Discovered is a Unihedron identified by probing an FTDI serial port: the enumerated port and USB-bridge descriptor (DeviceInfo), plus the SQM's own identity from ix (Unit.Serial is the meter's serial number, distinct from the FTDI bridge's Serial).
func Discover ¶
func Discover() ([]Discovered, error)
Discover enumerates FTDI serial ports and probes each with the ix command, returning only the ports that identify as a Unihedron SQM. Ports that are busy (held exclusively by another driver — e.g. a Pegasus focuser, which also uses FTDI VID 0x0403, on Linux) or that accept the open but don't answer as an SQM are skipped. This reliably separates SQMs from other FTDI devices, so callers don't need to supply a serial number.
type IntervalSettings ¶
type IntervalSettings struct {
PeriodEEPROM int // interval period stored in EEPROM (boot value), seconds
PeriodRAM int // interval period in RAM (live value), seconds
ThresholdEEPROM float64 // report threshold stored in EEPROM, mag/arcsec²
ThresholdRAM float64 // report threshold in RAM, mag/arcsec²
}
IntervalSettings is a decoded "Ix" interval-report settings response (manual §8.7.3, firmware Feature ≥13). Period is in seconds, Threshold in mag/arcsec².
type Reading ¶
type Reading struct {
MagPerArcsec2 float64 // sky brightness in mag/arcsec² (darker sky → larger value; 0.00 means the sensor is saturated by light)
FrequencyHz int // light-sensor output frequency, Hz
PeriodCounts int64 // sensor period in counts of the 460.8 kHz (14.7456 MHz/32) clock
PeriodSeconds float64 // sensor period in seconds (PeriodCounts / 460800)
TempC float64 // temperature at the light sensor, °C
}
Reading is a decoded "rx"/"ux" reading response (SQM-LU manual §8.2.1/§8.2.2).
type SQM ¶
type SQM struct {
// contains filtered or unexported fields
}
SQM is an opened Unihedron Sky Quality Meter.
func New ¶
func New(t Transport, info DeviceInfo) *SQM
New wraps an already-open Transport. Most callers use OpenFirst / OpenPort; New is for a custom Transport (alternate backend, or a fake for testing).
func OpenBySerial ¶
OpenBySerial opens the SQM whose USB-bridge serial number matches serial (case-insensitive). The serial comes from the USB descriptor via the enumerator — read before opening — so it disambiguates several FTDI devices sharing VID 0x0403 and binds the same physical unit across replug / port renumbering.
func (*SQM) Calibration ¶
func (s *SQM) Calibration() (Calibration, error)
Calibration requests the stored calibration constants with the "cx" command.
func (*SQM) Command ¶
Command issues a raw command string and returns the first reply line beginning with prefix (the response type byte, e.g. 'r', 'i', 'c'), trimmed of its "\r\n". This is the escape hatch for commands not wrapped by a typed method. Note SQM commands are sent verbatim (no line terminator).
func (*SQM) Info ¶
func (s *SQM) Info() DeviceInfo
Info returns the port/USB descriptor of the opened device. For the SQM's own firmware/serial identity, use UnitInfo.
func (*SQM) IntervalSettings ¶
func (s *SQM) IntervalSettings() (IntervalSettings, error)
IntervalSettings requests the timed-interval reporting parameters with the "Ix" command (firmware Feature ≥13; older units will time out).
func (*SQM) Reading ¶
Reading requests an averaged reading with the "rx" command (last-8 boxcar average in period mode; frequency mode is inherently averaged over a 1 s sample).
func (*SQM) UnaveragedReading ¶
UnaveragedReading requests the most recent, un-averaged reading with the "ux" command.
type Transport ¶
Transport is a byte-level serial channel to the FTDI VCP port (satisfied by a go.bug.st/serial port); the device logic frames ASCII commands over it. Read should block up to a short timeout and return 0 bytes (not an error) when nothing is available, so command() can poll to a deadline.
type UnitInfo ¶
type UnitInfo struct {
Protocol int // data-protocol revision (independent of Feature)
Model int // hardware model the firmware targets
Feature int // software feature revision
Serial int // the SQM's own unique serial number
}
UnitInfo is a decoded "ix" unit-information response (SQM-LU manual §8.2.5). All four are firmware-reported identity numbers; Feature gates optional capabilities (≥13 interval reporting, ≥14 serial in interval reports, ≥44 I²C accessories).
Directories
¶
| Path | Synopsis |
|---|---|
|
cmd
|
|
|
sqmsnap
command
sqmsnap is a small CLI over the unihedron driver: it opens a Unihedron SQM (by port, by USB serial, or the first one found), prints unit info + calibration + a reading, and can poll readings at an interval.
|
sqmsnap is a small CLI over the unihedron driver: it opens a Unihedron SQM (by port, by USB serial, or the first one found), prints unit info + calibration + a reading, and can poll readings at an interval. |