#include #include #include #include #include #include #include #include #include #include #include #include #include "app/app.h" #include "app/status.h" #include "wifi.h" #define WIFI_ACTION_NONE -1 #define WIFI_ACTION_IDLE 0 #define WIFI_ACTION_START 1 #define WIFI_ACTION_STOP 2 #define WIFI_ACTION_SCAN 3 #define WIFI_ACTION_CONNECT 4 #define WIFI_ACTION_DISCONNECT 5 static void handle_status(unsigned char type, unsigned char *buffer, uint16_t size) { EVEPage *page; WIFIStatus *status; int action; int rv; if (app_current_view() != wifi_app) goto handle_status_fin; page = (EVEPage *)app_search_view("main"); status = page->v.param; rv = eos_wifi_status_parse(buffer, size, &status->status, status->ip_addr, status->ssid); if (rv) { APP_LOG(APP_LOG_ERR, "BAD STATUS ERR:%d\n", rv); goto handle_status_fin; } action = WIFI_ACTION_NONE; switch (status->action) { case WIFI_ACTION_IDLE: { break; } case WIFI_ACTION_START: { if (status->status == EOS_WIFI_STATUS_DISCONNECTED) { action = WIFI_ACTION_SCAN; } break; } case WIFI_ACTION_STOP: { if (status->status == EOS_WIFI_STATUS_OFF) { action = WIFI_ACTION_IDLE; } break; } case WIFI_ACTION_CONNECT: { if (status->status == EOS_WIFI_STATUS_CONNECTED) { action = WIFI_ACTION_IDLE; } else { app_status_set_msg("CONNECT FAILED"); action = WIFI_ACTION_SCAN; } break; } case WIFI_ACTION_DISCONNECT: { if (status->status == EOS_WIFI_STATUS_DISCONNECTED) { action = WIFI_ACTION_SCAN; } break; } case WIFI_ACTION_SCAN: { /* ignore status updates during scan */ goto handle_status_fin; } } if (action == WIFI_ACTION_SCAN) { rv = eos_wifi_scan(buffer, 0); if (rv) { APP_LOG(APP_LOG_ERR, "WIFI SCAN ERR:%d\n", rv); goto handle_status_fin; } buffer = NULL; } wifi_update_status(page, action); app_refresh(); handle_status_fin: if (buffer) eos_net_free(buffer, 0); } static void handle_scan(unsigned char type, unsigned char *buffer, uint16_t size) { EVEPage *page; EVESelectWidget *selw; if (app_current_view() != wifi_app) goto handle_scan_fin; page = (EVEPage *)app_search_view("main"); wifi_update_scanr(page, buffer + 1, size - 1); app_refresh(); handle_scan_fin: eos_net_free(buffer, 0); } static void widget_ssid_draw(EVEFreeWidget *widget) { EVEWidget *_widget = &widget->w; WIFIStatus *status = _widget->page->v.param; if (_widget->flags & EVE_WIDGET_FLAG_BUSY) { eve_freew_tag(widget); eve_cmd(CMD_TEXT, "hhhhs", _widget->g.x, _widget->g.y, app_font()->id, 0, "BUSY!"); } else if (status->status >= EOS_WIFI_STATUS_CONNECTED) { char text[51]; if (status->status == EOS_WIFI_STATUS_CONNECTED) { strcpy(text, status->ssid); } else { sprintf(text, "%s (%d.%d.%d.%d)", status->ssid, status->ip_addr[0], status->ip_addr[1], status->ip_addr[2], status->ip_addr[3]); } eve_freew_tag(widget); eve_cmd(CMD_TEXT, "hhhhs", _widget->g.x, _widget->g.y, app_font()->id, 0, text); } } static int widget_ssid_touch(EVEFreeWidget *widget, EVETouch *touch, uint16_t evt) { if (evt & EVE_TOUCH_ETYPE_POINT_UP) { EVEPage *page = widget->w.page; int rv; rv = eos_wifi_disconnect(NULL, 0); if (!rv) wifi_update_status(page, WIFI_ACTION_DISCONNECT); return 1; } return 0; } static int widget_enable_touch(EVEWidget *_widget, EVETouch *touch, uint16_t evt) { EVEToggleWidget *widget = (EVEToggleWidget *)_widget; EVEPage *page = _widget->page; WIFIStatus *status = page->v.param; if (evt & EVE_TOUCH_ETYPE_TAG_UP) { int rv; if (widget->state) { rv = eos_wifi_stop(NULL, 0); if (!rv) wifi_update_status(page, WIFI_ACTION_STOP); } else { rv = eos_wifi_start(NULL, 0); if (!rv) wifi_update_status(page, WIFI_ACTION_START); } if (rv) (APP_LOG_ERR, "WIFI START ERR:%d\n", rv); return 1; } return 0; } void wifi_init(void) { eos_wifi_set_handler(EOS_WIFI_MTYPE_STATUS, handle_status); eos_wifi_set_handler(EOS_WIFI_MTYPE_SCAN, handle_scan); } int wifi_app(EVEWindow *window, EVEViewStack *stack) { EVEFormSpec spec[] = { APP_SPACERW(APP_SCREEN_W,20), { .label.title = "Enable:", .label.g.w = APP_SCREEN_W - 100, .widget.type = EVE_WIDGET_TYPE_TOGGLE, .widget.g.w = 100, .widget.tspec.toggle.labels = "off\xffon", }, { .widget.type = EVE_WIDGET_TYPE_FREE, .widget.g.h = eve_font_h(app_font()), .widget.tspec.free.draw = widget_ssid_draw, .widget.tspec.free.touch = widget_ssid_touch, }, { .label.g.w = APP_SCREEN_W, .label.title = "Select network:", .widget.type = EVE_WIDGET_TYPE_SELECT, .widget.g.w = APP_SCREEN_W, .widget.tspec.select.option_size = EOS_WIFI_MAX_SCAN_RECORDS * EOS_WIFI_SIZE_SSID, }, APP_SPACERW(APP_SCREEN_W,50), { .label.title = "Password:", .widget.type = EVE_WIDGET_TYPE_STR, .widget.tspec.str.str_size = EOS_WIFI_SIZE_PWD, }, }; EVEPage *page; EVEWidget *widget; WIFIStatus *status; int rv; int action; page = eve_form_create(window, stack, spec, APP_SPEC_SIZE(spec), wifi_uievt, wifi_close); if (page == NULL) { rv = EVE_ERR_NOMEM; APP_LOG(APP_LOG_ERR, "OUT OF MEMORY\n"); return rv; } status = eve_malloc(sizeof(WIFIStatus)); if (status == NULL) { rv = EVE_ERR_NOMEM; eve_form_destroy(page); APP_LOG(APP_LOG_ERR, "OUT OF MEMORY\n"); return rv; } page->v.param = status; widget = eve_page_widget(page, 0); widget->touch = widget_enable_touch; rv = eos_wifi_status(&status->status, status->ip_addr, status->ssid, NULL); if (rv) { wifi_close(page); APP_LOG(APP_LOG_ERR, "BAD STATUS ERR:%d\n", rv); return rv; } action = WIFI_ACTION_IDLE; if (status->status == EOS_WIFI_STATUS_DISCONNECTED) { rv = eos_wifi_scan(NULL, 0); if (rv) { wifi_close(page); APP_LOG(APP_LOG_ERR, "WIFI SCAN ERR:%d\n", rv); return rv; } action = WIFI_ACTION_SCAN; } wifi_update_status(page, action); return EVE_OK; } int wifi_uievt(EVEPage *page, uint16_t evt, void *param) { int ret = 0; switch (evt) { case EVE_UIEVT_WIDGET_FOCUS_OUT: { if (param == eve_page_widget(page, 3)) { EVESelectWidget *selw; utf8_t *ssid; selw = (EVESelectWidget *)eve_page_widget(page, 2); ssid = eve_selectw_option_selected(selw); if (ssid) { EVEStrWidget *strw = param; WIFIStatus *status = page->v.param; int rv; rv = eos_wifi_connect((char *)ssid, (char *)strw->str, NULL, 0); if (!rv) wifi_update_status(page, WIFI_ACTION_CONNECT); if (rv) APP_LOG(APP_LOG_ERR, "WIFI CONNECT ERR:%d\n", rv); } } break; } default: { ret = eve_form_uievt(page, evt, param); break; } } return ret; } void wifi_close(EVEPage *page) { eve_free(page->v.param); eve_form_destroy(page); } void wifi_update_status(EVEPage *page, int action) { WIFIStatus *status = page->v.param; EVEWidget *widget; int i; /* enable */ widget = eve_page_widget(page, 0); if (status->status == EOS_WIFI_STATUS_OFF) { ((EVEToggleWidget *)widget)->state = 0; } else { ((EVEToggleWidget *)widget)->state = 1; } /* ssid */ widget = eve_page_widget(page, 1); eve_widget_clr_flags(widget, (EVE_WIDGET_FLAG_HIDDEN | EVE_WIDGET_FLAG_BUSY)); if (action >= WIFI_ACTION_SCAN) { eve_widget_set_flags(widget, EVE_WIDGET_FLAG_BUSY); } if ((status->status < EOS_WIFI_STATUS_CONNECTED) && !(widget->flags & EVE_WIDGET_FLAG_BUSY)) { eve_widget_set_flags(widget, EVE_WIDGET_FLAG_HIDDEN); } /* select network and password */ widget = eve_page_widget(page, 2); for (i=0; i<3; i++) { eve_widget_set_flags(widget, EVE_WIDGET_FLAG_HIDDEN); widget = eve_widget_next(widget); } if (action != WIFI_ACTION_NONE) status->action = action; eve_form_update_g(page, NULL); } void wifi_update_scanr(EVEPage *page, unsigned char *buffer, size_t size) { WIFIStatus *status = page->v.param; EVEWidget *widget; EVESelectWidget *selw; int i, rv; selw = (EVESelectWidget *)eve_page_widget(page, 2); rv = eve_selectw_set_option(selw, buffer, size); if (rv) { APP_LOG(APP_LOG_ERR, "BAD SCAN ERR:%d\n", rv); return; } /* ssid */ widget = eve_page_widget(page, 1); eve_widget_clr_flags(widget, EVE_WIDGET_FLAG_BUSY); eve_widget_set_flags(widget, EVE_WIDGET_FLAG_HIDDEN); /* select network and password */ widget = eve_page_widget(page, 2); for (i=0; i<3; i++) { eve_widget_clr_flags(widget, EVE_WIDGET_FLAG_HIDDEN); widget = eve_widget_next(widget); } status->action = WIFI_ACTION_IDLE; eve_form_update_g(page, NULL); }