kopia lustrzana https://github.com/ozarchie/EQMOD-ETX
488 wiersze
16 KiB
C++
488 wiersze
16 KiB
C++
/**@file*/
|
|
// HBXSerialServer.ino
|
|
// https://esp-idf.readthedocs.io/en/latest/api-reference/wifi/esp_now.html
|
|
|
|
// Init ESP Now with fallback
|
|
void InitESPNow() {
|
|
WiFi.disconnect();
|
|
if (esp_now_init() == ESP_OK) {
|
|
dbgSerial.println("ESPNow Init Success");
|
|
}
|
|
else {
|
|
dbgSerial.println("ESPNow Init Failed");
|
|
// Retry InitESPNow, add a counter and then restart?
|
|
// InitESPNow();
|
|
// or Simply Restart
|
|
ESP.restart();
|
|
}
|
|
}
|
|
|
|
// Handle ESP_NOW WiFi data
|
|
// Data in recvWiFi.text, length recvWiFi.len
|
|
void recvCallBack(const uint8_t *senderMac, const uint8_t *incomingData, int len) {
|
|
|
|
// Get data from WiFi buffer
|
|
memcpy(&recvWiFi.text, incomingData, len); // Receive data from EQMOD Tx
|
|
recvWiFi.text[len] = 0; // Null terminate
|
|
recvWiFi.len = len;
|
|
|
|
// Check if serial device is requesting restart
|
|
if ((len == 20) && ((strncmp(recvWiFi.text, "Mount, please reply", 15) == 0))) {
|
|
// Capture the serial device mac address
|
|
for (byte n = 0; n < ESP_NOW_ETH_ALEN; n++) {
|
|
serial_peer.peer_addr[n] = senderMac[n];
|
|
}
|
|
// Discard data from reconnect request, clear flags
|
|
recvWiFi.len = 0;
|
|
Connected = false;
|
|
dataSending = false;
|
|
// Reply to reconnect request
|
|
strcpy(sendWiFi.text, "EQMOD WiFi Mount V1.0\n");
|
|
sendWiFi.len = sizeof("EQMOD WiFi Mount V1.0\n");
|
|
dbgSerial.println("Reconnecting");
|
|
sendData(&serial_peer);
|
|
return;
|
|
}
|
|
}
|
|
|
|
// Send data to ESP_NOW
|
|
void sendData(const esp_now_peer_info_t* s_peer) {
|
|
// If first time, create a peer2peer connection with the sender mac address
|
|
if (!Connected) {
|
|
esp_now_add_peer(s_peer); // Only one paired device - the first one to respond
|
|
}
|
|
|
|
// Send data, if not waiting for previous send to complete
|
|
if (!dataSending) {
|
|
memcpy(sendWiFi8, &sendWiFi, sendWiFi.len); // Need to satisfy esp_now
|
|
esp_now_send(serial_peer.peer_addr, sendWiFi8, sendWiFi.len);
|
|
dataSending = true;
|
|
}
|
|
}
|
|
|
|
// Get Send data status
|
|
void sendCallBack(const uint8_t* mac, esp_now_send_status_t sendStatus) {
|
|
if (sendStatus == 0) {
|
|
sendWiFi.len = 0; // Data successfully sent
|
|
Connected = true;
|
|
dataSending = false;
|
|
}
|
|
// Do some error checking?
|
|
}
|
|
|
|
// Put received WiFi (UDP/ESP_NOW) data into the mount input data buffer for processing
|
|
// Data in recvWiFi.text, length recvWiFi.len
|
|
void putRxDataIntoMountInputBuffer(void) {
|
|
uint8_t n;
|
|
n = 0;
|
|
while (n < recvWiFi.len) {
|
|
EQGRxBuffer[EQGRxiPtr++] = recvWiFi.text[n];
|
|
EQGRxiPtr &= EQGMASK;
|
|
n += 1;
|
|
}
|
|
recvWiFi.len = 0;
|
|
}
|
|
|
|
// Get mount data to send to WiFi (UDP/NOW) into WiFi buffer
|
|
// Data in sendWiFi.text, length sendWiFi.len
|
|
void getTxDataFromMountOutputBuffer(void) {
|
|
while (EQGTxoPtr != EQGTxiPtr) {
|
|
//jma dbgSerial.write(EQGTxBuffer[EQGTxoPtr]);
|
|
sendWiFi.text[TxDIndex++] = EQGTxBuffer[EQGTxoPtr++];
|
|
EQGTxoPtr &= EQGMASK;
|
|
}
|
|
// Send when a CR is detected
|
|
if (sendWiFi.text[TxDIndex - 1] == 0x0d) {
|
|
sendWiFi.text[TxDIndex] = 0;
|
|
sendWiFi.len = TxDIndex;
|
|
}
|
|
}
|
|
|
|
// Webserver functions for ssid, pass, telescope etc
|
|
// =================================================
|
|
|
|
void onRequest(AsyncWebServerRequest *request){
|
|
//Handle Unknown Request
|
|
request->send(404, "text/plain", "The content you are looking for was not found.");
|
|
}
|
|
|
|
void onBody(AsyncWebServerRequest *request, uint8_t *data, size_t len, size_t index, size_t total){
|
|
if (!index) {
|
|
dbgSerial.printf("BodyStart: %u B\n", total);
|
|
}
|
|
for (size_t i = 0; i < len; i++) {
|
|
dbgSerial.write(data[i]);
|
|
}
|
|
if (index + len == total) {
|
|
dbgSerial.printf("BodyEnd: %u B\n", total);
|
|
}
|
|
}
|
|
|
|
void onUpload(AsyncWebServerRequest *request, String filename, size_t index, uint8_t *data, size_t len, bool final){
|
|
if (!index) {
|
|
dbgSerial.printf("UploadStart: %s\n", filename.c_str());
|
|
}
|
|
for (size_t i = 0; i < len; i++) {
|
|
dbgSerial.write(data[i]);
|
|
}
|
|
if (final) {
|
|
dbgSerial.printf("UploadEnd: %s, %u B\n", filename.c_str(), index + len);
|
|
}
|
|
}
|
|
|
|
void AsyncServerResponseSetup(void) {
|
|
|
|
// respond to GET requests on URL /scan
|
|
//First request will return 0 results unless you start scan from somewhere else (loop/setup)
|
|
//Do not request more often than 3-5 seconds
|
|
|
|
server.on("/scan", HTTP_GET, [](AsyncWebServerRequest *request){
|
|
String json = "[";
|
|
int n = WiFi.scanComplete();
|
|
if(n == -2){
|
|
WiFi.scanNetworks(true);
|
|
} else if(n){
|
|
for (int i = 0; i < n; ++i) {
|
|
if(i) json += ",";
|
|
json += "{";
|
|
json += "\"rssi\":"+String(WiFi.RSSI(i));
|
|
json += ",\"ssid\":\""+WiFi.SSID(i)+"\"";
|
|
json += ",\"bssid\":\""+WiFi.BSSIDstr(i)+"\"";
|
|
json += ",\"channel\":"+String(WiFi.channel(i));
|
|
json += ",\"secure\":"+String(WiFi.encryptionType(i));
|
|
// json += ",\"hidden\":"+String(WiFi.isHidden(i)?"true":"false");
|
|
json += "}\r\n";
|
|
}
|
|
WiFi.scanDelete();
|
|
if(WiFi.scanComplete() == -2){
|
|
WiFi.scanNetworks(true);
|
|
}
|
|
}
|
|
json += "]";
|
|
request->send(200, "application/json", json);
|
|
json = String();
|
|
});
|
|
|
|
// upload a file to /upload
|
|
server.on("/upload", HTTP_POST, [](AsyncWebServerRequest *request){
|
|
request->send(200);
|
|
}, onUpload);
|
|
|
|
// send /index.htm file when /index is requested
|
|
server.on("/index", HTTP_ANY, [](AsyncWebServerRequest *request){
|
|
request->send(SPIFFS, "/www/index.htm");
|
|
});
|
|
|
|
// send /settings.htm file when /settings is requested
|
|
server.on("/settings", HTTP_GET, [](AsyncWebServerRequest *request) {
|
|
request->send(SPIFFS, "/www/settings.htm");
|
|
int paramsNr = request->params();
|
|
dbgSerial.print("Number of settings parameters: "); dbgSerial.println(paramsNr);
|
|
if (paramsNr) {
|
|
for (int i = 0; i < paramsNr; i++) {
|
|
AsyncWebParameter* p = request->getParam(i);
|
|
dbgSerial.print("Param name: "); dbgSerial.print(p->name());
|
|
dbgSerial.print(", value: "); dbgSerial.println(p->value());
|
|
if ((p->name()) == "ssid")
|
|
ssid = (p->value());
|
|
if ((p->name()) == "pass")
|
|
pass = (p->value());
|
|
if ((p->name()) == "scope")
|
|
strcpy(scope, (p->value()).c_str());
|
|
}
|
|
|
|
preferences.begin("EQG2HBX", false); // Access EQG2HBX namespace
|
|
|
|
dbgSerial.print("Original - ssid: "); dbgSerial.print(preferences.getString("STA_SSID"));
|
|
dbgSerial.print(", pass: "); dbgSerial.print(preferences.getString("STA_PASS"));
|
|
dbgSerial.print(", Telescope: "); dbgSerial.println(preferences.getString("TELESCOPE"));
|
|
|
|
if (strlen(ssid.c_str()) != 0) preferences.putString("STA_SSID", ssid);
|
|
if (strlen(pass.c_str()) != 0) preferences.putString("STA_PASS", pass);
|
|
if (strlen(scope) != 0) preferences.putString("TELESCOPE", scope);
|
|
|
|
dbgSerial.print("Updated - ssid: "); dbgSerial.print(preferences.getString("STA_SSID"));
|
|
dbgSerial.print(", pass: "); dbgSerial.print(preferences.getString("STA_PASS"));
|
|
dbgSerial.print(", Telescope: "); dbgSerial.println(preferences.getString("TELESCOPE"));
|
|
preferences.end();
|
|
}
|
|
});
|
|
|
|
// HTTP basic authentication
|
|
server.on("/login", HTTP_GET, [](AsyncWebServerRequest *request){
|
|
dbgSerial.print("B4 http_username: ");
|
|
dbgSerial.print(http_username);
|
|
dbgSerial.print(", http_password: ");
|
|
dbgSerial.println(http_password);
|
|
|
|
if(!request->authenticate(http_username, http_password))
|
|
return request->requestAuthentication();
|
|
else {
|
|
dbgSerial.print("http_username: ");
|
|
dbgSerial.print(http_username);
|
|
dbgSerial.print(", http_password: ");
|
|
dbgSerial.println(http_password);
|
|
}
|
|
request->send(200, "text/plain", "Login Success!");
|
|
loginValid = true;
|
|
});
|
|
|
|
// Simple Firmware Update Form
|
|
|
|
// send /update.htm file when /index is requested
|
|
server.on("/update", HTTP_GET, [](AsyncWebServerRequest *request) {
|
|
if (loginValid == true) {
|
|
request->send(SPIFFS, "/update.htm");
|
|
}
|
|
else {
|
|
request->send(200, "text/plain", "Please Login");
|
|
}
|
|
});
|
|
|
|
// Process POST from Update Form
|
|
server.on("/update", HTTP_POST, [](AsyncWebServerRequest *request){
|
|
shouldReboot = !Update.hasError();
|
|
AsyncWebServerResponse *response = request->beginResponse(200, "text/plain", shouldReboot?"OK":"FAIL");
|
|
response->addHeader("Connection", "close");
|
|
request->send(response);
|
|
},[](AsyncWebServerRequest *request, String filename, size_t index, uint8_t *data, size_t len, bool final){
|
|
if(!index){
|
|
dbgSerial.printf("Update Start: %s\n", filename.c_str());
|
|
|
|
// Update.runAsync(true);
|
|
// if (!Update.begin((ESP.getFreeSketchSpace() - 0x1000) & 0xFFFFF000)) {
|
|
if (!Update.begin(0x140000)) {
|
|
Update.printError(dbgSerial);
|
|
}
|
|
}
|
|
if(!Update.hasError()){
|
|
if(Update.write(data, len) != len){
|
|
Update.printError(dbgSerial);
|
|
}
|
|
}
|
|
if(final){
|
|
if(Update.end(true)){
|
|
dbgSerial.printf("Update Success: %uB\n", index+len);
|
|
} else {
|
|
Update.printError(dbgSerial);
|
|
}
|
|
}
|
|
});
|
|
}
|
|
|
|
void browseService(const char * service, const char * proto) {
|
|
Serial.printf("Browsing for service _%s._%s.local. ... ", service, proto);
|
|
int n = MDNS.queryService(service, proto);
|
|
if (n == 0) {
|
|
Serial.println("no services found");
|
|
}
|
|
else {
|
|
Serial.print(n);
|
|
Serial.println(" service(s) found");
|
|
for (int i = 0; i < n; ++i) {
|
|
// Print details for each service found
|
|
Serial.print(" ");
|
|
Serial.print(i + 1);
|
|
Serial.print(": ");
|
|
Serial.print(MDNS.hostname(i));
|
|
Serial.print(" (");
|
|
Serial.print(MDNS.IP(i));
|
|
Serial.print(":");
|
|
Serial.print(MDNS.port(i));
|
|
Serial.println(")");
|
|
}
|
|
}
|
|
Serial.println();
|
|
}
|
|
|
|
// ================================================================================================
|
|
|
|
void HBXWiFiSetup() {
|
|
|
|
// TODO
|
|
// Read from EEPROM
|
|
|
|
UDPFlag = true; // Either UDP or ESPNOW
|
|
APFlag = true; // Either AP or STA
|
|
|
|
if (APFlag) {
|
|
// AP mode device connects directly to EQMODWiFi (no router)
|
|
// For AP mode: UDP2Serial: This ESP assigns IP addresses
|
|
// For AP mode: ESP IP is always 192.168.88.1 (set above)
|
|
|
|
dbgSerial.println("EQMODWiFi Access Point Mode");
|
|
// Check preferences for ssid, pass
|
|
preferences.begin("EQG2HBX", false); // Access EQG2HBX namespace
|
|
if (preferences.getString("AP_SSID", "none") == "none")
|
|
preferences.putString("AP_SSID", "EQMODWiFi"); // Default EQMOD
|
|
if (preferences.getString("AP_PASS", "none") == "none")
|
|
preferences.putString("AP_PASS", "CShillit0");
|
|
ssid = preferences.getString("AP_SSID", "none");
|
|
pass = preferences.getString("AP_PASS", "none");
|
|
preferences.end();
|
|
|
|
WiFi.mode(WIFI_AP);
|
|
WiFi.softAPConfig(ip, ip, netmask); // softAP ip
|
|
WiFi.softAP(ssid.c_str(), pass.c_str()); // softAP ssid, pass
|
|
dbgSerial.print("SoftAP IP address: "); dbgSerial.println(WiFi.softAPIP());
|
|
}
|
|
else {
|
|
// STA mode EQMODWiFi connects to network router and gets an IP
|
|
// For STA mode: Host software must detect that IP
|
|
// For STA mode: UDP2Serial router network assigns IP address
|
|
// For STA mode: Start webserver, mDNS and accept changes to ssid, pass, Telescope etc
|
|
|
|
dbgSerial.println("EQMODWiFi Station Mode");
|
|
// Check preferences for ssid, pass
|
|
preferences.begin("EQG2HBX", false); // Access EQG2HBX namespace
|
|
if (preferences.getString("STA_SSID", "none") == "none")
|
|
preferences.putString("STA_SSID", "EQGnet"); // Default Home Network
|
|
if (preferences.getString("STA_PASS", "none") == "none")
|
|
preferences.putString("STA_PASS", "EQGconnect");
|
|
ssid = preferences.getString("STA_SSID", "none");
|
|
pass = preferences.getString("STA_PASS", "none");
|
|
preferences.end();
|
|
|
|
WiFi.mode(WIFI_STA);
|
|
WiFi.begin(ssid.c_str(), pass.c_str());
|
|
int i = 0;
|
|
while ((WiFi.status() != WL_CONNECTED) && (i++ < 50)) {
|
|
delay(100);
|
|
dbgSerial.print(i); dbgSerial.print(", ssid: "); dbgSerial.print(ssid.c_str()); dbgSerial.print(", pass: "); dbgSerial.println(pass.c_str());
|
|
|
|
}
|
|
if (i >= 50) {
|
|
WiFi.begin("EQGnet", "EQGconnect");
|
|
while (WiFi.status() != WL_CONNECTED) {
|
|
delay(100);
|
|
dbgSerial.print("!");
|
|
}
|
|
}
|
|
dbgSerial.println(" connected");
|
|
|
|
if (!MDNS.begin("eqmodwifi")) {
|
|
Serial.println("Error setting up MDNS responder!");
|
|
while (1) {
|
|
delay(1000);
|
|
}
|
|
}
|
|
Serial.println("mDNS responder started");
|
|
|
|
// Load 'server.on' responses
|
|
AsyncServerResponseSetup();
|
|
WiFi.scanNetworks();
|
|
|
|
// attach filesystem root at URL /fs
|
|
if (!SPIFFS.begin(FORMAT_SPIFFS_IF_FAILED)) {
|
|
dbgSerial.println("SPIFFS Mount Failed, SPIFF formatted");
|
|
}
|
|
else
|
|
dbgSerial.println("SPIFFS Mounted .. ");
|
|
writeFile(SPIFFS, "/www/index.htm", EQ2HBX_Version.c_str());
|
|
listDir(SPIFFS, "/", 0);
|
|
|
|
server.serveStatic("/", SPIFFS, "/www/").setDefaultFile("index.htm");
|
|
|
|
// Catch-All Handlers
|
|
// Any request that can not find a Handler that canHandle it
|
|
// ends in the callbacks below.
|
|
server.onNotFound(onRequest);
|
|
server.onFileUpload(onUpload);
|
|
server.onRequestBody(onBody);
|
|
|
|
server.begin();
|
|
// Add service to MDNS-SD
|
|
MDNS.addService("_http", "_tcp", 80);
|
|
MDNS.addService("_osc", "_udp", localUdpPort);
|
|
|
|
// browseService("http", "tcp");
|
|
}
|
|
|
|
dbgSerial.print("ssid: "); dbgSerial.println(ssid.c_str());
|
|
dbgSerial.print("pass: "); dbgSerial.println(pass.c_str());
|
|
|
|
if (!UDPFlag) {
|
|
// ESP_NOW mode (EQMODWiFi responds to MAC protocol)
|
|
dbgSerial.println("ESP_NOW Mode");
|
|
InitESPNow();
|
|
dbgSerial.println("ESPNOW2SerialServer");
|
|
dbgSerial.print("Mount soft mac: "); dbgSerial.println(WiFi.softAPmacAddress());
|
|
dbgSerial.print("Mount hard mac: "); dbgSerial.println(WiFi.macAddress());
|
|
// esp_now_set_self_role(ESP_NOW_ROLE_COMBO);
|
|
esp_now_register_recv_cb(recvCallBack);
|
|
esp_now_register_send_cb(sendCallBack);
|
|
}
|
|
else {
|
|
dbgSerial.println("UDP Mode");
|
|
udp.begin(localUdpPort);
|
|
dbgSerial.println("UDP2SerialServer");
|
|
if (APFlag)
|
|
dbgSerial.printf("Now listening at IP %s, UDP port %d\n", WiFi.softAPIP().toString().c_str(), localUdpPort);
|
|
else
|
|
dbgSerial.printf("Now listening at IP %s, UDP port %d\n", WiFi.localIP().toString().c_str(), localUdpPort);
|
|
}
|
|
|
|
TxDIndex = 0;
|
|
sendWiFi.len = 0;
|
|
recvWiFi.len = 0;
|
|
}
|
|
|
|
// -------------------------------------------------------------------------------------------
|
|
|
|
bool HBXCheckRx() {
|
|
if (UDPFlag) { // UDP - SynScanPro UDP
|
|
recvWiFi.len = udp.parsePacket();
|
|
if (recvWiFi.len > 0) {
|
|
// receive incoming UDP packets
|
|
recvWiFi.len = udp.read(recvWiFi.text, 250);
|
|
if (recvWiFi.len > 0) {
|
|
recvWiFi.text[recvWiFi.len] = 0; // Null terminate
|
|
|
|
// dbgSerial.print("RxUDP - len: ");
|
|
// dbgSerial.print(recvWiFi.len);
|
|
// dbgSerial.print(", data: ");
|
|
// dbgSerial.println(recvWiFi.text);
|
|
|
|
}
|
|
}
|
|
}
|
|
if (recvWiFi.len > 0) { // Send data to mount Input data buffer for processing
|
|
putRxDataIntoMountInputBuffer();
|
|
return true; // Data received from UDP or ESP_NOW callback
|
|
}
|
|
else
|
|
return false; // No Data received
|
|
}
|
|
|
|
void HBXCheckTx() {
|
|
if (UDPFlag) {
|
|
// Get data to send to SynScanPro via UDP into WiFi buffer
|
|
getTxDataFromMountOutputBuffer();
|
|
// send back a reply, to the IP address and port we got the packet from
|
|
if (sendWiFi.len > 0) {
|
|
|
|
// dbgSerial.print("TxUDP - len: ");
|
|
// dbgSerial.print(sendWiFi.len);
|
|
// dbgSerial.print(", data: ");
|
|
// dbgSerial.println(sendWiFi.text);
|
|
|
|
udp.beginPacket(udp.remoteIP(), udp.remotePort());
|
|
memcpy(sendWiFi8, &sendWiFi.text, sendWiFi.len);
|
|
udp.write(sendWiFi8, sendWiFi.len);
|
|
udp.endPacket();
|
|
}
|
|
sendWiFi.len = 0;
|
|
TxDIndex = 0;
|
|
}
|
|
else {
|
|
// Get data to send to ESP_NOW - EQMOD/SynScanPro Serial WiFi
|
|
if (Connected) {
|
|
getTxDataFromMountOutputBuffer();
|
|
if (sendWiFi.len > 0)
|
|
sendData(&serial_peer);
|
|
}
|
|
}
|
|
}
|
|
|
|
|