Compare commits
2 Commits
d5f0727517
...
e4393c2e5a
Author | SHA1 | Date | |
---|---|---|---|
e4393c2e5a | |||
ccb507d4d9 |
@ -114,7 +114,7 @@ controller: ControllerConfig = .{
|
||||
.elevation_input = .{ .channel = .diff_23, .range = .@"5 V" },
|
||||
.azimuth_outputs = .{ .increase = .{ .io = 0 }, .decrease = .{ .io = 1 } },
|
||||
.elevation_outputs = .{ .increase = .{ .io = 2 }, .decrease = .{ .io = 3 } },
|
||||
.loop_interval_ns = 50_000_000,
|
||||
.loop_interval_ns = 100_000_000,
|
||||
.parking_posture = .{ .azimuth = 180, .elevation = 90 },
|
||||
.angle_tolerance = .{ .azimuth = 1, .elevation = 1 },
|
||||
.angle_offset = .{ .azimuth = 0, .elevation = 0 },
|
||||
|
191
src/main.zig
191
src/main.zig
@ -12,18 +12,6 @@ fn printStderr(comptime fmt: []const u8, args: anytype) void {
|
||||
std.debug.print(fmt ++ "\n", args);
|
||||
}
|
||||
|
||||
const commands = .{
|
||||
.install_udev = "install-udev-rules",
|
||||
.write_config = "write-default-config",
|
||||
.run = "run",
|
||||
};
|
||||
|
||||
const command_help = .{
|
||||
.install_udev = "[udev rules.d path]: Install the built-in LabJack u12 udev rules file. May require sudo privileges. Linux only.",
|
||||
.write_config = "[path]: write the default configuration to a json file.",
|
||||
.run = "[config path]: run the rotctl interface with the provided config.",
|
||||
};
|
||||
|
||||
pub fn main() !u8 {
|
||||
var gpa = std.heap.GeneralPurposeAllocator(.{}){};
|
||||
defer _ = gpa.deinit();
|
||||
@ -35,21 +23,26 @@ pub fn main() !u8 {
|
||||
};
|
||||
defer std.process.argsFree(allocator, args);
|
||||
|
||||
if (args.len < 2) {
|
||||
printHelp();
|
||||
if (args.len < 1) {
|
||||
printStderr("No arguments at all?", .{});
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (std.mem.eql(u8, args[1], commands.install_udev)) {
|
||||
const exename = std.fs.path.basename(args[0]);
|
||||
|
||||
if (args.len < 2) {
|
||||
printHelp(exename, .main);
|
||||
return 1;
|
||||
} else if (std.mem.eql(u8, args[1], commands.install_udev)) {
|
||||
if (args.len > 3) {
|
||||
printHelp();
|
||||
printHelp(exename, .install_udev);
|
||||
return 1;
|
||||
}
|
||||
|
||||
return installUdevRules(if (args.len == 3) args[2] else null);
|
||||
} else if (std.mem.eql(u8, args[1], commands.write_config)) {
|
||||
if (args.len > 3) {
|
||||
printHelp();
|
||||
printHelp(exename, .write_config);
|
||||
return 1;
|
||||
}
|
||||
|
||||
@ -57,7 +50,7 @@ pub fn main() !u8 {
|
||||
return writeDefaultConfig(if (args.len == 3) args[2] else null);
|
||||
} else if (std.mem.eql(u8, args[1], commands.run)) {
|
||||
if (args.len > 3) {
|
||||
printHelp();
|
||||
printHelp(exename, .run);
|
||||
return 1;
|
||||
}
|
||||
blk: {
|
||||
@ -85,8 +78,23 @@ pub fn main() !u8 {
|
||||
};
|
||||
|
||||
return 0;
|
||||
} else if (std.mem.eql(u8, args[1], commands.help)) {
|
||||
if (args.len != 3) {
|
||||
printHelp(exename, .help);
|
||||
return 1;
|
||||
}
|
||||
|
||||
inline for (@typeInfo(@TypeOf(commands)).Struct.fields) |field| {
|
||||
if (std.mem.eql(u8, args[2], @field(commands, field.name))) {
|
||||
printHelp(exename, @field(HelpTag, field.name));
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
printHelp(exename, .help);
|
||||
return 1;
|
||||
}
|
||||
} else {
|
||||
printHelp();
|
||||
printHelp(exename, .main);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
@ -141,20 +149,135 @@ fn writeDefaultConfig(outarg: ?[]const u8) u8 {
|
||||
return 0;
|
||||
}
|
||||
|
||||
fn printHelp() void {
|
||||
printStderr(
|
||||
\\Usage: yaes [command] [args...]
|
||||
\\
|
||||
\\ Control a Yaesu G-5500DC rotator through a LabJack U12 using the hamlib TCP interface.
|
||||
\\
|
||||
\\Available commands:
|
||||
\\
|
||||
, .{});
|
||||
|
||||
inline for (@typeInfo(@TypeOf(commands)).Struct.fields) |field| {
|
||||
printStderr(
|
||||
" {s} {s}",
|
||||
.{ @field(commands, field.name), @field(command_help, field.name) },
|
||||
);
|
||||
fn printHelp(exename: []const u8, comptime cmd: HelpTag) void {
|
||||
switch (cmd) {
|
||||
.main => {
|
||||
printStderr(command_help.main, .{ .exename = exename });
|
||||
inline for (@typeInfo(@TypeOf(commands)).Struct.fields) |field| {
|
||||
printStderr(
|
||||
" {s: <" ++ max_command_len ++ "} {s}",
|
||||
.{ @field(commands, field.name), @field(command_help, field.name).brief },
|
||||
);
|
||||
}
|
||||
printStderr("", .{});
|
||||
},
|
||||
.help => {
|
||||
printStderr(command_help.help.full, .{ .exename = exename, .cmdname = "help" });
|
||||
inline for (@typeInfo(@TypeOf(commands)).Struct.fields) |field| {
|
||||
printStderr(
|
||||
" - {s}",
|
||||
.{@field(commands, field.name)},
|
||||
);
|
||||
}
|
||||
printStderr("", .{});
|
||||
},
|
||||
else => {
|
||||
printStderr(
|
||||
@field(command_help, @tagName(cmd)).full,
|
||||
.{ .exename = exename, .cmdname = @field(commands, @tagName(cmd)) },
|
||||
);
|
||||
printStderr("", .{});
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
const HelpTag = std.meta.FieldEnum(@TypeOf(command_help));
|
||||
|
||||
const commands = .{
|
||||
.install_udev = "install-udev-rules",
|
||||
.write_config = "write-default-config",
|
||||
.run = "run",
|
||||
.calibrate = "calibrate",
|
||||
.help = "help",
|
||||
};
|
||||
|
||||
const max_command_len: []const u8 = blk: {
|
||||
var len: usize = 0;
|
||||
for (@typeInfo(@TypeOf(commands)).Struct.fields) |field|
|
||||
if (@field(commands, field.name).len > len) {
|
||||
len = @field(commands, field.name).len;
|
||||
};
|
||||
break :blk std.fmt.comptimePrint("{d}", .{len});
|
||||
};
|
||||
|
||||
const command_help = .{
|
||||
.main =
|
||||
\\Usage: {[exename]s} <command> [arguments...]
|
||||
\\
|
||||
\\ Calibrate/Control a Yaesu G-5500DC rotator with a LabJack U12.
|
||||
\\
|
||||
\\Commands:
|
||||
,
|
||||
.install_udev = .{
|
||||
.brief = "Install a udev rules file for the LabJack U12",
|
||||
.full =
|
||||
\\Usage: {[exename]s} {[cmdname]s} [<rules_dir>]
|
||||
\\
|
||||
\\ Install a udev rules file for the LabJack U12, which allows unprivileged access to the device on
|
||||
\\ Linux-based operating systems.
|
||||
\\
|
||||
\\Arguments:
|
||||
\\ rules_dir [Optional] The path to the udev rules directory inside which the rules file will be
|
||||
\\ written. (Default: /etc/udev/rules.d)
|
||||
,
|
||||
},
|
||||
.write_config = .{
|
||||
.brief = "Write the default configuration to a file",
|
||||
.full =
|
||||
\\Usage: {[exename]s} {[cmdname]s} [<config_file>]
|
||||
\\
|
||||
\\ Write the built-in configuration defaults to a file. Useful as a starting point for creating a
|
||||
\\ custom configuration.
|
||||
\\
|
||||
\\Arguments:
|
||||
\\ config_file [Optional] the path of the file to write. (Default: ./yaes.json)
|
||||
,
|
||||
},
|
||||
.run = .{
|
||||
.brief = "Run the rotator with a hamlib-compatible TCP interface",
|
||||
.full =
|
||||
\\Usage: {[exename]s} {[cmdname]s} [<config_file>]
|
||||
\\
|
||||
\\ Expose a hamlib (rotctld)-compatible TCP interface through which the rotator can be controlled.
|
||||
\\ This listens on localhost port 4533 by default. Only a subset of the rotctld commands are
|
||||
\\ actually supported. A brief list of supported commands:
|
||||
\\
|
||||
\\ P, set_pos <az> <el> - point the rotator to the given azimuth and elevation
|
||||
\\ p, get_pos - return the rotator's current azimuth and elevation
|
||||
\\ S, stop - stop moving the rotator if it is moving
|
||||
\\ K, park - move the rotator to its parking posture (defined by the config)
|
||||
\\ q, Q, quit - [nonstandard] stop the rotator control loop and exit
|
||||
\\
|
||||
\\Arguments:
|
||||
\\ config_file [Optional] the name of the config file to load. If this file does not exist, then
|
||||
\\ the built-in defaults will be used. (Default: ./yaes.json)
|
||||
,
|
||||
},
|
||||
.calibrate = .{
|
||||
.brief = "Calibrate the rotator's feedback or its orientation to geodetic North",
|
||||
.full =
|
||||
\\Usage: {[exename]s} {[cmdname]s} <routine> [<config_file>]
|
||||
\\
|
||||
\\ Perform a calibration routine and write an updated configuration with its results.
|
||||
\\
|
||||
\\Arguments:
|
||||
\\ routine Must be one of `feedback` or `orientation`. The different calibration routines have
|
||||
\\ different requirements. `orientation` calibration is a sun-pointing-based routine and
|
||||
\\ should be performed after `feedback` calibration is complete.
|
||||
\\ config_file [Optional] the path of a config file to load. This file will be updated with the
|
||||
\\ results of the calibration process. If omitted and the configuration file does not
|
||||
\\ exist, then the default configuration will be used. (Default: ./yaes.json)
|
||||
,
|
||||
},
|
||||
.help = .{
|
||||
.brief = "Print detailed help for a given command",
|
||||
.full =
|
||||
\\Usage: {[exename]s} {[cmdname]s} <command>
|
||||
\\
|
||||
\\ Print information on how to use a command and exit.
|
||||
\\
|
||||
\\Arguments:
|
||||
\\ command The name of the command to print information about. Must be one of the following:
|
||||
,
|
||||
},
|
||||
};
|
||||
|
Loading…
x
Reference in New Issue
Block a user