mirror of
https://github.com/htotoo/DarkMesh.git
synced 2026-07-20 23:21:02 +00:00
+55
-8
@@ -263,9 +263,24 @@
|
||||
</div>
|
||||
<label for="radio-power">Output Power (dBm)</label>
|
||||
<input type="number" id="radio-power" value="22" min="2" max="22">
|
||||
<label for="radio-chanhash">Channel Hash</label>
|
||||
<input type="number" id="radio-chanhash" value="8" min="0" max="255">
|
||||
<button id="apply-config-btn">Apply Configuration</button>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="panel">
|
||||
<h2>WiFi STA Configuration</h2>
|
||||
|
||||
<label for="wifi-ssid">SSID</label>
|
||||
<input type="text" id="wifi-ssid" placeholder="Enter WiFi SSID">
|
||||
|
||||
<label for="wifi-password">Password</label>
|
||||
<input type="password" id="wifi-password" placeholder="Enter WiFi password">
|
||||
|
||||
<button id="save-wifi-btn">Save WiFi Configuration</button>
|
||||
</div>
|
||||
|
||||
<div class="panel">
|
||||
<h2>Continuous Attacks</h2>
|
||||
<p>Status: <span id="status-value">Idle</span></p>
|
||||
@@ -274,6 +289,7 @@
|
||||
<input type="number" id="attack-interval" min="10" max="7200" value="10" title="The delay between attacks.">
|
||||
<label for="attack-mqtt">Ok to MQTT</label>
|
||||
<input type="checkbox" id="attack-mqtt" title="Allow attacks to be sent via MQTT.">
|
||||
|
||||
<select id="attack-selector">
|
||||
<option value="none">-- Select Attack --</option>
|
||||
<option value="node_flood">Flood with Nodes</option>
|
||||
@@ -416,13 +432,13 @@
|
||||
const allNodes = new Map();
|
||||
|
||||
const loraPresets = {
|
||||
'long_fast': { bw: 250.0, sf: 11, cr: 5 },
|
||||
'long_slow': { bw: 125.0, sf: 12, cr: 8 },
|
||||
'long_moderate': { bw: 125.0, sf: 11, cr: 8 },
|
||||
'medium_slow': { bw: 250.0, sf: 10, cr: 5 },
|
||||
'medium_fast': { bw: 250.0, sf: 9, cr: 5 },
|
||||
'short_slow': { bw: 250.0, sf: 8, cr: 5 },
|
||||
'short_fast': { bw: 250.0, sf: 7, cr: 5 },
|
||||
'long_fast': { bw: 250.0, sf: 11, cr: 5, chanhash: 8 },
|
||||
'long_slow': { bw: 125.0, sf: 12, cr: 8, chanhash: 8 },
|
||||
'long_moderate': { bw: 125.0, sf: 11, cr: 8, chanhash: 8 },
|
||||
'medium_slow': { bw: 250.0, sf: 10, cr: 5, chanhash: 8 },
|
||||
'medium_fast': { bw: 250.0, sf: 9, cr: 5, chanhash: 31 },
|
||||
'short_slow': { bw: 250.0, sf: 8, cr: 5, chanhash: 8 },
|
||||
'short_fast': { bw: 250.0, sf: 7, cr: 5, chanhash: 8 },
|
||||
};
|
||||
|
||||
const statusValue = document.getElementById('status-value');
|
||||
@@ -433,6 +449,7 @@
|
||||
const stopAttackBtn = document.getElementById('stop-attack-btn');
|
||||
const sendMessageBtn = document.getElementById('send-message-btn');
|
||||
const applyConfigBtn = document.getElementById('apply-config-btn');
|
||||
const saveWifiBtn = document.getElementById('save-wifi-btn');
|
||||
const loraPresetSelector = document.getElementById('lora-preset-selector');
|
||||
const loraBw = document.getElementById('lora-bw');
|
||||
const loraSf = document.getElementById('lora-sf');
|
||||
@@ -501,9 +518,16 @@
|
||||
loraBw.value = data.config.bandwidth || 250.0;
|
||||
loraSf.value = data.config.spreading_factor || 11;
|
||||
loraCr.value = data.config.coding_rate || 5;
|
||||
document.getElementById('radio-chanhash').value = data.config.chanhash || 8;
|
||||
document.getElementById('radio-power').value = data.config.power || 20;
|
||||
break;
|
||||
}
|
||||
case 'wifi_sta_config':
|
||||
if (data.config) {
|
||||
document.getElementById('wifi-ssid').value = data.config.ssid || '';
|
||||
document.getElementById('wifi-password').value = data.config.password || '';
|
||||
}
|
||||
break;
|
||||
default:
|
||||
logToDebug(`Unknown message type: ${data.type}`);
|
||||
}
|
||||
@@ -566,6 +590,7 @@
|
||||
loraBw.value = values.bw;
|
||||
loraSf.value = values.sf;
|
||||
loraCr.value = values.cr;
|
||||
document.getElementById('radio-chanhash').value = values.chanhash;
|
||||
}
|
||||
});
|
||||
|
||||
@@ -650,13 +675,35 @@
|
||||
bandwidth: parseFloat(loraBw.value),
|
||||
spreading_factor: parseInt(loraSf.value),
|
||||
coding_rate: parseInt(loraCr.value),
|
||||
power: parseInt(document.getElementById('radio-power').value)
|
||||
power: parseInt(document.getElementById('radio-power').value),
|
||||
chanhash: parseInt(document.getElementById('radio-chanhash').value)
|
||||
}
|
||||
};
|
||||
logToDebug(`⚙️ Applying new radio configuration...`);
|
||||
sendWebSocketMessage(config);
|
||||
});
|
||||
|
||||
|
||||
saveWifiBtn.addEventListener('click', () => {
|
||||
const ssid = document.getElementById('wifi-ssid').value.trim();
|
||||
const password = document.getElementById('wifi-password').value;
|
||||
|
||||
if (!ssid) {
|
||||
alert('SSID cannot be empty.');
|
||||
return;
|
||||
}
|
||||
|
||||
logToDebug(`📶 Saving WiFi STA configuration for "${ssid}"...`);
|
||||
|
||||
sendWebSocketMessage({
|
||||
action: 'set_wifi_sta',
|
||||
params: {
|
||||
ssid,
|
||||
password
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
nodeListBody.addEventListener('click', (e) => {
|
||||
if (e.target.tagName === 'TD' && e.target.cellIndex === 0) {
|
||||
const nodeId = e.target.textContent;
|
||||
|
||||
+77
-15
@@ -10,6 +10,7 @@
|
||||
#include "esp_event.h"
|
||||
#include "nvs_flash.h"
|
||||
#include "esp_log.h"
|
||||
#include "mdns.h"
|
||||
|
||||
#include "esp_random.h"
|
||||
#include "MtCompact.hpp"
|
||||
@@ -40,9 +41,28 @@ LoraConfig lora_config = {
|
||||
/*.tcxo_voltage = */ 1.8,
|
||||
/*.use_regulator_ldo = */ false,
|
||||
}; // default LoRa configuration for EU LONGFAST 433
|
||||
uint8_t default_chanhash = 8;
|
||||
MtCompact mtCompact;
|
||||
uint16_t default_chan_hash = 31; // 8 = long_fast, 31 = medium fast
|
||||
|
||||
void initialize_mdns(void) {
|
||||
esp_err_t err = mdns_init();
|
||||
if (err) {
|
||||
ESP_LOGE(TAG, "mDNS initialization failed: %s", esp_err_to_name(err));
|
||||
return;
|
||||
}
|
||||
// Set the hostname -> Resolves to "darkmesh.local"
|
||||
mdns_hostname_set("darkmesh");
|
||||
mdns_instance_name_set("Darkmesh Network Node");
|
||||
ESP_LOGI(TAG, "mDNS initialized. You can now ping darkmesh.local");
|
||||
}
|
||||
static void mdns_ip_event_handler(void* arg, esp_event_base_t event_base, int32_t event_id, void* event_data) {
|
||||
if (event_base == IP_EVENT && event_id == IP_EVENT_STA_GOT_IP) {
|
||||
ESP_LOGI("mdns_hook", "Network is ready. Starting mDNS...");
|
||||
ip_event_got_ip_t* event = (ip_event_got_ip_t*)event_data;
|
||||
ESP_LOGI("mdns_hook", "STA IP is: " IPSTR, IP2STR(&event->ip_info.ip));
|
||||
initialize_mdns();
|
||||
}
|
||||
}
|
||||
void sendDebugMessage(const std::string& message) {
|
||||
std::string safe_text = message;
|
||||
std::replace(safe_text.begin(), safe_text.end(), '"', '\'');
|
||||
@@ -71,23 +91,45 @@ void app_main(void) {
|
||||
ESP_ERROR_CHECK(esp_netif_init());
|
||||
ESP_ERROR_CHECK(esp_event_loop_create_default());
|
||||
esp_netif_create_default_wifi_ap();
|
||||
|
||||
esp_event_handler_instance_register(IP_EVENT,
|
||||
IP_EVENT_STA_GOT_IP,
|
||||
&mdns_ip_event_handler,
|
||||
NULL,
|
||||
NULL);
|
||||
wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
|
||||
ESP_ERROR_CHECK(esp_wifi_init(&cfg));
|
||||
|
||||
wifi_config_t wifi_config = {};
|
||||
strcpy((char*)wifi_config.ap.ssid, ssid);
|
||||
wifi_config.ap.ssid_len = strlen(ssid);
|
||||
strcpy((char*)wifi_config.ap.password, password);
|
||||
wifi_config.ap.max_connection = 4;
|
||||
wifi_config.ap.authmode = WIFI_AUTH_WPA_WPA2_PSK;
|
||||
if (strlen(password) == 0) {
|
||||
wifi_config.ap.authmode = WIFI_AUTH_OPEN;
|
||||
wifi_config_t ap_config = {};
|
||||
strcpy((char*)ap_config.ap.ssid, ssid);
|
||||
ap_config.ap.ssid_len = strlen(ssid);
|
||||
strcpy((char*)ap_config.ap.password, password);
|
||||
ap_config.ap.max_connection = 4;
|
||||
ap_config.ap.authmode = (strlen(password) == 0) ? WIFI_AUTH_OPEN : WIFI_AUTH_WPA_WPA2_PSK;
|
||||
|
||||
bool wifi_sta = config.load_wifi();
|
||||
|
||||
if (wifi_sta) {
|
||||
ESP_LOGI(TAG, "WiFi STA mode enabled. Target SSID: %s", config.sta_ssid.c_str());
|
||||
esp_netif_create_default_wifi_sta();
|
||||
wifi_config_t sta_config = {};
|
||||
strcpy((char*)sta_config.sta.ssid, config.sta_ssid.c_str());
|
||||
strcpy((char*)sta_config.sta.password, config.sta_password.c_str());
|
||||
|
||||
ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_APSTA));
|
||||
ESP_ERROR_CHECK(esp_wifi_set_config(WIFI_IF_AP, &ap_config));
|
||||
ESP_ERROR_CHECK(esp_wifi_set_config(WIFI_IF_STA, &sta_config));
|
||||
} else {
|
||||
ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_AP));
|
||||
ESP_ERROR_CHECK(esp_wifi_set_config(WIFI_IF_AP, &ap_config));
|
||||
}
|
||||
ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_AP));
|
||||
ESP_ERROR_CHECK(esp_wifi_set_config(WIFI_IF_AP, &wifi_config));
|
||||
|
||||
ESP_ERROR_CHECK(esp_wifi_start());
|
||||
ESP_LOGI(TAG, "WiFi AP initialized. SSID: %s, Password: %s", ssid, password);
|
||||
ESP_LOGI(TAG, "WiFi hardware started.");
|
||||
|
||||
if (wifi_sta) {
|
||||
ESP_ERROR_CHECK(esp_wifi_connect());
|
||||
ESP_LOGI(TAG, "Connecting to AP...");
|
||||
}
|
||||
|
||||
init_httpd();
|
||||
ESP_LOGI(TAG, "Loading radio config.");
|
||||
@@ -132,7 +174,7 @@ void app_main(void) {
|
||||
mtCompact.setOnTraceroute([](MCT_Header& header, MCT_RouteDiscovery& route, bool for_me, bool is_reply, bool need_reply) {
|
||||
sendDebugMessage("Traceroute from 0x" + std::to_string(header.srcnode) + ": route_count=" + std::to_string(route.route_count) + ", for_me=" + std::to_string(for_me) + ", is_reply=" + std::to_string(is_reply));
|
||||
});
|
||||
mtCompact.setPrimaryChanByHash(default_chan_hash);
|
||||
mtCompact.setPrimaryChanByHash(default_chanhash); // should be a saved parameter
|
||||
|
||||
tmAttack.setRadio(&mtCompact);
|
||||
|
||||
@@ -176,6 +218,10 @@ void handle_start_attack(const char* attack_type, JSON_Object* params) {
|
||||
int mqtt = (int)json_object_get_number(params, "mqtt");
|
||||
mtCompact.setOkToMqtt(mqtt == 1);
|
||||
ESP_LOGI("WEB", "Attack MQTT sending set to %s", mqtt == 1 ? "enabled" : "disabled");
|
||||
uint8_t chanhash = (uint8_t)json_object_get_number(params, "chanhash");
|
||||
|
||||
mtCompact.setPrimaryChanByHash(chanhash);
|
||||
ESP_LOGI("WEB", "Attack channel set to hash %d", chanhash);
|
||||
}
|
||||
if (strcmp(attack_type, "pos_poison") == 0 && params != NULL) {
|
||||
double min_lat = json_object_get_number(params, "min_lat");
|
||||
@@ -261,12 +307,15 @@ void handle_set_config(JSON_Object* params) {
|
||||
double sf = json_object_get_number(params, "spreading_factor");
|
||||
double cr = json_object_get_number(params, "coding_rate");
|
||||
double power = json_object_get_number(params, "power");
|
||||
uint8_t chanhash = (uint8_t)json_object_get_number(params, "chanhash");
|
||||
ESP_LOGI("WEB", "Config: Freq=%.1f, BW=%.1f, SF=%.0f, CR=%.0f, Power=%.0f", frequency, bandwidth, sf, cr, power);
|
||||
mtCompact.setRadioFrequency(frequency);
|
||||
mtCompact.setRadioBandwidth(bandwidth);
|
||||
mtCompact.setRadioSpreadingFactor(static_cast<uint8_t>(sf));
|
||||
mtCompact.setRadioCodingRate(static_cast<uint8_t>(cr));
|
||||
mtCompact.setRadioPower(static_cast<int8_t>(power));
|
||||
mtCompact.setPrimaryChanByHash(chanhash);
|
||||
default_chanhash = chanhash;
|
||||
lora_config.frequency = frequency;
|
||||
lora_config.bandwidth = bandwidth;
|
||||
lora_config.spreading_factor = static_cast<uint8_t>(sf);
|
||||
@@ -290,6 +339,15 @@ void handle_send_message(const char* source_id, const char* message) {
|
||||
sendDebugMessage("Sent message.");
|
||||
}
|
||||
|
||||
void handle_set_wifi_sta(const char* ssid, const char* password, int channel) {
|
||||
ESP_LOGI("WEB", "Handling 'set_wifi_sta': SSID=%s, Password=%s, Channel=%d", ssid, password, channel);
|
||||
config.sta_ssid = ssid;
|
||||
config.sta_password = password;
|
||||
config.channel = channel;
|
||||
config.save_wifi();
|
||||
sendDebugMessage("WiFi STA configuration updated. Restart to apply changes.");
|
||||
}
|
||||
|
||||
void handle_initme() {
|
||||
ESP_LOGI("WEB", "Handling 'initme'");
|
||||
// sending all nodes to web
|
||||
@@ -305,6 +363,10 @@ void handle_initme() {
|
||||
ws_sendall((uint8_t*)attack_json.c_str(), attack_json.length(), true);
|
||||
vTaskDelay(pdMS_TO_TICKS(20));
|
||||
// send radio config
|
||||
std::string config_json = "{ \"type\": \"radio_config\", \"config\": { \"frequency\": " + std::to_string(lora_config.frequency) + ", \"bandwidth\": " + std::to_string(lora_config.bandwidth) + ", \"spreading_factor\": " + std::to_string(lora_config.spreading_factor) + ", \"coding_rate\": " + std::to_string(lora_config.coding_rate) + ", \"power\": " + std::to_string(lora_config.output_power) + " } }";
|
||||
std::string config_json = "{ \"type\": \"radio_config\", \"config\": { \"frequency\": " + std::to_string(lora_config.frequency) + ", \"bandwidth\": " + std::to_string(lora_config.bandwidth) + ", \"spreading_factor\": " + std::to_string(lora_config.spreading_factor) + ", \"coding_rate\": " + std::to_string(lora_config.coding_rate) + ", \"power\": " + std::to_string(lora_config.output_power) + ", \"chanhash\": " + std::to_string(default_chanhash) + " } }";
|
||||
ws_sendall((uint8_t*)config_json.c_str(), config_json.length(), true);
|
||||
vTaskDelay(pdMS_TO_TICKS(20));
|
||||
// send wifi config
|
||||
std::string wifi_json = "{ \"type\": \"wifi_sta_config\", \"config\": { \"ssid\": \"" + config.sta_ssid + "\", \"password\": \"" + config.sta_password + "\" } }";
|
||||
ws_sendall((uint8_t*)wifi_json.c_str(), wifi_json.length(), true);
|
||||
}
|
||||
|
||||
+41
-4
@@ -7,11 +7,48 @@
|
||||
|
||||
class TConfig {
|
||||
public:
|
||||
std::string ssid;
|
||||
std::string password;
|
||||
int channel;
|
||||
std::string sta_ssid;
|
||||
std::string sta_password;
|
||||
int32_t channel;
|
||||
|
||||
TConfig() : ssid(""), password(""), channel(1) {}
|
||||
TConfig() : sta_ssid(""), sta_password(""), channel(1) {}
|
||||
|
||||
bool load_wifi() {
|
||||
nvs_handle_t handle;
|
||||
esp_err_t err = nvs_open("wifi_cfg", NVS_READONLY, &handle);
|
||||
if (err != ESP_OK) return false;
|
||||
|
||||
char tmpstr[64] = {0};
|
||||
size_t tmpstrlen = sizeof(tmpstr);
|
||||
err = nvs_get_str(handle, "ssid", tmpstr, &tmpstrlen);
|
||||
if (err == ESP_OK) {
|
||||
sta_ssid = std::string(tmpstr);
|
||||
}
|
||||
tmpstrlen = sizeof(tmpstr);
|
||||
err = nvs_get_str(handle, "password", tmpstr, &tmpstrlen);
|
||||
if (err == ESP_OK) {
|
||||
sta_password = std::string(tmpstr);
|
||||
}
|
||||
err = nvs_get_i32(handle, "channel", &channel);
|
||||
if (err != ESP_OK) channel = 1;
|
||||
|
||||
nvs_close(handle);
|
||||
return sta_ssid.length() > 0 && sta_password.length() > 7;
|
||||
}
|
||||
|
||||
void save_wifi() {
|
||||
nvs_handle_t handle;
|
||||
esp_err_t err = nvs_open("wifi_cfg", NVS_READWRITE, &handle);
|
||||
if (err != ESP_OK) return;
|
||||
|
||||
nvs_set_str(handle, "ssid", sta_ssid.c_str());
|
||||
nvs_set_str(handle, "password", sta_password.c_str());
|
||||
nvs_set_i32(handle, "channel", channel);
|
||||
|
||||
ESP_LOGI("CONFIG", "WiFi configuration saved: SSID=%s, Password=%s, Channel=%d", sta_ssid.c_str(), sta_password.c_str(), channel);
|
||||
nvs_commit(handle);
|
||||
nvs_close(handle);
|
||||
}
|
||||
|
||||
bool load_radio(LoraConfig& lora_config) {
|
||||
nvs_handle_t handle;
|
||||
|
||||
@@ -24,6 +24,7 @@ void handle_stop_attack();
|
||||
void handle_send_message(const char* source_id, const char* message);
|
||||
void handle_set_config(JSON_Object* params);
|
||||
void handle_initme();
|
||||
void handle_set_wifi_sta(const char* ssid, const char* password, int channel);
|
||||
|
||||
static int hex_to_int(char c) {
|
||||
if (c >= '0' && c <= '9') {
|
||||
@@ -156,6 +157,15 @@ static esp_err_t handle_ws_req(httpd_req_t* req) {
|
||||
}
|
||||
} else if (strcmp(action, "initme") == 0) {
|
||||
handle_initme();
|
||||
|
||||
} else if (strcmp(action, "set_wifi_sta") == 0) {
|
||||
JSON_Object* params = json_object_get_object(root_object, "params");
|
||||
const char* ssid = json_object_get_string(params, "ssid");
|
||||
const char* password = json_object_get_string(params, "password");
|
||||
int channel = 1;
|
||||
if (ssid && password) {
|
||||
handle_set_wifi_sta(ssid, password, channel);
|
||||
}
|
||||
} else {
|
||||
ESP_LOGE("WEB", "Unknown action: %s", action);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user