diff --git a/ESP8266_Transmitter/ESP8266_Transmitter.ino b/ESP8266_Transmitter/ESP8266_Transmitter.ino
index a3ac0ab844625ac825ccf40339ac5b127c288530..bddeadc164194b3b9277b39b3126739108ac4394 100644
--- a/ESP8266_Transmitter/ESP8266_Transmitter.ino
+++ b/ESP8266_Transmitter/ESP8266_Transmitter.ino
@@ -209,7 +209,7 @@ boolean readPMSdata(Stream *s) {
   memcpy((void *)&data, (void *)buffer_u16, 30);
  
   if (sum != data.checksum) {
-    Serial.println("Checksum failure");
+    Serial.print("\n Checksum failure... ");
     Serial.print("Expected: "); Serial.print(sum);
     Serial.print(", Got: "); Serial.print(data.checksum);
     return false;
@@ -241,12 +241,12 @@ boolean clearToSend(int listenDuration) {
 
 // Listen of listenDuration seconds
 // If we see a response to our txHello packet, and txHello.okToTransmit is True, we can send our packet
-boolean listenTxHelloAccept(int listenDuration) {
+boolean listenTxHelloAccept(int listenDuration, int messageID) {
   int time_now = now() + listenDuration;
 
   // Listen until timeout expires
+  Serial.println("[+] Transmit - \"Hello\" - Listening for ack & clear to send");
   while (time_now >= now()) {
-    Serial.println("Listening for auth");
     int packetSize = LoRa.parsePacket();
     
     if (packetSize) {
@@ -280,16 +280,24 @@ boolean listenTxHelloAccept(int listenDuration) {
       StaticJsonDocument<200> doc;
       deserializeJson(doc, incoming);
 
-      const bool okToCopy = doc["okToTransmit"];
+      const bool okToTransmit = doc["okTransmit"];
       const String authIsForUid = doc["uid"];
+      const int authIsForMessageID = doc["messageID"];
+      const String gatewayUid = doc["gatewayUid"];
 
-      // Verify txHello.okToTransmit is True & UID Match
-      return (okToCopy && authIsForUid == getSensorUID());
+      // Verify txHello.okToTransmit is True & UID Match & Message IDs Match
+      if (authIsForUid == getSensorUID()) { Serial.println("[+] Transmit - \"Hello\" - Sensor UID Match!"); } else { Serial.println("[-] Transmit - \"Hello\" - Sensor UID Mis-Match! " + String(authIsForUid) + " vs " + String(getSensorUID())); }
+      if (authIsForMessageID == messageID) { Serial.println("[+] Transmit - \"Hello\" - Message ID Match!"); } else { Serial.println("[-] Transmit - \"Hello\" - MessageID Mis-Match!"); }
+      
+      return (okToTransmit 
+        && authIsForUid == getSensorUID() 
+        && authIsForMessageID == messageID);
     }
 
-    delay(5);
+    delay(3);
   }
 
+  Serial.println("[-] Transmit - \"Hello\" - Timeout while waiting for Clear to Send\n\n");
   return false; // We didn't hear anything, conside this as meaning "Can't Send"
 }
 
@@ -304,38 +312,103 @@ boolean transmitData(DynamicJsonDocument payload) {
 
   // Listen for other communication
   //    Rx - Listen for other messages, if no messages heard then continue
-//  if (!clearToSend(0.5)) {
-//    Serial.println("[-] Airways busy, could not send");
-//    delay(random(500, 1250)); // Introduce random delay to avoid another collision
-//    return false;
-//  }
-
+  if (!clearToSend(0.5)) {
+    Serial.println("[-] Airways busy, could not send");
+    delay(random(500, 1250)); // Introduce random delay to avoid another collision
+
+    // TODO Refactor
+    while (!clearToSend(0.5)) {
+      Serial.println("[-] Airways busy, could not send");
+      delay(random(500, 1250)); // Introduce random delay to avoid another collision
+    }
+    //return false;
+  }
 
+  Serial.println("[+] Transmit - \"Hello\"");
   // Send short "clear to send?" packet
   //    Tx - "I've got data to send!" + UID
   //    RX - Continue upon recieving "OK" + UID + TX_Auth_ID
   DynamicJsonDocument txHello(2048);
   txHello["uid"] = sensorID;
   txHello["reservationTime"] = reservationTime; // How long do we require reservation of radio?
+  txHello["messageID"] = msgCount;
   sendJsonPayloadWithLoRa(txHello);
 
-  if (!listenTxHelloAccept(reservationTime * 1.1)) { // Else we have clear to send
-    return false; // Can't transmit just now
-    
-  } else {
-    Serial.println("OK To Transmit");
+  if (!listenTxHelloAccept(reservationTime * 1.5, msgCount)) { // Can't transmit just now
+    Serial.println("[-] Transmit - \"Hello\" - Can Not Transmit At This Time\n");
+    return false; 
   }
 
+  Serial.println("[+] Recieved - Clear to Transmit Payload"); // Else we have clear to send
 
   // Transmit Payload
   //    Tx - Send payload + UID + TX_Auth_ID
   //    Rx - Listen for Ack/Nack
-  Serial.println("Sending Payload Now");
+  Serial.println("[+] Transmit - Payload");
   sendJsonPayloadWithLoRa(payload);
 
 
   // TODO Await Response Ack/Nak
+  int ackTimeout = 2; // Seconds
+  int time_now = now() + ackTimeout;
 
+  // Listen until timeout expires
+  Serial.println("[.] Transmit - Payload - Listening for Ack");
+  while (time_now >= now()) {
+    int packetSize = LoRa.parsePacket();
+    
+    if (packetSize) {
+      String incoming = "";
+      char temp;
+      
+      while (LoRa.available()) {
+        // TODO - Tidy this  up, ensure we only read in valid JSON
+        temp = (char)LoRa.read();
+
+        // Opening {
+        if (incoming.length() == 0 && temp == '{') {
+          incoming = "{";
+          
+        // Closing }  
+        } else if (temp == '}') {
+          incoming.concat("}");
+          break;
+
+        // Anything else that's valid
+        } else if (incoming.length() > 0) {
+          incoming.concat(temp);
+        }
+      }
+
+      // DEBUG
+//      Serial.print("\nin listedForAck() Recieved: \n"); 
+//      Serial.println(incoming);
+
+      StaticJsonDocument<200> doc;
+      deserializeJson(doc, incoming);
+
+      const bool ackStatus = doc["ackStatus"];
+      const String authIsForUid = doc["uid"];
+      const String gatewayUid = doc["gatewayUid"];
+
+      // Verify txHello.okToTransmit is True & UID Match
+      if (authIsForUid == getSensorUID()) {
+        Serial.println("[+] Transmit - Payload - Ack Recieved: " + String(ackStatus) + "\n");
+        
+        if (ackStatus) { return true; } // It all worked :)
+
+        // TODO Retransmit, recover, etc
+        return false;
+      }
+
+      // Else UID Mis-Match so we wait for next message
+    }
+
+    delay(5);
+  }
+
+  // TODO After Timeout we need to deal with!
+  Serial.println("[-] Transmit - Payload - Ack Timeout Reached - Assuming Message Was Not Delivered");
 
   // TODO Listen for ack/nak
  
@@ -359,7 +432,7 @@ void setup() {
   delay(1000);
   
   Serial.begin(115200); // Console Debug
-  Serial.println("[+] Transmitter Node");
+  Serial.println("\n\n[+] Transmitter Node");
 
   sensorID = getSensorUID();
 
@@ -385,7 +458,7 @@ void loop() {
   pollEventCount++;
   
   Serial.println();
-  Serial.print(String(pollEventCount) + ") Std Units: ");
+  Serial.print(String(pollEventCount) + ") ");
   Serial.print("PM 1.0: "); Serial.print(data.pm10_standard);
   Serial.print("\t\tPM 2.5: "); Serial.print(data.pm25_standard);
   Serial.print("\t\tPM 10: "); Serial.print(data.pm100_standard);
@@ -408,13 +481,13 @@ void loop() {
     avgHumidity = humidity / sendAfterPolls;
 
     // TODO Transmit Sensor Data
-    Serial.println("---------------------------------------");
+    Serial.println("");
     Serial.print("Avg ppm10: "); Serial.print(avgPpm10);
     Serial.print("\t\tAvg ppm25: "); Serial.print(avgPpm25);
     Serial.print("\t\tAvg ppm100: "); Serial.print(avgPpm100);
     Serial.print("\t\tAvg Temp: "); Serial.print(avgTemperature);
-    Serial.print("\t\tAvg Humidity: "); Serial.println(avgHumidity);
-    Serial.print("Chip ID: "); Serial.println(sensorID);
+    Serial.print("\t\tAvg Humidity: "); Serial.print(avgHumidity);
+    Serial.print("\t\tChip ID: "); Serial.println(sensorID);
     Serial.println("");
 
     // LORA SEND
@@ -443,40 +516,22 @@ void loop() {
       Serial.println("Packet Sent\n");
       
     } else {
-      while (!transmitData(doc)){
-        Serial.println("[-] Failed to send packet, retrying\n");
-        delay(reservationTime + random(250, 1250)); // Introduce random delay to avoid another collision
+      int maxRetries = 10; // TODO Move to Config
+      int numRetries = 1;
+      
+      while (!transmitData(doc) && numRetries < maxRetries){
+        numRetries++;
+        Serial.println("[-] Failed to send packet, retrying. Attempt " + String(numRetries) + " of " + String(maxRetries) + "\n");
+        delay(reservationTime + random(1250, 5250)); // Introduce random delay to avoid another collision
       }
-    }
 
-    Serial.println("---------------------------------------");
-
-    // TODO Wait for reply
-//      int i = 3000;
-//      int j = 0;
-//      String incoming = "";
-//      
-//      while (j < i) {
-//        
-//        int packetSize = LoRa.parsePacket();
-//        if (packetSize) {
-//          while (LoRa.available()) {
-//            incoming.concat((char)LoRa.read());
-//          }
-//
-//          // TODO Parse response to JSON, check if matches device & message ID
-//          Serial.print("Inbound!: \n");
-//          Serial.print(incoming);
-//          break;
-//        }
-//
-//        j+=10;
-//        delay(10);
-//
-//        // TODO If no response then consider not delivered
-//      }
-//      Serial.print("\n");
+      if (numRetries >= maxRetries) {
+        Serial.println("[-] Failed to send packet, max retries reached. Aborting");
 
+        // TODO Don't Clear Counters, record more values then try to retransmit
+      }
+    }
+    
     // Reset Loop Values
     ppm10 = 0;
     ppm25 = 0;