Exemplo n.º 1
0
def patch_firmware():
    version = flask.request.args.get('version', None)
    if version not in ['DRV120', 'DRV133', 'DRV139', 'DRV150', 'DRV151']:
        return 'Invalid firmware version.', 400

    with open('/root/9botcfw/bins/{}.bin'.format(version), 'rb') as fp:
        patcher = FirmwarePatcher(fp.read())

    kers_min_speed = flask.request.args.get('kers_min_speed', None)
    if kers_min_speed is not None:
        kers_min_speed = int(kers_min_speed)
        assert kers_min_speed >= 0 and kers_min_speed <= 100
        patcher.kers_min_speed(kers_min_speed)

    kers_dividor = flask.request.args.get('kers_dividor', None)
    if kers_dividor is not None:
        kers_dividor = int(kers_dividor)
        assert kers_dividor >= 0 and kers_dividor <= 100
        if kers_dividor == 2:
           patcher.kers_dividor_2()		
        if kers_dividor == 6:
           patcher.kers_dividor_6()
        if kers_dividor == 12:
           patcher.kers_dividor_6()
           patcher.kers_dividor_2() 

    max_speed = flask.request.args.get('max_speed', None)
    if max_speed is not None:
        max_speed = int(max_speed)
        assert max_speed >= 0 and max_speed <= 65
        patcher.max_speed(max_speed)


    wheel_speed_const = flask.request.args.get('wheel_speed_const', None)
    if wheel_speed_const:
        wheel_speed_const = int(wheel_speed_const)
        assert wheel_speed_const >= 200 and wheel_speed_const <= 500
        patcher.wheel_speed_const(wheel_speed_const)

    stay_on_locked = flask.request.args.get('stay_on_locked', None)
    if stay_on_locked:
        patcher.stay_on_locked()

    remove_charging_mode = flask.request.args.get('remove_charging_mode', None)
    if remove_charging_mode:
        patcher.remove_charging_mode()

    swd_enable = flask.request.args.get('swd_enable', None)
    if swd_enable:
        patcher.swd_enable()

    bypass_BMS = flask.request.args.get('bypass_BMS', None)
    if bypass_BMS:
        patcher.bypass_BMS()
		
    bms_uart_76800 = flask.request.args.get('bms_uart_76800', None)
    if bms_uart_76800:
        patcher.bms_uart_76800()

    motor_power_constant = flask.request.args.get('motor_power_constant', None)
    if motor_power_constant is not None:
        motor_power_constant = int(motor_power_constant)
        assert motor_power_constant >= 20000 and motor_power_constant <= 65535
        patcher.motor_power_constant(motor_power_constant)

    cruise_control_delay = flask.request.args.get('cruise_control_delay', None)
    if cruise_control_delay is not None:
        cruise_control_delay = int(cruise_control_delay)
        assert cruise_control_delay >= 0 and cruise_control_delay <= 100
        patcher.cruise_control_delay(cruise_control_delay)

    motor_start_speed = flask.request.args.get('motor_start_speed', None)
    if motor_start_speed is not None:
        motor_start_speed = int(motor_start_speed)
        assert motor_start_speed >= 0 and motor_start_speed <= 10
        patcher.motor_start_speed(motor_start_speed)
		
    throttle_alg = flask.request.args.get('throttle_alg', None)
    if throttle_alg:
        patcher.alt_throttle_alg()

    version_spoofing = flask.request.args.get('version_spoofing', None)
    if version_spoofing:
         patcher.version_spoofing()

    output = flask.request.args.get('output', None)
    if output == 'zip' or not output:
        # make zip file for firmware
        zip_buffer = io.BytesIO()
        zip_file = zipfile.ZipFile(zip_buffer, 'a', zipfile.ZIP_DEFLATED, False)

        zip_file.writestr('FIRM.bin', patcher.data)
        md5 = hashlib.md5()
        md5.update(patcher.data)

        patcher.encrypt()
        zip_file.writestr('FIRM.bin.enc', patcher.data)
        md5e = hashlib.md5()
        md5e.update(patcher.data)

        info_txt = 'dev: ES/SNSC;\nnam: {};\nenc: B;\ntyp: DRV;\nmd5: {};\nmd5e: {};\n'.format(
            version, md5.hexdigest(), md5e.hexdigest())

        zip_file.writestr('info.txt', info_txt.encode())
        message = "Downloaded from scooterhacking.org - Share this CFW with the following link : https://ninebot.scooterhacking.org"
        request_url = flask.request.full_path.encode()
        request_url = request_url.decode("utf-8").replace("cfw", "", 1).encode("utf-8")
        zip_file.comment = bytes(message, 'utf-8') + request_url
        zip_file.close()
        zip_buffer.seek(0)
        content = zip_buffer.getvalue()
        zip_buffer.close()

        resp = flask.Response(content)
        filename = version + '-' + str(int(time.time())) + '.zip'
        resp.headers['Content-Type'] = 'application/zip'
        resp.headers['Content-Disposition'] = 'inline; filename="{0}"'.format(filename)
        resp.headers['Content-Length'] = len(content)
    if output == 'bin' or output == 'enc':
        filename = version + '-' + str(int(time.time())) + '.bin'
        if output == 'enc':
            patcher.encrypt()
            filename += '.enc'
        resp = flask.Response(patcher.data)
        resp.headers['Content-Type'] = 'application/octet-stream'
        resp.headers['Content-Disposition'] = 'inline; filename="{0}"'.format(filename)
        resp.headers['Content-Length'] = len(patcher.data)

    return resp
Exemplo n.º 2
0
def patch_firmware():
    version = flask.request.args.get('version', None)
    if version not in ['DRV130', 'DRV134', 'DRV138']:
        return 'Invalid firmware version.', 400

    with open('../bins/{}.bin'.format(version), 'rb') as fp:
        patcher = FirmwarePatcher(fp.read())

    kers_min_speed = flask.request.args.get('kers_min_speed', None)
    if kers_min_speed is not None:
        kers_min_speed = float(kers_min_speed)
        assert kers_min_speed >= 0 and kers_min_speed <= 100
        patcher.kers_min_speed(kers_min_speed)

    normal_max_speed = flask.request.args.get('normal_max_speed', None)
    if normal_max_speed is not None:
        normal_max_speed = int(normal_max_speed)
        assert normal_max_speed >= 0 and normal_max_speed <= 100
        patcher.normal_max_speed(normal_max_speed)

    eco_max_speed = flask.request.args.get('eco_max_speed', None)
    if eco_max_speed is not None:
        eco_max_speed = int(eco_max_speed)
        assert eco_max_speed >= 0 and eco_max_speed <= 100
        patcher.eco_max_speed(eco_max_speed)

    motor_start_speed = flask.request.args.get('motor_start_speed', None)
    if motor_start_speed is not None:
        motor_start_speed = float(motor_start_speed)
        assert motor_start_speed >= 0 and motor_start_speed <= 100
        patcher.motor_start_speed(motor_start_speed)

    motor_power_constant = flask.request.args.get('motor_power_constant', None)
    if motor_power_constant is not None:
        motor_power_constant = int(motor_power_constant)
        assert motor_power_constant >= 25787 and motor_power_constant <= 65535
        patcher.motor_power_constant(motor_power_constant)

    cruise_control_delay = flask.request.args.get('cruise_control_delay', None)
    if cruise_control_delay is not None:
        cruise_control_delay = float(cruise_control_delay)
        assert cruise_control_delay >= 0.1 and cruise_control_delay <= 20.0
        patcher.cruise_control_delay(cruise_control_delay)

    instant_eco_switch = flask.request.args.get('instant_eco_switch', None)
    if instant_eco_switch:
        patcher.instant_eco_switch()

    boot_with_eco = flask.request.args.get('boot_with_eco', None)
    if boot_with_eco:
        patcher.boot_with_eco()

    idk_what_this_does = flask.request.args.get('idk_what_this_does', None)
    if idk_what_this_does:
        patcher.idk_what_this_does()

    resp = flask.Response(patcher.data)
    resp.headers['Content-Type'] = 'application/octet-stream'
    resp.headers[
        'Content-Disposition'] = 'inline; filename="{0}-patched.bin"'.format(
            version)
    resp.headers['Content-Length'] = len(patcher.data)

    return resp
Exemplo n.º 3
0
def patch_firmware():
    version = flask.request.args.get('version', None)
    if version not in [
            'DRV130', 'DRV134', 'DRV138', 'DRV140', 'DRV141', 'DRV142',
            'DRV143'
    ]:
        return 'Invalid firmware version.', 400

    with open('../bins/{}.bin'.format(version), 'rb') as fp:
        patcher = FirmwarePatcher(fp.read())

    kers_min_speed = flask.request.args.get('kers_min_speed', None)
    if kers_min_speed is not None:
        kers_min_speed = float(kers_min_speed)
        assert kers_min_speed >= 0 and kers_min_speed <= 100
        patcher.kers_min_speed(kers_min_speed)

    speed_params = flask.request.args.get('speed_params', None)
    if speed_params:
        speed_normal_kmh = int(flask.request.args.get('speed_normal_kmh',
                                                      None))
        assert speed_normal_kmh >= 0 and speed_normal_kmh <= 100
        speed_normal_phase = int(
            flask.request.args.get('speed_normal_phase', None))
        assert speed_normal_phase >= 0 and speed_normal_phase <= 65535
        speed_normal_battery = int(
            flask.request.args.get('speed_normal_battery', None))
        assert speed_normal_battery >= 0 and speed_normal_battery <= 65535
        speed_eco_kmh = int(flask.request.args.get('speed_eco_kmh', None))
        assert speed_eco_kmh >= 0 and speed_eco_kmh <= 100
        speed_eco_phase = int(flask.request.args.get('speed_eco_phase', None))
        assert speed_eco_phase >= 0 and speed_eco_phase <= 65535
        speed_eco_battery = int(
            flask.request.args.get('speed_eco_battery', None))
        assert speed_eco_battery >= 0 and speed_eco_battery <= 65535
        patcher.speed_params(speed_normal_kmh, speed_normal_phase,
                             speed_normal_battery, speed_eco_kmh,
                             speed_eco_phase, speed_eco_battery)

    brake_params = flask.request.args.get('brake_params', None)
    if brake_params:
        brake_limit = int(flask.request.args.get('brake_limit', None))
        assert brake_limit >= 1 and brake_limit <= 130
        brake_i_min = int(flask.request.args.get('brake_i_min', None))
        assert brake_i_min >= 0 and brake_i_min <= 65535
        brake_i_max = int(flask.request.args.get('brake_i_max', None))
        assert brake_i_max >= brake_i_min and brake_i_max <= 65535
        patcher.brake_params(brake_limit, brake_i_min, brake_i_max)

    motor_start_speed = flask.request.args.get('motor_start_speed', None)
    if motor_start_speed is not None:
        motor_start_speed = float(motor_start_speed)
        assert motor_start_speed >= 0 and motor_start_speed <= 100
        patcher.motor_start_speed(motor_start_speed)

    cruise_control_delay = flask.request.args.get('cruise_control_delay', None)
    if cruise_control_delay is not None:
        cruise_control_delay = float(cruise_control_delay)
        assert cruise_control_delay >= 0.1 and cruise_control_delay <= 20.0
        patcher.cruise_control_delay(cruise_control_delay)

    cruise_control_nobeep = flask.request.args.get('cruise_control_nobeep',
                                                   None)
    if cruise_control_nobeep:
        patcher.cruise_control_nobeep()

    instant_eco_switch = flask.request.args.get('instant_eco_switch', None)
    if instant_eco_switch:
        patcher.instant_eco_switch()

    boot_with_eco = flask.request.args.get('boot_with_eco', None)
    if boot_with_eco:
        patcher.boot_with_eco()

    voltage_limit = flask.request.args.get('voltage_limit', None)
    if voltage_limit is not None:
        voltage_limit = float(voltage_limit)
        assert voltage_limit >= 43.01 and voltage_limit <= 100.00
        patcher.voltage_limit(voltage_limit)

    russian_throttle = flask.request.args.get('russian_throttle', None)
    if russian_throttle:
        patcher.russian_throttle()

    remove_hard_speed_limit = flask.request.args.get('remove_hard_speed_limit',
                                                     None)
    if remove_hard_speed_limit:
        patcher.remove_hard_speed_limit()

    remove_charging_mode = flask.request.args.get('remove_charging_mode', None)
    if remove_charging_mode:
        patcher.remove_charging_mode()

    stay_on_locked = flask.request.args.get('stay_on_locked', None)
    if stay_on_locked:
        patcher.stay_on_locked()

    bms_uart_76800 = flask.request.args.get('bms_uart_76800', None)
    if bms_uart_76800:
        patcher.bms_uart_76800()

    wheel_speed_const = flask.request.args.get('wheel_speed_const', None)
    if wheel_speed_const:
        wheel_speed_const = int(wheel_speed_const)
        assert wheel_speed_const >= 200 and wheel_speed_const <= 500
        patcher.wheel_speed_const(wheel_speed_const)

    # make zip file for firmware
    zip_buffer = io.BytesIO()
    zip_file = zipfile.ZipFile(zip_buffer, 'a', zipfile.ZIP_DEFLATED, False)

    zip_file.writestr('FIRM.bin', patcher.data)
    md5 = hashlib.md5()
    md5.update(patcher.data)

    patcher.encrypt()
    zip_file.writestr('FIRM.bin.enc', patcher.data)
    md5e = hashlib.md5()
    md5e.update(patcher.data)

    info_txt = 'dev: M365;\nnam: {};\nenc: B;\ntyp: DRV;\nmd5: {};\nmd5e: {};\n'.format(
        version, md5.hexdigest(), md5e.hexdigest())

    zip_file.writestr('info.txt', info_txt.encode())
    zip_file.comment = flask.request.url.encode()
    zip_file.close()
    zip_buffer.seek(0)
    content = zip_buffer.getvalue()
    zip_buffer.close()

    resp = flask.Response(content)
    filename = version + '-' + str(int(time.time())) + '.zip'
    resp.headers['Content-Type'] = 'application/zip'
    resp.headers['Content-Disposition'] = 'inline; filename="{0}"'.format(
        filename)
    resp.headers['Content-Length'] = len(content)

    return resp
Exemplo n.º 4
0
def patch_firmware():
    version = flask.request.args.get('version', None)
    if version not in [
            'DRV130', 'DRV134', 'DRV138', 'DRV140', 'DRV141', 'DRV142',
            'DRV143'
    ]:
        return 'Invalid firmware version.', 400

    with open('../bins/{}.bin'.format(version), 'rb') as fp:
        patcher = FirmwarePatcher(fp.read())

    filename = version + '-' + str(int(time.time()))
    iversion = int(version[3:])

    kers_min_speed = flask.request.args.get('kers_min_speed', None)
    if kers_min_speed is not None:
        kers_min_speed = float(kers_min_speed)
        assert kers_min_speed >= 0 and kers_min_speed <= 100
        patcher.kers_min_speed(kers_min_speed)

    normal_max_speed = flask.request.args.get('normal_max_speed', None)
    if normal_max_speed is not None:
        normal_max_speed = int(normal_max_speed)
        assert normal_max_speed >= 0 and normal_max_speed <= 100
        patcher.normal_max_speed(normal_max_speed)

    eco_max_speed = flask.request.args.get('eco_max_speed', None)
    if eco_max_speed is not None:
        eco_max_speed = int(eco_max_speed)
        assert eco_max_speed >= 0 and eco_max_speed <= 100
        patcher.eco_max_speed(eco_max_speed)

    motor_start_speed = flask.request.args.get('motor_start_speed', None)
    if motor_start_speed is not None:
        motor_start_speed = float(motor_start_speed)
        assert motor_start_speed >= 0 and motor_start_speed <= 100
        patcher.motor_start_speed(motor_start_speed)

    motor_power_constant = flask.request.args.get('motor_power_constant', None)
    if motor_power_constant is not None:
        motor_power_constant = int(motor_power_constant)
        assert motor_power_constant >= 25787 and motor_power_constant <= 65535
        patcher.motor_power_constant(motor_power_constant)

    cruise_control_delay = flask.request.args.get('cruise_control_delay', None)
    if cruise_control_delay is not None:
        cruise_control_delay = float(cruise_control_delay)
        assert cruise_control_delay >= 0.1 and cruise_control_delay <= 20.0
        patcher.cruise_control_delay(cruise_control_delay)

    instant_eco_switch = flask.request.args.get('instant_eco_switch', None)
    if instant_eco_switch:
        patcher.instant_eco_switch()

    boot_with_eco = flask.request.args.get('boot_with_eco', None)
    if boot_with_eco:
        patcher.boot_with_eco()

    voltage_limit = flask.request.args.get('voltage_limit', None)
    if voltage_limit is not None:
        voltage_limit = float(voltage_limit)
        assert voltage_limit >= 43.01 and voltage_limit <= 63.00
        patcher.voltage_limit(voltage_limit)

    russian_throttle = flask.request.args.get('russian_throttle', None)
    if russian_throttle:
        patcher.russian_throttle()

    remove_hard_speed_limit = flask.request.args.get('remove_hard_speed_limit',
                                                     None)
    if remove_hard_speed_limit:
        patcher.remove_hard_speed_limit()

    remove_charging_mode = flask.request.args.get('remove_charging_mode', None)
    if remove_charging_mode:
        patcher.remove_charging_mode()

    bms_uart_76800 = flask.request.args.get('bms_uart_76800', None)
    if bms_uart_76800:
        patcher.bms_uart_76800()

    encrypt = flask.request.args.get('encrypt', None)
    if encrypt:
        assert iversion >= 140, 'Flashing encrypted 1.3.x firmware is not supported. Downgrade to 1.4.0 first.'
        patcher.encrypt()
        filename += '.encrypted'

    filename += '.bin'

    resp = flask.Response(patcher.data)
    resp.headers['Content-Type'] = 'application/octet-stream'
    resp.headers['Content-Disposition'] = 'inline; filename="{0}"'.format(
        filename)
    resp.headers['Content-Length'] = len(patcher.data)

    return resp
Exemplo n.º 5
0
def patch_firmware():
    version = flask.request.args.get('version', None)
    if version not in ['DRV126']:
        return 'Invalid firmware version.', 400

    with open('bins/{}.bin'.format(version), 'rb') as fp:
        patcher = FirmwarePatcher(fp.read())

    if ((flask.request.args.get('speed_normal_phase', None) or flask.request.args.get('speed_normal_battery', None)) and flask.request.args.get('motor_power_constant', None)):
        return 'Cannot patch MPC and current at the same time. You gotta make a decision.'

    speed_params = (flask.request.args.get('speed_normal_kmh', None) or flask.request.args.get('speed_normal_phase', None) or flask.request.args.get('speed_normal_battery', None))
    if speed_params:
        speed_normal_kmh = 33
        speed_normal_phase = 55000
        speed_normal_battery = 25000
        if flask.request.args.get('speed_normal_kmh', None):
            speed_normal_kmh = int(flask.request.args.get('speed_normal_kmh', None))
            assert speed_normal_kmh >= 0 and speed_normal_kmh <= 100
        if flask.request.args.get('speed_normal_phase', None):
            speed_normal_phase = int(flask.request.args.get('speed_normal_phase', None))
            assert speed_normal_phase >= 0 and speed_normal_phase <= 65535
        if flask.request.args.get('speed_normal_battery', None):
            speed_normal_battery = int(flask.request.args.get('speed_normal_battery', None))
            assert speed_normal_battery >= 0 and speed_normal_battery <= 65535
        patcher.speed_params(speed_normal_kmh, speed_normal_phase, speed_normal_battery)

    stay_on_locked = flask.request.args.get('stay_on_locked', None)
    if stay_on_locked:
        patcher.stay_on_locked()

    remove_charging_mode = flask.request.args.get('remove_charging_mode', None)
    if remove_charging_mode:
        patcher.remove_charging_mode()

    swd_enable = flask.request.args.get('swd_enable', None)
    if swd_enable:
        patcher.swd_enable()

    bypass_BMS = flask.request.args.get('bypass_BMS', None)
    if bypass_BMS:
        patcher.bypass_BMS()
		
    bms_uart_76800 = flask.request.args.get('bms_uart_76800', None)
    if bms_uart_76800:
        patcher.bms_uart_76800()

    motor_power_constant = flask.request.args.get('motor_power_constant', None)
    if motor_power_constant is not None:
        motor_power_constant = int(motor_power_constant)
        assert motor_power_constant >= 20000 and motor_power_constant <= 65535
        patcher.motor_power_constant(motor_power_constant)

    cruise_control_delay = flask.request.args.get('cruise_control_delay', None)
    if cruise_control_delay is not None:
        cruise_control_delay = int(cruise_control_delay)
        assert cruise_control_delay >= 0 and cruise_control_delay <= 100
        patcher.cruise_control_delay(cruise_control_delay)

    motor_start_speed = flask.request.args.get('motor_start_speed', None)
    if motor_start_speed is not None:
        motor_start_speed = int(motor_start_speed)
        assert motor_start_speed >= 0 and motor_start_speed <= 10
        patcher.motor_start_speed(motor_start_speed)
		
    throttle_alg = flask.request.args.get('throttle_alg', None)
    if throttle_alg:
        patcher.alt_throttle_alg()

    version_spoofing = flask.request.args.get('version_spoofing', None)
    if version_spoofing:
         patcher.version_spoofing()

    output = flask.request.args.get('output', None)
    if output == 'zip' or not output:
        # make zip file for firmware
        zip_buffer = io.BytesIO()
        zip_file = zipfile.ZipFile(zip_buffer, 'a', zipfile.ZIP_DEFLATED, False)

        zip_file.writestr('FIRM.bin', patcher.data)
        md5 = hashlib.md5()
        md5.update(patcher.data)

        patcher.encrypt()
        zip_file.writestr('FIRM.bin.enc', patcher.data)
        md5e = hashlib.md5()
        md5e.update(patcher.data)

        info_txt = 'dev: ES/SNSC;\nnam: {};\nenc: B;\ntyp: DRV;\nmd5: {};\nmd5e: {};\n'.format(
            version, md5.hexdigest(), md5e.hexdigest())

        zip_file.writestr('info.txt', info_txt.encode())
        message = "Downloaded from scooterhacking.org - Share this CFW with the following link : https://max.scooterhacking.org"
        request_url = flask.request.full_path.encode()
        request_url = request_url.decode("utf-8").replace("cfw", "", 1).encode("utf-8")
        zip_file.comment = bytes(message, 'utf-8') + request_url
        zip_file.close()
        zip_buffer.seek(0)
        content = zip_buffer.getvalue()
        zip_buffer.close()

        resp = flask.Response(content)
        filename = version + '-' + str(int(time.time())) + '.zip'
        resp.headers['Content-Type'] = 'application/zip'
        resp.headers['Content-Disposition'] = 'inline; filename="{0}"'.format(filename)
        resp.headers['Content-Length'] = len(content)
    if output == 'bin' or output == 'enc':
        filename = version + '-' + str(int(time.time())) + '.bin'
        if output == 'enc':
            patcher.encrypt()
            filename += '.enc'
        resp = flask.Response(patcher.data)
        resp.headers['Content-Type'] = 'application/octet-stream'
        resp.headers['Content-Disposition'] = 'inline; filename="{0}"'.format(filename)
        resp.headers['Content-Length'] = len(patcher.data)

    return resp
def patch_firmware():
    version = flask.request.args.get('version', None)
    if version not in [
            'DRV130', 'DRV134', 'DRV138', 'DRV140', 'DRV141', 'DRV142',
            'DRV143'
    ]:
        return 'Invalid firmware version.', 400

    with open('../bins/{}.bin'.format(version), 'rb') as fp:
        patcher = FirmwarePatcher(fp.read())

    kers_min_speed = flask.request.args.get('kers_min_speed', None)
    if kers_min_speed is not None:
        kers_min_speed = float(kers_min_speed)
        assert kers_min_speed >= 0 and kers_min_speed <= 100
        patcher.kers_min_speed(kers_min_speed)

    normal_max_speed = flask.request.args.get('normal_max_speed', None)
    if normal_max_speed is not None:
        normal_max_speed = int(normal_max_speed)
        assert normal_max_speed >= 0 and normal_max_speed <= 100
        patcher.normal_max_speed(normal_max_speed)

    eco_max_speed = flask.request.args.get('eco_max_speed', None)
    if eco_max_speed is not None:
        eco_max_speed = int(eco_max_speed)
        assert eco_max_speed >= 0 and eco_max_speed <= 100
        patcher.eco_max_speed(eco_max_speed)

    motor_start_speed = flask.request.args.get('motor_start_speed', None)
    if motor_start_speed is not None:
        motor_start_speed = float(motor_start_speed)
        assert motor_start_speed >= 0 and motor_start_speed <= 100
        patcher.motor_start_speed(motor_start_speed)

    motor_power_constant = flask.request.args.get('motor_power_constant', None)
    if motor_power_constant is not None:
        motor_power_constant = int(motor_power_constant)
        assert motor_power_constant >= 20000 and motor_power_constant <= 65535
        patcher.motor_power_constant(motor_power_constant)

    cruise_control_delay = flask.request.args.get('cruise_control_delay', None)
    if cruise_control_delay is not None:
        cruise_control_delay = float(cruise_control_delay)
        assert cruise_control_delay >= 0.1 and cruise_control_delay <= 20.0
        patcher.cruise_control_delay(cruise_control_delay)

    instant_eco_switch = flask.request.args.get('instant_eco_switch', None)
    if instant_eco_switch:
        patcher.instant_eco_switch()

    boot_with_eco = flask.request.args.get('boot_with_eco', None)
    if boot_with_eco:
        patcher.boot_with_eco()

    voltage_limit = flask.request.args.get('voltage_limit', None)
    if voltage_limit is not None:
        voltage_limit = float(voltage_limit)
        assert voltage_limit >= 43.01 and voltage_limit <= 63.00
        patcher.voltage_limit(voltage_limit)

    russian_throttle = flask.request.args.get('russian_throttle', None)
    if russian_throttle:
        patcher.russian_throttle()

    remove_hard_speed_limit = flask.request.args.get('remove_hard_speed_limit',
                                                     None)
    if remove_hard_speed_limit:
        patcher.remove_hard_speed_limit()

    remove_charging_mode = flask.request.args.get('remove_charging_mode', None)
    if remove_charging_mode:
        patcher.remove_charging_mode()

    bms_uart_76800 = flask.request.args.get('bms_uart_76800', None)
    if bms_uart_76800:
        patcher.bms_uart_76800()

    # make zip file for firmware
    zip_buffer = io.BytesIO()
    zip_file = zipfile.ZipFile(zip_buffer, 'a', zipfile.ZIP_DEFLATED, False)

    zip_file.writestr('FIRM.bin', patcher.data)
    md5 = hashlib.md5()
    md5.update(patcher.data)

    patcher.encrypt()
    zip_file.writestr('FIRM.bin.enc', patcher.data)
    md5e = hashlib.md5()
    md5e.update(patcher.data)

    info_txt = 'dev: M365;\nnam: {};\nenc: B;\ntyp: DRV;\nmd5: {};\nmd5e: {};\n'.format(
        version, md5.hexdigest(), md5e.hexdigest())

    zip_file.writestr('info.txt', info_txt.encode())
    zip_file.comment = flask.request.url.encode()
    zip_file.close()
    zip_buffer.seek(0)
    content = zip_buffer.getvalue()
    zip_buffer.close()

    resp = flask.Response(content)
    filename = version + '-' + str(int(time.time())) + '.zip'
    resp.headers['Content-Type'] = 'application/zip'
    resp.headers['Content-Disposition'] = 'inline; filename="{0}"'.format(
        filename)
    resp.headers['Content-Length'] = len(content)

    return resp