diff --git a/enni.html b/enni.html
index 80c64e1243f770a73088c458f0c1a9aa3aa3e3c2..08872a394c4d69c596336f6b9c4548ade9d3672a 100644
--- a/enni.html
+++ b/enni.html
@@ -32,28 +32,7 @@
 
 <body>
   <script type="text/javascript">
-    TMS_NUMBER = 2050001;
-    DIRECTION1_TEXT = "Suunta: tulee vasemmalta";
-    DIRECTION2_TEXT = "Suunta: tulee oikealta";
-
-    VEHICLE_CAR = 1;
-    VEHICLE_TRUCK = 2;
-    VEHICLE_BUS = 3;
-
-    AUDIO = {};
-    // Wav files are also available.
-    AUDIO[VEHICLE_CAR] = 'audio/car_marimba.mp3';
-    AUDIO[VEHICLE_TRUCK] = 'audio/truck_glockenspiel.mp3';
-    AUDIO[VEHICLE_BUS] = 'audio/bus_mallets.mp3';
-
-    SEP = ',';
-    SERVER = 'wss://smarter-data.tt.utu.fi/ws/';
-    // SERVER = 'ws://localhost:8080/'
-
-    function send_data(ws, direction, vehicle_class) {
-      ws.send(TMS_NUMBER + SEP + direction + SEP + vehicle_class + SEP + new Date().getTime());
-      new Audio(AUDIO[vehicle_class]).play();
-    }
+    TMS_NUMBER = 2050003;
   </script>
 
   <!-- Add your site or application content here -->
@@ -91,43 +70,7 @@
       </div>
     </div>
   </div>
-  <script type="text/javascript">
-    // Varoita, jos piste ei ole valittuna.
-
-    document.getElementById('direction1').textContent = DIRECTION1_TEXT;
-    document.getElementById('direction2').textContent = DIRECTION2_TEXT;
-
-    // https://stackoverflow.com/a/23176223
-    function connect() {
-      ws = new WebSocket(SERVER);
-      // ws.onopen = function() {
-      //   // subscribe to some channels
-      //   ws.send(JSON.stringify({
-      //       //.... some message the I must send when I connect ....
-      //   }));
-      // };
-
-      ws.onmessage = function(e) {
-        console.log('Message:', e.data);
-      };
-
-      ws.onclose = function(e) {
-        console.log('Socket is closed. Reconnect will be attempted in 1 second.', e.reason);
-        setTimeout(function() {
-          connect();
-        }, 1000);
-      };
-
-      ws.onerror = function(err) {
-        console.error('Socket encountered error: ', err.message, 'Closing socket');
-        ws.close();
-      };
-    }
-    function send(direction, vehicle,) {
-      console.log();
-    }
-    connect();
-  </script>
+  <script src="js/smarter-ui.js"></script>
 
 </body>
 
diff --git a/js/smarter-ui.js b/js/smarter-ui.js
new file mode 100644
index 0000000000000000000000000000000000000000..7c5ffa0c9a1dff3ddc2bf5384eb7ce1c8ed81727
--- /dev/null
+++ b/js/smarter-ui.js
@@ -0,0 +1,68 @@
+DIRECTION1_TEXT = "Suunta: tulee vasemmalta";
+DIRECTION2_TEXT = "Suunta: tulee oikealta";
+
+// Make it easier to read CSV files
+USER_AGENT = navigator.userAgent.replace(';', '').replace(',', '');
+
+VEHICLE_CAR = 1;
+VEHICLE_TRUCK = 2;
+VEHICLE_BUS = 3;
+
+AUDIO = {};
+// Wav files are also available.
+AUDIO[VEHICLE_CAR] = 'audio/car_marimba.mp3';
+AUDIO[VEHICLE_TRUCK] = 'audio/truck_glockenspiel.mp3';
+AUDIO[VEHICLE_BUS] = 'audio/bus_mallets.mp3';
+
+SEP = ',';
+// SERVER = 'wss://smarter-data.tt.utu.fi/ws/';
+SERVER = 'ws://localhost:8080/'
+
+function send_data(ws, direction, vehicle_class) {
+  ws.send(TMS_NUMBER + SEP + direction + SEP + vehicle_class + SEP + new Date().getTime() + SEP + USER_AGENT);
+}
+
+document.getElementById('direction1').textContent = DIRECTION1_TEXT;
+document.getElementById('direction2').textContent = DIRECTION2_TEXT;
+
+var heartBeat;
+
+// https://stackoverflow.com/a/23176223
+function connect() {
+  ws = new WebSocket(SERVER);
+  ws.onopen = function() {
+    // Initiate hearbeat
+    heartBeat = setInterval(function() {
+      console.log("PING");
+      ws.send('PING' + SEP + new Date().getTime() + SEP + USER_AGENT); 
+    }, 5000);
+  };
+
+  ws.onmessage = function(e) {
+    console.log('Message:', e.data);
+    try {
+      var vehicle_class = JSON.parse(e.data).vehicle_class;
+      new Audio(AUDIO[vehicle_class]).play();
+    } catch (exc) {
+      if (exc instanceof SyntaxError) {
+        console.log("Not json : " + e.data);
+      } else {
+        throw exc;
+      }
+    }
+  };
+
+  ws.onclose = function(e) {
+    console.log('Socket is closed. Reconnect will be attempted in 1 second.', e.reason);
+    clearInterval(heartBeat);
+    setTimeout(function() {
+      connect();
+    }, 1000);
+  };
+
+  ws.onerror = function(err) {
+    console.error('Socket encountered error: ', err.message, 'Closing socket');
+    ws.close();
+  };
+}
+connect();
diff --git a/paavo.html b/paavo.html
index 80c64e1243f770a73088c458f0c1a9aa3aa3e3c2..a49c8e687acb59d11c75c5d094d6d75bc1da2f1b 100644
--- a/paavo.html
+++ b/paavo.html
@@ -32,28 +32,7 @@
 
 <body>
   <script type="text/javascript">
-    TMS_NUMBER = 2050001;
-    DIRECTION1_TEXT = "Suunta: tulee vasemmalta";
-    DIRECTION2_TEXT = "Suunta: tulee oikealta";
-
-    VEHICLE_CAR = 1;
-    VEHICLE_TRUCK = 2;
-    VEHICLE_BUS = 3;
-
-    AUDIO = {};
-    // Wav files are also available.
-    AUDIO[VEHICLE_CAR] = 'audio/car_marimba.mp3';
-    AUDIO[VEHICLE_TRUCK] = 'audio/truck_glockenspiel.mp3';
-    AUDIO[VEHICLE_BUS] = 'audio/bus_mallets.mp3';
-
-    SEP = ',';
-    SERVER = 'wss://smarter-data.tt.utu.fi/ws/';
-    // SERVER = 'ws://localhost:8080/'
-
-    function send_data(ws, direction, vehicle_class) {
-      ws.send(TMS_NUMBER + SEP + direction + SEP + vehicle_class + SEP + new Date().getTime());
-      new Audio(AUDIO[vehicle_class]).play();
-    }
+    TMS_NUMBER = 2050002;
   </script>
 
   <!-- Add your site or application content here -->
@@ -91,43 +70,7 @@
       </div>
     </div>
   </div>
-  <script type="text/javascript">
-    // Varoita, jos piste ei ole valittuna.
-
-    document.getElementById('direction1').textContent = DIRECTION1_TEXT;
-    document.getElementById('direction2').textContent = DIRECTION2_TEXT;
-
-    // https://stackoverflow.com/a/23176223
-    function connect() {
-      ws = new WebSocket(SERVER);
-      // ws.onopen = function() {
-      //   // subscribe to some channels
-      //   ws.send(JSON.stringify({
-      //       //.... some message the I must send when I connect ....
-      //   }));
-      // };
-
-      ws.onmessage = function(e) {
-        console.log('Message:', e.data);
-      };
-
-      ws.onclose = function(e) {
-        console.log('Socket is closed. Reconnect will be attempted in 1 second.', e.reason);
-        setTimeout(function() {
-          connect();
-        }, 1000);
-      };
-
-      ws.onerror = function(err) {
-        console.error('Socket encountered error: ', err.message, 'Closing socket');
-        ws.close();
-      };
-    }
-    function send(direction, vehicle,) {
-      console.log();
-    }
-    connect();
-  </script>
+  <script src="js/smarter-ui.js"></script>
 
 </body>
 
diff --git a/petra.html b/petra.html
index 80c64e1243f770a73088c458f0c1a9aa3aa3e3c2..c6d9a8d6e38ecae12f8d721ce3d6139b0f79001a 100644
--- a/petra.html
+++ b/petra.html
@@ -32,28 +32,7 @@
 
 <body>
   <script type="text/javascript">
-    TMS_NUMBER = 2050001;
-    DIRECTION1_TEXT = "Suunta: tulee vasemmalta";
-    DIRECTION2_TEXT = "Suunta: tulee oikealta";
-
-    VEHICLE_CAR = 1;
-    VEHICLE_TRUCK = 2;
-    VEHICLE_BUS = 3;
-
-    AUDIO = {};
-    // Wav files are also available.
-    AUDIO[VEHICLE_CAR] = 'audio/car_marimba.mp3';
-    AUDIO[VEHICLE_TRUCK] = 'audio/truck_glockenspiel.mp3';
-    AUDIO[VEHICLE_BUS] = 'audio/bus_mallets.mp3';
-
-    SEP = ',';
-    SERVER = 'wss://smarter-data.tt.utu.fi/ws/';
-    // SERVER = 'ws://localhost:8080/'
-
-    function send_data(ws, direction, vehicle_class) {
-      ws.send(TMS_NUMBER + SEP + direction + SEP + vehicle_class + SEP + new Date().getTime());
-      new Audio(AUDIO[vehicle_class]).play();
-    }
+    TMS_NUMBER = 2050004;
   </script>
 
   <!-- Add your site or application content here -->
@@ -91,43 +70,7 @@
       </div>
     </div>
   </div>
-  <script type="text/javascript">
-    // Varoita, jos piste ei ole valittuna.
-
-    document.getElementById('direction1').textContent = DIRECTION1_TEXT;
-    document.getElementById('direction2').textContent = DIRECTION2_TEXT;
-
-    // https://stackoverflow.com/a/23176223
-    function connect() {
-      ws = new WebSocket(SERVER);
-      // ws.onopen = function() {
-      //   // subscribe to some channels
-      //   ws.send(JSON.stringify({
-      //       //.... some message the I must send when I connect ....
-      //   }));
-      // };
-
-      ws.onmessage = function(e) {
-        console.log('Message:', e.data);
-      };
-
-      ws.onclose = function(e) {
-        console.log('Socket is closed. Reconnect will be attempted in 1 second.', e.reason);
-        setTimeout(function() {
-          connect();
-        }, 1000);
-      };
-
-      ws.onerror = function(err) {
-        console.error('Socket encountered error: ', err.message, 'Closing socket');
-        ws.close();
-      };
-    }
-    function send(direction, vehicle,) {
-      console.log();
-    }
-    connect();
-  </script>
+  <script src="js/smarter-ui.js"></script>
 
 </body>
 
diff --git a/tommi.html b/tommi.html
index 80c64e1243f770a73088c458f0c1a9aa3aa3e3c2..9c8f3dc1b8561d0d853c14c6829b45da334aaa7b 100644
--- a/tommi.html
+++ b/tommi.html
@@ -33,27 +33,6 @@
 <body>
   <script type="text/javascript">
     TMS_NUMBER = 2050001;
-    DIRECTION1_TEXT = "Suunta: tulee vasemmalta";
-    DIRECTION2_TEXT = "Suunta: tulee oikealta";
-
-    VEHICLE_CAR = 1;
-    VEHICLE_TRUCK = 2;
-    VEHICLE_BUS = 3;
-
-    AUDIO = {};
-    // Wav files are also available.
-    AUDIO[VEHICLE_CAR] = 'audio/car_marimba.mp3';
-    AUDIO[VEHICLE_TRUCK] = 'audio/truck_glockenspiel.mp3';
-    AUDIO[VEHICLE_BUS] = 'audio/bus_mallets.mp3';
-
-    SEP = ',';
-    SERVER = 'wss://smarter-data.tt.utu.fi/ws/';
-    // SERVER = 'ws://localhost:8080/'
-
-    function send_data(ws, direction, vehicle_class) {
-      ws.send(TMS_NUMBER + SEP + direction + SEP + vehicle_class + SEP + new Date().getTime());
-      new Audio(AUDIO[vehicle_class]).play();
-    }
   </script>
 
   <!-- Add your site or application content here -->
@@ -91,43 +70,7 @@
       </div>
     </div>
   </div>
-  <script type="text/javascript">
-    // Varoita, jos piste ei ole valittuna.
-
-    document.getElementById('direction1').textContent = DIRECTION1_TEXT;
-    document.getElementById('direction2').textContent = DIRECTION2_TEXT;
-
-    // https://stackoverflow.com/a/23176223
-    function connect() {
-      ws = new WebSocket(SERVER);
-      // ws.onopen = function() {
-      //   // subscribe to some channels
-      //   ws.send(JSON.stringify({
-      //       //.... some message the I must send when I connect ....
-      //   }));
-      // };
-
-      ws.onmessage = function(e) {
-        console.log('Message:', e.data);
-      };
-
-      ws.onclose = function(e) {
-        console.log('Socket is closed. Reconnect will be attempted in 1 second.', e.reason);
-        setTimeout(function() {
-          connect();
-        }, 1000);
-      };
-
-      ws.onerror = function(err) {
-        console.error('Socket encountered error: ', err.message, 'Closing socket');
-        ws.close();
-      };
-    }
-    function send(direction, vehicle,) {
-      console.log();
-    }
-    connect();
-  </script>
+  <script src="js/smarter-ui.js"></script>
 
 </body>