1
0
mirror of https://github.com/mbirth/tcl_ota_check.git synced 2024-09-19 22:33:25 +01:00

Use new Device classes in ALL the features!

This commit is contained in:
Markus Birth 2018-02-07 01:49:44 +01:00
parent b687c4185f
commit 0b7ae53861
Signed by: mbirth
GPG Key ID: A9928D7A098C3A9A
10 changed files with 78 additions and 139 deletions

View File

@ -11,12 +11,11 @@ import sys
import tcllib import tcllib
import tcllib.argparser import tcllib.argparser
from tcllib.devices import Device
from tcllib.xmltools import pretty_xml from tcllib.xmltools import pretty_xml
fc = tcllib.FotaCheck() fc = tcllib.FotaCheck()
fc.serid = "3531510"
#fc.osvs = "7.1.1"
dpdesc = """ dpdesc = """
Checks for the latest FULL updates for the specified PRD number or for an OTA from the Checks for the latest FULL updates for the specified PRD number or for an OTA from the
@ -32,48 +31,45 @@ dp.add_argument("--rawmode", help="override --mode with raw value (2=OTA, 4=FULL
dp.add_argument("--rawcltp", help="override --type with raw value (10=MOBILE, 2010=DESKTOP)", metavar="CLTP") dp.add_argument("--rawcltp", help="override --type with raw value (10=MOBILE, 2010=DESKTOP)", metavar="CLTP")
args = dp.parse_args(sys.argv[1:]) args = dp.parse_args(sys.argv[1:])
dev = Device(args.prd[0], args.fvver)
dev.imei = "3531510"
def sel_mode(txtmode, autoval, rawval): def sel_mode(txtmode, autoval, rawval):
"""Handle custom mode.""" """Handle custom mode."""
if rawval: if rawval:
enum = tcllib.default_enum("MODE", {"RAW": rawval}) return rawval
return enum.RAW
if txtmode == "auto": if txtmode == "auto":
return autoval return autoval
elif txtmode == "ota": elif txtmode == "ota":
return fc.MODE.OTA return dev.MODE_STATES["OTA"]
return fc.MODE.FULL return dev.MODE_STATES["FULL"]
def sel_cltp(txtmode, autoval, rawval): def sel_cltp(txtmode, autoval, rawval):
"""Handle custom CLTP.""" """Handle custom CLTP."""
if rawval: if rawval:
enum = tcllib.default_enum("CLTP", {"RAW": rawval}) return rawval
return enum.RAW
if txtmode == "auto": if txtmode == "auto":
return autoval return autoval
elif txtmode == "desktop": elif txtmode == "desktop":
return fc.CLTP.DESKTOP return dev.CLTP_STATES["DESKTOP"]
return fc.CLTP.MOBILE return dev.CLTP_STATES["MOBILE"]
if args.imei: if args.imei:
print("Use specified IMEI: {}".format(args.imei)) print("Use specified IMEI: {}".format(args.imei))
fc.serid = args.imei dev.imei = args.imei
fc.curef = args.prd[0]
fc.fv = args.fvver
if args.fvver == "AAA000": if args.fvver == "AAA000":
fc.mode = sel_mode(args.mode, fc.MODE.FULL, args.rawmode) dev.mode = sel_mode(args.mode, dev.MODE_STATES["FULL"], args.rawmode)
fc.cltp = sel_cltp(args.type, fc.CLTP.DESKTOP, args.rawcltp) dev.cltp = sel_cltp(args.type, dev.CLTP_STATES["DESKTOP"], args.rawcltp)
else: else:
fc.mode = sel_mode(args.mode, fc.MODE.OTA, args.rawmode) dev.mode = sel_mode(args.mode, dev.MODE_STATES["OTA"], args.rawmode)
fc.cltp = sel_cltp(args.type, fc.CLTP.MOBILE, args.rawcltp) dev.cltp = sel_cltp(args.type, dev.CLTP_STATES["MOBILE"], args.rawcltp)
print("Mode: {}".format(fc.mode.value)) print("Mode: {}".format(dev.mode))
print("CLTP: {}".format(fc.cltp.value)) print("CLTP: {}".format(dev.cltp))
check_xml = fc.do_check() fc.reset_session(dev)
check_xml = fc.do_check(dev)
print(pretty_xml(check_xml)) print(pretty_xml(check_xml))
curef, fv, tv, fw_id, fileid, fn, fsize, fhash = fc.parse_check(check_xml) curef, fv, tv, fw_id, fileid, fn, fsize, fhash = fc.parse_check(check_xml)
@ -92,7 +88,7 @@ for s in slaves:
for s in s3_slaves: for s in s3_slaves:
print("http://{}{}".format(s, s3_fileurl)) print("http://{}{}".format(s, s3_fileurl))
if fc.mode == fc.MODE.FULL: if dev.mode == dev.MODE_STATES["FULL"]:
header = fc.do_encrypt_header(random.choice(encslaves), fileurl) header = fc.do_encrypt_header(random.choice(encslaves), fileurl)
headname = "header_{}.bin".format(tv) headname = "header_{}.bin".format(tv)
headdir = "headers" headdir = "headers"

View File

@ -16,9 +16,7 @@ from tcllib.devices import DesktopDevice
dev = DesktopDevice() dev = DesktopDevice()
fc = tcllib.FotaCheck() fc = tcllib.FotaCheck()
fc.mode = fc.MODE.FULL # still needed to set User-Agent
dpdesc = """ dpdesc = """
Checks for the latest FULL updates for all PRD numbers or only for Checks for the latest FULL updates for all PRD numbers or only for
@ -40,8 +38,8 @@ for prd, variant in prds.items():
lastver = variant["last_full"] lastver = variant["last_full"]
if prdcheck in prd: if prdcheck in prd:
try: try:
fc.reset_session()
dev.curef = prd dev.curef = prd
fc.reset_session(dev)
check_xml = fc.do_check(dev, max_tries=20) check_xml = fc.do_check(dev, max_tries=20)
curef, fv, tv, fw_id, fileid, fn, fsize, fhash = fc.parse_check(check_xml) curef, fv, tv, fw_id, fileid, fn, fsize, fhash = fc.parse_check(check_xml)
txt_tv = tv txt_tv = tv

View File

@ -16,9 +16,7 @@ from tcllib.devices import MobileDevice
dev = MobileDevice() dev = MobileDevice()
fc = tcllib.FotaCheck() fc = tcllib.FotaCheck()
fc.mode = fc.MODE.OTA # still needed to set User-Agent
dpdesc = """ dpdesc = """
Checks for the latest OTA updates for all PRD numbers or only for the PRD specified Checks for the latest OTA updates for all PRD numbers or only for the PRD specified
@ -49,9 +47,9 @@ for prd, variant in prds.items():
lastver = args.forcever lastver = args.forcever
if prdcheck in prd: if prdcheck in prd:
try: try:
fc.reset_session()
dev.curef = prd dev.curef = prd
dev.fwver = lastver dev.fwver = lastver
fc.reset_session(dev)
check_xml = fc.do_check(dev, max_tries=20) check_xml = fc.do_check(dev, max_tries=20)
curef, fv, tv, fw_id, fileid, fn, fsize, fhash = fc.parse_check(check_xml) curef, fv, tv, fw_id, fileid, fn, fsize, fhash = fc.parse_check(check_xml)
versioninfo = ansi.YELLOW_DARK + fv + ansi.RESET + "" + ansi.YELLOW + tv + ansi.RESET + " (FULL: {})".format(variant["last_full"]) versioninfo = ansi.YELLOW_DARK + fv + ansi.RESET + "" + ansi.YELLOW + tv + ansi.RESET + " (FULL: {})".format(variant["last_full"])

View File

@ -13,16 +13,11 @@ from requests.exceptions import RequestException, Timeout
import tcllib import tcllib
import tcllib.argparser import tcllib.argparser
from tcllib import ansi, devlist from tcllib import ansi, devlist
from tcllib.devices import DesktopDevice, MobileDevice
dev = DesktopDevice()
fc = tcllib.FotaCheck() fc = tcllib.FotaCheck()
fc.serid = "3531510"
fc.fv = "AAA000"
fc.mode = fc.MODE.FULL
# CLTP = 10 (only show actual updates or HTTP 206) / 2010 (always show latest version for MODE.FULL)
#fc.cltp = fc.CLTP.MOBILE
fc.cltp = fc.CLTP.DESKTOP
dpdesc = """ dpdesc = """
Finds new PRD numbers for all known variants, or specified variants with tocheck. Scan range Finds new PRD numbers for all known variants, or specified variants with tocheck. Scan range
@ -74,9 +69,9 @@ for center in sorted(prddict.keys()):
print("Checking {} ({}/{})".format(curef, done_count, total_count)) print("Checking {} ({}/{})".format(curef, done_count, total_count))
print(ansi.UP_DEL, end="") print(ansi.UP_DEL, end="")
try: try:
fc.reset_session() dev.curef = curef
fc.curef = curef fc.reset_session(dev)
check_xml = fc.do_check(https=False, max_tries=20) check_xml = fc.do_check(dev, https=False, max_tries=20)
curef, fv, tv, fw_id, fileid, fn, fsize, fhash = fc.parse_check(check_xml) curef, fv, tv, fw_id, fileid, fn, fsize, fhash = fc.parse_check(check_xml)
txt_tv = tv txt_tv = tv
print("{}: {} {}".format(curef, txt_tv, fhash)) print("{}: {} {}".format(curef, txt_tv, fhash))

View File

@ -12,19 +12,14 @@ from requests.exceptions import RequestException, Timeout
import tcllib import tcllib
import tcllib.argparser import tcllib.argparser
from tcllib import ansi, devlist from tcllib import ansi, devlist
from tcllib.devices import DesktopDevice, MobileDevice
# Variants to scan for # Variants to scan for
SCAN_VARIANTS = ["001", "003", "009", "010", "700"] SCAN_VARIANTS = ["001", "003", "009", "010", "700"]
dev = DesktopDevice()
fc = tcllib.FotaCheck() fc = tcllib.FotaCheck()
fc.serid = "3531510"
fc.fv = "AAA000"
fc.mode = fc.MODE.FULL
# CLTP = 10 (only show actual updates or HTTP 206) / 2010 (always show latest version for MODE.FULL)
#fc.cltp = fc.CLTP.MOBILE
fc.cltp = fc.CLTP.DESKTOP
dpdesc = """ dpdesc = """
Finds new PRD numbers for a range of variants. Scan range can be set by Finds new PRD numbers for a range of variants. Scan range can be set by
@ -61,9 +56,9 @@ for center in to_scan:
print("Checking {} ({}/{})".format(curef, done_count, total_count)) print("Checking {} ({}/{})".format(curef, done_count, total_count))
print(ansi.UP_DEL, end="") print(ansi.UP_DEL, end="")
try: try:
fc.reset_session() dev.curef = curef
fc.curef = curef fc.reset_session(dev)
check_xml = fc.do_check(https=False, max_tries=20) check_xml = fc.do_check(dev, https=False, max_tries=20)
curef, fv, tv, fw_id, fileid, fn, fsize, fhash = fc.parse_check(check_xml) curef, fv, tv, fw_id, fileid, fn, fsize, fhash = fc.parse_check(check_xml)
txt_tv = tv txt_tv = tv
print("{}: {} {}".format(curef, txt_tv, fhash)) print("{}: {} {}".format(curef, txt_tv, fhash))

View File

@ -12,11 +12,11 @@ from requests.exceptions import RequestException, Timeout
import tcllib import tcllib
import tcllib.argparser import tcllib.argparser
from tcllib import ansi from tcllib import ansi
from tcllib.devices import DesktopDevice, MobileDevice
dev = MobileDevice()
fc = tcllib.FotaCheck() fc = tcllib.FotaCheck()
fc.serid = "3531510"
fc.mode = fc.MODE.OTA
dpdesc = """ dpdesc = """
Finds all valid OTA updates for a given PRD. Scan range can be set by Finds all valid OTA updates for a given PRD. Scan range can be set by
@ -60,9 +60,9 @@ for fv in allvers:
print("Checking {} ({}/{})".format(fv, done_count, total_count)) print("Checking {} ({}/{})".format(fv, done_count, total_count))
print(ansi.UP_DEL, end="") print(ansi.UP_DEL, end="")
try: try:
fc.reset_session() dev.fwver = fv
fc.fv = fv fc.reset_session(dev)
check_xml = fc.do_check(https=False, max_tries=20) check_xml = fc.do_check(dev, https=False, max_tries=20)
curef, fv, tv, fw_id, fileid, fn, fsize, fhash = fc.parse_check(check_xml) curef, fv, tv, fw_id, fileid, fn, fsize, fhash = fc.parse_check(check_xml)
txt_tv = tv txt_tv = tv
print("{}: {}{} {}".format(curef, fv, txt_tv, fhash)) print("{}: {}{} {}".format(curef, fv, txt_tv, fhash))

View File

@ -11,17 +11,15 @@ import requests
from requests.exceptions import RequestException from requests.exceptions import RequestException
import tcllib import tcllib
from tcllib.devices import DesktopDevice, MobileDevice
# 1. Fetch list of missing OTAs (e.g. from ancient versions to current) # 1. Fetch list of missing OTAs (e.g. from ancient versions to current)
# 2. Query updates from FOTA servers (and store XML) # 2. Query updates from FOTA servers (and store XML)
# (3. Upload will be done manually with upload_logs.py) # (3. Upload will be done manually with upload_logs.py)
dev = MobileDevice()
fc = tcllib.FotaCheck() fc = tcllib.FotaCheck()
fc.serid = "3531510"
#fc.osvs = "7.1.1"
fc.mode = fc.MODE.OTA
fc.cltp = fc.CLTP.MOBILE
print("Loading list of missing OTAs.") print("Loading list of missing OTAs.")
versions_json = requests.get("https://tclota.birth-online.de/json_otaversions.php").text versions_json = requests.get("https://tclota.birth-online.de/json_otaversions.php").text
@ -38,10 +36,10 @@ for prd, data in versions.items():
for ver in data["missing_froms"]: for ver in data["missing_froms"]:
print(" {}".format(ver), end="", flush=True) print(" {}".format(ver), end="", flush=True)
try: try:
fc.reset_session() dev.curef = prd
fc.curef = prd dev.fwver = ver
fc.fv = ver fc.reset_session(dev)
check_xml = fc.do_check(max_tries=20) check_xml = fc.do_check(dev, max_tries=20)
curef, fv, tv, fw_id, fileid, fn, fsize, fhash = fc.parse_check(check_xml) curef, fv, tv, fw_id, fileid, fn, fsize, fhash = fc.parse_check(check_xml)
print("", end="", flush=True) print("", end="", flush=True)
except RequestException as e: except RequestException as e:

View File

@ -11,12 +11,12 @@ import sys
import tcllib import tcllib
import tcllib.argparser import tcllib.argparser
from tcllib.devices import DesktopDevice
from tcllib.xmltools import pretty_xml from tcllib.xmltools import pretty_xml
fc = tcllib.FotaCheck() fc = tcllib.FotaCheck()
fc.serid = "3531510" dev = DesktopDevice()
#fc.osvs = "7.1.1"
dpdesc = """ dpdesc = """
Downloads the given firmware file. Downloads the given firmware file.
@ -36,41 +36,39 @@ args = dp.parse_args(sys.argv[1:])
def sel_mode(defaultmode, rawval): def sel_mode(defaultmode, rawval):
"""Handle custom mode.""" """Handle custom mode."""
if rawval: if rawval:
enum = tcllib.default_enum("MODE", {"RAW": rawval}) return rawval
return enum.RAW
return defaultmode return defaultmode
def sel_cltp(txtmode, rawval): def sel_cltp(txtmode, rawval):
"""Handle custom CLTP.""" """Handle custom CLTP."""
if rawval: if rawval:
enum = tcllib.default_enum("CLTP", {"RAW": rawval}) return rawval
return enum.RAW
if txtmode == "mobile": if txtmode == "mobile":
return fc.CLTP.MOBILE return dev.CLTP_STATES["MOBILE"]
return fc.CLTP.DESKTOP return dev.CLTP_STATES["DESKTOP"]
if args.imei: if args.imei:
print("Use specified IMEI: {}".format(args.imei)) print("Use specified IMEI: {}".format(args.imei))
fc.serid = args.imei dev.imei = args.imei
fc.curef = args.prd[0] dev.curef = args.prd[0]
if args.ota: if args.ota:
fc.fv = args.ota[0] dev.fwver = args.ota[0]
fc.mode = sel_mode(fc.MODE.OTA, args.rawmode) dev.mode = sel_mode(dev.MODE_STATES["OTA"], args.rawmode)
else: else:
fc.fv = args.targetversion[0] dev.fwver = args.targetversion[0]
fc.mode = sel_mode(fc.MODE.FULL, args.rawmode) dev.mode = sel_mode(dev.MODE_STATES["FULL"], args.rawmode)
fc.cltp = sel_cltp(args.type, args.rawcltp) dev.cltp = sel_cltp(args.type, args.rawcltp)
print("Mode: {}".format(fc.mode.value)) print("Mode: {}".format(dev.mode))
print("CLTP: {}".format(fc.cltp.value)) print("CLTP: {}".format(dev.cltp))
fv = fc.fv fv = dev.fwver
tv = args.targetversion[0] tv = args.targetversion[0]
fw_id = args.fwid[0] fw_id = args.fwid[0]
req_xml = fc.do_request(fc.curef, fv, tv, fw_id) req_xml = fc.do_request(dev.curef, fv, tv, fw_id)
print(pretty_xml(req_xml)) print(pretty_xml(req_xml))
fileid, fileurl, slaves, encslaves, s3_fileurl, s3_slaves = fc.parse_request(req_xml) fileid, fileurl, slaves, encslaves, s3_fileurl, s3_slaves = fc.parse_request(req_xml)
@ -80,7 +78,7 @@ for s in slaves:
for s in s3_slaves: for s in s3_slaves:
print("http://{}{}".format(s, s3_fileurl)) print("http://{}{}".format(s, s3_fileurl))
if fc.mode == fc.MODE.FULL: if dev.mode == dev.MODE_STATES["FULL"]:
header = fc.do_encrypt_header(random.choice(encslaves), fileurl) header = fc.do_encrypt_header(random.choice(encslaves), fileurl)
headname = "header_{}.bin".format(tv) headname = "header_{}.bin".format(tv)
headdir = "headers" headdir = "headers"

View File

@ -5,19 +5,12 @@
"""Library for TCL API work and related functions.""" """Library for TCL API work and related functions."""
import enum
import requests import requests
from . import (dumpmgr, servervote, tclcheck, tclchecksum, tclencheader, from . import (dumpmgr, servervote, tclcheck, tclchecksum, tclencheader,
tclrequest) tclrequest)
def default_enum(enumname, vardict, qualroot="tcllib.FotaCheck"):
"""Enum with defaults set."""
return enum.IntEnum(enumname, vardict, module=__name__, qualname="{}.{}".format(qualroot, enumname))
class FotaCheck( class FotaCheck(
tclcheck.TclCheckMixin, tclcheck.TclCheckMixin,
tclrequest.TclRequestMixin, tclrequest.TclRequestMixin,
@ -28,35 +21,15 @@ class FotaCheck(
): ):
"""Main API handler class.""" """Main API handler class."""
CKTP = default_enum("CKTP", ["AUTO", "MANUAL"])
MODE = default_enum("MODE", {"OTA": 2, "FULL": 4})
RTD = default_enum("RTD", ["UNROOTED", "ROOTED"])
CHNL = default_enum("CHNL", ["3G", "WIFI"])
CLTP = default_enum("CLTP", {"MOBILE": 10, "DESKTOP": 2010})
CKOT = default_enum("CKOT", ["ALL", "AOTA_ONLY", "FOTA_ONLY"])
def __init__(self): def __init__(self):
"""Handle mixins and populate variables.""" """Handle mixins and populate variables."""
super().__init__() super().__init__()
self.serid = "543212345000000"
self.curef = "PRD-63117-011"
self.fv = "AAM481"
self.osvs = "7.1.1"
self.mode = self.MODE.FULL
self.ftype = "Firmware"
self.cltp = self.CLTP.MOBILE
self.cktp = self.CKTP.MANUAL
self.ckot = self.CKOT.ALL
self.rtd = self.RTD.UNROOTED
self.chnl = self.CHNL.WIFI
self.reset_session() self.reset_session()
def reset_session(self): def reset_session(self, device=None):
"""Reset everything to default.""" """Reset everything to default."""
self.g2master = self.get_master_server() self.g2master = self.get_master_server()
self.sess = requests.Session() self.sess = requests.Session()
if self.mode == self.MODE.FULL: if device:
self.sess.headers.update({"User-Agent": "com.tcl.fota/5.1.0.2.0029.0, Android"}) self.sess.headers.update({"User-Agent": device.ua})
else:
self.sess.headers.update({"User-Agent": "tcl"})
return self.sess return self.sess

View File

@ -11,6 +11,8 @@ from collections import OrderedDict, defaultdict
import requests import requests
from defusedxml import ElementTree from defusedxml import ElementTree
from .devices import Device
class TclCheckMixin: class TclCheckMixin:
"""A mixin component for TCL's update request API.""" """A mixin component for TCL's update request API."""
@ -21,38 +23,24 @@ class TclCheckMixin:
url = protocol + self.g2master + "/check.php" url = protocol + self.g2master + "/check.php"
return url return url
def prep_check(self, device=None, https=True): def prep_check(self, device: Device, https=True):
"""Prepare URL and parameters for update request.""" """Prepare URL and parameters for update request."""
url = self.prep_check_url(https) url = self.prep_check_url(https)
params = OrderedDict() params = OrderedDict()
if device: params["id"] = device.imei
# Need to support both ways for now params["curef"] = device.curef
params["id"] = device.imei params["fv"] = device.fwver
params["curef"] = device.curef params["mode"] = device.mode
params["fv"] = device.fwver params["type"] = device.type
params["mode"] = device.mode params["cltp"] = device.cltp
params["type"] = device.type params["cktp"] = device.cktp
params["cltp"] = device.cltp params["rtd"] = device.rtd
params["cktp"] = device.cktp params["chnl"] = device.chnl
params["rtd"] = device.rtd #params["osvs"] = device.osvs
params["chnl"] = device.chnl #params["ckot"] = device.ckot
#params["osvs"] = device.osvs
#params["ckot"] = device.ckot
else:
params["id"] = self.serid
params["curef"] = self.curef
params["fv"] = self.fv
params["mode"] = self.mode.value
params["type"] = self.ftype
params["cltp"] = self.cltp.value
params["cktp"] = self.cktp.value
params["rtd"] = self.rtd.value
params["chnl"] = self.chnl.value
#params["osvs"] = self.osvs
#params["ckot"] = self.ckot.value
return url, params return url, params
def do_check(self, device=None, https=True, timeout=10, max_tries=5): def do_check(self, device: Device, https=True, timeout=10, max_tries=5):
"""Perform update request with given parameters.""" """Perform update request with given parameters."""
url, params = self.prep_check(device, https) url, params = self.prep_check(device, https)
last_response = None last_response = None