Пример #1
0
void handle_device_name_order()
{
  if (parameter_length < 2)
  {
    send_insufficient_bytes_error_response(2);
    return;
  }

  const uint8_t device_type = parameter_value[0];
  const uint8_t device_number = parameter_value[1];

  uint8_t num_devices = get_num_devices(device_type);
  if (device_number >= num_devices)
  {
    if (num_devices < 0)
      send_app_error_response(PARAM_APP_ERROR_TYPE_INVALID_DEVICE_TYPE,0);
    else
      send_app_error_response(PARAM_APP_ERROR_TYPE_INVALID_DEVICE_NUMBER,0);
    return;
  }

  generate_response_start(RSP_OK);
  char *response_data_buf = (char *)generate_response_data_ptr();
  uint8_t response_data_buf_len = generate_response_data_len();

  int8_t length;
  if ((length = NVConfigStore::GetDeviceName(device_type, device_number, response_data_buf, response_data_buf_len)) > 0)
    generate_response_data_addlen(length);
  generate_response_send();
}
void handle_firmware_configuration_value_properties(const char *name)
{
  ConfigurationTree tree;

  if (name[0] == '\0')
  {
    send_app_error_response(PARAM_APP_ERROR_TYPE_BAD_PARAMETER_FORMAT,
                      PMSG(ERR_MSG_CONFIG_NODE_NOT_FOUND));
    return;
  }

  ConfigurationTreeNode *node = tree.FindNode(name);
  if (node == 0)
  {
    send_app_error_response(PARAM_APP_ERROR_TYPE_BAD_PARAMETER_VALUE,
                      PMSG(ERR_MSG_CONFIG_NODE_NOT_FOUND), name);
    return;
  }

  if (!node->IsLeafNode())
  {
    send_app_error_response(PARAM_APP_ERROR_TYPE_BAD_PARAMETER_VALUE,
                      PMSG(ERR_MSG_CONFIG_NODE_NOT_COMPLETE), name);
    return;
  }

  generate_response_start(RSP_OK, 2);
  generate_response_data_addbyte(node->GetLeafClass());
  generate_response_data_addbyte(node->GetLeafOperations());

  // determine default value status here where necessary.

  // determine whether configuration node is associated with a device
  // (we search for a parent instance node where the device type has been set)
  uint8_t device_type = PM_DEVICE_TYPE_INVALID;
  uint8_t device_number = 0;
  while ((node = tree.GetParentNode(node)) != 0)
  {
    if (node->IsInstanceNode()
        && node->GetLeafSetDataType() != PM_DEVICE_TYPE_INVALID)
    {
      device_type = node->GetLeafSetDataType();
      device_number = node->GetInstanceId();
    }
  }
  generate_response_data_addbyte(device_type);
  generate_response_data_addbyte(device_number);

  generate_response_send();
}
Пример #3
0
void handle_resume_order()
{
  if (parameter_length < 1)
  {
    send_insufficient_bytes_error_response(1);
    return;
  }

  const uint8_t resume_type = parameter_value[0];

  if (resume_type == PARAM_RESUME_TYPE_ACKNOWLEDGE)
  {
    stopped_is_acknowledged = true;
    send_stopped_response();
  }
  else if (resume_type == PARAM_RESUME_TYPE_CLEAR)
  {
    stopped_is_acknowledged = true;

    if (stopped_type == PARAM_STOPPED_TYPE_ONE_TIME_OR_CLEARED)
      is_stopped = false;

    send_stopped_response();
  }
  else
  {
    send_app_error_response(PARAM_APP_ERROR_TYPE_BAD_PARAMETER_VALUE,0);
  }
}
bool set_float_value(uint8_t node_type, uint8_t parent_instance_id,  uint8_t instance_id, float value)
{
  uint8_t retval;

  switch (node_type)
  {
  case NODE_TYPE_CONFIG_LEAF_HEATER_PID_KP:
    retval = Device_Heater::SetPidDefaultKp(parent_instance_id, value);
    break;
  case NODE_TYPE_CONFIG_LEAF_HEATER_PID_KI:
    retval = Device_Heater::SetPidDefaultKi(parent_instance_id, value);
    break;
  case NODE_TYPE_CONFIG_LEAF_HEATER_PID_KD:
    retval = Device_Heater::SetPidDefaultKd(parent_instance_id, value);
    break;

  default:
    send_app_error_response(PARAM_APP_ERROR_TYPE_FIRMWARE_ERROR,
         PMSG(MSG_ERR_CANNOT_HANDLE_FIRMWARE_CONFIG_REQUEST), __LINE__);
    return false;
  }

  if (retval == APP_ERROR_TYPE_SUCCESS)
    return true;

  generate_response_data_addbyte(retval);
  generate_response_send();
  return false;
}
Пример #5
0
void handle_enable_disable_steppers_order()
{
  if (parameter_length == 1) // expect 0 or >=2 bytes
  {
    send_insufficient_bytes_error_response(1);
    return;
  }

  if (parameter_length == 0)
  {
    for (uint8_t i=0; i<Device_Stepper::GetNumDevices(); i++)
    {
      if (Device_Stepper::IsInUse(i))
        Device_Stepper::WriteEnableState(i, false);
    }
  }
  else
  {
    uint8_t device_number = parameter_value[0];
    uint8_t device_state = parameter_value[1];
    if (!Device_Stepper::IsInUse(device_number))
    {
      send_app_error_at_offset_response(PARAM_APP_ERROR_TYPE_INVALID_DEVICE_NUMBER, 0);
      return;
    }
    if (is_stopped && device_state != 0)
    {
      send_app_error_response(PARAM_APP_ERROR_TYPE_DEVICE_UNAVAILABLE,
          PMSG(MSG_ERR_CANNOT_ACTIVATE_DEVICE_WHEN_STOPPED));
      return;
    }
    Device_Stepper::WriteEnableState(device_number, device_state);
  }
  send_OK_response();
}
Пример #6
0
void handle_set_heater_target_temperature_order()
{
  if (parameter_length < 3)
  {
    send_insufficient_bytes_error_response(3);
    return;
  }

  const uint8_t heater_number = parameter_value[0];
  const int16_t temp = (parameter_value[1] << 8) | parameter_value[2];
  const float ftemp = (float)temp / 10;

  generate_response_start(RSP_APPLICATION_ERROR, 1);
  uint8_t retval = Device_Heater::ValidateTargetTemperature(heater_number, ftemp);
  if (retval != APP_ERROR_TYPE_SUCCESS)
  {
    generate_response_data_addbyte(retval);
    generate_response_send();
    return;
  }

  if (is_stopped && ftemp != SENSOR_TEMPERATURE_INVALID)
  {
    send_app_error_response(PARAM_APP_ERROR_TYPE_DEVICE_UNAVAILABLE,
        PMSG(MSG_ERR_CANNOT_ACTIVATE_DEVICE_WHEN_STOPPED));
    return;
  }
  Device_Heater::SetTargetTemperature(heater_number, ftemp);
  send_OK_response();
}
bool set_int16_value(uint8_t node_type, uint8_t parent_instance_id,  uint8_t instance_id, int16_t value)
{
  uint8_t retval;

  switch (node_type)
  {
  case NODE_TYPE_CONFIG_LEAF_HEATER_MAX_TEMP:
    retval = Device_Heater::SetMaxTemperature(parent_instance_id, value);
    break;

  case NODE_TYPE_CONFIG_LEAF_TEMP_SENSOR_TYPE:
    retval = Device_TemperatureSensor::SetType(parent_instance_id, value);
    break;

  default:
    send_app_error_response(PARAM_APP_ERROR_TYPE_FIRMWARE_ERROR,
         PMSG(MSG_ERR_CANNOT_HANDLE_FIRMWARE_CONFIG_REQUEST), __LINE__);
    return false;
  }

  if (retval == APP_ERROR_TYPE_SUCCESS)
    return true;

  generate_response_data_addbyte(retval);
  generate_response_send();
  return false;
}
Пример #8
0
void handle_clear_command_queue_order()
{
  generate_response_start(RSP_APPLICATION_ERROR, 1);

  if (CommandQueue::GetQueueBufferLength() == 0)
  {
    if (!allocate_command_queue_memory())
    {
      send_app_error_response(PARAM_APP_ERROR_TYPE_FIRMWARE_ERROR,
                              PMSG(MSG_ERR_INSUFFICIENT_MEMORY));
      return;
    }
  }

  CommandQueue::FlushQueuedCommands();

  uint16_t remaining_slots;
  uint16_t current_command_count;
  uint16_t total_command_count;
  CommandQueue::GetQueueInfo(remaining_slots, current_command_count, total_command_count);

  generate_response_start(RSP_OK);
  generate_response_data_add(remaining_slots);
  generate_response_data_add(current_command_count);
  generate_response_data_add(total_command_count);
  generate_response_send();
}
Пример #9
0
void handle_configure_axis_movement_rates_order()
{
  if (parameter_length < 5)
  {
    send_insufficient_bytes_error_response(5);
    return;
  }

  uint8_t device_number = parameter_value[0];

  if (!Device_Stepper::IsInUse(device_number))
  {
    send_app_error_at_offset_response(PARAM_APP_ERROR_TYPE_INVALID_DEVICE_NUMBER, 0);
    return;
  }

  uint32_t max_rate = ((uint32_t)parameter_value[1] << 24) | ((uint32_t)parameter_value[2] << 16) | ((uint32_t)parameter_value[3] << 8) | parameter_value[4];

  if (max_rate > MAX_STEP_FREQUENCY)
  {
    send_app_error_at_offset_response(PARAM_APP_ERROR_TYPE_BAD_PARAMETER_VALUE,1);
    return;
  }

  uint8_t retval = AxisInfo::SetAxisMaxRate(device_number, (uint16_t)max_rate);
  if (retval != APP_ERROR_TYPE_SUCCESS)
  {
    send_app_error_response(retval, 0);
    return;
  }
  send_OK_response();
}
Пример #10
0
void handle_request_temperature_reading_order()
{
  if (parameter_length < 2)
  {
    send_insufficient_bytes_error_response(2);
    return;
  }
  if ((parameter_length & 1) == 1)
  {
    send_app_error_response(PARAM_APP_ERROR_TYPE_BAD_PARAMETER_FORMAT, 0);
    return;
  }

  generate_response_start(RSP_OK,parameter_length*2);

  for (int i = 0; i < parameter_length; i+=2)
  {
    const uint8_t device_type = parameter_value[i];
    const uint8_t device_number = parameter_value[i+1];
    float ftemp;
    int16_t temp;

    switch(device_type)
    {
    case PM_DEVICE_TYPE_HEATER:
    {
      if (!Device_Heater::IsInUse(device_number))
      {
        send_app_error_at_offset_response(PARAM_APP_ERROR_TYPE_INVALID_DEVICE_NUMBER, i+1);
        return;
      }
      ftemp = Device_Heater::ReadCurrentTemperature(device_number);
      break;
    }
    case PM_DEVICE_TYPE_TEMP_SENSOR:
    {
      if (!Device_TemperatureSensor::IsInUse(device_number))
      {
        send_app_error_at_offset_response(PARAM_APP_ERROR_TYPE_INVALID_DEVICE_NUMBER, i+1);
        return;
      }
      ftemp = Device_TemperatureSensor::ReadCurrentTemperature(device_number);
      break;
    }
    default:
      send_app_error_at_offset_response(PARAM_APP_ERROR_TYPE_INVALID_DEVICE_TYPE, i);
      return;
    }
    if (ftemp != SENSOR_TEMPERATURE_INVALID)
      temp = ftemp * 10.0;
    else
      temp = PM_TEMPERATURE_INVALID;
    generate_response_data_addbyte(highByte(temp));
    generate_response_data_addbyte(lowByte(temp));
  }

  generate_response_send();
}
Пример #11
0
void handle_firmware_configuration_traversal(const char *name)
{
  ConfigurationTree tree;

  ConfigurationTreeNode *node;
  if (name[0] == '\0')
  {
    node = tree.FindFirstLeafNode(tree.GetRootNode());
  }
  else
  {
    node = tree.FindNode(name);
    if (node == 0)
    {
      send_app_error_response(PARAM_APP_ERROR_TYPE_BAD_PARAMETER_VALUE,
                        PMSG(ERR_MSG_CONFIG_NODE_NOT_FOUND), name);
      return;
    }
    // currently only return nodes for devices which are in use
    node = tree.FindNextLeafNode(tree.GetRootNode());
  }

  if (node == 0)
  {
    send_OK_response();
    return;
  }

  generate_response_start(RSP_OK);

  char *response_data_buf = (char *)generate_response_data_ptr();
  uint8_t response_data_buf_len = generate_response_data_len();
  int8_t length;

  if ((length = tree.GetFullName(node, response_data_buf, response_data_buf_len)) > 0)
  {
    generate_response_data_addlen(length);
  }
  else
  {
    send_app_error_response(PARAM_APP_ERROR_TYPE_FIRMWARE_ERROR, 0);
    return;
  }
  generate_response_send();
}
Пример #12
0
bool setPin(uint8_t node_type, uint8_t device_number, uint8_t pin)
{
  uint8_t retval = false;

  switch (node_type)
  {
  case NODE_TYPE_CONFIG_LEAF_INPUT_SWITCH_PIN:
    retval = Device_InputSwitch::SetPin(device_number, pin);
    break;

  case NODE_TYPE_CONFIG_LEAF_OUTPUT_SWITCH_PIN:
    retval = Device_OutputSwitch::SetPin(device_number, pin);
    break;

  case NODE_TYPE_CONFIG_LEAF_PWM_OUTPUT_PIN:
    retval = Device_PwmOutput::SetPin(device_number, pin);
    break;

  case NODE_TYPE_CONFIG_LEAF_BUZZER_PIN:
    retval = Device_Buzzer::SetPin(device_number, pin);
    break;

  case NODE_TYPE_CONFIG_LEAF_TEMP_SENSOR_PIN:
    retval = Device_TemperatureSensor::SetPin(device_number, pin);
    break;

  case NODE_TYPE_CONFIG_LEAF_HEATER_PIN:
    retval = Device_Heater::SetHeaterPin(device_number, pin);
    break;

  case NODE_TYPE_CONFIG_LEAF_STEPPER_ENABLE_PIN:
    retval = Device_Stepper::SetEnablePin(device_number, pin);
    break;

  case NODE_TYPE_CONFIG_LEAF_STEPPER_DIRECTION_PIN:
    retval = Device_Stepper::SetDirectionPin(device_number, pin);
    break;

  case NODE_TYPE_CONFIG_LEAF_STEPPER_STEP_PIN:
    retval = Device_Stepper::SetStepPin(device_number, pin);
    break;

  default:
    send_app_error_response(PARAM_APP_ERROR_TYPE_FIRMWARE_ERROR,
         PMSG(MSG_ERR_CANNOT_HANDLE_FIRMWARE_CONFIG_REQUEST), __LINE__);
    return false;
  }

  if (retval == APP_ERROR_TYPE_SUCCESS)
    return true;

  generate_response_data_addbyte(retval);
  generate_response_msg_addPGM(PMSG(ERR_MSG_INVALID_PIN_NUMBER));
  generate_response_send();
  return false;
}
Пример #13
0
bool set_bool_value(uint8_t node_type, uint8_t parent_instance_id,  uint8_t instance_id, bool value)
{
  uint8_t retval;

  switch (node_type)
  {
  case NODE_TYPE_CONFIG_LEAF_INPUT_SWITCH_TRIGGER_LEVEL:
    retval = Device_InputSwitch::SetTriggerLevel(parent_instance_id, value);
    break;
  case NODE_TYPE_CONFIG_LEAF_INPUT_SWITCH_ENABLE_PULLUP:
    retval = Device_InputSwitch::SetEnablePullup(parent_instance_id, value);
    break;

  case NODE_TYPE_CONFIG_LEAF_PWM_OUTPUT_USE_SOFT_PWM:
    retval = Device_PwmOutput::EnableSoftPwm(parent_instance_id, value);
    break;
  case NODE_TYPE_CONFIG_LEAF_HEATER_USE_SOFT_PWM:
    retval = Device_Heater::EnableSoftPwm(parent_instance_id, value);
    break;

  case NODE_TYPE_CONFIG_LEAF_HEATER_USE_BANG_BANG:
    if (value)
      retval = Device_Heater::SetControlMode(parent_instance_id, HEATER_CONTROL_MODE_BANG_BANG);
    else
      retval = APP_ERROR_TYPE_SUCCESS;
    break;
  case NODE_TYPE_CONFIG_LEAF_HEATER_USE_PID:
    if (value)
      retval = Device_Heater::SetControlMode(parent_instance_id, HEATER_CONTROL_MODE_PID);
    else
      retval = APP_ERROR_TYPE_SUCCESS;
    break;

  case NODE_TYPE_CONFIG_LEAF_STEPPER_ENABLE_INVERT:
    retval = Device_Stepper::SetEnableInvert(parent_instance_id, value);
    break;
  case NODE_TYPE_CONFIG_LEAF_STEPPER_DIRECTION_INVERT:
    retval = Device_Stepper::SetDirectionInvert(parent_instance_id, value);
    break;
  case NODE_TYPE_CONFIG_LEAF_STEPPER_STEP_INVERT:
    retval = Device_Stepper::SetStepInvert(parent_instance_id, value);
    break;

  default:
    send_app_error_response(PARAM_APP_ERROR_TYPE_FIRMWARE_ERROR,
         PMSG(MSG_ERR_CANNOT_HANDLE_FIRMWARE_CONFIG_REQUEST), __LINE__);
    return false;
  }

  if (retval == APP_ERROR_TYPE_SUCCESS)
    return true;

  generate_response_data_addbyte(retval);
  generate_response_send();
  return false;
}
Пример #14
0
void handle_activate_stepper_control_order()
{
  if (parameter_length < 1)
  {
    send_insufficient_bytes_error_response(1);
    return;
  }

  // Currently Minnow does not supported disabling on stepper control. This is
  // primarily only necessary for SPI controlled stepper modules which are not
  // supported by Minnow and would complicate the initial_pin_state logic.
  if (!parameter_value[0])
  {
    send_app_error_response(PARAM_APP_ERROR_TYPE_FAILED,PMSG(MSG_ERR_NOT_SUPPORTED));
    return;
  }
  send_OK_response();
}
Пример #15
0
void handle_get_input_switch_state_order()
{
  uint8_t device_type, device_number;

  if (parameter_length < 2)
  {
    send_insufficient_bytes_error_response(2);
    return;
  }
  if ((parameter_length & 1) == 1)
  {
    send_app_error_response(PARAM_APP_ERROR_TYPE_BAD_PARAMETER_FORMAT, 0);
    return;
  }

  generate_response_start(RSP_OK,parameter_length/2);

  for (int i = 0; i < parameter_length; i+=2)
  {
    device_type = parameter_value[i];
    device_number = parameter_value[i+1];

    switch(device_type)
    {
    case PM_DEVICE_TYPE_SWITCH_INPUT:
    {
      if (!Device_InputSwitch::IsInUse(device_number))
      {
        send_app_error_at_offset_response(PARAM_APP_ERROR_TYPE_INVALID_DEVICE_NUMBER, i+1);
        return;
      }
      generate_response_data_addbyte(Device_InputSwitch::ReadState(device_number));
      break;
    }
    default:
      send_app_error_at_offset_response(PARAM_APP_ERROR_TYPE_INVALID_DEVICE_TYPE, i);
      return;
    }
  }

  generate_response_send();
}
Пример #16
0
void handle_device_count_order()
{
  if (parameter_length < 1)
  {
    send_insufficient_bytes_error_response(1);
    return;
  }

  const uint8_t device_type = parameter_value[0];

  uint8_t num_devices = get_num_devices(device_type);
  if (num_devices < 0)
  {
    send_app_error_response(PARAM_APP_ERROR_TYPE_INVALID_DEVICE_TYPE,0);
    return;
  }

  generate_response_start(RSP_OK,1);
  generate_response_data_addbyte(num_devices);
  generate_response_send();
}
Пример #17
0
void handle_get_heater_configuration_order()
{
  if (parameter_length < 1)
  {
    send_insufficient_bytes_error_response(1);
    return;
  }

  const uint8_t heater_number = parameter_value[0];

  if (Device_Heater::GetHeaterPin(heater_number) == 0xFF)
  {
    send_app_error_response(PARAM_APP_ERROR_TYPE_INVALID_DEVICE_NUMBER,0);
    return;
  }

  generate_response_start(RSP_OK);
  generate_response_data_addbyte(PARAM_HEATER_CONFIG_HOST_SENSOR_CONFIG);
  generate_response_data_addbyte(Device_Heater::GetTempSensor(heater_number));
  generate_response_send();
}
Пример #18
0
void handle_configure_heater_order()
{
  if (parameter_length < 2)
  {
    send_insufficient_bytes_error_response(2);
    return;
  }

  const uint8_t heater_number = parameter_value[0];
  const uint8_t temp_sensor = parameter_value[1];
  const uint8_t current_temp_sensor = Device_Heater::GetTempSensor(heater_number);

  if (current_temp_sensor != 0xFF)
  {
    if (current_temp_sensor != temp_sensor)
    {
      // Don't allow Pacemaker order to override internal configuration
      send_app_error_response(PARAM_APP_ERROR_TYPE_FAILED,
          PMSG(MSG_ERR_ALREADY_INITIALIZED));
    }
    else
    {
      send_OK_response();
    }
    return;
  }

  generate_response_start(RSP_APPLICATION_ERROR, 1);
  uint8_t retval = Device_Heater::SetTempSensor(heater_number, temp_sensor);
  if (retval != APP_ERROR_TYPE_SUCCESS)
  {
    generate_response_data_addbyte(retval);
    generate_response_send();
  }
  else
  {
    send_OK_response();
  }
}
Пример #19
0
bool set_string_value(uint8_t node_type, uint8_t parent_instance_id,  uint8_t instance_id, const char *value)
{
  uint8_t retval;

  generate_response_start(RSP_APPLICATION_ERROR, 1);

  switch (node_type)
  {
  case NODE_TYPE_CONFIG_LEAF_INPUT_SWITCH_FRIENDLY_NAME:
    retval = NVConfigStore::SetDeviceName(PM_DEVICE_TYPE_SWITCH_INPUT, parent_instance_id, value);
    break;
  case NODE_TYPE_CONFIG_LEAF_OUTPUT_SWITCH_FRIENDLY_NAME:
    retval = NVConfigStore::SetDeviceName(PM_DEVICE_TYPE_SWITCH_OUTPUT, parent_instance_id, value);
    break;
  case NODE_TYPE_CONFIG_LEAF_PWM_OUTPUT_FRIENDLY_NAME:
    retval = NVConfigStore::SetDeviceName(PM_DEVICE_TYPE_PWM_OUTPUT, parent_instance_id, value);
    break;
  case NODE_TYPE_CONFIG_LEAF_BUZZER_FRIENDLY_NAME:
    retval = NVConfigStore::SetDeviceName(PM_DEVICE_TYPE_BUZZER, parent_instance_id, value);
    break;
  case NODE_TYPE_CONFIG_LEAF_TEMP_SENSOR_FRIENDLY_NAME:
    retval = NVConfigStore::SetDeviceName(PM_DEVICE_TYPE_TEMP_SENSOR, parent_instance_id, value);
    break;
  case NODE_TYPE_CONFIG_LEAF_HEATER_FRIENDLY_NAME:
    retval = NVConfigStore::SetDeviceName(PM_DEVICE_TYPE_HEATER, parent_instance_id, value);
    break;
  case NODE_TYPE_CONFIG_LEAF_STEPPER_FRIENDLY_NAME:
    retval = NVConfigStore::SetDeviceName(PM_DEVICE_TYPE_STEPPER, parent_instance_id, value);
    break;

  case NODE_TYPE_CONFIG_LEAF_OUTPUT_SWITCH_INITIAL_STATE:
  {
    uint8_t pin_state;
    if (!parse_initial_pin_state_value(value, &pin_state))
    {
      generate_response_data_addbyte(PARAM_APP_ERROR_TYPE_BAD_PARAMETER_VALUE);
      generate_response_msg_addPGM(PMSG(MSG_ERR_UNKNOWN_VALUE));
      generate_response_send();
      return false;
    }
    retval = Device_OutputSwitch::SetInitialState(parent_instance_id, pin_state);
    break;
  }
  case NODE_TYPE_CONFIG_LEAF_SYSTEM_HARDWARE_NAME:
    retval = NVConfigStore::SetHardwareName(value);
    break;
  case NODE_TYPE_CONFIG_LEAF_SYSTEM_BOARD_IDENTITY:
    retval = NVConfigStore::SetBoardIdentity(value);
    break;
  case NODE_TYPE_CONFIG_LEAF_SYSTEM_BOARD_SERIAL_NUM:
    retval = NVConfigStore::SetBoardSerialNumber(value);
    break;

  case NODE_TYPE_CONFIG_LEAF_HEATER_PID_DO_AUTOTUNE:
  {
    char *end;
    long temp, cycles;
    if ((temp = strtol(value, &end, 10)) == 0 || *end != ',' ||
        (cycles = strtol(end+1, &end, 10)) == 0 || *end != '\0')
    {
      generate_response_data_addbyte(PARAM_APP_ERROR_TYPE_BAD_PARAMETER_FORMAT);
      generate_response_msg_addPGM(PMSG(MSG_EXPECTING));
      generate_response_msg_addPGM(PMSG(ERR_MSG_BAD_PID_AUTOTUNE_FORMAT));
      generate_response_send();
      return false;
    }
    if (!Device_Heater::IsInUse(parent_instance_id)
        || !Device_TemperatureSensor::IsInUse(Device_Heater::GetTempSensor(parent_instance_id)))
    {
      send_app_error_response(PARAM_APP_ERROR_TYPE_INVALID_DEVICE_NUMBER,
                              PMSG(ERR_MSG_DEVICE_NOT_IN_USE));
      return false;
    }
    send_OK_response(); // send response now as it takes a while to complete
    Device_Heater::DoPidAutotune(parent_instance_id, temp, cycles);
    return false;
  }
  case NODE_TYPE_OPERATION_LEAF_RESET_EEPROM:
    NVConfigStore::WriteDefaults(true);
    retval = APP_ERROR_TYPE_SUCCESS;
    break;
  default:
    send_app_error_response(PARAM_APP_ERROR_TYPE_FIRMWARE_ERROR,
         PMSG(MSG_ERR_CANNOT_HANDLE_FIRMWARE_CONFIG_REQUEST), __LINE__);
    return false;
  }

  if (retval == APP_ERROR_TYPE_SUCCESS)
    return true;

  generate_response_data_addbyte(retval);
  generate_response_send();
  return false;
}
Пример #20
0
void handle_request_information_order()
{
  if (parameter_length < 1)
  {
    send_insufficient_bytes_error_response(1);
    return;
  }

  const uint8_t request_type = parameter_value[0];

  generate_response_start(RSP_OK);
  char *response_data_buf = (char *)generate_response_data_ptr();
  uint8_t response_data_buf_len = generate_response_data_len();
  int8_t length;
  uint8_t value;

  switch(request_type)
  {
  case PARAM_REQUEST_INFO_FIRMWARE_NAME:
    generate_response_data_addPGM(PSTR(MINNOW_FIRMWARE_NAME));
    break;

  case PARAM_REQUEST_INFO_BOARD_SERIAL_NUMBER:
    if ((length = NVConfigStore::GetBoardSerialNumber(response_data_buf, response_data_buf_len)) > 0)
      generate_response_data_addlen(length);
    break;

  case PARAM_REQUEST_INFO_BOARD_NAME:
    if ((length = NVConfigStore::GetHardwareName(response_data_buf, response_data_buf_len)) > 0)
      generate_response_data_addlen(length);
    break;

  case PARAM_REQUEST_INFO_GIVEN_NAME:
    if ((length = NVConfigStore::GetBoardIdentity(response_data_buf, response_data_buf_len)) > 0)
      generate_response_data_addlen(length);
    break;

  case PARAM_REQUEST_INFO_PROTO_VERSION_MAJOR:
    generate_response_data_addbyte(PM_PROTCOL_VERSION_MAJOR);
    break;

  case PARAM_REQUEST_INFO_PROTO_VERSION_MINOR:
    generate_response_data_addbyte(PM_PROTCOL_VERSION_MINOR);
    break;

  case PARAM_REQUEST_INFO_SUPPORTED_EXTENSIONS:
    generate_response_data_addbyte(PM_EXTENSION_STEPPER_CONTROL);
    generate_response_data_addbyte(PM_EXTENSION_QUEUED_CMD);
    generate_response_data_addbyte(PM_EXTENSION_BASIC_MOVE);
    break;

  case PARAM_REQUEST_INFO_FIRMWARE_TYPE:
    generate_response_data_addbyte(PM_FIRMWARE_TYPE_MINNOW);
    break;

  case PARAM_REQUEST_INFO_FIRMWARE_VERSION_MAJOR:
    generate_response_data_addbyte(MINNOW_FIRMWARE_VERSION_MAJOR);
    break;

  case PARAM_REQUEST_INFO_FIRMWARE_VERSION_MINOR:
    generate_response_data_addbyte(MINNOW_FIRMWARE_VERSION_MINOR);
    break;

  case PARAM_REQUEST_INFO_HARDWARE_TYPE:
    generate_response_data_addbyte(NVConfigStore::GetHardwareType());
    break;

  case PARAM_REQUEST_INFO_HARDWARE_REVISION:
    if ((value = NVConfigStore::GetHardwareRevision()) != 0xFF)
      generate_response_data_addbyte(value);
    break;

  case PARAM_REQUEST_INFO_MAXIMUM_STEP_RATE:
    generate_response_data_add(MAX_STEP_FREQUENCY);
    break;

  case PARAM_REQUEST_INFO_HOST_TIMEOUT:
    generate_response_data_addbyte(HOST_TIMEOUT_SECS);
    break;

  default:
    send_app_error_response(PARAM_APP_ERROR_TYPE_BAD_PARAMETER_VALUE,0);
    return;
  }
  generate_response_send();
}
Пример #21
0
bool set_uint8_value(uint8_t node_type, uint8_t parent_instance_id,  uint8_t instance_id, uint8_t value)
{
  uint8_t retval;
  switch (node_type)
  {
  case NODE_TYPE_CONFIG_LEAF_INPUT_SWITCH_PIN:
  case NODE_TYPE_CONFIG_LEAF_OUTPUT_SWITCH_PIN:
  case NODE_TYPE_CONFIG_LEAF_PWM_OUTPUT_PIN:
  case NODE_TYPE_CONFIG_LEAF_BUZZER_PIN:
  case NODE_TYPE_CONFIG_LEAF_TEMP_SENSOR_PIN:
  case NODE_TYPE_CONFIG_LEAF_HEATER_PIN:
  case NODE_TYPE_CONFIG_LEAF_STEPPER_ENABLE_PIN:
  case NODE_TYPE_CONFIG_LEAF_STEPPER_DIRECTION_PIN:
  case NODE_TYPE_CONFIG_LEAF_STEPPER_STEP_PIN:
    return setPin(node_type, parent_instance_id, value);

  case NODE_TYPE_CONFIG_LEAF_SYSTEM_HARDWARE_TYPE:
    retval = NVConfigStore::SetHardwareType(value);
    break;
  case NODE_TYPE_CONFIG_LEAF_SYSTEM_HARDWARE_REV:
    retval = NVConfigStore::SetHardwareRevision(value);
    break;

  case NODE_TYPE_CONFIG_LEAF_SYSTEM_NUM_INPUT_SWITCHES:
    retval = Device_InputSwitch::Init(value);
    break;
  case NODE_TYPE_CONFIG_LEAF_SYSTEM_NUM_OUTPUT_SWITCHES:
    retval = Device_OutputSwitch::Init(value);
    break;
  case NODE_TYPE_CONFIG_LEAF_SYSTEM_NUM_PWM_OUTPUTS:
    retval = Device_PwmOutput::Init(value);
    break;
  case NODE_TYPE_CONFIG_LEAF_SYSTEM_NUM_BUZZERS:
    retval = Device_Buzzer::Init(value);
    break;
  case NODE_TYPE_CONFIG_LEAF_SYSTEM_NUM_TEMP_SENSORS:
    retval = Device_TemperatureSensor::Init(value);
    break;
  case NODE_TYPE_CONFIG_LEAF_SYSTEM_NUM_HEATERS:
    retval = Device_Heater::Init(value);
    break;
  case NODE_TYPE_CONFIG_LEAF_SYSTEM_NUM_STEPPERS:
    retval = Device_Stepper::Init(value);
    break;

  case NODE_TYPE_CONFIG_LEAF_OUTPUT_SWITCH_INITIAL_STATE:
    retval = Device_OutputSwitch::SetInitialState(parent_instance_id, value);
    break;

  case NODE_TYPE_CONFIG_LEAF_HEATER_TEMP_SENSOR:
    retval = Device_Heater::SetTempSensor(parent_instance_id, value);
    break;
  case NODE_TYPE_CONFIG_LEAF_HEATER_POWER_ON_LEVEL:
    retval = Device_Heater::SetPowerOnLevel(parent_instance_id, value);
    break;
  case NODE_TYPE_CONFIG_LEAF_HEATER_BANG_BANG_HYSTERESIS:
    retval = Device_Heater::SetBangBangHysteresis(parent_instance_id, value);
    break;
  case NODE_TYPE_CONFIG_LEAF_HEATER_PID_FUNCTIONAL_RANGE:
    retval = Device_Heater::SetPidFunctionalRange(parent_instance_id, value);
    break;

  default:
    send_app_error_response(PARAM_APP_ERROR_TYPE_FIRMWARE_ERROR,
         PMSG(MSG_ERR_CANNOT_HANDLE_FIRMWARE_CONFIG_REQUEST), __LINE__);
    return false;
  }

  if (retval == APP_ERROR_TYPE_SUCCESS)
    return true;

  generate_response_data_addbyte(retval);
  generate_response_send();
  return false;
}
Пример #22
0
void generate_value(uint8_t node_type, uint8_t parent_instance_id,  uint8_t instance_id)
{
    generate_response_start(RSP_OK);
    char *response_data_buf = (char *)generate_response_data_ptr();
    uint8_t response_data_buf_len = generate_response_data_len();
    int8_t length;
    uint8_t value;

    switch(node_type)
    {
    case NODE_TYPE_CONFIG_LEAF_INPUT_SWITCH_FRIENDLY_NAME:
      if ((length = NVConfigStore::GetDeviceName(PM_DEVICE_TYPE_SWITCH_INPUT, parent_instance_id, response_data_buf, response_data_buf_len)) > 0)
        generate_response_data_addlen(length);
      break;
    case NODE_TYPE_CONFIG_LEAF_INPUT_SWITCH_PIN:
      utoa(Device_InputSwitch::GetPin(parent_instance_id), response_data_buf, 10);
      generate_response_data_addlen(strlen(response_data_buf));
      break;
    case NODE_TYPE_CONFIG_LEAF_INPUT_SWITCH_TRIGGER_LEVEL:
      generate_response_data_addbyte(Device_InputSwitch::GetTriggerLevel(parent_instance_id) ? '1' : '0');
      break;
    case NODE_TYPE_CONFIG_LEAF_INPUT_SWITCH_ENABLE_PULLUP:
      generate_response_data_addbyte(Device_InputSwitch::GetEnablePullup(parent_instance_id) ? '1' : '0');
      break;

    case NODE_TYPE_CONFIG_LEAF_OUTPUT_SWITCH_FRIENDLY_NAME:
      if ((length = NVConfigStore::GetDeviceName(PM_DEVICE_TYPE_SWITCH_OUTPUT, instance_id, response_data_buf, response_data_buf_len)) > 0)
        generate_response_data_addlen(length);
      break;
    case NODE_TYPE_CONFIG_LEAF_OUTPUT_SWITCH_PIN:
      utoa(Device_OutputSwitch::GetPin(parent_instance_id), response_data_buf, 10);
      generate_response_data_addlen(strlen(response_data_buf));
      break;
    case NODE_TYPE_CONFIG_LEAF_OUTPUT_SWITCH_INITIAL_STATE:
      value = Device_OutputSwitch::GetInitialState(instance_id);
      strncpy_P(response_data_buf, stringify_initial_pin_state_value(value), response_data_buf_len);
      generate_response_data_addlen(strlen(response_data_buf));
      break;

    case NODE_TYPE_CONFIG_LEAF_PWM_OUTPUT_FRIENDLY_NAME:
      if ((length = NVConfigStore::GetDeviceName(PM_DEVICE_TYPE_PWM_OUTPUT, instance_id, response_data_buf, response_data_buf_len)) > 0)
        generate_response_data_addlen(length);
      break;
    case NODE_TYPE_CONFIG_LEAF_PWM_OUTPUT_PIN:
      utoa(Device_PwmOutput::GetPin(parent_instance_id), response_data_buf, 10);
      generate_response_data_addlen(strlen(response_data_buf));
      break;
    case NODE_TYPE_CONFIG_LEAF_PWM_OUTPUT_USE_SOFT_PWM:
      generate_response_data_addbyte(Device_PwmOutput::GetSoftPwmState(parent_instance_id) ? '1' : '0');
      break;


    case NODE_TYPE_CONFIG_LEAF_BUZZER_FRIENDLY_NAME:
      if ((length = NVConfigStore::GetDeviceName(PM_DEVICE_TYPE_BUZZER, instance_id, response_data_buf, response_data_buf_len)) > 0)
        generate_response_data_addlen(length);
      break;
    case NODE_TYPE_CONFIG_LEAF_BUZZER_PIN:
      utoa(Device_Buzzer::GetPin(parent_instance_id), response_data_buf, 10);
      generate_response_data_addlen(strlen(response_data_buf));
      break;

    case NODE_TYPE_CONFIG_LEAF_HEATER_FRIENDLY_NAME:
      if ((length = NVConfigStore::GetDeviceName(PM_DEVICE_TYPE_HEATER, instance_id, response_data_buf, response_data_buf_len)) > 0)
        generate_response_data_addlen(length);
      break;
    case NODE_TYPE_CONFIG_LEAF_HEATER_PIN:
      utoa(Device_Heater::GetHeaterPin(parent_instance_id), response_data_buf, 10);
      generate_response_data_addlen(strlen(response_data_buf));
      break;
    case NODE_TYPE_CONFIG_LEAF_HEATER_USE_SOFT_PWM:
      generate_response_data_addbyte(Device_Heater::GetSoftPwmState(parent_instance_id) ? '1' : '0');
      break;
    case NODE_TYPE_CONFIG_LEAF_HEATER_USE_BANG_BANG:
      generate_response_data_addbyte(
        (Device_Heater::GetControlMode(parent_instance_id) == HEATER_CONTROL_MODE_BANG_BANG) ? '1' : '0');
      break;
    case NODE_TYPE_CONFIG_LEAF_HEATER_USE_PID:
      generate_response_data_addbyte(
        (Device_Heater::GetControlMode(parent_instance_id) == HEATER_CONTROL_MODE_PID) ? '1' : '0');
      break;
    case NODE_TYPE_CONFIG_LEAF_HEATER_BANG_BANG_HYSTERESIS:
      if (Device_Heater::GetControlMode(parent_instance_id) == HEATER_CONTROL_MODE_BANG_BANG)
        generate_response_data_addbyte(Device_Heater::GetBangBangHysteresis(parent_instance_id));
      break;
    case NODE_TYPE_CONFIG_LEAF_HEATER_PID_FUNCTIONAL_RANGE:
      if (Device_Heater::GetControlMode(parent_instance_id) == HEATER_CONTROL_MODE_PID)
        generate_response_data_addbyte(Device_Heater::GetPidFunctionalRange(parent_instance_id));
      break;
    // TODO add other heater config

    // Statistics Related
    case NODE_TYPE_STATS_LEAF_RX_PACKET_COUNT:
    {
      extern uint32_t recv_count;
      ultoa(recv_count, response_data_buf, 10);
      generate_response_data_addlen(strlen(response_data_buf));
      break;
    }
    case NODE_TYPE_STATS_LEAF_RX_ERROR_COUNT:
    {
      extern uint16_t recv_errors;
      utoa(recv_errors, response_data_buf, 10);
      generate_response_data_addlen(strlen(response_data_buf));
      break;
    }
    case NODE_TYPE_STATS_LEAF_QUEUE_MEMORY:
    {
      utoa(CommandQueue::GetQueueBufferLength(), response_data_buf, 10);
      generate_response_data_addlen(strlen(response_data_buf));
      break;
    }
    case NODE_TYPE_DEBUG_LEAF_STACK_MEMORY:
    {
      extern uint8_t *startOfStack();
      uint8_t you_are_here;;
      ultoa((unsigned long)&you_are_here - (unsigned long)startOfStack(), response_data_buf, 10);
      generate_response_data_addlen(strlen(response_data_buf));
      break;
    }
    case NODE_TYPE_DEBUG_LEAF_STACK_LOW_WATER_MARK:
    {
      extern uint16_t countStackLowWatermark();
      utoa(countStackLowWatermark(), response_data_buf, 10);
      generate_response_data_addlen(strlen(response_data_buf));
      break;
    }

    default:
      send_app_error_response(PARAM_APP_ERROR_TYPE_FIRMWARE_ERROR,
              PMSG(MSG_ERR_CANNOT_HANDLE_FIRMWARE_CONFIG_REQUEST), __LINE__);
      return;
    }

  generate_response_send();
}
Пример #23
0
void handle_firmware_configuration_request(const char *name, const char* value)
{
  ConfigurationTree tree;

  if (*name == '\0')
  {
    send_app_error_response(PARAM_APP_ERROR_TYPE_BAD_PARAMETER_FORMAT, 0);
    return;
  }

  ConfigurationTreeNode *node = tree.FindNode(name);
  if (node == 0)
  {
    // TODO: improve on this error message
    send_app_error_response(PARAM_APP_ERROR_TYPE_BAD_PARAMETER_VALUE,
                      PMSG(ERR_MSG_CONFIG_NODE_NOT_FOUND), name);
    return;
  }

  if (!node->IsLeafNode())
  {
    // TODO: improve on this error message
    send_app_error_response(PARAM_APP_ERROR_TYPE_BAD_PARAMETER_VALUE,
                      PMSG(ERR_MSG_CONFIG_NODE_NOT_COMPLETE), name);
    return;
  }

  if (value == 0)
  {
    if ((node->GetLeafOperations() & FIRMWARE_CONFIG_OPS_READABLE) == 0)
    {
      send_app_error_response(PARAM_APP_ERROR_TYPE_BAD_PARAMETER_VALUE,
                      PMSG(ERR_MSG_CONFIG_NODE_NOT_READABLE));
      return;
    }
    generate_value(node->GetNodeType(), tree.GetParentNode(node)->GetInstanceId(), node->GetInstanceId());
  }
  else
  {
    if ((node->GetLeafOperations() & FIRMWARE_CONFIG_OPS_WRITEABLE) == 0)
    {
      send_app_error_response(PARAM_APP_ERROR_TYPE_BAD_PARAMETER_VALUE,
                      PMSG(ERR_MSG_CONFIG_NODE_NOT_WRITEABLE));
      return;
    }

    generate_response_start(RSP_APPLICATION_ERROR, 1);

    // ensure value has correct format and then attempt to set
    switch (node->GetLeafSetDataType())
    {
    case LEAF_SET_DATATYPE_PIN:
    {
      long number;
      if (!read_pin(number, value)
        || number < 0 || number > UINT8_MAX)
      {
        send_app_error_response(PARAM_APP_ERROR_TYPE_BAD_PARAMETER_FORMAT,
                                PMSG(ERR_MSG_INVALID_PIN_NUMBER), number);
        return;
      }

      if (!set_uint8_value(node->GetNodeType(), tree.GetParentNode(node)->GetInstanceId(),
          node->GetInstanceId(), number))
      {
        return; // assume that set function has generated an error response
      }
      break;
    }

    case LEAF_SET_DATATYPE_UINT8:
    {
      long number;
      if (!read_number(number, value)
        || number < 0 || number > UINT8_MAX)
      {
        send_app_error_response(PARAM_APP_ERROR_TYPE_BAD_PARAMETER_FORMAT,
                                PMSG(ERR_MSG_EXPECTED_UINT8_VALUE));
        return;
      }

      if (!set_uint8_value(node->GetNodeType(), tree.GetParentNode(node)->GetInstanceId(),
          node->GetInstanceId(), number))
      {
        return; // assume that set function has generated an error response
      }
      break;
    }

    case LEAF_SET_DATATYPE_INT16:
    {
      long number;
      if (!read_number(number, value))
      {
        send_app_error_response(PARAM_APP_ERROR_TYPE_BAD_PARAMETER_FORMAT,
                                PMSG(ERR_MSG_EXPECTED_INT16_VALUE));
        return;
      }

      if (!set_int16_value(node->GetNodeType(), tree.GetParentNode(node)->GetInstanceId(),
          node->GetInstanceId(), number))
      {
        return; // assume that set function has generated an error response
      }
      break;
    }

    case LEAF_SET_DATATYPE_BOOL:
    {
      bool val;
      if (strcmp(value, "true") == 0 || strcmp(value, "1") == 0)
      {
        val = true;
      }
      else if (strcmp(value, "false") == 0 || strcmp(value, "0") == 0)
      {
        val = false;
      }
      else
      {
        send_app_error_response(PARAM_APP_ERROR_TYPE_BAD_PARAMETER_FORMAT,
                                PMSG(ERR_MSG_EXPECTED_BOOL_VALUE));
        return;
      }

      if (!set_bool_value(node->GetNodeType(), tree.GetParentNode(node)->GetInstanceId(),
          node->GetInstanceId(), val))
      {
        return; // assume that set function has generated an error response
      }
      break;
    }

    case LEAF_SET_DATATYPE_STRING:
    {
      if (!set_string_value(node->GetNodeType(), tree.GetParentNode(node)->GetInstanceId(),
          node->GetInstanceId(), value))
      {
        return; // assume that set function has generated an error response
      }
      break;
    }

    case LEAF_SET_DATATYPE_FLOAT:
    {
      char *end;
      float val = strtod(value, &end);
      if (end == value || *end != '\0')
      {
        send_app_error_response(PARAM_APP_ERROR_TYPE_BAD_PARAMETER_FORMAT,
                                PMSG(ERR_MSG_EXPECTED_FLOAT_VALUE));
        return;
      }

      if (!set_float_value(node->GetNodeType(), tree.GetParentNode(node)->GetInstanceId(),
          node->GetInstanceId(), val))
      {
        return; // assume that set function has generated an error response
      }
      break;
    }

    default:
      send_app_error_response(PARAM_APP_ERROR_TYPE_BAD_PARAMETER_FORMAT,
                              PMSG(MSG_ERR_CANNOT_HANDLE_FIRMWARE_CONFIG_REQUEST), __LINE__);
      return;
    }

    send_OK_response();
  }
}
Пример #24
0
void handle_device_status_order()
{
  if (parameter_length < 2)
  {
    send_insufficient_bytes_error_response(2);
    return;
  }

  const uint8_t device_type = parameter_value[0];
  const uint8_t device_number = parameter_value[1];

  uint8_t num_devices = get_num_devices(device_type);
  if (device_number >= num_devices)
  {
    if (num_devices < 0)
      send_app_error_response(PARAM_APP_ERROR_TYPE_INVALID_DEVICE_TYPE,0);
    else
      send_app_error_response(PARAM_APP_ERROR_TYPE_INVALID_DEVICE_NUMBER,0);
    return;
  }

  generate_response_start(RSP_OK, 1);

  switch(device_type)
  {
  case PM_DEVICE_TYPE_SWITCH_INPUT:
    if (!Device_InputSwitch::IsInUse(device_number))
      generate_response_data_addbyte(DEVICE_STATUS_CONFIG_ERROR);
    else
      generate_response_data_addbyte(DEVICE_STATUS_ACTIVE);
    break;
  case PM_DEVICE_TYPE_SWITCH_OUTPUT:
    if (!Device_OutputSwitch::IsInUse(device_number))
      generate_response_data_addbyte(DEVICE_STATUS_CONFIG_ERROR);
    else if (!Device_OutputSwitch::GetEnableState(device_number))
      generate_response_data_addbyte(DEVICE_STATUS_DISABLED);
      // TODO handle inactive state
    else
      generate_response_data_addbyte(DEVICE_STATUS_ACTIVE);
    break;
  case PM_DEVICE_TYPE_PWM_OUTPUT:
    if (!Device_PwmOutput::IsInUse(device_number))
      generate_response_data_addbyte(DEVICE_STATUS_CONFIG_ERROR);
    else if (!Device_PwmOutput::GetActiveState(device_number))
      generate_response_data_addbyte(DEVICE_STATUS_INACTIVE);
    else
      generate_response_data_addbyte(DEVICE_STATUS_ACTIVE);
    break;
  case PM_DEVICE_TYPE_STEPPER:
    if (!AxisInfo::IsInUse(device_number))
      generate_response_data_addbyte(DEVICE_STATUS_CONFIG_ERROR);
    else if (is_stopped)
      generate_response_data_addbyte(DEVICE_STATUS_STOPPED);
    else if (!AxisInfo::GetStepperEnableState(device_number))
      generate_response_data_addbyte(DEVICE_STATUS_INACTIVE);
    else
      generate_response_data_addbyte(DEVICE_STATUS_ACTIVE);
    break;
  case PM_DEVICE_TYPE_HEATER:
    if (!Device_Heater::ValidateTargetTemperature(device_number, 0))
      generate_response_data_addbyte(DEVICE_STATUS_CONFIG_ERROR);
    else if (is_stopped)
      generate_response_data_addbyte(DEVICE_STATUS_STOPPED);
    else if (Device_Heater::GetTargetTemperature(device_number) == 0)
      generate_response_data_addbyte(DEVICE_STATUS_INACTIVE);
    else
      generate_response_data_addbyte(DEVICE_STATUS_ACTIVE);
    break;
  case PM_DEVICE_TYPE_TEMP_SENSOR:
    if (!Device_TemperatureSensor::IsInUse(device_number))
      generate_response_data_addbyte(DEVICE_STATUS_CONFIG_ERROR);
    else
      generate_response_data_addbyte(DEVICE_STATUS_ACTIVE);
    break;
  case PM_DEVICE_TYPE_BUZZER:
    if (!Device_Buzzer::IsInUse(device_number))
      generate_response_data_addbyte(DEVICE_STATUS_CONFIG_ERROR);
    else if (Device_Buzzer::GetActiveState(device_number) == 0)
      generate_response_data_addbyte(DEVICE_STATUS_INACTIVE);
    else
      generate_response_data_addbyte(DEVICE_STATUS_ACTIVE);
    break;
  default:
    send_app_error_response(PARAM_APP_ERROR_TYPE_INVALID_DEVICE_TYPE,0);
    return;
  }
  generate_response_send();
}
Пример #25
0
//
// Top level order handler
//
void process_command()
{
  if (is_stopped && !stopped_is_acknowledged && order_code != ORDER_RESUME)
  {
    send_stopped_response();
    return;
  }

  // we allow a sequence of write configuration commands
  // to be set as configured as a group. For instance,
  // writing the following sequence:
  // device.stepper.0.enable_pin=48
  // device.stepper.0.enable_invert=1
  // ...
  // will only result in the stepper configuration being applied when all
  // attributes have been applied.
  if (firmware_configuration_change_made || !final_firmware_configuration_update_done)
  {
    if (!final_firmware_configuration_update_done
        && (order_code == ORDER_SET_HEATER_TARGET_TEMP
            || order_code == ORDER_SET_OUTPUT_SWITCH_STATE
            || order_code == ORDER_SET_PWM_OUTPUT_STATE
            || order_code == ORDER_SET_OUTPUT_TONE
            || order_code == ORDER_ACTIVATE_STEPPER_CONTROL
            || order_code == ORDER_ENABLE_DISABLE_STEPPERS
            || order_code == ORDER_QUEUE_COMMAND_BLOCKS))
    {
      // assume that once devices are activated then initial firmware
      // configuration is complete and EEPROM state should be updated
      firmware_configuration_change_made = false;
      final_firmware_configuration_update_done = true;
      update_firmware_configuration(true);
    }
    else if (firmware_configuration_change_made
        && order_code != ORDER_WRITE_FIRMWARE_CONFIG_VALUE)
    {
      // update individual device states once firmware configuration
      // block is done
      firmware_configuration_change_made = false;
      update_firmware_configuration(false);
    }
  }

  switch (order_code)
  {
  case ORDER_RESET:
    emergency_stop(PARAM_STOPPED_CAUSE_USER_REQUEST);
    die();
    break;
  case ORDER_RESUME:
    handle_resume_order();
    break;
  case ORDER_REQUEST_INFORMATION:
    handle_request_information_order();
    break;
  case ORDER_DEVICE_COUNT:
    handle_device_count_order();
    break;
  case ORDER_DEVICE_NAME:
    handle_device_name_order();
    break;
  case ORDER_DEVICE_STATUS:
    handle_device_status_order();
    break;
  case ORDER_REQUEST_TEMPERATURE_READING:
    handle_request_temperature_reading_order();
    break;
  case ORDER_GET_HEATER_CONFIGURATION:
    handle_get_heater_configuration_order();
    break;
  case ORDER_CONFIGURE_HEATER:
    handle_configure_heater_order();
    break;
  case ORDER_SET_HEATER_TARGET_TEMP:
    handle_set_heater_target_temperature_order();
    break;
  case ORDER_GET_INPUT_SWITCH_STATE:
    handle_get_input_switch_state_order();
    break;
  case ORDER_SET_OUTPUT_SWITCH_STATE:
    handle_set_output_switch_state_order();
    break;
  case ORDER_SET_PWM_OUTPUT_STATE:
    handle_set_pwm_output_state_order();
    break;
  case ORDER_SET_OUTPUT_TONE:
    handle_set_output_tone_order();
    break;
  case ORDER_WRITE_FIRMWARE_CONFIG_VALUE:
    firmware_configuration_change_made = true;
    handle_write_firmware_configuration_value_order();
    break;
  case ORDER_READ_FIRMWARE_CONFIG_VALUE:
    // note: get_command() already makes the end of the command (ie. name) null-terminated
    handle_firmware_configuration_request((const char *)&parameter_value[0], 0);
    break;
  case ORDER_TRAVERSE_FIRMWARE_CONFIG:
    // note: get_command() already makes the end of the command (ie. name) null-terminated
    handle_firmware_configuration_traversal((const char *)&parameter_value[0]);
    break;
  case ORDER_GET_FIRMWARE_CONFIG_PROPERTIES:
    // note: get_command() already makes the end of the command (ie. name) null-terminated
    handle_firmware_configuration_value_properties((const char *)&parameter_value[0]);
    break;
  case ORDER_EMERGENCY_STOP:
    emergency_stop(PARAM_STOPPED_CAUSE_USER_REQUEST);
    send_OK_response();
    break;
  case ORDER_ACTIVATE_STEPPER_CONTROL:
    handle_activate_stepper_control_order();
    break;
  case ORDER_CONFIGURE_ENDSTOPS:
    handle_configure_endstops_order();
    break;
  case ORDER_ENABLE_DISABLE_STEPPERS:
    handle_enable_disable_steppers_order();
    break;
  case ORDER_ENABLE_DISABLE_ENDSTOPS:
    handle_enable_disable_endstops_order();
    break;
  case ORDER_QUEUE_COMMAND_BLOCKS:
    enqueue_command();
    break;
  case ORDER_CLEAR_COMMAND_QUEUE:
    handle_clear_command_queue_order();
    break;
  case ORDER_CONFIGURE_AXIS_MOVEMENT_RATES:
    handle_configure_axis_movement_rates_order();
    break;
  case ORDER_CONFIGURE_UNDERRUN_PARAMS:
    handle_configure_underrun_params_order();
    break;
  default:
    send_app_error_response(PARAM_APP_ERROR_TYPE_UNKNOWN_ORDER, 0);
    break;
  }

}
Пример #26
0
//
// Top level enqueue command handler
//
void enqueue_command()
{
  uint8_t *ptr = parameter_value;
  uint8_t index = 0;

  if (CommandQueue::GetQueueBufferLength() == 0)
  {
    if (!allocate_command_queue_memory())
    {
      send_app_error_response(PARAM_APP_ERROR_TYPE_FIRMWARE_ERROR, 
                              PMSG(MSG_ERR_INSUFFICIENT_MEMORY));
      return;
    }
  }  
  
  generate_response_start(RSP_ORDER_SPECIFIC_ERROR, QUEUE_ERROR_MSG_OFFSET);
  
  while (ptr < parameter_value + parameter_length)
  {
    const uint8_t length = *ptr++;
    const uint8_t cmd = ptr[0];
    
    if (length < 1 || ptr + length > parameter_value + parameter_length
      || (cmd == QUEUE_COMMAND_ORDER_WRAPPER && length < 2))
    {
      generate_response_msg_addPGM(PMSG(ERR_MSG_INSUFFICENT_BYTES));
      generate_response_msg_add_ascii_number(length);
      send_enqueue_error(QUEUE_COMMAND_ERROR_TYPE_MALFORMED_BLOCK, index);
      return;
    }
    
    uint8_t retval;
    switch (cmd)
    {
    case QUEUE_COMMAND_LINEAR_MOVE:
      retval = enqueue_linear_move_command(ptr+1, length-1);
      break;
    
    case QUEUE_COMMAND_MOVEMENT_CHECKPOINT:
      retval = enqueue_move_checkpoint_command(ptr+1, length-1);
      break;
    
    case QUEUE_COMMAND_DELAY:
      retval = enqueue_delay_command(ptr+1, length-1);
      break;
    
    case QUEUE_COMMAND_ORDER_WRAPPER:
      switch (ptr[1])
      {
      case ORDER_SET_OUTPUT_SWITCH_STATE:
        retval = enqueue_set_output_switch_state_command(ptr+2, length-2);
        break;
      case ORDER_SET_PWM_OUTPUT_STATE:
        retval = enqueue_set_pwm_output_state_command(ptr+2, length-2);
        break;
      case ORDER_SET_OUTPUT_TONE:
        retval = enqueue_set_output_tone_command(ptr+2, length-2);
        break;
      case ORDER_SET_HEATER_TARGET_TEMP:
        retval = enqueue_set_heater_target_temperature_command(ptr+2, length-2);
        break;
      case ORDER_ENABLE_DISABLE_STEPPERS:
        retval = enqueue_set_stepper_enable_state_command(ptr+2, length-2);
        break;
      case ORDER_ENABLE_DISABLE_ENDSTOPS:
        retval = enqueue_set_endstop_enable_state_command(ptr+2, length-2);
        break;
      default:
        generate_response_msg_addPGM(PMSG(ERR_MSG_QUEUE_ORDER_NOT_PERMITTED));
        generate_response_msg_add_ascii_number(ptr[1]);
        send_enqueue_error(QUEUE_COMMAND_ERROR_TYPE_ERROR_IN_COMMAND_BLOCK, index, PARAM_APP_ERROR_TYPE_UNKNOWN_ORDER);
        return;
      }
      break;
      
    default:
      send_enqueue_error(QUEUE_COMMAND_ERROR_TYPE_UNKNOWN_COMMAND_BLOCK, index);
      return;
    }
    if (retval != ENQUEUE_SUCCESS)
    {
      send_enqueue_error(QUEUE_COMMAND_ERROR_TYPE_ERROR_IN_COMMAND_BLOCK, index, retval);
      return;
    }
    ptr += length;
    index += 1;
  }
  
  uint16_t remaining_slots;
  uint16_t current_command_count;
  uint16_t total_command_count;
  CommandQueue::GetQueueInfo(remaining_slots, current_command_count, total_command_count);
  
  generate_response_start(RSP_OK);
  generate_response_data_add(remaining_slots);
  generate_response_data_add(current_command_count);
  generate_response_data_add(total_command_count);
  generate_response_send(); 
}
Пример #27
0
void loop()
{

    // quickly scan through baudrates until we receive a valid packet within timeout period
#if 0 // the baud rate change still isn't working for some reason.
    if (autodetect_baudrates_index != 0xFF)
    {
        if (millis() - first_rcvd_time > MAX_FRAME_COMPLETION_DELAY_MS * 1.5) // make sure its not a multiple of 100ms
        {
            PSERIAL.end();
            PSERIAL.flush();
            autodetect_baudrates_index += 1;
            if (autodetect_baudrates_index >= NUM_ARRAY_ELEMENTS(autodetect_baudrates))
                autodetect_baudrates_index = 0;
            PSERIAL.begin(pgm_read_dword(&autodetect_baudrates[autodetect_baudrates_index]));
            recv_buf_len = 0;
            first_rcvd_time = millis();
        }
    }
#endif

    if (get_command())
    {
        autodetect_baudrates_index = 0xFF;
        last_order_time = millis();
        is_host_active = true;
        order_code = recv_buf[PM_ORDER_BYTE_OFFSET];
        control_byte = recv_buf[PM_CONTROL_BYTE_OFFSET];
        parameter_length = recv_buf[PM_LENGTH_BYTE_OFFSET]-2;

#if TRACE_ORDER
        DEBUGPGM("\nOrder(");
        DEBUG_F(order_code, HEX);
        DEBUGPGM(", plen=");
        DEBUG_F(parameter_length, DEC);
        DEBUGPGM(", cb=");
        DEBUG_F(control_byte, HEX);
        DEBUGPGM("):");
        for (uint8_t i = 0; i < parameter_length; i++)
        {
            DEBUG_CH(' ');
            DEBUG_F(recv_buf[i], HEX);
        }
        DEBUG_EOL();
#endif

        // does this match the sequence number of the last reply
        if ((control_byte & CONTROL_BYTE_SEQUENCE_NUMBER_MASK) ==
                (reply_control_byte & CONTROL_BYTE_SEQUENCE_NUMBER_MASK)
                && (control_byte & CONTROL_BYTE_ORDER_HOST_RESET_BIT) == 0
                && reply_control_byte != 0xFF)
        {
            if (!reply_started)
            {
                // resend last response
                reply_started = true;
                generate_response_send();
            }
            else
            {
                // this is an unexpected error case (matching sequence number but nothing to send)
                generate_response_transport_error_start(PARAM_FRAME_RECEIPT_ERROR_TYPE_UNABLE_TO_ACCEPT,
                                                        control_byte);
                generate_response_msg_addPGM(PMSG(MSG_ERR_NO_RESPONSE_TO_SEND));
                generate_response_send();
            }
        }
        else
        {
            reply_sent = false;

            process_command();

            if (!reply_sent)
            {
                send_app_error_response(PARAM_APP_ERROR_TYPE_FIRMWARE_ERROR,
                                        PMSG(MSG_ERR_NO_RESPONSE_GENERATED));
            }
        }
        recv_buf_len = 0;
    }

    // Idle loop activities

    // Check if heaters need to be updated?
    if (temp_meas_ready)
    {
        Device_TemperatureSensor::UpdateTemperatureSensors();
        Device_Heater::UpdateHeaters();
    }

    // Now check low-priority stuff
    uint32_t now = millis();
    if (now - last_idle_check > 1000) // checked every second
    {
#if !DEBUG_DISABLE_HOST_TIMEOUT
        // have we heard from the host within the timeout?
        if (now - last_order_time > (HOST_TIMEOUT_SECS * 1000) && is_host_active)
        {
            is_host_active = false;
            if (!is_stopped)
            {
                emergency_stop(PARAM_STOPPED_CAUSE_HOST_TIMEOUT);
            }
        }
#endif
#if TRACE_MOVEMENT
        print_movement_ISR_state();
#endif
        last_idle_check = now;
    }
}