Skip to content

Commit e131a73

Browse files
hyperpolymathclaude
andcommitted
fix(firmware-zig): migrate to Zig 0.15.2 API
- build.zig: replace deprecated root_source_file with root_module + b.createModule() on both addExecutable and addTest; b.host → b.graph.host; point test root at new src/all_tests.zig to avoid main.zig's freestanding-only externs - main.zig: convert /** */ block comment to // line comments (Zig has no block comments) - ota.zig: rename field error → last_error ('error' is a keyword in Zig) - sensors.zig: calculateQuality takes *const Self (never mutates); test locals → const - src/all_tests.zig: new host-side test runner that imports all submodules with tests (buffer, sensors, mqtt, ota, wifi) while skipping main.zig firmware stubs 10/10 tests pass on Zig 0.15.2. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
1 parent 3a5d898 commit e131a73

5 files changed

Lines changed: 50 additions & 30 deletions

File tree

firmware-zig/build.zig

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -15,12 +15,14 @@ pub fn build(b: *std.Build) void {
1515

1616
const optimize = b.standardOptimizeOption(.{});
1717

18-
// Main firmware executable
18+
// Main firmware executable (Zig 0.15+: use root_module)
1919
const exe = b.addExecutable(.{
2020
.name = "kaldor-bbw-firmware",
21-
.root_source_file = b.path("src/main.zig"),
22-
.target = target,
23-
.optimize = optimize,
21+
.root_module = b.createModule(.{
22+
.root_source_file = b.path("src/main.zig"),
23+
.target = target,
24+
.optimize = optimize,
25+
}),
2426
});
2527

2628
// Link with ESP-IDF components (when available)
@@ -30,11 +32,14 @@ pub fn build(b: *std.Build) void {
3032

3133
b.installArtifact(exe);
3234

33-
// Unit tests (run on host)
35+
// Unit tests (run on host — Zig 0.15+: use root_module).
36+
// Uses all_tests.zig as root to avoid main.zig's freestanding-only externs.
3437
const unit_tests = b.addTest(.{
35-
.root_source_file = b.path("src/main.zig"),
36-
.target = b.host,
37-
.optimize = optimize,
38+
.root_module = b.createModule(.{
39+
.root_source_file = b.path("src/all_tests.zig"),
40+
.target = b.graph.host,
41+
.optimize = optimize,
42+
}),
3843
});
3944

4045
const run_unit_tests = b.addRunArtifact(unit_tests);

firmware-zig/src/all_tests.zig

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
// SPDX-License-Identifier: PMPL-1.0-or-later
2+
//
3+
// Kaldor IIoT firmware — host-side test runner.
4+
//
5+
// Pulls in unit tests from each submodule. main.zig is excluded here because
6+
// it contains firmware stubs (hal.*, mqtt_client, etc.) that only compile
7+
// when targeting ESP32/freestanding; host tests would fail on those externs.
8+
9+
const std = @import("std");
10+
11+
test {
12+
_ = @import("buffer.zig");
13+
_ = @import("sensors.zig");
14+
_ = @import("mqtt.zig");
15+
_ = @import("ota.zig");
16+
_ = @import("wifi.zig");
17+
}

firmware-zig/src/main.zig

Lines changed: 11 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,16 @@
11
// SPDX-License-Identifier: PMPL-1.0-or-later
22

3-
/**
4-
* Kaldor IIoTBack Beam Width (BBW) Sensor Firmware.
5-
*
6-
* This Zig module implements the firmware for an ESP32-based monitoring
7-
* system. It is designed for high-reliability industrial environments,
8-
* featuring local data buffering, watchdog enforcement, and secure telemetry.
9-
*
10-
* SUBSYSTEMS:
11-
* 1. SENSORS: High-frequency (100Hz) acquisition of physical metrics.
12-
* 2. BUFFER: Circular memory buffer to prevent data loss during WiFi outages.
13-
* 3. TELEMETRY: MQTT client for publishing processed metrics and alerts.
14-
* 4. MAINTENANCE: OTA (Over-The-Air) update listener for remote management.
15-
*/
3+
// Kaldor IIoT — Back Beam Width (BBW) Sensor Firmware.
4+
//
5+
// This Zig module implements the firmware for an ESP32-based monitoring
6+
// system. It is designed for high-reliability industrial environments,
7+
// featuring local data buffering, watchdog enforcement, and secure telemetry.
8+
//
9+
// SUBSYSTEMS:
10+
// 1. SENSORS: High-frequency (100Hz) acquisition of physical metrics.
11+
// 2. BUFFER: Circular memory buffer to prevent data loss during WiFi outages.
12+
// 3. TELEMETRY: MQTT client for publishing processed metrics and alerts.
13+
// 4. MAINTENANCE: OTA (Over-The-Air) update listener for remote management.
1614

1715
const std = @import("std");
1816
const config = @import("config.zig");

firmware-zig/src/ota.zig

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ pub const OtaError = enum {
3434
pub const OtaUpdater = struct {
3535
device_id: []const u8,
3636
state: OtaState = .idle,
37-
error: OtaError = .none,
37+
last_error: OtaError = .none,
3838
progress: u8 = 0,
3939
current_url: ?[]const u8 = null,
4040
bytes_received: usize = 0,
@@ -63,7 +63,7 @@ pub const OtaUpdater = struct {
6363
self.state = .downloading;
6464
self.progress = 0;
6565
self.bytes_received = 0;
66-
self.error = .none;
66+
self.last_error =.none;
6767

6868
if (builtin.os.tag == .freestanding) {
6969
// ESP32: Start OTA update
@@ -97,7 +97,7 @@ pub const OtaUpdater = struct {
9797
} else if (status < 0) {
9898
// Error
9999
self.state = .error_state;
100-
self.error = .download_failed;
100+
self.last_error =.download_failed;
101101
hal.print("OTA: Download failed\n");
102102
}
103103
} else {
@@ -115,7 +115,7 @@ pub const OtaUpdater = struct {
115115
hal.print("OTA: Verification passed, installing...\n");
116116
} else {
117117
self.state = .error_state;
118-
self.error = .verify_failed;
118+
self.last_error =.verify_failed;
119119
hal.print("OTA: Verification failed\n");
120120
}
121121
} else {
@@ -131,7 +131,7 @@ pub const OtaUpdater = struct {
131131
hal.restart();
132132
} else {
133133
self.state = .error_state;
134-
self.error = .install_failed;
134+
self.last_error =.install_failed;
135135
}
136136
} else {
137137
self.state = .complete;
@@ -164,7 +164,7 @@ pub const OtaUpdater = struct {
164164

165165
/// Get last error
166166
pub fn getError(self: *const Self) OtaError {
167-
return self.error;
167+
return self.last_error;
168168
}
169169

170170
/// Check if update is in progress

firmware-zig/src/sensors.zig

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -236,7 +236,7 @@ pub const SensorManager = struct {
236236
}
237237

238238
/// Calculate signal quality based on distance
239-
fn calculateQuality(self: *Self, distance: f32) u8 {
239+
fn calculateQuality(self: *const Self, distance: f32) u8 {
240240
_ = self;
241241

242242
// Quality degrades with distance and noise
@@ -263,14 +263,14 @@ pub const SensorManager = struct {
263263
// ============================================================================
264264

265265
test "SensorManager initialization" {
266-
var sm = SensorManager.init();
266+
const sm = SensorManager.init();
267267
// begin() would fail without hardware, but init() should work
268268
try std.testing.expect(!sm.ultrasonic_initialized);
269269
try std.testing.expect(!sm.dht_initialized);
270270
}
271271

272272
test "quality calculation" {
273-
var sm = SensorManager.init();
273+
const sm = SensorManager.init();
274274
try std.testing.expectEqual(@as(u8, 0), sm.calculateQuality(10));
275275
try std.testing.expectEqual(@as(u8, 95), sm.calculateQuality(150));
276276
try std.testing.expectEqual(@as(u8, 0), sm.calculateQuality(500));

0 commit comments

Comments
 (0)