working implementation
This commit is contained in:
parent
802b9e766b
commit
100d49b4c7
1 changed files with 122 additions and 52 deletions
174
src/main.zig
174
src/main.zig
|
|
@ -228,37 +228,55 @@ fn getDevices(allocator: std.mem.Allocator, id_token: []const u8, username: []co
|
|||
}
|
||||
|
||||
/// Starts recirculation for the specified device with given duration
|
||||
fn startRecirculation(allocator: std.mem.Allocator, id_token: []const u8, serial_number: []const u8, duration_minutes: u32) !void {
|
||||
fn setRecirculation(allocator: std.mem.Allocator, id_token: []const u8, thing_name: []const u8, duration_minutes: ?u32) !void {
|
||||
var client = http.Client{ .allocator = allocator };
|
||||
defer client.deinit();
|
||||
|
||||
const url = try std.fmt.allocPrint(allocator,
|
||||
\\{s}/{s}/shadow
|
||||
, .{ shadow_api_url, serial_number });
|
||||
, .{ shadow_api_url, thing_name });
|
||||
defer allocator.free(url);
|
||||
|
||||
const body = try std.fmt.allocPrint(allocator,
|
||||
\\{{"recirculation_duration":{d},"set_recirculation_enabled":true}}
|
||||
, .{duration_minutes});
|
||||
const body = if (duration_minutes) |min|
|
||||
try std.fmt.allocPrint(allocator,
|
||||
\\{{"recirculation_duration":"{d}","set_recirculation_enabled":true}}
|
||||
, .{min})
|
||||
else
|
||||
try allocator.dupe(u8,
|
||||
\\{"set_recirculation_enabled":false}
|
||||
);
|
||||
defer allocator.free(body);
|
||||
|
||||
// std.debug.print("DEBUG: PATCH URL: {s}\n", .{url});
|
||||
// std.debug.print("DEBUG: PATCH Body: {s}\n", .{body});
|
||||
|
||||
const uri = try std.Uri.parse(url);
|
||||
const auth_header = try std.fmt.allocPrint(allocator,
|
||||
\\Bearer {s}
|
||||
, .{id_token});
|
||||
defer allocator.free(auth_header);
|
||||
|
||||
var response_buf: [4096]u8 = undefined;
|
||||
var writer = std.Io.Writer.fixed(&response_buf);
|
||||
const result = try client.fetch(.{
|
||||
.location = .{ .uri = uri },
|
||||
.method = .PATCH,
|
||||
.payload = body,
|
||||
.response_writer = &writer,
|
||||
.extra_headers = &.{
|
||||
.{ .name = "Authorization", .value = auth_header },
|
||||
.{ .name = "Content-Type", .value = "application/json" },
|
||||
},
|
||||
});
|
||||
|
||||
if (result.status != .ok) return error.StartRecirculationFailed;
|
||||
const response_body = response_buf[0..writer.end];
|
||||
// std.debug.print("DEBUG: PATCH Response Status: {}\n", .{result.status});
|
||||
// std.debug.print("DEBUG: PATCH Response Body: {s}\n", .{response_body});
|
||||
|
||||
if (result.status != .ok) {
|
||||
std.debug.print("PATCH failed - Status: {}, Body: {s}\n", .{ result.status, response_body });
|
||||
return error.StartRecirculationFailed;
|
||||
}
|
||||
}
|
||||
|
||||
const DeviceShadow = struct {
|
||||
|
|
@ -372,6 +390,10 @@ pub fn main() !void {
|
|||
defer _ = gpa.deinit();
|
||||
const allocator = gpa.allocator();
|
||||
|
||||
const args = try std.process.argsAlloc(allocator);
|
||||
defer std.process.argsFree(allocator, args);
|
||||
const debug_mode = args.len > 1 and std.mem.eql(u8, args[1], "--debug");
|
||||
|
||||
var stdout_buffer: [1024]u8 = undefined;
|
||||
var stdout_writer = std.fs.File.stdout().writer(&stdout_buffer);
|
||||
const stdout = &stdout_writer.interface;
|
||||
|
|
@ -393,6 +415,12 @@ pub fn main() !void {
|
|||
defer allocator.free(auth.id_token);
|
||||
defer allocator.free(auth.user_uuid);
|
||||
try stdout.print("✓ User UUID: {s}\n\n", .{auth.user_uuid});
|
||||
|
||||
if (debug_mode) {
|
||||
try stdout.print("\n=== DEBUG MODE ===\n", .{});
|
||||
try stdout.print("IdToken:\n{s}\n\n", .{auth.id_token});
|
||||
}
|
||||
|
||||
try stdout.print("📱 Fetching devices...\n", .{});
|
||||
try stdout.flush();
|
||||
var result = try getDevices(
|
||||
|
|
@ -422,54 +450,96 @@ pub fn main() !void {
|
|||
1 => {
|
||||
const device = result.devices[0];
|
||||
|
||||
if (device.serial_id) |sid| {
|
||||
try stdout.print("🔍 Checking recirculation status for {?s}...\n", .{device.device_name});
|
||||
try stdout.flush();
|
||||
|
||||
var status = try getRecirculationStatus(allocator, auth.id_token, sid);
|
||||
defer status.deinit();
|
||||
|
||||
try stdout.print("\n{f}", .{status});
|
||||
|
||||
const recirc_enabled = status.recirculation_enabled orelse false;
|
||||
|
||||
if (recirc_enabled) {
|
||||
try stdout.print("\n✓ Recirculation is already active\n", .{});
|
||||
} else {
|
||||
try stdout.print("\n🚿 Starting 15-minute recirculation...\n", .{});
|
||||
try stdout.flush();
|
||||
|
||||
startRecirculation(
|
||||
allocator,
|
||||
auth.id_token,
|
||||
sid,
|
||||
15,
|
||||
) catch |e| {
|
||||
try stderr.print("❌ Failed to start recirculation\n", .{});
|
||||
try stderr.flush();
|
||||
return e;
|
||||
};
|
||||
|
||||
try stdout.print("✓ Recirculation command sent\n", .{});
|
||||
try stdout.print("⏳ Waiting 20 seconds for device to respond...\n", .{});
|
||||
try stdout.flush();
|
||||
|
||||
std.Thread.sleep(20 * std.time.ns_per_s);
|
||||
|
||||
var post_command_state = try getRecirculationStatus(
|
||||
allocator,
|
||||
auth.id_token,
|
||||
sid,
|
||||
);
|
||||
defer post_command_state.deinit();
|
||||
try stdout.print("\n{f}", .{post_command_state});
|
||||
}
|
||||
try stdout.flush();
|
||||
} else {
|
||||
try stderr.print("❌ No serial_id found for device\n", .{});
|
||||
if (device.serial_id == null or
|
||||
device.thing_name == null)
|
||||
{
|
||||
try stderr.print("❌ thing_name and serial_id both required\n", .{});
|
||||
try stderr.flush();
|
||||
return error.NoSerialId;
|
||||
return error.SerialIdAndThingNameRequired;
|
||||
}
|
||||
|
||||
const sid = device.serial_id.?;
|
||||
const tn = device.thing_name.?;
|
||||
|
||||
try stdout.print("🔍 Checking recirculation status for {?s}...\n", .{device.device_name});
|
||||
try stdout.flush();
|
||||
|
||||
var status = try getRecirculationStatus(allocator, auth.id_token, sid);
|
||||
defer status.deinit();
|
||||
|
||||
try stdout.print("\n{f}", .{status});
|
||||
|
||||
if (debug_mode) {
|
||||
try stdout.print("\n=== CURL COMMANDS ===\n", .{});
|
||||
try stdout.print("Reset recirculation:\n", .{});
|
||||
try stdout.print("curl -X PATCH '{s}/{s}/shadow' \\\n", .{ shadow_api_url, tn });
|
||||
try stdout.print(" -H 'Authorization: Bearer {s}' \\\n", .{auth.id_token});
|
||||
try stdout.print(" -H 'Content-Type: application/json' \\\n", .{});
|
||||
try stdout.print(" -d '{{\"set_recirculation_enabled\":false}}'\n\n", .{});
|
||||
|
||||
try stdout.print("Start recirculation:\n", .{});
|
||||
try stdout.print("curl -X PATCH '{s}/{s}/shadow' \\\n", .{ shadow_api_url, tn });
|
||||
try stdout.print(" -H 'Authorization: Bearer {s}' \\\n", .{auth.id_token});
|
||||
try stdout.print(" -H 'Content-Type: application/json' \\\n", .{});
|
||||
try stdout.print(" -d '{{\"recirculation_duration\":15,\"set_recirculation_enabled\":true}}'\n\n", .{});
|
||||
try stdout.flush();
|
||||
return;
|
||||
}
|
||||
|
||||
const recirc_enabled = status.recirculation_enabled orelse false;
|
||||
|
||||
if (recirc_enabled) {
|
||||
try stdout.print("\n✓ Recirculation is already active\n", .{});
|
||||
} else {
|
||||
try stdout.print("\n🚿 Starting 15-minute recirculation...\n", .{});
|
||||
try stdout.flush();
|
||||
|
||||
if (status.set_recirculation_enabled) |en| {
|
||||
if (en) {
|
||||
try stdout.print("⚠️ set_recirculation_enabled is already true, resetting first...\n", .{});
|
||||
try stdout.flush();
|
||||
|
||||
// The shadow state doesn't seem to update. The react native
|
||||
// application doesn't wait, it just yolo's here, so
|
||||
// we'll do the same
|
||||
try setRecirculation(
|
||||
allocator,
|
||||
auth.id_token,
|
||||
sid,
|
||||
null,
|
||||
);
|
||||
|
||||
try stdout.print("⏳ Waiting 3 seconds...\n", .{});
|
||||
try stdout.flush();
|
||||
std.Thread.sleep(3 * std.time.ns_per_s);
|
||||
}
|
||||
}
|
||||
setRecirculation(
|
||||
allocator,
|
||||
auth.id_token,
|
||||
tn,
|
||||
15,
|
||||
) catch |e| {
|
||||
try stderr.print("❌ Failed to start recirculation\n", .{});
|
||||
try stderr.flush();
|
||||
return e;
|
||||
};
|
||||
|
||||
try stdout.print("✓ Recirculation command sent\n", .{});
|
||||
try stdout.print("⏳ Waiting 20 seconds for device to respond...\n", .{});
|
||||
try stdout.flush();
|
||||
|
||||
std.Thread.sleep(20 * std.time.ns_per_s);
|
||||
|
||||
var post_command_state = try getRecirculationStatus(
|
||||
allocator,
|
||||
auth.id_token,
|
||||
sid,
|
||||
);
|
||||
defer post_command_state.deinit();
|
||||
try stdout.print("\n{f}", .{post_command_state});
|
||||
}
|
||||
try stdout.flush();
|
||||
},
|
||||
else => {
|
||||
try stderr.print("❌ More than one device found for user, not currently equipped to handle this\n", .{});
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue