diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000000000000000000000000000000000000..bee8a64b79a99590d5303307144172cfe824fbf7
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1 @@
+__pycache__
diff --git a/README.md b/README.md
new file mode 100644
index 0000000000000000000000000000000000000000..f40ce2d7a188b27fe2cd575b38eadabc54cef2fc
--- /dev/null
+++ b/README.md
@@ -0,0 +1,92 @@
+# Internet Of Things - Worksheet 3
+
+![image](src/uwe.png)
+
+**Module Name:** Internet Of Things
+
+**Module Code:** UFCFVK‑15‑2
+
+**Module Leader Name:** Benedict R. Gaster
+
+- [Internet Of Things - Worksheet 3](#internet-of-things---worksheet-3)
+  - [Description](#description)
+    - [Task 1: UDP decoder.](#task-1-udp-decoder)
+    - [Task 2: Checksum.](#task-2-checksum)
+    - [Task 3: Server UDP time.](#task-3-server-udp-time)
+  - [Getting Started](#getting-started)
+    - [Dependencies](#dependencies)
+    - [Installing](#installing)
+  - [Authors](#authors)
+  - [Version History](#version-history)
+  - [License](#license)
+
+## Description
+
+Morse code :: Worksheet 3
+This is a rep for only worksheet 3. Worksheet 2 part 2 can be found here [IOT - Worksheet 2 part 2 ](https://gitlab.uwe.ac.uk/jo2-holdsworth/iot-worksheet-2-part-2)
+
+
+### Task 1: UDP decoder.
+* *The CSCT cloud server has a port open on 5612 which transmits and receives UDP packets. We are to create a basic client to receive the hello message from the UDP server and decode it.
+* ***server.py*** This is the foundation of the worksheet. It connects a and receives the packet from the server. It uses **asyncio** which allows parallelism. As the program it waiting for the response from the server It will continue with other parts of the program. ![image](src/screenshot1.PNG)
+* ***udpdecoder.py*** This file contains two functions a decoder and a print function. I choose to do this so we can access the decoder or print in the future. They will be useful separate.
+  * **decodePacket(response)** Takes the raw udp pack and outputs a dictionary. Using the function `int.from_bytes(packet,'little')` we can decode bytes straight into ints. Following this table we can decode the UDP packet. Source port is bytes 0,1. Dest Port is bytes 2,3. Data Length is bytes 4,5. Checksum is bytes 6,7. The rest is the payload. ![image](src/screenshot2.PNG) the code: ![image](src/screenshot3.PNG)
+  * **printUDPPacket(dict)** Takes the decoded packet and prints the packet in a user friendly format. ![image](src/screenshot4.PNG)![image](src/screenshot5.PNG)
+* ***unittest.py*** unittest is an inbuilt Python library. Its a test runner and is specially design for running tests and debugging. This one contains a few useful tools that we are going to use. It works similarly to the assert function. Ive written a few tests to test decoding the packet. All the tests were successful.![image](src/screenshot13.PNG)
+___
+### Task 2: Checksum.
+* To check that the packet is valid from the server we can use the checksum included within the header. We will compute our own checksum to compare the two values and see if they are a match. If they match we can be confident that the packet was transmitted successfully from the server.
+* ***compute_checksum(sourcePort, destPort, payload)*** Takes in arguments in ints and calcuates the expected UDP checksum. This uses python bits wise operations and `.to_bytes(2, 'little')` to convert ints to bytes. This took many tries to get working, took a deeper understanding of udp to get working correctly. ![image](src/screenshot6.PNG)
+* ***check_checksum(checksum0,checksum1)*** is a very simple function that returns true of false if a check sum is the same. ![image](src/screenshot7.PNG)
+* ***print_checksum(dict)*** similar to `printUDPPacket()` it prints the packet and outputs if the check sum is the same. E.I if a valid packet or not. ![image](src/screenshot8.PNG) ![image](src/screenshot9.PNG)
+* ***unittest.py*** unittest is an inbuilt Python library. Its a test runner and is specially design for running tests and debugging. This one contains a few useful tools that we are going to use. It works similarly to the assert function. Ive written a few tests to test the checksum. All the tests were successful.![image](src/screenshot14.PNG)
+___
+### Task 3: Server UDP time.
+* This takes builds upon **task 1** and **task 2** we need to send and receive packets from the sever with the correct checksum. This means encoding and decoding UDP.
+* ***mainSendandReceive()*** This function is a controller for smaller functions. It simply connects to server and tells the program to send and get packets from the server.![image](src/screenshot10.PNG)
+* ***recv_and_decode_packet(websocket)***  We are taking a websocket connecting to it and printing the packet all it one. This take doesnt require us todo much else with the packet so it can just be called in a function. ![image](src/screenshot11.PNG)
+* ***send_packet(websocket, sourcePort, deskPort, payLoad)*** To send packets to the server they need to be in UDP format in base64. This function will create a header for the payload including the correct checksum so the server can confirm the packet has arrived valid. ![image](src/screenshot12.PNG)
+* ***unittest.py*** unittest is an inbuilt Python library. Its a test runner and is specially design for running tests and debugging. This one contains a few useful tools that we are going to use. It works similarly to the assert function. Task 3 doesn't have any output other than to the terminal. I could alter the output but this is out of my scope for the project. Here I am just checking if the program runs correctly. All the tests were successful.![image](src/screenshot15.PNG)![image](src/screenshot16.PNG)
+
+
+## Getting Started
+
+* Running the task files
+  * Task 1: `python3 udpdecoder.py`
+  * Task 2: `python3 checksum.py`
+  * Task 3: `python3 serverudptime.py`
+
+### Dependencies
+
+* unittest
+* asyncio
+* websockets
+* json
+* time
+* base64
+
+### Installing
+
+* Nothing to install
+
+## Authors
+
+Contributors names and contact info
+
+ex. Jack Holdsworth @ [my website](https://holdsworth.dev)
+
+## Version History
+* 0.4
+  * README
+  * Unittesting
+* 0.3
+  * task 2 done
+  * started task 3
+* 0.2
+  * most of task 2 done
+  * README made
+* 0.1
+  * init.
+
+## License
+This project is licensed under the GPL License - see the LICENSE.md file for details
diff --git a/checksum.py b/checksum.py
new file mode 100644
index 0000000000000000000000000000000000000000..d8b7d72c45101e8b8e8e245a65baa8737723c4a8
--- /dev/null
+++ b/checksum.py
@@ -0,0 +1,61 @@
+from udpdecoder import *
+
+def compute_checksum(sourcePort, destPort, payload):
+    # a function to calculate the checksum from packet data (ints)
+
+    # convert ints back to bytes
+    sourcePort = sourcePort.to_bytes(2, 'little')
+    destPort = destPort.to_bytes(2, 'little')
+    length = (len(payload)+8).to_bytes(2, 'little')
+
+    # append bytes 
+    calc = sourcePort + destPort + length + bytes(2) + payload
+    sum = 0
+
+    # make odd num of bytes even
+    if len(payload) % 2:
+        calc += bytes(1)
+
+    #take two bytes and bit shit, add them append to sum
+    for i in range(0, len(calc), 2):
+        tmp = (calc[i] << 8) + calc[i+1]
+        sum += tmp
+        
+    # mask bits
+    sum = (sum >> 16) + (sum & 0xFFFF)
+    # invert
+    sum = ~sum & 0xFFFF
+    # output int
+    sum = int(format(sum,'b'),2)
+    return sum
+
+def check_checksum(checksum0,checksum1):
+    # a simple function to check if two values are the same
+    if checksum0 == checksum1:
+        return True
+    else:
+        return False
+    
+def print_checksum(dict):
+    # print the dictionary + checksum
+    checksum= compute_checksum(dict['Source Port'],dict['Dest Port'], dict['Server Sent'][8:(len(dict['Server Sent'])+8)])
+    printUDPPacket(dict)
+    print(f"Server checksum: {dict['Checksum']}")
+    print(f"Client Calculated checksum: {checksum}")
+    # compare checksums and output result
+    if check_checksum(dict['Checksum'],checksum) == True:
+        print("Match!")
+    else:
+        print("ERROR!")
+    print("=====================================")
+
+if __name__ == '__main__':
+    x = 0
+    print("=== Task 2 by Jack H ===")
+    while x <= 10:
+        packet = asyncio.run(getPacket())
+        dict = decodePacket(packet)
+        print_checksum(dict)
+        time.sleep(1)
+        x += 1
+    print("========================")
\ No newline at end of file
diff --git a/server.py b/server.py
new file mode 100644
index 0000000000000000000000000000000000000000..c08bc38a8a83e9af42307d1eadf5c7bc8bcd508f
--- /dev/null
+++ b/server.py
@@ -0,0 +1,24 @@
+import asyncio
+import websockets
+import json
+import time
+
+
+async def getPacket():
+    # connect to server and get packet
+    uri = "ws://localhost:5612" # server port
+    async with websockets.connect(uri) as websocket: #connect
+        # get packet
+        return await websocket.recv()
+
+
+async def recv_message(websocket):
+    message = json.loads(await websocket.recv()) # strip json
+    return message['payload'] # return packet
+
+if __name__ == "__main__":
+    print("Server packet getter")
+
+    while 1:
+        print(asyncio.run(getPacket()))
+        time.sleep(1)
\ No newline at end of file
diff --git a/serverudptime.py b/serverudptime.py
new file mode 100644
index 0000000000000000000000000000000000000000..efb5d061f363be6733b909e5c48ec847647b8729
--- /dev/null
+++ b/serverudptime.py
@@ -0,0 +1,44 @@
+from checksum import *
+
+async def mainSendandReceive():
+    # connect to server, send and get packet with time.
+    uri = "ws://localhost:5612" # server port
+    async with websockets.connect(uri) as websocket: #connect
+        await recv_and_decode_packet(websocket) # get packet decode and print
+        x = 0
+        while x <= 10:
+            await send_packet(websocket, 0, 542, b'1111') # get time packet
+            await recv_and_decode_packet(websocket) # decode and print time packet
+            time.sleep(1)
+            x += 1
+
+async def recv_and_decode_packet(websocket):
+    # get packet and print user readable
+    message = await websocket.recv() # get packet
+    dict = decodePacket(message) # decode
+    print_checksum(dict) # print
+
+
+async def send_packet(websocket, sourcePort, destPort, payload):
+    # a function to send a packet via UDP
+
+    # compute checksum
+    checkSum = compute_checksum(sourcePort, destPort, payload)
+
+    # convert to bytes
+    destPort = destPort.to_bytes(2, 'little')
+    sourcePort = sourcePort.to_bytes(2, 'little')
+    length = 8 + len(payload)
+    length = length.to_bytes(2, 'little')
+    checkSum = checkSum.to_bytes(2, 'little')
+    # build packet
+    packet = sourcePort + destPort + length + checkSum + payload
+    # covert packet
+    packet = base64.b64encode(packet)
+    await websocket.send(packet) # send a move on while sending
+
+if __name__ == '__main__':
+    x = 0
+    print("=== Task 3 by Jack H ===")
+    asyncio.run(mainSendandReceive())
+    print("========================")
\ No newline at end of file
diff --git a/src/screenshot1.PNG b/src/screenshot1.PNG
new file mode 100644
index 0000000000000000000000000000000000000000..7969e643ede2d76a3eea7105129908745e68641f
Binary files /dev/null and b/src/screenshot1.PNG differ
diff --git a/src/screenshot10.PNG b/src/screenshot10.PNG
new file mode 100644
index 0000000000000000000000000000000000000000..be75e052931da56e4a22131806305ec11414936a
Binary files /dev/null and b/src/screenshot10.PNG differ
diff --git a/src/screenshot11.PNG b/src/screenshot11.PNG
new file mode 100644
index 0000000000000000000000000000000000000000..e67a982b45e11a94fcd09faa9e5f676c899a94ea
Binary files /dev/null and b/src/screenshot11.PNG differ
diff --git a/src/screenshot12.PNG b/src/screenshot12.PNG
new file mode 100644
index 0000000000000000000000000000000000000000..86cdcd547c676c496fd7a596d7991fb76ec9cbbf
Binary files /dev/null and b/src/screenshot12.PNG differ
diff --git a/src/screenshot13.PNG b/src/screenshot13.PNG
new file mode 100644
index 0000000000000000000000000000000000000000..6b13ad6aca1ab86abafc39fde1ba0f4e2a19da9b
Binary files /dev/null and b/src/screenshot13.PNG differ
diff --git a/src/screenshot14.PNG b/src/screenshot14.PNG
new file mode 100644
index 0000000000000000000000000000000000000000..f39964335b18505470444f486a98d859c3e96b1f
Binary files /dev/null and b/src/screenshot14.PNG differ
diff --git a/src/screenshot15.PNG b/src/screenshot15.PNG
new file mode 100644
index 0000000000000000000000000000000000000000..0f7b292eefafb1a087433e42dc18940fb4501820
Binary files /dev/null and b/src/screenshot15.PNG differ
diff --git a/src/screenshot16.PNG b/src/screenshot16.PNG
new file mode 100644
index 0000000000000000000000000000000000000000..31d10fe6293dc2e0f2c22aba344d71065bc31610
Binary files /dev/null and b/src/screenshot16.PNG differ
diff --git a/src/screenshot2.PNG b/src/screenshot2.PNG
new file mode 100644
index 0000000000000000000000000000000000000000..002d8991432d4dc8cc0c0278acbbd9232430c78b
Binary files /dev/null and b/src/screenshot2.PNG differ
diff --git a/src/screenshot3.PNG b/src/screenshot3.PNG
new file mode 100644
index 0000000000000000000000000000000000000000..c48dd538568f2827f7a5e56fd9d4b252027560af
Binary files /dev/null and b/src/screenshot3.PNG differ
diff --git a/src/screenshot4.PNG b/src/screenshot4.PNG
new file mode 100644
index 0000000000000000000000000000000000000000..944853f2a00303cf01b5ecff49ae0cc49fd9b993
Binary files /dev/null and b/src/screenshot4.PNG differ
diff --git a/src/screenshot5.PNG b/src/screenshot5.PNG
new file mode 100644
index 0000000000000000000000000000000000000000..b099ab65d88c8f4ca32816e2c93b4c8aafc00c5d
Binary files /dev/null and b/src/screenshot5.PNG differ
diff --git a/src/screenshot6.PNG b/src/screenshot6.PNG
new file mode 100644
index 0000000000000000000000000000000000000000..64653f34df9008ae07ce331fed1930652ac5b987
Binary files /dev/null and b/src/screenshot6.PNG differ
diff --git a/src/screenshot7.PNG b/src/screenshot7.PNG
new file mode 100644
index 0000000000000000000000000000000000000000..e9c46fa75b1c827ff0b9357ca2203abf9ab23132
Binary files /dev/null and b/src/screenshot7.PNG differ
diff --git a/src/screenshot8.PNG b/src/screenshot8.PNG
new file mode 100644
index 0000000000000000000000000000000000000000..440fc70cc32c3c484cac19dc641bb55f19328445
Binary files /dev/null and b/src/screenshot8.PNG differ
diff --git a/src/screenshot9.PNG b/src/screenshot9.PNG
new file mode 100644
index 0000000000000000000000000000000000000000..8211c0e85eb6787cad9aa5f4aeaca61cb1ee29d3
Binary files /dev/null and b/src/screenshot9.PNG differ
diff --git a/src/uwe.png b/src/uwe.png
new file mode 100644
index 0000000000000000000000000000000000000000..e3c5878ecfa07bf72ea7239a678182a37bcb669e
Binary files /dev/null and b/src/uwe.png differ
diff --git a/udp.py b/udp.py
index dc4274e253946e020ac9086b74dfc00d2cb76335..9ff1f17612a07274f1ab90325e95033c3bf7a22e 100644
--- a/udp.py
+++ b/udp.py
@@ -13,7 +13,7 @@ async def main():
         udp = decodePacket(message)
         printUDPPacket(udp)
         compute_checksum(udp['Source Port'],udp['Dest Port'],udp['Server Sent'][8:(len(udp['Server Sent'])+8)])
-        #print(f"calculated checksum: {int(compute_checksum(2,1,b'AB'),2)}")
+        # print(f"calculated checksum: {int(compute_checksum(2,1,b'AB'),2)}")
 
         print(bin(udp['Checksum']))
 
@@ -43,11 +43,11 @@ async def send_packet(websocket, sourcePort, destPort, payload):
     length = 8 + len(payload)
     length = length.to_bytes(2, 'little')
     checkSum = checkSum.to_bytes(2, 'little')
-    print(f"length : {length}")
+    print(f"length : {int.from_bytes(length, 'little')}")
     
     packet = sourcePort + destPort + length + checkSum + payload
     
-    print(destPort + sourcePort)
+    print(f"packet: {packet}")
     packet = base64.b64encode(packet)
     await websocket.send(packet)
 
@@ -67,8 +67,10 @@ def decodePacket(response):
 
 
 def printUDPPacket(dict):
+    print("=== Decoded UDP Packet ===")
     for key, value in dict.items():
         print(f"{key}: {value}")
+    print("=== Decoded UDP Packet ===")
         
 
 def compute_checksum(sourcePort, destPort, payload):
@@ -85,14 +87,21 @@ def compute_checksum(sourcePort, destPort, payload):
     print(f"starting calc: {calc}")
     calcPayload = ""
     print(type(calcPayload))
-    
+    print(destPort)
     sum = 0
     if len(payload) % 2:
         calc += bytes(1)
 
     for i in range(0, len(calc), 2):
         tmp = (calc[i] << 8) + calc[i+1]
+        print(calc[i])
+        print(format(calc[i],'b'))
+        print(format(calc[i+1],'b'))
+        print(format(tmp,'b'))
+        print(calc[i+1])
         sum += tmp
+        
+        print(tmp)
 
     sum = (sum >> 16) + (sum & 0xFFFF)
     sum = ~sum & 0xFFFF
@@ -109,5 +118,5 @@ if __name__ == "__main__":
     print("Echo client")
 
 # while 1:
-    asyncio.run(mainSend())
+    asyncio.run(main())
     time.sleep(10)
diff --git a/udpdecoder.py b/udpdecoder.py
new file mode 100644
index 0000000000000000000000000000000000000000..360f4c5b0a2a7063aba84980c0dcdf1546ad65d0
--- /dev/null
+++ b/udpdecoder.py
@@ -0,0 +1,31 @@
+from server import *
+import base64
+
+def decodePacket(response):
+    # takes in a packet and outputs a decoded dictionary
+    decoded = {} # the dict
+    decoded['Base64'] = response # the base64 response from server (raw)
+    packet = base64.b64decode(response) # decoded into hex
+    decoded['Server Sent'] = packet # decoded hex
+    decoded['Source Port'] = int.from_bytes(packet[:2], 'little') # server port
+    decoded['Dest Port'] = int.from_bytes(packet[2:4], 'little') # going to
+    decoded['Data Length'] = int.from_bytes(packet[4:6], 'little') # length of the payload + 8
+    decoded['Checksum'] = int.from_bytes(packet[6:8], 'little') # server calculated checksum
+    decoded['Payload'] = packet[8:(len(packet)+8)].decode("utf-8") # the message
+    return decoded # return dict
+
+def printUDPPacket(dict):
+    # print the dictionary
+    print("=== Decoded UDP Packet ===")
+    for key, value in dict.items():
+        print(f"{key}: {value}")
+    print("==========================")
+
+if __name__ == '__main__':
+    x = 0
+    print("=== Task 1 by Jack H ===")
+    while x <= 10:
+        printUDPPacket(decodePacket(asyncio.run(getPacket())))
+        time.sleep(1)
+        x+1
+    print("========================")
\ No newline at end of file
diff --git a/unititest.py b/unititest.py
new file mode 100644
index 0000000000000000000000000000000000000000..fba46d166178233cd27563e6c5d1476c48226381
--- /dev/null
+++ b/unititest.py
@@ -0,0 +1,37 @@
+import unittest
+import datetime 
+from serverudptime import *
+
+class TestMorse(unittest.TestCase):
+# task 1
+    def test_decode_packet_1(self):
+        self.assertEqual(decodePacket(asyncio.run(getPacket())), {'Base64': b'CgAqACEAyztXZWxjb21lIHRvIElvVCBVRFAgU2VydmVy', 'Server Sent': b'\n\x00*\x00!\x00\xcb;Welcome to IoT UDP Server', 'Source Port': 10, 'Dest Port': 42, 'Data Length': 33, 'Checksum': 15307, 'Payload': 'Welcome to IoT UDP Server'})
+    def test_decode_packet_2(self):
+        self.assertEqual(decodePacket(b'AAAeAhcAC8JJT1QgSVMgVEhFIEJFU1Q='), {'Base64': b'AAAeAhcAC8JJT1QgSVMgVEhFIEJFU1Q=', 'Server Sent': b'\x00\x00\x1e\x02\x17\x00\x0b\xc2IOT IS THE BEST', 'Source Port': 0, 'Dest Port': 542, 'Data Length': 23, 'Checksum': 49675, 'Payload': 'IOT IS THE BEST'})
+    def test_decode_packet_3(self):
+        self.assertEqual(decodePacket(b'FAAeAiUAU/1Db21tdW5pY2F0aW9uIHdpdGggdGhlIHNlcnZlcg=='), {'Base64': b'FAAeAiUAU/1Db21tdW5pY2F0aW9uIHdpdGggdGhlIHNlcnZlcg==', 'Server Sent': b'\x14\x00\x1e\x02%\x00S\xfdCommunication with the server', 'Source Port': 20, 'Dest Port': 542, 'Data Length': 37, 'Checksum': 64851, 'Payload': 'Communication with the server'})
+    def test_decode_packet_4(self):
+        self.assertEqual(decodePacket(b'FAAeAiUAU/1Db21tdW5pY2F0aW9uIHdpdGggdGhlIHNlcnZlcg=='), {'Base64': b'FAAeAiUAU/1Db21tdW5pY2F0aW9uIHdpdGggdGhlIHNlcnZlcg==', 'Server Sent': b'\x14\x00\x1e\x02%\x00S\xfdCommunication with the server', 'Source Port': 20, 'Dest Port': 542, 'Data Length': 34, 'Checksum': 64851, 'Payload': 'Communication with the server'})
+    def test_decode_packet_5(self):
+        self.assertEqual(decodePacket(b'FAArABQAY49CZXN0IHN0dWRlbnQ='), {'Base64': b'FAArABQAY49CZXN0IHN0dWRlbnQ=', 'Server Sent': b'\x14\x00+\x00\x14\x00c\x8fBest student', 'Source Port': 20, 'Dest Port': 43, 'Data Length': 20, 'Checksum': 36708, 'Payload': 'Best student'})
+
+# task 2
+    def test_checksum_1(self):
+        self.assertEqual(compute_checksum(0,400,b'AACQAQwAJJxUZXN0'), 44976)
+    def test_checksum_2(self):
+        self.assertEqual(compute_checksum(10,200,b'CgDIABcAbG1Jb3QgaXMgdGhlIEJlc3Q='), 53000)
+    def test_checksum_3(self):
+        self.assertEqual(compute_checksum(10,200,b'CgDIABcAbG1Jb3QgaXMgdGhlIEJlc3Q='), 53001)
+    def test_check_checksum_4(self):
+        self.assertEqual(check_checksum(compute_checksum(10,200,b'CgDIABcAbG1Jb3QgaXMgdGhlIEJlc3Q='),53000), True)
+    def test_check_checksum_5(self):
+        self.assertEqual(check_checksum(compute_checksum(10,200,b'CgDIABcAbG1Jb3QgaXMgdGhlIEJlc3Q='),53001), False)
+    def test_check_checksum_6(self):
+        self.assertEqual(check_checksum(compute_checksum(10,200,b'CgDIABcAbG1Jb3QgaXMgdGhlIEJlc3Q='),53000), False)
+
+# task 3
+    def test_all(self):
+        self.assertEqual(asyncio.run(mainSendandReceive()), None)
+
+if __name__ == '__main__':
+    unittest.main()