private static string ToMountHex(Dms value) { var intval = (uint)(value.ValueMod * (uint.MaxValue + 1.0)); intval &= 0xffffff00; return(intval.ToString("X8")); }
private string FormatLatLon(Dms lat, Dms lon) { var(latSign, latDeg, latMin, latSec, _) = lat.DegreesMinutesSeconds; var(lonSign, lonDeg, lonMin, lonSec, _) = lon.DegreesMinutesSeconds; // The format of the location commands is: ABCDEFGH, where: // A is the number of degrees of latitude. // B is the number of minutes of latitude. // C is the number of seconds of latitude. // D is 0 for north and 1 for south. // E is the number of degrees of longitude. // F is the number of minutes of longitude. // G is the number of seconds of longitude. // H is 0 for east and 1 for west. var builder = new StringBuilder(8); builder.Append((char)latDeg); builder.Append((char)latMin); builder.Append((char)latSec); builder.Append(latSign ? (char)1 : (char)0); builder.Append((char)lonDeg); builder.Append((char)lonMin); builder.Append((char)lonSec); builder.Append(lonSign ? (char)1 : (char)0); return(builder.ToString()); }
private static async Task <(Dms ra, Dms dec)?> SolveOne(string filename) { var low = 0.9; var high = 1.1; var downsample = 4; var info = new ProcessStartInfo(_bashLocation, BuildCommand(low, high, downsample, filename)) { UseShellExecute = false, RedirectStandardOutput = true, }; var process = Process.Start(info); var output = await process.StandardOutput.ReadToEndAsync(); var matches = _regex.Match(output); if (matches.Success) { var one = matches.Groups[1].Value; var two = matches.Groups[2].Value; if (double.TryParse(one, out var oneValue) && double.TryParse(two, out var twoValue)) { return(Dms.FromDegrees(oneValue), Dms.FromDegrees(twoValue)); } } return(null); }
public async Task SlewAzAlt(Dms az, Dms alt) { var res = await Interact($"b{ToMountHex(az)},{ToMountHex(alt)}"); if (res != "") { throw new Exception($"Slew az/alt failed: {res}"); } }
public async Task Slew(Dms ra, Dms dec) { var res = await Interact($"r{ToMountHex(ra)},{ToMountHex(dec)}"); if (res != "") { throw new Exception($"Slew RA/DEC failed: {res}"); } }
public async Task OverwriteRaDec(Dms ra, Dms dec) { var res = await Interact($"s{ToMountHex(ra)},{ToMountHex(dec)}"); if (res != "") { throw new Exception($"Overwrite RA/DEC failed: {res}"); } }
public async Task SetLocation(Dms lat, Dms lon) { var location = FormatLatLon(lat, lon); var result = await Interact($"W{location}"); if (result != "") { throw new Exception($"Set location failed: {result}"); } }
static void SplitThreeBytes(Dms valueDms, out byte high, out byte med, out byte low) { var value = valueDms.ValueMod; value *= 256; high = (byte)value; value = Dms.Mod(value, 1); value *= 256; med = (byte)value; value = Dms.Mod(value, 1); value *= 256; low = (byte)value; }
async Task PCommandThree(byte one, byte two, byte three, Dms data) { SplitThreeBytes(data, out var high, out var med, out var low); var cmd = new char[8]; cmd[0] = 'P'; cmd[1] = (char)one; cmd[2] = (char)two; cmd[3] = (char)three; cmd[4] = (char)high; cmd[5] = (char)med; cmd[6] = (char)low; cmd[7] = (char)0; await Interact(new string(cmd)); }
public async Task <(Dms, Dms)> GetAzAlt() { var line = await Interact("z"); var split = line.Split(','); if (split.Length != 2) { throw new Exception($"Invalid response to 'z': {line}"); } var az = Convert.ToUInt32(split[0], 16) / (uint.MaxValue + 1.0); var alt = Convert.ToUInt32(split[1], 16) / (uint.MaxValue + 1.0); return(Dms.From0to1(az), Dms.From0to1(alt)); }
public async Task <(Dms, Dms)> GetRaDec() { var line = await Interact("e"); var split = line.Split(','); if (split.Length != 2) { throw new Exception($"Invalid response to 'e': {line}"); } var ra = Convert.ToUInt32(split[0], 16) / (uint.MaxValue + 1.0); var dec = Convert.ToUInt32(split[1], 16) / (uint.MaxValue + 1.0); return(Dms.From0to1(ra), Dms.From0to1(dec)); }
public static bool TryParse(string s, out Dms dms) { var match = _parseRegex.Match(s); if (!match.Success) { dms = default; return(false); } var signMatch = match.Groups["sign"]; var isNegative = signMatch.Success ? signMatch.Value == "-" : false; var degrees = double.Parse(match.Groups["degrees"].Value); var minutesMatch = match.Groups["minutes"]; var minutes = minutesMatch.Success ? double.Parse(minutesMatch.Value) : 0; var secondsMatch = match.Groups["seconds"]; var seconds = secondsMatch.Success ? double.Parse(secondsMatch.Value) : 0; var unitMatch = match.Groups["unit"]; if (unitMatch.Success) { if (unitMatch.Value == "h" || unitMatch.Value == "H") { dms = FromHms(isNegative, degrees, minutes, seconds); } else { dms = FromDms(isNegative, degrees, minutes, seconds); } } else { if (double.TryParse(s, out var rawValue)) { dms = From0to1(rawValue); if (rawValue < 0 || rawValue > 1) { Console.WriteLine("Got a value outside [0,1] for raw value - did you mean to add a unit? e.g. " + s + "d for degrees"); return(false); } } else { throw new Exception("Missing unit, but didn't parse as double: " + s); } } return(true); }
private (Dms, Dms) ParseLatLon(string value) { if (value.Length != 8) { throw new Exception($"Invalid lat/lon: {value}"); } var latDeg = (int)value[0]; var latMin = (int)value[1]; var latSec = (int)value[2]; var latSign = value[3] == 1; var lonDeg = (int)value[4]; var lonMin = (int)value[5]; var lonSec = (int)value[6]; var lonSign = value[7] == 1; var lat = Dms.FromDms(latSign, latDeg, latMin, latSec); var lon = Dms.FromDms(lonSign, lonDeg, lonMin, lonSec); return(lat, lon); }
public Task SlowGotoDec(Dms data) => PCommandThree(4, 17, 23, data);
public Task SlowGotoRA(Dms data) => PCommandThree(4, 16, 23, data);
public Task ResetDec(Dms data) => PCommandThree(4, 17, 4, data);
public Task ResetRA(Dms data) => PCommandThree(4, 16, 4, data);
private static async Task ReplMount(string[] cmd, Mount mount) { switch (cmd[0]) { case "help": Console.WriteLine("slew [ra] [dec] - slew to direction"); Console.WriteLine("slewra [ra] - slow goto"); Console.WriteLine("slewdec [dec] - slow goto"); Console.WriteLine("cancel - cancel slew"); Console.WriteLine("pos - get current direction"); Console.WriteLine("setpos - overwrite current direction"); Console.WriteLine("syncpos - sync/calibrate current direction"); Console.WriteLine("azalt - get current az/alt"); Console.WriteLine("azalt [az] [alt] - slew to az/alt"); Console.WriteLine("track - get tracking mode"); Console.WriteLine("track [value] - set tracking mode"); Console.WriteLine("location - get lat/lon"); Console.WriteLine("location [lat] [lon] - set lat/lon"); Console.WriteLine("time - get mount's time"); Console.WriteLine("time now - set mount's time to now"); Console.WriteLine("aligned - get true/false if mount is aligned"); Console.WriteLine("ping - ping mount, prints time it took"); Console.WriteLine("solve [filename] - plate-solve image with ANSVR"); break; case "slew": { cmd[1] = cmd[1].TrimEnd(','); if (cmd.Length == 3 && Dms.TryParse(cmd[1], out var ra) && Dms.TryParse(cmd[2], out var dec)) { await mount.Slew(ra, dec); } else { goto default; } } break; case "slewra": { if (cmd.Length == 2 && Dms.TryParse(cmd[1], out var ra)) { await mount.SlowGotoRA(ra); } else { goto default; } } break; case "slewdec": { if (cmd.Length == 2 && Dms.TryParse(cmd[1], out var ra)) { await mount.SlowGotoDec(ra); } else { goto default; } } break; case "cancel": await mount.CancelSlew(); break; case "pos": { var(ra, dec) = await mount.GetRaDec(); Console.WriteLine($"{ra.ToDmsString(Dms.Unit.Hours)}, {dec.ToDmsString(Dms.Unit.Degrees)}"); } break; case "setpos": { cmd[1] = cmd[1].TrimEnd(','); if (cmd.Length == 3 && Dms.TryParse(cmd[1], out var ra) && Dms.TryParse(cmd[2], out var dec)) { await mount.ResetRA(ra); await mount.ResetDec(dec); } else { goto default; } } break; case "syncpos": { cmd[1] = cmd[1].TrimEnd(','); if (cmd.Length == 3 && Dms.TryParse(cmd[1], out var ra) && Dms.TryParse(cmd[2], out var dec)) { await mount.OverwriteRaDec(ra, dec); } else { goto default; } } break; case "azalt": if (cmd.Length == 1) { var(az, alt) = await mount.GetAzAlt(); Console.WriteLine($"{az.ToDmsString(Dms.Unit.Degrees)}, {alt.ToDmsString(Dms.Unit.Degrees)}"); } else if (cmd.Length == 3 && Dms.TryParse(cmd[1], out var az) && Dms.TryParse(cmd[2], out var alt)) { await mount.SlewAzAlt(az, alt); } else { goto default; } break; case "track": if (cmd.Length == 1) { var track = await mount.GetTrackingMode(); Console.WriteLine($"Mode: {track}"); Console.WriteLine($"(available: {string.Join(", ", (Mount.TrackingMode[])Enum.GetValues(typeof(Mount.TrackingMode)))})"); } else if (cmd.Length == 2 && Enum.TryParse <Mount.TrackingMode>(cmd[1], out var mode)) { await mount.SetTrackingMode(mode); } else { goto default; } break; case "location": if (cmd.Length == 1) { var(lat, lon) = await mount.GetLocation(); Console.WriteLine($"{lat.ToDmsString(Dms.Unit.Degrees)}, {lon.ToDmsString(Dms.Unit.Degrees)}"); } else if (cmd.Length == 3 && Dms.TryParse(cmd[1], out var lat) && Dms.TryParse(cmd[2], out var lon)) { await mount.SetLocation(lat, lon); } else { goto default; } break; case "time": if (cmd.Length == 1) { var now_one = DateTime.Now; var time = await mount.GetTime(); Console.WriteLine($"Mount time: {time} (off by {now_one - time})"); } else if (cmd.Length == 2 && cmd[1] == "now") { await mount.SetTime(DateTime.Now); } else { goto default; } break; case "aligned": { var aligned = await mount.IsAligned(); Console.WriteLine($"IsAligned: {aligned}"); } break; case "ping": { var timer = Stopwatch.StartNew(); var res = await mount.Echo('p'); Console.WriteLine($"{timer.ElapsedMilliseconds}ms"); } break; case "solve": if (cmd.Length == 2) { var task = PlateSolve.SolveFile(cmd[1]); } else { goto default; } break; default: Console.WriteLine($"Unknown command {string.Join(" ", cmd)}"); break; } }