diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..2014244 --- /dev/null +++ b/.gitignore @@ -0,0 +1,35 @@ +# Byte-compiled / optimized / DLL files +__pycache__/ +*.py[cod] +*$py.class + +# Distribution / packaging +.Python +env/ +venv/ +build/ +dist/ +.eggs/ +*.egg-info/ + +# Docker +docker-compose.override.yml + +# IDEs +.vscode/ +.idea/ + +# macOS +.DS_Store + +# Python environment +.env + +# Logs +*.log + +# Node +node_modules/ + +# Bytecode +*.pyc diff --git a/LK01 - Wanda Azizah Subekti - 2546000082.pdf b/LK01 - Wanda Azizah Subekti - 2546000082.pdf new file mode 100644 index 0000000..c17947c Binary files /dev/null and b/LK01 - Wanda Azizah Subekti - 2546000082.pdf differ diff --git a/MQTT/pub.py b/MQTT/pub.py index 747af7c..d99aaba 100644 --- a/MQTT/pub.py +++ b/MQTT/pub.py @@ -9,14 +9,15 @@ import paho.mqtt.client as mqtt import time import sys +import random # Gunakan broker lokal dalam docker compose broker = "mqtt-broker" port = 1883 # Port default untuk MQTT # Inisialisasi topik dan pesan suhu -topic = "sister/temp" -suhu = 28 # Suhu tetap 28'C +topic_temp = "sister/temp" +topic_humidity = "sister/humidity" # Callback untuk koneksi def on_connect(client, userdata, flags, rc, properties=None): @@ -38,17 +39,21 @@ def on_connect(client, userdata, flags, rc, properties=None): print(f"Gagal menghubungkan ke broker: {e}") sys.exit(1) -# Loop untuk mengirim pesan setiap detik +# Mengirimkan data suhu dan kelembapan secara periodik try: while True: - # Mempublikasikan suhu ke topik - message = f"Suhu: {suhu}°C" - client.publish(topic, message) - print(f"Published: {message}") - - # Tunggu 1 detik sebelum mengirim lagi - time.sleep(1) + suhu = random.randint(20, 35) # Suhu acak antara 20°C dan 35°C + kelembapan = random.randint(30, 50) # Kelembapan acak antara 30% dan 50% + # Publikasi ke topik suhu + client.publish(topic_temp, f"{suhu}°C") + print(f"Mengirim suhu: {suhu}°C") + + # Publikasi ke topik kelembapan + client.publish(topic_humidity, f"{kelembapan}%") + print(f"Mengirim kelembapan: {kelembapan}%") + + time.sleep(1) # Tunggu 1 detik sebelum mengirim data berikutnya except KeyboardInterrupt: print("Publisher dihentikan.") client.disconnect() diff --git a/MQTT/sub.py b/MQTT/sub.py index b5cc9e4..00fc684 100644 --- a/MQTT/sub.py +++ b/MQTT/sub.py @@ -12,22 +12,29 @@ # Gunakan broker lokal dalam docker compose broker = "mqtt-broker" # Service name port = 1883 # Port default untuk MQTT -topic = "sister/temp" + +# Tambahkan dukungan untuk banyak topik +topics = ["sister/temp", "sister/humidity"] # Callback ketika koneksi berhasil def on_connect(client, userdata, flags, rc, properties=None): if rc == 0: print(f"Berhasil terhubung ke broker MQTT {broker}") - # Berlangganan topik setelah koneksi berhasil - client.subscribe(topic) - print(f"Berlangganan topik: {topic}") + # Berlangganan ke semua topik dalam daftar + for t in topics: + client.subscribe(t) + print(f"Berlangganan topik: {t}") else: print(f"Gagal terhubung ke broker, kode error: {rc}") sys.exit(1) # Callback untuk pesan yang diterima def on_message(client, userdata, message, properties=None): - print(f"Received message: {message.payload.decode()} (Topic: {message.topic})") + msg = f"Received message: {message.payload.decode()} (Topic: {message.topic})" + print(msg) + # Simpan pesan ke file log + with open("mqtt_messages.log", "a") as log_file: + log_file.write(msg + "\n") # Inisialisasi klien MQTT dengan API versi terbaru client = mqtt.Client(mqtt.CallbackAPIVersion.VERSION2) @@ -48,4 +55,4 @@ def on_message(client, userdata, message, properties=None): client.loop_forever() except KeyboardInterrupt: print("\nSubscriber dihentikan.") - client.disconnect() \ No newline at end of file + client.disconnect() diff --git a/REST/client.py b/REST/client.py index f7789c0..a189b16 100644 --- a/REST/client.py +++ b/REST/client.py @@ -24,15 +24,20 @@ def call(endpoint, a, b): print(f"{endpoint} exception: {e}") def main(): - parser = argparse.ArgumentParser(description="Simple REST client for add/mul endpoints") - parser.add_argument('--op', choices=['add','mul','both'], default='both', help='Operation to invoke') - parser.add_argument('-a', type=int, default=10) - parser.add_argument('-b', type=int, default=5) + parser = argparse.ArgumentParser(description="Simple REST client for add/mul/sub/div endpoints") + parser.add_argument('--op', choices=['add','mul','sub','div','all'], default='all', help='Operation to invoke') + parser.add_argument('-a', type=float, help='First number', required=True) + parser.add_argument('-b', type=float, help='Second number', required=True) args = parser.parse_args() - if args.op in ('add','both'): + + if args.op in ('add', 'all'): call('add', args.a, args.b) - if args.op in ('mul','both'): + if args.op in ('mul', 'all'): call('mul', args.a, args.b) + if args.op in ('sub', 'all'): + call('sub', args.a, args.b) + if args.op in ('div', 'all'): + call('div', args.a, args.b) if __name__ == '__main__': sys.exit(main()) diff --git a/REST/server.py b/REST/server.py index 58bf530..be9a10e 100644 --- a/REST/server.py +++ b/REST/server.py @@ -11,9 +11,9 @@ # Inisialisasi aplikasi Flask app = Flask(__name__) -# Endpoint untuk pengurangan +# Endpoint untuk penjumlahan @app.route('/add', methods=['GET']) -def sub_numbers(): +def add_numbers(): try: # Mengambil parameter a dan b dari query string a = int(request.args.get('a')) @@ -25,7 +25,23 @@ def sub_numbers(): except (TypeError, ValueError): # Menangani error jika input tidak valid return jsonify({'error': 'Invalid input'}), 400 - + +# Endpoint untuk pengurangan +@app.route('/sub', methods=['GET']) +def sub_numbers(): + try: + # Mengambil parameter a dan b dari query string + a = int(request.args.get('a')) + b = int(request.args.get('b')) + result = a - b + + # Mengembalikan hasil dalam format JSON + return jsonify({'result': result}) + except (TypeError, ValueError): + # Menangani error jika input tidak valid + return jsonify({'error': 'Invalid input'}), 400 + +# Endpoint untuk perkalian @app.route('/mul', methods=['GET']) def mul_numbers(): try: @@ -40,6 +56,23 @@ def mul_numbers(): # Menangani error jika input tidak valid return jsonify({'error': 'Invalid input'}), 400 +# Endpoint untuk pembagian +@app.route('/div', methods=['GET']) +def div_numbers(): + try: + # Mengambil parameter a dan b dari query string + a = int(request.args.get('a')) + b = int(request.args.get('b')) + if b == 0: + return jsonify({'error': 'Division by zero is not allowed'}), 400 + result = a / b + + # Mengembalikan hasil dalam format JSON + return jsonify({'result': result}) + except (TypeError, ValueError): + # Menangani error jika input tidak valid + return jsonify({'error': 'Invalid input'}), 400 + # Jalankan server di port 5000 if __name__ == '__main__': # Bind to 0.0.0.0 so container port mapping works externally diff --git a/SOAP/client.py b/SOAP/client.py index b83f788..20c30c2 100644 --- a/SOAP/client.py +++ b/SOAP/client.py @@ -19,3 +19,9 @@ # Menampilkan hasil penjumlahan print(f'Hasil penjumlahan dari server SOAP: {result}') +# Memanggil metode pengurangan dari layanan SOAP server +result_sub = client.service.subtract(10, 5) + +# Menampilkan hasil pengurangan +print(f'Hasil pengurangan dari server SOAP: {result_sub}') + diff --git a/SOAP/server.py b/SOAP/server.py index 0c81207..211974b 100644 --- a/SOAP/server.py +++ b/SOAP/server.py @@ -16,6 +16,10 @@ class CalculatorService(ServiceBase): def add(ctx, a, b): return a + b + @rpc(Integer, Integer, _returns=Integer) + def subtract(ctx, a, b): + return a - b + # Membuat aplikasi SOAP dengan protokol Soap11 app = Application([CalculatorService], tns='spyne.examples.calculator', diff --git a/upcall/clientcall.py b/upcall/clientcall.py index 7470404..d94ccb5 100644 --- a/upcall/clientcall.py +++ b/upcall/clientcall.py @@ -7,23 +7,52 @@ """ import socket +import logging + +# Konfigurasi logging +logging.basicConfig(filename='client_log.txt', level=logging.INFO, + format='%(asctime)s - %(message)s') def client_program(): - client_socket = socket.socket() - # Use docker compose service DNS instead of a hardcoded external IP - client_socket.connect(('upcall-server', 4141)) - - message = input("Enter message: ") - - while message.lower().strip() != 'bye': - client_socket.send(message.encode()) - data = client_socket.recv(1024).decode() - - print('Received upcall from server:', data) # Simulating upcall response + try: + client_socket = socket.socket() + client_socket.settimeout(10) # Timeout 10 detik untuk koneksi + client_socket.connect(('upcall-server', 4141)) + logging.info("Connected to server at upcall-server:4141") + + while True: + try: + # Meminta pengguna untuk memasukkan beberapa pesan sekaligus, dipisahkan dengan koma + messages = input("Enter messages (separated by commas): ").split(',') + + for message in messages: + message = message.strip() + if message.lower() == 'bye': + print("Exiting...") + client_socket.close() + logging.info("Connection closed by user.") + return + + client_socket.send(message.encode()) + logging.info(f"Sent: {message}") + + data = client_socket.recv(1024).decode() + logging.info(f"Received: {data}") + + print('Received upcall from server:', data) + except socket.timeout: + print("Timeout: No response from server.") + logging.warning("Timeout: No response from server.") + break - message = input("Enter another message: ") - - client_socket.close() + client_socket.close() + logging.info("Connection closed.") + except socket.error as e: + print(f"Socket error: {e}") + logging.error(f"Socket error: {e}") + except Exception as e: + print(f"An error occurred: {e}") + logging.error(f"An error occurred: {e}") if __name__ == '__main__': client_program()