2025年10月28日 星期二

RFID Tree Algorithm 樹演算法 for RFID Tag Anti-Collision

 RFID Tree Algorithm 樹演算法for RFID Tag Anti-Collision



import tkinter as tk

from tkinter import simpledialog


class RFIDTreeApp:

    def __init__(self, master):

        self.master = master

        master.title("RFID Tree Algorithm Visualizer")


        # --- Configuration ---

        self.canvas_width = 800

        self.canvas_height = 600

        self.node_radius = 8

        self.highlight_color = "red"

        self.normal_color = "blue"

        self.tag_size = 4  # The depth of the tree (4-bit tags)


        # Structure to hold node coordinates and IDs

        self.nodes = {}

        self.lines = {}

        self.labels = {}

        self.tag_boxes = {}

        self.tag_text_items = {}


        # --- UI Elements ---

        self.canvas = tk.Canvas(master, width=self.canvas_width, height=self.canvas_height, bg="lightyellow")

        self.canvas.pack()


        self.input_frame = tk.Frame(master)

        self.input_frame.pack(pady=10)


        self.input_label = tk.Label(self.input_frame, text="Enter 4-bit Tag (e.g., 0101):")

        self.input_label.pack(side=tk.LEFT, padx=5)


        self.tag_entry = tk.Entry(self.input_frame, width=10)

        self.tag_entry.pack(side=tk.LEFT, padx=5)

        self.tag_entry.insert(0, "0101") # Default value


        self.draw_button = tk.Button(self.input_frame, text="Show Path", command=self.highlight_path)

        self.draw_button.pack(side=tk.LEFT, padx=5)


        self.clear_button = tk.Button(self.input_frame, text="Clear Path", command=self.clear_highlight)

        self.clear_button.pack(side=tk.LEFT, padx=5)


        # --- Initial Drawing ---

        self.draw_tree()


    def draw_tree(self):

        """Draws the complete 4-bit binary tree structure."""

        self.canvas.delete("all")

        self.nodes.clear()

        self.lines.clear()

        self.labels.clear()

        self.tag_boxes.clear()

        self.tag_text_items.clear()


        # Coordinates for the root node

        root_x = self.canvas_width / 2

        root_y = 50


        # Recursively draw the tree

        self._recursive_draw(root_x, root_y, 0, self.canvas_width / 4, "")

        

        # Draw the title

        self.canvas.create_text(

            self.canvas_width / 2, 20,

            text="RFID Tree Algorithm",

            font=("Times New Roman", 20, "bold"),

            fill="darkblue"

        )

        self.canvas.create_line(100, 35, self.canvas_width - 100, 35, fill="red", width=2)


    def _recursive_draw(self, x, y, depth, x_offset, current_path):

        """

        Recursively draws nodes, edges, and labels.


        Args:

            x (float): X-coordinate of the current node.

            y (float): Y-coordinate of the current node.

            depth (int): Current depth in the tree (0 is root).

            x_offset (float): Horizontal space for child nodes.

            current_path (str): Binary string path to the current node.

        """

        node_id = current_path

        

        # 1. Draw the current node (Yellow circle)

        node_obj = self.canvas.create_oval(

            x - self.node_radius, y - self.node_radius,

            x + self.node_radius, y + self.node_radius,

            fill="yellow", outline=self.normal_color

        )

        self.nodes[node_id] = node_obj


        if depth < self.tag_size:

            # Calculate child coordinates

            y_child = y + 80

            x_left = x - x_offset

            x_right = x + x_offset


            # 2. Draw Left Child (Bit 0)

            # Draw Line

            line_left = self.canvas.create_line(x, y + self.node_radius, x_left, y_child - self.node_radius, fill=self.normal_color, width=2)

            self.lines[node_id + "0"] = line_left

            # Draw Label (Box)

            label_x = x - x_offset / 2

            label_y = y + 30

            rect_left = self.canvas.create_rectangle(label_x - 15, label_y - 15, label_x + 15, label_y + 15, outline=self.normal_color, fill="white")

            text_left = self.canvas.create_text(label_x, label_y, text="0", fill="black", font=("Arial", 10))

            self.labels[node_id + "0_rect"] = rect_left

            self.labels[node_id + "0_text"] = text_left

            # Recurse

            self._recursive_draw(x_left, y_child, depth + 1, x_offset / 2, current_path + "0")


            # 3. Draw Right Child (Bit 1)

            # Draw Line

            line_right = self.canvas.create_line(x, y + self.node_radius, x_right, y_child - self.node_radius, fill=self.normal_color, width=2)

            self.lines[node_id + "1"] = line_right

            # Draw Label (Box)

            label_x = x + x_offset / 2

            label_y = y + 30

            rect_right = self.canvas.create_rectangle(label_x - 15, label_y - 15, label_x + 15, label_y + 15, outline=self.normal_color, fill="white")

            text_right = self.canvas.create_text(label_x, label_y, text="1", fill="black", font=("Arial", 10))

            self.labels[node_id + "1_rect"] = rect_right

            self.labels[node_id + "1_text"] = text_right

            # Recurse

            self._recursive_draw(x_right, y_child, depth + 1, x_offset / 2, current_path + "1")

        else:

            # 4. Draw the RFID tag box at the leaf level

            tag_y = y + 60

            box_width = 45

            box_height = 20

            tag_box = self.canvas.create_rectangle(

                x - box_width, tag_y - box_height,

                x + box_width, tag_y + box_height,

                outline="black", fill="white"

            )

            tag_text = self.canvas.create_text(x, tag_y, text=current_path, fill="black", font=("Arial", 12, "bold"))

            self.tag_boxes[node_id] = tag_box

            self.tag_text_items[node_id] = tag_text


    def clear_highlight(self):

        """Resets all colors to the default 'blue'."""

        

        # Reset nodes (circles)

        for node_id, item_id in self.nodes.items():

            self.canvas.itemconfig(item_id, outline=self.normal_color)


        # Reset lines (edges)

        for line_id, item_id in self.lines.items():

            self.canvas.itemconfig(item_id, fill=self.normal_color)


        # Reset labels (0/1 boxes and text) - Boxes only

        for label_id, item_id in self.labels.items():

            if label_id.endswith("_rect"):

                self.canvas.itemconfig(item_id, outline=self.normal_color)

            elif label_id.endswith("_text"):

                 self.canvas.itemconfig(item_id, fill="black")


        # Reset tag boxes

        for tag_id, item_id in self.tag_boxes.items():

            self.canvas.itemconfig(item_id, outline="black")


    def highlight_path(self):

        """Highlights the path in the tree corresponding to the entered tag."""

        

        self.clear_highlight() # Start by resetting


        tag_value = self.tag_entry.get().strip()

        

        # --- Input Validation ---

        if not tag_value or len(tag_value) != self.tag_size or not all(c in '01' for c in tag_value):

            tk.messagebox.showerror("Invalid Input", f"Please enter a valid {self.tag_size}-bit binary value (e.g., 0101).")

            return


        current_path = ""

        

        # Highlight the root node

        if "" in self.nodes:

             self.canvas.itemconfig(self.nodes[""], outline=self.highlight_color, width=3)


        # Iterate through each bit of the tag

        for i, bit in enumerate(tag_value):

            prev_path = current_path

            current_path += bit

            

            # Highlight the line (edge)

            line_key = current_path

            if line_key in self.lines:

                self.canvas.itemconfig(self.lines[line_key], fill=self.highlight_color, width=3)

            

            # Highlight the label (0/1 box)

            rect_key = line_key + "_rect"

            text_key = line_key + "_text"

            if rect_key in self.labels:

                self.canvas.itemconfig(self.labels[rect_key], outline=self.highlight_color, width=2)

            if text_key in self.labels:

                 self.canvas.itemconfig(self.labels[text_key], fill=self.highlight_color)


            # Highlight the node (circle)

            if current_path in self.nodes:

                self.canvas.itemconfig(self.nodes[current_path], outline=self.highlight_color, width=3)

        

        # Highlight the final RFID tag box

        if current_path in self.tag_boxes:

            self.canvas.itemconfig(self.tag_boxes[current_path], outline=self.highlight_color, width=3)

            self.canvas.itemconfig(self.tag_text_items[current_path], fill=self.highlight_color)

            

# --- Run the application ---

if __name__ == "__main__":

    root = tk.Tk()

    app = RFIDTreeApp(root)

    root.mainloop()


沒有留言:

張貼留言

ESP32 (ESP-IDF in VS Code) MFRC522 + MQTT + PYTHON TKinter +SQLite

 ESP32 (ESP-IDF in VS Code) MFRC522 + MQTT + PYTHON TKinter +SQLite  ESP32 VS Code 程式 ; PlatformIO Project Configuration File ; ;   Build op...