Skip to content

Instantly share code, notes, and snippets.

@ryansturmer
Created October 9, 2015 02:40
Show Gist options
  • Save ryansturmer/f4b62435ff304583156e to your computer and use it in GitHub Desktop.
Save ryansturmer/f4b62435ff304583156e to your computer and use it in GitHub Desktop.
configure_edison with better wifi management
#!/usr/bin/python
# Copyright (c) 2014, Intel Corporation.
#
# This program is free software; you can redistribute it and/or modify it
# under the terms and conditions of the GNU Lesser General Public License,
# version 2.1, as published by the Free Software Foundation.
#
# This program is distributed in the hope it will be useful, but WITHOUT ANY
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
# FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for
# more details.
#
import os
import sys
from sys import stdout
import time
import termios
import fcntl
import subprocess
import signal
import urllib2
import hashlib
import argparse
import json
import re
import popen2
from array import *
WSREGEX = re.compile(r"\s+")
DESTINATION_PATH = "/tmp/"
STATE_DIR = '/var/lib/edison_config_tools'
HOST_AP_MODE_FILE = "/.start-in-host-ap-mode"
CURR_PACKAGE_PATH = ""
class text_colors:
CYAN = '\033[96m'
MAGENTA = '\033[95m'
BLUE = '\033[94m'
YELLOW = '\033[93m'
GREEN = '\033[92m'
RED = '\033[91m'
END = '\033[0m'
class wpa_templates:
START = '''
ctrl_interface=/var/run/wpa_supplicant
ctrl_interface_group=0
update_config=1
ap_scan=1
'''
OPEN = '''
network={
ssid="%s"
%s
key_mgmt=NONE
}'''
WEP = '''
network={
ssid="%s"
%s
key_mgmt=NONE
group=WEP104 WEP40
wep_key0="%s"
}
'''
WPAPSK = '''
network={
ssid="%s"
%s
key_mgmt=WPA-PSK
pairwise=CCMP TKIP
group=CCMP TKIP WEP104 WEP40
eap=TTLS PEAP TLS
psk="%s"
}
'''
WPAEAP = '''
network={
ssid="%s"
%s
key_mgmt=WPA-EAP
pairwise=CCMP TKIP
group=CCMP TKIP WEP104 WEP40
eap=TTLS PEAP TLS
identity="%s"
password="%s"
phase1="peaplabel=0"
}
'''
#worst case, break this out.
MAX = '''
network={
ssid="%s"
%s
key_mgmt=WPA-EAP WPA-PSK IEEE8021X NONE
pairwise=CCMP TKIP
group=CCMP TKIP WEP104 WEP40
psk="%s"
eap=TTLS PEAP TLS
identity="%s"
password="%s"
phase1="peaplabel=0"
}
'''
# Helpers
#######################################
def getch():
fd = sys.stdin.fileno()
oldterm = termios.tcgetattr(fd)
newattr = termios.tcgetattr(fd)
newattr[3] = newattr[3] & ~termios.ICANON & ~termios.ECHO
termios.tcsetattr(fd, termios.TCSANOW, newattr)
oldflags = fcntl.fcntl(fd, fcntl.F_GETFL)
fcntl.fcntl(fd, fcntl.F_SETFL, oldflags | os.O_NONBLOCK)
try:
while 1:
try:
c = sys.stdin.read(1)
break
except IOError: pass
finally:
termios.tcsetattr(fd, termios.TCSAFLUSH, oldterm)
fcntl.fcntl(fd, fcntl.F_SETFL, oldflags)
return c
def getPassword(prompt):
stdout.write(prompt)
pw = ""
while 1:
c = getch()
if c == '\r' or c == '\n':
break
if c == '\003':
raise KeyboardInterrupt
if c == '\x08' or c == '\x7f':
if len(pw):
pw = pw[:-1]
stdout.write('\x08')
stdout.write('\x20')
stdout.write('\x08')
else:
pw = pw + c
stdout.write("*")
stdout.write('\r')
stdout.write('\n')
return pw
#failure code. needs to create an error log later.
def noooo(location):
unacceptable_failure = "Strange Error... this shouldn't happen. Failure at %s. Let us know so we can patch this."
print unacceptable_failure % location
quit()
def verified(selection):
verify = raw_input("Is " + text_colors.MAGENTA + selection + text_colors.END + " correct? " + text_colors.YELLOW + "[Y or N]" + text_colors.END + ": ")
if verify == "Y" or verify == "y":
return 1
elif verify == "N" or verify == "n":
return 0
else:
while 1:
verify = raw_input("Please enter either " + text_colors.YELLOW + "[Y or N]" + text_colors.END + ": ")
if verify == "Y" or verify == "y":
return 1
elif verify == "N" or verify == "n":
return 0
def changeName(newName):
if WSREGEX.search(newName):
print "New name contains whitespaces. Ignoring"
return
_changeHostName(newName)
_changeP2PSSID(newName)
_changeAPSSID(newName)
def _changeHostName(newName):
hostname_file = open('/etc/hostname','w')
hostname_file.write(newName + "\n")
hostname_file.close();
subprocess.call("hostname -F /etc/hostname", shell=True)
def _changeAPSSID(newName):
saveDefaultSSID()
subprocess.call(["sed", "-i", "s/^ssid=.*/ssid=" + newName + "/", "/etc/hostapd/hostapd.conf"])
subprocess.call("systemctl restart mdns && sleep 2", shell=True)
def _changeP2PSSID(newName):
subprocess.call(["sed", "-i", "s/^p2p_ssid_postfix=.*/p2p_ssid_postfix=" + newName + "/", "/etc/wpa_supplicant/p2p_supplicant.conf"])
def changePassword(newPass):
if WSREGEX.search(newPass):
print "New password contains whitespaces. Ignoring"
return
_changeRootPassword(newPass)
if len(newPass) > 0:
_changeAPPassword(newPass)
if (not os.path.isfile(STATE_DIR + "/password-setup.done")):
pass_done = open(STATE_DIR + "/password-setup.done", "w")
pass_done.write("Indicates that password has been changed via oobe.\n")
pass_done.close()
print "First-time root password setup complete. Enabling SSH on WiFi interface."
subprocess.call("sed -i 's/^BindToDevice=/# BindToDevice=/g' /lib/systemd/system/sshd.socket ; sync ; systemctl daemon-reload; systemctl restart sshd.socket", shell=True)
def _changeRootPassword(newPass):
echoSub = subprocess.Popen(["echo", "root:" + newPass], stdout=subprocess.PIPE)
chpasswdSub = subprocess.Popen(["chpasswd"], stdin=echoSub.stdout, stdout=subprocess.PIPE)
echoSub.stdout.close() # Allow echoSub to receive a SIGPIPE if chpasswdSub exits.
chpasswdSub.communicate()[0]
def _changeAPPassword(newPass):
subprocess.call(["sed", "-i", "s/^wpa_passphrase=.*/wpa_passphrase=" + newPass + "/", "/etc/hostapd/hostapd.conf"])
def getNetworkIdentity():
return raw_input("Please enter the network username: ")
def getNetworkPassword():
pw = ''
while len(pw) == 0:
pw = getPassword("What is the network password?: ")
return pw
def reset(stage):
subprocess.call("clear", shell=True)
print text_colors.CYAN + "\nConfigure Edison: " + stage + "\n" + text_colors.END
# Main Functions
#######################################
def setEdisonHostname():
while 1:
name = raw_input("Give this Edison a unique name.\nThis will be used for the access point SSID and mDNS address.\nMake it at least five characters long (leave empty to skip): ")
if (WSREGEX.search(name)):
print ""
print 'Hostname must not contain whitespaces. Please try again.'
print ""
elif (len(name) == 0):
print "Skipping name change..."
break
elif (len(name) > 4):
if verified(name):
print ""
break
else:
print ""
else:
print ""
print '\"' + name + '\" is too short. Please try again.'
print ""
if len(name) > 0:
changeName(name)
def setEdisonPassword():
while 1:
password = getPassword("Enter a new password (leave empty to abort)\nThis will be used to connect to the access point and login to the device.\nPassword: \t")
if (password == getPassword("Please enter the password again: \t")):
if (WSREGEX.search(password)):
print ""
print 'The device password must not contain whitespaces. Please try again.'
print ""
elif len(password) == 0:
print "Skipping password change."
return
elif len(password) < 8 or len(password) > 63:
print ""
print "The device password must be between 8 and 63 characters long. Please try again."
print ""
else:
break
else:
print ""
print "The passwords do not match. Please try again."
print ""
changePassword(password)
print "The device password has been changed.\n"
def decideToConnect():
while 1:
verify = raw_input("Do you want to set up wifi? " + text_colors.YELLOW + "[Y or N]" + text_colors.END + ": ")
if verify == "y" or verify == "Y":
return 1
elif verify == "n" or verify == "N":
return 0
else:
print "I need Y or N as a reply."
WPAPSK_REGEX=re.compile(r'\[WPA[2]?-PSK-.+\]')
WPAEAP_REGEX=re.compile(r'\[WPA[2]?-EAP-.+\]')
WEP_REGEX=re.compile(r'\[WEP.*\]')
def scanForNetworks():
stdout.write("Starting scan\r")
stdout.flush()
os.popen("systemctl stop hostapd && sleep 2 && systemctl start wpa_supplicant")
r = range(10,0,-1)
for i in r:
stdout.write("Scanning: %s seconds left \r" % i)
stdout.flush()
if i == 6:
os.popen("wpa_cli scan")
time.sleep(1)
data = os.popen("wpa_cli scan_results").read().split("\n")
print "\n"
network_map = {}
ssid_keys = []
while (len(data)):
line = data.pop().split("\t")
if (len(line) == 5):
ssid = line.pop()
if ssid not in ssid_keys and not ssid == "" and "\\x00" not in ssid:
tokens = line.pop()
if WPAPSK_REGEX.search(tokens):
network_map[ssid] = "WPA-PSK"
elif WPAEAP_REGEX.search(tokens):
network_map[ssid] = "WPA-EAP"
elif WEP_REGEX.search(tokens):
network_map[ssid] = "WEP"
else:
network_map[ssid] = "OPEN"
ssid_keys.append(ssid)
network_file = open(STATE_DIR + "/networks.txt", "w")
network_file.write("{\n")
for i in range(0, len(ssid_keys)):
network_file.write('\t"' + ssid_keys[i] + '": "' + network_map[ssid_keys[i]])
if i == len(ssid_keys)-1:
network_file.write('"\n')
else:
network_file.write('",\n')
network_file.write("}\n")
network_file.close()
return (ssid_keys, network_map)
def selectNetwork(ssid_keys):
i = 2
print "0 :\tRescan for networks"
print "1 :\tExit WiFi Setup"
print "2 :\tManually input a hidden SSID"
for ssid in ssid_keys:
i = i + 1
print i, ":\t", ssid
print ""
choice = -1
while 1:
try:
if i == 2:
choice = int(raw_input("\nEnter 0 to rescan for networks.\nEnter 1 to exit.\nEnter 2 to input a hidden network SSID: "))
elif i == 3:
choice = int(raw_input("\nEnter 0 to rescan for networks.\nEnter 1 to exit.\nEnter 2 to input a hidden network SSID.\nEnter 3 to choose %s: " % ssid_keys[0]))
else:
choice = int(raw_input("\nEnter 0 to rescan for networks.\nEnter 1 to exit.\nEnter 2 to input a hidden network SSID.\nEnter a number between 3 to %s to choose one of the listed network SSIDs: " % i))
except TypeError:
choice = -1
except ValueError:
choice = -1
if choice == 0:
break
elif choice == 1:
sys.exit(0)
elif choice == 2:
break
elif choice > 2 and choice <= i and verified(ssid_keys[choice-3]):
break
return choice
def configureHiddenNetwork(ssid):
print '''
0: OPEN
1: WEP
2: WPA-Personal(PSK)
3: WPA-Enterprise (EAP)
'''
while 1:
try:
security = int(raw_input("Select the type of security [0 to 3]: "))
except TypeError:
security = -1
except ValueError:
security = -1
if security == 0:
return wpa_templates.OPEN % (ssid, "scan_ssid=1")
elif security == 1:
password = ''
while len(password) != 5 and len(password) != 13:
print "Password must be either 5 or 13 characters."
password = getNetworkPassword()
return wpa_templates.WEP % (ssid, "scan_ssid=1", password)
elif security == 2:
password = ''
while len(password) < 8 or len(password) > 63:
print "Password must be between 8 and 63 characters."
password = getNetworkPassword()
return wpa_templates.WPAPSK % (ssid, "scan_ssid=1", password)
elif security == 3:
identity = getNetworkIdentity()
password = getNetworkPassword()
return wpa_templates.WPAEAP % (ssid, "scan_ssid=1", identity, password)
else:
print "Invalid input."
return network_template_open % ssid
def configureNetwork(choice,ssid_keys,network_map):
ssid = ssid_keys[choice-3]
if network_map[ssid] == "OPEN":
return wpa_templates.OPEN % (ssid, "")
elif network_map[ssid] == "WEP":
password = ''
while len(password) != 5 and len(password) != 13:
print "Password must be either 5 or 13 characters."
password = getNetworkPassword()
return wpa_templates.WEP % (ssid, "", password)
elif network_map[ssid] == "WPA-PSK":
password = ''
while len(password) < 8 or len(password) > 63:
print "Password must be between 8 and 63 characters."
password = getNetworkPassword()
return wpa_templates.WPAPSK % (ssid, "", password)
elif network_map[ssid] == "WPA-EAP":
identity = getNetworkIdentity()
password = getNetworkPassword()
return wpa_templates.WPAEAP % (ssid, "", identity, password)
else:
print noooo("the last line of startNetworkConfig")
def configureNetworkAP(changewifi):
protocol = changewifi[0]
ssid = changewifi[1]
if protocol == "OPEN":
return wpa_templates.OPEN % (ssid, "scan_ssid=1")
elif protocol == "WEP":
password = changewifi[2]
if len(password) != 5 and len(password) != 13:
print "Password must be either 5 or 13 characters."
return None
return wpa_templates.WEP % (ssid, "scan_ssid=1", password)
elif protocol == "WPA-PSK":
password = changewifi[2]
if len(password) < 8 or len(password) > 63:
print "Password must be between 8 and 63 characters."
return None
return wpa_templates.WPAPSK % (ssid, "scan_ssid=1", password)
elif protocol == "WPA-EAP":
if len(changewifi) != 4:
print "Both Identify and Password must be provided. Unable to proceed"
return
identity = changewifi[2]
password = changewifi[3]
return wpa_templates.WPAEAP % (ssid, "scan_ssid=1", identity, password)
else:
print noooo("the last line of startNetworkConfig")
def setNetwork(network_conf, ssid):
if not os.path.isfile('/etc/wpa_supplicant/wpa_supplicant.conf.original'):
subprocess.call("cp /etc/wpa_supplicant/wpa_supplicant.conf /etc/wpa_supplicant/wpa_supplicant.conf.original", shell=True)
wpa_supplicant = open('/etc/wpa_supplicant/wpa_supplicant.conf','a') #Will not take care of duplicates at the moment.
wpa_supplicant.write(network_conf)
wpa_supplicant.close();
print "Initiating connection to " + ssid + ". Please wait..."
try:
if int(subprocess.check_output("systemctl status wpa_supplicant | grep 'active (running)' | wc -l", shell=True)) == 0:
subprocess.call("systemctl stop hostapd &> /dev/null", shell=True)
subprocess.call("systemctl start wpa_supplicant &> /dev/null", shell=True)
time.sleep(10)
else:
subprocess.call("wpa_cli reconfigure &> /dev/null && sleep 2", shell=True)
network_count = int(subprocess.check_output('wpa_cli list_networks | wc -l', shell=True))
subprocess.call("wpa_cli select_network " + str(network_count - 2 - 1) + " &> /dev/null", shell=True)
time.sleep(5)
ifarray = subprocess.check_output("wpa_cli ifname", shell=True).split()
subprocess.call("udhcpc -i " + ifarray[len(ifarray)-1] + " -n &> /dev/null", shell=True)
except Exception as e:
print e
print "Sorry. Could not get an IP address."
else:
print "Attempting to enable network access, please check 'wpa_cli status' after a minute to confirm."
def checkNetwork():
i = 60
while 1:
waiting = "Connecting: %s seconds left \r" % i
stdout.write(waiting)
stdout.flush()
time.sleep(1)
address = os.popen("ifconfig | grep -A1 'wlan0' | grep 'inet'| awk -F' ' '{ print $2 }' | awk -F':' '{ print $2 }'").read().rstrip()
if not address == "":
print "Done. Please connect your laptop or PC to the same network as this device and go to " + \
text_colors.CYAN + "http://" + address + text_colors.END + " or " + text_colors.CYAN + \
"http://" + subprocess.check_output('hostname').strip() + ".local" + text_colors.END + \
" in your browser."
break
if i == 0:
print "Not connected. Something went wrong."
break
i = i-1
def connectNetwork():
network_conf = ""
ssid = ""
while 1:
reset("WiFi Connection")
(ssid_keys, network_map) = scanForNetworks()
choice = selectNetwork(ssid_keys)
#choice is validated within selectNetwork.
if choice == 2:
while 1:
ssid = raw_input("Please enter the hidden network SSID: ")
if verified(ssid):
break
network_conf = configureHiddenNetwork(ssid)
break
elif choice:
network_conf = configureNetwork(choice, ssid_keys,network_map)
ssid = ssid_keys[choice-3]
break
#print network_conf
setNetwork(network_conf, ssid)
checkNetwork()
disableOneTimeSetup(True)
def showWiFiIP():
ipstr = ''
try:
ipstr = subprocess.check_output('ifconfig wlan0 | grep \'inet addr:\'', shell=True)
except subprocess.CalledProcessError:
print >> sys.stderr, "No IP address found. Device not connected?"
return "none"
except Exception as inst:
print >> sys.stderr, type(inst)
print >> sys.stderr, inst
return "none"
startIdx = ipstr.find('inet addr:')
if (startIdx == -1):
return "none"
ipstr = ipstr[ipstr.find('inet addr:')+10:].split()[0]
return ipstr
def showWiFiMode():
modestr = ''
try:
modestr = subprocess.check_output('iwconfig wlan0 | grep Mode:', shell=True)
except subprocess.CalledProcessError:
print >> sys.stderr, "No interface found."
return "none"
except Exception as inst:
print >> sys.stderr, type(inst)
print >> sys.stderr, inst
return "none"
startIdx = modestr.find('Mode:')
if (startIdx == -1):
return "none"
modestr = modestr[modestr.find('Mode:')+5:].split()[0]
return modestr
def getCurrentFirmwareInfo():
f = open('/etc/version','r')
ver_str = f.readline()
f.close()
return ("edison-" + ver_str.split('-')[0], ver_str.split('-')[1].splitlines()[0])
def parseFirmwareInfo(firmwareinfo, build_type):
fwInfoObj = json.loads(firmwareinfo)
count = 0;
# get version number
strarray = fwInfoObj["url"].split("/")
while (count < len(strarray)):
if strarray[count] == build_type:
break
else:
count += 1
count += 1
return (strarray[count], fwInfoObj["hash"], fwInfoObj["url"])
def getLatestFirmwareInfo():
build_type = None
build_number = None
try:
build_type, build_number = getCurrentFirmwareInfo()
except Exception as inst:
print >> sys.stderr, "Could not determine firmware version information."
raise
build_url = "http://software.wearables.intel.com/getLatestFirmwareUpdateURL?product=" + build_type
request = urllib2.Request(build_url)
request.add_header("Accept", "application/json")
filehandle = urllib2.urlopen(request)
response = filehandle.read()
return parseFirmwareInfo(response, build_type)
def getSpecificFirmwareInfo(build_type, build_number):
build_url = "http://software.wearables.intel.com/getFirmwareUpdateURL?product=" + build_type + "&version=" + build_number
request = urllib2.Request(build_url)
request.add_header("Accept", "application/json")
filehandle = urllib2.urlopen(request)
response = filehandle.read()
return parseFirmwareInfo(response, build_type)
def removeFolderContents(folder_path):
try:
# remove the entire contents of the folder including files, hidden files, sub-folders, hidden sub-folders and their contents
# excluding . and .. folders which are system files to denote current directory and parent directory
ret_value = subprocess.call("rm -rf " + folder_path + "/* " + folder_path + "/.[!.]* " + folder_path + "/..?*", shell=True)
if ret_value != 0:
#this is not expected to happen ever !!
print "Could not remove previous installation files"
print "Please reboot the device to return to normal."
return -1
except Exception as inst:
print "Error: Exception while removing previous installation files."
print >> sys.stderr, type(inst)
print >> sys.stderr, inst
return -1
return 0
def removePackage():
global CURR_PACKAGE_PATH
try:
os.remove(CURR_PACKAGE_PATH)
except Exception, e:
pass
CURR_PACKAGE_PATH = ""
def signal_term_handler(signal, handler):
removePackage()
removeFolderContents("/update")
sys.exit(0)
def signal_term_handler_package_only(signal, handler):
removePackage()
sys.exit(0)
def err_downloadPackage():
print "Failed to download the new firmware. Unable to proceed."
removePackage()
def err_createDestPackage():
print "Could not create destination folder. Unable to proceed."
removePackage()
removeFolderContents("/update")
def err_unloadKernelModules():
print "Could not unload kernel modules. Unable to proceed."
print "Please reboot the device to return to normal."
removePackage()
removeFolderContents("/update")
def err_setupLoopDevice():
print "Could not setup loop device. Unable to proceed"
print "Please reboot the device to return to normal."
removePackage()
removeFolderContents("/update")
def err_mountDevice():
print "Could not perform mount operation. Unable to proceed"
print "Please reboot the device to return to normal."
removePackage()
removeFolderContents("/update")
def err_extractPackage():
print "Could not extract the package. Unable to proceed"
print "Please reboot the device to return to normal."
removePackage()
removeFolderContents("/update")
def err_umountDevice():
print "Could not perform umount operation. Unable to proceed"
print "Please reboot the device to return to normal."
removePackage()
removeFolderContents("/update")
def genSha1ForFile(file_path):
chunkSize = 524288 # 512 KB chunk
sha = hashlib.sha1()
with open(file_path, 'rb') as f:
buf = f.read(chunkSize)
while len(buf) > 0:
sha.update(buf)
buf = f.read(chunkSize)
return sha.hexdigest()
def downloadPackage(packageUrl, sha1FromServer, packagePath):
ret_value = subprocess.call("curl --connect-timeout 10 "+ "'"+packageUrl+"'" + " >"+packagePath, shell=True)
if ret_value != 0:
err_downloadPackage()
return -1
shaOfDownloadedPkg = genSha1ForFile(packagePath)
if sha1FromServer != shaOfDownloadedPkg:
print "Could not establish integrity of downloaded firmware (hash mismatch). Unable to proceed"
removePackage()
return -1
return 0
def doOTAFlash(packageUrl, sha1FromServer, packagePath, rebootInApMode):
if len(sha1FromServer) != 40:
print "Could not establish integrity of latest firmware (bad hash). Unable to proceed."
return -1
try:
signal.signal(signal.SIGTERM, signal_term_handler_package_only)
try:
ret_value = downloadPackage(packageUrl, sha1FromServer, packagePath)
if ret_value != 0:
return -1
except Exception as inst:
err_downloadPackage()
print >> sys.stderr, type(inst)
print >> sys.stderr, inst
return -1
flashFile(packagePath, rebootInApMode)
except KeyboardInterrupt:
print ""
print "Interrupted by user. Cleaning up."
removePackage()
print "Please reboot the device to return to normal."
except Exception as inst:
print "Exception occurred while upgrading. Cleaning up."
print >> sys.stderr, type(inst)
print >> sys.stderr, inst
removePackage()
print "Please reboot the device to return to normal."
def flashFile(packagePath, rebootInApMode):
if not os.path.isfile(packagePath):
print "Error: cannot upgrade. Package file " + packagePath + " does not exist."
return -1
try:
signal.signal(signal.SIGTERM, signal_term_handler)
try:
ret_value = subprocess.call("mkdir -p /update", shell=True)
if ret_value != 0:
err_createDestPackage()
return -1
except Exception as inst:
err_createDestPackage()
print >> sys.stderr, type(inst)
print >> sys.stderr, inst
return -1
#notify user that partition will be disconnected from computer if plugged
try:
ret_value_clloader = subprocess.call("systemctl stop clloader", shell=True)
ret_value_pm = subprocess.call("echo on > /sys/devices/pci0000:00/0000:00:11.0/dwc3-device.1/power/control", shell=True)
ret_value = subprocess.call("rmmod g_multi", shell=True)
if ret_value_clloader != 0 or ret_value_pm != 0 or ret_value != 0:
err_unloadKernelModules()
return -1
except Exception as inst:
err_unloadKernelModules()
print >> sys.stderr, type(inst)
print >> sys.stderr, inst
return -1
try:
ret_value = subprocess.call("losetup -o 8192 /dev/loop0 /dev/disk/by-partlabel/update", shell=True)
if ret_value != 0:
err_setupLoopDevice()
return -1
except Exception as inst:
err_setupLoopDevice()
print >> sys.stderr, type(inst)
print >> sys.stderr, inst
return -1
try:
ret_value = subprocess.call("mount /dev/loop0 /update", shell=True)
if ret_value != 0:
err_mountDevice()
return -1
except Exception as inst:
err_mountDevice()
print >> sys.stderr, type(inst)
print >> sys.stderr, inst
return -1
if os.listdir("/update") != []:
print "Removing previous installation files"
ret_value = removeFolderContents("/update")
if ret_value != 0:
print "Please reboot the device to return to normal."
removePackage()
return -1
try:
ret_value = subprocess.call("unzip -o " + packagePath + " -d /update", shell=True)
if ret_value != 0:
err_extractPackage()
return -1
except Exception as inst:
err_extractPackage()
print >> sys.stderr, type(inst)
print >> sys.stderr, inst
return -1
if rebootInApMode:
if (not os.path.isfile("/update" + HOST_AP_MODE_FILE)):
host_ap_mode_file = open("/update" + HOST_AP_MODE_FILE, "w")
host_ap_mode_file.write("Indicates that Edison will start in host AP mode next boot\n")
host_ap_mode_file.close()
print "Will start in host AP mode next boot."
try:
ret_value = subprocess.call("umount /update", shell=True)
if ret_value != 0:
err_umountDevice()
return -1
except Exception as inst:
err_umountDevice()
print >> sys.stderr, type(inst)
print >> sys.stderr, inst
return -1
print "Ready to upgrade. Rebooting device..."
time.sleep(2)
ret_value = subprocess.call("reboot ota", shell=True)
if ret_value != 0:
#this is not expected to happen ever !!
print "Could not perform reboot ota operation"
print "Please reboot the device to return to normal."
removePackage()
removeFolderContents("/update")
return -1
#notify user that update will take few minutes and that he shouldn't remove power supply
except KeyboardInterrupt:
print ""
print "Interrupted by user. Cleaning up."
removePackage()
removeFolderContents("/update")
print "Please reboot the device to return to normal."
except Exception as inst:
print "Exception occurred while upgrading. Cleaning up."
print >> sys.stderr, type(inst)
print >> sys.stderr, inst
removePackage()
removeFolderContents("/update")
print "Please reboot the device to return to normal."
def isRestartWithAPSet():
try:
ret_value = subprocess.call("mkdir -p /update", shell=True)
if ret_value != 0:
print "Could not create destination folder."
return False
except Exception as inst:
print "Could not create destination folder."
print >> sys.stderr, type(inst)
print >> sys.stderr, inst
return False
try:
ret_value = subprocess.call("losetup -o 8192 /dev/loop0 /dev/disk/by-partlabel/update", shell=True)
if ret_value != 0:
print "Could not setup loop device"
return False
except Exception as inst:
print "Could not setup loop device"
print >> sys.stderr, type(inst)
print >> sys.stderr, inst
return False
try:
ret_value = subprocess.call("mount /dev/loop0 /update", shell=True)
if ret_value != 0:
print "Could not perform mount operation."
return False
except Exception as inst:
print "Could not perform mount operation."
print >> sys.stderr, type(inst)
print >> sys.stderr, inst
return False
if os.path.isfile("/update" + HOST_AP_MODE_FILE):
ap_mode = True
else:
ap_mode = False
try:
ret_value = subprocess.call("umount /update", shell=True)
if ret_value != 0:
print "Could not perform umount operation."
return False
except Exception as inst:
print "Could not perform umount operation."
print >> sys.stderr, type(inst)
print >> sys.stderr, inst
return False
try:
ret_value = subprocess.call("rmdir /update", shell=True)
if ret_value != 0:
print "Could not delete destination folder."
return False
except Exception as inst:
print "Could not delete destination folder."
print >> sys.stderr, type(inst)
print >> sys.stderr, inst
return False
return ap_mode
def upgrade(packagePath, rebootInApMode):
curr = None
build_type = None
try:
build_type, curr = getCurrentFirmwareInfo()
except Exception as inst:
print >> sys.stderr, "Could not determine firmware version information."
raise
try:
latest, sha1, url = getLatestFirmwareInfo()
except Exception as inst:
print >> sys.stderr, "Could not retrieve latest firmware version information."
raise
if int(latest) > int(curr):
doOTAFlash(url, sha1, packagePath, rebootInApMode)
else:
print "The latest version is already installed."
def full():
reset("Device Password")
setEdisonPassword()
reset("Device Name")
setEdisonHostname()
if decideToConnect():
connectNetwork()
else:
print "Done.\n"
def getSSID():
return subprocess.check_output("grep -o '^ssid=.*' /etc/hostapd/hostapd.conf | awk -F'=' '{print $2}'", shell=True).strip()
def saveDefaultSSID():
if not os.path.isfile(STATE_DIR + "/default-ssid.txt"):
curr_ssid = getSSID()
default_ssid_file = open(STATE_DIR + "/default-ssid.txt", "w")
default_ssid_file.write(curr_ssid + "\n")
default_ssid_file.close()
def getDefaultSSID():
saveDefaultSSID()
default_ssid_file = open(STATE_DIR + "/default-ssid.txt", "r")
curr_ssid = default_ssid_file.readline()
default_ssid_file.close()
return curr_ssid.strip()
def enableOneTimeSetup(persist):
subprocess.call("systemctl restart blink-led", shell=True)
hostname = subprocess.check_output('hostname').strip()
print "Scanning and saving WiFi networks..."
scanForNetworks()
subprocess.call("systemctl stop wpa_supplicant", shell=True)
print "Restarting WiFi access point. Please wait..."
print ""
if persist:
subprocess.call("systemctl disable wpa_supplicant &> /dev/null", shell=True)
subprocess.call("systemctl enable hostapd &> /dev/null", shell=True)
subprocess.call("systemctl enable blink-led &> /dev/null", shell=True)
if int(subprocess.check_output("systemctl status hostapd | grep 'active (running)' | wc -l", shell=True)) == 0:
subprocess.call("systemctl start hostapd &> /dev/null", shell=True)
myssid = getSSID()
print "From your PC or laptop, connect to the", "'" + myssid + "' network "
print "and visit", "'" + hostname + ".local' in the browser"
def disableOneTimeSetup(persist):
subprocess.call("systemctl stop blink-led &> /dev/null", shell=True)
subprocess.call("systemctl stop hostapd &> /dev/null", shell=True)
try:
os.remove(STATE_DIR + "/networks.txt")
except Exception as inst:
pass
if persist:
subprocess.call("systemctl enable wpa_supplicant &> /dev/null", shell=True)
subprocess.call("systemctl disable hostapd &> /dev/null", shell=True)
subprocess.call("systemctl disable blink-led &> /dev/null", shell=True)
if int(subprocess.check_output("systemctl status wpa_supplicant | grep 'active (running)' | wc -l", shell=True)) == 0:
subprocess.call("systemctl start wpa_supplicant &> /dev/null", shell=True)
def toggleOneTimeSetup(persist):
if showWiFiMode() == "Master":
disableOneTimeSetup(persist)
else:
enableOneTimeSetup(persist)
def showNames():
hostname = subprocess.check_output('hostname', shell=True).strip()
ssid = getSSID()
default_ssid = getDefaultSSID()
print '{"hostname": "' + hostname + '", "ssid": "' + ssid + '", "default_ssid": "' + default_ssid + '"}'
def configureNetworkSilently(ssid,network_map, password):
if network_map[ssid] == "OPEN":
return wpa_templates.OPEN % (ssid, "")
elif network_map[ssid] == "WEP":
if len(password) != 5 and len(password) != 13:
raise Exception("Password must be either 5 or 13 characters.")
return wpa_templates.WEP % (ssid, "", password)
elif network_map[ssid] == "WPA-PSK":
if len(password) < 8 or len(password) > 63:
raise Exception("Password must be between 8 and 63 characters.")
return wpa_templates.WPAPSK % (ssid, "", password)
#elif network_map[ssid] == "WPA-EAP":
# identity = getNetworkIdentity()
# password = getNetworkPassword()
# return wpa_templates.WPAEAP % (ssid, "", identity, password)
else:
print noooo("Unknown network authentication type: %s" % network_map[ssid])
def goodbye():
time.sleep(2.0)
print '\n\nSee you,',
stdout.flush()
time.sleep(1.5)
print 'space cowboy...\n\n'
stdout.flush()
time.sleep(1.0)
def enterAPMode():
mode = showWiFiMode()
if mode.strip().lower() == 'master':
print "You are already in AP mode. You can use configure_edison --stationMode to join a wireless network."
return
ssid = getSSID();
print '---------------------------------------------------------------------'
print " The system will now switch to AP mode."
print ' After pressing <enter> you will lose this connection'
print " and have to reconnect to the '%s' network. " % ssid
print ' Your terminal may hang. This is normal. Do not panic.'
print '---------------------------------------------------------------------'
confirm = ''
while confirm not in list('yYnN'):
confirm = raw_input('Are you sure you want to switch to AP mode? (y/n) ')
if confirm in list('nN'):
return
goodbye()
os.popen("systemctl stop wpa_supplicant && sleep 2 && systemctl start hostapd && sleep 2 && systemctl restart fabmo")
def enterStationMode():
mode = showWiFiMode()
if mode.strip().lower() != 'master':
print "You are not in AP mode. Use configure_edison --wifi to change networks. It's much nicer."
return
while True:
ssid = ''
while ssid == '':
ssid = raw_input("Enter the wireless network SSID: ")
confirm = ''
while confirm not in list('YyNn'):
confirm = raw_input("The SSID you have entered is '%s' - is this correct? (y/n) " % ssid)
if confirm in 'Yy':
break
while True:
password = ''
while password == '':
password = raw_input("Enter the wireless network passphrase: ")
confirm = ''
while confirm not in list('YyNn'):
confirm = raw_input("The passphrase you have entered is '%s' - is this correct? (y/n) " % password)
if confirm in 'Yy':
break
print '--------------------------------------------------------'
print " The system will now join the '%s' network." % ssid
print ' After pressing <enter> you will lose this connection, '
print ' and will have to reconnect on the specified network.'
print ' Your terminal may hang. This is normal. Do not panic.'
print '--------------------------------------------------------'
raw_input('')
goodbye()
(ssid_keys, network_map) = scanForNetworks()
if ssid not in ssid_keys:
raise Exception("No such SSID in the site survey: %s" % ssid)
network_conf = configureNetworkSilently(ssid, network_map, password)
setNetwork(network_conf, ssid)
checkNetwork()
disableOneTimeSetup(True)
os.popen("systemctl restart fabmo")
def main():
global CURR_PACKAGE_PATH
parser = argparse.ArgumentParser(prog='configure_edison')
parser.add_argument('--restartWithAP', dest='restartwithap', help=argparse.SUPPRESS, action='store_true', default=False)
parser.add_argument('--persist', dest='persist', help=argparse.SUPPRESS, action='store_true', default=False)
root_group = parser.add_mutually_exclusive_group()
group_interactive = root_group.add_mutually_exclusive_group()
group_interactive.add_argument('--setup', dest='setup', help='Goes through changing the device name, password, and wifi options', action='store_true', default=False)
group_interactive.add_argument('--name', dest='name', help='Changes the device name', action='store_true', default=False)
group_interactive.add_argument('--password', dest='password', help='Changes the device password', action='store_true', default=False)
group_interactive.add_argument('--wifi', dest='wifi', help='Changes the wifi options', action='store_true', default=False)
group_non_interactive = root_group.add_mutually_exclusive_group()
group_non_interactive.add_argument('--isRestartWithAPSet', dest='isrestartwithapset', help=argparse.SUPPRESS, action='store_true', default=False)
group_non_interactive.add_argument('--showWiFiIP', dest='showwifiip', help='IP address associated with the wireless interface', action='store_true', default=False)
group_non_interactive.add_argument('--showWiFiMode', dest='showwifimode', help='Show current mode for the wireless interface', action='store_true', default=False)
group_non_interactive.add_argument('--version', dest='version', help='Gets the current firmware version', action='store_true', default=False)
group_non_interactive.add_argument('--latest-version', dest='latestversion', help='Gets the latest firmware version', action='store_true', default=False)
group_non_interactive.add_argument('--disableOneTimeSetup', dest='disableonetimesetup', help='Disable one-time setup with WiFi access point and enable WiFi client mode \
Append --persist to retain this setting after reboot', action='store_true', default=False)
group_non_interactive.add_argument('--enableOneTimeSetup', dest='enableonetimesetup', help='Enable one-time setup with WiFi access point and disable WiFi client mode. \
Append --persist to retain this setting after reboot', action='store_true', default=False)
group_non_interactive.add_argument('--toggleOneTimeSetup', dest='toggleonetimesetup', help='Switch between one-time setup with WiFi access point and WiFi client mode, and visa-versa. \
Append --persist to retain this setting after reboot', action='store_true', default=False)
group_non_interactive.add_argument('--upgrade', dest='upgrade', help='Downloads the latest firmware. Append --restartWithAP to reboot in WiFi access point mode after flashing', \
action='store_true', default=False)
group_non_interactive.add_argument('--flash', metavar=('<version>','<release name>'), nargs='+', dest='otaflash', help='Downloads and flashes an image \
Append --restartWithAP to reboot in WiFi access point mode after flashing')
group_non_interactive.add_argument('--flashFile', metavar=('<image-file>'), nargs=1, dest='flashfile', help='Flashes the given image (.zip). \
Append --restartWithAP to reboot WiFi access point mode after flashing')
group_non_interactive.add_argument('--changePassword', metavar='password', dest='changepassword', const='', help=argparse.SUPPRESS, nargs='?')
group_non_interactive.add_argument('--changeName', metavar='name', dest='changename', help=argparse.SUPPRESS, nargs=1)
group_non_interactive.add_argument('--changeWiFi', metavar='securityType SSID [Identity | password]', dest='changewifi', help=argparse.SUPPRESS, nargs='+')
group_non_interactive.add_argument('--showNames', dest='shownames', help='Show device name and SSID', action='store_true', default=False)
group_non_interactive.add_argument('--stationMode', dest='station_mode', help='Put the wifi into station mode with the specified network', action='store_true', default=False)
group_non_interactive.add_argument('--APMode', dest='ap_mode', help='Put the wifi into AP mode with the network', action='store_true', default=False)
if len(sys.argv)==1:
parser.print_help()
sys.exit(1)
args = parser.parse_args()
if args.station_mode:
enterStationMode()
if args.ap_mode:
enterAPMode()
if args.name:
reset("Device Name")
setEdisonHostname()
if args.password:
reset("Device Password")
setEdisonPassword()
if args.wifi:
connectNetwork()
if not os.path.isfile(STATE_DIR + "/password-setup.done"):
print "Warning: SSH is not yet enabled on the wireless interface. To enable SSH access to this device via wireless run configure_edison --password first."
if args.setup:
full()
if args.version:
try:
build_type, version = getCurrentFirmwareInfo()
print version
except Exception as inst:
print >> sys.stderr, "Could not determine firmware version information. Quitting."
print "none"
if args.latestversion:
try:
latestversion, sha1, url = getLatestFirmwareInfo()
print latestversion
except Exception as inst:
print >> sys.stderr, "Could not retrieve latest firmware version information. Quitting."
print "none"
if args.upgrade:
try:
CURR_PACKAGE_PATH = DESTINATION_PATH + "package.zip"
upgrade(CURR_PACKAGE_PATH, args.restartwithap)
except Exception as inst:
print "Could not upgrade device firmware. Quitting."
print >> sys.stderr, type(inst)
print >> sys.stderr, inst
return -1
if args.shownames:
showNames()
if args.isrestartwithapset:
print isRestartWithAPSet()
if args.otaflash != None:
version = None
sha1 = None
url = None
try:
if len(args.otaflash) == 1:
try:
build_type, build_number = getCurrentFirmwareInfo()
version, sha1, url = getSpecificFirmwareInfo(build_type, args.otaflash[0])
except Exception as inst:
print >> sys.stderr, "Could not determine firmware verison information."
raise
elif len(args.otaflash) == 2:
version, sha1, url = getSpecificFirmwareInfo(args.otaflash[1], args.otaflash[0])
else:
print "error: usage: configure_edison --flash <version> [ <release name> ]"
except Exception as inst:
print "Could not retrieve required firmware information. Quitting."
return -1
CURR_PACKAGE_PATH = DESTINATION_PATH + "package.zip"
try:
doOTAFlash(url, sha1, CURR_PACKAGE_PATH, args.restartwithap)
except Exception as inst:
print >> sys.stderr, type(inst)
print >> sys.stderr, inst
print "Could not flash device. Quitting."
return -1
if args.flashfile != None:
CURR_PACKAGE_PATH = args.flashfile[0]
flashFile(CURR_PACKAGE_PATH, args.restartwithap)
if args.changepassword != None:
changePassword(args.changepassword)
if args.changename != None:
changeName(args.changename[0])
if args.showwifiip:
print showWiFiIP()
if args.showwifimode:
print showWiFiMode()
if args.enableonetimesetup:
enableOneTimeSetup(args.persist)
if args.disableonetimesetup:
disableOneTimeSetup(args.persist)
if args.toggleonetimesetup:
toggleOneTimeSetup(args.persist)
if args.changewifi != None:
network_conf = configureNetworkAP(args.changewifi)
if network_conf != None:
setNetwork(network_conf, args.changewifi[1])
#print 'restartwithap = ',args.restartwithap
#print 'persist = ',args.persist
#print 'setup = ',args.setup
#print 'name = ',args.name
#print 'password = ',args.password
#print 'wifi = ',args.wifi
#print 'showwifiip = ',args.showwifiip
#print 'version = ',args.version
#print 'latestversion = ',args.latestversion
#print 'upgrade = ',args.upgrade
#print 'disableonetimesetup = ',args.disableonetimesetup
#print 'enableonetimesetup = ',args.enableonetimesetup
#print 'otaflash = ',args.otaflash
#print 'changepassword = ',args.changepassword
#print 'changename = ',args.changename
if __name__ == "__main__":
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment