/** {@inheritDoc} */
  @Override
  public void simulate(final SimulationContext context) throws Exception {
    final SimulatedDevice device =
        context.getDevice(context.getMacros().resolveMacros(command.getDeviceName()));

    final double start = getLoopStart();
    final double end = getLoopEnd();
    final double step = getLoopStep();
    if (step > 0)
      for (double value = start; value <= end; value += step) simulateStep(context, device, value);
    else // step is < 0, so stepping down
    for (double value = end; value >= start; value += step) simulateStep(context, device, value);
  }
  /**
   * Simulate one step in the loop iteration
   *
   * @param context {@link SimulationContext}
   * @param device {@link SimulatedDevice} that the loop modifies
   * @param value Value of the loop variable for this iteration
   * @throws Exception on error
   */
  private void simulateStep(
      final SimulationContext context, final SimulatedDevice device, final double value)
      throws Exception {
    // Get previous value
    final double original = VTypeHelper.toDouble(device.read());

    // Estimate execution time
    final double time_estimate = command.getWait() ? device.getChangeTimeEstimate(value) : 0.0;

    // Show command
    final StringBuilder buf = new StringBuilder();
    buf.append("Loop '").append(command.getDeviceName()).append("' = ").append(value);
    command.appendConditionDetail(buf);
    if (!Double.isNaN(original)) buf.append(" [was ").append(original).append("]");
    context.logExecutionStep(context.getMacros().resolveMacros(buf.toString()), time_estimate);

    // Set to (simulated) new value
    device.write(value);

    // Simulate loop body
    context.simulate(implementation);
  }