diff --git a/app/src/main/java/eu/ztsh/garmin/Garmin.kt b/app/src/main/java/eu/ztsh/garmin/Garmin.kt
index 46a702b..e9731cc 100644
--- a/app/src/main/java/eu/ztsh/garmin/Garmin.kt
+++ b/app/src/main/java/eu/ztsh/garmin/Garmin.kt
@@ -5,11 +5,11 @@ import android.bluetooth.BluetoothAdapter
 import android.bluetooth.BluetoothDevice
 import android.bluetooth.BluetoothSocket
 import android.util.Log
-import com.mapbox.navigation.core.trip.session.LocationMatcherResult
-import com.mapbox.navigation.core.trip.session.NavigationSessionState
 import com.mapbox.navigation.tripdata.maneuver.model.Maneuver
 import eu.ztsh.garmin.data.DataCache
+import eu.ztsh.garmin.data.GarminManeuver
 import eu.ztsh.garmin.data.GarminMapper
+import eu.ztsh.garmin.data.GarminModelItem
 import eu.ztsh.garmin.data.MapboxMapper
 import java.io.IOException
 import java.util.*
@@ -39,46 +39,61 @@ class Garmin(
         ManeuverProcessingThread(maneuver).start()
     }
 
-    fun process(location: LocationMatcherResult) {
-        LocationProcessingThread(location).start()
-    }
+//    fun process(location: LocationMatcherResult) {
+//        LocationProcessingThread(location).start()
+//    }
 
-    fun process(navigationSessionState: NavigationSessionState) {
-        cache.update(navigationSessionState)
-    }
+//    fun process(navigationSessionState: NavigationSessionState) {
+//        cache.update(navigationSessionState)
+//    }
 
-    private inner class ManeuverProcessingThread(val maneuver: Maneuver) : ProcessingThread() {
+    private inner class ManeuverProcessingThread(val maneuver: Maneuver) : ProcessingThread<GarminManeuver>() {
 
-        override fun run() {
+        override fun process(): GarminManeuver? {
             if (cache.hasChanged(maneuver)) {
                 cache.update(maneuver)
-                send(MapboxMapper.apply(maneuver))
+                return MapboxMapper.map(maneuver)
             }
+            return null
+        }
+
+        override fun enqueue(item: GarminManeuver) {
+            if (cache.hasChanged(item.lanes)) {
+                connection.enqueue(GarminMapper.map(item.lanes))
+            }
+            if (cache.hasChanged(item.direction)) {
+                connection.enqueue(GarminMapper.map(item.direction))
+            }
+            if (cache.hasChanged(item.distance)) {
+                connection.enqueue(GarminMapper.map(item.distance))
+            }
+            // flag?
         }
 
     }
 
-    private inner class LocationProcessingThread(val location: LocationMatcherResult) : ProcessingThread() {
+//    private inner class LocationProcessingThread(val location: LocationMatcherResult) : ProcessingThread() {
+//
+//        override fun process() {
+//            if (cache.hasChanged(location)) {
+//                cache.update(location)
+//                send(MapboxMapper.apply(location))
+//            }
+//        }
+//    }
+
+    private abstract inner class ProcessingThread<T : GarminModelItem> : Thread() {
+
+        abstract fun process(): T?
+
+        abstract fun enqueue(item: T)
 
         override fun run() {
-            if (cache.hasChanged(location)) {
-                cache.update(location)
-                send(MapboxMapper.apply(location))
+            val processing = process()
+            if (processing != null) {
+                enqueue(processing)
+                cache.update(processing)
             }
-        }
-
-    }
-
-    private open inner class ProcessingThread : Thread() {
-
-        fun send(incoming: eu.ztsh.garmin.data.State) {
-            if (cache.hasChanged(incoming.distance)) {
-                connection.enqueue(GarminMapper.setDistance(incoming))
-            }
-            if (cache.hasChanged(incoming.direction)) {
-                connection.enqueue(GarminMapper.setDirection(incoming))
-            }
-            cache.update(incoming)
             observer.join(this)
         }
 
@@ -86,7 +101,7 @@ class Garmin(
 
     private inner class ProcessingThreadObserver {
 
-        fun join(thread: ProcessingThread) {
+        fun <T : GarminModelItem> join(thread: ProcessingThread<T>) {
             thread.join()
         }
 
diff --git a/app/src/main/java/eu/ztsh/garmin/data/DataCache.kt b/app/src/main/java/eu/ztsh/garmin/data/DataCache.kt
index a7f8b8b..2abeaa8 100644
--- a/app/src/main/java/eu/ztsh/garmin/data/DataCache.kt
+++ b/app/src/main/java/eu/ztsh/garmin/data/DataCache.kt
@@ -6,39 +6,38 @@ import com.mapbox.navigation.tripdata.maneuver.model.Maneuver
 
 class DataCache {
 
-    private val stateCache: State = State()
+    private val garminManeuver: GarminManeuver = GarminManeuver.empty()
     private var maneuverCache: Maneuver? = null
     private var locationCache: LocationMatcherResult? = null
     private var session: NavigationSessionState? = null
 
     // state
-    fun hasChanged(lanes: Lanes?): Boolean {
-        return stateCache.lineArrows == null || stateCache.lineArrows != lanes
+    fun hasChanged(lanes: Lanes): Boolean {
+        return garminManeuver.lanes != lanes
     }
 
-    fun hasChanged(outlines: Outlines?): Boolean {
-        return stateCache.lineOutlines == null || stateCache.lineOutlines != outlines
+    fun hasChanged(distance: Distance): Boolean {
+        return garminManeuver.distance != distance
     }
 
-    fun hasChanged(distance: Distance?): Boolean {
-        return stateCache.distance == null || stateCache.distance != distance
-    }
-
-    fun hasChanged(direction: Direction?): Boolean {
-        return stateCache.direction == null || stateCache.direction != direction
-    }
-
-    fun hasChanged(speed: Speed?): Boolean {
-        return stateCache.speed == null || stateCache.speed != speed
-    }
-
-    fun hasChanged(arrival: Arrival?): Boolean {
-        return stateCache.arrival == null || stateCache.arrival != arrival
+    fun hasChanged(direction: Direction): Boolean {
+        return garminManeuver.direction != direction
     }
+//
+//    fun hasChanged(speed: Speed?): Boolean {
+//        return stateCache.speed == null || stateCache.speed != speed
+//    }
+//
+//    fun hasChanged(arrival: Arrival?): Boolean {
+//        return stateCache.arrival == null || stateCache.arrival != arrival
+//    }
 
     // Merge states
-    fun update(state: State) {
-        stateCache.merge(state)
+    fun update(item: GarminModelItem) {
+        when(item) {
+            is GarminManeuver -> garminManeuver.merge(item)
+        }
+
     }
 
     // maneuver
diff --git a/app/src/main/java/eu/ztsh/garmin/data/GarminMapper.kt b/app/src/main/java/eu/ztsh/garmin/data/GarminMapper.kt
index 9045fff..11757f5 100644
--- a/app/src/main/java/eu/ztsh/garmin/data/GarminMapper.kt
+++ b/app/src/main/java/eu/ztsh/garmin/data/GarminMapper.kt
@@ -4,24 +4,20 @@ class GarminMapper {
 
     companion object {
 
-        fun setLines(state: State): IntArray {
-            return intArrayOf(0x02, state.lineOutlines.sumOf { it.value }, state.lineArrows.sumOf { it.value })
+        fun map(lanes: Lanes): IntArray {
+            return intArrayOf(0x02, lanes.lanes.lanes.sumOf { it.value }, lanes.outlines.lanes.sumOf { it.value })
         }
 
-        fun setDirection(state: State): IntArray {
-            return setDirection(state.direction.angle, state.direction.out, state.direction.roundabout)
+        fun map(direction: Direction): IntArray {
+            return toDirectionArray(direction.angle, direction.out, direction.roundabout)
         }
 
-        fun setDistance(state: State): IntArray {
-            return setDistance(state.distance, state.unit)
+        fun map(distance: Distance): IntArray {
+            return setDistance(distance.distance, distance.unit)
         }
 
-        fun setSpeed(state: State): IntArray {
-            return setSpeed(state.speed, state.limit, state.speed > state.limit)
-        }
-
-        fun setSpeedFreeRide(state: State): Pair<IntArray, IntArray> {
-            return Pair(setDistance(state.speed), setSpeed(state.limit, limitWarning = state.speed > state.limit))
+        fun map(speed: Speed): IntArray {
+            return setSpeed(speed.speed, speed.limit, speed.speed > speed.limit)
         }
 
         fun setTime(hours: Int, minutes: Int, traffic: Boolean = false, flag: Boolean = false): IntArray {
@@ -54,20 +50,15 @@ class GarminMapper {
             }
         }
 
-        fun setSpeedControl(state: State): IntArray {
-            return intArrayOf(0x04, if (state.control) 0x01 else 0x02)
-        }
-
-        fun setCompass(state: State): IntArray {
-            // TODO: Implement
-            return setDirection(OutAngle.Straight, OutType.ArrowOnly)
+        fun speedControl(state: Boolean): IntArray {
+            return intArrayOf(0x04, if (state) 0x01 else 0x02)
         }
 
         fun cleanDistance(): IntArray {
             return intArrayOf(0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00)
         }
 
-        private fun setDirection(
+        private fun toDirectionArray(
             angle: OutAngle,
             out: OutType = OutType.Lane,
             roundabout: OutAngle = OutAngle.AsDirection
diff --git a/app/src/main/java/eu/ztsh/garmin/data/MapboxMapper.kt b/app/src/main/java/eu/ztsh/garmin/data/MapboxMapper.kt
index db40c45..eada8e1 100644
--- a/app/src/main/java/eu/ztsh/garmin/data/MapboxMapper.kt
+++ b/app/src/main/java/eu/ztsh/garmin/data/MapboxMapper.kt
@@ -7,14 +7,14 @@ class MapboxMapper {
 
     companion object {
 
-        fun apply(maneuver: Maneuver): State {
-            val state = State()
+        fun map(maneuver: Maneuver): GarminManeuver {
+            val state = GarminManeuver()
             maneuver.apply {
                 this.primary.apply {
                     state.direction = Direction()
                     when (this.type) {
                         "roundabout" -> {
-                            state.direction!!.out = OutType.RightRoundabout
+                            state.direction.out = OutType.RightRoundabout
                         }
 
                         "arrive" -> {
@@ -24,11 +24,11 @@ class MapboxMapper {
                     when (this.modifier) {
                         "right" -> {
                             when (this.type) {
-                                "turn" -> state.direction!!.angle = OutAngle.Right
+                                "turn" -> state.direction.angle = OutAngle.Right
                                 "roundabout" -> {
                                     when (this.degrees) {
-                                        137.0 -> state.direction!!.angle = OutAngle.EasyRight
-                                        180.0 -> state.direction!!.angle = OutAngle.Straight
+                                        137.0 -> state.direction.angle = OutAngle.EasyRight
+                                        180.0 -> state.direction.angle = OutAngle.Straight
                                     }
                                 }
                             }
@@ -36,16 +36,16 @@ class MapboxMapper {
 
                         "left" -> {
                             when (this.type) {
-                                "turn" -> state.direction!!.angle = OutAngle.Left
+                                "turn" -> state.direction.angle = OutAngle.Left
                             }
                         }
                     }
                 }
                 this.stepDistance.apply {
                     this.distanceRemaining?.apply {
-                        distanceFormatter.formatDistance(distanceRemaining!!).split(" ").apply {
+                        distanceFormatter.formatDistance(this).split(" ").apply {
                             state.distance = Distance(
-                                this[0].replace(',', '.').toDouble().toInt(),
+                                this[0].replace(',', '.').toDouble(),
                                 when (this[1]) {
                                     "m" -> Unit.Metres
                                     "km" -> Unit.Kilometres
@@ -65,8 +65,8 @@ class MapboxMapper {
             return state
         }
 
-        fun apply(locationMatcherResult: LocationMatcherResult): State {
-            val state = State()
+        fun map(locationMatcherResult: LocationMatcherResult): GarminLocation {
+            val state = GarminLocation()
             // TODO: speed, limit, location?, bearing
             return state
         }
diff --git a/app/src/main/java/eu/ztsh/garmin/data/Model.kt b/app/src/main/java/eu/ztsh/garmin/data/Model.kt
index a11b2a3..82bffe6 100644
--- a/app/src/main/java/eu/ztsh/garmin/data/Model.kt
+++ b/app/src/main/java/eu/ztsh/garmin/data/Model.kt
@@ -12,7 +12,6 @@ enum class OutType(val value: Int) {
 
 }
 
-
 enum class OutAngle(val value: Int) {
 
     Down(0x01),
@@ -52,7 +51,7 @@ enum class Lane(val value: Int) {
 
 }
 
-open class Arrows(val lanes: List<Lane>) {
+class Arrows(val lanes: List<Lane>) {
 
     override fun equals(other: Any?): Boolean {
         if (this === other) return true
@@ -68,11 +67,9 @@ open class Arrows(val lanes: List<Lane>) {
     }
 }
 
-class Lanes(lanes: List<Lane>) : Arrows(lanes)
+class Lanes(val outlines: Arrows, val lanes: Arrows)
 
-class Outlines(lanes: List<Lane>) : Arrows(lanes)
-
-class Distance(val distance: Int, val unit: Unit) {
+class Distance(val distance: Double, val unit: Unit) {
 
     override fun equals(other: Any?): Boolean {
         if (this === other) return true
@@ -87,7 +84,7 @@ class Distance(val distance: Int, val unit: Unit) {
     }
 
     override fun hashCode(): Int {
-        var result = distance
+        var result = distance.hashCode()
         result = 31 * result + unit.hashCode()
         return result
     }
@@ -98,47 +95,12 @@ class Speed(val speed: Int, val limit: Int)
 
 class Arrival(val hours: Int, val minutes: Int)
 
-class State {
-
-    var lineArrows: Lanes? = null
-    var lineOutlines: Outlines? = null
-    var direction : Direction? = null
-    var distance: Distance? = null
-    var speed: Speed? = null
-    var arrival: Arrival? = null
-    // TODO: Bearing
-    // TODO: support
-    var traffic: Boolean? = null
-    var flag: Boolean? = null
-    var control: Boolean? = null
-    
-    fun merge(other: State) {
-        if (other.lineArrows != null) {
-            this.lineArrows = other.lineArrows
-        }
-        if (other.lineOutlines != null) {
-            this.lineOutlines = other.lineOutlines
-        }
-        if (other.direction != null) {
-            this.direction = other.direction
-        }
-        if (other.distance != null) {
-            this.distance = other.distance
-        }
-        if (other.speed != null) {
-            this.speed = other.speed
-        }
-        if (other.arrival != null) {
-            this.arrival = other.arrival
-        }
-    }
-
-}
-
-class Direction {
-    var angle: OutAngle = OutAngle.AsDirection
-    var out: OutType = OutType.Lane
+class Direction(
+    var angle: OutAngle = OutAngle.AsDirection,
+    var out: OutType = OutType.Lane,
     var roundabout: OutAngle = OutAngle.AsDirection
+) {
+
     override fun equals(other: Any?): Boolean {
         if (this === other) return true
         if (javaClass != other?.javaClass) return false
@@ -160,3 +122,39 @@ class Direction {
     }
 
 }
+
+interface GarminModelItem {
+
+    fun merge(item: GarminModelItem)
+}
+
+class GarminManeuver : GarminModelItem {
+
+    lateinit var lanes: Lanes
+    lateinit var direction: Direction
+    lateinit var distance: Distance
+    var flag: Boolean = false // WTF?
+
+    override fun merge(item: GarminModelItem) {
+        TODO("Not yet implemented")
+    }
+
+    companion object {
+
+        val empty: () -> GarminManeuver = {
+            val manouver = GarminManeuver()
+            manouver.lanes = Lanes(Arrows(listOf()), Arrows(listOf()))
+            manouver.direction = Direction(out = OutType.Off)
+            manouver.distance = Distance(0.0, Unit.Any)
+            manouver
+        }
+    }
+}
+
+class GarminLocation : GarminModelItem {
+
+    override fun merge(item: GarminModelItem) {
+        TODO("Not yet implemented")
+    }
+
+}
diff --git a/app/src/test/java/eu/ztsh/garmin/data/GarminMapperTest.kt b/app/src/test/java/eu/ztsh/garmin/data/GarminMapperTest.kt
index f0f1269..82be573 100644
--- a/app/src/test/java/eu/ztsh/garmin/data/GarminMapperTest.kt
+++ b/app/src/test/java/eu/ztsh/garmin/data/GarminMapperTest.kt
@@ -253,10 +253,8 @@ class GarminMapperTest {
     }
 
     private fun linesTest(outlines: List<Lane>, arrows: List<Lane>, expectedRaw: IntArray, expectedBoxed: IntArray) {
-        val state = State()
-        state.lineOutlines = outlines
-        state.lineArrows = arrows
-        makeAssertions(GarminMapper.setLines(state), expectedRaw, expectedBoxed)
+        val lanes = Lanes(Arrows(arrows), Arrows(outlines))
+        makeAssertions(GarminMapper.map(lanes), expectedRaw, expectedBoxed)
     }
 
     private fun directionTest(outAngle: OutAngle, expectedRaw: IntArray, expectedBoxed: IntArray) {
@@ -264,10 +262,8 @@ class GarminMapperTest {
     }
 
     private fun directionTest(outAngle: OutAngle, outType: OutType, expectedRaw: IntArray, expectedBoxed: IntArray) {
-        val state = State()
-        state.direction.angle = outAngle
-        state.direction.out = outType
-        makeAssertions(GarminMapper.setDirection(state), expectedRaw, expectedBoxed)
+        val direction = Direction(outAngle, outType)
+        makeAssertions(GarminMapper.map(direction), expectedRaw, expectedBoxed)
     }
 
     private fun makeAssertions(resultRaw: IntArray, expectedRaw: IntArray, expectedBoxed: IntArray) {