Zack - nächstes Problem!
Folgendes Programm soll sich einen Client suchen, die versendeten Daten auslesen und bei Verbindungstrennung sich einen neuen Client suchen. Ziel ist es, dass zwei ESPs über WLAN in Verbindung stehen. Zu Testzwecken soll auch noch über D7 ein Ton ausgegeben werden, besser gesagt über den Buzzer an dem Pin. Aber das ist egal, das läuft bzw. piept.
#include <ESP8266WiFi.h>
#include <algorithm>
#ifndef APSSID
#define APSSID "ESPAP"
#define APPSK "ThisPasswortIsShitty"
#endif
const int port = 23;
String input;
WiFiServer server(port);
WiFiClient client;
IPAddress apIP(192,168,4,1);
void setup(){
Serial.begin(115200);
Serial.setRxBufferSize(1024);
Serial.println("\n\nUsing Serial for logging");
Serial.println(ESP.getFullVersion());
WiFi.mode(WIFI_AP);
WiFi.softAPConfig(apIP, apIP, IPAddress(255, 255, 255, 0));
WiFi.softAP(APSSID, APPSK);
Serial.println(APSSID);
Serial.println();
Serial.print("connected, address=");
Serial.println(WiFi.softAPIP());
server.begin();
server.setNoDelay(true);
Serial.print("Ready! Use 'telnet ");
Serial.print(WiFi.softAPIP());
Serial.printf(" %d' to connect\n", port);
Serial.println("Okay...");
}
uint16_t getFreq(uint8_t note){
float freq[] = {65.4, 69.3, 73.4, 77.7, 82.4, 87.3, 92.5, 98.0, 103.8, 110.0, 116.5, 123.4};
return freq[note%12] * (1 << uint8_t(note / 12)) * std::min(1, int(note));
}
void loop(){
if(!client.connected() && server.hasClient()){
client = server.available();
}
while(client.available()){
char ch = client.read();
input += ch;
if(ch == '\n'){
int in = input.toInt();
tone(13, int(getFreq(floor(map(float(in), 0, 1024, 0, 12) + 24))));
for(int8_t i = -2;i <= 2;i++){
Serial.print(in + i);
Serial.write('\t');
}
Serial.println();
input = "";
}
}
}
Das Sendeprogramm sieht so aus:
#include <ESP8266WiFi.h>
#define STASSID "ESPAP"
#define STAPSK "ThisPasswortIsShitty"
WiFiClient data;
void setup(){
pinMode(LED_BUILTIN, OUTPUT);
digitalWrite(LED_BUILTIN, LOW);
delay(250);
digitalWrite(LED_BUILTIN, HIGH);
WiFi.begin(STASSID, STAPSK);
while(WiFi.status() != WL_CONNECTED){
delay(250);
}
data.connect("192.168.4.1", 23);
data.setNoDelay(true);
digitalWrite(LED_BUILTIN, LOW);
}
void loop(){
String temp;
for(byte i = 0;i < 10;i++){
temp += analogRead(0);
temp += '\n';
delay(5);
}
data.print(temp);
}
Dank eurer Hilfe ist inzwischen die Datenübertragung flüssig. Was aber nicht funktioniert, ist, dass nach einem Reset vom Sender der Client vom Server als nicht mehr verbunden betrachtet wird. !client bzw. !client.connected() ist immer false. Das hat folgender Versuch ergeben:
#include <ESP8266WiFi.h>
#include <algorithm>
#ifndef APSSID
#define APSSID "ESPAP"
#define APPSK "ThisPasswortIsShitty"
#endif
#define STACK_PROTECTOR 512
#define MAX_SRV_CLIENTS 1
const int port = 23;
String input;
WiFiServer server(port);
WiFiClient serverClients[MAX_SRV_CLIENTS];
IPAddress apIP(192,168,4,1);
void setup(){
Serial.begin(115200);
Serial.setRxBufferSize(1024);
Serial.println("\n\nUsing Serial for logging");
Serial.println(ESP.getFullVersion());
WiFi.mode(WIFI_AP);
WiFi.softAPConfig(apIP, apIP, IPAddress(255, 255, 255, 0));
WiFi.softAP(APSSID, APPSK);
Serial.println(APSSID);
Serial.println();
Serial.print("connected, address=");
Serial.println(WiFi.softAPIP());
//start server
server.begin();
server.setNoDelay(true);
Serial.print("Ready! Use 'telnet ");
Serial.print(WiFi.softAPIP());
Serial.printf(" %d' to connect\n", port);
}
uint16_t getFreq(uint8_t note){
float freq[] = {65.4, 69.3, 73.4, 77.7, 82.4, 87.3, 92.5, 98.0, 103.8, 110.0, 116.5, 123.4};
return freq[note%12] * (1 << uint8_t(note / 12)) * std::min(1, int(note));
}
void loop() {
//check if there are any new clients
if (server.hasClient()) {
//find free/disconnected spot
int i;
for (i = 0; i < MAX_SRV_CLIENTS; i++)
if (!serverClients[i]) { // equivalent to !serverClients[i].connected()
serverClients[i] = server.available();
Serial.print("New client: index ");
Serial.print(i);
break;
}
//no free/disconnected spot so reject
if (i == MAX_SRV_CLIENTS) {
server.available().println("busy");
// hints: server.available() is a WiFiClient with short-term scope
// when out of scope, a WiFiClient will
// - flush() - all data will be sent
// - stop() - automatically too
Serial.printf("server is busy with %d active connections\n", MAX_SRV_CLIENTS);
}
}
for(int i = 0; i < MAX_SRV_CLIENTS; i++){
while(serverClients[i].available()){
// working char by char is not very efficient
char ch = serverClients[i].read();
input += ch;
if(ch == '\n'){
tone(13, int(getFreq(floor(map(float(input.toInt()), 0, 1024, 0, 12) + 24))));
Serial.println(input);
input = "";
}
}
}
size_t maxToTcp = 0;
for (int i = 0; i < MAX_SRV_CLIENTS; i++)
if (serverClients[i]) {
size_t afw = serverClients[i].availableForWrite();
if (afw) {
if (!maxToTcp) {
maxToTcp = afw;
} else {
maxToTcp = std::min(maxToTcp, afw);
}
} else {
// warn but ignore congested clients
Serial.println("one client is congested");
}
}
//check UART for data
size_t len = std::min((size_t)Serial.available(), maxToTcp);
len = std::min(len, (size_t)STACK_PROTECTOR);
if (len) {
uint8_t sbuf[len];
size_t serial_got = Serial.readBytes(sbuf, len);
for (int i = 0; i < MAX_SRV_CLIENTS; i++)
if (serverClients[i].availableForWrite() >= serial_got) {
size_t tcp_sent = serverClients[i].write(sbuf, serial_got);
if (tcp_sent != len) {
Serial.printf("len mismatch: available:%zd serial-read:%zd tcp-write:%zd\n", len, serial_got, tcp_sent);
}
}
}
}
Mir wird, wenn der Sender resettet wird,
server is busy with 1 active connections
angezeigt. Das ist also das Problem: Der Server erkennt nicht, dass die Verbindung zum anderen ESP getrennt ist. Vermutlich, weil nirgendwo im Sendeprogramm data.stop() aufgerufen wird. Kann auf eine andere Weise erkannt werden, wenn der ESP nicht mehr verbunden ist? Ich möchte nicht alle halbe Sekunde ein "Ich bin noch da!" mit dem Sender verschicken.