Add option for AP discovery type (#351)

This commit is contained in:
Jonny Bergdahl
2024-11-02 23:10:00 +01:00
committed by GitHub
parent a57c797542
commit d4ccaf6027
8 changed files with 75 additions and 36 deletions

3
.gitignore vendored
View File

@@ -31,3 +31,6 @@ $PROJECT_DIR/
# OS generated files # OS generated files
.DS_Store .DS_Store
# Jetbrains IDE
.idea/

View File

@@ -73,6 +73,7 @@ struct Config {
uint8_t sleepTime1; uint8_t sleepTime1;
uint8_t sleepTime2; uint8_t sleepTime2;
uint8_t ble; uint8_t ble;
uint8_t discovery;
String repo; String repo;
String env; String env;
}; };

View File

@@ -1,26 +1,30 @@
#include <Arduino.h> #include <Arduino.h>
#include "AsyncUDP.h" #include "AsyncUDP.h"
#include "tag_db.h"
#ifndef defudpcomm #ifndef defudpcomm
#define defudpcomm #define defudpcomm
extern Config config;
class UDPcomm { class UDPcomm {
public: public:
UDPcomm(); UDPcomm();
~UDPcomm(); ~UDPcomm();
void init(); void init();
void getAPList(); void getAPList();
void netProcessDataReq(struct espAvailDataReq* eadr); void netProcessDataReq(struct espAvailDataReq* eadr);
void netProcessXferComplete(struct espXferComplete* xfc); void netProcessXferComplete(struct espXferComplete* xfc);
void netProcessXferTimeout(struct espXferComplete* xfc); void netProcessXferTimeout(struct espXferComplete* xfc);
void netSendDataAvail(struct pendingData* pending); void netSendDataAvail(struct pendingData* pending);
void netTaginfo(struct TagInfo* taginfoitem); void netTaginfo(struct TagInfo* taginfoitem);
private:
AsyncUDP udp; private:
void processPacket(AsyncUDPPacket packet); AsyncUDP udp;
void processPacket(AsyncUDPPacket packet);
void writeUdpPacket(uint8_t* buffer, uint16_t len, IPAddress senderIP);
}; };
#endif #endif
void init_udp(); void init_udp();

View File

@@ -308,7 +308,7 @@ void clearPending(tagRecord* taginfo) {
} }
void initAPconfig() { void initAPconfig() {
DynamicJsonDocument APconfig(500); DynamicJsonDocument APconfig(768);
File configFile = contentFS->open("/current/apconfig.json", "r"); File configFile = contentFS->open("/current/apconfig.json", "r");
if (configFile) { if (configFile) {
DeserializationError error = deserializeJson(APconfig, configFile); DeserializationError error = deserializeJson(APconfig, configFile);
@@ -333,6 +333,7 @@ void initAPconfig() {
config.sleepTime1 = APconfig.containsKey("sleeptime1") ? APconfig["sleeptime1"] : 0; config.sleepTime1 = APconfig.containsKey("sleeptime1") ? APconfig["sleeptime1"] : 0;
config.sleepTime2 = APconfig.containsKey("sleeptime2") ? APconfig["sleeptime2"] : 0; config.sleepTime2 = APconfig.containsKey("sleeptime2") ? APconfig["sleeptime2"] : 0;
config.ble = APconfig.containsKey("ble") ? APconfig["ble"] : 0; config.ble = APconfig.containsKey("ble") ? APconfig["ble"] : 0;
config.discovery = APconfig.containsKey("discovery") ? APconfig["discovery"] : 0;
#ifdef BLE_ONLY #ifdef BLE_ONLY
config.ble = true; config.ble = true;
#endif #endif
@@ -370,6 +371,7 @@ void saveAPconfig() {
APconfig["ble"] = config.ble; APconfig["ble"] = config.ble;
APconfig["repo"] = config.repo; APconfig["repo"] = config.repo;
APconfig["env"] = config.env; APconfig["env"] = config.env;
APconfig["discovery"] = config.discovery;
serializeJsonPretty(APconfig, configFile); serializeJsonPretty(APconfig, configFile);
configFile.close(); configFile.close();
xSemaphoreGive(fsMutex); xSemaphoreGive(fsMutex);

View File

@@ -31,12 +31,22 @@ UDPcomm::~UDPcomm() {
} }
void UDPcomm::init() { void UDPcomm::init() {
if (udp.listenMulticast(UDPIP, UDPPORT)) { if (config.discovery == 0) {
udp.onPacket([this](AsyncUDPPacket packet) { if (udp.listenMulticast(UDPIP, UDPPORT)) {
if (packet.remoteIP() != WiFi.localIP()) { udp.onPacket([this](AsyncUDPPacket packet) {
this->processPacket(packet); if (packet.remoteIP() != WiFi.localIP()) {
} this->processPacket(packet);
}); }
});
}
} else {
if (udp.listen(UDPPORT)) {
udp.onPacket([this](AsyncUDPPacket packet) {
if (packet.isBroadcast() && packet.remoteIP() != WiFi.localIP()) {
this->processPacket(packet);
}
});
}
} }
setAPchannel(); setAPchannel();
} }
@@ -87,7 +97,7 @@ void UDPcomm::processPacket(AsyncUDPPacket packet) {
uint8_t buffer[sizeof(struct APlist) + 1]; uint8_t buffer[sizeof(struct APlist) + 1];
buffer[0] = PKT_APLIST_REPLY; buffer[0] = PKT_APLIST_REPLY;
memcpy(buffer + 1, &APitem, sizeof(struct APlist)); memcpy(buffer + 1, &APitem, sizeof(struct APlist));
udp.writeTo(buffer, sizeof(buffer), senderIP, UDPPORT); writeUdpPacket(buffer, sizeof(buffer), senderIP);
break; break;
} }
case PKT_APLIST_REPLY: { case PKT_APLIST_REPLY: {
@@ -158,40 +168,48 @@ void UDPcomm::getAPList() {
uint8_t buffer[sizeof(struct APlist) + 1]; uint8_t buffer[sizeof(struct APlist) + 1];
buffer[0] = PKT_APLIST_REQ; buffer[0] = PKT_APLIST_REQ;
memcpy(buffer + 1, &APitem, sizeof(struct APlist)); memcpy(buffer + 1, &APitem, sizeof(struct APlist));
udp.writeTo(buffer, sizeof(buffer), UDPIP, UDPPORT); writeUdpPacket(buffer, sizeof(buffer), UDPIP);
} }
void UDPcomm::netProcessDataReq(struct espAvailDataReq* eadr) { void UDPcomm::netProcessDataReq(struct espAvailDataReq* eadr) {
uint8_t buffer[sizeof(struct espAvailDataReq) + 1]; uint8_t buffer[sizeof(struct espAvailDataReq) + 1];
buffer[0] = PKT_AVAIL_DATA_INFO; buffer[0] = PKT_AVAIL_DATA_INFO;
memcpy(buffer + 1, eadr, sizeof(struct espAvailDataReq)); memcpy(buffer + 1, eadr, sizeof(struct espAvailDataReq));
udp.writeTo(buffer, sizeof(buffer), UDPIP, UDPPORT); writeUdpPacket(buffer, sizeof(buffer), UDPIP);
} }
void UDPcomm::netProcessXferComplete(struct espXferComplete* xfc) { void UDPcomm::netProcessXferComplete(struct espXferComplete* xfc) {
uint8_t buffer[sizeof(struct espXferComplete) + 1]; uint8_t buffer[sizeof(struct espXferComplete) + 1];
buffer[0] = PKT_XFER_COMPLETE; buffer[0] = PKT_XFER_COMPLETE;
memcpy(buffer + 1, xfc, sizeof(struct espXferComplete)); memcpy(buffer + 1, xfc, sizeof(struct espXferComplete));
udp.writeTo(buffer, sizeof(buffer), UDPIP, UDPPORT); writeUdpPacket(buffer, sizeof(buffer), UDPIP);
} }
void UDPcomm::netProcessXferTimeout(struct espXferComplete* xfc) { void UDPcomm::netProcessXferTimeout(struct espXferComplete* xfc) {
uint8_t buffer[sizeof(struct espXferComplete) + 1]; uint8_t buffer[sizeof(struct espXferComplete) + 1];
buffer[0] = PKT_XFER_TIMEOUT; buffer[0] = PKT_XFER_TIMEOUT;
memcpy(buffer + 1, xfc, sizeof(struct espXferComplete)); memcpy(buffer + 1, xfc, sizeof(struct espXferComplete));
udp.writeTo(buffer, sizeof(buffer), UDPIP, UDPPORT); writeUdpPacket(buffer, sizeof(buffer), UDPIP);
} }
void UDPcomm::netSendDataAvail(struct pendingData* pending) { void UDPcomm::netSendDataAvail(struct pendingData* pending) {
uint8_t buffer[sizeof(struct pendingData) + 1]; uint8_t buffer[sizeof(struct pendingData) + 1];
buffer[0] = PKT_AVAIL_DATA_REQ; buffer[0] = PKT_AVAIL_DATA_REQ;
memcpy(buffer + 1, pending, sizeof(struct pendingData)); memcpy(buffer + 1, pending, sizeof(struct pendingData));
udp.writeTo(buffer, sizeof(buffer), UDPIP, UDPPORT); writeUdpPacket(buffer, sizeof(buffer), UDPIP);
} }
void UDPcomm::netTaginfo(struct TagInfo* taginfoitem) { void UDPcomm::netTaginfo(struct TagInfo* taginfoitem) {
uint8_t buffer[sizeof(struct TagInfo) + 1]; uint8_t buffer[sizeof(struct TagInfo) + 1];
buffer[0] = PKT_TAGINFO; buffer[0] = PKT_TAGINFO;
memcpy(buffer + 1, taginfoitem, sizeof(struct TagInfo)); memcpy(buffer + 1, taginfoitem, sizeof(struct TagInfo));
udp.writeTo(buffer, sizeof(buffer), UDPIP, UDPPORT); writeUdpPacket(buffer, sizeof(buffer), UDPIP);
}
void UDPcomm::writeUdpPacket(uint8_t *buffer, uint16_t len, IPAddress senderIP) {
if (config.discovery == 0) {
udp.writeTo(buffer, len, senderIP, UDPPORT);
} else {
udp.broadcastTo(buffer, len, UDPPORT);
}
} }

View File

@@ -312,7 +312,7 @@ void init_web() {
Serial.println("getQueueItem: no queue item"); Serial.println("getQueueItem: no queue item");
request->send(404, "text/plain", "File not found"); request->send(404, "text/plain", "File not found");
return; return;
} }
if (queueItem->data == nullptr) { if (queueItem->data == nullptr) {
fs::File file = contentFS->open(queueItem->filename); fs::File file = contentFS->open(queueItem->filename);
if (file) { if (file) {
@@ -517,7 +517,7 @@ void init_web() {
udpsync.getAPList(); udpsync.getAPList();
AsyncResponseStream *response = request->beginResponseStream("application/json"); AsyncResponseStream *response = request->beginResponseStream("application/json");
response->print("{"); response->print("{");
#ifdef C6_OTA_FLASHING #ifdef C6_OTA_FLASHING
response->print("\"C6\": \"1\", "); response->print("\"C6\": \"1\", ");
#else #else
@@ -625,6 +625,9 @@ void init_web() {
setenv("TZ", config.timeZone, 1); setenv("TZ", config.timeZone, 1);
tzset(); tzset();
} }
if (request->hasParam("discovery", true)) {
config.discovery = static_cast<uint8_t>(request->getParam("discovery", true)->value().toInt());
}
if (request->hasParam("repo", true)) { if (request->hasParam("repo", true)) {
config.repo = request->getParam("repo", true)->value(); config.repo = request->getParam("repo", true)->value();
} }
@@ -988,4 +991,4 @@ void dotagDBUpload(AsyncWebServerRequest *request, String filename, size_t index
loadDB("/current/tagDBrestored.json"); loadDB("/current/tagDBrestored.json");
request->send(200, "text/plain", "Ok, restored."); request->send(200, "text/plain", "Ok, restored.");
} }
} }

View File

@@ -234,7 +234,7 @@
<h4>Mode</h4> <h4>Mode</h4>
<div style="max-width:400px;"> <div style="max-width:400px;">
<button class="button" id="doAutoflash">Automatic flash</button><br><br> <button class="button" id="doAutoflash">Automatic flash</button><br><br>
With automatic flash, a tag is flashed to the latest firmware as soon as you connect it. With automatic flash, a tag is flashed to the latest firmware as soon as you connect it.
It sets the mac automatically, tries to recognize the type, and starts flashing. Currently, Solum M2 tags only. It sets the mac automatically, tries to recognize the type, and starts flashing. Currently, Solum M2 tags only.
<br><br> <br><br>
<button class="button" id="doUSBflash">Command line</button><br><br> <button class="button" id="doUSBflash">Command line</button><br><br>
@@ -375,7 +375,7 @@ options:
</select> </select>
</p> </p>
<p <p
title="Stops updates at night, and put the tags to sleep. title="Stops updates at night, and put the tags to sleep.
During the configured night time, this overrides the maximum sleep time."> During the configured night time, this overrides the maximum sleep time.">
<label for="apcnight1">No updates between</label> <label for="apcnight1">No updates between</label>
<select id="apcnight1"></select> <select id="apcnight1"></select>
@@ -400,7 +400,7 @@ options:
<p <p
title="* Work in progress * When locking the tag inventory, the AP will only title="* Work in progress * When locking the tag inventory, the AP will only
show tags that are already in the database. For now, the AP will still keep answering show tags that are already in the database. For now, the AP will still keep answering
new tags, because that needs to be fixed in the radio firmware. new tags, because that needs to be fixed in the radio firmware.
This will probably change in the future."> This will probably change in the future.">
<label for="apclock">Lock tag inventory</label> <label for="apclock">Lock tag inventory</label>
<select id="apclock"> <select id="apclock">
@@ -471,6 +471,13 @@ options:
</optgroup> </optgroup>
</select> </select>
</p> </p>
<p title="Set to Broadcast if using a multi WiFi AP setup that does not support IGMP sniffing">
<label for="apcdiscovery">AP discovery method</label>
<select id="apcdiscovery">
<option value="0" selected>Multicast</option>
<option value="1">Broadcast</option>
</select>
</p>
<p> <p>
<input type="button" value="Save" id="apcfgsave"><span id="apcfgmsg"></span> <input type="button" value="Save" id="apcfgsave"><span id="apcfgmsg"></span>
</p> </p>

View File

@@ -784,6 +784,7 @@ document.addEventListener("loadTab", function (event) {
$("#apctimezone").value = data.timezone; $("#apctimezone").value = data.timezone;
$("#apcnight1").value = data.sleeptime1; $("#apcnight1").value = data.sleeptime1;
$("#apcnight2").value = data.sleeptime2; $("#apcnight2").value = data.sleeptime2;
$("#apcdiscovery").value = data.discovery;
} }
}) })
$('#apcfgmsg').innerHTML = ''; $('#apcfgmsg').innerHTML = '';
@@ -821,7 +822,7 @@ $('#apcfgsave').onclick = function () {
formData.append('timezone', $('#apctimezone').value); formData.append('timezone', $('#apctimezone').value);
formData.append('sleeptime1', $('#apcnight1').value); formData.append('sleeptime1', $('#apcnight1').value);
formData.append('sleeptime2', $('#apcnight2').value); formData.append('sleeptime2', $('#apcnight2').value);
formData.append('discovery', $('#apcdiscovery').value)
fetch("save_apcfg", { fetch("save_apcfg", {
method: "POST", method: "POST",
body: formData body: formData