1

Since ubuntu 14.04 LTS, i've been having this issue that my wireless connection gets "messed up" - more specifically I sometimes loose connection.

I'm currently solving this issue by disconnecting and then connecting back again. This works either by me clicking the top right unity bar icon, or by issuing an rfkill block wifi followed by an rfkill unblock wifi command

I haven't found a solution to the read problem yet, but I got this idea that if i could programatically handle this situation with a script that triggers when the disconnect occurs, i'll be just fine.

I also don't want to create a script that constantl polls for the wifi status, I'd want to listen for this specific event, and act uopn being notified.

Is this somehow possible?

  • I am not sure what you mean by "I also don't want to create a script that constantly polls for the wifi status". A mechanism that acts on certain status- changes has to check the current status at intervals in a loop. Not much you can do about that. That is basically what "listening" is. (if that's what you mean?). – Jacob Vlijm Sep 21 '14 at 17:21
  • if there's nothing else i can do, then i'll gladly poll, but i want to make sure. especially that there's this inotify which seens to do something very similar to what i want: http://en.wikipedia.org/wiki/Inotify - haven't used it, dunno much about it though – vlad-ardelean Sep 21 '14 at 17:32
  • Look here: http://www.ibm.com/developerworks/library/l-inotify/ which descripbes how Inotify is applied. Loops should not consume a noticable deal of your resources. – Jacob Vlijm Sep 21 '14 at 17:43
  • Are you sure the two commands: rfkill block wifi and rfkill unblock wifi are doing the job? They do nothing on my wifi. what does work however is sudo service network-manager restart as mentioned here: http://askubuntu.com/a/399159/72216. If you want, I can make an example "watch" script. – Jacob Vlijm Sep 21 '14 at 18:34
  • @JacobVlijm positive. a "coincidence" is excluded. Perhaps we have different problems, but that's how i solve it every time by clicking "deactivate network" -> "activate network" (or something similar, don't really know, i use ubuntu in german) – vlad-ardelean Sep 22 '14 at 07:23
  • Well, actually I have no problem, but I was just testing the commands. – Jacob Vlijm Sep 23 '14 at 06:45
  • Check if there are some NetworkManager event when "wirless is messed up" in /var/log/syslog. If yes, it is possible to write a event hook script. If system doesn't emit any event on this kind of situation, than probably the only way is follow @JacobVlijm approach. – Lety Sep 23 '14 at 12:04

2 Answers2

3

First of all:

What you describe as your desired answer is what you actually call: I also don't want to create a script that constantl polls. Inotify also is used in a constant loop to "listen" to changes in the current state. In other words: the other option you assume to exist does not exist without some kind of a loop.

I also think your image of a loop is too heavy. On every system, in every application there are numerous loops active to wait for triggers. It should have no noticable effect on your resources.

The "anatomy" of such a take-action-on-event mechanism is basically:

in a while loop:

check the current status;
if a is True:
    take action A
if a is False:
    do nothing
wait a few seconds

In a bash script

Integrating this script (to check your connection) in a while loop (with a few minor changes) should do what you describe: re-establish your connection and send a notification.

#!/bin/bash

while :
do
  wget -q --tries=10 --timeout=20 --spider http://google.com
  if [[ $? -eq 0 ]]; then
          :
  else
          rfkill block wifi
          rfkill unblock wifi
          notify-send "connection re-established"
  fi
  sleep 4
done

In a python script

The function check() returns True or False. If True (connection is up), nothing happens. If False, your rfkill block wifi / rfkill ublock wifi is executed.

#!/usr/bin/env python3

import socket
import time
import subprocess

def check():
    try:
        host = socket.gethostbyname("www.google.com")
        s = socket.create_connection((host, 80), 2)
        return True
    except Exception:
        return False

while True:
    if check() == True:
        pass
    else:
        subprocess.call(["/bin/bash", "-c", "rfkill", "block", "wifi"])
        subprocess.call(["/bin/bash", "-c", "rfkill", "unblock", "wifi"])
        subprocess.Popen(["/bin/bash", "-c", "notify-send 'conncection re-established'"])
    time.sleep(4)
Jacob Vlijm
  • 83,767
  • @vlad-ardelean is this what you are looking for? – Jacob Vlijm Sep 23 '14 at 08:38
  • @JacomVlijm Thank you for the detailed response, but it wouldn't have been a problem for me to come up with this solution, in python or bash. I was most curious in handling events. I'll thumb up your answer, but i can't accept it as the answer to my question. I can accept an answer with my desired solution, or one that says it's impossible to do it the way i want. – vlad-ardelean Sep 23 '14 at 11:19
  • @vlad-ardelean see my edited answer. – Jacob Vlijm Sep 23 '14 at 11:34
  • Thank you for the effort put in for helping. At this point I am basically forced to accept your answer :D – vlad-ardelean Sep 23 '14 at 15:15
1

My script for handling FREE WIFI login/logout and WIRELESS connection reconnect and repair.

It connects to free wifi, logs in, gets connection time left and waits until time is up and checks wifi and login status and internet connection, logs out and repeats.

For sending notifications to desktop enviroment use

notify-send "YOUR MESSAGE HERE"

Wifi connection repair is handled in function ReConnect()

#!/bin/bash
WIFI_DEVICE="wlp3s2"
USER_PC="T-00%3AC0%3AA8%3AC7%3AF0%3AF1"
USER_USB="T-00%3AE0%3A4C%3A84%3AD2%3A5C"
USER_NAME="$USER_PC"
LOGIN_URL="http://starse.hotspot/login?username="
LOGOUT_URL="http://starse.hotspot/logout"
STATUS_URL="http://starse.hotspot/status"
WIFI_NETWORK="starse.WiFiPoint"
WIFI_PROFILE_FILE_SEARCH="starse"
PORT=5555
LOGIN_RETRY=5
REPEAT_HOURS=10000
SECONDS_LEFT="0"
ONE_MINUTE=15
MINUTES=0
START=0
END=0
ONE=1
ZERO=0

function CleanConnections()
{
    MYDIR=$(pwd)
    #remove all connections from network manager
    cd /etc/NetworkManager/system-connections/ &> /dev/null
    rm "$WIFI_PROFILE_FILE_SEARCH.*" &> /dev/null
    cd $MYDIR &> /dev/null
}

function ReConnect()
{
    # check if WIFI_DEVICE is connected to WIFI_NETWORK
    WIFI_OK=$(iwconfig $WIFI_DEVICE | grep -c $WIFI_NETWORK)

    # while not connected, try to repair connection
    while [ $WIFI_OK = "0" ]
    do
        # check if wifi radio is on / turn it on
        RADIO=$(nmcli radio wifi)
        sleep 1
        if [ "$RADIO" = "onemogočeno" ]
        then
            nmcli radio wifi on
            echo "$(date), WIFI RADIO OMOGOČEN!"
        fi
        sleep 1
        # check if WIFI_DEVICE is connected to WIFI_NETWORK again
        WIFI_OK=$(iwconfig $WIFI_DEVICE | grep -c $WIFI_NETWORK)
        if [ $WIFI_OK = "0" ]
        then
            # if not connected, connect to WIFI_NETWORK
            echo "$(date), POVEZAVA WIFI PREKINJENA!"
            nmcli d wifi connect "$WIFI_NETWORK" &> /dev/null
            sleep 1

            # check if WIFI_DEVICE is connected to WIFI_NETWORK again
            WIFI_OK=$(iwconfig $WIFI_DEVICE | grep -c $WIFI_NETWORK)
            sleep 1

            # if connection is still not established, restart network-manager and check connection
            if [ $WIFI_OK = "0" ] 
            then
                service network-manager restart
                sleep 2
                WIFI_OK=$(iwconfig $WIFI_DEVICE | grep -c $WIFI_NETWORK)
                echo "$(date), NETWORK MANAGER PONOVNO ZAGNAN!" 
            else
                echo "$(date), POVEZAVA WIFI VZPOSTAVLJENA!"
                sleep 2         
            fi
        fi
    done
}


function Login()
{
    RETRY_COUNT=0
    LOGIN_OK=0
    # while not logged in
    while [ $LOGIN_OK = "0" ]
    do
        # try to login
        LOGIN_OK=$(curl -s -m 2 "$LOGIN_URL$USER_NAME" | grep -c "You are logged in")
        if [ $LOGIN_OK = "1" ] 
        then
            echo "$(date), PRIJAVA USPEŠNA."
            break
        else
            # if could not login, try for RETRY_COUN
            echo "$(date), PRIJAVA NEUSPEŠNA! Ponavljam $RETRY_COUNT od $LOGIN_RETRY"
            RETRY_COUNT=$((RETRY_COUNT+1))
            sleep 1
        fi

        # if RETRY_COUNT expired then ReConnect and continue
        if [ $RETRY_COUNT -gt $LOGIN_RETRY ]
        then
            ReConnect
            RETRY_COUNT=0
            continue
        fi
    done
}


function GetSecondsLeft()
{
    STATUS_PAGE=$(wget -T 2 -q -O - "$@" "$STATUS_URL") 
    sleep 10
    MIN1=$(echo $STATUS_PAGE | grep -o '[0-9| ][0-9]m' | tail -1 | tr -d 'm' | tr -d ' ')
    sleep 1
    SEC1=$((MIN1*60))
    echo "$(date), ČAS PRIDOBLJEN. NA VOLJO: $((SEC1))s"
    eval "$1"="$SEC1"
}

#ReConnect

LOGIN_NR=1
while  [ "$LOGIN_NR" -lt "$REPEAT_HOURS" ]
do


    # try to login first
    Login

    #set counters
    START=$(date +%s)

    # get time left from status page
    GetSecondsLeft SECONDS_LEFT

    # clean wifi profiles dir
    CleanConnections

    # get first ELPASED_SEC
    END=$(date +%s)
    ELPASED_SEC=$((END-START))

    # count till next login
    while [ $ELPASED_SEC -lt $SECONDS_LEFT ]
    do  
        # display info
        echo "$(date), LOGIN: $LOGIN_NR, PRETEKLO: $((ELPASED_SEC))s,  NA VOLJO ŠE: $((SECONDS_LEFT-ELPASED_SEC))s"


        # wait ONE_MINUTE and periodicaly check for wifi and internet connection every two/three seconds    
        ELPASED_MINUTE_SEC=0
        while [ $ELPASED_MINUTE_SEC -lt $ONE_MINUTE ]
        do
            # start timer
            S=$(date +%s)

            # check for wifi connection
            WIFI_OK=$(iwconfig $WIFI_DEVICE | grep -c $WIFI_NETWORK)
            if [ $WIFI_OK = "1" ]
            then
                #  if wifi connection OK, check for internet connection
                PING="0"
                PING=$(ping -c 1 -w 2000 -s 1 www.google.si | grep -c "9 bytes")
                sleep 2
                if [ "$PING" = "0" ]
                then
                    echo "$(date), INTERNETNA POVEZAVA PREKINJENA! Vzpostavljam ..."
                    # if no internet connection then Login()
                    Login
                    # on reconnect caculate SECONDS_LEFT and reset ELPASED_SEC
                    GetSecondsLeft SECONDS_LEFT
                    ELPASED_SEC=0
                else
                    sleep 1
                fi
            else
                # if wifi connection is lost ReConnect()
                ReConnect   
            fi                  

            # check if whole time is up and break
            END=$(date +%s)
            ELPASED_SEC=$((END-START))
            if [ $SECONDS_LEFT -le $ELPASED_SEC ]
            then
                break
            fi

            # add used seconds to ELPASED MINUTE            
            E=$(date +%s)
            ELPASED_MINUTE_SEC=$((ELPASED_MINUTE_SEC+(E-S)))            
        done    
        END=$(date +%s)
        ELPASED_SEC=$((END-START))
    done


    # TIME IS UP
    # logout and increase LOGIN_NR
    curl -s -m 2 "$LOGOUT_URL" &> /dev/null
    LOGIN_NR=$((LOGIN_NR+1))

done