# main.py
# Version 2.18 - Feb 10, 2019
from machine import Pin, deepsleep, ADC, reset
import random
import time
import utime
import uio
import os
import gc
from globals import __np
from utils import I2C_com
from tcpcom import *
gc.collect()
html = """
Oxocard Setup
Welcome to the Oxocard
Please fill in the form and press OK
(Use only A..Z, a..z, 0..9, and the period .)
%s
"""
_defaultPort = 80
_cfgFile = 'oxoconfig.py'
_serverRoot = '/oxocard/users/'
_cfgDict = {}
_pixColor = 255
_setupBlink = True
_downloadError = False
_a = range(48, 58)
_b = range(65, 91)
_c = range(97, 123)
def _validate(word):
for c in word:
if not (ord(c) in _a or ord(c) in _b or ord(c) in _c or c == '.'):
return False
return True
def _onRequest(clientIP, filename, params):
global _pixColor, _setupBlink
confirmation = ""
if filename != '/':
return ""
cfgDict = _getCfgDict()
if not cfgDict: # file not found
ssid = ""
passphrase = ""
host = ""
pairingcode = ""
else:
# print("config:", cfgDict)
try:
ssid = cfgDict['ssid']
passphrase = cfgDict['passphrase']
host = cfgDict['host']
pairingcode = cfgDict['pairingcode']
except KeyError as e:
print("KeyError exception in cfgDict", str(e))
ssid = ""
passphrase = ""
host = ""
pairingcode = ""
if len(params) == 4: # got submit
ssid = params[0][1].strip()
passphrase = params[1][1].strip()
host = params[2][1].strip()
pairingcode = params[3][1].strip()
if ssid == "" or host == "":
confirmation = "Illegal empty field!"
elif not _validate(ssid):
confirmation = "Illegal character in ssid"
elif not _validate(host):
confirmation = "Illegal character in host"
elif pairingcode == "":
confirmation = "Create a pairing code!"
else:
with open(_cfgFile, 'wb') as f:
f.write("ssid = " + ssid + "\n")
f.write("passphrase = " + passphrase + "\n")
f.write("host = " + host + "\n")
f.write("pairingcode = " + pairingcode + "\n")
_pixColor = 150 << 8
_setupBlink = False
confirmation = "Setup done. Thank you!"
return html % (ssid, passphrase, host, pairingcode, confirmation)
def _getCfgDict():
cfgDict = {}
try:
with open(_cfgFile) as f:
for line in f:
if "=" in line:
key, value = line.split("=")
cfgDict[key.strip()] = value.strip()
except:
pass
return cfgDict
def checkOxocard():
try:
# Check if oxocard is available
i2c_address = 0x28 # LIS3DE Accelerometer
i2c = I2C_com(i2c_address, scl = Pin(22), sda = Pin(21))
WHO_AM_I = 0x0F
return i2c.readFromMem(WHO_AM_I, 1) == b'3'
except:
return False
def checkOxoboard():
try:
# Check if oxoboard is available
i2c_address = 0x6A # LSM9D1 Accelerometer
i2c = I2C_com(i2c_address, scl = Pin(22), sda = Pin(21))
WHO_AM_I = 0x0F
return i2c.readFromMem(WHO_AM_I, 1) == b'h'
except:
return False
def _blink():
__np.set(1, 255 << 8)
time.sleep(0.3)
__np.set(1, 0)
def _set(li):
for n in li:
__np.set(n, _pixColor)
def _showSetup():
li = ( 10, 11, 12, 13, 14, 15,
17, 24,
27, 28, 29, 30,
34, 39,
44, 45,
52, 53)
_set(li)
time.sleep(0.5)
if _setupBlink:
__np.fill(0)
time.sleep(0.5)
def _showDownload():
global _pixColor
li = ( 19, 22,
26, 31 ,
33, 34, 35, 36, 37, 38, 39, 40,
42, 47,
51, 54)
_pixColor = 255
_set(li)
def _showDownloadFail():
global _pixColor
li = (35, 36, 37, 38)
_pixColor = 150 << 16
_set(li)
def _toPix(x, y):
return 8 * y + x + 1
def _writeFile(text, dst):
with uio.open(dst, 'wb') as f:
for c in text:
f.write(c)
def _showPairingCode():
_cfgDict = _getCfgDict()
if _cfgDict:
code = _cfgDict['pairingcode']
from oxocard import *
while True:
if code == "":
print("Pairing code not defined")
bigTextScroll(" undefined ", YELLOW, BLACK, 6)
else:
print("Pairing code:", code)
bigTextScroll(" " + code + " ", YELLOW, BLACK, 4)
time.sleep(2)
def _download():
global _downloadError
Pin(15, Pin.OUT).value(0) # neopix on
_showDownload()
_cfgDict = _getCfgDict()
if not _cfgDict: # empty
_downloadError = True
return
host = _cfgDict['host']
port = _defaultPort
ssid = _cfgDict['ssid']
if ssid == "":
from oxocard import *
print("No config data defined yet.")
smallTextScroll("no setup", RED)
_downloadError = True
return
passphrase = _cfgDict['passphrase']
if not Wlan.connect(ssid, passphrase, verbose = True):
from oxocard import *
print("Connection to AP failed. ssid:", ssid, "passphrase:", passphrase)
smallTextScroll("no AP", RED)
_downloadError = True
return
client = HTTPClient()
rc = client.connect(host, port)
if not rc:
from oxocard import *
print("Connection to Host failed. host:", host)
smallTextScroll("no HOST", RED)
_downloadError = True
return
request = _serverRoot + _cfgDict['pairingcode'] + "/appmain.py"
print("request:", request)
response = client.sendGetRequest(request)
client.closeConnection()
print("response:", response)
if response == None or response == "":
print("No response from host:", host)
_showDownloadFail()
_downloadError = True
return
index = response.find('HTTP/1.1 404 Not Found')
if index != -1:
print("File not found: " + request)
_showDownloadFail()
_downloadError = True
return
index = response.find("\r\n\r\n")
if index == -1:
_downloadError = True
return
prog = response[index + 4:]
_writeFile(prog, "appmain.py")
reset()
# R1 & R2 & R3 -> setup
if Pin(13, Pin.IN, Pin.PULL_DOWN).value() == 1 and Pin(14, Pin.IN, Pin.PULL_DOWN).value() == 1 and Pin(27, Pin.IN, Pin.PULL_DOWN).value() == 1:
Pin(15, Pin.OUT).value(0) # neopix on
Wlan.activateAP(ssid = "oxocard", password = "")
HTTPServer(requestHandler = _onRequest)
while True:
_showSetup()
# R1 & R3-> show pairing code
if Pin(14, Pin.IN, Pin.PULL_DOWN).value() == 1 and Pin(27, Pin.IN, Pin.PULL_DOWN).value() == 1:
Pin(15, Pin.OUT).value(0) # neopix on
_showPairingCode()
# R2 & R3-> deepsleep
if Pin(13, Pin.IN, Pin.PULL_DOWN).value() == 1 and Pin(27, Pin.IN, Pin.PULL_DOWN).value() == 1:
Pin(15, Pin.OUT).value(0) # neopix on
print("deep sleep")
for k in [250, 100, 50, 20, 10, 5, 1, 0]:
for i in range(8):
__np.set(_toPix(i, i), k << 16, update = False)
__np.set(_toPix(7 - i, i), k << 16, update = False)
__np.show()
time.sleep(0.5)
Pin(2, Pin.OUT).value(0) # audio ampli off
Pin(15, Pin.OUT).value(1) # neopix off
deepsleep()
# R1 & R2-> download
if Pin(14, Pin.IN, Pin.PULL_DOWN).value() == 1 and Pin(13, Pin.IN, Pin.PULL_DOWN).value() == 1:
_showDownload()
_download()
def fileCopy(src, dst):
try:
with uio.open(src, 'rb') as f1:
with uio.open(dst, 'wb') as f2:
f2.write(f1.read())
except:
pass
def roll():
for i in range(2, -1, -1):
fileCopy('appmain' + str(i) + '.py', 'appmain' + str(i + 1) + '.py')
fileCopy('appmain.py', 'appmain0.py')
os.remove('appmain.py')
def _runapp():
if device == "oxocard":
dir = os.listdir()
if 'appmain.py' in dir: # new download
roll()
file = "appmain0.py"
if Pin(27, Pin.IN, Pin.PULL_DOWN).value() == 1:
file = "appmain1.py"
elif Pin(13, Pin.IN, Pin.PULL_DOWN).value() == 1:
file = "appmain2.py"
elif Pin(14, Pin.IN, Pin.PULL_DOWN).value() == 1:
file = "appmain3.py"
_blink()
dir = os.listdir()
if file not in dir:
print("Failed to find " + file + " to execute")
return
print("Running " + file)
execfile(file)
elif device == "oxoboard" or device == "unknown":
_blink()
if '$$$flash$$$.py' in os.listdir():
print("flash tag detected")
os.remove("$$$flash$$$.py")
os.remove("appmain.py")
else:
file = "appmain.py"
if file in os.listdir():
print("Running " + file)
execfile(file)
else:
print("Can't find " + file + " to execute.")
if checkOxocard():
device = "oxocard"
elif checkOxoboard():
device = "oxoboard"
else:
device = "unknown"
print("Device detected: " + device)
# random seed to fix bug in random module
# this is because time.time() returns 1 after reset
random.seed(utime.ticks_cpu())
if device == "oxocard":
Pin(2, Pin.OUT).value(1) # audio ampli on
Pin(15, Pin.OUT).value(0) # neopix on
elif device == "oxoboard":
Pin(15, Pin.OUT).value(0) # neopix on
if not _downloadError:
_runapp()