#!/usr/bin/python3.4 # -*- coding: utf-8 -*- # from typing import List import asyncio from jinja2 import Environment, PackageLoader from flask import Flask import flask import os import sys import errno import logging #import subprocess from subprocess import Popen,call,PIPE import shlex import time import threading import json from collections import namedtuple import sqlite3 from jinja2 import FileSystemLoader FileInfo = namedtuple('FileInfo', ['relative_path', 'target_path', 'filename', 'context'], verbose=True) app = Flask(__name__) # env = Environment(loader=FileSystemLoader('.')) # env = Environment(loader=PackageLoader('yourapplication', 'templates')) script_lock = threading.Lock() class clientThread(threading.Thread): def __init__(self, ssid, passwd): threading.Thread.__init__(self) self.ssid = ssid self.passwd = passwd def run(self): if not is_associated() : run_script('config_client') connect_to_network(self.ssid,self.passwd) class apThread(threading.Thread): def __init__(self): threading.Thread.__init__(self) def run(self): configure('config_ap', dict()) class checkUSBThread(threading.Thread): def __init__(self): threading.Thread.__init__(self) def run(self): cmd ="su pi -c 'mono /home/pi/yodiwo/wisperFactoryReset/wisperFactoryReset.exe > /home/pi/yodiwo/wisperFactoryReset.log' &" run_wpa_cli_cmd(cmd) class WiFiNet: def __init__(self, essid, mac,encryption,authsuites): self.essid = essid self.mac= mac self.encryption = encryption self.authsuites = authsuites @app.route("/") def hello(): return "Hello World!" @app.route("/render") def render(): return "Hello World!" @app.route('/config_client', methods=['GET', 'POST']) def config_client(): ssid = flask.request.args.get('config_wifi_ssid') password = flask.request.args.get('config_wifi_password') if not password: password = "" if not ssid: return "Invalid parameters", 400 else: thread1 = clientThread(ssid,password) thread1.start() return "Ok" @app.route('/client_mode', methods=['GET', 'POST']) def client_mode(): run_script('config_client') return "Ok" @app.route('/config_ap', methods=['GET', 'POST']) def config_ap(): thread1 = apThread() thread1.start() return "Ok" # vars = { # } # configure('config_ap', vars) @app.route('/purge_wifi_settings', methods=['GET', 'POST']) def purge_wifi_settings(): configure('config_ap', dict(), 1) return "Ok" @app.route('/scan', methods=['GET', 'POST']) def scan(): essid_list = [] j = 0 cmd = "sudo iwlist wlan0 scan" res = run_wpa_cli_cmd(cmd) res = res.strip() cells= res.decode("utf-8").split('Cell') print (cells[1]) foundessid= False foundaddress= False foundencryption=False foundauthsuites= False; authenticationsuites=[] cells.pop(0) for cell in cells: lines= cell.split('\n') for line in lines: if "ESSID" in line: essid = line.strip().split(':')[1] elif "Encryption" in line: encryption = line.strip().split(':')[1] elif "Address" in line: address = line.strip().split(': ')[1] elif "Authentication Suites" in line: auth = line.strip().split(': ')[1] authenticationsuites.append(auth) print ("Construct wifi net") authsuites = ",".join(authenticationsuites) wifinet= WiFiNet(essid,address,encryption,authsuites) authenticationsuites=[] authsuites='' essid_list.append(wifinet) res_json = json.dumps([ob.__dict__ for ob in essid_list]) return (res_json) @app.route('/check_usb') def check_usb(): thread1 = checkUSBThread() thread1.start() return "Ok" @app.route('/connectinfo',methods=['GET', 'POST']) def connectinfo(): try: cmd = "sudo iwconfig wlan0" res = run_wpa_cli_cmd(cmd) print(res) #res = res.strip() lines = res.decode("utf-8").split('\n') for line in lines: if ("ESSID" in line): essid = line.strip().split('ESSID:')[1] return essid return "None" except: return "Unexpected Error" @app.route('/reboot') def reboot(): cmd = "sudo reboot" run_wpa_cli_cmd(cmd) return "Ok" @app.route('/removeflic', methods=['GET', 'POST']) def removeflic(): try: bdaddr = flask.request.args.get('bdaddr') print(bdaddr) if bdaddr is None: removeallflics() res=stopflicd() print(res) time.sleep(3) res=startflicd() print(res) else: removesingleflic(bdaddr) res=stopflicd() print(res) time.sleep(3) startflicd() print(res) return "OK" except Exception as e: print ("Oops, exception while removing flic buttons") print(str(e)) return "Bad Request" def stopflicd(): try: print ("Stop Flicd") run_wpa_cli_cmd("sudo killall flicd") #os.system("sudo killall flicd") return "OK" except Exception as e: print ("Oops, exception while stopping flicd ") print(str(e)) return "Bad Request" def startflicd(): try: print ("StartFlicd") run_wpa_cli_cmd("sudo /home/pi/extools/flic/flicd -d -f /home/pi/extools/flic/flic.sqlite3 -s 0.0.0.0 -l /tmp/log_flicd &") #os.system("sudo /home/pi/extools/flic/flicd -d -f /home/pi/extools/flic/flic.sqlite3 -s 0.0.0.0 -l /tmp/log_flicd &") return "OK" except Exception as e: print ("Oops, exception while stopping flicd ") print(str(e)) return "Bad Request" def removeallflics(): print("Remove All Flics") try: conn=sqlite3.connect('/home/pi/extools/flic/flic.sqlite3') curs=conn.cursor() curs.execute("DELETE FROM buttons") conn.commit() except Exception as e: print (str(e)) def removesingleflic(bdaddr): print("Remove Single Flic") try: conn=sqlite3.connect('/home/pi/extools/flic/flic.sqlite3') curs=conn.cursor() query = 'DELETE FROM buttons WHERE bdaddr=?' curs.execute(query, (bdaddr.strip(),)) #curs.execute("DELETE FROM buttons WHERE bdaddr='" + bdaddr +"'") conn.commit() except Exception as e: print (str(e)) def configure(context, vars = None, flag = None): make_config(context, vars, flag) run_script(context) def make_config(context, vars = None, flag = None): file_infos = get_files(context) for info in file_infos: """ do nothing with wpa_supplicant.conf """ if info.relative_path == "config_ap/etc/wpa_supplicant" and flag!=1: continue else: # processed = render_file(os.path.join(info.relative_path, info.filename), vars) processed = render_file(info.relative_path, info.filename, vars) print (info.relative_path) with open(os.path.join(info.target_path, info.filename), 'w') as f: f.write(processed) # @asyncio.coroutine def run_script(context): script = os.path.join('.', context + '.sh') print (script) call([script]) #Popen([script]) #t1 = threading.Thread(target=run_script_inner, args=[script]) #t1.start() #def run_script_inner(filename): # with script_lock: # subprocess.call([filename]) def get_files(context):# -> List[FileInfo]: dirs = os.walk(context) files = [] for d in dirs: targetpath = d[0].split(context, 1)[1] new = [FileInfo(d[0], targetpath, f, context) for f in d[2]] files.extend(new) return files def render_file(path, filename, vars = None): # with open(filename, 'r') as f: # template_string = f.read() # template = Environment().from_string(template_string) template = Environment(loader=FileSystemLoader(path)).get_template(filename) return template.render(**vars) def run_wpa_cli_cmd(rcmd): """ Runs a program, and it's paramters (e.g. rcmd="ls -lh /var/www") Returns output if successful, or None and logs error if not. """ cmd = shlex.split(rcmd) executable = cmd[0] executable_options=cmd[1:] try: proc = Popen(([executable] + executable_options), stdout=PIPE, stderr=PIPE) response = proc.communicate() response_stdout, response_stderr = response[0], response[1] except OSError(e): if e.errno == errno.ENOENT: logging.debug( "Unable to locate '%s' program. Is it in your path?" % executable ) else: logging.error( "O/S error occured when trying to run '%s': \"%s\"" % (executable, str(e)) ) except ValueError(e): logging.debug( "Value error occured. Check your parameters." ) else: if proc.wait() != 0: logging.debug( "Executable '%s' returned with the error: \"%s\"" %(executable,response_stderr) ) return response else: logging.debug( "Executable '%s' returned successfully. First line of response was \"%s\"" %(executable, response_stdout.decode("utf-8").split('\n')[0] )) return response_stdout def get_net_number(ssid): """ Returns the number of existing network """ cmd = "wpa_cli -i wlan0 list_net" res = run_wpa_cli_cmd(cmd) nets = res.decode("utf-8").split('\n') print(len(nets)) for i in range(1, (len(nets)-1)) : found = nets[i].count(ssid) if found: break return i def check_network_exist(ssid): """ Check if a network already exists, in order to avoid duplicate entry in wpa_supplicant.conf """ try: cmd = "wpa_cli -i wlan0 list_net" res = run_wpa_cli_cmd(cmd) tmp = res.decode("utf-8").find(ssid) if ( tmp == -1 ): return tmp else: net_no = get_net_number(ssid) return net_no except: return -1 ''' For future use in order to implement temporary disable nets ''' # def check_enabled_net(): # """ # Check if active networks exist # """ # try: # cmd = "wpa_cli -i wlan0 list_net" # res = run_wpa_cli_cmd(cmd) # nets = res.decode("utf-8").split('\n') # print(len(nets)) # # for i in range(1, (len(nets)-1)) : # found = nets[i].count("CURRENT") # if found: # return i # except: # return -1 def connect_to_network(ssid, password): netw = check_network_exist(ssid) if netw == -1 : print ("Network is NOT found , add it to conf") cmd_add_net = "wpa_cli -i wlan0 add_network" res = run_wpa_cli_cmd(cmd_add_net) print (cmd_add_net) print (res.strip()) cmd_set_ssid = "wpa_cli -i wlan0 set_network %d ssid \\\"%s\\\"" % (int(res),ssid) resp = run_wpa_cli_cmd(cmd_set_ssid) print(cmd_set_ssid) print(resp.strip()) if password != "": cmd_set_mgmt = "wpa_cli -i wlan0 set_network %d key_mgmt WPA-PSK" % (int(res)) resp = run_wpa_cli_cmd(cmd_set_mgmt) print(cmd_set_mgmt) print(resp.strip()) cmd_set_key = "wpa_cli -i wlan0 set_network %d psk \\\"%s\\\"" % (int(res),password) resp = run_wpa_cli_cmd(cmd_set_key) print(cmd_set_key) print(resp.strip()) else: cmd_set_mgmt = "wpa_cli -i wlan0 set_network %d key_mgmt NONE" % (int(res)) resp = run_wpa_cli_cmd(cmd_set_mgmt) print(cmd_set_mgmt) print(resp.strip()) # active_net = check_enabled_net() # if(active_net): # cmd_disable = "wpa_cli -i wlan0 disable_network %d" % (int(active_net)-1) # resp = run_wpa_cli_cmd(cmd_disable) cmd_enable = "wpa_cli -i wlan0 enable_network %d" % (int(res)) resp = run_wpa_cli_cmd(cmd_enable) time.sleep(5) print (cmd_enable) print(resp.strip()) #cmd_save = "wpa_cli -i wlan0 save_config" #resp = run_wpa_cli_cmd(cmd_save) #print (cmd_save) #print(resp.strip()) else: # active_net = check_enabled_net() # if active_net : # cmd_disable = "wpa_cli -i wlan0 disable_network %d" % (int(active_net)-1) # resp = run_wpa_cli_cmd(cmd_disable) # print (cmd_disable) # print(resp.strip()) cmd_enable = "wpa_cli -i wlan0 enable_network %d" % (int(netw)-1) resp = run_wpa_cli_cmd(cmd_enable) time.sleep(5) print (cmd_enable) print(resp.strip()) #time.sleep(10) cnt = 0 while not is_associated(): if cnt < 60 : time.sleep(1) print("*") cnt = cnt + 1 else : break if cnt == 60 : configure('config_ap',dict()) else : cmd_save = "wpa_cli -i wlan0 save_config" resp = run_wpa_cli_cmd(cmd_save) print (cmd_save) print(resp.strip()) return True def is_associated(): """ Check if we're associated to a network. """ try: res = run_wpa_cli_cmd("wpa_cli -i wlan0 status | grep wpa_state") #print (res) tmp = res.decode("utf-8").find('COMPLETED') #tmp = res.strip().decode("utf-8").split('=')[1] print(tmp) if tmp != -1: print ("Connected !!!!!!!!!!!!!!!!!!!!!!!") return True except: return False if __name__ == "__main__": # make_config('config_client', {'config_wifi_ssid': 'asdf', 'config_wifi_password': 'zxcv'}) # files = get_files('config_ap') if len(sys.argv) == 1: app.run(host="0.0.0.0", port=8080, debug=True) else: if 'config_client' in sys.argv[1] and len(sys.argv) >= 4: print('configuring client') thread1 = clientThread(sys.argv[2],sys.argv[3]) thread1.start() # if not is_associated() : # run_script('config_client') # connect_to_network(sys.argv[2],sys.argv[3]) elif 'config_ap' in sys.argv[1] : print('configuring ap') configure('config_ap', dict()) elif 'scan' in sys.argv[1] : essid_list = [] print("Start scanning") cmd = "sudo iwlist wlan0 scan" res = run_wpa_cli_cmd(cmd) resp = res.decode("utf-8").split('\n') j = 0 for i in range(1, len(resp)): if "ESSID" in resp[i]: essid_list.insert(j,resp[i].strip().split(':')[1]) j = j + 1 res_json = json.dumps(essid_list) print(res_json) elif 'purge_wifi_settings' in sys.argv[1] : configure('config_ap',dict(),1)