diff --git a/Cargo.lock b/Cargo.lock index d1f009e..d23a6ec 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -140,6 +140,7 @@ dependencies = [ "can-dbc", "clap", "daedalus", + "definition-rs", "futures-util", "num_enum", "phf", @@ -161,6 +162,7 @@ dependencies = [ name = "calypso-cangen" version = "0.1.0" dependencies = [ + "definition-rs", "proc-macro2", "quote", "regex", @@ -333,11 +335,22 @@ name = "daedalus" version = "0.1.0" dependencies = [ "calypso-cangen", + "definition-rs", "proc-macro2", "quote", "serde_json", ] +[[package]] +name = "definition-rs" +version = "0.1.0" +dependencies = [ + "proc-macro2", + "quote", + "schemars", + "serde", +] + [[package]] name = "digest" version = "0.10.7" diff --git a/Cargo.toml b/Cargo.toml index 1ea44e9..7196fab 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -24,6 +24,7 @@ serde = { version = "1.0.228", features = ["derive"] } serde_json = "1.0.150" regex = "1.12.3" schemars = "1.2.1" +definition-rs = { path = "./Odyssey-Definitions/definition-rs"} [dependencies] rumqttc = "0.25.0" @@ -49,6 +50,8 @@ num_enum = "0.7.5" [target.'cfg(target_os = "linux")'.dependencies] socketcan = { version = "3.6.1", features = ["tokio"] } +definition-rs.workspace = true + [build-dependencies] protobuf-codegen = "3.7.2" diff --git a/Odyssey-Definitions b/Odyssey-Definitions index b3a32f1..7972023 160000 --- a/Odyssey-Definitions +++ b/Odyssey-Definitions @@ -1 +1 @@ -Subproject commit b3a32f1621076a2169694d947f0668782f5d1301 +Subproject commit 7972023297513d015075a5f39ae148a9a06fb2c1 diff --git a/libs/calypso-cangen/Cargo.toml b/libs/calypso-cangen/Cargo.toml index a674178..eb93376 100644 --- a/libs/calypso-cangen/Cargo.toml +++ b/libs/calypso-cangen/Cargo.toml @@ -12,3 +12,4 @@ serde_json = { workspace = true } thiserror = "2.0.18" schemars = { workspace = true } serde_path_to_error = "0.1.20" +definition-rs.workspace = true diff --git a/libs/calypso-cangen/src/can_gen_decode.rs b/libs/calypso-cangen/src/can_gen_decode.rs index 4462034..dd246b8 100644 --- a/libs/calypso-cangen/src/can_gen_decode.rs +++ b/libs/calypso-cangen/src/can_gen_decode.rs @@ -1,4 +1,4 @@ -use crate::can_types::{CANMsg, CANPoint, NetField}; +use definition_rs::{CANMsg, CANPoint, NetField}; use proc_macro2::Literal; use proc_macro2::TokenStream as ProcMacro2TokenStream; use quote::{format_ident, quote}; diff --git a/libs/calypso-cangen/src/can_gen_encode.rs b/libs/calypso-cangen/src/can_gen_encode.rs index a324faa..5288a7c 100644 --- a/libs/calypso-cangen/src/can_gen_encode.rs +++ b/libs/calypso-cangen/src/can_gen_encode.rs @@ -1,4 +1,4 @@ -use crate::can_types::{CANMsg, CANPoint}; +use definition_rs::{CANMsg, CANPoint}; use proc_macro2::Literal; use proc_macro2::TokenStream as ProcMacro2TokenStream; use quote::{format_ident, quote}; diff --git a/libs/calypso-cangen/src/can_gen_simulate.rs b/libs/calypso-cangen/src/can_gen_simulate.rs index 904c857..e6741ad 100644 --- a/libs/calypso-cangen/src/can_gen_simulate.rs +++ b/libs/calypso-cangen/src/can_gen_simulate.rs @@ -1,4 +1,4 @@ -use crate::can_types::{CANMsg, CANPoint, NetField, Sim}; +use definition_rs::{CANMsg, CANPoint, NetField, Sim}; use proc_macro2::TokenStream as ProcMacro2TokenStream; use quote::quote; use regex::Regex; diff --git a/libs/calypso-cangen/src/can_types.rs b/libs/calypso-cangen/src/can_types.rs deleted file mode 100644 index 25ab42a..0000000 --- a/libs/calypso-cangen/src/can_types.rs +++ /dev/null @@ -1,144 +0,0 @@ -use proc_macro2::TokenStream; -use quote::quote; -use schemars::JsonSchema; -use serde::{Deserialize, Serialize}; - -// Classes to represent levels of the CAN hierarchy -// For more specific descriptions, refer to the README -// in Embedded-Base/cangen - -// See https://nerdocs.atlassian.net/wiki/spaces/NER/pages/1162018881/Odyssey+Car+Configuration+Framework -#[derive(Serialize, Deserialize, Clone)] -#[serde(untagged, expecting = "CANMsg")] -pub enum OdysseyMsg { - Can(CANMsg), - Meta(MetaMsg), // to be indexed, but not recieved - MUST GO LAST -} - -#[derive(JsonSchema, Deserialize, Serialize, Debug, Clone)] -#[serde(deny_unknown_fields)] -pub struct MetaMsg { - pub desc: String, - pub fields: Vec, -} - -/** - * Class representing a CAN message - */ -#[derive(JsonSchema, Deserialize, Serialize, Clone, Debug)] -#[serde(deny_unknown_fields)] -pub struct CANMsg { - pub id: String, - pub desc: String, - pub points: Vec, - pub fields: Vec, - #[serde(skip_serializing_if = "Option::is_none")] - pub key: Option, - #[serde(skip_serializing_if = "Option::is_none")] - pub is_ext: Option, - #[serde(default)] - pub bidir_mode: BidirMode, - #[serde(skip_serializing_if = "Option::is_none")] - pub sim_freq: Option, - #[serde(skip_serializing_if = "Option::is_none")] - pub clients: Option>, -} - -#[derive(JsonSchema, Debug, Deserialize, Serialize, PartialEq, Copy, Clone)] -#[serde(rename_all(deserialize = "lowercase", serialize = "PascalCase"))] -#[derive(Default)] -pub enum BidirMode { - Oneshot, - #[default] - Broadcast, - Configuration, -} - -impl quote::ToTokens for BidirMode { - fn to_tokens(&self, tokens: &mut TokenStream) { - let path: TokenStream = match self { - BidirMode::Broadcast => { - quote!(::calypso_cangen::can_types::BidirMode::Broadcast) - } - BidirMode::Oneshot => quote!(::calypso_cangen::can_types::BidirMode::Oneshot), - BidirMode::Configuration => { - panic!("Configuration sendable message is not available yet") - } - }; - tokens.extend(path); - } -} - -/** - * Class representing a `NetField` of a CAN message - */ -#[derive(JsonSchema, Deserialize, Serialize, Clone, Debug)] -#[serde(deny_unknown_fields)] -pub struct NetField { - pub name: String, - pub unit: String, - pub doc: String, - pub desc: Option, - pub values: Vec, -} - -/** - * Class representing a `NetField` of a Meta message (there are no values) - */ -#[derive(JsonSchema, Deserialize, Serialize, Clone, Debug)] -#[serde(deny_unknown_fields)] -pub struct DumbNetField { - pub name: String, - pub unit: String, - pub doc: String, - pub desc: Option, -} - -/** - * Class representing a CAN point of a `NetField` - */ -#[derive(JsonSchema, Deserialize, Serialize, Clone, Debug)] -#[serde(deny_unknown_fields)] -pub struct CANPoint { - pub size: usize, - #[serde(skip_serializing_if = "Option::is_none")] - pub name: Option, - #[serde(skip_serializing_if = "Option::is_none")] - pub c_type: Option, - #[serde(skip_serializing_if = "Option::is_none")] - pub parse: Option, - #[serde(skip_serializing_if = "Option::is_none")] - pub signed: Option, - #[serde(skip_serializing_if = "Option::is_none")] - pub endianness: Option, - #[serde(skip_serializing_if = "Option::is_none")] - pub formatter: Option, - #[serde(skip_serializing_if = "Option::is_none")] - pub default: Option, - #[serde(skip_serializing_if = "Option::is_none")] - pub ieee754_f32: Option, - #[serde(skip_serializing_if = "Option::is_none")] - pub sim: Option, -} - -#[derive(JsonSchema, Deserialize, Serialize, Clone, Debug)] -pub struct Formatter { - pub key: String, - pub arg: f32, -} - -#[derive(JsonSchema, Deserialize, Serialize, Clone, Debug)] -#[serde(untagged, deny_unknown_fields)] -pub enum Sim { - SimRange { - min: f32, - max: f32, - inc_min: f32, - inc_max: f32, - #[serde(skip_serializing_if = "Option::is_none")] - round: Option, - }, - SimDiscrete { - options: Vec<[f32; 2]>, - }, -} diff --git a/libs/calypso-cangen/src/lib.rs b/libs/calypso-cangen/src/lib.rs index 720e8c5..e3d89d6 100644 --- a/libs/calypso-cangen/src/lib.rs +++ b/libs/calypso-cangen/src/lib.rs @@ -1,7 +1,6 @@ pub mod can_gen_decode; pub mod can_gen_encode; pub mod can_gen_simulate; -pub mod can_types; pub mod validate; /** * Path to CAN spec JSON files diff --git a/libs/calypso-cangen/src/validate.rs b/libs/calypso-cangen/src/validate.rs index c292b09..2fe60ce 100644 --- a/libs/calypso-cangen/src/validate.rs +++ b/libs/calypso-cangen/src/validate.rs @@ -1,5 +1,5 @@ use crate::CANGEN_SPEC_PATH; -use crate::can_types::{BidirMode, OdysseyMsg, Sim}; +use definition_rs::{BidirMode, OdysseyMsg, Sim}; use regex::Regex; use std::collections::HashSet; use std::fs; @@ -74,6 +74,11 @@ pub enum CANSpecError { #[error("Invalid topic name {0}")] InvalidTopicName(String), + #[error( + "Message {0} CAN ID {1} is too large. Did you mean to use an extended ID (is_ext=true) ?" + )] + CanIdTooLarge(String, String), + #[error(transparent)] // Pass-through for IO error IOError(#[from] std::io::Error), } @@ -196,6 +201,15 @@ fn validate_msg( )); } + let _id_int = u32::from_str_radix(_msg.id.clone().trim_start_matches("0x"), 16) + .unwrap_or_else(|_| panic!("Invalid CAN ID for message {}", _msg.desc)); + if !_msg.is_ext.unwrap_or(false) && _id_int > 0x7FF { + _errors.push(CANSpecError::CanIdTooLarge( + _msg.desc.clone(), + _msg.id.clone(), + )); + } + let mut _is_byte_aligned = true; // if the whole message has only byte aligned points let mut _contains_little_endians = false; // if the message contains any little endian points diff --git a/libs/daedalus/Cargo.toml b/libs/daedalus/Cargo.toml index 56096e7..ce27c41 100644 --- a/libs/daedalus/Cargo.toml +++ b/libs/daedalus/Cargo.toml @@ -11,3 +11,4 @@ calypso-cangen = { path = "../calypso-cangen" } proc-macro2.workspace = true quote.workspace = true serde_json.workspace = true +definition-rs.workspace = true diff --git a/libs/daedalus/src/lib.rs b/libs/daedalus/src/lib.rs index f09f5f1..536451b 100644 --- a/libs/daedalus/src/lib.rs +++ b/libs/daedalus/src/lib.rs @@ -5,7 +5,7 @@ use calypso_cangen::CANGEN_SPEC_PATH; use calypso_cangen::can_gen_decode::gen_decoder_fn; use calypso_cangen::can_gen_encode::gen_encoder_fn; use calypso_cangen::can_gen_simulate::gen_simulate_canmsg; -use calypso_cangen::can_types::{BidirMode, OdysseyMsg}; +use definition_rs::{BidirMode, OdysseyMsg}; use proc_macro::TokenStream; use proc_macro2::TokenStream as ProcMacro2TokenStream; use quote::{format_ident, quote}; @@ -23,7 +23,7 @@ pub fn gen_decode_data(_item: TokenStream) -> TokenStream { use std::io::Cursor; use bitstream_io::{BigEndian, LittleEndian, BitReader, BitRead}; use phf::phf_map; - use calypso_cangen::can_types::*; + use definition_rs::*; use crate::data::{DecodeData, FormatData}; }; let mut __decode_functions = quote! {}; @@ -137,7 +137,7 @@ pub fn gen_encode_data(_item: TokenStream) -> TokenStream { let __encode_prelude = quote! { use bitstream_io::{BigEndian, LittleEndian, BitWriter, BitWrite}; use phf::phf_map; - use calypso_cangen::can_types::*; + use definition_rs::*; use crate::data::{EncodeData, FormatData}; }; let mut __encode_functions = quote! {}; diff --git a/src/bin/nerdbc.rs b/src/bin/nerdbc.rs index 89d7875..0edc22d 100644 --- a/src/bin/nerdbc.rs +++ b/src/bin/nerdbc.rs @@ -1,7 +1,7 @@ use std::{env, fs::File, io::Read}; -use calypso_cangen::can_types::{CANMsg, CANPoint, Formatter, NetField, Sim}; use can_dbc::{ByteOrder, NumericValue}; +use definition_rs::{CANMsg, CANPoint, Formatter, NetField, Sim}; /// decode a DBC file and paste (mostly) compliant JSON to stdout fn main() { @@ -97,7 +97,7 @@ fn main() { is_ext: None, sim_freq: None, clients: None, - bidir_mode: calypso_cangen::can_types::BidirMode::Broadcast, + bidir_mode: definition_rs::BidirMode::Broadcast, }); } diff --git a/src/bin/to_json_schema.rs b/src/bin/to_json_schema.rs index 1506689..922a61b 100644 --- a/src/bin/to_json_schema.rs +++ b/src/bin/to_json_schema.rs @@ -1,4 +1,4 @@ -use calypso_cangen::can_types::CANMsg; +use definition_rs::CANMsg; use schemars::schema_for; fn main() { diff --git a/src/main.rs b/src/main.rs index 20eccf9..2fef319 100644 --- a/src/main.rs +++ b/src/main.rs @@ -13,8 +13,8 @@ use calypso::{ serverdata::{self, ServerData}, }, }; -use calypso_cangen::can_types::BidirMode; use clap::Parser; +use definition_rs::BidirMode; use protobuf::Message; use rumqttc::v5::{ AsyncClient, Event, EventLoop, MqttOptions,