const std = @import("std");
const fmt = std.fmt;
const mem = std.mem;
const net = std.net;
const config = @cImport(@cInclude("config.h"));
const Action = enum(u8) {
ON = 'n',
OFF = 'f',
CYCLE = 'c',
QUERY = 'q',
fn parse(str: []const u8) !Action {
if (mem.eql(u8, str, "on")) {
return .ON;
}
if (mem.eql(u8, str, "off")) {
return .OFF;
}
if (mem.eql(u8, str, "cycle")) {
return .CYCLE;
}
if (mem.eql(u8, str, "query")) {
return .QUERY;
}
return error.InvalidAction;
}
};
inline fn usage() noreturn {
std.debug.warn("Usage: iboot <on|off|cycle|query>\n", .{});
std.process.exit(1);
}
pub fn main() anyerror!void {
var args = std.process.args();
_ = args.skip();
const action = if (args.nextPosix()) |arg|
Action.parse(arg) catch {
std.debug.warn("Invalid action: {}\n", .{arg});
usage();
}
else
usage();
const addr = try net.Address.parseIp4(mem.span(config.ADDRESS), config.PORT);
const sock = try net.tcpConnectToAddress(addr);
// 4 extra bytes for the two escape characters, the action character, and
// the carriage return
comptime var size = mem.span(config.PASSWORD).len + 4;
var buf: [size]u8 = undefined;
_ = try fmt.bufPrint(&buf, "\x1b{}\x1b{c}\r", .{
mem.span(config.PASSWORD),
@enumToInt(action),
});
try sock.writeAll(&buf);
mem.set(u8, &buf, 0);
_ = try sock.read(&buf);
std.debug.warn("{}\n", .{buf});
}