def main():
    """
    This code, which must run on the ROBOT:
      1. Constructs a robot, an MQTT SENDER, and a DELEGATE to respond
           to messages FROM the LAPTOP sent TO the ROBOT via MQTT.
      2. Stays in an infinite loop while a listener (for MQTT messages)
           runs in the background, "delegating" work to the "delegate".
    """
    robot = rb.RoseBot()

    delegate = DelegateForRobotCode(robot)
    mqtt_sender = mqtt.MqttClient(delegate)
    delegate.set_mqtt_sender(mqtt_sender)

    number = robot_number.get_robot_number()
    mqtt_sender.connect_to_mqtt_to_talk_to_laptop(lego_robot_number=number)

    time.sleep(1)  # To let the connection process complete
    print()
    print("Starting to listen for messages. The delegate responds to them.")
    print()

    # Stay in an infinite loop while the listener (for MQTT messages)
    # runs in the background:
    while True:
        time.sleep(0.01)
        if delegate.is_time_to_quit:
            break
def main():
    """
    This code, which must run on a LAPTOP:
      1. Displays and runs the Graphical User Interface (GUI) and
      2. Constructs the MQTT object for SENDING messages to the ROBOT and
           RECEIVING messages from the ROBOT.  ALso constructs a "delegate"
           object to which the MQTT RECEIVER routes messages from the ROBOT.
    """
    # -------------------------------------------------------------------------
    # The root TK object for the GUI:
    # -------------------------------------------------------------------------
    root = tkinter.Tk()
    root.title("Team XX, Person XX")
    # TODO: 2.  Fill in the XX's above appropriately for your team.

    # -------------------------------------------------------------------------
    # The main frame, upon which the widgets (including sub-frames) are placed.
    # -------------------------------------------------------------------------
    frame = ttk.Frame(root, padding=10, borderwidth=5, relief="groove")
    frame.grid()
    # TODO: 3.  Modify the characteristics of the above  main_frame  as desired.

    # -------------------------------------------------------------------------
    # Add widgets to your  main_frame  as desired.
    # -------------------------------------------------------------------------
    speed_label = ttk.Label(frame, text="Enter a speed: -100 to 100")
    speed_entry_box = ttk.Entry(frame)

    go_button = ttk.Button(frame, text="Make the robot GO")
    go_button["command"] = lambda: go_callback(mqtt_sender, speed_entry_box)

    stop_button = ttk.Button(frame, text="Make the robot STOP")
    stop_button["command"] = lambda: stop_callback(mqtt_sender)

    speed_label.grid(row=0, column=0)
    speed_entry_box.grid(row=0, column=1)
    go_button.grid(row=1, columnspan=2)
    stop_button.grid(row=2, columnspan=2)
    # TODO: 4. READ and UNDERSTAND the above code.  ASK QUESTIONS as desired.

    # TODO: 5. Add widgets as desired to your  main_frame below here:

    # -------------------------------------------------------------------------
    # Construct a DELEGATE (for responding to MQTT messages from the robot)
    # and a MQTT SENDER (to send messages to the robot).  The latter gets sent
    # to the   mX_laptop_code   modules via their  get_my_frame   methods.
    # Then  "connect"  the MQTT SENDER to the MQTT server, arranging for
    # messages to go to and from YOUR robot, while also making the
    # MQTT LISTENER start running in a loop in the background.
    # -------------------------------------------------------------------------
    delegate = DelegateForLaptopCode(root, frame)
    mqtt_sender = mqtt.MqttClient(delegate)
    delegate.set_mqtt_sender(mqtt_sender)
    # TODO: 6. READ and UNDERSTAND the above code.  ASK QUESTIONS as desired.

    # Use  None  for the robot number to just show the GUI (and NOT connect):
    number = robot_number.get_robot_number()
    mqtt_sender.connect_to_mqtt_to_talk_to_robot(lego_robot_number=number)
    # TODO: 7. READ and UNDERSTAND the above code.  ASK QUESTIONS as desired.

    # -------------------------------------------------------------------------
    # The event loop:
    # -------------------------------------------------------------------------
    root.mainloop()
    mqtt_sender.close()
def main():
    """
    This code, which must run on a LAPTOP:
      1. Displays and runs the Graphical User Interface (GUI).

      2. Constructs the MQTT object for:
           -- SENDING messages to the ROBOT and
           -- RECEIVING messages from the ROBOT.
         ALso constructs a "delegate" object to which the MQTT RECEIVER
         routes messages from the ROBOT.

      3. Puts widgets on the GUI and arranges for buttons et al
           to send appropriate messages to the robot, using callbacks
           and the   send_message   method of the MqttClient class.

      4. Receives messages from the robot and acts upon them,
           via the   DelegateForLaptopCode  object.
    """
    # -------------------------------------------------------------------------
    # The root TK object for the GUI:
    # -------------------------------------------------------------------------
    root = tkinter.Tk()
    root.title("Team XX, Person XX")
    # TODO: 2.  Fill in the XX's above appropriately for your team.

    # -------------------------------------------------------------------------
    # The main frame, upon which the widgets (including sub-frames) are placed.
    # -------------------------------------------------------------------------
    frame = ttk.Frame(root, padding=10, borderwidth=5, relief="groove")
    frame.grid()
    # TODO: 3.  Modify the characteristics of the above  main_frame  as desired.

    # -------------------------------------------------------------------------
    # Add widgets to your  main_frame  as desired.
    # -------------------------------------------------------------------------
    label_text = "Enter speeds for left and\nright wheels: -100 to 100"
    speed_label = ttk.Label(frame, text=label_text)

    left_speed_entry_box = ttk.Entry(frame)
    right_speed_entry_box = ttk.Entry(frame)

    go_button = ttk.Button(frame, text="Make the robot GO")
    go_button["command"] = lambda: go_callback(mqtt_sender,
                                               left_speed_entry_box,
                                               right_speed_entry_box)

    stop_button = ttk.Button(frame, text="Make the robot STOP")
    stop_button["command"] = lambda: stop_callback(mqtt_sender)

    speed_label.grid(row=0, column=0)
    left_speed_entry_box.grid(row=0, column=1)
    right_speed_entry_box.grid(row=0, column=2)
    go_button.grid(row=1, column=1)
    stop_button.grid(row=1, column=2)

    button_text = "Read sensors, print values on SSH window."
    read_sensors_button = ttk.Button(frame, text=button_text)
    read_sensors_button.grid(row=3, columnspan=3)
    read_sensors_button['command'] = lambda: read_sensors_callback(mqtt_sender)

    # -------------------------------------------------------------------------
    # TODO: 4. READ and UNDERSTAND the above code.  ASK QUESTIONS as desired.
    # -------------------------------------------------------------------------

    # -------------------------------------------------------------------------
    # TODO: 5. Add widgets as desired to your  main_frame below here:
    # -------------------------------------------------------------------------
    # SOLUTION: REMOVE before giving this to the students.

    # For the Arm and Claw:
    arm_label = ttk.Label(frame, text="Desired arm position:")
    arm_entry_box = ttk.Entry(frame)
    arm_calibrate_button = ttk.Button(frame, text="Calibrate the arm")
    arm_up_button = ttk.Button(frame, text="raise arm all the way UP")
    arm_down_button = ttk.Button(frame, text="lower arm all the way DOWN")
    arm_move_button = ttk.Button(frame, text="Move arm to desired position")

    arm_label.grid(row=4, column=0)
    arm_entry_box.grid(row=4, column=1)
    arm_move_button.grid(row=4, column=2)
    arm_calibrate_button.grid(row=5, column=0)
    arm_up_button.grid(row=5, column=1)
    arm_down_button.grid(row=5, column=2)

    arm_calibrate_button['command'] = lambda: arm_calibrate_callback(
        mqtt_sender)
    arm_move_button['command'] = lambda: arm_move_callback(mqtt_sender,
                                                           arm_entry_box)
    arm_up_button['command'] = lambda: arm_up_callback(mqtt_sender)
    arm_down_button['command'] = lambda: arm_down_callback(mqtt_sender)

    # For the LEDs:
    line1 = "Color to which to set\n"
    line2 = "the LEFT/RIGHT LED:\n"
    line3 = "red, green, amber, or off."
    color_label = ttk.Label(frame, text=line1 + line2 + line3)
    left_led_color_entry_box = ttk.Entry(frame)
    left_led_button = ttk.Button(
        frame, text="Set the LEFT LED\nto the specified color")
    right_led_color_entry_box = ttk.Entry(frame)
    right_led_button = ttk.Button(
        frame, text="Set the RIGHT LED\nto the specified color")

    color_label.grid(row=6, rowspan=2, column=0)
    left_led_color_entry_box.grid(row=6, column=1)
    left_led_button.grid(row=6, column=2)
    right_led_color_entry_box.grid(row=7, column=1)
    right_led_button.grid(row=7, column=2)

    left_led_button['command'] = lambda: set_led_callback(
        mqtt_sender, left_led_color_entry_box, "left")
    right_led_button['command'] = lambda: set_led_callback(
        mqtt_sender, right_led_color_entry_box, "right")

    # -------------------------------------------------------------------------
    # Construct a DELEGATE (for responding to MQTT messages from the robot)
    # and a MQTT SENDER (to send messages to the robot).  The latter gets sent
    # to the   mX_laptop_code   modules via their  get_my_frame   methods.
    # Then  "connect"  the MQTT SENDER to the MQTT server, arranging for
    # messages to go to and from YOUR robot, while also making the
    # MQTT LISTENER start running in a loop in the background.
    # -------------------------------------------------------------------------
    delegate = DelegateForLaptopCode(root, frame)
    mqtt_sender = mqtt.MqttClient(delegate)
    delegate.set_mqtt_sender(mqtt_sender)
    # -------------------------------------------------------------------------
    # TODO: 6. READ and UNDERSTAND the above code.  ASK QUESTIONS as desired.
    # -------------------------------------------------------------------------

    # Use  None  for the robot number to just show the GUI (and NOT connect):
    number = robot_number.get_robot_number()
    mqtt_sender.connect_to_mqtt_to_talk_to_robot(lego_robot_number=number)
    # -------------------------------------------------------------------------
    # TODO: 7. READ and UNDERSTAND the above code.  ASK QUESTIONS as desired.
    # -------------------------------------------------------------------------

    # -------------------------------------------------------------------------
    # The event loop:
    # -------------------------------------------------------------------------
    root.mainloop()
    mqtt_sender.close()