#ifndef APP_H #define APP_H #include #include #include #include #include "hx711_sensor.h" #ifndef HX711_SCK_PIN #define HX711_SCK_PIN 17 #endif #ifndef HX711_DOUT_PIN #define HX711_DOUT_PIN 18 #endif #ifndef HX711_REFERENCE_WEIGHT_GRAMS #define HX711_REFERENCE_WEIGHT_GRAMS 100.0f #endif constexpr const char *kPrefsNamespace = "filgauge"; constexpr const char *kDefaultInventreeBaseUrl = "http://192.168.0.3:1337"; constexpr const char *kDefaultInventreeUsername = "scale"; constexpr const char *kDefaultInventreePassword = "scale"; constexpr uint32_t kUiRefreshMs = 200; constexpr uint32_t kWifiPollMs = 500; constexpr uint32_t kWifiConnectTimeoutMs = 20000; constexpr uint32_t kSensorTimeoutMs = 1500; constexpr uint8_t kAverageSamples = 16; constexpr uint8_t kRawFilterWindow = 8; constexpr uint8_t kBatchCodeMaxLength = 4; constexpr float kRawFilterAlpha = 0.20f; constexpr float kWeightStepHysteresisGrams = 0.75f; constexpr lv_coord_t kScreenMargin = 12; constexpr lv_coord_t kPanelRadius = 24; constexpr lv_coord_t kContentPadding = 24; constexpr lv_coord_t kContentWidth = 608; constexpr lv_coord_t kContentHeight = 456; constexpr lv_coord_t kContentInnerWidth = kContentWidth - (kContentPadding * 2); constexpr lv_coord_t kTextEditorPanelHeight = 112; constexpr lv_coord_t kTextEditorGap = 12; constexpr lv_coord_t kTextEditorMinKeyboardHeight = 240; enum class PageId : uint8_t { Weight = 0, Calibration = 1, Wifi = 2, Inventree = 3, Count = 4 }; struct CalibrationData { int32_t offset = 0; float scale = 0.0f; bool has_offset = false; }; struct WifiData { String ssid; String password; bool connecting = false; wl_status_t last_status = WL_IDLE_STATUS; uint32_t connect_started_ms = 0; uint32_t next_poll_ms = 0; }; struct InventreeMatch { int id = 0; int part_id = 0; float quantity = 0.0f; String location; String part_name; String batch; String spool_weight; }; constexpr size_t kInventreeMaxMatches = 8; struct InventreeData { String base_url; String token; String batch; String status_text; String result_text; int total_matches = 0; int stored_matches = 0; int selected_match = -1; InventreeMatch matches[kInventreeMaxMatches]; }; struct UiRefs { lv_obj_t *screen = nullptr; lv_obj_t *nav_panel = nullptr; lv_obj_t *content_panel = nullptr; lv_obj_t *nav_buttons[static_cast(PageId::Count)] = {}; lv_obj_t *nav_labels[static_cast(PageId::Count)] = {}; lv_obj_t *pages[static_cast(PageId::Count)] = {}; lv_obj_t *status_chip = nullptr; lv_obj_t *status_label = nullptr; lv_obj_t *weight_label = nullptr; lv_obj_t *weight_unit_label = nullptr; lv_obj_t *mode_label = nullptr; lv_obj_t *weight_note_label = nullptr; lv_obj_t *weight_raw_value = nullptr; lv_obj_t *workflow_batch_ta = nullptr; lv_obj_t *workflow_spool_weight_value = nullptr; lv_obj_t *workflow_filament_weight_value = nullptr; lv_obj_t *workflow_stock_name_label = nullptr; lv_obj_t *workflow_stock_meta_label = nullptr; lv_obj_t *cal_offset_value = nullptr; lv_obj_t *cal_scale_value = nullptr; lv_obj_t *cal_raw_value = nullptr; lv_obj_t *cal_note_label = nullptr; lv_obj_t *wifi_status_value = nullptr; lv_obj_t *wifi_ip_value = nullptr; lv_obj_t *wifi_ssid_ta = nullptr; lv_obj_t *wifi_password_ta = nullptr; lv_obj_t *wifi_note_label = nullptr; lv_obj_t *wifi_keyboard = nullptr; lv_obj_t *text_editor_overlay = nullptr; lv_obj_t *text_editor_panel = nullptr; lv_obj_t *text_editor_title = nullptr; lv_obj_t *text_editor_ta = nullptr; lv_obj_t *text_editor_cancel_button = nullptr; lv_obj_t *text_editor_apply_button = nullptr; lv_obj_t *text_editor_target = nullptr; lv_obj_t *inventree_url_ta = nullptr; lv_obj_t *inventree_token_ta = nullptr; lv_obj_t *inventree_batch_ta = nullptr; lv_obj_t *inventree_status_value = nullptr; lv_obj_t *inventree_result_value = nullptr; lv_obj_t *inventree_note_label = nullptr; }; extern Hx711Sensor hx711; extern Preferences prefs; extern CalibrationData calibration; extern WifiData wifi_data; extern InventreeData inventree_data; extern UiRefs ui; extern PageId active_page; extern bool have_sample; extern bool sensor_online; extern float filtered_raw; extern int32_t last_raw; extern int32_t raw_samples[kRawFilterWindow]; extern uint8_t raw_sample_count; extern uint8_t raw_sample_index; extern int32_t displayed_weight_grams; extern bool displayed_weight_valid; extern uint32_t last_sample_ms; extern uint32_t next_ui_refresh_ms; extern uint32_t last_lv_tick_ms; constexpr size_t pageIndex(PageId page) { return static_cast(page); } void saveCalibration(); void loadCalibration(); void saveWifiConfig(); void loadWifiConfig(); void saveInventreeConfig(); void loadInventreeConfig(); float getCurrentWeightGrams(); bool getFilamentWeightGrams(int32_t &grams); void performTare(); void performCalibration(float reference_grams); void clearCalibration(); void sampleSensor(); void connectWifi(const String &ssid, const String &password, bool save_credentials); void connectWifiFromForm(bool save_credentials); void disconnectWifi(); void handleWifi(); bool inventreeConfigured(); void clearInventreeMatches(); void saveInventreeSettingsFromForm(); void testInventreeApi(); void findInventreeStockByBatch(); void selectInventreeMatch(int delta); void pushMeasuredWeightToInventree(); void setLabelTextIfChanged(lv_obj_t *label, const char *text); void setWeightStatus(const char *text, lv_color_t color); void setWeightNote(const char *text); void setCalibrationNote(const char *text); void setWifiNote(const char *text); void setInventreeNote(const char *text); void hideKeyboard(); void refreshUi(); void updateWifiUi(bool force = false); void updateInventreeLabels(); void setActivePage(PageId page); void buildUi(); #endif