gcd-parser/grmn/updateserver.py
2019-09-10 16:42:11 +02:00

150 lines
5.2 KiB
Python

# -*- coding: utf-8 -*-
from . import devices
from .proto import GetAllUnitSoftwareUpdates_pb2
from xml.dom.minidom import getDOMImplementation
import requests
PROTO_API_GETALLUNITSOFTWAREUPDATES_URL = "http://omt.garmin.com/Rce/ProtobufApi/SoftwareUpdateService/GetAllUnitSoftwareUpdates"
WEBUPDATER_SOFTWAREUPDATE_URL = "https://www.garmin.com/support/WUSoftwareUpdate.jsp"
GRMN_CLIENT_VERSION = "5.7.0.2"
class UpdateServer:
def query_updates(self, sku_numbers):
# Garmin Express Protobuf API
device_xml = self.get_device_xml(sku_numbers)
reply = self.get_unit_updates(device_xml)
print(reply)
# WebUpdater
requests_xml = self.get_requests_xml(sku_numbers)
reply = self.get_webupdater_softwareupdate(requests_xml)
print(reply)
def dom_add_text(self, doc, parent, elem_name, text):
e = doc.createElement(elem_name)
t = doc.createTextNode(text)
e.appendChild(t)
parent.appendChild(e)
def get_device_xml(self, sku_numbers):
dom = getDOMImplementation()
doc = dom.createDocument(None, "Device", None)
root = doc.documentElement
root.setAttribute("xmlns", "http://www.garmin.com/xmlschemas/GarminDevice/v2")
root.setAttribute("xmlns:xsi", "http://www.w3.org/2001/XMLSchema-instance")
root.setAttribute("xsi:schemaLocation", "http://www.garmin.com/xmlschemas/GarminDevice/v2 http://www.garmin.com/xmlschemas/GarminDevicev2.xsd")
model = doc.createElement("Model")
self.dom_add_text(doc, model, "PartNumber", sku_numbers[0])
self.dom_add_text(doc, model, "SoftwareVersion", "1")
self.dom_add_text(doc, model, "Description", "-")
root.appendChild(model)
self.dom_add_text(doc, root, "Id", "2345678910")
msm = doc.createElement("MassStorageMode")
for sku in sku_numbers:
uf = doc.createElement("UpdateFile")
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, uf, "Path", "GARMIN")
self.dom_add_text(doc, uf, "FileName", "GUPDATE.GCD")
msm.appendChild(uf)
root.appendChild(msm)
xml = doc.toxml("utf-8")
return xml
def get_requests_xml(self, sku_numbers):
dom = getDOMImplementation()
doc = dom.createDocument(None, "Requests", None)
doc.standalone = False
root = doc.documentElement
root.setAttribute("xmlns", "http://www.garmin.com/xmlschemas/UnitSoftwareUpdate/v3")
for sku in sku_numbers:
req = doc.createElement("Request")
self.dom_add_text(doc, req, "PartNumber", sku)
self.dom_add_text(doc, req, "TransferType", "USB")
reg = doc.createElement("Region")
self.dom_add_text(doc, reg, "RegionId", "14")
ver = doc.createElement("Version")
self.dom_add_text(doc, ver, "VersionMajor", "0")
self.dom_add_text(doc, ver, "VersionMinor", "1")
self.dom_add_text(doc, ver, "BuildType", "Release")
reg.appendChild(ver)
req.appendChild(reg)
root.appendChild(req)
xml = doc.toxml("utf-8")
return xml
def get_unit_updates(self, device_xml):
query = GetAllUnitSoftwareUpdates_pb2.GetAllUnitSoftwareUpdates()
query.client_data.client = "express"
query.client_data.language ="en_US"
query.client_data.client_platform = "Windows"
query.client_data.client_platform_version = "601 Service Pack 1"
query.device_xml = device_xml
proto_msg = query.SerializeToString()
headers = {
"User-Agent": "Garmin Core Service Win - {}".format(GRMN_CLIENT_VERSION),
"Garmin-Client-Name": "CoreService",
"Garmin-Client-Version": GRMN_CLIENT_VERSION,
"X-garmin-client-id": "EXPRESS",
"Garmin-Client-Platform": "windows",
"Garmin-Client-Platform-Version": "601",
"Garmin-Client-Platform-Version-Revision": "1",
"Content-Type": "application/octet-stream",
}
r = requests.post(PROTO_API_GETALLUNITSOFTWAREUPDATES_URL, headers=headers, data=proto_msg)
if r.status_code != 200:
r.raise_for_status()
return None
#print(r.content)
with open("protoreply.bin", "wb") as f:
f.write(r.content)
f.close()
reply = GetAllUnitSoftwareUpdates_pb2.GetAllUnitSoftwareUpdatesReply()
reply.ParseFromString(r.content)
return reply
def get_webupdater_softwareupdate(self, requests_xml):
headers = {
"User-Agent": "Undefined agent",
}
data = {
"req": requests_xml,
}
print(repr(data))
r = requests.post(WEBUPDATER_SOFTWAREUPDATE_URL, headers=headers, data=data)
if r.status_code != 200:
r.raise_for_status()
return None
#print(r.content)
with open("webupdaterreply.xml", "wb") as f:
f.write(r.content)
f.close()
return r.content