diff --git a/Cargo.toml b/Cargo.toml
index ebaa5b25..18ef5d86 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -30,7 +30,7 @@ members = [
"samples/managed_subscribe",
"samples/mixed",
"samples/property",
- "samples/seat_massager",
+ # "samples/seat_massager",
"samples/streaming",
"samples/tutorial"
]
@@ -38,9 +38,9 @@ members = [
[workspace.dependencies]
async-std = "^1.5"
bytes = "1.4.0"
-config = "0.13.3"
+config = "0.14.0"
dyn-clone = "1.0.14"
-env_logger= "0.10.0"
+env_logger= "0.11.2"
futures = "0.3.28"
futures-core = "0.3.4"
futures-util = "0.3.28"
@@ -56,13 +56,13 @@ paho-mqtt = "0.12"
parking_lot = "0.12.1"
prost = "0.12"
prost-types = "0.12"
-regex = " 1.9.3"
-sdl2 = "0.35.2"
+regex = " 1.10.3"
+sdl2 = "0.34.0"
serde = "1.0.160"
serde_derive = "1.0.163"
serde_json = "^1.0"
-strum = "0.25"
-strum_macros = "0.25.1"
+strum = "0.26.1"
+strum_macros = "0.26.1"
tokio = "1.29.1"
tokio-console-subscriber = { version = "0.2.0", package = "console-subscriber" }
tokio-stream = "0.1.14"
diff --git a/README.md b/README.md
index 1f8e0d5b..36a5f1de 100644
--- a/README.md
+++ b/README.md
@@ -85,7 +85,7 @@ sudo apt install -y libsdl2-dev
You will need to install dotnet-sdk for the dtdl-tools crate. This can be done by executing:
```shell
-sudo apt install -y dotnet-sdk-7.0
+sudo apt install -y dotnet-sdk-8.0
```
### Install MQTT Broker
diff --git a/digital-twin-model/dtdl/dtmi/sdv/airbag_seat_massager-1.json b/digital-twin-model/dtdl/dtmi/sdv/airbag_seat_massager-1.json
new file mode 100644
index 00000000..43574653
--- /dev/null
+++ b/digital-twin-model/dtdl/dtmi/sdv/airbag_seat_massager-1.json
@@ -0,0 +1,116 @@
+{
+ "@context": ["dtmi:dtdl:context;3"],
+ "@type": "Interface",
+ "@id": "dtmi:sdv:airbag_seat_massager;1",
+ "description": "Airbag Seat Massager Interface",
+ "extends": "dtmi:sdv:seat_massager;1",
+ "contents": [
+ {
+ "@type": "Command",
+ "@id": "dtmi:sdv:airbag_seat_massager:store_sequence;1",
+ "name": "store_sequence",
+ "request": {
+ "name": "request",
+ "schema": {
+ "@type": "Object",
+ "fields": [
+ {
+ "name": "sequence",
+ "schema": "dtmi:sdv:massage_sequence;1"
+ }
+ ]
+ }
+ },
+ "response": {
+ "name": "response",
+ "schema": {
+ "@type": "Object",
+ "fields": [
+ {
+ "name": "status",
+ "schema": "dtmi:sdv:airbag_seat_massager:status;1"
+ }
+ ]
+ }
+ }
+ },
+ {
+ "@type": "Command",
+ "@id": "dtmi:sdv:airbag_seat_massager:perform_step;1",
+ "name": "perfom_step",
+ "request": {
+ "name": "request",
+ "schema": {
+ "@type": "Object",
+ "fields": [
+ {
+ "name": "sequence",
+ "schema": "dtmi:sdv:massage_sequence;1"
+ }
+ ]
+ }
+ },
+ "response": {
+ "name": "response",
+ "schema": {
+ "@type": "Object",
+ "fields": [
+ {
+ "name": "status",
+ "schema": "dtmi:sdv:airbag_seat_massager:status;1"
+ }
+ ]
+ }
+ }
+ }
+ ],
+ "schemas": [
+ {
+ "@id": "dtmi:sdv:airbag_seat_massager:status;1",
+ "@type": "Object",
+ "fields": [
+ {
+ "name": "code",
+ "schema": "integer"
+ },
+ {
+ "name": "message",
+ "schema": "string"
+ }
+ ]
+ },
+ {
+ "@id": "dtmi:sdv:massage_sequence;1",
+ "@type": "Array",
+ "elementSchema": "dtmi:sdv:massage_step;1"
+ },
+ {
+ "@id": "dtmi:sdv:massage_step;1",
+ "@type": "Array",
+ "elementSchema": "dtmi:sdv:airbag_adjustments;1"
+ },
+ {
+ "@id": "dtmi:sdv:airbag_adjustments;1",
+ "@type": "Array",
+ "elementSchema": "dtmi:sdv:airbag_adjustment;1"
+ },
+ {
+ "@id": "dtmi:sdv:airbag_adjustment;1",
+ "@type": "Object",
+ "fields": [
+ {
+ "name": "airbag_identifier",
+ "schema": "integer"
+ },
+ {
+ "name": "inflation_level",
+ "schema": "integer"
+ },
+ {
+ "name": "duration",
+ "schema": "duration"
+ }
+ ]
+ }
+ ]
+}
diff --git a/digital-twin-model/dtdl/dtmi/sdv/basic_airbag_seat_massager-1.json b/digital-twin-model/dtdl/dtmi/sdv/basic_airbag_seat_massager-1.json
new file mode 100644
index 00000000..83e08328
--- /dev/null
+++ b/digital-twin-model/dtdl/dtmi/sdv/basic_airbag_seat_massager-1.json
@@ -0,0 +1,7 @@
+{
+ "@context": ["dtmi:dtdl:context;3"],
+ "@type": "Interface",
+ "@id": "dtmi:sdv:basic_airbag_seat_massager;1",
+ "description": "Basic Airbag Seat Massager Interface",
+ "extends": "dtmi:sdv:airbag_seat_massager;1"
+}
diff --git a/digital-twin-model/dtdl/dtmi/sdv/cabin-1.json b/digital-twin-model/dtdl/dtmi/sdv/cabin-1.json
new file mode 100644
index 00000000..3ae3d164
--- /dev/null
+++ b/digital-twin-model/dtdl/dtmi/sdv/cabin-1.json
@@ -0,0 +1,62 @@
+{
+ "@context": ["dtmi:dtdl:context;3"],
+ "@type": "Interface",
+ "@id": "dtmi:sdv:cabin;1",
+ "description": "Cabin Interface",
+ "contents": [
+ {
+ "@type": "Relationship",
+ "@id": "dtmi:sdv:cabin:has_infotainment;1",
+ "target": "dtmi:sdv:infotainment;1",
+ "name": "has_infotainment",
+ "maxMultiplicity": 1
+ },
+ {
+ "@type": "Relationship",
+ "@id": "dtmi:sdv:cabin:has_hvac;1",
+ "target": "dtmi:sdv:hvac;1",
+ "name": "has_hvac",
+ "maxMultiplicity": 1
+ },
+ {
+ "@type": "Relationship",
+ "@id": "dtmi:sdv:cabin:has_seat;1",
+ "name": "has_seat",
+ "target": "dtmi:sdv:seat;1",
+ "properties": [
+ {
+ "@type": "Property",
+ "@id": "dtmi:sdv:seat:seat_row;1",
+ "name": "seat_row",
+ "schema": "integer"
+ },
+ {
+ "@type": "Property",
+ "@id": "dtmi:sdv:Seat:seat_position;1",
+ "name": "seat_position",
+ "schema": {
+ "@type": "Enum",
+ "valueSchema": "string",
+ "enumValues": [
+ {
+ "name": "left",
+ "displayName": "left",
+ "enumValue": "left"
+ },
+ {
+ "name": "center",
+ "displayName": "center",
+ "enumValue": "center"
+ },
+ {
+ "name": "right",
+ "displayName": "right",
+ "enumValue": "right"
+ }
+ ]
+ }
+ }
+ ]
+ }
+ ]
+}
diff --git a/digital-twin-model/dtdl/dtmi/sdv/camera-1.json b/digital-twin-model/dtdl/dtmi/sdv/camera-1.json
new file mode 100644
index 00000000..5236d1b6
--- /dev/null
+++ b/digital-twin-model/dtdl/dtmi/sdv/camera-1.json
@@ -0,0 +1,31 @@
+{
+ "@context": "dtmi:dtdl:context;3",
+ "@type": "Interface",
+ "@id": "dtmi:sdv:camera;1",
+ "description": "Cabin camera.",
+ "contents": [
+ {
+ "@type": "Property",
+ "@id": "dtmi:sdv:camera:feed;1",
+ "name": "Feed",
+ "description": "The camera feed inside of the cabin.",
+ "schema": {
+ "@type": "Object",
+ "fields": [
+ {
+ "name": "media_type",
+ "schema": "string"
+ },
+ {
+ "name": "media_content",
+ "description": "An array of bytes (represented by integers here).",
+ "schema": {
+ "@type": "Array",
+ "elementSchema": "integer"
+ }
+ }
+ ]
+ }
+ }
+ ]
+}
diff --git a/digital-twin-model/dtdl/dtmi/sdv/hmi-1.json b/digital-twin-model/dtdl/dtmi/sdv/hmi-1.json
new file mode 100644
index 00000000..d36f652c
--- /dev/null
+++ b/digital-twin-model/dtdl/dtmi/sdv/hmi-1.json
@@ -0,0 +1,21 @@
+{
+ "@context": ["dtmi:dtdl:context;3"],
+ "@type": "Interface",
+ "@id": "dtmi:sdv:hmi;1",
+ "description": "The Human Machine Interface.",
+ "contents": [
+ {
+ "@type": "Command",
+ "@id": "dtmi:sdv:hmi:show_notification;1",
+ "name": "show_notification",
+ "description": "Show a notification on the HMI.",
+ "request": {
+ "@id": "dtmi:sdv:hmi:show_notification:request;1",
+ "name": "notification",
+ "displayName": "Notification",
+ "description": "The notification to show on the HMI.",
+ "schema": "string"
+ }
+ }
+ ]
+}
diff --git a/digital-twin-model/dtdl/dtmi/sdv/hvac-1.json b/digital-twin-model/dtdl/dtmi/sdv/hvac-1.json
new file mode 100644
index 00000000..b3dfcd20
--- /dev/null
+++ b/digital-twin-model/dtdl/dtmi/sdv/hvac-1.json
@@ -0,0 +1,22 @@
+{
+ "@context": ["dtmi:dtdl:context;3"],
+ "@type": "Interface",
+ "@id": "dtmi:sdv:hvac;1",
+ "description": "Heat, Ventilation and Air Conditioning",
+ "contents": [
+ {
+ "@type": "Property",
+ "@id": "dtmi:sdv:hvac:ambient_air_temperature;1",
+ "name": "ambient_air_temperature",
+ "description": "The immediate surroundings' air temperature (in Fahrenheit).",
+ "schema": "integer"
+ },
+ {
+ "@type": "Property",
+ "@id": "dtmi:sdv:hvac:is_air_conditioning_active;1",
+ "name": "is_air_conditioning_active",
+ "description": "Is air conditioning active?",
+ "schema": "boolean"
+ }
+ ]
+}
diff --git a/digital-twin-model/dtdl/dtmi/sdv/infotainment-1.json b/digital-twin-model/dtdl/dtmi/sdv/infotainment-1.json
new file mode 100644
index 00000000..2087c304
--- /dev/null
+++ b/digital-twin-model/dtdl/dtmi/sdv/infotainment-1.json
@@ -0,0 +1,15 @@
+{
+ "@context": ["dtmi:dtdl:context;3"],
+ "@type": "Interface",
+ "@id": "dtmi:sdv:infotainment;1",
+ "description": "Infotainment Interface",
+ "contents": [
+ {
+ "@type": "Relationship",
+ "@id": "dtmi:sdv:infotainment:has_hmi;1",
+ "target": "dtmi:sdv:hmi;1",
+ "name": "has_hmi",
+ "maxMultiplicity": 1
+ }
+ ]
+}
diff --git a/digital-twin-model/dtdl/dtmi/sdv/obd-1.json b/digital-twin-model/dtdl/dtmi/sdv/obd-1.json
new file mode 100644
index 00000000..de669d23
--- /dev/null
+++ b/digital-twin-model/dtdl/dtmi/sdv/obd-1.json
@@ -0,0 +1,15 @@
+{
+ "@context": "dtmi:dtdl:context;3",
+ "@type": "Interface",
+ "@id": "dtmi:sdv:obd;1",
+ "description": "On-board Diagnostics Interface",
+ "contents": [
+ {
+ "@type": "Property",
+ "@id": "dtmi:sdv:obd:hybri_bBattery_remaining;1",
+ "name": "hybrid_battery_remaining",
+ "description": "The remaining hybrid battery life.",
+ "schema": "integer"
+ }
+ ]
+}
diff --git a/digital-twin-model/dtdl/dtmi/sdv/premium_airbag_seat_massager-1.json b/digital-twin-model/dtdl/dtmi/sdv/premium_airbag_seat_massager-1.json
new file mode 100644
index 00000000..723405a8
--- /dev/null
+++ b/digital-twin-model/dtdl/dtmi/sdv/premium_airbag_seat_massager-1.json
@@ -0,0 +1,7 @@
+{
+ "@context": ["dtmi:dtdl:context;3"],
+ "@type": "Interface",
+ "@id": "dtmi:sdv:premium_airbag_seat_massager;1",
+ "description": "Premium Airbag Seat Massager Interface",
+ "extends": "dtmi:sdv:airbag_seat_massager;1"
+}
diff --git a/digital-twin-model/dtdl/dtmi/sdv/seat-1.json b/digital-twin-model/dtdl/dtmi/sdv/seat-1.json
new file mode 100644
index 00000000..1e4deac1
--- /dev/null
+++ b/digital-twin-model/dtdl/dtmi/sdv/seat-1.json
@@ -0,0 +1,6 @@
+{
+ "@context": ["dtmi:dtdl:context;3"],
+ "@type": "Interface",
+ "@id": "dtmi:sdv:seat;1",
+ "description": "Seat Interface"
+}
diff --git a/digital-twin-model/dtdl/dtmi/sdv/seat_massager-1.json b/digital-twin-model/dtdl/dtmi/sdv/seat_massager-1.json
new file mode 100644
index 00000000..bf74a5f6
--- /dev/null
+++ b/digital-twin-model/dtdl/dtmi/sdv/seat_massager-1.json
@@ -0,0 +1,110 @@
+{
+ "@context": ["dtmi:dtdl:context;3"],
+ "@type": "Interface",
+ "@id": "dtmi:sdv:seat_massager;1",
+ "description": "Seat Massager Interface",
+ "contents": [
+ {
+ "@type": "Property",
+ "name": "sequence_names",
+ "@id": "dtmi:sdv:seat_massager:sequence_names;1",
+ "description": "The name of each of the stored sequences.",
+ "schema": {
+ "@type": "Array",
+ "elementSchema": "string"
+ }
+ },
+ {
+ "@type": "Command",
+ "name": "load_sequence",
+ "request": {
+ "name": "request",
+ "schema": {
+ "@type": "Object",
+ "fields": [
+ {
+ "name": "sequence_name",
+ "schema": "string"
+ }
+ ]
+ }
+ },
+ "response": {
+ "name": "response",
+ "schema": {
+ "@type": "Object",
+ "fields": [
+ {
+ "name": "status",
+ "schema": "dtmi:sdv:seatmassager:status;1"
+ }
+ ]
+ }
+ }
+ },
+ {
+ "@type": "Command",
+ "name": "pause",
+ "response": {
+ "name": "response",
+ "schema": {
+ "@type": "Object",
+ "fields": [
+ {
+ "name": "status",
+ "schema": "dtmi:sdv:seatmassager:status;1"
+ }
+ ]
+ }
+ }
+ },
+ {
+ "@type": "Command",
+ "name": "play",
+ "response": {
+ "name": "response",
+ "schema": {
+ "@type": "Object",
+ "fields": [
+ {
+ "name": "status",
+ "schema": "dtmi:sdv:seatmassager:status;1"
+ }
+ ]
+ }
+ }
+ },
+ {
+ "@type": "Command",
+ "name": "reset",
+ "response": {
+ "name": "response",
+ "schema": {
+ "@type": "Object",
+ "fields": [
+ {
+ "name": "status",
+ "schema": "dtmi:sdv:seatmassager:status;1"
+ }
+ ]
+ }
+ }
+ }
+ ],
+ "schemas": [
+ {
+ "@id": "dtmi:sdv:seatmassager:status;1",
+ "@type": "Object",
+ "fields": [
+ {
+ "name": "code",
+ "schema": "integer"
+ },
+ {
+ "name": "message",
+ "schema": "string"
+ }
+ ]
+ }
+ ]
+}
diff --git a/digital-twin-model/dtdl/dtmi/sdv/seat_with_massager-1.json b/digital-twin-model/dtdl/dtmi/sdv/seat_with_massager-1.json
new file mode 100644
index 00000000..9849b0ee
--- /dev/null
+++ b/digital-twin-model/dtdl/dtmi/sdv/seat_with_massager-1.json
@@ -0,0 +1,16 @@
+{
+ "@context": ["dtmi:dtdl:context;3"],
+ "@type": "Interface",
+ "@id": "dtmi:sdv:seat_with_massager;1",
+ "description": "Seat with Massager Interface",
+ "extends": "dtmi:sdv:seat;1",
+ "contents": [
+ {
+ "@type": "Relationship",
+ "@id": "dtmi:sdv:seat_with_massager:has_seat_massager;1",
+ "target": "dtmi:sdv:seatmassager;1",
+ "name": "has_seat_massager",
+ "maxMultiplicity": 1
+ }
+ ]
+}
diff --git a/digital-twin-model/dtdl/dtmi/sdv/vehicle-1.json b/digital-twin-model/dtdl/dtmi/sdv/vehicle-1.json
new file mode 100644
index 00000000..36a3c01f
--- /dev/null
+++ b/digital-twin-model/dtdl/dtmi/sdv/vehicle-1.json
@@ -0,0 +1,32 @@
+{
+ "@context": ["dtmi:dtdl:context;3"],
+ "@type": "Interface",
+ "@id": "dtmi:sdv:vehicle;1",
+ "description": "Vehicle Interface",
+ "contents": [
+ {
+ "@type": "Property",
+ "@id": "dtmi:sdv:vehicle:vehicle_identification;1",
+ "name": "vehicle_identification",
+ "description": "Vehicle Identification",
+ "schema": {
+ "@type": "Object",
+ "fields": [
+ {
+ "@id": "dtmi:sdv:vehicle:vehicle_identification:vin;1",
+ "name": "vin",
+ "description": "Vehicle Identification Number",
+ "schema": "string"
+ }
+ ]
+ }
+ },
+ {
+ "@type": "Relationship",
+ "@id": "dtmi:sdv:vehicle:has_cabin;1",
+ "target": "dtmi:sdv:cabin;1",
+ "name": "has_cabin",
+ "maxMultiplicity": 1
+ }
+ ]
+}
diff --git a/digital-twin-model/dtdl/v3/spec/sdv/airbag_seat_massager.json b/digital-twin-model/dtdl/v3/spec/sdv/airbag_seat_massager.json
deleted file mode 100644
index be2478bb..00000000
--- a/digital-twin-model/dtdl/v3/spec/sdv/airbag_seat_massager.json
+++ /dev/null
@@ -1,20 +0,0 @@
-[
- {
- "@context": ["dtmi:dtdl:context;3"],
- "@type": "Interface",
- "@id": "dtmi:sdv:AirbagSeatMassager;1",
- "description": "Airbag Seat Massager",
- "contents": [
- {
- "@type": "Property",
- "@id": "dtmi:sdv:AirbagSeatMassager:MassageAirbags;1",
- "name": "MassageAirbags",
- "description": "The inflation level (0..100) for each massage airbag.",
- "schema": {
- "@type": "Array",
- "elementSchema": "integer"
- }
- }
- ]
- }
-]
diff --git a/digital-twin-model/dtdl/v3/spec/sdv/camera.json b/digital-twin-model/dtdl/v3/spec/sdv/camera.json
deleted file mode 100644
index e4ac45ea..00000000
--- a/digital-twin-model/dtdl/v3/spec/sdv/camera.json
+++ /dev/null
@@ -1,33 +0,0 @@
-[
- {
- "@context": "dtmi:dtdl:context;3",
- "@type": "Interface",
- "@id": "dtmi:sdv:Camera;1",
- "description": "Cabin camera.",
- "contents": [
- {
- "@type": "Property",
- "@id": "dtmi:sdv:Camera:Feed;1",
- "name": "Feed",
- "description": "The camera feed inside of the cabin.",
- "schema": {
- "@type": "Object",
- "fields": [
- {
- "name": "MediaType",
- "schema": "string"
- },
- {
- "name": "MediaContent",
- "description": "An array of bytes (represented by integers here).",
- "schema": {
- "@type": "Array",
- "elementSchema": "integer"
- }
- }
- ]
- }
- }
- ]
- }
-]
diff --git a/digital-twin-model/dtdl/v3/spec/sdv/hmi.json b/digital-twin-model/dtdl/v3/spec/sdv/hmi.json
deleted file mode 100644
index 8d025274..00000000
--- a/digital-twin-model/dtdl/v3/spec/sdv/hmi.json
+++ /dev/null
@@ -1,23 +0,0 @@
-[
- {
- "@context": ["dtmi:dtdl:context;3"],
- "@type": "Interface",
- "@id": "dtmi:sdv:HMI;1",
- "description": "The Human Machine Interface.",
- "contents": [
- {
- "@type": "Command",
- "@id": "dtmi:sdv:HMI:ShowNotification;1",
- "name": "ShowNotification",
- "description": "Show a notification on the HMI.",
- "request": {
- "@id": "dtmi:sdv:HMI:ShowNotification:request;1",
- "name": "Notification",
- "displayName": "Notification",
- "description": "The notification to show on the HMI.",
- "schema": "string"
- }
- }
- ]
- }
-]
diff --git a/digital-twin-model/dtdl/v3/spec/sdv/hvac.json b/digital-twin-model/dtdl/v3/spec/sdv/hvac.json
deleted file mode 100644
index 14075f02..00000000
--- a/digital-twin-model/dtdl/v3/spec/sdv/hvac.json
+++ /dev/null
@@ -1,24 +0,0 @@
-[
- {
- "@context": ["dtmi:dtdl:context;3"],
- "@type": "Interface",
- "@id": "dtmi:sdv:HVAC;1",
- "description": "Heat, Ventilation and Air Conditioning",
- "contents": [
- {
- "@type": "Property",
- "@id": "dtmi:sdv:HVAC:AmbientAirTemperature;1",
- "name": "AmbientAirTemperature",
- "description": "The immediate surroundings' air temperature (in Fahrenheit).",
- "schema": "integer"
- },
- {
- "@type": "Property",
- "@id": "dtmi:sdv:HVAC:IsAirConditioningActive;1",
- "name": "IsAirConditioningActive",
- "description": "Is air conditioning active?",
- "schema": "boolean"
- }
- ]
- }
-]
diff --git a/digital-twin-model/dtdl/v3/spec/sdv/obd.json b/digital-twin-model/dtdl/v3/spec/sdv/obd.json
deleted file mode 100644
index 9453a419..00000000
--- a/digital-twin-model/dtdl/v3/spec/sdv/obd.json
+++ /dev/null
@@ -1,17 +0,0 @@
-[
- {
- "@context": ["dtmi:dtdl:context;3"],
- "@type": "Interface",
- "@id": "dtmi:sdv:OBD;1",
- "description": "On-board Diagnostics Interface",
- "contents": [
- {
- "@type": "Property",
- "@id": "dtmi:sdv:OBD:HybridBatteryRemaining;1",
- "name": "HybridBatteryRemaining",
- "description": "The remaining hybrid battery life.",
- "schema": "integer"
- }
- ]
- }
-]
diff --git a/digital-twin-model/src/sdv_v1.rs b/digital-twin-model/src/sdv_v1.rs
index 996deb5a..c46cb3ce 100644
--- a/digital-twin-model/src/sdv_v1.rs
+++ b/digital-twin-model/src/sdv_v1.rs
@@ -4,15 +4,6 @@
// Note: In the future this code should be generated from a DTDL spec.
-pub mod airbag_seat_massager {
- pub mod massage_airbags {
- pub const ID: &str = "dtmi:sdv:AirbagSeatMassager:MassageAirbags;1";
- pub const NAME: &str = "MassageAirbags";
- pub const DESCRIPTION: &str = "The inflation level (0..100) for each massage airbag.";
- pub type TYPE = Vec;
- }
-}
-
#[allow(dead_code)]
pub mod camera {
pub mod feed {
@@ -46,25 +37,79 @@ pub mod hmi {
pub mod hvac {
pub mod ambient_air_temperature {
- pub const ID: &str = "dtmi:sdv:HVAC:AmbientAirTemperature;1";
- pub const NAME: &str = "AmbientAirTemperature";
+ pub const ID: &str = "dtmi:sdv:hvac:ambient_air_temperature;1";
+ pub const NAME: &str = "ambient_air_temperature";
pub const DESCRIPTION: &str = "The immediate surroundings air temperature (in Fahrenheit).";
pub type TYPE = i32;
}
pub mod is_air_conditioning_active {
- pub const ID: &str = "dtmi:sdv:HVAC:IsAirConditioningActive;1";
- pub const NAME: &str = "IsAirConditioningActive";
+ pub const ID: &str = "dtmi:sdv:HVAC:is_air_conditioning_active;1";
+ pub const NAME: &str = "is_air_conditioning_active";
pub const DESCRIPTION: &str = "Is air conditioning active?";
pub type TYPE = bool;
}
}
pub mod obd {
+ pub const ID: &str = "dtmi:sdv:obd;1";
+ pub const DESCRIPTION: &str = "On-board Diagnostics Interface";
pub mod hybrid_battery_remaining {
- pub const ID: &str = "dtmi:sdv:OBD:HybridBatteryRemaining;1";
- pub const NAME: &str = "HybridBatteryRemaining";
+ pub const ID: &str = "dtmi:sdv:obd:hybrid_battery_remaining;1";
+ pub const NAME: &str = "hybrid_battery_remaining";
pub const DESCRIPTION: &str = "The remaining hybrid battery life.";
pub type TYPE = i32;
}
}
+
+pub mod seat_massager {
+ pub const ID: &str = "dtmi:sdv:seatmassager;1";
+ pub const DESCRIPTION: &str = "Seat Massager Interface";
+ pub mod massage_airbags {
+ pub const ID: &str = "dtmi:sdv:massage_seat:sequence_names;1";
+ pub const NAME: &str = "sequence_names";
+ pub const DESCRIPTION: &str = "The name of each of the stored sequences.";
+ pub type TYPE = Vec;
+ }
+}
+
+pub mod basic_airbag_seat_massager {
+ pub const ID: &str = "dtmi:sdv:basic_airbag_seat_massager;1";
+ pub const DESCRIPTION: &str = "Basic Airbag Seat Massager Interface";
+}
+
+pub mod premium_airbag_seat_massager {
+ pub const ID: &str = "dtmi:sdv:premium_airbag_seat_massager;1";
+ pub const DESCRIPTION: &str = "Premium Airbag Seat Massager Interface";
+}
+
+pub mod airbag_seat_massager {
+ pub const ID: &str = "dtmi:sdv:airbag_seat_massager;1";
+ pub const DESCRIPTION: &str = "Airbag Seat Massager Interface";
+}
+
+pub mod seat {
+ pub const ID: &str = "dtmi:sdv:seat;1";
+ pub const DESCRIPTION: &str = "Seat Interface";
+}
+
+pub mod cabin {
+ pub const ID: &str = "dtmi:sdv:cabin;1";
+ pub const DESCRIPTION: &str = "Cabin Interface";
+}
+
+pub mod vehicle {
+ pub const ID: &str = "dtmi:sdv:vehcile;1";
+ pub const DESCRIPTION: &str = "Vehicle Interface";
+ pub mod vehicle_identification {
+ pub const ID: &str = "dtmi:sdv:vehicle:vehicle_identification;1";
+ pub const NAME: &str = "vehicle_identification";
+ pub const DESCRIPTION: &str = "Vehicle Identification";
+ pub mod vin {
+ pub const ID: &str = "dtmi:sdv:vehicle:vehicle_identification:vin;1";
+ pub const NAME: &str = "vin";
+ pub const DESCRIPTION: &str = "Vehicle Identification Number";
+ pub type TYPE = String;
+ }
+ }
+}
\ No newline at end of file
diff --git a/dtdl-tools/src/dtdl-validator/DtdlValidator.cs b/dtdl-tools/src/dtdl-validator/DtdlValidator.cs
index 19f50d4e..778e8dcd 100644
--- a/dtdl-tools/src/dtdl-validator/DtdlValidator.cs
+++ b/dtdl-tools/src/dtdl-validator/DtdlValidator.cs
@@ -4,6 +4,8 @@
using DTDLParser;
using DTDLParser.Models;
+using Azure;
+using Azure.IoT.ModelsRepository;
using System;
using System.Collections.Generic;
using System.CommandLine;
@@ -20,6 +22,13 @@ class Program
private const int EXIT_SUCCESS = 0;
private const int EXIT_FAILURE = 1;
+ static string ConvertToDTMI(string filepath, string dirpath, string extension)
+ {
+ string relativepath = filepath.Substring(dirpath.Length + 1, filepath.Length - dirpath.Length - extension.Length - 2);
+ string dtmi = relativepath.Replace('/', ':').Replace('-', ';'); // .ToLower();
+ return dtmi;
+ }
+
///
/// This method validates all of the DTDL files with the provided extension that are located
/// under the provided directory.
@@ -46,17 +55,29 @@ static int ValidateDtdl(DirectoryInfo directory, String extension)
return EXIT_FAILURE;
}
- var parser = new ModelParser();
+ var dmrClient = new ModelsRepositoryClient(new Uri(directory.FullName));
+
+ var parser = new ModelParser(new ParsingOptions()
+ {
+ DtmiResolverAsync = dmrClient.ParserDtmiResolverAsync
+ });
bool failureOccured = false;
foreach (var file in files)
{
try
- {
- var dtdl = File.ReadAllText(file);
- parser.ParseAsync(dtdl).GetAwaiter().GetResult();
+ {
+ string dtmi = ConvertToDTMI(file, directory.FullName, extension);
+ Console.WriteLine("DTMI = {0}", dtmi);
+
+ // var dtdl = File.ReadAllText(file);
+ // parser.ParseAsync(dtdl).GetAwaiter().GetResult();
+ var model = dmrClient.GetModelAsync(dtmi).GetAwaiter().GetResult();
+ Console.WriteLine("For {0} the model cardinality is {1}", dtmi, model.Content.Count);
+ // Console.WriteLine("Content = {0}", model.Content[dtmi]);
+ var dictParsed = parser.ParseAsync(model.Content[dtmi]).GetAwaiter().GetResult();
Console.WriteLine($"{file} - ok");
- }
+ }
catch (ParsingException ex)
{
Console.WriteLine($"{file} - failed");
@@ -65,6 +86,18 @@ static int ValidateDtdl(DirectoryInfo directory, String extension)
}
failureOccured = true;
}
+ catch (ResolutionException ex)
+ {
+ Console.WriteLine($"{file} - failed");
+ Console.WriteLine($" {ex.ToString()}");
+ failureOccured = true;
+ }
+ catch (Exception ex)
+ {
+ Console.WriteLine($"{file} - failed");
+ Console.WriteLine($" {ex.ToString()}");
+ failureOccured = true;
+ }
}
if (failureOccured)
diff --git a/dtdl-tools/src/dtdl-validator/ModelsRepositoryClientExtensions.cs b/dtdl-tools/src/dtdl-validator/ModelsRepositoryClientExtensions.cs
new file mode 100644
index 00000000..359cd503
--- /dev/null
+++ b/dtdl-tools/src/dtdl-validator/ModelsRepositoryClientExtensions.cs
@@ -0,0 +1,21 @@
+
+using Azure.IoT.ModelsRepository;
+using DTDLParser;
+using System.Runtime.CompilerServices;
+
+internal static class ModelsRepositoryClientExtensions
+{
+ public static async IAsyncEnumerable ParserDtmiResolverAsync(
+ this ModelsRepositoryClient client, IReadOnlyCollection dtmis,
+ [EnumeratorCancellation] CancellationToken ct = default)
+ {
+ Console.WriteLine("HERE");
+ foreach (var dtmi in dtmis.Select(s => s.AbsoluteUri))
+ {
+ Console.WriteLine($"DTMI >>> {dtmi}");
+ var result = await client.GetModelAsync(dtmi, ModelDependencyResolution.Disabled, ct);
+ Console.WriteLine("DTMI <<<");
+ yield return result.Content[dtmi];
+ }
+ }
+}
\ No newline at end of file
diff --git a/dtdl-tools/src/dtdl-validator/dtdl-validator.csproj b/dtdl-tools/src/dtdl-validator/dtdl-validator.csproj
index f7aa0b82..44d6779d 100644
--- a/dtdl-tools/src/dtdl-validator/dtdl-validator.csproj
+++ b/dtdl-tools/src/dtdl-validator/dtdl-validator.csproj
@@ -3,12 +3,15 @@
Exe
- net7.0
+ net8.0
+ enable
+ enable
+
diff --git a/dtdl-tools/src/lib.rs b/dtdl-tools/src/lib.rs
index 3e1d2b90..3af290ae 100644
--- a/dtdl-tools/src/lib.rs
+++ b/dtdl-tools/src/lib.rs
@@ -15,7 +15,7 @@ mod dtdl_tools_tests {
const OUT_DIR: &str = env!("OUT_DIR");
const DTDL_VALIDATOR_FILENAME: &str = "dtdl-validator";
- const DTDL_VALIDATOR_BIN_DIR: &str = "Debug/net7.0";
+ const DTDL_VALIDATOR_BIN_DIR: &str = "Debug/net8.0";
const DTDL_VALIDATOR_EXT_OPTION: &str = "-e";
/// Validate DTDL files.
@@ -27,7 +27,7 @@ mod dtdl_tools_tests {
let dtdl_validator_command_path =
Path::new(OUT_DIR).join(DTDL_VALIDATOR_BIN_DIR).join(DTDL_VALIDATOR_FILENAME);
- println!("dtdl_validator_command_path = '{:?}", dtdl_validator_command_path);
+ println!("dtdl_validator_command_path = {:?}", dtdl_validator_command_path);
let dtdl_validator_output = Command::new(dtdl_validator_command_path)
.arg(directory)
diff --git a/samples/interfaces/sample_grpc/v2/digital_twin_common.proto b/samples/interfaces/sample_grpc/v2/digital_twin_common.proto
new file mode 100644
index 00000000..f9ba04b3
--- /dev/null
+++ b/samples/interfaces/sample_grpc/v2/digital_twin_common.proto
@@ -0,0 +1,12 @@
+// Copyright (c) Microsoft Corporation.
+// Licensed under the MIT license.
+// SPDX-License-Identifier: MIT
+
+syntax = "proto3";
+
+package sample_grpc.v2.digital_twin_common;
+
+message Status {
+ int32 code = 1;
+ string message = 2;
+}
diff --git a/samples/interfaces/sample_grpc/v2/digital_twin_consumer.proto b/samples/interfaces/sample_grpc/v2/digital_twin_consumer.proto
new file mode 100644
index 00000000..b60c0181
--- /dev/null
+++ b/samples/interfaces/sample_grpc/v2/digital_twin_consumer.proto
@@ -0,0 +1,31 @@
+// Copyright (c) Microsoft Corporation.
+// Licensed under the MIT license.
+// SPDX-License-Identifier: MIT
+
+syntax = "proto3";
+
+import "digital_twin_common.proto";
+
+package sample_grpc.v2.digital_twin_consumer;
+
+service DigitalTwinConsumer {
+ rpc Publish (PublishRequest) returns (PublishResponse);
+ rpc Respond (RespondRequest) returns (RespondResponse);
+}
+
+message PublishRequest {
+ string entity_id = 1;
+ string value = 2;
+}
+
+message PublishResponse {
+}
+
+message RespondRequest {
+ string entity_id = 1;
+ string response_id = 2;
+ string payload = 3;
+}
+
+message RespondResponse {
+}
\ No newline at end of file
diff --git a/samples/interfaces/sample_grpc/v2/digital_twin_provider.proto b/samples/interfaces/sample_grpc/v2/digital_twin_provider.proto
new file mode 100644
index 00000000..927d26fb
--- /dev/null
+++ b/samples/interfaces/sample_grpc/v2/digital_twin_provider.proto
@@ -0,0 +1,44 @@
+// Copyright (c) Microsoft Corporation.
+// Licensed under the MIT license.
+// SPDX-License-Identifier: MIT
+
+syntax = "proto3";
+
+import "digital_twin_common.proto";
+
+package sample_grpc.v2.digital_twin_provider;
+
+service DigitalTwinProvider {
+ rpc Get (GetRequest) returns (GetResponse);
+ rpc Set (SetRequest) returns (SetResponse);
+ rpc Invoke (InvokeRequest) returns (InvokeResponse);
+}
+
+message GetRequest {
+ string entity_id = 1;
+ string consumer_uri = 2;
+}
+
+message GetResponse {
+ sample_grpc.v2.digital_twin_common.Status status = 1;
+}
+
+message SetRequest {
+ string entity_id = 1;
+ string value = 2;
+}
+
+message SetResponse {
+ sample_grpc.v2.digital_twin_common.Status status = 1;
+}
+
+message InvokeRequest {
+ string entity_id = 1;
+ string consumer_uri = 2;
+ string response_id = 3;
+ string payload = 4;
+}
+
+message InvokeResponse {
+ sample_grpc.v2.digital_twin_common.Status status = 1;
+}
\ No newline at end of file
diff --git a/samples/protobuf_data_access/build.rs b/samples/protobuf_data_access/build.rs
index cf214dbd..a2a0f8d0 100644
--- a/samples/protobuf_data_access/build.rs
+++ b/samples/protobuf_data_access/build.rs
@@ -5,6 +5,9 @@
fn main() -> Result<(), Box> {
tonic_build::compile_protos("../interfaces/sample_grpc/v1/digital_twin_consumer.proto")?;
tonic_build::compile_protos("../interfaces/sample_grpc/v1/digital_twin_provider.proto")?;
+ tonic_build::compile_protos("../interfaces/sample_grpc/v2/digital_twin_common.proto")?;
+ tonic_build::compile_protos("../interfaces/sample_grpc/v2/digital_twin_consumer.proto")?;
+ tonic_build::compile_protos("../interfaces/sample_grpc/v2/digital_twin_provider.proto")?;
tonic_build::configure()
.message_attribute("EndpointInfo", "#[derive(serde::Deserialize, serde::Serialize)]")
.message_attribute("EntityAccessInfo", "#[derive(serde::Deserialize, serde::Serialize)]")
diff --git a/samples/protobuf_data_access/src/lib.rs b/samples/protobuf_data_access/src/lib.rs
index 30208109..0744cff5 100644
--- a/samples/protobuf_data_access/src/lib.rs
+++ b/samples/protobuf_data_access/src/lib.rs
@@ -26,6 +26,7 @@ pub mod chariott {
}
}
+
pub mod sample_grpc {
pub mod v1 {
pub mod digital_twin_consumer {
@@ -36,6 +37,19 @@ pub mod sample_grpc {
tonic::include_proto!("digital_twin_provider");
}
}
+ pub mod v2 {
+ pub mod digital_twin_common {
+ tonic::include_proto!("sample_grpc.v2.digital_twin_common");
+ }
+
+ pub mod digital_twin_consumer {
+ tonic::include_proto!("sample_grpc.v2.digital_twin_consumer");
+ }
+
+ pub mod digital_twin_provider {
+ tonic::include_proto!("sample_grpc.v2.digital_twin_provider");
+ }
+ }
}
pub mod tutorial_grpc {