Add config capabilities

This commit is contained in:
sqozz 2018-11-17 23:23:33 +01:00
parent f4d951a088
commit ee2e55e174
3 changed files with 88 additions and 18 deletions

25
config.json Normal file
View file

@ -0,0 +1,25 @@
{
"devices" : {
"84:F3:EB:B4:4D:A7" : {
"role" : "ota_test",
"version" : "latest"
},
"AA:BB:CC:DD:EE:FF" : {
"role" : "non_existant",
"version" : "latest"
}
},
"firmwares" : {
"ota_test" : {
"latest" : {
"filename" : "latest.bin",
"hash" : "d41d8cd98f00b204e9800998ecf8427e"
},
"backup" : {
"filename" : "backup.bin",
"hash" : ""
}
}
}
}

View file

View file

@ -1,34 +1,72 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
import hashlib
from bottle import route, run, request, HTTPResponse, response from bottle import route, run, request, HTTPResponse, response
import hashlib
import json
import pdb import pdb
import os
updated = True updated = True
filename = "firmware.bin" filename = "firmware.bin"
@route('/update') @route('/update')
def update(): def updateRequest():
#for header in request.headers.keys(): #for header in request.headers.keys():
# print("{}: {}".format(header, request.headers.get(header, ""))) # print("{}: {}".format(header, request.headers.get(header, "")))
requestor_mac = request.headers.get("X-Esp8266-Sta-Mac") if not "X-Esp8266-Sta-Mac" in request.headers:
running_fw_md5 = request.headers.get("X-Esp8266-Sketch-Md5", "") return "Hello fellow friend! Looking for updates?"
print("Update request from {} with fw {}".format(requestor_mac, running_fw_md5))
available_fw_md5 = md5(filename)
print("Lates firmware available is {} - ".format(available_fw_md5), end="") readConfig()
if available_fw_md5 != running_fw_md5: global config
print("Differs, updating…") requestor_mac = request.headers.get("X-Esp8266-Sta-Mac", "")
response.set_header('Content-Type', 'application/octet-stream') running_fw_md5 = request.headers.get("X-Esp8266-Sketch-Md5", "")
response.set_header('Content-Disposition', ' attachment; filename={}'.format(filename)) role, version, fw_filename, fw_hash = getProperties(config, requestor_mac)
with open(filename, "rb") as firmware: if role == "" and version == "" and fw_filename == "" and fw_hash == "":
fw = firmware.read() print("No configuration for {} found. Serving 304 - No Firmware".format(requestor_mac))
response.set_header('Content-Length', '{}'.format(len(fw))) return nofirmware()
response.set_header('X-MD5', available_fw_md5)
return fw print("Update request from {} with role {} (running fw hash: {}).".format(requestor_mac, role, running_fw_md5))
else: fw_path = os.path.join("firmwares", role, version, fw_filename)
try:
latest_fw_md5 = md5(fw_path)
except FileNotFoundError:
print("Configured firmware not found at {}".format(fw_path))
return nofirmware()
if latest_fw_md5 != fw_hash:
print("Configured hash ({}) does not match calculeted one ({})".format(fw_hash, latest_fw_md5))
return nofirmware()
print("Latest firmware for role \"{}\" is \"{}\" ({}) - ".format(role, fw_filename, latest_fw_md5), end="")
if latest_fw_md5 == running_fw_md5:
print("Same, skipping…") print("Same, skipping…")
return HTTPResponse(status=304, body="") return nofirmware()
print("Differs, updating…")
response.set_header('Content-Type', 'application/octet-stream')
response.set_header('Content-Disposition', ' attachment; filename={}'.format(filename))
with open(fw_path, "rb") as fw:
firmware = fw.read()
response.set_header('Content-Length', '{}'.format(len(firmware)))
response.set_header('X-MD5', latest_fw_md5)
print("Serving {} bytes to {} with role {}".format(len(firmware), requestor_mac, role))
return firmware
def getProperties(config, mac):
configured_devices = config.get("devices", {}).keys()
devices = config.get("devices", {})
firmwares = config.get("firmwares", {})
match = devices.get(mac, {"role":"", "version":""})
role = match.get("role", "")
version = match.get("version", "")
role_firmwares = firmwares.get(role, {})
firmware = role_firmwares.get(version, {})
firmware_filename = firmware.get("filename", "")
firmware_hash = firmware.get("hash", "")
return role, version, firmware_filename, firmware_hash
def nofirmware():
return HTTPResponse(status=304, body="")
def md5(fname): def md5(fname):
hash_md5 = hashlib.md5() hash_md5 = hashlib.md5()
@ -37,4 +75,11 @@ def md5(fname):
hash_md5.update(chunk) hash_md5.update(chunk)
return hash_md5.hexdigest() return hash_md5.hexdigest()
def readConfig(config_name="config.json"):
global config
config = ""
with open(config_name, "r") as conf:
config = json.loads(conf.read())
readConfig()
run(host='localhost', port=8080, debug=True) run(host='localhost', port=8080, debug=True)