Auto-Complete Association

本文介绍如何在Rails应用中实现自动补全功能,通过在产品视图中使用该功能来选择Thing模型的相关属性,包括名称、材料和尺寸等字段。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

针对有些情况下下拉菜单过长导致选择不便,此处我将演示通过输入文字自动补全来选择

 

我这里要在product的view中自动补全thing

 

Gemfile中

 

gem 'rails3-jquery-autocomplete'

 

routes中

 

resources :products do
  collection do
    get :autocomplete_thing_name
  end
end

 

thing.rb中(这里想显示name、material、size三个字段)

 

def name_with_material_and_size
  "#{name} - #{material} - #{size}"
end

 

products_controller中

 

autocomplete :thing, :name, :full => true, :display_value => :name_with_material_and_size, :extra_data => [:name, :material, :size]
 

products.js.coffee

 

jQuery ->
  $("#autocomplete_thing_name").bind('railsAutocomplete.select', (e,data)->
    $("#product_thing_id").val(data.item.id)
  )
 

product的view中

 

= f.hidden_field :thing_id
= f.input :thing_id, :as => :autocomplete, :url => autocomplete_thing_name_products_path, :input_html => {:id => 'autocomplete_thing_name', :name => "thing_name"}
#include <esp_wifi.h> #include <esp_event.h> #include <esp_log.h> #include <esp_timer.h> #include <esp_sleep.h> // 状态枚举 enum class WifiState { INIT, // 初始化 SCANNING, // AP扫描 AUTHENTICATING, // 认证中 ASSOCIATING, // 关联中 CONNECTED, // 已连接 DISCONNECTED, // 断开连接 ROAMING_SCAN, // 漫游扫描 ROAMING_AUTH, // 漫游认证 ROAMING_ASSOC, // 漫游关联 LIGHT_SLEEP, // 轻睡眠模式 DEEP_SLEEP // 深睡眠模式 }; // 事件枚举 enum class WifiEvent { SCAN_COMPLETE, // 扫描完成 AUTH_REQ, // 认证请求 AUTH_RESP, // 认证响应 ASSOC_REQ, // 关联请求 ASSOC_RESP, // 关联响应 CONNECTED, // 连接成功 DISCONNECTED, // 连接断开 ROAM_TRIGGER, // 漫游触发 BEACON_LOST, // 信标丢失 SLEEP_ENTER, // 进入睡眠 WAKE_UP // 唤醒事件 }; class WiFiStateMachine { private: // 当前状态 WifiState currentState = WifiState::INIT; // 状态转移表(状态 -> 事件 -> 新状态) std::map<WifiState, std::map<WifiEvent, WifiState>> transitionTable = { {WifiState::INIT, { {WifiEvent::SCAN_COMPLETE, WifiState::SCANNING} }}, {WifiState::SCANNING, { {WifiEvent::AUTH_REQ, WifiState::AUTHENTICATING} }}, {WifiState::AUTHENTICATING, { {WifiEvent::AUTH_RESP, WifiState::ASSOCIATING}, {WifiEvent::DISCONNECTED, WifiState::DISCONNECTED} }}, {WifiState::ASSOCIATING, { {WifiEvent::ASSOC_RESP, WifiState::CONNECTED}, {WifiEvent::DISCONNECTED, WifiState::DISCONNECTED} }}, {WifiState::CONNECTED, { {WifiEvent::DISCONNECTED, WifiState::DISCONNECTED}, {WifiEvent::ROAM_TRIGGER, WifiState::ROAMING_SCAN}, {WifiEvent::SLEEP_ENTER, WifiState::LIGHT_SLEEP} }}, {WifiState::ROAMING_SCAN, { {WifiEvent::AUTH_REQ, WifiState::ROAMING_AUTH} }}, {WifiState::ROAMING_AUTH, { {WifiEvent::AUTH_RESP, WifiState::ROAMING_ASSOC} }}, {WifiState::ROAMING_ASSOC, { {WifiEvent::ASSOC_RESP, WifiState::CONNECTED} }}, {WifiState::LIGHT_SLEEP, { {WifiEvent::WAKE_UP, WifiState::CONNECTED}, {WifiEvent::BEACON_LOST, WifiState::SCANNING} }} }; // 低功耗配置参数 struct { int beacon_interval = 5000; // 默认信标监测间隔(ms) int sleep_delay = 300; // 进入休眠等待时间(s) int roam_threshold = -75; // 漫游触发RSSI阈值(dBm) int roam_scan_duration = 100; // 漫游扫描时长(ms) } powerConfig; // 连接稳定性计数器 int stableCounter = 0; const int STABLE_THRESHOLD = 5; // 连续稳定计数阈值 // 定时器句柄 esp_timer_handle_t beacon_timer; esp_timer_handle_t sleep_timer; /** * 处理状态转移 * @param event 触发事件 */ void handleEvent(WifiEvent event) { auto stateTransitions = transitionTable.find(currentState); if (stateTransitions != transitionTable.end()) { auto newState = stateTransitions->second.find(event); if (newState != stateTransitions->second.end()) { // 执行状态转移前的清理 exitStateActions(currentState); // 更新状态 currentState = newState->second; ESP_LOGI("StateMachine", "Transition: %s -> %s", stateToString(currentState).c_str(), stateToString(newState->second).c_str()); // 执行新状态的入口动作 enterStateActions(newState->second); } } } /** * 状态退出动作 * @param state 退出的状态 */ void exitStateActions(WifiState state) { switch(state) { case WifiState::SCANNING: esp_timer_stop(beacon_timer); break; case WifiState::LIGHT_SLEEP: // 唤醒后恢复活动 esp_sleep_disable_wakeup_source(ESP_SLEEP_WAKEUP_TIMER); break; default: break; } } /** * 状态进入动作 * @param state 进入的状态 */ void enterStateActions(WifiState state) { switch(state) { case WifiState::SCANNING: startScan(); break; case WifiState::AUTHENTICATING: sendAuthRequest(); break; case WifiState::CONNECTED: startBeaconMonitoring(); checkConnectionStability(); break; case WifiState::ROAMING_SCAN: startRoamScan(); break; case WifiState::LIGHT_SLEEP: enterLightSleep(); break; default: break; } } /** * 启动AP扫描 */ void startScan() { wifi_scan_config_t scan_config = { .ssid = nullptr, .bssid = nullptr, .channel = 0, .show_hidden = true, .scan_type = WIFI_SCAN_TYPE_ACTIVE, .scan_time = { .active = 120 } // 120ms主动扫描 }; ESP_ERROR_CHECK(esp_wifi_scan_start(&scan_config, false)); } /** * 启动低功耗漫游扫描 */ void startRoamScan() { wifi_scan_config_t scan_config = { .scan_type = WIFI_SCAN_TYPE_PASSIVE, // 被动扫描省电 .scan_time = { .passive = powerConfig.roam_scan_duration } }; ESP_ERROR_CHECK(esp_wifi_scan_start(&scan_config, false)); } /** * 进入轻睡眠模式(ESP32优化) */ void enterLightSleep() { // 配置唤醒源 esp_sleep_enable_timer_wakeup(powerConfig.sleep_delay * 1000000); esp_sleep_enable_wifi_wakeup(); // 保存当前状态 WifiState preSleepState = currentState; // 进入轻睡眠(保留WiFi连接) esp_light_sleep_start(); // 唤醒后恢复状态 currentState = preSleepState; handleEvent(WifiEvent::WAKE_UP); } /** * 动态调整信标监测周期 */ void adjustBeaconMonitoring() { // 获取当前信号强度 wifi_ap_record_t ap_info; esp_wifi_sta_get_ap_info(&ap_info); int8_t rssi = ap_info.rssi; // 根据信号质量调整监测频率 if (rssi > -60) { // 强信号 powerConfig.beacon_interval = 10000; // 10秒 stableCounter++; } else if (rssi > -70) { // 中等信号 powerConfig.beacon_interval = 5000; // 5秒 stableCounter = 0; } else { // 弱信号 powerConfig.beacon_interval = 2000; // 2秒 stableCounter = 0; } // 重启定时器 esp_timer_stop(beacon_timer); esp_timer_start_periodic(beacon_timer, powerConfig.beacon_interval * 1000); } /** * 检查连接稳定性 */ void checkConnectionStability() { if (stableCounter >= STABLE_THRESHOLD) { handleEvent(WifiEvent::SLEEP_ENTER); } } /** * 状态转字符串(调试用) */ std::string stateToString(WifiState state) { const std::map<WifiState, std::string> stateMap = { {WifiState::INIT, "INIT"}, {WifiState::SCANNING, "SCANNING"}, {WifiState::AUTHENTICATING, "AUTHENTICATING"}, {WifiState::ASSOCIATING, "ASSOCIATING"}, {WifiState::CONNECTED, "CONNECTED"}, {WifiState::DISCONNECTED, "DISCONNECTED"}, {WifiState::ROAMING_SCAN, "ROAMING_SCAN"}, {WifiState::ROAMING_AUTH, "ROAMING_AUTH"}, {WifiState::ROAMING_ASSOC, "ROAMING_ASSOC"}, {WifiState::LIGHT_SLEEP, "LIGHT_SLEEP"}, {WifiState::DEEP_SLEEP, "DEEP_SLEEP"} }; return stateMap.at(state); } public: WiFiStateMachine() { // 初始化定时器 esp_timer_create_args_t beacon_timer_args = { .callback = [](void* arg) { static_cast<WiFiStateMachine*>(arg)->checkBeacon(); }, .arg = this, .name = "beacon_timer" }; esp_timer_create(&beacon_timer_args, &beacon_timer); esp_timer_create_args_t sleep_timer_args = { .callback = [](void* arg) { static_cast<WiFiStateMachine*>(arg)->handleEvent(WifiEvent::SLEEP_ENTER); }, .arg = this, .name = "sleep_timer" }; esp_timer_create(&sleep_timer_args, &sleep_timer); // 注册WiFi事件处理 esp_event_handler_register(WIFI_EVENT, ESP_EVENT_ANY_ID, [](void* arg, esp_event_base_t base, int32_t id, void* data) { auto self = static_cast<WiFiStateMachine*>(arg); switch(id) { case WIFI_EVENT_STA_CONNECTED: self->handleEvent(WifiEvent::CONNECTED); break; case WIFI_EVENT_STA_DISCONNECTED: self->handleEvent(WifiEvent::DISCONNECTED); break; case WIFI_EVENT_STA_AUTHMODE_CHANGE: // 认证处理 break; } }, this); } /** * 启动状态机 */ void start() { handleEvent(WifiEvent::SCAN_COMPLETE); } /** * 信标监测函数 */ void checkBeacon() { if (currentState == WifiState::CONNECTED) { // 检查信标是否丢失 if (/* 信标丢失检测逻辑 */) { handleEvent(WifiEvent::BEACON_LOST); } // 动态调整监测频率 adjustBeaconMonitoring(); // 检查漫游触发条件 wifi_ap_record_t ap_info; esp_wifi_sta_get_ap_info(&ap_info); if (ap_info.rssi < powerConfig.roam_threshold) { handleEvent(WifiEvent::ROAM_TRIGGER); } } } }; // 初始化WiFi(乐鑫专用API) extern "C" void app_main() { // WiFi初始化 wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT(); ESP_ERROR_CHECK(esp_wifi_init(&cfg)); ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA)); // 启动状态机 WiFiStateMachine stateMachine; stateMachine.start(); }不用针对乐鑫芯片写,直接用C++写代码,该有的功能要完整,注释要详细
06-16
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值