mirror of
https://github.com/OpenEPaperLink/OpenEPaperLink.git
synced 2026-03-21 11:06:49 +01:00
auto channel select, ap config screen
This commit is contained in:
@@ -47,6 +47,60 @@
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div id="apconfigbox">
|
||||
<div class="closebtn">✖</div>
|
||||
<h3 id="cfgmac">Access Point config</h3>
|
||||
<p>
|
||||
<label for="apcfgalias">Alias</label>
|
||||
<input id="apcfgalias" type="text">
|
||||
</p>
|
||||
<p>
|
||||
<label for="apcfgchid">Channel</label>
|
||||
<select id="apcfgchid">
|
||||
<option value="0">auto</option>
|
||||
<option value="11">11</option>
|
||||
<option value="15">15</option>
|
||||
<option value="20">20</option>
|
||||
<option value="25">25</option>
|
||||
<option value="26">26</option>
|
||||
<option value="27">27</option>
|
||||
</select>
|
||||
</p>
|
||||
<p>
|
||||
<input type="button" value="Save" id="apcfgsave">
|
||||
</p>
|
||||
<!--
|
||||
<p><pre>
|
||||
work in progress
|
||||
- upload tagDB
|
||||
- update webinterface from github
|
||||
- update APtag FW from github
|
||||
- update all tag FW from github
|
||||
- update esp32 fw
|
||||
</pre>
|
||||
</p>
|
||||
-->
|
||||
<p>
|
||||
Active access points:<br>
|
||||
<table id="aptable">
|
||||
<tr>
|
||||
<th>ip</th>
|
||||
<th>alias</th>
|
||||
<th>tags</th>
|
||||
<th>ch</th>
|
||||
<th>fw ver</th>
|
||||
</tr>
|
||||
</table>
|
||||
</p>
|
||||
<p>
|
||||
<span id="rebootbutton">reboot AP</span>
|
||||
<a href="/backup_db" id="downloadDBbutton">download tagDB</a>
|
||||
</p>
|
||||
<p>
|
||||
<a href="https://github.com/jjwbruijn/OpenEPaperLink" target="_new">Github OpenEPaperLink</a>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<form>
|
||||
<div class="container">
|
||||
|
||||
@@ -55,8 +109,8 @@
|
||||
<div class="actionbox">
|
||||
<div>
|
||||
<div>Currently active tags:</div>
|
||||
<div class="rebootbtn"><span id="rebootbutton">reboot AP</span></div>
|
||||
<div class="editbtn"><a href="/edit" target="littlefs" class="filebutton">edit littleFS</a></div>
|
||||
<div><span id="apconfigbutton">AP config</span></div>
|
||||
<div><a href="/edit" target="littlefs" class="filebutton">edit littleFS</a></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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 = "<a href=\"http://" + msg.apitem.ip + "\" target=\"_new\">" + msg.apitem.ip + "</a>";
|
||||
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];
|
||||
|
||||
@@ -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)
|
||||
@@ -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();
|
||||
void refreshAllPending();
|
||||
void setAPchannel();
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
#include <Arduino.h>
|
||||
|
||||
extern struct espSetChannelPower curChannel;
|
||||
extern uint16_t version;
|
||||
|
||||
void zbsTx(uint8_t* packetdata, uint8_t len);
|
||||
void zbsRxTask(void* parameter);
|
||||
|
||||
|
||||
@@ -49,6 +49,7 @@ class tagRecord {
|
||||
};
|
||||
|
||||
extern std::vector<tagRecord*> 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)
|
||||
@@ -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);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
|
||||
#include<Arduino.h>
|
||||
#include <Arduino.h>
|
||||
#include <AsyncTCP.h>
|
||||
#include <ESPAsyncWebServer.h>
|
||||
|
||||
@@ -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;
|
||||
@@ -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
|
||||
|
||||
@@ -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();
|
||||
|
||||
|
||||
@@ -432,4 +432,17 @@ void refreshAllPending() {
|
||||
wsSendTaginfo(taginfo->mac);
|
||||
}
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
void setAPchannel() {
|
||||
if (APconfig["channel"].as<int>() == 0) {
|
||||
// trigger channel autoselect
|
||||
UDPcomm udpsync;
|
||||
udpsync.getAPList();
|
||||
} else {
|
||||
if (curChannel.channel != APconfig["channel"].as<int>()) {
|
||||
curChannel.channel = APconfig["channel"].as<int>();
|
||||
if (version) sendChannelPower(&curChannel);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,12 +2,13 @@
|
||||
|
||||
#include <Arduino.h>
|
||||
#include <ArduinoJson.h>
|
||||
|
||||
#include <FS.h>
|
||||
#include <vector>
|
||||
|
||||
#include "LittleFS.h"
|
||||
|
||||
std::vector<tagRecord*> 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();
|
||||
}
|
||||
@@ -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<int>() == 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);
|
||||
}
|
||||
@@ -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<String>());
|
||||
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();
|
||||
|
||||
Reference in New Issue
Block a user