diff --git a/src/main.zig b/src/main.zig index bb4ed3d..c1e79a1 100644 --- a/src/main.zig +++ b/src/main.zig @@ -261,6 +261,44 @@ fn startRecirculation(allocator: std.mem.Allocator, id_token: []const u8, serial return result.status == .ok; } +const DeviceShadow = struct { + json_data: json.Parsed(json.Value), + heater_serial_number: ?[]const u8, + set_recirculation_enabled: ?bool, + recirculation_enabled: ?bool, + recirculation_duration: ?i64, + set_domestic_temperature: ?i64, + operation_enabled: ?bool, + + pub fn deinit(self: *DeviceShadow) void { + self.json_data.deinit(); + } +}; + +fn parseDeviceShadow(parsed: json.Parsed(json.Value)) !DeviceShadow { + if (parsed.value.object.get("data")) |data| { + if (data.object.get("getDeviceShadow")) |shadow| { + const heater_serial_number = stringFromJson(shadow, "heater_serial_number"); + const set_recirculation_enabled = if (shadow.object.get("set_recirculation_enabled")) |v| if (v == .bool) v.bool else null else null; + const recirculation_enabled = if (shadow.object.get("recirculation_enabled")) |v| if (v == .bool) v.bool else null else null; + const recirculation_duration = if (shadow.object.get("recirculation_duration")) |v| if (v == .integer) v.integer else null else null; + const set_domestic_temperature = if (shadow.object.get("set_domestic_temperature")) |v| if (v == .integer) v.integer else null else null; + const operation_enabled = if (shadow.object.get("operation_enabled")) |v| if (v == .bool) v.bool else null else null; + + return .{ + .json_data = parsed, + .heater_serial_number = heater_serial_number, + .set_recirculation_enabled = set_recirculation_enabled, + .recirculation_enabled = recirculation_enabled, + .recirculation_duration = recirculation_duration, + .set_domestic_temperature = set_domestic_temperature, + .operation_enabled = operation_enabled, + }; + } + } + return error.NoShadowFound; +} + fn removeNewlines(comptime input: []const u8) []const u8 { comptime { var result: [input.len]u8 = undefined; @@ -275,7 +313,7 @@ fn removeNewlines(comptime input: []const u8) []const u8 { } /// Queries the device shadow to get current recirculation status -fn getRecirculationStatus(allocator: std.mem.Allocator, id_token: []const u8, serial_number: []const u8) !json.Parsed(json.Value) { +fn getRecirculationStatus(allocator: std.mem.Allocator, id_token: []const u8, serial_number: []const u8) !DeviceShadow { var client = http.Client{ .allocator = allocator }; defer client.deinit(); @@ -315,7 +353,8 @@ fn getRecirculationStatus(allocator: std.mem.Allocator, id_token: []const u8, se }); const response_body = response_buf[0..writer.end]; - return try json.parseFromSlice(json.Value, allocator, response_body, .{}); + const parsed = try json.parseFromSlice(json.Value, allocator, response_body, .{}); + return try parseDeviceShadow(parsed); } pub fn main() !void { @@ -371,44 +410,27 @@ pub fn main() !void { try stdout.print("šŸ” Checking recirculation status for {?s}...\n", .{device.device_name}); try stdout.flush(); - const status = try getRecirculationStatus(allocator, auth.id_token, sid); + var status = try getRecirculationStatus(allocator, auth.id_token, sid); defer status.deinit(); - if (status.value.object.get("data")) |status_data| { - if (status_data.object.get("getDeviceShadow")) |shadow| { - try stdout.print("\nCurrent Shadow State:\n", .{}); + try stdout.print("\nCurrent Shadow State:\n", .{}); + try stdout.print(" heater_serial_number: {?s}\n", .{status.heater_serial_number}); + try stdout.print(" set_recirculation_enabled: {?}\n", .{status.set_recirculation_enabled}); + try stdout.print(" recirculation_enabled: {?}\n", .{status.recirculation_enabled}); + try stdout.print(" recirculation_duration: {?}\n", .{status.recirculation_duration}); + try stdout.print(" set_domestic_temperature: {?}\n", .{status.set_domestic_temperature}); + try stdout.print(" operation_enabled: {?}\n", .{status.operation_enabled}); - if (shadow.object.get("heater_serial_number")) |v| { - if (v == .string) try stdout.print(" heater_serial_number: {s}\n", .{v.string}); - } - if (shadow.object.get("set_recirculation_enabled")) |v| { - if (v == .bool) try stdout.print(" set_recirculation_enabled: {}\n", .{v.bool}); - } - if (shadow.object.get("recirculation_enabled")) |v| { - if (v == .bool) try stdout.print(" recirculation_enabled: {}\n", .{v.bool}); - } - if (shadow.object.get("recirculation_duration")) |v| { - if (v == .integer) try stdout.print(" recirculation_duration: {}\n", .{v.integer}); - } - if (shadow.object.get("set_domestic_temperature")) |v| { - if (v == .integer) try stdout.print(" set_domestic_temperature: {}\n", .{v.integer}); - } - if (shadow.object.get("operation_enabled")) |v| { - if (v == .bool) try stdout.print(" operation_enabled: {}\n", .{v.bool}); - } + const recirc_enabled = status.recirculation_enabled orelse false; - const recirc_enabled = if (shadow.object.get("recirculation_enabled")) |re| if (re == .bool) re.bool else false else false; - - if (recirc_enabled) { - try stdout.print("\nāœ“ Recirculation is already active\n", .{}); - // Recirculation code commented out as requested - } else { - // Recirculation code would go here but not called during testing - try stdout.print("\n(Recirculation start function available but not called during testing)\n", .{}); - } - try stdout.flush(); - } + if (recirc_enabled) { + try stdout.print("\nāœ“ Recirculation is already active\n", .{}); + // Recirculation code commented out as requested + } else { + // Recirculation code would go here but not called during testing + try stdout.print("\n(Recirculation start function available but not called during testing)\n", .{}); } + try stdout.flush(); } else { try stderr.print("āŒ No serial_id found for device\n", .{}); try stderr.flush();