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)
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)
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
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,))
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
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
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
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))
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))
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
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
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
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
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))
#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()
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))
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)
# 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()