diff --git a/icons/pid_symbols/dark/motor_valve_green.svg b/icons/pid_symbols/dark/motor_valve_green.svg
new file mode 100644
index 0000000000000000000000000000000000000000..c5e62636f99c5e7e9c9f0cb42563f167fc4c7d48
--- /dev/null
+++ b/icons/pid_symbols/dark/motor_valve_green.svg
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+   width="10"
+   height="8"
+   version="1.1"
+   id="svg1"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:svg="http://www.w3.org/2000/svg">
+  <defs
+     id="defs1" />
+  <path
+     fill="none"
+     stroke="#ffffff"
+     d="M 1,3 V 7 L 9,3 v 4 z"
+     id="path1"
+     style="fill:#00ff00;stroke-width:0.2;stroke-linejoin:round" />
+  <path
+     fill="none"
+     stroke="#ffffff"
+     d="M 0,5 H 1"
+     id="path2"
+     style="stroke-width:0.2" />
+  <path
+     fill="none"
+     stroke="#ffffff"
+     d="M 5,2.5 V 5"
+     id="path3"
+     style="stroke-width:0.2" />
+  <path
+     fill="none"
+     stroke="#ffffff"
+     d="m 9,5 h 1"
+     id="path4"
+     style="stroke-width:0.2" />
+  <circle
+     style="fill:none;stroke:#ffffff;stroke-width:0.2"
+     id="circle1"
+     cx="5"
+     cy="1.5"
+     r="1" />
+  <path
+     style="fill:#ffffff;stroke:#ffffff;stroke-opacity:1;stroke-width:0.05;stroke-dasharray:none;stroke-linejoin:round"
+     d="M 4.5,2 L 4.5,1 L 4.7,1 L 5,1.9 L 5.3,1 L 5.5,1 L 5.5,2 L 5.4,2 L 5.4,1.1 L 5.1,2 L 4.9,2 L 4.6,1.1 L 4.6,2 Z"
+     id="text1" />
+</svg>
diff --git a/icons/pid_symbols/dark/motor_valve_red.svg b/icons/pid_symbols/dark/motor_valve_red.svg
new file mode 100644
index 0000000000000000000000000000000000000000..cf1404caf8354abab263d067909b3073768fb5d8
--- /dev/null
+++ b/icons/pid_symbols/dark/motor_valve_red.svg
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+   width="10"
+   height="8"
+   version="1.1"
+   id="svg1"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:svg="http://www.w3.org/2000/svg">
+  <defs
+     id="defs1" />
+  <path
+     fill="none"
+     stroke="#ffffff"
+     d="M 1,3 V 7 L 9,3 v 4 z"
+     id="path1"
+     style="fill:#ff0000;stroke-width:0.2;stroke-linejoin:round" />
+  <path
+     fill="none"
+     stroke="#ffffff"
+     d="M 0,5 H 1"
+     id="path2"
+     style="stroke-width:0.2" />
+  <path
+     fill="none"
+     stroke="#ffffff"
+     d="M 5,2.5 V 5"
+     id="path3"
+     style="stroke-width:0.2" />
+  <path
+     fill="none"
+     stroke="#ffffff"
+     d="m 9,5 h 1"
+     id="path4"
+     style="stroke-width:0.2" />
+  <circle
+     style="fill:none;stroke:#ffffff;stroke-width:0.2"
+     id="circle1"
+     cx="5"
+     cy="1.5"
+     r="1" />
+  <path
+     style="fill:#ffffff;stroke:#ffffff;stroke-opacity:1;stroke-width:0.05;stroke-dasharray:none;stroke-linejoin:round"
+     d="M 4.5,2 L 4.5,1 L 4.7,1 L 5,1.9 L 5.3,1 L 5.5,1 L 5.5,2 L 5.4,2 L 5.4,1.1 L 5.1,2 L 4.9,2 L 4.6,1.1 L 4.6,2 Z"
+     id="text1" />
+</svg>
diff --git a/icons/pid_symbols/light/motor_valve_green.svg b/icons/pid_symbols/light/motor_valve_green.svg
new file mode 100644
index 0000000000000000000000000000000000000000..ef8cea865f8d42cf205e78aad98e3e95a3cf582e
--- /dev/null
+++ b/icons/pid_symbols/light/motor_valve_green.svg
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+   width="10"
+   height="8"
+   version="1.1"
+   id="svg1"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:svg="http://www.w3.org/2000/svg">
+  <defs
+     id="defs1" />
+  <path
+     fill="none"
+     stroke="#000000"
+     d="M 1,3 V 7 L 9,3 v 4 z"
+     id="path1"
+     style="fill:#00ff00;stroke-width:0.2;stroke-linejoin:round" />
+  <path
+     fill="none"
+     stroke="#000000"
+     d="M 0,5 H 1"
+     id="path2"
+     style="stroke-width:0.2" />
+  <path
+     fill="none"
+     stroke="#000000"
+     d="M 5,2.5 V 5"
+     id="path3"
+     style="stroke-width:0.2" />
+  <path
+     fill="none"
+     stroke="#000000"
+     d="m 9,5 h 1"
+     id="path4"
+     style="stroke-width:0.2" />
+  <circle
+     style="fill:none;stroke:#000000;stroke-width:0.2"
+     id="circle1"
+     cx="5"
+     cy="1.5"
+     r="1" />
+  <path
+     style="fill:#000000;stroke:#000000;stroke-opacity:1;stroke-width:0.05;stroke-dasharray:none;stroke-linejoin:round"
+     d="M 4.5,2 L 4.5,1 L 4.7,1 L 5,1.9 L 5.3,1 L 5.5,1 L 5.5,2 L 5.4,2 L 5.4,1.1 L 5.1,2 L 4.9,2 L 4.6,1.1 L 4.6,2 Z"
+     id="text1" />
+</svg>
diff --git a/icons/pid_symbols/light/motor_valve_red.svg b/icons/pid_symbols/light/motor_valve_red.svg
new file mode 100644
index 0000000000000000000000000000000000000000..7e947e9ea86e240dd37554369a789bc28e996529
--- /dev/null
+++ b/icons/pid_symbols/light/motor_valve_red.svg
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+   width="10"
+   height="8"
+   version="1.1"
+   id="svg1"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:svg="http://www.w3.org/2000/svg">
+  <defs
+     id="defs1" />
+  <path
+     fill="none"
+     stroke="#000000"
+     d="M 1,3 V 7 L 9,3 v 4 z"
+     id="path1"
+     style="fill:#ff0000;stroke-width:0.2;stroke-linejoin:round" />
+  <path
+     fill="none"
+     stroke="#000000"
+     d="M 0,5 H 1"
+     id="path2"
+     style="stroke-width:0.2" />
+  <path
+     fill="none"
+     stroke="#000000"
+     d="M 5,2.5 V 5"
+     id="path3"
+     style="stroke-width:0.2" />
+  <path
+     fill="none"
+     stroke="#000000"
+     d="m 9,5 h 1"
+     id="path4"
+     style="stroke-width:0.2" />
+  <circle
+     style="fill:none;stroke:#000000;stroke-width:0.2"
+     id="circle1"
+     cx="5"
+     cy="1.5"
+     r="1" />
+  <path
+     style="fill:#000000;stroke:#000000;stroke-opacity:1;stroke-width:0.05;stroke-dasharray:none;stroke-linejoin:round"
+     d="M 4.5,2 L 4.5,1 L 4.7,1 L 5,1.9 L 5.3,1 L 5.5,1 L 5.5,2 L 5.4,2 L 5.4,1.1 L 5.1,2 L 4.9,2 L 4.6,1.1 L 4.6,2 Z"
+     id="text1" />
+</svg>
diff --git a/src/ui/panes/pid_drawing_tool.rs b/src/ui/panes/pid_drawing_tool.rs
index 0ee1b861e177f8369cf753b9140422b2cc4011cf..b7b5bbaada800354191af830d4917a2ecc78f0ca 100644
--- a/src/ui/panes/pid_drawing_tool.rs
+++ b/src/ui/panes/pid_drawing_tool.rs
@@ -18,7 +18,7 @@ use crate::ui::{composable_view::PaneResponse, utils::egui_to_glam};
 
 use super::PaneBehavior;
 
-#[derive(Clone, Serialize, Deserialize, PartialEq, Debug)]
+#[derive(Clone, Debug)]
 enum Action {
     Connect(usize),
     ContextMenu(Vec2),
@@ -28,7 +28,7 @@ enum Action {
 }
 
 /// Piping and instrumentation diagram
-#[derive(Clone, Serialize, Deserialize, PartialEq, Default, Debug)]
+#[derive(Clone, Serialize, Deserialize, Default, Debug)]
 pub struct PidPane {
     elements: Vec<Element>,
     connections: Vec<Connection>,
@@ -44,6 +44,15 @@ pub struct PidPane {
     center_content: bool,
 }
 
+impl PartialEq for PidPane {
+    fn eq(&self, other: &Self) -> bool {
+        self.elements == other.elements
+            && self.connections == other.connections
+            && self.grid == other.grid
+            && self.center_content == other.center_content
+    }
+}
+
 impl PaneBehavior for PidPane {
     fn ui(&mut self, ui: &mut egui::Ui) -> PaneResponse {
         let theme = PidPane::find_theme(ui.ctx());
@@ -178,8 +187,8 @@ impl PidPane {
         }
     }
 
-    fn draw_elements(&self, ui: &Ui, theme: Theme) {
-        for element in &self.elements {
+    fn draw_elements(&mut self, ui: &Ui, theme: Theme) {
+        for element in &mut self.elements {
             element.draw(&self.grid, ui, theme);
         }
     }
diff --git a/src/ui/panes/pid_drawing_tool/elements.rs b/src/ui/panes/pid_drawing_tool/elements.rs
index 7db6c7239208c62e83a4dcf92e0cd17ec43bb63f..db0c3154333913f315f573f46f4bc5d08b03161c 100644
--- a/src/ui/panes/pid_drawing_tool/elements.rs
+++ b/src/ui/panes/pid_drawing_tool/elements.rs
@@ -1,12 +1,14 @@
-use crate::ui::utils::glam_to_egui;
+use crate::{msg_broker, ui::utils::glam_to_egui};
 
 use super::grid::GridInfo;
 use super::symbols::Symbol;
+use crate::error::ErrInstrument;
 use egui::{Rect, Theme, Ui};
 use glam::{Mat2, Vec2};
 use serde::{Deserialize, Serialize};
 
-#[derive(Clone, Serialize, Deserialize, PartialEq, Debug)]
+#[derive(Clone, Serialize, Deserialize, Debug)]
+#[serde(from = "SerialElement")]
 pub struct Element {
     /// Anchor postion in grid coordinates, top-left corner
     position: glam::Vec2,
@@ -21,9 +23,18 @@ pub struct Element {
     ///
     /// These vectors include the current rotation of the element.
     /// They are cached to avoid recomputing the rotation.
+    #[serde(skip)]
     anchor_points: Vec<Vec2>,
 }
 
+impl PartialEq for Element {
+    fn eq(&self, other: &Self) -> bool {
+        self.position == other.position
+            && self.symbol == other.symbol
+            && self.rotation == other.rotation
+    }
+}
+
 impl Element {
     pub fn new(center: Vec2, symbol: Symbol) -> Self {
         Self {
@@ -113,12 +124,36 @@ impl Element {
         self.position + Mat2::from_angle(self.rotation) * self.size() * 0.5
     }
 
-    pub fn draw(&self, grid: &GridInfo, ui: &Ui, theme: Theme) {
+    pub fn draw(&mut self, grid: &GridInfo, ui: &Ui, theme: Theme) {
         let center = glam_to_egui(grid.grid_to_screen(self.position)).to_pos2();
         let image_rect = Rect::from_min_size(center, glam_to_egui(self.size() * grid.size()));
 
         egui::Image::new(self.symbol.get_image(theme))
             .rotate(self.rotation, egui::Vec2::splat(0.0))
             .paint_at(ui, image_rect);
+
+        if let Symbol::MotorValve(motor_valve) = &mut self.symbol {
+            msg_broker!().refresh_view(motor_valve).log_expect("bruh");
+        }
+    }
+}
+
+#[derive(Deserialize)]
+pub struct SerialElement {
+    position: glam::Vec2,
+    symbol: Symbol,
+    rotation: f32,
+}
+
+impl From<SerialElement> for Element {
+    fn from(value: SerialElement) -> Self {
+        let mut value = Self {
+            position: value.position,
+            symbol: value.symbol,
+            rotation: value.rotation,
+            anchor_points: Vec::new(),
+        };
+        value.reload_anchor_points();
+        value
     }
 }
diff --git a/src/ui/panes/pid_drawing_tool/grid.rs b/src/ui/panes/pid_drawing_tool/grid.rs
index 9b0797f3844bf8278b82984fe5d75f708e101371..aa74330e567662659f3c2a6da2678ff805d043ec 100644
--- a/src/ui/panes/pid_drawing_tool/grid.rs
+++ b/src/ui/panes/pid_drawing_tool/grid.rs
@@ -14,7 +14,6 @@ pub const CONNECTION_POINT_SIZE: f32 = 1.0; // Grid units
 
 #[derive(Clone, Serialize, Deserialize, PartialEq, Debug)]
 pub struct GridInfo {
-    /// Grid's zero position on screen
     pub zero_pos: Vec2,
     size: f32,
 }
diff --git a/src/ui/panes/pid_drawing_tool/symbols.rs b/src/ui/panes/pid_drawing_tool/symbols.rs
index 0b848909a6419b2844c89e7baea719e70b39e18c..1245043d5c62f000ad683d0c76c6ed1cce1d4759 100644
--- a/src/ui/panes/pid_drawing_tool/symbols.rs
+++ b/src/ui/panes/pid_drawing_tool/symbols.rs
@@ -1,5 +1,8 @@
+mod motor_valve;
+
 use egui::{ImageSource, Theme};
 use glam::Vec2;
+use motor_valve::MotorValve;
 use serde::{Deserialize, Serialize};
 use strum_macros::{Display, EnumIter};
 
@@ -10,7 +13,7 @@ pub enum Symbol {
     CheckValve,
     FlexibleConnection,
     ManualValve,
-    MotorValve,
+    MotorValve(MotorValve),
     PressureGauge,
     PressureRegulator,
     PressureTransducer,
@@ -53,12 +56,26 @@ impl Symbol {
             (Symbol::ReliefValve, Theme::Dark) => {
                 egui::include_image!("../../../../icons/pid_symbols/dark/relief_valve.svg")
             }
-            (Symbol::MotorValve, Theme::Light) => {
-                egui::include_image!("../../../../icons/pid_symbols/light/motor_valve.svg")
-            }
-            (Symbol::MotorValve, Theme::Dark) => {
-                egui::include_image!("../../../../icons/pid_symbols/dark/motor_valve.svg")
-            }
+            (Symbol::MotorValve(state), Theme::Light) => match state.last_value {
+                None => egui::include_image!("../../../../icons/pid_symbols/light/motor_valve.svg"),
+                Some(true) => {
+                    egui::include_image!(
+                        "../../../../icons/pid_symbols/light/motor_valve_green.svg"
+                    )
+                }
+                Some(false) => {
+                    egui::include_image!("../../../../icons/pid_symbols/light/motor_valve_red.svg")
+                }
+            },
+            (Symbol::MotorValve(state), Theme::Dark) => match state.last_value {
+                None => egui::include_image!("../../../../icons/pid_symbols/dark/motor_valve.svg"),
+                Some(true) => {
+                    egui::include_image!("../../../../icons/pid_symbols/dark/motor_valve_green.svg")
+                }
+                Some(false) => {
+                    egui::include_image!("../../../../icons/pid_symbols/dark/motor_valve_red.svg")
+                }
+            },
             (Symbol::ThreeWayValve, Theme::Light) => {
                 egui::include_image!("../../../../icons/pid_symbols/light/three_way_valve.svg")
             }
@@ -112,7 +129,7 @@ impl Symbol {
             Symbol::CheckValve => (10.0, 5.0),
             Symbol::FlexibleConnection => (10.0, 6.0),
             Symbol::ManualValve => (10.0, 5.0),
-            Symbol::MotorValve => (10.0, 8.0),
+            Symbol::MotorValve(_) => (10.0, 8.0),
             Symbol::PressureGauge => (7.0, 7.0),
             Symbol::PressureRegulator => (10.0, 10.0),
             Symbol::PressureTransducer => (7.0, 7.0),
@@ -132,7 +149,7 @@ impl Symbol {
             Symbol::CheckValve => vec![(0.0, 2.5), (10.0, 2.5)],
             Symbol::FlexibleConnection => vec![(0.0, 3.0), (10.0, 3.0)],
             Symbol::ManualValve => vec![(0.0, 2.5), (10.0, 2.5)],
-            Symbol::MotorValve => vec![(0.0, 5.0), (10.0, 5.0)],
+            Symbol::MotorValve(_) => vec![(0.0, 5.0), (10.0, 5.0)],
             Symbol::PressureGauge => vec![(3.5, 7.0)],
             Symbol::PressureRegulator => vec![(0.0, 7.0), (10.0, 7.0)],
             Symbol::PressureTransducer => vec![(3.5, 7.0)],
@@ -146,3 +163,30 @@ impl Symbol {
         .collect()
     }
 }
+
+/// Single MavLink value source info
+#[derive(Clone, Serialize, Deserialize, PartialEq, Debug)]
+#[serde(from = "SerialMavlinkValue")]
+struct MavlinkValue {
+    msg_id: u32,
+    field: String,
+
+    #[serde(skip)]
+    view_id: egui::Id,
+}
+
+#[derive(Deserialize)]
+struct SerialMavlinkValue {
+    msg_id: u32,
+    field: String,
+}
+
+impl From<SerialMavlinkValue> for MavlinkValue {
+    fn from(value: SerialMavlinkValue) -> Self {
+        Self {
+            msg_id: value.msg_id,
+            field: value.field,
+            view_id: egui::Id::new(""),
+        }
+    }
+}
diff --git a/src/ui/panes/pid_drawing_tool/symbols/motor_valve.rs b/src/ui/panes/pid_drawing_tool/symbols/motor_valve.rs
new file mode 100644
index 0000000000000000000000000000000000000000..af4f38f55f56eef934762ba41ab9218be32d8111
--- /dev/null
+++ b/src/ui/panes/pid_drawing_tool/symbols/motor_valve.rs
@@ -0,0 +1,60 @@
+use crate::mavlink::{extract_from_message, MavlinkResult, MessageView, TimedMessage};
+
+use super::MavlinkValue;
+
+use serde::{Deserialize, Serialize};
+use skyward_mavlink::{mavlink::MessageData, orion};
+
+#[derive(Clone, Serialize, Deserialize, PartialEq, Debug)]
+pub struct MotorValve {
+    source: MavlinkValue,
+
+    /// false = closed, true = open
+    pub last_value: Option<bool>,
+}
+
+impl Default for MotorValve {
+    fn default() -> Self {
+        Self {
+            source: MavlinkValue {
+                msg_id: orion::GSE_TM_DATA::ID,
+                field: "n2o_filling_valve_state".to_string(),
+                view_id: egui::Id::new(""),
+            },
+            last_value: None,
+        }
+    }
+}
+
+impl MessageView for MotorValve {
+    fn widget_id(&self) -> &egui::Id {
+        &self.source.view_id
+    }
+
+    fn id_of_interest(&self) -> u32 {
+        self.source.msg_id
+    }
+
+    fn is_valid(&self) -> bool {
+        self.last_value.is_some()
+    }
+
+    fn populate_view(&mut self, msg_slice: &[TimedMessage]) -> MavlinkResult<()> {
+        self.update_view(msg_slice)
+    }
+
+    fn update_view(&mut self, msg_slice: &[TimedMessage]) -> MavlinkResult<()> {
+        if let Some(msg) = msg_slice.last() {
+            let values: MavlinkResult<Vec<Option<u8>>> =
+                extract_from_message(&msg.message, [&self.source.field]);
+            if let Ok(values) = values {
+                if !values.is_empty() {
+                    if let Some(value) = values[0].map(|v| v != 0) {
+                        self.last_value = Some(value);
+                    }
+                }
+            }
+        }
+        Ok(())
+    }
+}