Example #1
0
    def changesn(self, new_sn):
        from py9b.command.mfg import WriteSN, CalcSNAuth

        tran = self.conn._tran
        old_sn = tran.execute(ReadRegs(BT.ESC, 0x10, "14s"))[0].decode()
        tprint("Old S/N:", old_sn)

        uid3 = tran.execute(ReadRegs(BT.ESC, 0xDE, "<L"))[0]
        tprint("UID3: %08X" % (uid3))

        auth = CalcSnAuth(old_sn, new_sn, uid3)
        # auth = 0
        tprint("Auth: %08X" % (auth))

        try:
            tran.execute(WriteSN(BT.ESC, new_sn.encode('utf-8'), auth))
            tprint("OK")
        except LinkTimeoutException:
            tprint("Timeout !")

        # save config and restart
        tran.execute(WriteRegs(BT.ESC, 0x78, "<H", 0x01))
        time.sleep(3)

        old_sn = tran.execute(ReadRegs(BT.ESC, 0x10, "14s"))[0]
        tprint("Current S/N:", old_sn)
Example #2
0
def changesn(ctx, new_sn, device):
    from py9b.command.mfg import WriteSNAuth, CalcSNAuth
    dev = {
        'esc': BT.ESC,
        'bms': BT.BMS,
        'extbms': BT.EXTBMS,
    }[device]
    with ctx.obj as tran:
        old_sn = tran.execute(ReadRegs(dev, 0x10, "14s"))[0].decode()
        print("Old S/N:", old_sn)

        uid3 = tran.execute(ReadRegs(dev, 0xDE, "<L"))[0]
        print("UID3: %08X" % (uid3))

        auth = CalcSnAuth(old_sn, new_sn, uid3)
        # auth = 0
        print("Auth: %08X" % (auth))

        try:
            tran.execute(WriteSNAuth(dev, new_sn.encode('utf-8'), auth))
            print("OK")
        except LinkTimeoutException:
            print("Timeout !")

        # save config and restart
        tran.execute(WriteRegs(BT.ESC, 0x78, "<H", 0x01))
        time.sleep(3)

        old_sn = tran.execute(ReadRegs(dev, 0x10, "14s"))[0]
        print("Current S/N:", old_sn)
Example #3
0
    def UpdateFirmware(self, tran, dev, fwfile):
        tprint('update started')

        tprint('flashing ' + self.fwfilep + ' to ' + self.device)
        fwfile.seek(0, os.SEEK_END)
        fw_size = fwfile.tell()
        fwfile.seek(0)
        fw_page_size = 0x80

        dev = self.devices.get(self.device)

        for retry in range(self.PING_RETRIES):
            tprint('Pinging...')
            try:
                if dev == BT.BLE:
                    tran.execute(ReadRegs(dev, 0, "13s"))
                else:
                    tran.execute(ReadRegs(dev, 0x10, "14s"))
            except LinkTimeoutException:
                continue
            break
        else:
            tprint("Timed out!")
            return False
        tprint("OK")

        if self.lock:
            tprint('Locking...')
            tran.execute(WriteRegs(BT.ESC, 0x70, '<H', 0x0001))
        else:
            tprint('Not Locking...')

        tprint('Starting...')
        tran.execute(StartUpdate(dev, fw_size))

        tprint('Writing...')

        page = 0
        chk = 0
        while fw_size:
            self.update_progress(page, fw_size // fw_page_size + 1)
            chunk_sz = min(fw_size, fw_page_size)
            data = fwfile.read(chunk_sz)
            chk = self.checksum(chk, data)
            tran.execute(
                WriteUpdate(dev, page,
                            data + b'\x00' * (fw_page_size - chunk_sz)))
            page += 1
            fw_size -= chunk_sz

        tprint('Finalizing...')
        tran.execute(FinishUpdate(dev, chk ^ 0xFFFFFFFF))

        tprint('Reboot')
        tran.execute(RebootUpdate(dev))
        tprint('Done')
        tprint('update finished')
        return True
Example #4
0
def bms_info(tran, dev):
    print('BMS S/N:         %s' % tran.execute(ReadRegs(dev, 0x10, "14s"))[0].decode())
    print_reg(tran, 'BMS Version:     %04x', 0x17, "<H", dev=dev)
    print_reg(tran, 'BMS charge:      %d%%', 0x32, "<H", dev=dev)
    print_reg(tran, 'BMS full cycles: %d', 0x1b, "<H", dev=dev)
    print_reg(tran, 'BMS charges:     %d', 0x1c, "<H", dev=dev)
    print_reg(tran, 'BMS health:      %d%%', 0x3b, "<H", dev=dev)
    print('BMS current:     %.2fA' % (tran.execute(ReadRegs(dev, 0x33, "<h"))[0] / 100.0,))
    print('BMS voltage:     %.2fV' % (tran.execute(ReadRegs(dev, 0x34, "<h"))[0] / 100.0,))
Example #5
0
def UpdateFirmware(link, tran, dev, fwfile):
    fwfile.seek(0, os.SEEK_END)
    fw_size = fwfile.tell()
    fwfile.seek(0)
    fw_page_size = 0x80

    print("Pinging...", end="")
    for retry in range(PING_RETRIES):
        print(".", end="")
        try:
            if dev == BT.BLE:
                tran.execute(ReadRegs(dev, 0, "13s"))
            else:
                tran.execute(ReadRegs(dev, 0x10, "14s"))
        except LinkTimeoutException:
            continue
        break
    else:
        print("Timed out !")
        return False
    print("OK")

    if args.interface != "blefleet":
        print("Locking...")
        tran.execute(WriteRegs(BT.ESC, 0x70, "<H", 0x0001))
    else:
        print("Not Locking...")

    print("Starting...")
    tran.execute(StartUpdate(dev, fw_size))

    print("Writing...")
    pb = ProgressBar(maxval=fw_size // fw_page_size + 1).start()
    page = 0
    chk = 0
    while fw_size:
        pb.update(page)
        chunk_sz = min(fw_size, fw_page_size)
        data = fwfile.read(chunk_sz)
        chk = checksum(chk, data)
        # tran.execute(WriteUpdate(dev, page, data))
        tran.execute(
            WriteUpdate(dev, page, data + b"\x00" * (fw_page_size - chunk_sz))
        )  # TODO: Ninebot wants this padding. Will it work on M365 too?
        page += 1
        fw_size -= chunk_sz
    pb.finish()

    print("Finalizing...")
    tran.execute(FinishUpdate(dev, chk ^ 0xFFFFFFFF))

    print("Reboot")
    tran.execute(RebootUpdate(dev))
    print("Done")
    return True
Example #6
0
    def UpdateFirmware(self, link, tran, dev, fwfile):
        print('flashing ' + fwfilep + ' to ' + self.device)
        fwfile.seek(0, os.SEEK_END)
        fw_size = fwfile.tell()
        fwfile.seek(0)
        fw_page_size = 0x80

        dev = self.devices.get(self.device)
        print('Pinging...')
        for retry in range(PING_RETRIES):
            print('.')
            try:
                if dev == BT.BLE:
                    tran.execute(ReadRegs(dev, 0, '13s'))
                else:
                    tran.execute(ReadRegs(dev, 0x10, '14s'))
            except LinkTimeoutException:
                continue
            break
        else:
            print('Timed out !')
            return False
        print('OK')

        if self.interface != 'tcpnl':
            print('Locking...')
            tran.execute(WriteRegs(BT.ESC, 0x70, '<H', 0x0001))
        else:
            print('Not Locking...')

        print('Starting...')
        tran.execute(StartUpdate(dev, fw_size))

        print('Writing...')
        page = 0
        chk = 0
        while fw_size:
            chunk_sz = min(fw_size, fw_page_size)
            data = fwfile.read(chunk_sz)
            chk = checksum(chk, data)
            #tran.execute(WriteUpdate(dev, page, data))
            tran.execute(
                WriteUpdate(dev, page,
                            data + b'\x00' * (fw_page_size - chunk_sz)))
            page += 1
            fw_size -= chunk_sz

        print('Finalizing...')
        tran.execute(FinishUpdate(dev, chk ^ 0xFFFFFFFF))

        print('Reboot')
        tran.execute(RebootUpdate(dev))
        print('Done')
        return True
Example #7
0
def UpdateFirmware(link, tran, dev, fwfile):
    fwfile.seek(0, os.SEEK_END)
    fw_size = fwfile.tell()
    fwfile.seek(0)
    fw_page_size = 0x80

    print('Pinging...', end='')
    for retry in range(PING_RETRIES):
        print('.', end='')
        try:
            if dev == BT.BLE:
                tran.execute(ReadRegs(dev, 0, '13s'))
            else:
                tran.execute(ReadRegs(dev, 0x10, '14s'))
        except LinkTimeoutException:
            continue
        break
    else:
        print('Timed out !')
        return False
    print('OK')

    print('Locking...')
    tran.execute(WriteRegs(BT.ESC, 0x70, '<H', 0x0001))

    print('Starting...')
    tran.execute(StartUpdate(dev, fw_size))

    print('Writing...')
    pb = ProgressBar(maxval=fw_size // fw_page_size + 1).start()
    page = 0
    chk = 0
    while fw_size:
        pb.update(page)
        chunk_sz = min(fw_size, fw_page_size)
        data = fwfile.read(chunk_sz)
        chk = checksum(chk, data)
        #tran.execute(WriteUpdate(dev, page, data))
        tran.execute(
            WriteUpdate(dev, page, data + b'\x00' * (fw_page_size - chunk_sz))
        )  # TODO: Ninebot wants this padding. Will it work on M365 too?
        page += 1
        fw_size -= chunk_sz
    pb.finish()

    print('Finalizing...')
    tran.execute(FinishUpdate(dev, chk ^ 0xFFFFFFFF))

    print('Reboot')
    tran.execute(RebootUpdate(dev))
    print('Done')
    return True
Example #8
0
def info(ctx):
    with ctx.obj as tran:
        print('ESC S/N:       %s' % tran.execute(ReadRegs(BT.ESC, 0x10, "14s"))[0].decode())
        print('ESC PIN:       %s' % tran.execute(ReadRegs(BT.ESC, 0x17, "6s"))[0].decode())
        print()
        print_reg(tran, 'BLE Version:   %04x', 0x68, "<H")
        print_reg(tran, 'ESC Version:   %04x', 0x1A, "<H")
        print()
        print_reg(tran, 'Error code:    %d', 0x1B, "<H")
        print_reg(tran, 'Warning code:  %d', 0x1C, "<H")
        print()
        print('Total mileage: %s' % pp_distance(tran.execute(ReadRegs(BT.ESC, 0x29, "<L"))[0]))
        print('Total runtime: %s' % pp_time(tran.execute(ReadRegs(BT.ESC, 0x32, "<L"))[0]))
        print('Total riding:  %s' % pp_time(tran.execute(ReadRegs(BT.ESC, 0x34, "<L"))[0]))
        print('Chassis temp:  %d°C' % (tran.execute(ReadRegs(BT.ESC, 0x3e, "<H"))[0] / 10.0,))
        print()

        try:
            print(' *** Internal BMS ***')
            bms_info(tran, BT.BMS)
        except Exception as exc:
            print('No internal BMS found', repr(exc))

        print()

        try:
            print(' *** External BMS ***')
            bms_info(tran, BT.EXTBMS)
        except Exception as exc:
            print('No external BMS found', repr(exc))
Example #9
0
def dump(ctx, device):
    dev = {
        'esc': BT.ESC,
        'ble': BT.BLE,
        'bms': BT.BMS,
        'extbms': BT.EXTBMS,
    }[device]
    with ctx.obj as tran:
        for offset in range(256):
            try:
                print('0x%02x: %04x' % (offset, tran.execute(ReadRegs(dev, offset, "<H"))[0]))
            except Exception as exc:
                print('0x%02x: %s' % (offset, exc))
Example #10
0
    def _connect_inner(self, link):
        try:
            if self.address is '':
                ports = link.scan()
                if not link.scanned.is_set():
                    link.scanned.wait(link.timeout)
                if not ports:
                    raise Exception('No devices found')
                if isinstance(ports[0], tuple):
                    self.address = ports[0][1]
                else:
                    self.address = ports[0]
                link.open(self.address)
            elif self.address is not '':
                link.open(self.address)

            transport = None
            if self.transport == 'ninebot':
                from py9b.transport.ninebot import NinebotTransport
                transport = NinebotTransport(link)
            elif self.transport == 'xiaomi':
                from py9b.transport.xiaomi import XiaomiTransport
                transport = XiaomiTransport(link)

                if transport.execute(
                        ReadRegs(BT.ESC, 0x68,
                                 "<H"))[0] > 0x081 and self.link is ('ble'):
                    transport.keys = link.fetch_keys()
                    transport.recover_keys()
                    tprint('Keys recovered')
                    tprint('functionality may be limited for now')

            self._tran = transport
            self._link = link

            if not self._link.connected.is_set():
                self._link.connected.wait(self._link.timeout * 1.5)

            if self._link.connected.is_set():
                self.update_state('connected')
            else:
                self.disconnect()

            return transport

        except Exception as exc:
            self.dispatch('on_error', repr(exc))
            raise exc
Example #11
0
def ReadAllRegs(link, tran, dev, hfo):
    size = 0x200 if dev == BT.ESC else 0x100
    pb = ProgressBar(maxval=size).start()
    for i in xrange(0x0, size, READ_CHUNK_SIZE):
        pb.update(i)
        for retry in xrange(5):
            try:
                data = tran.execute(ReadRegs(dev, i >> 1, "16s"))[0]
            except LinkTimeoutException:
                continue
            break
        else:
            print("No response !")
            return False
        hfo.write(data)
    pb.finish()
    print("OK")
    return True
Example #12
0
    def __enter__(self):
        link = None
        if self.link == 'bleak':
            from py9b.link.bleak import BleakLink
            link = BleakLink()
        elif self.link == 'tcp':
            from py9b.link.tcp import TCPLink
            link = TCPLink()
        elif self.link == 'serial':
            from py9b.link.serial import SerialLink
            link = SerialLink(timeout=1.0)

        link.__enter__()

        if not self.address:
            ports = link.scan()
            if not ports:
                raise Exception('No devices found')
            self.address = ports[0]

        link.open(self.address)

        transport = None
        if self.transport == 'ninebot':
            from py9b.transport.ninebot import NinebotTransport
            transport = NinebotTransport(link)

        elif self.transport == 'xiaomi':
            from py9b.transport.xiaomi import XiaomiTransport
            transport = XiaomiTransport(link)

            if transport.execute(
                    ReadRegs(BT.ESC, 0x68,
                             "<H"))[0] > 0x081 and self.link.startswith('ble'):
                transport.keys = link.fetch_keys_pro()
                transport.recover_keys()
                print('Keys recovered')

        self._transport = transport
        self._link = link

        return transport
Example #13
0
    def _connect_inner(self, link):
        try:
            if not self.address:
                if platform != 'android':
                    ports = link.scan()
                    if not ports:
                        raise Exception('No devices found')
                    if isinstance(ports[0], tuple):
                        self.address = ports[0][1]
                    else:
                        self.address = ports[0]
                link.open(self.address)
            elif self.address:
                link.open(self.address)

            transport = None
            if self.transport == 'ninebot':
                from py9b.transport.ninebot import NinebotTransport
                transport = NinebotTransport(link)
            elif self.transport == 'xiaomi':
                from py9b.transport.xiaomi import XiaomiTransport
                transport = XiaomiTransport(link)

                if transport.execute(
                        ReadRegs(BT.ESC, 0x68,
                                 "<H"))[0] > 0x081 and self.link is ('ble'):
                    transport.keys = link.fetch_keys_pro()
                    transport.recover_keys()
                    tprint('Keys recovered')

            self._tran = transport
            self._link = link

            return transport

        except Exception as exc:
            self.update_state('disconnected')
            self.dispatch('on_error', repr(exc))
            raise exc
Example #14
0
    print("Scanning...")
    ports = link.scan()
    print(ports)

    #tran = XiaomiTransport(link)
    tran = NinebotTransport(link)

    #link.open(("192.168.1.45", 6000))
    link.open(ports[0][1])
    print("Connected")

    print("Pinging...")
    for retry in xrange(20):
        print(".", end="")
        try:
            old_sn = tran.execute(ReadRegs(BT.ESC, 0x10, "14s"))[0]
        except LinkTimeoutException:
            continue
        break
    else:
        exit("Timed out !")
    print("")

    #lock
    #tran.execute(WriteRegs(BT.ESC, 0x70, "<H", 0x01))

    old_sn = tran.execute(ReadRegs(BT.ESC, 0x10, "14s"))[0]
    print("Old S/N:", old_sn)

    uid3 = tran.execute(ReadRegs(BT.ESC, 0xDE, "<L"))[0]
    print("UID3: %08X" % (uid3))
Example #15
0
#link = BLELink()

with link:
	print "Scanning..."
	ports = link.scan()
	print ports

	#tran = XiaomiTransport(link)
	tran = NinebotTransport(link)

	#link.open(("192.168.1.45", 6000))
	link.open(ports[0][1])
	print "Connected"

	hfo = open("EscRegs.bin", "wb")
	for i in xrange(0x0, 0x200, READ_CHUNK_SIZE):
		print ".",
		for retry in xrange(5):
			try:
				data = tran.execute(ReadRegs(BT.ESC, i>>1, "16s"))[0]
			except LinkTimeoutException:
				continue
			break
		else:
			print "No response !"
			break
		hfo.write(data)

	hfo.close()
	link.close()
Example #16
0
 def print_reg(self, tran, desc, reg, format, dev=BT.ESC):
     try:
         data = tran.execute(ReadRegs(dev, reg, format))
         tprint(desc % data)
     except Exception as exc:
         tprint(desc, repr(exc))
Example #17
0
from py9b.transport.xiaomi import XiaomiTransport

from py9b.command.regio import ReadRegs

import time

link = BleakLink()
with link:
    devs = link.scan()
    print(devs)

    tran = XiaomiTransport(link)

    link.open(devs[0])

    data = tran.execute(ReadRegs(BT.ESC, 0x68, "<H"))[0]
    print("BLE version: %04x" % data)

    if data >= 0x81:
        print("Connected, fetching keys...")
        keys = link.fetch_keys()
        tran.keys = keys
        print("keys:", keys)

        # Recover longer keystream
        req = PKT(src=BT.HOST,
                  dst=BT.BMS,
                  cmd=0x01,
                  arg=0x50,
                  data=bytearray([0x20]))
        tran.send(req)
Example #18
0
# from py9b.link.ble import BLELink
from py9b.link.serial import SerialLink
from py9b.transport.base import BaseTransport as BT
from py9b.transport.packet import BasePacket as PKT

# from py9b.transport.xiaomi import XiaomiTransport
from py9b.transport.ninebot import NinebotTransport
from py9b.command.regio import ReadRegs, WriteRegs

# link = SerialLink(dump=True)
link = TCPLink()
# link = BLELink()

with link:
    print("Scanning...")
    ports = link.scan()
    print(ports)

    # tran = XiaomiTransport(link)
    tran = NinebotTransport(link)

    link.open(("127.0.0.20:6000"))
    # 	link.open(ports[0][1])
    print("Connected")

    print("Reading passwd...")
    pwd = tran.execute(ReadRegs(BT.ESC, 0x17, "6s"))
    print("Passwd:", pwd)

    link.close()