streaming UDP packets with esp32 access point cause massive packet loss - android

I'm currently running my esp32 wroom as Access Point to stream UDP packets (~100 packets per second, 1Ko per packet) to different smartphones.
At close range, I lost about 30% of the packets at steady rate.
It not unusual to lose packets with UDP protocol however this issue happens only with some specific and quite recent smartphones.
After some Wireshark investigations of the Wifi messages, I observe that this packet loss is happening only for smartphones using IEEE 802.11 Power Save mecanism.
There are plenty of options regarding Power saving mode in ESP 32 configuration and I suspect that I may have misconfigured the ESP32.
Do you have an idea of what could cause the problem ?
Thanks
I'm sharing with you the ESP32 configuration:
#
# Wi-Fi
#
CONFIG_ESP32_WIFI_STATIC_RX_BUFFER_NUM=16
CONFIG_ESP32_WIFI_DYNAMIC_RX_BUFFER_NUM=64
CONFIG_ESP32_WIFI_STATIC_TX_BUFFER=y
# CONFIG_ESP32_WIFI_DYNAMIC_TX_BUFFER is not set
CONFIG_ESP32_WIFI_TX_BUFFER_TYPE=0
CONFIG_ESP32_WIFI_STATIC_TX_BUFFER_NUM=32
# CONFIG_ESP32_WIFI_CSI_ENABLED is not set
CONFIG_ESP32_WIFI_AMPDU_TX_ENABLED=y
CONFIG_ESP32_WIFI_TX_BA_WIN=32
CONFIG_ESP32_WIFI_AMPDU_RX_ENABLED=y
CONFIG_ESP32_WIFI_RX_BA_WIN=32
CONFIG_ESP32_WIFI_NVS_ENABLED=y
CONFIG_ESP32_WIFI_TASK_PINNED_TO_CORE_0=y
# CONFIG_ESP32_WIFI_TASK_PINNED_TO_CORE_1 is not set
CONFIG_ESP32_WIFI_SOFTAP_BEACON_MAX_LEN=752
CONFIG_ESP32_WIFI_MGMT_SBUF_NUM=32
# CONFIG_ESP32_WIFI_DEBUG_LOG_ENABLE is not set
CONFIG_ESP32_WIFI_IRAM_OPT=y
CONFIG_ESP32_WIFI_RX_IRAM_OPT=y
CONFIG_ESP32_WIFI_ENABLE_WPA3_SAE=y
# CONFIG_ESP_WIFI_SLP_IRAM_OPT is not set
# CONFIG_ESP_WIFI_STA_DISCONNECTED_PM_ENABLE is not set
# end of Wi-Fi
see the Access point initialization code:
esp_err_t COM_wifi_access_point_start(void)
{
esp_err_t esp_err;
do {
// Initialization of the physical WiFi port
tcpip_adapter_init();
// Shutdown of the DHCP server before reprogramming the IP address of the probe
BREAK_ON_ERR( esp_err = tcpip_adapter_dhcps_stop(TCPIP_ADAPTER_IF_AP) );
// Initialization of the structure containing the IP address of the probe
tcpip_adapter_ip_info_t ip_info;
IP4_ADDR(&ip_info.ip,EPF_IPV4_IP_ADDR_1,EPF_IPV4_IP_ADDR_2,EPF_IPV4_IP_ADDR_3,EPF_IPV4_IP_ADDR_4);
IP4_ADDR(&ip_info.gw,EPF_IPV4_GW_ADDR_1,EPF_IPV4_GW_ADDR_2,EPF_IPV4_GW_ADDR_3,EPF_IPV4_GW_ADDR_4);
IP4_ADDR(&ip_info.netmask,EPF_IPV4_NM_ADDR_1,EPF_IPV4_NM_ADDR_2,EPF_IPV4_NM_ADDR_3,EPF_IPV4_NM_ADDR_4);
// The new IP address is applied
BREAK_ON_ERR( esp_err = tcpip_adapter_set_ip_info(TCPIP_ADAPTER_IF_AP, &ip_info) );
// Restarting the DHCP server
BREAK_ON_ERR( esp_err = tcpip_adapter_dhcps_start(TCPIP_ADAPTER_IF_AP) );
// Connecting the IT WiFi handler
BREAK_ON_ERR( esp_err = esp_event_loop_init(wifi_event_handler, NULL) );
// Initialization of the WiFi driver to the default configuration
wifi_init_config_t wifi_init_config = WIFI_INIT_CONFIG_DEFAULT();
BREAK_ON_ERR( esp_err = esp_wifi_init(&wifi_init_config) );
// The driver is told to store all WiFi configuration in RAM
// => We don't always write the configuration in flash each time
BREAK_ON_ERR( esp_err = esp_wifi_set_storage(WIFI_STORAGE_RAM) );
// Switching from the default connection mode to Access Point mode
BREAK_ON_ERR( esp_err = esp_wifi_set_mode(WIFI_MODE_AP) );
// The desired configuration is applied to the WiFi driver
wifi_config_t ap_config =
{
.ap =
{
.ssid = "",
.channel = EPF_WIFI_CHANNEL_NUMBER,
.password = EPF_WIFI_PASSWORD,
.authmode = WIFI_AUTH_WPA_WPA2_PSK,
.ssid_hidden = COM_WIFI_BROADCAST, // SSID in broadcast mode => Non-hidden network
.max_connection = EPF_WIFI_NB_CONNECTION, // Only one connection allowed simultaneously
.beacon_interval= COM_WIFI_BEACON_INT
}
};
sprintf((char*)ap_config.ap.ssid, EPF_WIFI_SSID_TMPL, PAR_get_live_raw_fast(EPF_MAI_PROBE_SERIAL_NB) );
BREAK_ON_ERR( esp_err = esp_wifi_set_config(WIFI_IF_AP, &ap_config) );
// Starting WiFi
// After calling this function, the access point is visible from remote WiFi devices
BREAK_ON_ERR( esp_err = esp_wifi_start() );
// Renaming the hostname
BREAK_ON_ERR( esp_err = tcpip_adapter_set_hostname(TCPIP_ADAPTER_IF_AP, COM_LOCALHOSTNAME) );
esp_err = ESP_OK;
} while(0);
return esp_err;
}

The ESP32-s WiFi power saving is enabled by default. You can disable it with a call to esp_wifi_set_ps(WIFI_PS_NONE); - see if it works for you. I've had to turn it off after I saw significant ICMP packet loss under load.

Related

Web Bluetooth characteristic.writeValue break the connection automatically

I follows Google/chrome samples for Web Bluetooth. I have two writeValue operations. One is within the requestDevice promise and it works perfectly. Second one, I save the characteristic reference and writeValue when the action trigger. The message is sent but connection broke automatically. I am using Mac OSX 10.13.3 and chrome64 and modify Android BLE Peripheral Simulator (From google github)
The code segment ---
var bluetoothDevice;
var myCharacteristic;
navigator.bluetooth.requestDevice({
...
})
.then(device => {
bluetoothDevice = device;
....
})
....
.then(characteristic =>{
myCharacteristic = characteristic;
let encoder = new TextEncoder('utf-8');
let sendMsg = encoder.encode("hello");
/*
It works...
*/
myCharacteristic.writeValue(sendMsg);
})
....
function onSendMessage() {
if (!bluetoothDevice.gatt.connected) {
log("device is disconnected")
return
}
if (!myCharacteristic){
log("no characteristic defined")
return
}
let encoder = new TextEncoder('utf-8');
let sendMsg = encoder.encode("hello");
/*
message sent but auto disconnect the peripheral
*/
myCharacteristic.writeValue(sendMsg);
}
Does anyone has same experience and any suggestion for keep connection persistence for writeValue?
Your code looks good to me. A similar code can be found as well at https://googlechrome.github.io/samples/web-bluetooth/link-loss.html
However I wonder which characteristic you're trying to write to. If that is not supported, the Android device might simply disconnect.
Check out https://www.chromium.org/developers/how-tos/file-web-bluetooth-bugs#TOC-Android and grab Android adb logs if that helps.

Python 3.5 on Windows in Bluetooth context. The requested address is not valid in its context

Code is as follows:
from bluetooth import *
import sys
if sys.version < '3':
input = raw_input
addr = None
if len(sys.argv) < 2:
print("no device specified. Searching all nearby bluetooth devices for")
print("the SampleServer service")
else:
addr = sys.argv[1]
print("Searching for SampleServer on %s" % addr)
# search for the SampleServer service
addr = "CC:79:4A:4B:35:85"
service_matches = find_service( address = addr )
if len(service_matches) == 0:
print("couldn't find the SampleServer service =(")
sys.exit(0)
first_match = service_matches[0]
port = first_match["port"]
name = first_match["name"]
host = first_match["host"]
print("connecting to \"%s\" at Address - %s on Port %d" % (name, host, port))
# Create the client socket
sock=BluetoothSocket( RFCOMM )
sock.connect((host, port))
print("connected. type stuff")
while True:
data = input()
if len(data) == 0: break
sock.send(data)
sock.close()
Run time error thrown as follows:
no device specified. Searching all nearby bluetooth devices for
the SampleServer service
connecting to "None" at Address - CC:79:4A:4B:35:85 on Port 31
Traceback (most recent call last):
File "T_C_1.py", line 40, in <module>
sock.connect((host, port))
File "C:\Python 3.5\lib\site-packages\bluetooth\msbt.py", line 72, in connect
bt.connect (self._sockfd, addr, port)
OSError: The requested address is not valid in its context.
I am unable to figure out why. Some sites tell me that my Host address need to be on the local machine....
This code resides and is run from my WIndows machine in an attempt to connect to an Android phone over Bluetooth.
I don't get why / how...
Help is appreciated!
I have run across the same error using PyBluez on Windows since I had to leave my Mac environment after receiving a bind error. I found out that the issue comes about when you are binding to a foreign IP address, or one that isn't known by your system(e.g outside public IPs). Try creating a server in PyBluez with the addr of '' and attempt to connect to that. We can further diagnose your problem from there if that doesn't work. Sorry for it not being a solid answer, I'm new to StackOverflow and I couldn't exactly comment but I wanted to offer some help.

PJSIP VOIP call not connected using SIP2SIP.info server

i am using PJSIP for voice calling. When i used our server, everything fine i.e. call connected, communicate. But when i am using SIP2SIP.INFO server. Registration is OK But Call is not connected. i saw log in SIP2SIP.info there wasn't log of outgoing or incoming call.
so call is not initiate.
char cfg_reg_uri[] = "sip:sip2sip.info";
char cfg_cred_realm[] = "sip2sip.info";
char cfg_cred_scheme[]="digest";
pjsua_acc_config cfg;
pjsua_acc_config_default(&cfg);
cfg.id = pj_str(cfg_id);
cfg.reg_uri = pj_str(cfg_reg_uri);
cfg.cred_count = 1;
cfg.cred_info[0].realm = pj_str(cfg_cred_realm);
cfg.cred_info[0].scheme = pj_str(cfg_cred_scheme);
cfg.cred_info[0].username = pj_str(cfg_cred_username);
cfg.cred_info[0].data_type = PJSIP_CRED_DATA_PLAIN_PASSWD;
cfg.cred_info[0].data = pj_str(cfg_cred_password);
status = pjsua_acc_add(&cfg, PJ_TRUE, &_acc_id);
I noted that we need to use outbound proxy in sip2sip called "proxy.sipthor.net".
but confused how can i used in pjsip code.
please help expert.
If you read the Sip2Sip device configuration page it states that:
" the SIP device must always perform DNS lookups as defined in SIP standard RFC3263 (NAPTR + SRV + A DNS lookups)"
PJSIP supports DNS SRV lookups.
In PJSUA it will only do DNS SRV lookup if you don't provide the port number in the SIP URL.
"sip:xxx#sip2sip.info" will try to do a DNS SRV record lookup first then fail over to DNS A/C name lookup.
and
"sip:xxx#sip2sip.info:5060" will only do DNS A/C name lookup.
What PJSUA will not support automatically is failover support, they say:
"What we've been suggesting is to implement the failover mechanism in the application layer."
If you want a "quick and easy" setup, what you want to do is set the outbound_proxy to "proxy.sipthor.net". e.g.
cfg.outbound_proxy_cnt = 1;
cfg.outbound_proxy[0] = pj_str("sip:proxy.sipthor.net:5060");
If you want a more robust solution, you need to use pjsip's SRV resolution functions to resolve sip2sip.info srv record e.g: "_sip._udp.sip2sip.info" and then set the outbound_proxy records with the result.
The code is a little bit involved.
pjsip_resolver_t* resolver_;
...
status = pjsip_resolver_create( pool, &resolver_ );
...
pjsip_host_info host;
host.flag = PJSIP_TRANSPORT_DATAGRAM; // is using UDP, see pjsip_transport_flags_e
host.type = PJSIP_TRANSPORT_UDP; // if using UDP, see pjsip_transport_type_e
host.addr.host = pj_str("sip2sip.info");
host.addr.port = 5060;
pjsip_resolve(resolver_, pool, &host, token, resolver_cb_func);
...
static void resolver_cb_func( pj_status_t status, void *token, const struct pjsip_server_addresses *addr)
{
...
// use results to fill in the outbound_proxy
}
You could also take it further to support failover, but it looks like sip2sip doesn't have multiple sip servers in there DNS SRV record so it will not be used currently. If they ever add more then it would become more useful.
_sip._udp.sip2sip.info
Server: fritz.box Address: fd00::2665:11ff:fef9:ec51
Non-authoritative answer:
_sip._udp.sip2sip.info SRV service location:
priority = 100
weight = 100
port = 5060
svr hostname = proxy.sipthor.net
sip2sip.info nameserver = ns2.dns-hosting.info
sip2sip.info nameserver = ns1.dns-hosting.info
sip2sip.info nameserver = ns7.dns-hosting.info
Sip2Sip also support STUN setup, so I would also setup the STUN settings on the account as well:
cfg.stun_srv_cnt = 1;
cfg.stun_srv[0] = pj_str("sip2sip.info");
Since your example seems to not provide the port information it should work. To diagnose this further would require see the pjsip log output.

android bluetooth serversocket with python-bluez client

I am trying to connect my laptop(as client) to my android phone(as listener) using python-bluez on the laptop and android-bluetooth API on the phone.
I use the following code for my phone:
BluetoothServerSocket tmp = badapter.listenUsingRfcommWithServiceRecord(
badapter.getName(), MY_UUID);
BluetoothServerSocket bserversocket = tmp;
if(bserversocket != null)
{
BluetoothSocket acceptsocket = bserversocket.accept(timeout);
}
//timeout is set to about 15 sec
if(acceptsocket != null)
{
out.append("got the connection...\n");
}
and the following in python for my laptop client:
from bluetooth import *
btooth_addr = "38:EC:E4:57:1F:1B"
sock = BluetoothSocket(RFCOMM)
sock.connect((btooth_addr, 2))
print "Connected"
sock.close()
the listener time-outs without acknowledging any connections from the laptop, while the sender moves on to print 'Connected' on all attempts on different ports.
the problem is that I don't know and can't set the port/channel the android phone is listening on, and also that I am required to fill in a port number as second argument of 'connect'(2 in this snippet).
please help me out - my sole goal at this time is to get the connection attempt acknowledged by the phone.
Have a look at the pybluez documentation(source code) for establishing client connections.
You can get the correct port for the supplied Bluetooth address and UUID using find_service.
Then connect your socket just as you do in your code, replacing hardcoded port value with the correct one.
Don't forget to vote up!

Unable to configure the wifi open network programmatically android?

I have written code for adding open network to wifi configured list.It adds the open network to configured lists and displays the same SSID's in Wifi Settings.but it adds the same network with same name extra but it doesn't shows any open network When i press on the second on alert shows with Security WEP the following text i observed with those same networks
1) Open network
2) remembered , not in range
But i want to add open network into my list, why this extra one is added and if i connect the same network it is trying to connect to the (2) one programmatically.Actually I changed secured network to open network for this trial.It displays with open network text and when i press on that one it obtains the address and connects succesfully manually.Why this extra one is adding how can i add the open network to my list.For reference plz see the link for image.
http://www.freeimagehosting.net/uploads/3dbccfc2bd.png
Code snippet :
String hotSpotSsid = hotSpot.SSID;
String hotSpotBssid = hotSpot.BSSID;
Log.i(TAG,"in RSSI Changed Acion SSID: "+hotSpotSsid+" BSSID: "+hotSpotBssid);
StringBuffer sBuf = new StringBuffer("\"");
sBuf.append(hotSpotSsid+"\"");
hotSpotSsid = sBuf.toString();
WifiConfiguration wifiConfiguration = new WifiConfiguration();
wifiConfiguration.SSID = hotSpotSsid;
wifiConfiguration.allowedKeyManagement.set(KeyMgmt.NONE);
wifiConfiguration.BSSID = hotSpotBssid;
wifiConfiguration.hiddenSSID = false;
// wifiConfiguration.priority = 1;
// add this to the configured networks
int inetId = wifiManager.addNetwork(wifiConfiguration);
Log.i(TAG,"INetId :"+inetId);
configs = wifiManager.getConfiguredNetworks();
Log.e(TAG,"After adding config :"+configs);
if(inetId < 0) {
Log.i(TAG,"Unable to add network configuration for SSID: "+hotSpotSsid);
return;
}else {
message="\t Successfully added to configured Networks";
Log.i(TAG,message);
}
regards,
Rajendar
Try removing SSID and seeing if it works. I was having a similar issue and that worked for me.
Appending and prepending quotes to the SSID, as you did, should work though. Not sure why it doesn't.
Give SSID as wifiConfiguration.SSID = "\"".concat(SSID_NAME).concat("\"");

Categories

Resources