Add command to show firmware Git hash #167

Open
atse wants to merge 2 commits from atse/thermostat:show-firmware-ver into master
9 changed files with 245 additions and 1 deletions

165
Cargo.lock generated
View File

@ -62,6 +62,21 @@ version = "1.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693" checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693"
[[package]]
name = "bitflags"
version = "2.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ed570934406eb16438a4e976b1b4500774099c13b8cb96eec99f620f05090ddf"
[[package]]
name = "built"
version = "0.7.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c360505aed52b7ec96a3636c3f039d99103c37d1d9b4f7a8c743d3ea9ffcd03b"
dependencies = [
"git2",
]
[[package]] [[package]]
name = "byteorder" name = "byteorder"
version = "1.3.4" version = "1.3.4"
@ -74,6 +89,16 @@ version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5" checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5"
[[package]]
name = "cc"
version = "1.0.83"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f1174fb0b6ec23863f8b971027804a42614e347eafb0a95bf0b12cdae21fc4d0"
dependencies = [
"jobserver",
"libc",
]
[[package]] [[package]]
name = "cfg-if" name = "cfg-if"
version = "0.1.10" version = "0.1.10"
@ -90,6 +115,12 @@ dependencies = [
"num-traits", "num-traits",
] ]
[[package]]
name = "const-str"
version = "0.5.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3618cccc083bb987a415d85c02ca6c9994ea5b44731ec28b9ecf09658655fba9"
[[package]] [[package]]
name = "cortex-m" name = "cortex-m"
version = "0.6.7" version = "0.6.7"
@ -204,6 +235,15 @@ dependencies = [
"void", "void",
] ]
[[package]]
name = "form_urlencoded"
version = "1.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e13624c2627564efccf4934284bdd98cbaa14e79b0b5a141218e507b3a823456"
dependencies = [
"percent-encoding",
]
[[package]] [[package]]
name = "generic-array" name = "generic-array"
version = "0.12.3" version = "0.12.3"
@ -232,6 +272,19 @@ dependencies = [
"version_check", "version_check",
] ]
[[package]]
name = "git2"
version = "0.19.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b903b73e45dc0c6c596f2d37eccece7c1c8bb6e4407b001096387c63d0d93724"
dependencies = [
"bitflags 2.4.2",
"libc",
"libgit2-sys",
"log",
"url",
]
[[package]] [[package]]
name = "hash32" name = "hash32"
version = "0.1.1" version = "0.1.1"
@ -254,12 +307,61 @@ dependencies = [
"stable_deref_trait", "stable_deref_trait",
] ]
[[package]]
name = "idna"
version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "634d9b1461af396cad843f47fdba5597a4f9e6ddd4bfb6ff5d85028c25cb12f6"
dependencies = [
"unicode-bidi",
"unicode-normalization",
]
[[package]]
name = "jobserver"
version = "0.1.27"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8c37f63953c4c63420ed5fd3d6d398c719489b9f872b9fa683262f8edd363c7d"
dependencies = [
"libc",
]
[[package]]
name = "libc"
version = "0.2.152"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "13e3bf6590cbc649f4d1a3eefc9d5d6eb746f5200ffb04e5e142700b8faa56e7"
[[package]]
name = "libgit2-sys"
version = "0.17.0+1.8.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "10472326a8a6477c3c20a64547b0059e4b0d086869eee31e6d7da728a8eb7224"
dependencies = [
"cc",
"libc",
"libz-sys",
"pkg-config",
]
[[package]] [[package]]
name = "libm" name = "libm"
version = "0.2.1" version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c7d73b3f436185384286bd8098d17ec07c9a7d2388a6599f824d8502b529702a" checksum = "c7d73b3f436185384286bd8098d17ec07c9a7d2388a6599f824d8502b529702a"
[[package]]
name = "libz-sys"
version = "1.1.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "037731f5d3aaa87a5675e895b63ddff1a87624bc29f77004ea829809654e48f6"
dependencies = [
"cc",
"libc",
"pkg-config",
"vcpkg",
]
[[package]] [[package]]
name = "log" name = "log"
version = "0.4.11" version = "0.4.11"
@ -342,6 +444,18 @@ dependencies = [
"cortex-m-semihosting", "cortex-m-semihosting",
] ]
[[package]]
name = "percent-encoding"
version = "2.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e"
[[package]]
name = "pkg-config"
version = "0.3.29"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2900ede94e305130c13ddd391e0ab7cbaeb783945ae07a279c268cb05109c6cb"
[[package]] [[package]]
name = "postcard" name = "postcard"
version = "0.5.1" version = "0.5.1"
@ -469,7 +583,7 @@ version = "0.7.5"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3e4a069bef843d170df47e7c0a8bf8d037f217d9f5b325865acc3e466ffe40d3" checksum = "3e4a069bef843d170df47e7c0a8bf8d037f217d9f5b325865acc3e466ffe40d3"
dependencies = [ dependencies = [
"bitflags", "bitflags 1.2.1",
"byteorder", "byteorder",
"log", "log",
"managed", "managed",
@ -553,7 +667,9 @@ version = "0.0.0"
dependencies = [ dependencies = [
"bare-metal 1.0.0", "bare-metal 1.0.0",
"bit_field", "bit_field",
"built",
"byteorder", "byteorder",
"const-str",
"cortex-m 0.6.7", "cortex-m 0.6.7",
"cortex-m-log", "cortex-m-log",
"cortex-m-rt 0.6.13", "cortex-m-rt 0.6.13",
@ -576,12 +692,42 @@ dependencies = [
"usbd-serial", "usbd-serial",
] ]
[[package]]
name = "tinyvec"
version = "1.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "87cc5ceb3875bb20c2890005a4e226a4651264a5c75edb2421b52861a0a0cb50"
dependencies = [
"tinyvec_macros",
]
[[package]]
name = "tinyvec_macros"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20"
[[package]] [[package]]
name = "typenum" name = "typenum"
version = "1.12.0" version = "1.12.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "373c8a200f9e67a0c95e62a4f52fbf80c23b4381c05a17845531982fa99e6b33" checksum = "373c8a200f9e67a0c95e62a4f52fbf80c23b4381c05a17845531982fa99e6b33"
[[package]]
name = "unicode-bidi"
version = "0.3.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "08f95100a766bf4f8f28f90d77e0a5461bbdb219042e7679bebe79004fed8d75"
[[package]]
name = "unicode-normalization"
version = "0.1.22"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5c5713f0fc4b5db668a2ac63cdb7bb4469d8c9fed047b1d0292cc7b0ce2ba921"
dependencies = [
"tinyvec",
]
[[package]] [[package]]
name = "unicode-xid" name = "unicode-xid"
version = "0.2.1" version = "0.2.1"
@ -599,6 +745,17 @@ dependencies = [
"typenum", "typenum",
] ]
[[package]]
name = "url"
version = "2.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "31e6302e3bb753d46e83516cae55ae196fc0c309407cf11ab35cc51a4c2a4633"
dependencies = [
"form_urlencoded",
"idna",
"percent-encoding",
]
[[package]] [[package]]
name = "usb-device" name = "usb-device"
version = "0.2.7" version = "0.2.7"
@ -622,6 +779,12 @@ version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "876e32dcadfe563a4289e994f7cb391197f362b6315dc45e8ba4aa6f564a4b3c" checksum = "876e32dcadfe563a4289e994f7cb391197f362b6315dc45e8ba4aa6f564a4b3c"
[[package]]
name = "vcpkg"
version = "0.2.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426"
[[package]] [[package]]
name = "version_check" name = "version_check"
version = "0.9.2" version = "0.9.2"

View File

@ -37,6 +37,10 @@ serde = { version = "1.0", default-features = false, features = ["derive"] }
heapless = "0.5" heapless = "0.5"
serde-json-core = "0.1" serde-json-core = "0.1"
sfkv = "0.1" sfkv = "0.1"
const-str = { version = "0.5.7" }
[build-dependencies]
built = { version = "0.7", features = ["git2"] }
[features] [features]
semihosting = ["panic-semihosting", "cortex-m-log/semihosting"] semihosting = ["panic-semihosting", "cortex-m-log/semihosting"]

View File

@ -127,6 +127,7 @@ formatted as line-delimited JSON.
| `fcurve <a> <b> <c>` | Set fan controller curve coefficients (see *Fan control* section) | | `fcurve <a> <b> <c>` | Set fan controller curve coefficients (see *Fan control* section) |
| `fcurve default` | Set fan controller curve coefficients to defaults (see *Fan control* section) | | `fcurve default` | Set fan controller curve coefficients to defaults (see *Fan control* section) |
| `hwrev` | Show hardware revision, and settings related to it | | `hwrev` | Show hardware revision, and settings related to it |
| `version` | Show firmware version |
## USB ## USB

View File

@ -15,4 +15,6 @@ fn main() {
// Only re-run the build script when memory.x is changed, // Only re-run the build script when memory.x is changed,
// instead of when any part of the source code changes. // instead of when any part of the source code changes.
println!("cargo:rerun-if-changed=memory.x"); println!("cargo:rerun-if-changed=memory.x");
built::write_built_file().expect("Failed to acquire build-time information");
Review

Maybe this shouldn't be a hard error?

Maybe this shouldn't be a hard error?
} }

View File

@ -42,6 +42,7 @@
nativeBuildInputs = [ pkgs.llvm ]; nativeBuildInputs = [ pkgs.llvm ];
NIX_DRV_DIRTY_REV = "${toString (self.rev or self.dirtyRev or "unknown")}";
buildPhase = '' buildPhase = ''
cargo build --release --bin thermostat cargo build --release --bin thermostat
''; '';

View File

@ -6,6 +6,7 @@ use super::{
}, },
config::ChannelConfig, config::ChannelConfig,
dfu, dfu,
firmware_ver,
flash_store::FlashStore, flash_store::FlashStore,
hw_rev::HWRev, hw_rev::HWRev,
net, FanCtrl, CHANNEL_CONFIG_KEY, net, FanCtrl, CHANNEL_CONFIG_KEY,
@ -42,6 +43,10 @@ pub enum Error {
Flash, Flash,
} }
mod built_info {
include!(concat!(env!("OUT_DIR"), "/built.rs"));
}
pub type JsonBuffer = Vec<u8, U1024>; pub type JsonBuffer = Vec<u8, U1024>;
fn send_line(socket: &mut TcpSocket, data: &[u8]) -> bool { fn send_line(socket: &mut TcpSocket, data: &[u8]) -> bool {
@ -463,6 +468,20 @@ impl Handler {
} }
} }
fn show_firmware_version(socket: &mut TcpSocket) -> Result<Handler, Error> {
match firmware_ver::summary() {
Ok(buf) => {
send_line(socket, &buf);
Ok(Handler::Handled)
}
Err(e) => {
error!("unable to serialize FirmwareVer summary: {:?}", e);
let _ = writeln!(socket, "{{\"error\":\"{:?}\"}}", e);
Err(Error::Report)
}
}
}
pub fn handle_command( pub fn handle_command(
command: Command, command: Command,
socket: &mut TcpSocket, socket: &mut TcpSocket,
@ -523,6 +542,7 @@ impl Handler {
} }
Command::FanCurveDefaults => Handler::fan_defaults(socket, fan_ctrl), Command::FanCurveDefaults => Handler::fan_defaults(socket, fan_ctrl),
Command::ShowHWRev => Handler::show_hwrev(socket, hwrev), Command::ShowHWRev => Handler::show_hwrev(socket, hwrev),
Command::ShowFirmwareVer => Handler::show_firmware_version(socket),
} }
} }
} }

View File

@ -194,6 +194,7 @@ pub enum Command {
}, },
FanCurveDefaults, FanCurveDefaults,
ShowHWRev, ShowHWRev,
ShowFirmwareVer,
} }
fn end(input: &[u8]) -> IResult<&[u8], ()> { fn end(input: &[u8]) -> IResult<&[u8], ()> {
@ -578,6 +579,7 @@ fn command(input: &[u8]) -> IResult<&[u8], Result<Command, Error>> {
fan, fan,
fan_curve, fan_curve,
value(Ok(Command::ShowHWRev), tag("hwrev")), value(Ok(Command::ShowHWRev), tag("hwrev")),
value(Ok(Command::ShowFirmwareVer), tag("version")),
))(input) ))(input)
} }
@ -867,4 +869,10 @@ mod test {
let command = Command::parse(b"hwrev"); let command = Command::parse(b"hwrev");
assert_eq!(command, Ok(Command::ShowHWRev)); assert_eq!(command, Ok(Command::ShowHWRev));
} }
#[test]
fn parse_firmware_ver() {
let command = Command::parse(b"version");
assert_eq!(command, Ok(Command::ShowFirmwareVer));
}
} }

44
src/firmware_ver.rs Normal file
View File

@ -0,0 +1,44 @@
use crate::command_handler::JsonBuffer;
use serde::Serialize;
mod built_info {
include!(concat!(env!("OUT_DIR"), "/built.rs"));
}
#[derive(Serialize)]
pub struct FirmwareSummary {
git_hash: Option<&'static str>,
git_dirty: Option<bool>,
}
impl FirmwareSummary {
pub const fn get() -> FirmwareSummary {
if let Some(rev) = option_env!("NIX_DRV_DIRTY_REV") {
Review

Is there environment variables in the firmware?
And I think it's better to use some different variable/approach, because now it depends on Nix, which may be absent during build process. Consider using git directly or invert the dependency, or combine both - let Nix insert the revision and if absent, default to git info.

~~Is there environment variables in the firmware?~~ And I think it's better to use some different variable/approach, because now it depends on Nix, which may be absent during build process. Consider using git directly or invert the dependency, or combine both - let Nix insert the revision and if absent, default to git info.
Review

Agree. You can add logic to fetch the git info if the NIX_DRV_DIRTY_REV environment variable is not set.
(as nix does not copy the .git folder, you cannot call git cmd in build.rs during nix build stage.)

Agree. You can add logic to fetch the git info if the NIX_DRV_DIRTY_REV environment variable is not set. (as nix does not copy the .git folder, you cannot call git cmd in build.rs during nix build stage.)
if const_str::equal!(rev, "unknown") {
FirmwareSummary {
git_hash: None,
git_dirty: None,
}
} else if const_str::ends_with!(rev, "-dirty") {
FirmwareSummary {
git_hash: const_str::strip_suffix!(rev, "-dirty"),
git_dirty: Some(true),
}
} else {
FirmwareSummary {
git_hash: Some(rev),
git_dirty: Some(false),
Review

Do we really need to parse this here? Why not just send the string verbatim? What is consuming that string?

Do we really need to parse this here? Why not just send the string verbatim? What is consuming that string?
}
}
} else {
FirmwareSummary {
git_hash: built_info::GIT_COMMIT_HASH,
git_dirty: built_info::GIT_DIRTY,
}
}
}
}
pub fn summary() -> Result<JsonBuffer, serde_json_core::ser::Error> {
serde_json_core::to_vec(&FirmwareSummary::get())
}

View File

@ -50,6 +50,7 @@ mod flash_store;
use command_handler::Handler; use command_handler::Handler;
mod fan_ctrl; mod fan_ctrl;
use fan_ctrl::FanCtrl; use fan_ctrl::FanCtrl;
mod firmware_ver;
mod hw_rev; mod hw_rev;
const HSE: MegaHertz = MegaHertz(8); const HSE: MegaHertz = MegaHertz(8);