Skip to content

Commit

Permalink
keira: WIP on WiFi config app
Browse files Browse the repository at this point in the history
  • Loading branch information
and3rson committed Mar 12, 2024
1 parent 3e572d7 commit f9c9e79
Show file tree
Hide file tree
Showing 5 changed files with 161 additions and 59 deletions.
73 changes: 61 additions & 12 deletions firmware/keira/src/apps/demos/wifi_scan.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
#include <WiFi.h>

#include "wifi_scan.h"
#include "servicemanager.h"
#include "services/network.h"

WifiScanApp::WifiScanApp() : App("WiFi Scanner") {
}
Expand Down Expand Up @@ -35,24 +37,71 @@ void WifiScanApp::run() {
networks[i] = WiFi.SSID(i);
}

// TODO: FreeRTOS experiment
// lilka::ui_menu(canvas, "Мережі", networks, count, 0);
lilka::Menu menu("Мережі");
for (int16_t i = 0; i < count; i++) {
menu.addItem(networks[i]);
}
menu.draw(canvas);
queueDraw();
menu.addItem("<< Назад");
count++;
while (1) {
menu.update();
menu.draw(canvas);
int index = -1;
while (index == -1) {
menu.update();
menu.draw(canvas);
queueDraw();
index = menu.getSelectedIndex();
}
if (index == count - 1) {
return;
}

String ssid = networks[index];

// Attempt to connect to the selected network
NetworkService* networkService = (NetworkService*)ServiceManager::getInstance()->getService<NetworkService>();
// TODO: assert networkService != nullptr
if (!networkService->connect(ssid)) {
// Password required
lilka::InputDialog passwordDialog("Введіть пароль:");
passwordDialog.setMasked(true);
while (!passwordDialog.isDone()) {
passwordDialog.update();
passwordDialog.draw(canvas);
queueDraw();
}
String password = passwordDialog.getValue();
networkService->connect(ssid, password);
}

buffer.fillScreen(buffer.color565(0, 0, 0));
buffer.setCursor(4, 150);
buffer.println("Під'єднуємось...");
canvas->drawCanvas(&buffer);
queueDraw();
if (menu.getSelectedIndex() != -1) {
break;

// Wait for the network to connect or fail
while (networkService->getNetworkState() == NETWORK_STATE_CONNECTING) {
taskYIELD();
}
}

// while (!lilka::controller.getState().a.justPressed) {
// delay(10);
// }
lilka::Alert alert("", "");
bool success = networkService->getNetworkState() == NETWORK_STATE_ONLINE;
if (success) {
alert.setTitle("Успіх");
alert.setMessage("Під'єднано до мережі " + ssid);
} else {
alert.setTitle("Помилка");
alert.setMessage("Не вдалося під'єднатись до мережі " + ssid);
}

alert.draw(canvas);
queueDraw();
while (!alert.isDone()) {
alert.update();
}

if (success) {
return;
}
}
}
121 changes: 80 additions & 41 deletions firmware/keira/src/services/network.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,90 +2,129 @@

#include "network.h"

// EEPROM preferences used:
// - network.last_ssid - last connected SSID
// - network.[SSID]_password - password of known network with a given SSID

NetworkService::NetworkService() : Service("network") {
state = NETWORK_STATE_OFFLINE;
_signalStrength = 0;
signalStrength = 0;
mutex = xSemaphoreCreateMutex();
}

void NetworkService::run() {
ssid = "";
password = "";

Preferences prefs;

// Check if there is a known network to connect to
prefs.begin("network", true);
if (!prefs.isKey("ssid")) {
Serial.println("network worker: no SSID found in preferences");
prefs.end();
return;
if (!prefs.isKey("last_ssid")) {
Serial.println("network worker: no last SSID found, skipping startup connection");
} else {
String currentSSID = prefs.getString("last_ssid");
String currentPassword = prefs.getString(String(currentSSID + "_password").c_str());
connect(currentSSID, currentPassword);
}
ssid = prefs.getString("ssid");
password = prefs.getString("password");
prefs.end();

WiFi.onEvent([this](WiFiEvent_t event, WiFiEventInfo_t info) {
switch (event) {
case ARDUINO_EVENT_WIFI_STA_START:
case ARDUINO_EVENT_WIFI_STA_START: {
Serial.println("network worker: connecting to WiFi");
state = NETWORK_STATE_CONNECTING;
break;
case ARDUINO_EVENT_WIFI_STA_CONNECTED:
}
case ARDUINO_EVENT_WIFI_STA_CONNECTED: {
Serial.println("network worker: connected to WiFi");
state = NETWORK_STATE_ONLINE;
// Get SSID from info
// char ssid[33];
// memcpy(ssid, info.wifi_sta_connected.ssid, info.wifi_sta_connected.ssid_len);
Preferences prefs;
String connectedSSID = String(info.wifi_sta_connected.ssid, info.wifi_sta_connected.ssid_len);
prefs.begin("network", true);
if (!String(prefs.getString("last_ssids")).equals(connectedSSID)) {
// Set current SSID as last connected
prefs.putString("last_ssid", String(connectedSSID));
Serial.println("network worker: last SSID set to " + connectedSSID);
}
if (!prefs.isKey(String(connectedSSID + "_password").c_str())) {
// Save password for the connected network
prefs.putString(String(connectedSSID + "_password").c_str(), connectedSSID);
Serial.println("network worker: password for " + connectedSSID + " saved");
}
prefs.end();
break;
case ARDUINO_EVENT_WIFI_STA_DISCONNECTED:
}
case ARDUINO_EVENT_WIFI_STA_DISCONNECTED: {
Serial.println("network worker: disconnected from WiFi");
state = NETWORK_STATE_OFFLINE;
break;
}
default:
break;
}
});

connect();

while (1) {
const int8_t rssi = WiFi.RSSI();
const int8_t excellent = -50;
const int8_t good = -70;
const int8_t fair = -80;

if (rssi >= excellent) {
_signalStrength = 3;
} else if (rssi >= good) {
_signalStrength = 2;
} else if (rssi >= fair) {
_signalStrength = 1;
if (rssi == 0) {
signalStrength = 0;
} else {
_signalStrength = 0;
const int8_t excellent = -50;
const int8_t good = -70;
const int8_t fair = -80;

if (rssi >= excellent) {
signalStrength = 3;
} else if (rssi >= good) {
signalStrength = 2;
} else if (rssi >= fair) {
signalStrength = 1;
} else {
signalStrength = 0;
}
}

vTaskDelay(1000 / portTICK_PERIOD_MS);
}
}

void NetworkService::configure(String ssid, String password) {
ssid = ssid;
password = password;
Preferences prefs;
prefs.begin("network", false);
prefs.putString("ssid", ssid);
prefs.putString("password", password);
prefs.end();
connect();
}
// bool NetworkService::connect(String ssid, String password) {
// ssid = ssid;
// password = password;
// Preferences prefs;
// prefs.begin("network", false);
// prefs.putString("ssid", ssid);
// prefs.putString("password", password);
// prefs.end();
// connect();
// }

NetworkState NetworkService::getNetworkState() {
return state;
}

int NetworkService::getSignalStrength() {
return _signalStrength;
return signalStrength;
}

// Attempt to connect to a given network.
// If the network is not known (password is required), return false.
bool NetworkService::connect(String ssid) {
Preferences prefs;
prefs.begin("network", false);
if (!prefs.isKey(String(ssid + "_password").c_str())) {
Serial.println("network worker: no password found for SSID " + ssid);
prefs.end();
return false;
}
prefs.end();
// connect(ssid, prefs.getString(String(ssid + "_password").c_str()));
Serial.println("network worker: found password for SSID " + ssid);
connect(ssid, prefs.getString(String(ssid + "_password").c_str()));
return true;
}

void NetworkService::connect() {
// Attempt to connect to a given network with a given password.
void NetworkService::connect(String ssid, String password) {
Serial.println("network worker: connecting to " + ssid);
state = NETWORK_STATE_CONNECTING;
WiFi.begin(ssid.c_str(), password.c_str());
}
12 changes: 6 additions & 6 deletions firmware/keira/src/services/network.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,16 +12,16 @@ enum NetworkState {
class NetworkService : public Service {
public:
NetworkService();
void configure(String ssid, String password);
// void configure(String ssid, String password);
NetworkState getNetworkState();
int getSignalStrength();
bool connect(String ssid);
void connect(String ssid, String password);

private:
void run() override;
void connect();
NetworkState state;

String ssid;
String password;
int8_t _signalStrength; // Value in range [0,3]
SemaphoreHandle_t mutex;
NetworkState state;
int8_t signalStrength; // Value in range [0,3]
};
8 changes: 8 additions & 0 deletions sdk/lib/lilka/src/lilka/ui.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,14 @@ Alert::Alert(String title, String message) {
this->done = false;
}

void Alert::setTitle(String title) {
this->title = title;
}

void Alert::setMessage(String message) {
this->message = message;
}

void Alert::update() {
State state = controller.getState();
if (state.a.justPressed) {
Expand Down
6 changes: 6 additions & 0 deletions sdk/lib/lilka/src/lilka/ui.h
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,12 @@ class Alert {
/// @param title Заголовок сповіщення.
/// @param message Повідомлення сповіщення.
Alert(String title, String message);
/// Змінити заголовок сповіщення.
/// @param title Новий заголовок сповіщення.
void setTitle(String title);
/// Змінити повідомлення сповіщення.
/// @param message Нове повідомлення сповіщення.
void setMessage(String message);
/// Оновити стан сповіщення.
///
/// Цю функцію потрібно викликати, щоб сповіщення опрацювало вхідні дані від користувача та оновило свій стан.
Expand Down

0 comments on commit f9c9e79

Please sign in to comment.