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(); }
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(); }
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_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(); }
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(); }
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(); }
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(); }
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(); }
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(); }
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(); } }
// // 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(); }
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; }
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(); }
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(); } }
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(); }
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(); }