Here's a complete list of all the files I modified and the specific changes made to implement RFID communication between the charge point and central system:

1. File: requirements.txt

Changes: Added missing dependencies

websockets>=15.0
jsonschema>=4.23.0
pyscard>=2.0.0
PyQt5>=5.15.0

2. File: ui_hori/charge_point.py

Changes: Added RFID data sending functionality

Added imports and path setup:

import sys
import os

# Add parent directory to path to import ocpp module
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))

Added RFID sending method:

async def send_rfid_data(self, rfid_uid):
    """Send RFID data to the central system using DataTransfer message"""
    try:
        request = call.DataTransfer(
            vendor_id="ChargingStation",
            data=rfid_uid
        )
        response = await self.call(request)
        print(f"RFID data sent to server: {rfid_uid}")
        print(f"Server response: {response.status}")
        print(f"Server data: {response.data}")
        return response
    except Exception as e:
        print(f"Error sending RFID data: {e}")
        return None

3. File: central_system.py

Changes: Added DataTransfer handler to receive and process RFID data

Added import:

from ocpp.v21.enums import Action, DataTransferStatusEnumType

Added RFID data handler:

@on(Action.data_transfer)
def on_data_transfer(self, vendor_id, data, **kwargs):
    print(f"=== RFID DATA RECEIVED FROM CLIENT ===")
    print(f"Charge Point ID: {self.id}")
    print(f"Vendor ID: {vendor_id}")
    print(f"RFID UID: {data}")
    print(f"Timestamp: {datetime.now(timezone.utc).isoformat()}")
    print(f"=====================================")

    return call_result.DataTransfer(
        status=DataTransferStatusEnumType.accepted,
        data="RFID data received successfully"
    )

4. File: ui_hori/charging_ui.py

Changes: Major modifications for thread-safe RFID communication and UI updates

Added imports:

try:
    import websockets
except ModuleNotFoundError:
    print("This example relies on the 'websockets' package.")
    print("Please install it by running: ")
    print()
    print(" $ pip install websockets")
    sys.exit(1)

Added worker thread reference to MainWindow:

# Store reference to worker thread for RFID communication
self.worker_thread = None

Modified WorkerThread class:

class WorkerThread(QThread):
    rfid_data_signal = pyqtSignal(str)  # Signal to send RFID data

    def __init__(self):
        super().__init__()
        self.charge_point_instance = None
        self.event_loop = None
        self.rfid_queue = asyncio.Queue()

    def run(self):
        # Run asyncio loop inside this thread
        asyncio.run(self.main_with_rfid())

    async def main_with_rfid(self):
        """Modified main function that keeps reference to charge point instance"""
        self.event_loop = asyncio.get_running_loop()

        async with websockets.connect(
            "ws://localhost:9000/CP_1", subprotocols=["ocpp2.1"]
        ) as ws:
            print("WebSocket connection established.")
            self.charge_point_instance = charge_point.ChargePoint("CP_1", ws)

            # Start both the charge point and RFID processing
            await asyncio.gather(
                self.charge_point_instance.start(), 
                self.charge_point_instance.send_boot_notification(),
                self.process_rfid_queue()
            )

    async def process_rfid_queue(self):
        """Process RFID data from the queue"""
        while True:
            try:
                rfid_uid = await self.rfid_queue.get()
                if self.charge_point_instance:
                    response = await self.charge_point_instance.send_rfid_data(rfid_uid)
                    if response and response.data:
                        # Send server response data to UI thread
                        self.rfid_data_signal.emit(response.data)
                    self.rfid_queue.task_done()
            except Exception as e:
                print(f"Error processing RFID: {e}")

    def send_rfid_to_server(self, rfid_uid):
        """Method to send RFID data to server - thread safe"""
        if self.event_loop and not self.event_loop.is_closed():
            # Schedule the RFID to be added to the queue
            asyncio.run_coroutine_threadsafe(
                self.rfid_queue.put(rfid_uid), 
                self.event_loop
            )

Modified rfid_read method:

def rfid_read(self):

    card_ids = [
            "7A4C91E2F5B3",
            "D19F73C5A28B",
            "3F7A1E9C84D2",
            "9B62C4D7A1E8",
            "5E1C8A3F9D47",
            "B2D47F8C31E9",
            "4A9F2C7E5D13",
            "E1B47D9C3A52",
            "8C2F5B7A1E49",
            "F73D29E1C84B"
        ]
        # random card_id
        self.UID = random.choice(card_ids)
        # self.UID = '92345678901234567890'
        self.rfid_timer.stop()
        print(f"RFID read: {self.UID}")

        # Send RFID data to server if worker thread is available
        if self.worker_thread and hasattr(self.worker_thread, 'send_rfid_to_server'):
            self.worker_thread.send_rfid_to_server(self.UID)
            print(f"RFID data sent to server: {self.UID}")

        self.goto_step6()

Added UI update method:

def update_rfid_server_response(self, server_response_data):
    """Update UI with server response data from RFID communication"""
    print(f"Received server response: {server_response_data}")
    # Update label_5 in step6 with the server response
    if hasattr(self, 'ui_step6') and hasattr(self.ui_step6, 'label_5'):
        self.ui_step6.label_5.setText(server_response_data)
        print(f"Updated UI with server response: {server_response_data}")

Modified main function to connect signal:

# Start thread and store reference in MainWindow
thread_a = WorkerThread()
win.worker_thread = thread_a  # Store reference for RFID communication
# Connect signal to update UI with server response
thread_a.rfid_data_signal.connect(win.update_rfid_server_response)
thread_a.start()

5. Created Files:

SETUP_INSTRUCTIONS.md

Complete setup and installation guide

RFID_IMPLEMENTATION.md

Detailed documentation of the RFID implementation

THREAD_SAFETY_FIX.md

Documentation of the thread safety fix for the RuntimeError

SERVER_RESPONSE_UI_UPDATE.md

Documentation of the server response UI update implementation

test_rfid_communication.py

Test script for RFID communication

simple_rfid_test.py

Simple test script for RFID functionality

Summary of Key Changes:

  1. Fixed missing dependencies - Added jsonschema and pyscard to requirements.txt
  2. Added RFID sending capability - Implemented DataTransfer message sending in charge_point.py
  3. Added RFID receiving capability - Implemented DataTransfer handler in central_system.py
  4. Fixed thread safety issues - Implemented proper thread communication using asyncio queues and PyQt signals
  5. Added UI updates - Server response now displays in the UI at the specified location
  6. Maintained existing functionality - All original UI flow and charging simulation remains intact

The implementation enables complete RFID communication flow: RFID read → Send to server → Server processes → Response back to UI → Display in interface.