Clean way to real, always working, auto-reconnect - arduino-esp8266

I hope to open a question that is useful for the users of this shield.
Incipit: WiFi.setAutoReconnect(true); seems that not prevent 100% of disconnections.
I've tested a lot of shields (ESP12F, ESP01) and in some case i noted that the auto-reconnect does not work properly.
Fact:
I was unable to reproduce when the shield is connect to pc/debugger.
When did it happen, i try to execute a task depending on a botton press, eg:
loop(){
if (digitalRead... == HIGH) do_something()
}
And the shield... do something! So, the shield was not frozen.
I try to reset (BOTH via HW and SW) and the shield immediately reconnect.
I read some other source and this behavior is often described (es. https://randomnerdtutorials.com/solved-reconnect-esp32-to-wifi/ ). Brief: try WiFi.reconnect(), if it does not work try ESP.restart().
Then, the question:
Why does this happen? Is there a problem with the arduino libraries, or with the native expressif interface? Or is a well-known hardware problem unsolvable via SW?
If indeed so, what techniques do you use to prevent disconnection? I have set a ticker every 30 minutes, which if it sees the card disconnected for more than a certain time, it restarts it. Eg.
void checkWifi() {
if (lastPing + DELTA < millis()) ESP.restart();
}
ticker.attach(checkWifi, ...)
void loop() {
if WiFi.isConnect() {
lastPing = millis();
...
}
}
If there is nothing to do, what do you think of the restart technique? Is it risky to restart frequently, can it reduce the life of the device?
Thanks to anyone who wants to contribute or exchange impressions!

Related

Can I trigger the Hololens Calibration sequence from inside my application?

I have a hololens app I am creating that requires the best accuracy possible for hologram placement. This application will be used by numerous individuals. Whenever I try to show the application progress, I have to have the user go through the calibration process, otherwise the holograms appear to have way too much drift.
I would like to be able to call the hololens calibration process automatically when the application opens. Later, after I set up user authentication and id management, I will call the calibration process when a new user is found.
https://learn.microsoft.com/en-us/windows/mixed-reality/calibration
I have looked into the calibration (via the above documentation and elsewhere) and it seems that all it is setting is IPD. However the alternative solutions I have found that allow for dynamic ipd adjustment appear to be invalid for UWP Store apps. This makes them unusable for me.
I am looking for any help or direction, or if this is even possible. Thank you.
Yes, it is possible to to this, you need to use the LaunchUriAsync protocol to launch the following URI: ms-hololenssetup://EyeTracking
Here is an example implementation, obtained from the LaunchUri example in MRTK
public void LaunchEyeTracking()
{
#if WINDOWS_UWP
UnityEngine.WSA.Application.InvokeOnUIThread(async () =>
{
bool result = await global::Windows.System.Launcher.LaunchUriAsync(new System.Uri("ms-hololenssetup://EyeTracking"));
if (!result)
{
Debug.LogError("Launching URI failed to launch.");
}
}, false);
#else
Debug.LogError("Launching eye tracking not supported Windows UWP");
#endif
}

Coded ui test in a multithreaded scenario and control not found.

As you all know Coded ui playback can be kind of slow depending on the controls you're querying.
To try and solve this issue I am looking at adding some multithreading capabilities to the test.
Here is a for loop which works successfully, now converted to a Parallel.For - only the control cannot be found (not at all).
Parallel.For(0, totalItems, (i, loopState) =>
{
DxLookup.OpenPopup();
var cell = _popupGrid.GetCell(viewName, column.ColumnName, i);
cell.DrawHighlight();
if (cell.ValueAsString == item)
{
found = true;
loopState.Stop();
}
});
The code fails on the DxLookup.OpenPopup - because the control is not found. Looks like it could be thread related.
How is it possible to access a test control from another thread then?
I am not too sure about Coded UI playback supports multi-threading capabilities check this link for playback related information
Configure Playback
you may try come other techniques to speedup the playback
what kind of app are you trying to test? if it's a winforms app multithrreading is problematic.
try testing wheter you can locate tha main app window or any kind of control. if not you'll know it's a threading problem. if you can locate any kind of control just not the desired control you'll be able to tweak the search configurations to loacte the control.
hope this helps

How to set up a internet connectivity detector for a Net::IRC bot?

I have an IRC bot written in Perl, using the deprecated, undocumented and unloved Net::IRC library. Still, it runs just fine... unless the connection goes down. It appears that the library ceased to be updated before they've implemented support for reconnecting. The obvious solution would be to rewrite the whole bot to make use of the library's successors, but that would unfortunately require rewriting the whole bot.
So I'm interested in workarounds.
Current setup I have is supervisord configured to restart the bot whenever the process exits unexpectedly, and a cron job to kill the process whenever internet connectivity is lost.
This does not work as I would like it to, because the bot seems incapable of detecting that it has lost connectivity due to internet outage. It will happily continue running, doing nothing, pretending to still be connected to the IRC server.
I have the following code as the main program loop:
while (1) {
$irc->do_one_loop;
# can add stuff here
}
What I would like it to do is:
a) detect that the internet has gone down,
b) wait until the internet has gone up,
c) exit the script, so that supervisord can resurrect it.
Are there any other, better ways of doing this?
EDIT: The in-script method did not work, for unknown reasons. I'm trying to make a separate script to solve it.
#!/usr/bin/perl
use Net::Ping::External;
while (1) {
while (Net::Ping::External::ping(host => "8.8.8.8")) { sleep 5; }
sleep 5 until Net::Ping::External::ping(host => "8.8.8.8");
system("sudo kill `pgrep -f 'perl painbot.pl'`");
}
Assuming that do_one_loop will not hang (may need to add some alarm if it does), you'll need to actively poll something to tell whether or not the network is up. Something like this should work to ping every 5 seconds after a failure until you get a response, then exit.
use Net::Ping::External;
sub connectionCheck {
return if Net::Ping::External::ping(host => "8.8.8.8");
sleep 5 until Net::Ping::External::ping(host => "8.8.8.8");
exit;
}
Edit:
Since do_one_loop does seem to hang, you'll need some way to wrap a timeout around it. The amount of time depends on how long you expect it to run for, and how long you are willing to wait if it becomes unresponsive. A simple way to do this is using alarm (assuming you are not on windows):
local $SIG{'ALRM'} = sub { die "Timeout" };
alarm 30; # 30 seconds
eval {
$irc->do_one_loop;
alarm 0;
};
The Net::IRC main loop has support for timeouts and scheduled events.
Try something like this (I haven't tested it, and it's been 7 years since I last used the module...):
# connect to IRC, add event handlers, etc.
$time_of_last_ping = $time_of_last_pong = time;
$irc->timeout(30);
# Can't handle PONG in Net::IRC (!), so handle "No origin specified" error
# (this may not work for you; you may rather do this some other way)
$conn->add_handler(409, sub { $time_of_last_pong = time });
while (1) {
$irc->do_one_loop;
# check internet connection: send PING to server
if ( time-$time_of_last_ping > 30 ) {
$conn->sl("PING"); # Should be "PING anything"
$time_of_last_ping = time;
}
break if time-$time_of_last_pong > 90;
}

Custom Joystick Behavior Linux - Adding Mod Keys

I don't have much experience with this type of stuff so I wanted to get some feedback on what I should be looking into.
Here is the situation: I have a joystick (Thrustmaster T-Flight Hotas X) that has about 12 buttons. What I would like to do is be able to hold 1 of the buttons and use it as a mod key so that I could double the number of buttons I have (I would effectively have 22 buttons).
Now what is the best way to go about this? I am currently running Ubuntu 13.10. I believe the device is picked up by the usbhid driver. Now should I be trying to write a custom driver that would yield this behavior or is there a better/less complicated way of going about this - i.e. intercepting the events and modifying them on the fly - or something else I don't even know is possible.
Anyways hope I was clear. Just trying to figure out the best course of action here.
Thanks in advance.
I would just try to use the existing Linux joystick API
https://git.kernel.org/cgit/linux/kernel/git/stable/linux-stable.git/tree/Documentation/input/joystick-api.txt?id=refs/tags/v3.9.6
then is user space you can get all the joystick events, and process them as you see fit. Specifically you can get button press events and use logic as follows:
void handle_button_y_press()
{
if (button_X_pressed)
{
do_y_function_a();
}
else
{
do_y_function_b();
}
}

Block All Keyboard Input in a Linux Application (Using Qt or Mono)

I'm working on a online quiz client where we use a dedicated custom-made linux distro which contains only the quiz client software along with text editors and other utility software. When the user has started the quiz, I want to prevent him/her from minimizing the window/closing it/switching to the desktop or other windows. The quizzes can be attempted using only the mouse, so I need the keyboard to be completed disabled for the period of the quiz. How could I do this, using Qt or Mono? I'm ready to use any low-level libraries/drivers, if required.
You may use QWidget::grabKeyboard and QWidget::grabMouse, and please note the warning in comments:
Warning: Bugs in mouse-grabbing
applications very often lock the
terminal. Use this function with
extreme caution, and consider using
the -nograb command line option while
debugging.
Have you looked at XGrabKeyboard? That should do a global grab of the keyboard.
Did you try to use EventFilter ? You have the opportunity to block all the events related to, as instance, keypress...
More information here : http://qt.nokia.com/doc/4.6/eventsandfilters.html
Hope it helps !
Something like :
bool MyWidget::event(QEvent *event)
{
if (event->type() == QEvent::KeyPress)
{
return true;
}
return QWidget::event(event);
}

Resources