Here's the formulation of the linear program and the Gurobi code to solve it:

**Decision Variables:**

* `x`: kg of maple syrup produced
* `y`: kg of maple candy produced

**Objective Function:**

Maximize profit: 20x + 15y

**Constraints:**

* **Production Capacity:**
    * x <= 10  (Maple syrup capacity)
    * y <= 12  (Maple candy capacity)
* **Minimum Demand:**
    * x >= 3   (Maple syrup demand)
    * y >= 5   (Maple candy demand)
* **Boiling Station Time:**
    * 2x + 2y <= 20 (Boiling station availability)
* **Non-negativity:**
    * x >= 0
    * y >= 0


```python
import gurobipy as gp
from gurobipy import GRB

# Create a new model
m = gp.Model("maple_production")

# Create variables
x = m.addVar(name="maple_syrup", lb=0)  # Maple syrup production (kg)
y = m.addVar(name="maple_candy", lb=0)  # Maple candy production (kg)

# Set objective function
m.setObjective(20*x + 15*y, GRB.MAXIMIZE)

# Add constraints
m.addConstr(x <= 10, "syrup_capacity")
m.addConstr(y <= 12, "candy_capacity")
m.addConstr(x >= 3, "syrup_demand")
m.addConstr(y >= 5, "candy_demand")
m.addConstr(2*x + 2*y <= 20, "boiling_time")


# Optimize model
m.optimize()

# Print results
if m.status == GRB.OPTIMAL:
    print(f"Optimal Production Plan:")
    print(f"Maple Syrup: {x.x:.2f} kg")
    print(f"Maple Candy: {y.x:.2f} kg")
    print(f"Maximum Profit: ${m.objVal:.2f}")
elif m.status == GRB.INFEASIBLE:
    print("The model is infeasible.")
else:
    print(f"Optimization terminated with status {m.status}")

```
