How Reconnect to WiFiManager after manually disconnecting the WiFi - bluetooth

I want to use Bluetooth and WiFi of the ESP32, however, it seems that they cannot be used at the same time, so I have made that when ESP32 starts it will connect to WiFi and get data from database after that, it will be disconnected and the Bluetooth will be enabled and connect to a Bluetooth Thermal printer and prints a receipt, after the receipt is printed it will then connect again to the WiFiManager.
Code for Connecting to WiFiManager by tzapu:
void setup()
{
Serial.begin(115200);
bool res;
res = wm.autoConnect("AutoConnectAP");
if (!res)
{
Serial.println("NETWORK FAILED");
}
else
{
Serial.println("CONNECTED TO NETWORK");
}
config.api_key = APY_KEY;
config.database_url = URL;
if (Firebase.signUp(&config, &auth, "", ""))
{
Serial.println("CONNECTED TO FIREBASE");
signupOK = true;
}
config.token_status_callback = tokenStatusCallback;
Firebase.begin(&config, &auth);
Firebase.reconnectWiFi(true);
if (Firebase.ready() && signupOK)
{
if (Firebase.RTDB.getJSON(&firebaseData, "/addedCards"))
{
jsonData = firebaseData.jsonString();
}
}
}
After Connecting to WiFi and getting data from database, disconnect WiFi and Enable Bluetooth:
void loop()
{
// DISCONNECT WIFI
WiFi.disconnect(true);
SerialBT.begin("ESP32test", true);
Serial.println("CONNECTING TO PRINTER");
connected = SerialBT.connect(address);
Serial.println(connected);
if (connected)
{
Serial.println("CONNECTED TO PRINTER");
}
else
{
while (!SerialBT.connected(10000))
{
Serial.println("PRINTER FAILED");
}
}
if (SerialBT.disconnect())
{
Serial.println("PRINTER DISCONNECTED");
}
// CONNECT TO BLUETOOTH
SerialBT.connect();
if (connected)
{
Serial.println("PRINTING...");
printer.begin();
// PRINT VALUES FROM DATABASE
printer.feed(2);
printer.setDefault();
}
// DISCONNECT BLUETOOTH
SerialBT.disconnect();
// HOW TO RECONNECT TO WIFI AGAIN??
WiFi.begin();
WiFi.reconnect();
if (WiFi.status() != WL_CONNECTED)
{
Serial.println("Reconnecting...");
wm.autoConnect("AutoConnectAP");
wm.startConfigPortal("AutoConnectAP");
}
}
I am getting this error trying to reconnect to the WiFi:
Reconnecting...
*wm:AutoConnect
[ 7527][E][WiFiGeneric.cpp:680] wifiLowLevelInit(): esp_wifi_init 257
*wm:[FATAL] Unable to enable wifi!
[ 7545][E][WiFiGeneric.cpp:680] wifiLowLevelInit(): esp_wifi_init 257
*wm:StartAP with SSID: AutoConnectAP
[ 7563][E][WiFiGeneric.cpp:680] wifiLowLevelInit(): esp_wifi_init 257
[ 7564][E][WiFiAP.cpp:141] softAP(): enable AP first!
*wm:[ERROR] There was a problem starting the AP
*wm:AP IP address:
*wm:Starting Web Portal
[ 8088][E][WiFiGeneric.cpp:680] wifiLowLevelInit(): esp_wifi_init 257
I want to reconnect to WiFi after disconnection without restarting the ESP "ESP.restart()" because it takes 3 to 4 seconds to reconnect again.

Related

Android app fails bluetooth connection with ESP when calling connect()

I'm trying to build an Android app in Android Studio using Kotlin to send some simple data between an ESP32 and a mobile over Bluetooth. I've been following along a number of tutorials but just can't seem to get the connection established, permissions and scanning for devices looks to be working correctly. When I call connect() on the socket the app hangs for a few seconds and then crashes with this error:
E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.btleveller, PID: 28899
java.lang.RuntimeException: Failure delivering result ResultInfo{who=null, request=0, result=-1, data=Intent { (has extras) }} to activity {com.example.btleveller/com.example.btleveller.MainActivity}: java.io.IOException: read failed, socket might closed or timeout, read ret: -1
at android.app.ActivityThread.deliverResults(ActivityThread.java:5368)
at android.app.ActivityThread.handleSendResult(ActivityThread.java:5407)
etc... I can post the full output if it's helpful
My ESP is running some very basic helloworld style code using the NimBLE-Arduino code, programmed through VSCode with the PlatformIO extension. I think this side of it is all working correct as I can see the device in the "nRF Connect" app on my mobile. The scanning is done through the CompanionDeviceManager library:
I thought maybe there was a problem with the UUID I was supplying, or that I needed to make changes for BLE as opposed to regular Bluetooth but so far nothing I've found online has worked. I've also tried using "createL2capChannel()" to create the socket but got stuck on the PSM value. These are the relevant bits of code:
//private val ESP_UUID = UUID.fromString("0000dead-0000-1000-8000-00805F9B34FB")
private val ESP_UUID = UUID.fromString("0000baad-0000-1000-8000-00805F9B34FB")
...
// Look for connection, kicked off by button press
fun lookForConn(view: View) {
val deviceFilter: BluetoothDeviceFilter = BluetoothDeviceFilter.Builder()
.setNamePattern(Pattern.compile("BLE"))
.build()
// The argument provided in setSingleDevice() determines whether a single
// device name or a list of them appears.
val pairingRequest: AssociationRequest = AssociationRequest.Builder()
.addDeviceFilter(deviceFilter)
.setSingleDevice(false)
.build()
// When the app tries to pair with a Bluetooth device, show the
// corresponding dialog box to the user.
deviceManager.associate(pairingRequest,
object : CompanionDeviceManager.Callback() {
override fun onDeviceFound(chooserLauncher: IntentSender) {
startIntentSenderForResult(chooserLauncher,
SELECT_DEVICE_REQUEST_CODE, null, 0, 0, 0)
}
override fun onFailure(error: CharSequence?) {
// Handle the failure.
Log.d("DEVHandler","failed to find dev?")
}
}, null)
}
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
when (requestCode) {
SELECT_DEVICE_REQUEST_CODE -> when(resultCode) {
Activity.RESULT_OK -> {
// The user chose to pair the app with a Bluetooth device.
val deviceToPair: BluetoothDevice? =
data?.getParcelableExtra(CompanionDeviceManager.EXTRA_DEVICE)
Log.d("DEVHandler","try to bond:" + deviceToPair?.name)
deviceToPair?.let { device ->
device.createBond()
val newConn = ConnectThread(deviceToPair).run()
}
}
}
else -> super.onActivityResult(requestCode, resultCode, data)
}
}
private inner class ConnectThread(device: BluetoothDevice) : Thread() {
private var mHaveConn = false
public fun IsConnected(): Boolean {
return mHaveConn
}
private val mmSocket: BluetoothSocket? by lazy(LazyThreadSafetyMode.NONE) {
//device.createRfcommSocketToServiceRecord(ESP_UUID)
device.createInsecureRfcommSocketToServiceRecord(ESP_UUID)
}
public override fun run() {
// Cancel discovery because it otherwise slows down the connection.
BTMan.mBTAdapter?.cancelDiscovery()
mmSocket?.let { socket ->
// Connect to the remote device through the socket. This call blocks
// until it succeeds or throws an exception.
if (socket == null)
Log.d("CONNThread", "Socket is null...")
if (socket.isConnected == true)
Log.d("CONNThread", "Socket is already connected...")
socket.connect()
Log.d("CONNThread", "Made a connection")
// The connection attempt succeeded. Perform work associated with
// the connection in a separate thread.
//manageMyConnectedSocket(socket)
mHaveConn = true
}
}
// Closes the client socket and causes the thread to finish.
fun cancel() {
try {
mmSocket?.close()
} catch (e: IOException) {
Log.e("CONNThread", "Could not close the client socket", e)
}
mHaveConn = false
}
}

CAN socketCAN - how reliable is for file transfer

I want to send files (mp3 about 4MB each) to devices connected via CAN. I'm testing with Linux machine and ESP32. The problem is that not all data arrives to destination.
I'm sending from Linux machine using socketCAN and UCCB USB-CAN converter
https://www.tindie.com/products/lll7/can-usb-converter-uccb/ to ESP32, or between two ESP32.
When sending from PC Linux to ESP32, sometimes only 1/3 of mp3 file is saved, during sending I have candump slcan0 command running and it looks like all data is on the bus, but ESP32 does not see some frames.
When I send between two ESP32, for instance 4MB of data, receiving ESP32 gets around 3,98MB of data, some frames gets lost.
I'm using command "slcand -o -c -f -s8 /dev/ttyACM0 slcan0" to create slcan0 interface, although changing the speed with -s switch does not seem to work.
Am I missing something, or CAN is not suitable for such high speed, high load operations? I want to have 30 devices on canbus that receive around 1GB of data (mp3 files)
code below:
CanMgr::CanMgr(QObject *parent,LogModel *logModel):QObject(parent) {
this->logModel=logModel;
send_timer=new QTimer(this);
send_timer->setSingleShot(true);
send_timer->setInterval(1);
connect(send_timer,&QTimer::timeout,this,&CanMgr::processQueue);
}
void CanMgr::connectDevice() {
QString errorString;
m_canDevice = QCanBus::instance()->createDevice(m_pluginName,m_socketName,&errorString);
if (!m_canDevice) {
qDebug()<<QString("Error creating device '%1', reason: '%2'").arg(m_pluginName).arg(errorString);
return;
}
m_numberFramesWritten = 0;
connect(m_canDevice, &QCanBusDevice::errorOccurred, this, &CanMgr::processErrors);
connect(m_canDevice, &QCanBusDevice::framesReceived, this, &CanMgr::processReceivedFrames);
connect(m_canDevice, &QCanBusDevice::framesWritten, this, &CanMgr::processFramesWritten);
connect(m_canDevice, &QCanBusDevice::stateChanged,this, &CanMgr::stateChanged);
m_canDevice->setConfigurationParameter(QCanBusDevice::BitRateKey,"250000");
if (!m_canDevice->connectDevice()) {
qDebug()<<tr("Connection error: %1").arg(m_canDevice->errorString());
delete m_canDevice;
m_canDevice = nullptr;
} else {
QVariant bitRate = m_canDevice->configurationParameter(QCanBusDevice::BitRateKey);
if (bitRate.isValid()) {
qDebug()<<tr("Plugin: %1, connected to %2 at %3 kBit/s").arg(m_pluginName).arg(m_socketName).arg(bitRate.toInt() / 1000);
} else {
qDebug()<<tr("Plugin: %1, connected to %2").arg(m_pluginName).arg(m_socketName);
}
}
}
void CanMgr::sendFileContent(QByteArray data) {
quint32 frameId = 0;
quint32 dev_id=2;
quint32 cmd_id=0;
frameId=(dev_id<<16) | cmd_id;
m_canDevice->clear();
QByteArray size=Helper::byteArrFromInt((quint32)data.size(),8);
qDebug()<<"CanMgr::sendFileContent file size in bytes:"<<Helper::printHex(size);
QCanBusFrame frame = QCanBusFrame(frameId,size);
frame.setExtendedFrameFormat(true);
qDebug()<<"frame data:"<<frame.toString()<<" stat:"<<m_canDevice->state();
queue.append(frame);
frameId = 0;
dev_id=2;
cmd_id=1;
frameId=(dev_id<<16) | cmd_id;
for(int i=0;i<data.size();i+=8) {
QCanBusFrame frame = QCanBusFrame(frameId, data.mid(i,8));
frame.setExtendedFrameFormat(true);
queue.append(frame);
}
frameId = 0;
dev_id=2;
cmd_id=2;
frameId=(dev_id<<16) | cmd_id;
frame = QCanBusFrame(frameId, size);
frame.setExtendedFrameFormat(true);
queue.append(frame);
process_frame=false;
send_timer->start();
}
void CanMgr::processQueue() {
if(queue.isEmpty()) {
qDebug()<<"CanMgr::processQueu queue empty";
return;
}
if(process_frame) {
;
}
else {
curr_frame=queue.dequeue();
process_frame=true;
}
qDebug()<<"CanMgr::processQueue frame data:"<<curr_frame.toString()<<" towrite:"<<m_canDevice->framesToWrite()<<" left:"<<queue.count();
m_canDevice->writeFrame(curr_frame);
}
void CanMgr::processFramesWritten(qint64 count) {
qDebug()<<"CanMgr::processFramesWritten count:"<<count;
process_frame=false;
this->processQueue();
}
QString CanMgr::processErrors(QCanBusDevice::CanBusError error) const
{
QString err_str;
switch (error) {
case QCanBusDevice::ReadError:
case QCanBusDevice::WriteError:
case QCanBusDevice::ConnectionError:
case QCanBusDevice::ConfigurationError:
case QCanBusDevice::UnknownError:
err_str= m_canDevice->errorString();
qDebug()<<"Error:"<<err_str;
send_timer->start();
return err_str;
break;
default:
break;
}
}
Best,
Marek

Send json from arduino and esp8266 to node.js socket server

I've been trying to send JSON data from arduino mega by using ESP8266 as a wifi shield, and I've used node.js as a socket server. The problem is it seems that a server didn't receive any data. here is my code
#include <ArduinoJson.h>
#include "SoftwareSerial.h"
String ssid ="ssid";
String password="pwd";
//SoftwareSerial esp(22,23);// RX, TX
String data;
String server = "server ip";
byte objlength;
String url = "";
String temp,hum,weight;
StaticJsonBuffer<200> jsonBuffer;
JsonObject& root = jsonBuffer.createObject();
//String uri = "yourURI";
void reset() {
Serial2.println("AT+RST");
delay(1000);
if(Serial2.find("OK") ) Serial.println("Module Reset");
}
void connectWifi() {
String cmd = "AT+CWJAP=\"" +ssid+"\",\"" + password + "\"";
Serial2.println(cmd);
delay(4000);
if(Serial2.find("OK")) {
Serial.println("Connected!");
Serial2.println("AT+CIPSTATUS");
delay(300);
while(Serial2.available()){Serial.print(Serial2.read());}
}
else {
connectWifi();
Serial.println("Cannot connect to wifi"); }
}
void setup() {
delay(5000);
// put your setup code here, to run once:
Serial2.begin(115200);
Serial.begin(115200);
reset();
connectWifi();
}
void loop() {
temp = 25.60;
hum = 65.3;
weight = 65.3;
root["weight"] = weight;
root["light"] = temp;
root["humid"] = hum;
objlength = root.measureLength();
senddata();
delay(10000);
}
void senddata()
{
int objlength = root.measureLength();
Serial2.println("AT+CIPSTART=\"TCP\",\"" + server + "\",1336");//start a TCP connection.
delay(500);
if( Serial2.find("OK")) {
Serial.println("TCP connection ready");
}
else
{
Serial.println("can't establish TCP connection");
}
String sendCmd = "AT+CIPSEND=";//determine the number of caracters to be sent.
Serial2.println(sendCmd);
delay(200);
Serial2.println(objlength);
delay(500);
if(Serial2.find(">"))
{
Serial.println("Sending..");
root.printTo(Serial2);
root.printTo(Serial);
//Serial.println(postRequest);
delay(2000);
if( Serial2.find("SEND OK"))
{
Serial.println("Packet sent");
delay(200);
while (Serial2.available()) {
String tmpResp = Serial2.readString();
Serial.println(tmpResp);
}
// close the connection
}
//delay(1000);
Serial2.print("+++");
delay(1200);
Serial2.println("AT+CIPCLOSE");
delay(50);
Serial.println("Closed");
}
}
Here's my node.js
var net = require('net');
var server = net.createServer(function(socket){
socket.write('SEND OK');
//
socket.pipe(socket);
socket.on('data',function(data){
//if(typeof data != 'string'){
var jsontest = JSON.parse(data);
console.log('Received: ' + data);
console.log(jsontest.weight);
console.log(jsontest.light);
console.log(jsontest.humid);
//}
});
socket.on('listening',function(){
console.log(listen);
});
});
/*server.getConnections(function(err,count){
console.log(count);
});*/
server.listen(1336, '10.42.0.1');
I think that esp8266 can establish a connection with a server , but I don't know why the data won't show. Maybe it's about esp8266 respond time?
screenshot
As you can see from this screenshot, I run node.js server and arduino ,but data won't show on server side. Due to this,I'm not sure where are the problems that cause this.
I'm not an expert. I'm just learning how to do it but i'd say you are not giving enough time through connections. You are relying on delays rather than timeouts while waiting for a true response. There is a difference.
Add much more time or change your strategy by using serial.available() and read in a loop that last a prudential amount of time, and exit when you got data.
Sorry no pasting some code, but i hope you got the idea.
Also i'm facing a power problem. 3,3v pin in arduino uno could be weak in clone boards. But i dont think that's the case.

Multithreaded FTP server socket VC++

I am writing a basic FTP client server code in VC++ with multithreading.
The code works fine with single client but it doesn't work for 2 clients. I don't know how socket keep information for multiple clients.
If I do CD from on client it reflects in other one too. I mean if two different clients cannot work on different server directory.
May be something very basic I am missing here due to my lack of knowledge of socket programming.
code to accept connections:
void acceptUserConnections()
{
calen=sizeof(ca);
int thread_count = 0;
thread t[num_threads];
while(1)
{
cout<<"Accepting user connections: "<<endl;
if((cs=accept(serverSocket,&ca.generic,&calen))==INVALID_SOCKET)
throw "Couldn't accept connection\n";
string userAddress(inet_ntoa(ca.ca_in.sin_addr));
thread_count = thread_count +1;
t[thread_count] = thread(handleUserConnection, cs);
t[thread_count].detach();
//handleUserConnection(clientSocket);
}
}
}
to handle:
void handleUserConnection(SOCKET clientSocket)
{
if (strcmpi(command.c_str(),"PWD")==0)
{
ftpPWD(clientSocket);
}
}
for CD
void ftpCD(string directory, SOCKET clientSocket)
{
memset(szbuffer,'\0',1024);
if(!SetCurrentDirectory(directory.c_str()))
{
cout<<strerror(errno)<<endl;
sprintf(szbuffer,"System cannot find the specified directory.");
if(send(clientSocket,szbuffer,1024,0) == SOCKET_ERROR)
throw SEND_FAILED_MSG;
}
else
{
sprintf(szbuffer,"Directory changed successfully.");
if(send(clientSocket,szbuffer,1024,0) == SOCKET_ERROR)
throw SEND_FAILED_MSG;
}
}
for PWD
void ftpPWD(SOCKET clientSocket)
{
memset(szbuffer,'\0',1024);
int nBufferLength =GetCurrentDirectory(MAX_PATH, pwd);
if(!nBufferLength)
{
sprintf(szbuffer,"Failed to get current directory");
if(send(clientSocket,szbuffer,1024,0) == SOCKET_ERROR )
throw SEND_FAILED_MSG;
}
else
{
sprintf(szbuffer,(string(pwd)).c_str());
if(send(clientSocket,szbuffer,1024,0) == SOCKET_ERROR )
throw SEND_FAILED_MSG;
}
}
}

HOw to pair the bluetooth in two devices using NFC

I am trying to pair two devices
One is Google Nexus S which has the applicaion running which reads the mac address written over the tag which is stuck on the other phone which is not Android one .
Now i am trying to pair the devices as i tap on the other phone , my application reads the MAC address stored in the TAG and automatically creates the Bluetooth connection .
Everything is working fine but i am getting a pairing request or to match the keys on both the phones which should not come.
Here is the Bluetooth Segment where the connection is happening
private class ConnectThread extends Thread {
private final BluetoothSocket mmSocket;
private final BluetoothDevice mmDevice;
private String mSocketType;
public ConnectThread(BluetoothDevice device, boolean secure) {
mmDevice = device;
BluetoothSocket tmp = null;
mSocketType = secure ? "Secure" : "Insecure";
// Get a BluetoothSocket for a connection with the
// given BluetoothDevice
try {
if (secure) {
tmp = device.createRfcommSocketToServiceRecord(
MY_UUID_SECURE);
} else {
tmp = device.createInsecureRfcommSocketToServiceRecord(
MY_UUID_INSECURE);
Log.d("CHECK", "Sucessfully created insecure socket");
}
} catch (IOException e) {
Log.e(TAG, "Socket Type: " + mSocketType + "create() failed", e);
}
mmSocket = tmp;
}
public void run() {
Log.i(TAG, "BEGIN mConnectThread SocketType:" + mSocketType);
setName("ConnectThread" + mSocketType);
// Always cancel discovery because it will slow down a connection
mAdapter.cancelDiscovery();
Log.d("CHECK", "Inside RUN");
// Make a connection to the BluetoothSocket
try {
// This is a blocking call and will only return on a
// successful connection or an exception
Log.d("CHECK", "Trying to connect");
mmSocket.connect();
Log.d("CHECK", "Tried to connect");
} catch (IOException e) {
// Close the socket
try {
mmSocket.close();
Log.d("CHECK", "Socket closed");
} catch (IOException e2) {
Log.e(TAG, "unable to close() " + mSocketType +
" socket during connection failure", e2);
}
Log.d("CHECK", "Connection failed");
connectionFailed();
return;
}
// Reset the ConnectThread because we're done
synchronized (BluetoothChatService.this) {
mConnectThread = null;
}
// Start the connected thread
connected(mmSocket, mmDevice, mSocketType);
Log.d("CHECK RESULT", "Sucessfully connected");
// Toast.makeText(BluetoothChatService.ConnectThread.this, "Sucessfully connected" , Toast.LENGTH_LONG).show();
}
public void cancel() {
try {
mmSocket.close();
} catch (IOException e) {
Log.e(TAG, "close() of connect " + mSocketType + " socket failed", e);
}
}
}
I am trying for the insecure connection , but i dont know why it is asking for the pairing keys in both the phones.
Chek your bluetooth version because:
(sic) "For Bluetooth 2.1 devices, the link key will be encrypted, as encryption is mandatory. For legacy devices (pre Bluetooth 2.1 devices) the link key will be not be encrypted."

Resources