From 64be0eb8943bca854182fda6d9708c171dafb596 Mon Sep 17 00:00:00 2001 From: Markus Birth Date: Sat, 14 Sep 2019 04:21:10 +0200 Subject: [PATCH] Added options to get_updates.py. Some new features for updateserver.py. --- get_updates.py | 76 +++++++++++++++++++++++++++++++++++++------- grmn/updateserver.py | 60 ++++++++++++++++++++++++++-------- 2 files changed, 112 insertions(+), 24 deletions(-) diff --git a/get_updates.py b/get_updates.py index 8f028a4..8fa2d9f 100644 --- a/get_updates.py +++ b/get_updates.py @@ -5,27 +5,81 @@ Queries the updateserver for given device's updates. """ +__author__ = "mbirth" + from grmn import updateserver, devices +from optparse import OptionParser, OptionGroup +import os.path import sys -if len(sys.argv) < 2: - print("Syntax: {} DEVICESKU1 [DEVICESKU2..n]".format(sys.argv[0])) - print("Examples:") - print(" {} 3196 - Query update info for 006-B3196-00".format(sys.argv[0])) - print(" {} 006-B3196-00 - Query update info for given SKU".format(sys.argv[0])) - sys.exit(1) +optp = OptionParser(usage="usage: %prog [options] SKU1 [SKU2..SKUn]") +optp.add_option("-c", "--changelog", action="store_true", dest="changelog", help="also show changelog") +optp.add_option("-l", "--license", action="store_true", dest="license", help="also show license") +optp.add_option("-E", "--express", action="store_false", dest="webupdater", default=True, help="Only query Garmin Express") +optp.add_option("-W", "--webupdater", action="store_false", dest="express", default=True, help="Only query WebUpdater") +optp.add_option("--id", dest="unit_id", help="Specify custom Unit ID") +optp.add_option("--code", action="append", dest="unlock_codes", metavar="UNLOCK_CODE", default=[], help="Specify map unlock codes") +optp.add_option("--devicexml", dest="devicexml", metavar="FILE", help="Use specified GarminDevice.xml (also implies -E)") -device_skus = sys.argv[1:] +optp.usage = """ + %prog [options] SKU1 [SKU2..SKUn] + +Examples: + %prog 3196 - Query update info for 006-B3196-00 + %prog 006-B3196-00 - Query update info for given SKU + %prog --devicexml=~/fenix/GARMIN/GarminDevice.xml""" + +(opts, device_skus) = optp.parse_args() + +if len(device_skus) < 1 and not opts.devicexml: + optp.print_help() + sys.exit(1) us = updateserver.UpdateServer() +if opts.devicexml: + # Filename given, load GarminDevice.xml from there; also disable WebUpdater + print("Using GarminDevice.xml from {}.".format(opts.devicexml)) + if not os.path.isfile(opts.devicexml): + print("ERROR: Not a file.", file=sys.stderr) + sys.exit(2) + device_xml = "" + with open(opts.devicexml, "rt") as f: + device_xml = f.read() + print("Querying Garmin Express ...", end="", flush=True) + result = us.get_unit_updates(device_xml) + print(" done.") + print(result) + sys.exit(0) + +# If no GarminDevice.xml read from file, continue here for i, sku in enumerate(device_skus): if len(sku) <= 4: device_skus[i] = "006-B{:>04}-00".format(sku) -primary_hwid = int(device_skus[0][5:9]) -device_name = devices.DEVICES.get(primary_hwid, "Unknown device") +if device_skus[0][0:5] == "006-B": + primary_hwid = int(device_skus[0][5:9]) + device_name = devices.DEVICES.get(primary_hwid, "Unknown device") + print("Device (guessed): {}".format(device_name)) -print("Device: {}".format(device_name)) +if opts.unit_id: + print("Custom Unit ID: {}".format(opts.unit_id)) + us.device_id = opts.unit_id -us.query_updates(device_skus) +for uc in opts.unlock_codes: + print("Unlock Code: {}".format(uc)) + us.unlock_codes.append(uc) + +results = [] + +if opts.express: + print("Querying Garmin Express ...", end="", flush=True) + results.append(us.query_express(device_skus)) + print(" done.") + +if opts.webupdater: + print("Querying Garmin WebUpdater ...", end="", flush=True) + results.append(us.query_webupdater(device_skus)) + print(" done.") + +print(results) diff --git a/grmn/updateserver.py b/grmn/updateserver.py index ac19394..f69b463 100644 --- a/grmn/updateserver.py +++ b/grmn/updateserver.py @@ -14,18 +14,39 @@ PROTO_API_GETALLUNITSOFTWAREUPDATES_URL = "http://omt.garmin.com/Rce/ProtobufApi WEBUPDATER_SOFTWAREUPDATE_URL = "https://www.garmin.com/support/WUSoftwareUpdate.jsp" GRMN_CLIENT_VERSION = "6.17.0.0" +class UpdateInfo: + def __init__(self): + pass + class UpdateServer: - def query_updates(self, sku_numbers): + def __init__(self): + self.device_id = "2345678910" + self.unlock_codes = [] + self.debug = False + + def query_express(self, sku_numbers): # Garmin Express Protobuf API device_xml = self.get_device_xml(sku_numbers) reply = self.get_unit_updates(device_xml) - print(reply) + return reply + def query_webupdater(self, sku_numbers): # WebUpdater requests_xml = self.get_requests_xml(sku_numbers) reply = self.get_webupdater_softwareupdate(requests_xml) - print(reply) + return reply + + def query_updates(self, sku_numbers, query_express=True, query_webupdater=True): + results = [] + + if query_express: + results.append(self.query_express(sku_numbers)) + + if query_webupdater: + results.append(self.query_webupdater(sku_numbers)) + + return results def dom_add_text(self, doc, parent, elem_name, text): e = doc.createElement(elem_name) @@ -49,7 +70,12 @@ class UpdateServer: self.dom_add_text(doc, model, "Description", "-") root.appendChild(model) - self.dom_add_text(doc, root, "Id", "2345678910") + self.dom_add_text(doc, root, "Id", self.device_id) + + for uc in self.unlock_codes: + ul = doc.createElement("Unlock") + self.dom_add_text(doc, ul, "Code", uc) + root.appendChild(ul) msm = doc.createElement("MassStorageMode") for sku in sku_numbers: @@ -57,7 +83,7 @@ class UpdateServer: self.dom_add_text(doc, uf, "PartNumber", sku) v = doc.createElement("Version") self.dom_add_text(doc, v, "Major", "0") - self.dom_add_text(doc, v, "Minor", "1") + self.dom_add_text(doc, v, "Minor", "00") uf.appendChild(v) self.dom_add_text(doc, uf, "Path", "GARMIN") self.dom_add_text(doc, uf, "FileName", "GUPDATE.GCD") @@ -105,6 +131,12 @@ class UpdateServer: query.device_xml = device_xml proto_msg = query.SerializeToString() + if self.debug: + #print(proto_msg) + with open("protorequest.bin", "wb") as f: + f.write(proto_msg) + f.close() + headers = { "User-Agent": "Garmin Core Service Win - {}".format(GRMN_CLIENT_VERSION), "Garmin-Client-Name": "CoreService", @@ -122,10 +154,11 @@ class UpdateServer: r.raise_for_status() return None - #print(r.content) - #with open("protoreply.bin", "wb") as f: - # f.write(r.content) - # f.close() + if self.debug: + #print(r.content) + with open("protoreply.bin", "wb") as f: + f.write(r.content) + f.close() reply = GetAllUnitSoftwareUpdates_pb2.GetAllUnitSoftwareUpdatesReply() reply.ParseFromString(r.content) @@ -147,9 +180,10 @@ class UpdateServer: r.raise_for_status() return None - #print(r.content) - #with open("webupdaterreply.xml", "wb") as f: - # f.write(r.content) - # f.close() + if self.debug: + #print(r.content) + with open("webupdaterreply.xml", "wb") as f: + f.write(r.content) + f.close() return r.content