@@ -55,8 +109,8 @@
Currently active tags:
-
reboot AP
-
+
AP config
+
diff --git a/ESP32_AP-Flasher/data/www/main.css b/ESP32_AP-Flasher/data/www/main.css
index d24cf8c6..be547bdc 100644
--- a/ESP32_AP-Flasher/data/www/main.css
+++ b/ESP32_AP-Flasher/data/www/main.css
@@ -64,7 +64,7 @@ label {
gap: 20px;
}
-#rebootbutton {
+#rebootbutton, #downloadDBbutton, #apconfigbutton, .filebutton {
padding: 2px 5px;
background-color: #cccccc;
text-decoration: none;
@@ -72,13 +72,6 @@ label {
cursor: pointer;
}
-.filebutton {
- padding: 2px 5px;
- background-color: #cccccc;
- text-decoration: none;
- color: black;
-}
-
.columns div {
flex: 1;
}
@@ -89,14 +82,14 @@ input[type="text"],
input[type="button"],
input[type="submit"],
button {
- -webkit-appearance: none;
+ appearance: none;
border-radius: 0;
}
input {
border: solid 1px #666666;
padding: 4px;
- -webkit-border-radius: 0px;
+ border-radius: 0px;
}
input[type=button] {
@@ -109,10 +102,10 @@ input[type=button]:hover {
}
select {
padding: 4px;
- -webkit-border-radius: 0px;
+ border-radius: 0px;
}
-#configbox {
+#configbox, #apconfigbox {
display: none;
position: fixed;
top: 80px;
@@ -124,24 +117,53 @@ select {
box-shadow: 7px 10px 52px -19px rgba(0, 0, 0, 0.63);
}
-#configbox p {
+#configbox p, #apconfigbox p {
padding: 5px;
}
-#configbox h3 {
+#configbox h3, #apconfigbox h3 {
font-size: 1.5em;
font-weight: bold;
}
-#configbox input {
+#configbox input, #apconfigbox input {
border: solid 1px #666666;
padding: 4px;
}
-#configbox label {
+#configbox label, #apconfigbox label {
text-transform: capitalize;
}
+#apconfigbox {
+ background-color: #e6f0d3;
+}
+
+#aptable {
+ width: 100%;
+ border-spacing: 0;
+}
+
+#aptable th {
+ text-align: left;
+ background-color: #00000020;
+ padding: 0px 3px;
+}
+
+#aptable th, #aptable td {
+ border-right: 1px solid #000010;
+ padding: 0px 3px;
+}
+
+#aptable td:nth-child(1), #aptable th:nth-child(1) {
+ border-left: 1px solid #000010;
+}
+
+#aptable td:nth-child(3),
+#aptable td:nth-child(4) {
+ text-align: right;
+}
+
#cfgdelete {
position: absolute;
bottom: 15px;
diff --git a/ESP32_AP-Flasher/data/www/main.js b/ESP32_AP-Flasher/data/www/main.js
index 6cd58191..d350d958 100644
--- a/ESP32_AP-Flasher/data/www/main.js
+++ b/ESP32_AP-Flasher/data/www/main.js
@@ -34,7 +34,14 @@ let servertimediff = 0;
let socket;
connect();
setInterval(updatecards, 1000);
-window.addEventListener("load", function () { loadTags(0) });
+window.addEventListener("load", function () {
+ fetch("/get_ap_list")
+ .then(response => response.json())
+ .then(data => {
+ if (data.alias) $(".logo").innerHTML = data.alias;
+ })
+ loadTags(0)
+});
function loadTags(pos) {
fetch("/get_db?pos="+pos)
@@ -69,6 +76,14 @@ function connect() {
$('#sysinfo').innerHTML = 'free heap: ' + msg.sys.heap + ' bytes ┇ db size: ' + msg.sys.dbsize + ' bytes ┇ db record count: ' + msg.sys.recordcount + ' ┇ littlefs free: ' + msg.sys.littlefsfree + ' bytes';
servertimediff = (Date.now() / 1000) - msg.sys.currtime;
}
+ if (msg.apitem) {
+ var row = $("#aptable").insertRow();
+ row.insertCell(0).innerHTML = "
" + msg.apitem.ip + "";
+ row.insertCell(1).innerHTML = msg.apitem.alias;
+ row.insertCell(2).innerHTML = msg.apitem.count;
+ row.insertCell(3).innerHTML = msg.apitem.channel;
+ row.insertCell(4).innerHTML = msg.apitem.version;
+ }
});
socket.addEventListener("close", (event) => {
@@ -208,9 +223,11 @@ $('#clearlog').onclick = function () {
$('#messages').innerHTML='';
}
-$('.closebtn').onclick = function (event) {
- event.target.parentNode.style.display='none';
-}
+document.querySelectorAll('.closebtn').forEach(button => {
+ button.addEventListener('click', (event) => {
+ event.target.parentNode.style.display = 'none';
+ });
+});
$('#taglist').addEventListener("click", (event) => {
let currentElement = event.target;
@@ -242,7 +259,6 @@ $('#taglist').addEventListener("click", (event) => {
})
$('#cfgsave').onclick = function () {
-
let contentMode = $('#cfgcontent').value;
let extraoptions = contentModeOptions[contentMode];
let obj={};
@@ -292,6 +308,36 @@ $('#rebootbutton').onclick = function () {
socket.close();
}
+$('#apconfigbutton').onclick = function () {
+ var table = document.getElementById("aptable");
+ var rowCount = table.rows.length;
+ for (var i = rowCount - 1; i > 0; i--) {
+ table.deleteRow(i);
+ }
+ $('#apconfigbox').style.display = 'block'
+ fetch("/get_ap_list")
+ .then(response => response.json())
+ .then(data => {
+ $('#apcfgalias').value = data.alias;
+ $('#apcfgchid').value = data.channel;
+ })
+}
+
+$('#apcfgsave').onclick = function () {
+ let formData = new FormData();
+ formData.append("alias", $('#apcfgalias').value);
+ formData.append("channel", $('#apcfgchid').value);
+ fetch("/save_apcfg", {
+ method: "POST",
+ body: formData
+ })
+ .then(response => response.text())
+ .then(data => showMessage(data))
+ .catch(error => showMessage('Error: ' + error));
+ $(".logo").innerHTML = $('#apcfgalias').value;
+ $('#apconfigbox').style.display = 'none';
+}
+
function contentselected() {
let contentMode = $('#cfgcontent').value;
let extraoptions = contentModeOptions[contentMode];
diff --git a/ESP32_AP-Flasher/include/commstructs.h b/ESP32_AP-Flasher/include/commstructs.h
index ac73dd81..a1a15e05 100644
--- a/ESP32_AP-Flasher/include/commstructs.h
+++ b/ESP32_AP-Flasher/include/commstructs.h
@@ -86,4 +86,20 @@ struct pendingData {
#define BLOCK_DATA_SIZE 4096
#define BLOCK_XFER_BUFFER_SIZE BLOCK_DATA_SIZE + sizeof(struct blockData)
+#define PKT_AVAIL_DATA_REQ 0xE5
+#define PKT_AVAIL_DATA_INFO 0xE6
+#define PKT_XFER_COMPLETE 0xEA
+#define PKT_XFER_TIMEOUT 0xED
+#define PKT_CANCEL_XFER 0xEC
+#define PKT_APLIST_REQ 0x80
+#define PKT_APLIST_REPLY 0x81
+
+struct APlist {
+ uint32_t src;
+ char alias[32];
+ uint8_t channelId;
+ uint8_t tagCount;
+ uint16_t version;
+} __packed;
+
#pragma pack(pop)
\ No newline at end of file
diff --git a/ESP32_AP-Flasher/include/newproto.h b/ESP32_AP-Flasher/include/newproto.h
index 4a755815..92f3417f 100644
--- a/ESP32_AP-Flasher/include/newproto.h
+++ b/ESP32_AP-Flasher/include/newproto.h
@@ -10,4 +10,5 @@ extern void prepareExternalDataAvail(struct pendingData* pending, IPAddress remo
extern void processXferComplete(struct espXferComplete* xfc);
extern void processXferTimeout(struct espXferComplete* xfc);
extern void processDataReq(struct espAvailDataReq* adr);
-void refreshAllPending();
\ No newline at end of file
+void refreshAllPending();
+void setAPchannel();
diff --git a/ESP32_AP-Flasher/include/serial.h b/ESP32_AP-Flasher/include/serial.h
index bc597799..d3911058 100644
--- a/ESP32_AP-Flasher/include/serial.h
+++ b/ESP32_AP-Flasher/include/serial.h
@@ -1,5 +1,8 @@
#include
+extern struct espSetChannelPower curChannel;
+extern uint16_t version;
+
void zbsTx(uint8_t* packetdata, uint8_t len);
void zbsRxTask(void* parameter);
diff --git a/ESP32_AP-Flasher/include/tag_db.h b/ESP32_AP-Flasher/include/tag_db.h
index 83d819bd..eb24ca22 100644
--- a/ESP32_AP-Flasher/include/tag_db.h
+++ b/ESP32_AP-Flasher/include/tag_db.h
@@ -49,6 +49,7 @@ class tagRecord {
};
extern std::vector tagDB;
+extern DynamicJsonDocument APconfig;
String tagDBtoJson(uint8_t mac[6] = nullptr, uint8_t startPos = 0);
bool deleteRecord(uint8_t mac[6]);
void fillNode(JsonObject &tag, tagRecord* &taginfo);
@@ -56,5 +57,7 @@ void saveDB(String filename);
void loadDB(String filename);
uint8_t getTagCount();
void clearPending(tagRecord* taginfo);
+void initAPconfig();
+void saveAPconfig();
#pragma pack(pop)
\ No newline at end of file
diff --git a/ESP32_AP-Flasher/include/udp.h b/ESP32_AP-Flasher/include/udp.h
index 980a6174..f2a25a08 100644
--- a/ESP32_AP-Flasher/include/udp.h
+++ b/ESP32_AP-Flasher/include/udp.h
@@ -10,6 +10,7 @@ class UDPcomm {
UDPcomm();
~UDPcomm();
void init();
+ void getAPList();
void netProcessDataReq(struct espAvailDataReq* eadr);
void netProcessXferComplete(struct espXferComplete* xfc);
void netProcessXferTimeout(struct espXferComplete* xfc);
diff --git a/ESP32_AP-Flasher/include/web.h b/ESP32_AP-Flasher/include/web.h
index 524234df..991d9e13 100644
--- a/ESP32_AP-Flasher/include/web.h
+++ b/ESP32_AP-Flasher/include/web.h
@@ -1,5 +1,5 @@
-#include
+#include
#include
#include
@@ -11,9 +11,10 @@ void wsLog(String text);
void wsErr(String text);
void wsSendTaginfo(uint8_t mac[6]);
void wsSendSysteminfo();
+void wsSendAPitem(struct APlist* apitem);
extern uint64_t swap64(uint64_t x);
-extern AsyncWebSocket ws; //("/ws");
+extern AsyncWebSocket ws;
extern SemaphoreHandle_t wsMutex;
extern TaskHandle_t websocketUpdater;
\ No newline at end of file
diff --git a/ESP32_AP-Flasher/platformio.ini b/ESP32_AP-Flasher/platformio.ini
index b87f2863..b7cd9bb3 100644
--- a/ESP32_AP-Flasher/platformio.ini
+++ b/ESP32_AP-Flasher/platformio.ini
@@ -131,6 +131,7 @@ board = esp32dev
board_build.partitions = no_ota.csv
build_flags =
+ -DCORE_DEBUG_LEVEL=0
-D SIMPLE_AP
-D FLASHER_AP_SS=5
diff --git a/ESP32_AP-Flasher/src/main.cpp b/ESP32_AP-Flasher/src/main.cpp
index 6c8856bd..27e7a984 100644
--- a/ESP32_AP-Flasher/src/main.cpp
+++ b/ESP32_AP-Flasher/src/main.cpp
@@ -50,12 +50,22 @@ void setup() {
Serial.printf("Flash Size %d, Flash Speed %d\n", ESP.getFlashChipSize(), ESP.getFlashChipSpeed());
Serial.println("##################################\n\n");
- Serial.println(ESP.getFreeHeap());
+ Serial.printf("Total heap: %d\n", ESP.getHeapSize());
+ Serial.printf("Free heap: %d\n", ESP.getFreeHeap());
+ Serial.printf("Total PSRAM: %d\n", ESP.getPsramSize());
+ Serial.printf("Free PSRAM: %d\n\n", ESP.getFreePsram());
- Serial.printf("Total heap: %d", ESP.getHeapSize());
- Serial.printf("Free heap: %d", ESP.getFreeHeap());
- Serial.printf("Total PSRAM: %d", ESP.getPsramSize());
- Serial.printf("Free PSRAM: %d", ESP.getFreePsram());
+ Serial.printf("ESP32 Partition table:\n");
+ Serial.printf("| Type | Sub | Offset | Size | Label |\n");
+ Serial.printf("| ---- | --- | -------- | -------- | ---------------- |\n");
+ esp_partition_iterator_t pi = esp_partition_find(ESP_PARTITION_TYPE_ANY, ESP_PARTITION_SUBTYPE_ANY, NULL);
+ if (pi != NULL) {
+ do {
+ const esp_partition_t* p = esp_partition_get(pi);
+ Serial.printf("| %02x | %02x | 0x%06X | 0x%06X | %-16s |\r\n",
+ p->type, p->subtype, p->address, p->size, p->label);
+ } while (pi = (esp_partition_next(pi)));
+ }
#ifdef HAS_USB
xTaskCreate(usbFlasherTask, "flasher", 10000, NULL, configMAX_PRIORITIES - 10, NULL);
@@ -64,6 +74,7 @@ void setup() {
configTzTime("CET-1CEST,M3.5.0,M10.5.0/3", "0.nl.pool.ntp.org", "europe.pool.ntp.org", "time.nist.gov");
// https://github.com/nayarsystems/posix_tz_db/blob/master/zones.csv
+ initAPconfig();
init_web();
init_udp();
diff --git a/ESP32_AP-Flasher/src/newproto.cpp b/ESP32_AP-Flasher/src/newproto.cpp
index cd2c1116..7eb5285c 100644
--- a/ESP32_AP-Flasher/src/newproto.cpp
+++ b/ESP32_AP-Flasher/src/newproto.cpp
@@ -432,4 +432,17 @@ void refreshAllPending() {
wsSendTaginfo(taginfo->mac);
}
}
-};
\ No newline at end of file
+};
+
+void setAPchannel() {
+ if (APconfig["channel"].as() == 0) {
+ // trigger channel autoselect
+ UDPcomm udpsync;
+ udpsync.getAPList();
+ } else {
+ if (curChannel.channel != APconfig["channel"].as()) {
+ curChannel.channel = APconfig["channel"].as();
+ if (version) sendChannelPower(&curChannel);
+ }
+ }
+}
diff --git a/ESP32_AP-Flasher/src/serial.cpp b/ESP32_AP-Flasher/src/serial.cpp
index 3e53e214..0dd4d74a 100644
--- a/ESP32_AP-Flasher/src/serial.cpp
+++ b/ESP32_AP-Flasher/src/serial.cpp
@@ -35,6 +35,9 @@ volatile uint8_t cmdReplyValue = CMD_REPLY_WAIT;
#define AP_SERIAL_PORT Serial1
+uint8_t channelList[6];
+struct espSetChannelPower curChannel = {0, 11, 8};
+
bool txStart() {
while (1) {
if (xPortInIsrContext()) {
@@ -153,9 +156,9 @@ void sendCancelPending(struct pendingData* pending) {
AP_SERIAL_PORT.write(((uint8_t*)pending)[c]);
}
if (waitCmdReply()) goto cxdsent;
- AP_SERIAL_PORT.printf("CXD send failed in try %d\n", attempt);
+ Serial.printf("CXD send failed in try %d\n", attempt);
}
- AP_SERIAL_PORT.print("CXD failed to send...\n");
+ Serial.print("CXD failed to send...\n");
txEnd();
return;
cxdsent:
@@ -172,9 +175,9 @@ bool sendChannelPower(struct espSetChannelPower* scp) {
AP_SERIAL_PORT.write(((uint8_t*)scp)[c]);
}
if (waitCmdReply()) goto scpSent;
- AP_SERIAL_PORT.printf("SCP send failed in try %d\n", attempt);
+ Serial.printf("SCP send failed in try %d\n", attempt);
}
- AP_SERIAL_PORT.print("SCP failed to send...\n");
+ Serial.print("SCP failed to send...\n");
txEnd();
return false;
scpSent:
@@ -402,6 +405,8 @@ void zbsRxTask(void* parameter) {
vTaskDelay(2 / portTICK_PERIOD_MS);
rampTagPower(FLASHER_AP_POWER, true);
wsErr("The AP tag crashed. Restarting tag, regenerating all pending info.");
+ vTaskDelay(3000 / portTICK_PERIOD_MS);
+ sendChannelPower(&curChannel);
refreshAllPending();
}
} else {
@@ -423,9 +428,8 @@ void zbsRxTask(void* parameter) {
} else {
Serial.println("Failed to update version on the AP :(");
}
- } else if (!fsversion) {
- Serial.println("No ZBS/Zigbee FW binary found on SPIFFS, please upload a zigbeebase000X.bin - format binary to enable flashing");
}
+ sendChannelPower(&curChannel);
firstrun = false;
}
}
diff --git a/ESP32_AP-Flasher/src/tag_db.cpp b/ESP32_AP-Flasher/src/tag_db.cpp
index 58bc96c3..b1fe45ec 100644
--- a/ESP32_AP-Flasher/src/tag_db.cpp
+++ b/ESP32_AP-Flasher/src/tag_db.cpp
@@ -2,12 +2,13 @@
#include
#include
-
+#include
#include
#include "LittleFS.h"
std::vector tagDB;
+DynamicJsonDocument APconfig(150);
tagRecord* tagRecord::findByMAC(uint8_t mac[6]) {
for (int16_t c = 0; c < tagDB.size(); c++) {
@@ -221,3 +222,28 @@ void clearPending(tagRecord* taginfo) {
}
taginfo->pending = false;
}
+
+void initAPconfig() {
+ LittleFS.begin(true);
+ File configFile = LittleFS.open("/current/apconfig.json", "r");
+ if (!configFile) {
+ //default values'
+ Serial.println("APconfig not found");
+ APconfig["channel"] = 0;
+ APconfig["alias"] = String();
+ return;
+ }
+ DeserializationError error = deserializeJson(APconfig, configFile);
+ if (error) {
+ configFile.close();
+ Serial.println("apconfig.json file corrupted, or not enough space in apconfig to hold it");
+ return;
+ }
+ configFile.close();
+}
+
+void saveAPconfig() {
+ fs::File configFile = LittleFS.open("/current/apconfig.json", "w");
+ serializeJson(APconfig, configFile);
+ configFile.close();
+}
\ No newline at end of file
diff --git a/ESP32_AP-Flasher/src/udp.cpp b/ESP32_AP-Flasher/src/udp.cpp
index 8215c0e6..8ec0c4c8 100644
--- a/ESP32_AP-Flasher/src/udp.cpp
+++ b/ESP32_AP-Flasher/src/udp.cpp
@@ -4,17 +4,18 @@
#include "AsyncUDP.h"
#include "commstructs.h"
#include "newproto.h"
+#include "tag_db.h"
+#include "web.h"
+#include "serial.h"
-#define PKT_AVAIL_DATA_REQ 0xE5
-#define PKT_AVAIL_DATA_INFO 0xE6
-#define PKT_XFER_COMPLETE 0xEA
-#define PKT_XFER_TIMEOUT 0xED
-#define PKT_CANCEL_XFER 0xEC
-#define PKT_ID_APS 0x80
+#define UDPIP IPAddress(239, 10, 0, 1)
+#define UDPPORT 16033
UDPcomm udpsync;
-uint8_t channelList[6] = {11, 15, 20, 25, 26, 27};
+extern uint8_t channelList[6];
+extern espSetChannelPower curChannel;
+extern uint16_t version;
void init_udp() {
udpsync.init();
@@ -29,63 +30,139 @@ UDPcomm::~UDPcomm() {
}
void UDPcomm::init() {
- if (udp.listenMulticast(IPAddress(239, 10, 0, 1), 16033)) {
+ if (udp.listenMulticast(UDPIP, UDPPORT)) {
udp.onPacket([this](AsyncUDPPacket packet) {
- this->processPacket(packet);
+ if (packet.remoteIP() != WiFi.localIP()) {
+ this->processPacket(packet);
+ }
});
}
+ setAPchannel();
}
void UDPcomm::processPacket(AsyncUDPPacket packet) {
- if (packet.data()[0] == PKT_AVAIL_DATA_INFO) {
- espAvailDataReq* adr = (espAvailDataReq*)&packet.data()[1];
- adr->src[7] = 0xFF;
- processDataReq(adr);
+ switch (packet.data()[0]) {
+ case PKT_AVAIL_DATA_INFO: {
+ espAvailDataReq* adr = (espAvailDataReq*)&packet.data()[1];
+ adr->src[7] = 0xFF;
+ processDataReq(adr);
+ break;
+ }
+ case PKT_XFER_COMPLETE: {
+ espXferComplete* xfc = (espXferComplete*)&packet.data()[1];
+ processXferComplete(xfc);
+ break;
+ }
+ case PKT_XFER_TIMEOUT: {
+ espXferComplete* xfc = (espXferComplete*)&packet.data()[1];
+ processXferTimeout(xfc);
+ break;
+ }
+ case PKT_AVAIL_DATA_REQ: {
+ pendingData* pending = (pendingData*)&packet.data()[1];
+ prepareExternalDataAvail(pending, packet.remoteIP());
+ break;
+ }
+ case PKT_APLIST_REQ: {
+ IPAddress senderIP = packet.remoteIP();
+
+ APlist APitem;
+ APitem.src = WiFi.localIP();
+ strcpy(APitem.alias, APconfig["alias"]);
+ APitem.channelId = curChannel.channel;
+ APitem.tagCount = getTagCount();
+ APitem.version = version;
+
+ uint8_t buffer[sizeof(struct APlist) + 1];
+ buffer[0] = PKT_APLIST_REPLY;
+ memcpy(buffer + 1, &APitem, sizeof(struct APlist));
+ udp.writeTo(buffer, sizeof(buffer), senderIP, UDPPORT);
+ break;
+ }
+ case PKT_APLIST_REPLY: {
+ APlist* APreply = (APlist*)&packet.data()[1];
+ //remove active channel from list
+ for (int i = 0; i < 6; i++) {
+ if (channelList[i] == APreply->channelId) channelList[i] = 0;
+ }
+ wsSendAPitem(APreply);
+ break;
+ }
}
- if (packet.data()[0] == PKT_XFER_COMPLETE) {
- espXferComplete* xfc = (espXferComplete*)&packet.data()[1];
- processXferComplete(xfc);
+}
+
+void autoselect(void* pvParameters) {
+ // reset channel list
+ uint8_t values[] = {11, 15, 20, 25, 26, 27};
+ memcpy(channelList, values, sizeof(values));
+ // wait 5s for channelList to collect all AP's
+ vTaskDelay(5000 / portTICK_PERIOD_MS);
+
+ curChannel.channel = 0;
+ for (int i = 0; i < 6; i++) {
+ if (channelList[i] > 0) {
+ curChannel.channel = channelList[i];
+ break;
+ }
}
- if (packet.data()[0] == PKT_XFER_TIMEOUT) {
- espXferComplete* xfc = (espXferComplete*)&packet.data()[1];
- processXferTimeout(xfc);
- }
- if (packet.data()[0] == PKT_AVAIL_DATA_REQ) {
- pendingData* pending = (pendingData*)&packet.data()[1];
- prepareExternalDataAvail(pending, packet.remoteIP());
- }
- if (packet.data()[0] == PKT_ID_APS) {
- Serial.println("ap list req");
- IPAddress senderIP = packet.remoteIP();
- unsigned int senderPort = packet.remotePort();
- //todo: autoselect channel
+ if (curChannel.channel == 0) {
+ curChannel.channel = 11;
+ }
+ APconfig["channel"] = curChannel.channel;
+ do {
+ vTaskDelay(1000 / portTICK_PERIOD_MS);
+ } while (!version);
+
+ sendChannelPower(&curChannel);
+ saveAPconfig();
+
+ vTaskDelay(1000 / portTICK_PERIOD_MS);
+ vTaskDelete(NULL);
+}
+
+void UDPcomm::getAPList() {
+ APlist APitem;
+ APitem.src = WiFi.localIP();
+ strcpy(APitem.alias, APconfig["alias"]);
+ APitem.channelId = curChannel.channel;
+ APitem.tagCount = getTagCount();
+ APitem.version = version;
+ wsSendAPitem(&APitem);
+
+ if (APconfig["channel"].as() == 0) {
+ xTaskCreate(autoselect, "autoselect", 10000, NULL, configMAX_PRIORITIES - 10, NULL);
}
+
+ uint8_t buffer[sizeof(struct APlist) + 1];
+ buffer[0] = PKT_APLIST_REQ;
+ memcpy(buffer + 1, &APitem, sizeof(struct APlist));
+ udp.writeTo(buffer, sizeof(buffer), UDPIP, UDPPORT);
}
void UDPcomm::netProcessDataReq(struct espAvailDataReq* eadr) {
uint8_t buffer[sizeof(struct espAvailDataReq) + 1];
buffer[0] = PKT_AVAIL_DATA_INFO;
memcpy(buffer + 1, eadr, sizeof(struct espAvailDataReq));
- udp.writeTo(buffer, sizeof(buffer), IPAddress(239, 10, 0, 1), 16033);
+ udp.writeTo(buffer, sizeof(buffer), UDPIP, UDPPORT);
}
void UDPcomm::netProcessXferComplete(struct espXferComplete* xfc) {
uint8_t buffer[sizeof(struct espXferComplete) + 1];
buffer[0] = PKT_XFER_COMPLETE;
memcpy(buffer + 1, xfc, sizeof(struct espXferComplete));
- udp.writeTo(buffer, sizeof(buffer), IPAddress(239, 10, 0, 1), 16033);
+ udp.writeTo(buffer, sizeof(buffer), UDPIP, UDPPORT);
}
void UDPcomm::netProcessXferTimeout(struct espXferComplete* xfc) {
uint8_t buffer[sizeof(struct espXferComplete) + 1];
buffer[0] = PKT_XFER_TIMEOUT;
memcpy(buffer + 1, xfc, sizeof(struct espXferComplete));
- udp.writeTo(buffer, sizeof(buffer), IPAddress(239, 10, 0, 1), 16033);
+ udp.writeTo(buffer, sizeof(buffer), UDPIP, UDPPORT);
}
void UDPcomm::netSendDataAvail(struct pendingData* pending) {
uint8_t buffer[sizeof(struct pendingData) + 1];
buffer[0] = PKT_AVAIL_DATA_REQ;
memcpy(buffer + 1, pending, sizeof(struct pendingData));
- udp.writeTo(buffer, sizeof(buffer), IPAddress(239, 10, 0, 1), 16033);
+ udp.writeTo(buffer, sizeof(buffer), UDPIP, UDPPORT);
}
\ No newline at end of file
diff --git a/ESP32_AP-Flasher/src/web.cpp b/ESP32_AP-Flasher/src/web.cpp
index ef1e21bf..51d16795 100644
--- a/ESP32_AP-Flasher/src/web.cpp
+++ b/ESP32_AP-Flasher/src/web.cpp
@@ -16,6 +16,7 @@
#include "newproto.h"
#include "settings.h"
#include "tag_db.h"
+#include "udp.h"
extern uint8_t data_to_send[];
@@ -168,6 +169,24 @@ void wsSendTaginfo(uint8_t mac[6]) {
xSemaphoreGive(wsMutex);
}
+void wsSendAPitem(struct APlist* apitem) {
+ DynamicJsonDocument doc(250);
+ JsonObject ap = doc.createNestedObject("apitem");
+
+ char version_str[6];
+ sprintf(version_str, "%04X", apitem->version);
+
+ ap["ip"] = ((IPAddress)apitem->src).toString();
+ ap["alias"] = apitem->alias;
+ ap["count"] = apitem->tagCount;
+ ap["channel"] = apitem->channelId;
+ ap["version"] = version_str;
+
+ if (wsMutex) xSemaphoreTake(wsMutex, portMAX_DELAY);
+ ws.textAll(doc.as());
+ if (wsMutex) xSemaphoreGive(wsMutex);
+}
+
void init_web() {
LittleFS.begin(true);
@@ -273,6 +292,36 @@ void init_web() {
}
});
+ server.on("/get_ap_list", HTTP_GET, [](AsyncWebServerRequest *request) {
+ UDPcomm udpsync;
+ udpsync.getAPList();
+ File configFile = LittleFS.open("/current/apconfig.json", "r");
+ if (!configFile) {
+ request->send(500, "text/plain", "Error opening apconfig.json file");
+ return;
+ }
+ request->send(configFile, "application/json");
+ configFile.close();
+ });
+
+ server.on("/save_apcfg", HTTP_POST, [](AsyncWebServerRequest *request) {
+ if (request->hasParam("alias", true) && request->hasParam("channel", true)) {
+ APconfig["alias"] = request->getParam("alias", true)->value();
+ APconfig["channel"] = request->getParam("channel", true)->value();
+ saveAPconfig();
+ setAPchannel();
+ }
+ request->send(200, "text/plain", "Ok, saved");
+ });
+
+ server.on("/backup_db", HTTP_GET, [](AsyncWebServerRequest *request) {
+ saveDB("/current/tagDB.json");
+ File file = LittleFS.open("/current/tagDB.json", "r");
+ AsyncWebServerResponse *response = request->beginResponse(file, "tagDB.json", String(), true);
+ request->send(response);
+ file.close();
+ });
+
server.onNotFound([](AsyncWebServerRequest *request) {
if (request->url() == "/" || request->url() == "index.htm") {
request->send(200, "text/html", "-");
@@ -291,7 +340,6 @@ void doImageUpload(AsyncWebServerRequest *request, String filename, size_t index
} else {
filename = "unknown.jpg";
}
- Serial.print((String) "UploadStart: " + filename);
request->_tempFile = LittleFS.open("/" + filename, "w");
}
if (len) {
@@ -299,7 +347,6 @@ void doImageUpload(AsyncWebServerRequest *request, String filename, size_t index
request->_tempFile.write(data, len);
}
if (final) {
- Serial.println((String) " End: " + filename + ", " + index + len);
request->_tempFile.close();
if (request->hasParam("mac", true)) {
String dst = request->getParam("mac", true)->value();