diff --git a/src/packet.rs b/src/packet.rs
index bb43dce53d35bc075f710797facf2738477faaaf..12288e7bb9c680ce6be2258126f1fb2038070491 100644
--- a/src/packet.rs
+++ b/src/packet.rs
@@ -292,7 +292,7 @@ impl<'a, const N: usize> Packet<'a, N> {
             .iter()
             .filter(|r| match r {
                 RouteNode::Internet => false,
-                RouteNode::Identity(_, _, is_future) => !is_future,
+                RouteNode::Identity(ident) => !ident.is_future(),
             })
             .count();
 
@@ -302,7 +302,9 @@ impl<'a, const N: usize> Packet<'a, N> {
 
         let already_digipeated = route.iter().any(|r| match r {
             RouteNode::Internet => false,
-            RouteNode::Identity(rc, rs, is_future) => rc == callsign && rs == ssid && !is_future,
+            RouteNode::Identity(ident) => {
+                ident.callsign() == callsign && ident.ssid() == ssid && !ident.is_future()
+            }
         });
 
         if already_digipeated {
@@ -310,14 +312,14 @@ impl<'a, const N: usize> Packet<'a, N> {
         }
 
         let next_node = route.iter().find_map(|r| match r {
-            RouteNode::Identity(c, s, is_future) if is_future => Some((c, s)),
+            RouteNode::Identity(ident) if ident.is_future() => {
+                Some((ident.callsign(), ident.ssid()))
+            }
             _ => None,
         });
 
         match next_node {
-            Some((rc, rs)) if rc != callsign || rs != ssid => {
-                return Err(DigipeatError::SetDestiny)
-            }
+            Some((rc, rs)) if rc != callsign || rs != ssid => Err(DigipeatError::SetDestiny),
             _ => Ok(()),
         }
     }
@@ -327,10 +329,11 @@ impl<'a, const N: usize> Packet<'a, N> {
         &mut self,
         callsign: &str,
         ssid: u8,
+        rssi: Option<f64>,
     ) -> Result<(), PacketRouteAppendError> {
         let mut route = self.route().ok_or(PacketRouteAppendError::NoRouteWhisker)?;
         route
-            .append_node(callsign, ssid)
+            .append_node(callsign, ssid, rssi)
             .map_err(|error| PacketRouteAppendError::Route { error })?;
         self.clear_route();
 
diff --git a/src/whisker/mod.rs b/src/whisker/mod.rs
index 3352b4ee64950fd9d4570d3292228bf96fdb4d43..dfb94dfa0a48c774f0506f2cf1370fadbe067ab1 100644
--- a/src/whisker/mod.rs
+++ b/src/whisker/mod.rs
@@ -184,7 +184,7 @@ impl<'a> Iterator for ValidatedWhiskerIter<'a> {
 mod tests {
     use half::f16;
 
-    use crate::whisker::route::RouteNode;
+    use crate::whisker::route::{RouteIdentity, RouteNode};
 
     use super::*;
 
@@ -287,40 +287,58 @@ mod tests {
     #[test]
     fn route_push_and_iter() {
         let mut route = Route::new(34);
-        route.push_callsign("VE2XYZ", 23, false).unwrap();
+        route
+            .push_callsign(RouteIdentity::new("VE2XYZ", 23, None, false))
+            .unwrap();
         route.push_internet().unwrap();
         route.push_internet().unwrap();
         route.push_internet().unwrap();
-        route.push_callsign("VE9AAAAA", 94, true).unwrap();
-        assert!(route.push_callsign("VE9AAAAA", 94, false).is_none());
+        route
+            .push_callsign(RouteIdentity::new("VE9AAAAA", 94, None, true))
+            .unwrap();
+        // past after future - not allowed
+        assert!(route
+            .push_callsign(RouteIdentity::new("VE9AAAAA", 94, None, false))
+            .is_none());
 
         // too long
         assert!(route
-            .push_callsign(
+            .push_callsign(RouteIdentity::new(
                 "lsdfjslkdfjlksdjflksfjsdklfjsdklfjsdklfjsdklfjsklfsef;jklsdfjkl;sdf;klsdf;klsjdfJSDJFSKL:DFJDSL:KFskldfj;slkdfjsdkl;fjdskl;fjsdfl;kjsdfl;ksdjfkl;ssdfl;kjsdfl;ksdjf;sdklsd;lfkjsdlfk;jsdl;fkjsd;klfjsd;fljsf;oidfjgwper0tujdfgndfjkl;gjnergjol;kehfgo;dijge;oghdfkl;gjdfkl;gjdeior;lgjedr;ioghjdorighndeklo;grjiop[",
                 20,
+				None,
                 true,
-            ).is_none());
+            )).is_none());
 
         route
-            .push_callsign("This is the last callsign", 0, true)
+            .push_callsign(RouteIdentity::new(
+                "This is the last callsign",
+                0,
+                None,
+                true,
+            ))
             .unwrap();
         route.push_internet().unwrap();
 
         let mut iter = route.iter();
         assert_eq!(
-            RouteNode::Identity("VE2XYZ", 23, false),
+            RouteNode::Identity(RouteIdentity::new("VE2XYZ", 23, None, false)),
             iter.next().unwrap()
         );
         assert_eq!(RouteNode::Internet, iter.next().unwrap());
         assert_eq!(RouteNode::Internet, iter.next().unwrap());
         assert_eq!(RouteNode::Internet, iter.next().unwrap());
         assert_eq!(
-            RouteNode::Identity("VE9AAAAA", 94, true),
+            RouteNode::Identity(RouteIdentity::new("VE9AAAAA", 94, None, true)),
             iter.next().unwrap()
         );
         assert_eq!(
-            RouteNode::Identity("This is the last callsign", 0, true),
+            RouteNode::Identity(RouteIdentity::new(
+                "This is the last callsign",
+                0,
+                None,
+                true
+            )),
             iter.next().unwrap()
         );
         assert_eq!(RouteNode::Internet, iter.next().unwrap());
@@ -332,13 +350,22 @@ mod tests {
     #[test]
     fn route_e2e() {
         let mut route = Route::new(34);
-        route.push_callsign("VE2XYZ", 23, false).unwrap();
+        route
+            .push_callsign(RouteIdentity::new("VE2XYZ", 23, Some(0.0), false))
+            .unwrap();
         route.push_internet().unwrap();
         route.push_internet().unwrap();
         route.push_internet().unwrap();
-        route.push_callsign("VE9AAAAA", 94, true).unwrap();
         route
-            .push_callsign("This is the last callsign", 0, true)
+            .push_callsign(RouteIdentity::new("VE9AAAAA", 94, Some(10.0), true))
+            .unwrap();
+        route
+            .push_callsign(RouteIdentity::new(
+                "This is the last callsign",
+                0,
+                Some(-159.0),
+                true,
+            ))
             .unwrap();
         route.push_internet().unwrap();
 
@@ -352,44 +379,46 @@ mod tests {
     #[test]
     fn route_doc_examples() {
         let mut ex1 = Route::new(4);
-        ex1.push_callsign("VE1ABC", 0, false);
-        ex1.push_callsign("VE2DEF", 234, false);
-        ex1.push_callsign("VE3XYZ", 14, false);
+        ex1.push_callsign(RouteIdentity::new("VE1ABC", 0, Some(-96.0), false));
+        ex1.push_callsign(RouteIdentity::new("VE2DEF", 234, Some(-13.0), false));
+        ex1.push_callsign(RouteIdentity::new("VE3XYZ", 14, Some(-106.0), false));
 
         let mut buf = [0; 256];
         let encoded = ex1.encode(&mut buf).unwrap();
         assert_eq!(
             &[
-                0x19, 0x04, 0x56, 0x45, 0x31, 0x41, 0x42, 0x43, 0xFF, 0x00, 0x56, 0x45, 0x32, 0x44,
-                0x45, 0x46, 0xFF, 0xEA, 0x56, 0x45, 0x33, 0x58, 0x59, 0x5A, 0xFF, 0x0E
+                0x1C, 0x04, 0x56, 0x45, 0x31, 0x41, 0x42, 0x43, 0xFF, 0x00, 0x60, 0x56, 0x45, 0x32,
+                0x44, 0x45, 0x46, 0xFF, 0xEA, 0xDC, 0x56, 0x45, 0x33, 0x58, 0x59, 0x5A, 0xFF, 0x0E,
+                0x51
             ],
             &encoded
         );
 
         let mut ex2 = Route::new(3);
-        ex2.push_callsign("VE1ABC", 0, false);
+        ex2.push_callsign(RouteIdentity::new("VE1ABC", 0, None, false));
         ex2.push_internet();
-        ex2.push_callsign("VE2DEF", 234, false);
+        ex2.push_callsign(RouteIdentity::new("VE2DEF", 234, Some(-86.5), false));
         ex2.push_internet();
-        ex2.push_callsign("VE3XYZ", 14, false);
+        ex2.push_callsign(RouteIdentity::new("VE3XYZ", 14, Some(-65.0), false));
 
         let encoded = ex2.encode(&mut buf).unwrap();
         assert_eq!(
             &[
-                0x1B, 0x03, 0x56, 0x45, 0x31, 0x41, 0x42, 0x43, 0xFF, 0x00, 0xFE, 0x56, 0x45, 0x32,
-                0x44, 0x45, 0x46, 0xFF, 0xEA, 0xFE, 0x56, 0x45, 0x33, 0x58, 0x59, 0x5A, 0xFF, 0x0E
+                0x1E, 0x03, 0x56, 0x45, 0x31, 0x41, 0x42, 0x43, 0xFF, 0x00, 0x00, 0xFE, 0x56, 0x45,
+                0x32, 0x44, 0x45, 0x46, 0xFF, 0xEA, 0x6E, 0xFE, 0x56, 0x45, 0x33, 0x58, 0x59, 0x5A,
+                0xFF, 0x0E, 0x8E
             ],
             &encoded
         );
 
         let mut ex3 = Route::new(0);
-        ex3.push_callsign("VE1ABC", 0, false);
+        ex3.push_callsign(RouteIdentity::new("VE1ABC", 0, Some(-42.5), false));
         ex3.push_internet();
         ex3.push_internet();
 
         let encoded = ex3.encode(&mut buf).unwrap();
         assert_eq!(
-            &[0x0B, 0x00, 0x56, 0x45, 0x31, 0x41, 0x42, 0x43, 0xFF, 0x00, 0xFE, 0xFE],
+            &[0x0C, 0x00, 0x56, 0x45, 0x31, 0x41, 0x42, 0x43, 0xFF, 0x00, 0xB0, 0xFE, 0xFE],
             &encoded
         );
     }
diff --git a/src/whisker/route.rs b/src/whisker/route.rs
index 33ef8c29aa360a69a352bfd4d18820ee5a5a73e1..af3df817d39863157fd7526fdcb5ce731ee812c1 100644
--- a/src/whisker/route.rs
+++ b/src/whisker/route.rs
@@ -25,25 +25,26 @@ impl Route {
     /// is_future=false when this callsign has digipeated
     /// is_future=true when this callsign is expected to be part of the route, but isn't yet
     /// see the specs for more information
-    pub fn push_callsign(&mut self, callsign: &str, ssid: u8, is_future: bool) -> Option<()> {
-        let len = callsign.as_bytes().len() + 2;
+    pub fn push_callsign(&mut self, ident: RouteIdentity) -> Option<()> {
+        let len = ident.callsign.as_bytes().len() + 3;
         let free_space = self.path.capacity() - self.path.len();
 
         if len > free_space {
             return None;
         }
 
-        self.has_future = self.has_future || is_future;
-        if self.has_future && !is_future {
+        self.has_future = self.has_future || ident.is_future;
+        if self.has_future && !ident.is_future {
             return None;
         }
 
         // safe to unwrap since we already did a length check
         self.path
-            .try_extend_from_slice(callsign.as_bytes())
+            .try_extend_from_slice(ident.callsign.as_bytes())
             .unwrap();
-        self.path.push(if is_future { 0xFD } else { 0xFF });
-        self.path.push(ssid);
+        self.path.push(if ident.is_future { 0xFD } else { 0xFF });
+        self.path.push(ident.ssid);
+        self.path.push(ident.rssi);
 
         Some(())
     }
@@ -65,7 +66,12 @@ impl Route {
     /// I.e. replace future node if possible
     /// Returns an Err if the route is out of space, or appending the node doesn't make logical sense
     /// (there's a future node that doesn't match)
-    pub fn append_node(&mut self, callsign: &str, ssid: u8) -> Result<(), AppendNodeError> {
+    pub fn append_node(
+        &mut self,
+        callsign: &str,
+        ssid: u8,
+        rssi: Option<f64>,
+    ) -> Result<(), AppendNodeError> {
         let mut new_route = Route::new(self.max_hops);
 
         let mut already_inserted = false;
@@ -74,37 +80,34 @@ impl Route {
                 RouteNode::Internet => new_route
                     .push_internet()
                     .ok_or(AppendNodeError::RouteOverflow)?,
-                RouteNode::Identity(rc, rs, is_future) => {
-                    let us = rc == callsign && rs == ssid;
+                RouteNode::Identity(ident) => {
+                    let us = ident.callsign() == callsign && ident.ssid() == ssid;
 
-                    if is_future {
+                    if ident.is_future() {
                         if us {
                             if already_inserted {
                                 return Err(AppendNodeError::DuplicateNode);
                             } else {
-                                new_route.push_callsign(callsign, ssid, false);
+                                new_route
+                                    .push_callsign(RouteIdentity::new(callsign, ssid, rssi, false));
                                 already_inserted = true;
                             }
+                        } else if already_inserted {
+                            new_route.push_callsign(ident);
                         } else {
-                            if already_inserted {
-                                new_route.push_callsign(rc, rs, true);
-                            } else {
-                                return Err(AppendNodeError::SetFuture);
-                            }
+                            return Err(AppendNodeError::SetFuture);
                         }
+                    } else if us {
+                        return Err(AppendNodeError::DuplicateNode);
                     } else {
-                        if us {
-                            return Err(AppendNodeError::DuplicateNode);
-                        } else {
-                            new_route.push_callsign(rc, rs, false);
-                        }
+                        new_route.push_callsign(ident);
                     }
                 }
             }
         }
 
         if !already_inserted {
-            new_route.push_callsign(callsign, ssid, false);
+            new_route.push_callsign(RouteIdentity::new(callsign, ssid, rssi, false));
         }
 
         if new_route.iter().count() > usize::from(new_route.max_hops) {
@@ -157,7 +160,51 @@ impl Route {
 #[derive(Debug, Eq, PartialEq)]
 pub enum RouteNode<'a> {
     Internet,
-    Identity(&'a str, u8, bool),
+    Identity(RouteIdentity<'a>),
+}
+
+#[derive(Debug, Eq, PartialEq)]
+pub struct RouteIdentity<'a> {
+    callsign: &'a str,
+    ssid: u8,
+    rssi: u8,
+    is_future: bool,
+}
+
+impl<'a> RouteIdentity<'a> {
+    pub fn new(callsign: &'a str, ssid: u8, rssi: Option<f64>, is_future: bool) -> Self {
+        let rssi = match rssi {
+            Some(rssi) => (rssi * 1.5 + 240.0).max(1.0) as u8,
+            None => 0,
+        };
+
+        Self {
+            callsign,
+            ssid,
+            rssi,
+            is_future,
+        }
+    }
+
+    pub fn callsign(&self) -> &'a str {
+        self.callsign
+    }
+
+    pub fn ssid(&self) -> u8 {
+        self.ssid
+    }
+
+    pub fn rssi(&self) -> Option<f64> {
+        if self.rssi == 0 {
+            None
+        } else {
+            Some(((self.rssi as f64) - 240.0) / 1.5)
+        }
+    }
+
+    pub fn is_future(&self) -> bool {
+        self.is_future
+    }
 }
 
 #[derive(Debug)]
@@ -201,11 +248,16 @@ impl<'a> UntrustedRouteIter<'a> {
         }
         self.seen_future |= is_future;
 
-        self.i += 1;
-        let ssid = *self.route.path.get(self.i).ok_or(())?;
-        self.i += 1;
+        let ssid = *self.route.path.get(self.i + 1).ok_or(())?;
+        let rssi = *self.route.path.get(self.i + 2).ok_or(())?;
+        self.i += 3;
 
-        Ok(RouteNode::Identity(callsign, ssid, is_future))
+        Ok(RouteNode::Identity(RouteIdentity {
+            callsign,
+            ssid,
+            rssi,
+            is_future,
+        }))
     }
 }
 
@@ -258,94 +310,164 @@ mod tests {
     #[test]
     fn append_fails_when_existing_future() {
         let mut r = Route::new(5);
-        r.push_callsign("C1", 0, false);
-        r.push_callsign("C2", 0, false);
-        r.push_callsign("C3", 0, true);
+        r.push_callsign(RouteIdentity::new("C1", 0, None, false))
+            .unwrap();
+        r.push_callsign(RouteIdentity::new("C2", 0, None, false))
+            .unwrap();
+        r.push_callsign(RouteIdentity::new("C3", 0, None, true))
+            .unwrap();
 
         assert_eq!(
             AppendNodeError::SetFuture,
-            r.append_node("C3", 1).unwrap_err()
+            r.append_node("C3", 1, None).unwrap_err()
         );
 
         assert_eq!(
             AppendNodeError::SetFuture,
-            r.append_node("C4", 0).unwrap_err()
+            r.append_node("C4", 0, None).unwrap_err()
         );
     }
 
     #[test]
     fn append_fails_when_would_exceed_max_hops() {
         let mut r = Route::new(3);
-        r.append_node("C1", 0).unwrap();
-        r.append_node("C2", 0).unwrap();
-        r.append_node("C2", 1).unwrap();
+        r.append_node("C1", 0, None).unwrap();
+        r.append_node("C2", 0, None).unwrap();
+        r.append_node("C2", 1, None).unwrap();
         assert_eq!(
             AppendNodeError::HopsOverflow,
-            r.append_node("C4", 0).unwrap_err()
+            r.append_node("C4", 0, None).unwrap_err()
         );
     }
 
     #[test]
     fn append_fails_when_already_in_route() {
         let mut r = Route::new(3);
-        r.append_node("C1", 0).unwrap();
+        r.append_node("C1", 0, None).unwrap();
 
         assert_eq!(
             AppendNodeError::DuplicateNode,
-            r.append_node("C1", 0).unwrap_err()
+            r.append_node("C1", 0, None).unwrap_err()
         );
     }
 
     #[test]
     fn append_overwrites_future() {
         let mut r = Route::new(5);
-        r.push_callsign("C1", 0, false);
-        r.push_callsign("C2", 0, false);
-        r.push_callsign("C3", 0, true);
-        r.push_callsign("C4", 0, true);
+        r.push_callsign(RouteIdentity::new("C1", 0, None, false))
+            .unwrap();
+        r.push_callsign(RouteIdentity::new("C2", 0, None, false))
+            .unwrap();
+        r.push_callsign(RouteIdentity::new("C3", 0, None, true))
+            .unwrap();
+        r.push_callsign(RouteIdentity::new("C4", 0, None, true))
+            .unwrap();
 
-        r.append_node("C3", 0).unwrap();
+        r.append_node("C3", 0, None).unwrap();
 
         let mut iter = r.iter();
-        assert_eq!(Some(RouteNode::Identity("C1", 0, false)), iter.next());
-        assert_eq!(Some(RouteNode::Identity("C2", 0, false)), iter.next());
-        assert_eq!(Some(RouteNode::Identity("C3", 0, false)), iter.next());
-        assert_eq!(Some(RouteNode::Identity("C4", 0, true)), iter.next());
+        assert_eq!(
+            Some(RouteNode::Identity(RouteIdentity::new(
+                "C1", 0, None, false
+            ))),
+            iter.next()
+        );
+        assert_eq!(
+            Some(RouteNode::Identity(RouteIdentity::new(
+                "C2", 0, None, false
+            ))),
+            iter.next()
+        );
+        assert_eq!(
+            Some(RouteNode::Identity(RouteIdentity::new(
+                "C3", 0, None, false
+            ))),
+            iter.next()
+        );
+        assert_eq!(
+            Some(RouteNode::Identity(RouteIdentity::new("C4", 0, None, true))),
+            iter.next()
+        );
         assert_eq!(None, iter.next());
     }
 
     #[test]
     fn append_overwrites_future_even_when_at_hop_limit() {
         let mut r = Route::new(4);
-        r.push_callsign("C1", 0, false);
-        r.push_callsign("C2", 0, false);
-        r.push_callsign("C3", 0, true);
-        r.push_callsign("C4", 0, true);
+        r.push_callsign(RouteIdentity::new("C1", 0, None, false))
+            .unwrap();
+        r.push_callsign(RouteIdentity::new("C2", 0, None, false))
+            .unwrap();
+        r.push_callsign(RouteIdentity::new("C3", 0, None, true))
+            .unwrap();
+        r.push_callsign(RouteIdentity::new("C4", 0, None, true))
+            .unwrap();
 
-        r.append_node("C3", 0).unwrap();
+        r.append_node("C3", 0, None).unwrap();
 
         let mut iter = r.iter();
-        assert_eq!(Some(RouteNode::Identity("C1", 0, false)), iter.next());
-        assert_eq!(Some(RouteNode::Identity("C2", 0, false)), iter.next());
-        assert_eq!(Some(RouteNode::Identity("C3", 0, false)), iter.next());
-        assert_eq!(Some(RouteNode::Identity("C4", 0, true)), iter.next());
+        assert_eq!(
+            Some(RouteNode::Identity(RouteIdentity::new(
+                "C1", 0, None, false
+            ))),
+            iter.next()
+        );
+        assert_eq!(
+            Some(RouteNode::Identity(RouteIdentity::new(
+                "C2", 0, None, false
+            ))),
+            iter.next()
+        );
+        assert_eq!(
+            Some(RouteNode::Identity(RouteIdentity::new(
+                "C3", 0, None, false
+            ))),
+            iter.next()
+        );
+        assert_eq!(
+            Some(RouteNode::Identity(RouteIdentity::new("C4", 0, None, true))),
+            iter.next()
+        );
         assert_eq!(None, iter.next());
     }
 
     #[test]
     fn append_appends_when_no_future() {
         let mut r = Route::new(5);
-        r.push_callsign("C1", 0, false);
-        r.push_callsign("C2", 0, false);
-        r.push_callsign("C3", 0, false);
+        r.push_callsign(RouteIdentity::new("C1", 0, None, false))
+            .unwrap();
+        r.push_callsign(RouteIdentity::new("C2", 0, None, false))
+            .unwrap();
+        r.push_callsign(RouteIdentity::new("C3", 0, None, false))
+            .unwrap();
 
-        r.append_node("C4", 0).unwrap();
+        r.append_node("C4", 0, None).unwrap();
 
         let mut iter = r.iter();
-        assert_eq!(Some(RouteNode::Identity("C1", 0, false)), iter.next());
-        assert_eq!(Some(RouteNode::Identity("C2", 0, false)), iter.next());
-        assert_eq!(Some(RouteNode::Identity("C3", 0, false)), iter.next());
-        assert_eq!(Some(RouteNode::Identity("C4", 0, false)), iter.next());
+        assert_eq!(
+            Some(RouteNode::Identity(RouteIdentity::new(
+                "C1", 0, None, false
+            ))),
+            iter.next()
+        );
+        assert_eq!(
+            Some(RouteNode::Identity(RouteIdentity::new(
+                "C2", 0, None, false
+            ))),
+            iter.next()
+        );
+        assert_eq!(
+            Some(RouteNode::Identity(RouteIdentity::new(
+                "C3", 0, None, false
+            ))),
+            iter.next()
+        );
+        assert_eq!(
+            Some(RouteNode::Identity(RouteIdentity::new(
+                "C4", 0, None, false
+            ))),
+            iter.next()
+        );
         assert_eq!(None, iter.next());
     }
 }