oyooyo / keyble

Command line tools and library for controlling eqiva eQ-3 Bluetooth smart locks
90 stars 28 forks source link

Help Adding Support for Sherlock #43

Closed wes1993 closed 2 years ago

wes1993 commented 2 years ago

Hello @oyooyo , I have seen your project and hard work and I hope you could help me with my Sherlock Smart Lock. 🤞 Unfortunately the company has died and the app won’t work anymore… :( so I can’t use this smart lock…

I have one smart key that can open the smart lock but I think that from not so much time it will stop to work either, now I ask you if you could help me to decode the logic of my smart lock ad we can add also the compatibility of Sherlock in your library :)

I can connect to the smart lock BLE with Sherlock, I could also see the notification and the write UUID but I don’t know how sould I write to open the door.

i hope in your reply Best regards Stefano

wes1993 commented 2 years ago

I have decompiled the app and here there are some information:

package com.aerolite.sherlockble.bluetooth.bluetooth.impl;

import android.os.Handler;
import android.os.Looper;
import android.support.annotation.Keep;
import android.text.TextUtils;
import android.util.Log;
import com.aerolite.sherlockble.bluetooth.C3980a;
import com.aerolite.sherlockble.bluetooth.bluetooth.C4006a;
import com.aerolite.sherlockble.bluetooth.entities.Command;
import com.aerolite.sherlockble.bluetooth.entities.DeviceStatus;
import com.aerolite.sherlockble.bluetooth.entities.Packet;
import com.aerolite.sherlockble.bluetooth.entities.request.AuthRequest;
import com.aerolite.sherlockble.bluetooth.entities.request.DeleteSKeyRequest;
import com.aerolite.sherlockble.bluetooth.entities.request.InitRequest;
import com.aerolite.sherlockble.bluetooth.entities.request.ResetKeyDisabledRequest;
import com.aerolite.sherlockble.bluetooth.entities.request.ReversedRequest;
import com.aerolite.sherlockble.bluetooth.entities.request.SKeyUpdateRequest;
import com.aerolite.sherlockble.bluetooth.entities.request.SecurityModeRequest;
import com.aerolite.sherlockble.bluetooth.entities.request.SetupRequest;
import com.aerolite.sherlockble.bluetooth.entities.request.TouchBarDisabledRequest;
import com.aerolite.sherlockble.bluetooth.entities.response.AuthResponse;
import com.aerolite.sherlockble.bluetooth.entities.response.BusinessResponse;
import com.aerolite.sherlockble.bluetooth.entities.response.InitResponse;
import com.aerolite.sherlockble.bluetooth.entities.response.SKeyUpdateResponse;
import com.aerolite.sherlockble.bluetooth.entities.response.SetupResponse;
import com.aerolite.sherlockble.bluetooth.enumerations.CommandType;
import com.aerolite.sherlockble.bluetooth.p115a.C3993a;
import com.aerolite.sherlockble.bluetooth.p115a.C3994b;
import com.aerolite.sherlockble.bluetooth.p115a.C3999g;
import com.aerolite.sherlockble.bluetooth.p118c.C4105a;
import com.aerolite.sherlockble.bluetooth.p118c.C4108d;
import com.aerolite.sherlockble.bluetooth.p118c.C4109e;
import com.aerolite.sherlockble.bluetooth.p118c.C4113i;
import com.aerolite.sherlockble.bluetooth.p118c.C4114j;
import com.aerolite.sherlockble.bluetooth.p118c.C4123k;
import com.aerolite.sherlockble.bluetooth.p118c.C4126n;
import com.aerolite.sherlockblenet.p120b.C4132a;
import com.google.gson.C4782e;
import com.inuker.bluetooth.library.connect.options.BleConnectOptions;
import com.inuker.bluetooth.library.connect.p171a.C5227a;
import com.inuker.bluetooth.library.connect.p173c.C5255a;
import com.inuker.bluetooth.library.connect.p173c.C5257c;
import com.inuker.bluetooth.library.connect.p173c.C5262h;
import com.inuker.bluetooth.library.connect.p173c.C5263i;
import com.inuker.bluetooth.library.model.BleGattProfile;
import com.quintic.libota.bleGlobalVariables;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.Queue;
import java.util.UUID;

public class SherlockBluetoothClientManager implements C4006a {

    /* renamed from: a */
    private static final String f21767a = "SherlockBle-S";

    /* renamed from: b */
    private static volatile SherlockBluetoothClientManager f21768b = null;
    /* access modifiers changed from: private */

    /* renamed from: c */
    public static final UUID f21769c = UUID.fromString(bleGlobalVariables.f28661b);

    /* renamed from: d */
    private static final UUID f21770d = UUID.fromString(bleGlobalVariables.f28664e);
    /* access modifiers changed from: private */

    /* renamed from: e */
    public static final UUID f21771e = UUID.fromString("d44bc439-abfd-45a2-b575-925416129601");

    /* renamed from: f */
    private static final int f21772f = 1;

    /* renamed from: g */
    private static final int f21773g = 10000;

    /* renamed from: h */
    private static final int f21774h = 3;

    /* renamed from: i */
    private static final int f21775i = 10000;

    /* renamed from: j */
    private static final int f21776j = 20;

    /* renamed from: k */
    private static final long f21777k = 15000;

    /* renamed from: l */
    private static final long f21778l = 15000;

    /* renamed from: A */
    private int f21779A;

    /* renamed from: B */
    private boolean f21780B;
    /* access modifiers changed from: private */

    /* renamed from: C */
    public long f21781C;
    /* access modifiers changed from: private */

    /* renamed from: D */
    public boolean f21782D;
    /* access modifiers changed from: private */

    /* renamed from: E */
    public long f21783E;
    /* access modifiers changed from: private */

    /* renamed from: F */
    public long f21784F;
    /* access modifiers changed from: private */

    /* renamed from: G */
    public Handler f21785G = new Handler(Looper.getMainLooper());

    /* renamed from: H */
    private C5263i f21786H = new C5263i() {
        /* renamed from: a */
        public void mo18531a(int i) {
            if (i == 0 && SherlockBluetoothClientManager.this.f21798x.peek() != null) {
                SherlockBluetoothClientManager.this.m11265j();
            }
        }
    };

    /* renamed from: m */
    private byte[] f21787m;
    /* access modifiers changed from: private */
    @Keep
    public Runnable mAuthenticateRunnable = new Runnable() {
        public void run() {
            if (!SherlockBluetoothClientManager.this.f21797w && SherlockBluetoothClientManager.this.f21790p != null) {
                SherlockBluetoothClientManager.this.f21790p.mo18479c();
            }
        }
    };
    @Keep
    C5227a mConnectStatusListener = new C5227a() {
        /* renamed from: a */
        public void mo18487a(String str, int i) {
            boolean unused = SherlockBluetoothClientManager.this.f21796v = i == 16;
            if (SherlockBluetoothClientManager.this.f21796v) {
                long unused2 = SherlockBluetoothClientManager.this.f21783E = System.currentTimeMillis();
            } else {
                long unused3 = SherlockBluetoothClientManager.this.f21784F = System.currentTimeMillis();
            }
            Log.d(SherlockBluetoothClientManager.f21767a, "onConnectStatusChanged: mConnected: " + SherlockBluetoothClientManager.this.f21796v + "mConnectRetry: " + SherlockBluetoothClientManager.this.f21795u + "mInitiativeDisconnect: " + SherlockBluetoothClientManager.this.f21782D);
            SherlockBluetoothClientManager.this.m11267k();
            long g = (SherlockBluetoothClientManager.this.f21784F - SherlockBluetoothClientManager.this.f21783E) / 1000;
            StringBuilder sb = new StringBuilder();
            sb.append("onConnectStatusChanged: connectedTime");
            sb.append(g);
            Log.d(SherlockBluetoothClientManager.f21767a, sb.toString());
            if (!SherlockBluetoothClientManager.this.f21796v) {
                SherlockBluetoothClientManager.m11262i(SherlockBluetoothClientManager.this);
                if (SherlockBluetoothClientManager.this.f21795u > 1) {
                    Log.e(SherlockBluetoothClientManager.f21767a, "onConnectStatusChanged max retry");
                    if (SherlockBluetoothClientManager.this.f21782D) {
                        boolean unused4 = SherlockBluetoothClientManager.this.f21782D = false;
                        return;
                    }
                    SherlockBluetoothClientManager.this.mo18494b(str);
                    if (SherlockBluetoothClientManager.this.f21790p != null) {
                        SherlockBluetoothClientManager.this.f21790p.mo18477a(SherlockBluetoothClientManager.this.f21796v);
                    }
                }
            } else if (SherlockBluetoothClientManager.this.f21782D) {
                boolean unused5 = SherlockBluetoothClientManager.this.f21782D = false;
            } else if ((g < 29 || g > 31) && SherlockBluetoothClientManager.this.f21790p != null) {
                SherlockBluetoothClientManager.this.f21790p.mo18477a(SherlockBluetoothClientManager.this.f21796v);
            }
        }
    };
    @Keep
    Handler mReceiveHandler = new Handler(Looper.getMainLooper());
    @Keep
    Runnable mReceiveRunnable = new Runnable() {
        public void run() {
            if (System.currentTimeMillis() - SherlockBluetoothClientManager.this.f21781C > 15000) {
                SherlockBluetoothClientManager.this.m11267k();
                SherlockBluetoothClientManager.this.m11271m();
                if (SherlockBluetoothClientManager.this.f21793s instanceof SetupRequest) {
                    if (SherlockBluetoothClientManager.this.f21791q != null) {
                        SherlockBluetoothClientManager.this.f21791q.mo18484a();
                    }
                } else if (SherlockBluetoothClientManager.this.f21792r != null) {
                    SherlockBluetoothClientManager.this.f21792r.mo18471a();
                }
            } else {
                SherlockBluetoothClientManager.this.mReceiveHandler.postDelayed(this, 1000);
            }
        }
    };

    /* renamed from: n */
    private byte[] f21788n;

    /* renamed from: o */
    private byte[] f21789o;
    /* access modifiers changed from: private */

    /* renamed from: p */
    public C3994b f21790p;
    /* access modifiers changed from: private */

    /* renamed from: q */
    public C3999g f21791q;
    /* access modifiers changed from: private */

    /* renamed from: r */
    public C3993a f21792r;
    /* access modifiers changed from: private */

    /* renamed from: s */
    public Command f21793s;

    /* renamed from: t */
    private String f21794t;
    /* access modifiers changed from: private */

    /* renamed from: u */
    public int f21795u;
    /* access modifiers changed from: private */

    /* renamed from: v */
    public boolean f21796v;
    /* access modifiers changed from: private */

    /* renamed from: w */
    public boolean f21797w;
    /* access modifiers changed from: private */

    /* renamed from: x */
    public Queue<byte[]> f21798x = new LinkedList();

    /* renamed from: y */
    private byte[] f21799y = null;

    /* renamed from: z */
    private int f21800z;

    /* renamed from: i */
    static /* synthetic */ int m11262i(SherlockBluetoothClientManager sherlockBluetoothClientManager) {
        int i = sherlockBluetoothClientManager.f21795u;
        sherlockBluetoothClientManager.f21795u = i + 1;
        return i;
    }

    private SherlockBluetoothClientManager() {
        if (f21768b != null) {
            throw new IllegalStateException("Already initialized.");
        }
    }

    /* renamed from: d */
    public static SherlockBluetoothClientManager m11254d() {
        SherlockBluetoothClientManager sherlockBluetoothClientManager = f21768b;
        if (sherlockBluetoothClientManager == null) {
            synchronized (SherlockBluetoothClientManager.class) {
                sherlockBluetoothClientManager = f21768b;
                if (sherlockBluetoothClientManager == null) {
                    sherlockBluetoothClientManager = new SherlockBluetoothClientManager();
                    f21768b = sherlockBluetoothClientManager;
                }
            }
        }
        return sherlockBluetoothClientManager;
    }

    /* renamed from: a */
    public void mo18489a(String str) {
        if (!TextUtils.isEmpty(str)) {
            this.f21788n = C4113i.m11692a((CharSequence) str);
        } else {
            this.f21788n = null;
        }
    }

    /* renamed from: a */
    public boolean mo18491a() {
        return this.f21796v;
    }

    /* renamed from: b */
    public boolean mo18495b() {
        return this.f21797w;
    }

    /* renamed from: a */
    public void mo18490a(String str, final C3994b bVar) {
        BleConnectOptions a = new BleConnectOptions.C5271a().mo23818a(1).mo23821c(10000).mo23820b(3).mo23822d(10000).mo23819a();
        this.f21795u = 0;
        this.f21782D = false;
        this.f21797w = false;
        this.f21794t = str;
        this.f21790p = bVar;
        C4021a.m11295a().mo23638a(str, this.mConnectStatusListener);
        C4021a.m11295a().mo23641a(str, a, new C5255a() {
            /* renamed from: a */
            public void mo18530a(int i, BleGattProfile bleGattProfile) {
                Log.d(SherlockBluetoothClientManager.f21767a, "connectDevice onResponse mConnectRetry:" + SherlockBluetoothClientManager.this.f21795u + ", code:" + i + ", profile:" + new C4782e().mo22571b((Object) bleGattProfile));
                if (i == 0) {
                    if (!SherlockBluetoothClientManager.this.f21797w) {
                        SherlockBluetoothClientManager.this.f21785G.postDelayed(SherlockBluetoothClientManager.this.mAuthenticateRunnable, 15000);
                    }
                    SherlockBluetoothClientManager.this.m11263i();
                } else if (i == -1) {
                    bVar.mo18474a();
                }
            }
        });
    }

    /* renamed from: c */
    public void mo18496c() {
        mo18494b(this.f21794t);
    }

    /* renamed from: b */
    public void mo18494b(String str) {
        Log.d(f21767a, "disconnectDevice: " + str);
        if (!TextUtils.isEmpty(str)) {
            this.f21782D = true;
            m11271m();
            mo18526e();
            this.f21785G.removeCallbacks(this.mAuthenticateRunnable);
            this.mReceiveHandler.removeCallbacks(this.mReceiveRunnable);
            C4021a.m11295a().mo23636a(str);
            C4021a.m11295a().mo23651b(str, this.mConnectStatusListener);
            C4021a.m11295a().mo23637a(str, 0);
            this.f21796v = false;
            this.f21797w = false;
            this.f21790p = null;
        }
    }

    /* access modifiers changed from: private */
    /* renamed from: i */
    public void m11263i() {
        C4021a.m11295a().mo23642a(this.f21794t, f21769c, f21771e, (C5257c) new C5257c() {
            /* renamed from: a */
            public void mo18532a(UUID uuid, UUID uuid2, byte[] bArr) {
                Log.d(SherlockBluetoothClientManager.f21767a, "onNotify: " + C4113i.m11688a(bArr));
                if (uuid.equals(SherlockBluetoothClientManager.f21769c) && uuid2.equals(SherlockBluetoothClientManager.f21771e)) {
                    Log.d(SherlockBluetoothClientManager.f21767a, "onNotifyNeed: " + C4113i.m11688a(bArr));
                    SherlockBluetoothClientManager.this.m11249b(bArr);
                }
            }

            /* renamed from: a */
            public void mo18531a(int i) {
                Log.d(SherlockBluetoothClientManager.f21767a, "onResponse: " + i);
            }
        });
    }

    /* renamed from: e */
    public void mo18526e() {
        C4021a.m11295a().mo23644a(this.f21794t, f21769c, f21771e, (C5262h) new C5262h() {
            /* renamed from: a */
            public void mo18531a(int i) {
                Log.d(SherlockBluetoothClientManager.f21767a, "unNotifyDevice onResponse:  " + i);
            }
        });
    }

    /* renamed from: a */
    public boolean mo18493a(SetupRequest setupRequest, C3999g gVar) {
        this.f21791q = gVar;
        return m11244a((Command) setupRequest);
    }

    /* renamed from: a */
    public boolean mo18492a(Command command, C3993a aVar) {
        this.f21792r = aVar;
        return m11244a(command);
    }

    /* renamed from: a */
    private boolean m11244a(Command command) {
        C4114j.m11722b(C4132a.m11816a().mo22571b((Object) command));
        this.f21793s = command;
        if (!this.f21796v) {
            Log.e(f21767a, "Please connect device first ");
            return false;
        }
        byte[] bArr = null;
        CommandType commandType = command.getCommandType();
        int currentTimeMillis = (int) (System.currentTimeMillis() / 1000);
        if (commandType == CommandType.Setup) {
            SetupRequest setupRequest = (SetupRequest) command;
            this.f21787m = setupRequest.getSetupKeyData();
            this.f21788n = setupRequest.getAuthKeyData();
            if (this.f21787m == null || this.f21788n == null) {
                Log.e(f21767a, "setup request requires setup key and auth key");
                return false;
            }
            byte[] a = C4109e.m11659a(setupRequest.getMd5DeviceUuidData(), this.f21788n, C4126n.m11801a(16).getBytes());
            C4105a aVar = new C4105a();
            aVar.mo18617c(this.f21787m);
            byte[] a2 = aVar.mo18615a(a);
            Log.d(f21767a, "setup request");
            bArr = Packet.wrap(C3980a.C3986f.f21669i, currentTimeMillis, a2).getBuffer();
        } else if (commandType == CommandType.Auth) {
            AuthResponse authResponse = (AuthResponse) command;
            if (this.f21788n == null) {
                Log.e(f21767a, "auth response requires auth key");
                return false;
            }
            this.f21789o = C4126n.m11801a(16).getBytes();
            byte[] bArr2 = {authResponse.getErrorId(), authResponse.getResponseId()};
            byte[] a3 = C4109e.m11659a(bArr2, this.f21789o, C4126n.m11801a(16).getBytes(), new byte[]{0});
            C4105a aVar2 = new C4105a();
            aVar2.mo18617c(this.f21788n);
            byte[] a4 = aVar2.mo18615a(a3);
            Log.d(f21767a, "auth response");
            bArr = Packet.wrap(C3980a.C3986f.f21664d, currentTimeMillis, a4).getBuffer();
        } else if (commandType == CommandType.Init) {
            InitResponse initResponse = (InitResponse) command;
            byte[] challengeAnswerData = initResponse.getChallengeAnswerData();
            byte[] a5 = C4109e.m11659a(new byte[]{initResponse.getErrorId(), initResponse.getResponseId()}, challengeAnswerData);
            C4105a aVar3 = new C4105a();
            aVar3.mo18617c(this.f21789o);
            byte[] a6 = aVar3.mo18615a(a5);
            Log.d(f21767a, "init response");
            bArr = Packet.wrap(C3980a.C3986f.f21666f, currentTimeMillis, a6).getBuffer();
        } else if (commandType == CommandType.SKeyUpdate) {
            SKeyUpdateResponse sKeyUpdateResponse = (SKeyUpdateResponse) command;
            byte[] challengeAnswerData2 = sKeyUpdateResponse.getChallengeAnswerData();
            byte[] a7 = C4109e.m11659a(new byte[]{sKeyUpdateResponse.getErrorId(), sKeyUpdateResponse.getResponseId()}, challengeAnswerData2);
            C4105a aVar4 = new C4105a();
            aVar4.mo18617c(this.f21789o);
            byte[] a8 = aVar4.mo18615a(a7);
            Log.d(f21767a, "smart key update response");
            bArr = Packet.wrap(C3980a.C3986f.f21672l, currentTimeMillis, a8).getBuffer();
        } else if (commandType == CommandType.Lock) {
            bArr = m11245a(currentTimeMillis, (byte) 2);
        } else if (commandType == CommandType.Unlock) {
            bArr = m11245a(currentTimeMillis, (byte) 1);
        } else if (commandType == CommandType.DeviceUnbindAccessories) {
            bArr = m11245a(currentTimeMillis, (byte) C3980a.C3983c.f21640v);
        } else if (commandType == CommandType.TrimSave) {
            bArr = m11245a(currentTimeMillis, (byte) 3);
        } else if (commandType == CommandType.Trim) {
            bArr = m11245a(currentTimeMillis, (byte) 4);
        } else if (commandType == CommandType.FactoryReset) {
            bArr = m11245a(currentTimeMillis, (byte) 5);
        } else if (commandType == CommandType.Reboot) {
            bArr = m11245a(currentTimeMillis, (byte) 6);
        } else if (commandType == CommandType.AddSKey) {
            bArr = m11245a(currentTimeMillis, (byte) 7);
        } else if (commandType == CommandType.DeleteSKey) {
            bArr = m11246a(currentTimeMillis, (byte) 8, ((DeleteSKeyRequest) command).getAddressData());
        } else if (commandType == CommandType.SecurityMode) {
            bArr = m11246a(currentTimeMillis, (byte) 9, new byte[]{((SecurityModeRequest) command).getValue()});
        } else if (commandType == CommandType.Reversed) {
            bArr = m11246a(currentTimeMillis, (byte) 11, new byte[]{((ReversedRequest) command).getValue()});
        } else if (commandType == CommandType.TouchBarDisabled) {
            bArr = m11246a(currentTimeMillis, (byte) 15, new byte[]{((TouchBarDisabledRequest) command).getValue()});
        } else if (commandType == CommandType.ResetKeyDisabled) {
            bArr = m11246a(currentTimeMillis, C3980a.C3983c.f21636r, new byte[]{((ResetKeyDisabledRequest) command).getValue()});
        }
        if (bArr == null || bArr.length == 0) {
            Log.e(f21767a, "no data to send");
            return false;
        }
        m11241a(bArr);
        m11267k();
        if (!(commandType == CommandType.Auth || commandType == CommandType.Init || commandType == CommandType.SKeyUpdate)) {
            m11268l();
        }
        return true;
    }

    /* renamed from: a */
    private byte[] m11245a(int i, byte b) {
        return m11246a(i, b, new byte[0]);
    }

    /* renamed from: a */
    private byte[] m11246a(int i, byte b, byte[] bArr) {
        if (this.f21789o == null) {
            Log.e(f21767a, "business request requires session key");
            return null;
        }
        byte[] a = C4109e.m11659a(new byte[]{b}, bArr);
        C4105a aVar = new C4105a();
        aVar.mo18617c(this.f21789o);
        byte[] a2 = aVar.mo18615a(a);
        Log.d(f21767a, "businessId hex string:" + C4113i.m11685a((long) b));
        return Packet.wrap(C3980a.C3986f.f21667g, i, a2).getBuffer();
    }

    /* renamed from: a */
    private void m11241a(byte[] bArr) {
        this.f21798x.clear();
        this.f21798x = m11236a(bArr, 20);
        Log.d(f21767a, "send data queue size:" + this.f21798x.size());
        m11265j();
    }

    /* access modifiers changed from: private */
    /* renamed from: j */
    public void m11265j() {
        if (this.f21798x != null && !this.f21798x.isEmpty() && this.f21798x.peek() != null) {
            byte[] poll = this.f21798x.poll();
            Log.d(f21767a, "send data:" + C4113i.m11688a(poll));
            C4021a.m11295a().mo23647a(this.f21794t, f21769c, f21770d, poll, this.f21786H);
        }
    }

    /* renamed from: a */
    private Queue<byte[]> m11236a(byte[] bArr, int i) {
        byte[] bArr2;
        LinkedList linkedList = new LinkedList();
        if (bArr == null || i <= 0) {
            return linkedList;
        }
        int i2 = 0;
        do {
            byte[] bArr3 = new byte[(bArr.length - i2)];
            System.arraycopy(bArr, i2, bArr3, 0, bArr.length - i2);
            if (bArr3.length <= i) {
                bArr2 = new byte[bArr3.length];
                System.arraycopy(bArr3, 0, bArr2, 0, bArr3.length);
                i2 += bArr3.length;
            } else {
                bArr2 = new byte[i];
                System.arraycopy(bArr, i2, bArr2, 0, i);
                i2 += i;
            }
            linkedList.offer(bArr2);
        } while (i2 < bArr.length);
        return linkedList;
    }

    /* access modifiers changed from: private */
    /* renamed from: k */
    public void m11267k() {
        this.f21799y = null;
        this.f21800z = 0;
        this.f21779A = 0;
    }

    /* renamed from: l */
    private void m11268l() {
        if (!this.f21780B) {
            this.f21780B = true;
            this.f21781C = System.currentTimeMillis();
            this.mReceiveHandler.postDelayed(this.mReceiveRunnable, 1000);
        }
    }

    /* access modifiers changed from: private */
    /* renamed from: m */
    public void m11271m() {
        this.f21780B = false;
        this.mReceiveHandler.removeCallbacks(this.mReceiveRunnable);
    }

    /* access modifiers changed from: private */
    /* renamed from: b */
    public void m11249b(byte[] bArr) {
        if (bArr == null || bArr.length == 0) {
            Log.e(f21767a, "no data to receive");
            return;
        }
        this.f21781C = System.currentTimeMillis();
        if (this.f21799y != null) {
            Log.d(f21767a, "received mReceiveData.length:" + this.f21799y.length + ", mReceiveOffset:" + this.f21779A + ", mReceiveLength:" + this.f21800z + ", data.length:" + bArr.length);
            int length = bArr.length;
            if (this.f21779A + bArr.length > this.f21799y.length) {
                length = this.f21799y.length - this.f21779A;
            }
            System.arraycopy(bArr, 0, this.f21799y, this.f21779A, length);
            this.f21779A += bArr.length;
            Log.d(f21767a, "received " + this.f21779A + "/" + this.f21800z);
        } else if (bArr[0] != -17 || bArr.length < 10) {
            Log.d(f21767a, "receiveData: invalid data");
        } else {
            byte b = bArr[1];
            byte[] bArr2 = new byte[2];
            System.arraycopy(bArr, 2, new byte[2], 0, 2);
            System.arraycopy(bArr, 4, new byte[4], 0, 4);
            System.arraycopy(bArr, 8, bArr2, 0, 2);
            this.f21800z = C4109e.m11662b(bArr2, false);
            this.f21799y = new byte[this.f21800z];
            this.f21779A += bArr.length;
            System.arraycopy(bArr, 0, this.f21799y, 0, bArr.length);
            Log.d(f21767a, "receive header");
        }
        if (this.f21779A >= this.f21800z && this.f21800z > 0) {
            m11271m();
            m11255d(this.f21799y);
            byte[] bArr3 = new byte[2];
            byte[] bArr4 = new byte[4];
            byte[] bArr5 = new byte[(this.f21800z - 11)];
            System.arraycopy(this.f21799y, 2, bArr3, 0, 2);
            System.arraycopy(this.f21799y, 4, bArr4, 0, 4);
            System.arraycopy(this.f21799y, 10, bArr5, 0, bArr5.length);
            m11267k();
            int b2 = C4109e.m11662b(bArr3, false);
            C4109e.m11662b(bArr4, false);
            if (b2 == 29999) {
                Log.e(f21767a, "received decode error response");
                if (this.f21792r != null) {
                    this.f21792r.mo18473b();
                }
                mo18494b(this.f21794t);
            } else if (b2 == 20011) {
                Log.d(f21767a, "received setup response");
                if (this.f21787m != null) {
                    C4105a aVar = new C4105a();
                    aVar.mo18617c(this.f21787m);
                    byte[] b3 = aVar.mo18616b(bArr5);
                    if (b3 == null || b3.length < 2) {
                        Log.e(f21767a, "decode error or received invalid data");
                        if (this.f21791q != null) {
                            this.f21791q.mo18486b();
                        }
                        mo18494b(this.f21794t);
                        return;
                    }
                    byte b4 = b3[0];
                    byte b5 = b3[1];
                    byte[] bArr6 = new byte[16];
                    byte[] bArr7 = new byte[24];
                    if (b4 == 0 && b5 == 0 && b3.length >= 42) {
                        System.arraycopy(b3, 2, bArr6, 0, 16);
                        System.arraycopy(b3, 18, bArr7, 0, 24);
                    }
                    if (this.f21791q != null) {
                        this.f21791q.mo18485a(new SetupResponse(b4, b5, bArr6, bArr7));
                        return;
                    }
                    return;
                }
                Log.e(f21767a, "setupKey is null");
                mo18494b(this.f21794t);
            } else if (b2 == 10001) {
                Log.d(f21767a, "received auth request");
                if (this.f21788n != null) {
                    C4105a aVar2 = new C4105a();
                    aVar2.mo18617c(this.f21788n);
                    byte[] b6 = aVar2.mo18616b(bArr5);
                    if (b6 == null || b6.length < 22) {
                        Log.e(f21767a, "decode error or received invalid data");
                        if (this.f21790p != null) {
                            this.f21790p.mo18478b();
                        }
                        mo18494b(this.f21794t);
                        return;
                    }
                    byte[] bArr8 = new byte[6];
                    byte[] bArr9 = new byte[16];
                    System.arraycopy(b6, 0, bArr8, 0, 6);
                    System.arraycopy(b6, 6, bArr9, 0, 16);
                    m11238a(new AuthRequest(bArr8, bArr9));
                    return;
                }
                Log.e(f21767a, "authKey is null");
                mo18494b(this.f21794t);
            } else if (b2 == 10003) {
                Log.d(f21767a, "received init request");
                if (this.f21789o != null) {
                    C4105a aVar3 = new C4105a();
                    aVar3.mo18617c(this.f21789o);
                    byte[] b7 = aVar3.mo18616b(bArr5);
                    if (b7 == null || b7.length < 4) {
                        Log.e(f21767a, "decode error or received invalid data");
                        if (this.f21790p != null) {
                            this.f21790p.mo18478b();
                        }
                        mo18494b(this.f21794t);
                        return;
                    }
                    byte[] bArr10 = new byte[4];
                    byte[] bArr11 = new byte[(b7.length - 4)];
                    System.arraycopy(b7, 0, bArr10, 0, 4);
                    System.arraycopy(b7, 4, bArr11, 0, bArr11.length);
                    m11239a(new InitRequest(bArr10, m11251c(bArr11)));
                    return;
                }
                Log.e(f21767a, "sessionKey is null");
                mo18494b(this.f21794t);
            } else if (b2 == 10013) {
                Log.d(f21767a, "received skey update request");
                if (this.f21789o != null) {
                    C4105a aVar4 = new C4105a();
                    aVar4.mo18617c(this.f21789o);
                    byte[] b8 = aVar4.mo18616b(bArr5);
                    if (b8 != null) {
                        int i = 5;
                        if (b8.length >= 5) {
                            byte[] bArr12 = new byte[4];
                            byte[] bArr13 = new byte[1];
                            System.arraycopy(b8, 0, bArr12, 0, 4);
                            System.arraycopy(b8, 4, bArr13, 0, 1);
                            int b9 = C4109e.m11662b(bArr13, false);
                            int length2 = b8.length - 5;
                            ArrayList arrayList = new ArrayList();
                            if (b9 > 0 && length2 == b9 * 6) {
                                while (true) {
                                    int i2 = i + 6;
                                    if (i2 > b8.length) {
                                        break;
                                    }
                                    byte[] bArr14 = new byte[6];
                                    System.arraycopy(b8, i, bArr14, 0, 6);
                                    arrayList.add(C4123k.m11788a(bArr14));
                                    i = i2;
                                }
                            }
                            m11240a(new SKeyUpdateRequest(bArr12, arrayList));
                            return;
                        }
                    }
                    Log.e(f21767a, "decode error or received invalid data");
                    if (this.f21790p != null) {
                        this.f21790p.mo18478b();
                    }
                    mo18494b(this.f21794t);
                    return;
                }
                Log.e(f21767a, "sessionKey is null");
                mo18494b(this.f21794t);
            } else if (b2 == 10002) {
                Log.d(f21767a, "received business response");
                if (this.f21789o != null) {
                    C4105a aVar5 = new C4105a();
                    aVar5.mo18617c(this.f21789o);
                    byte[] b10 = aVar5.mo18616b(bArr5);
                    if (b10 == null || b10.length < 3) {
                        Log.e(f21767a, "decode error or received invalid data");
                        if (this.f21792r != null) {
                            this.f21792r.mo18473b();
                        }
                        mo18494b(this.f21794t);
                        return;
                    }
                    byte b11 = b10[0];
                    byte b12 = b10[1];
                    byte b13 = b10[2];
                    if (this.f21792r != null) {
                        this.f21792r.mo18472a(new BusinessResponse(b11, b12, b13));
                        return;
                    }
                    return;
                }
                Log.e(f21767a, "sessionKey is null");
                mo18494b(this.f21794t);
            }
        }
    }

    /* renamed from: a */
    private void m11238a(AuthRequest authRequest) {
        m11244a((Command) new AuthResponse((byte) 0, (byte) 0));
    }

    /* renamed from: a */
    private void m11239a(InitRequest initRequest) {
        m11244a((Command) new InitResponse((byte) 0, (byte) 0, initRequest.getChallengeData()));
        this.f21797w = true;
        if (!(this.f21785G == null || this.mAuthenticateRunnable == null)) {
            this.f21785G.removeCallbacks(this.mAuthenticateRunnable);
        }
        if (this.f21790p != null) {
            this.f21790p.mo18475a(initRequest.getDeviceStatus());
        }
    }

    /* renamed from: a */
    private void m11240a(SKeyUpdateRequest sKeyUpdateRequest) {
        if (this.f21790p != null) {
            this.f21790p.mo18476a(sKeyUpdateRequest);
        }
    }

    /* renamed from: c */
    private DeviceStatus m11251c(byte[] bArr) {
        DeviceStatus deviceStatus = new DeviceStatus();
        int length = bArr.length;
        byte[] bArr2 = new byte[1];
        byte[] bArr3 = new byte[2];
        int i = 0;
        while (true) {
            int i2 = i + 3;
            if (i2 >= length) {
                return deviceStatus;
            }
            System.arraycopy(bArr, i, bArr2, 0, 1);
            System.arraycopy(bArr, i + 1, bArr3, 0, 2);
            int b = C4109e.m11662b(bArr3, false);
            int i3 = i2 + b;
            if (i3 <= length) {
                byte[] bArr4 = new byte[b];
                System.arraycopy(bArr, i2, bArr4, 0, b);
                if (bArr2[0] == 1) {
                    deviceStatus.bound = bArr4[0] == 1;
                } else if (bArr2[0] == 3) {
                    deviceStatus.securityMode = bArr4[0] == 1;
                } else if (bArr2[0] == 4) {
                    deviceStatus.lockCounts = C4109e.m11662b(bArr4, false);
                } else if (bArr2[0] == 5) {
                    deviceStatus.battery = C4109e.m11662b(bArr4, false);
                } else if (bArr2[0] == 6) {
                    deviceStatus.keyPush = bArr4[0] == 1;
                } else if (bArr2[0] == 7) {
                    deviceStatus.keyTurn = bArr4[0] == 1;
                } else if (bArr2[0] == 8) {
                    deviceStatus.firmwareVersion = String.valueOf(C4109e.m11662b(bArr4, false));
                } else if (bArr2[0] == 9) {
                    deviceStatus.reversed = bArr4[0] == 1;
                } else if (bArr2[0] == 12) {
                    deviceStatus.touchBarDisabled = bArr4[0] == 1;
                } else if (bArr2[0] == 15) {
                    deviceStatus.resetKeyDisabled = bArr4[0] == 1;
                }
            }
            i = i3;
        }
    }

    /* renamed from: d */
    private boolean m11255d(byte[] bArr) {
        String replaceAll = C4108d.m11637a(bArr).replaceAll(" ", "");
        return (replaceAll.length() - replaceAll.replaceAll("1", "").length()) % 2 == 1;
    }

    /* renamed from: f */
    public byte[] mo18527f() {
        return this.f21789o;
    }
}

Another File

package com.quintic.libota;

import java.util.UUID;

public class bleGlobalVariables {

    /* renamed from: a */
    public static final String f28660a = "0000fee8-0000-1000-8000-00805f9b34fb";

    /* renamed from: b */
    public static final String f28661b = "0000fee9-0000-1000-8000-00805f9b34fb";

    /* renamed from: c */
    public static final String f28662c = "013784cf-f7e3-55b4-6c4c-9fd140100a16";

    /* renamed from: d */
    public static final String f28663d = "003784cf-f7e3-55b4-6c4c-9fd140100a16";

    /* renamed from: e */
    public static final String f28664e = "d44bc439-abfd-45a2-b575-925416129600";

    /* renamed from: f */
    public static final String f28665f = "00002902-0000-1000-8000-00805f9b34fb";

    /* renamed from: g */
    public static final UUID f28666g = UUID.fromString(f28660a);

    /* renamed from: h */
    public static final UUID f28667h = UUID.fromString(f28661b);

    /* renamed from: i */
    public static final UUID f28668i = UUID.fromString(f28662c);

    /* renamed from: j */
    public static final UUID f28669j = UUID.fromString(f28663d);

    /* renamed from: k */
    public static final UUID f28670k = UUID.fromString(f28664e);

    /* renamed from: l */
    public static final UUID f28671l = UUID.fromString(f28665f);

    protected enum OtaNotiDataPkg {
        OTA_NOTI_LENGTH_L,
        OTA_NOTI_LENGTH_H,
        OTA_NOTI_CMD,
        OTA_NOTI_RESULT,
        OTA_NOTI_RCVED_LENGTH_L,
        OTA_NOTI_RCVED_LENGTH_H,
        OTA_NOTI_RCVED_CS_L,
        OTA_NOTI_RCVED_CS_H
    }

    protected enum otaCmd {
        OTA_CMD_META_DATA,
        OTA_CMD_BRICK_DATA,
        OTA_CMD_DATA_VERIFY,
        OTA_CMD_EXECUTION_NEW_CODE
    }

    public enum otaResult {
        OTA_RESULT_SUCCESS,
        OTA_RESULT_PKT_CHECKSUM_ERROR,
        OTA_RESULT_PKT_LEN_ERROR,
        OTA_RESULT_DEVICE_NOT_SUPPORT_OTA,
        OTA_RESULT_FW_SIZE_ERROR,
        OTA_RESULT_FW_VERIFY_ERROR,
        OTA_RESULT_INVALID_ARGUMENT,
        OTA_RESULT_OPEN_FIRMWAREFILE_ERROR,
        OTA_RESULT_SEND_META_ERROR,
        OTA_RESULT_RECEIVED_INVALID_PACKET,
        OTA_RESULT_META_RESPONSE_TIMEOUT,
        OTA_RESULT_DATA_RESPONSE_TIMEOUT
    }
}
wes1993 commented 2 years ago

Some screen of LightBlue App connected to the sherlock: IMG_0223 IMG_0224 IMG_0228 IMG_0229 IMG_0230 IMG_0231

oyooyo commented 2 years ago

Hello @wes1993 , I'm afraid I can't help you much with that smart lock. keyble is a piece of software exclusively for one particular smart lock model from "eqiva" (named "Key-BLE", thus the name), I don't intend to add support for any other smart locks to it.

If you want to write your own piece of software for controlling this "Sherlock" smart lock then I can give you some general advice based on my own experience when I developed keyble, but that's about all I can do. But I want to be honest, I doubt if it's really worth the effort for you to do this. The "Key-BLE" smart lock for example uses a fairly complex protocol, reverse-engineering it up to a point where I could control the lock myself took me dozens of hours, was a real pain in the ass, and I was lucky to even succeed in the end. If I had known in advance how much work it would be, I would have probably never started.

That being said, if you still want to try to write to reverse-engineer the Sherlock's protocol and control it with your own piece of software, then my usual advice would be to start by sniffing the Bluetooth communication between smartphone and smart lock when you control the smart lock via the app. That's rather easy to do thanks to a feature in the Android developer options, google for "android btsnoop" and look here for instructions.

But there's a huge problem: You say that the smartphone app doesn't even work anymore, because the company that developed the app has died. I don't understand why this makes the smartphone app unusable, the smartphone app of the "Key-BLE" for example would still work fine in that case. Why is the Sherlock's app no longer working, what kind of error occurs? If you really do not manage to get the smartphone app working, that's a big problem. I definitely wouldn't have succeeded if I didn't have a working smartphone app.

I'm closing this issue now since I will not add support for the Sherlock to keyble, but you can of course still write here.

wes1993 commented 2 years ago

Thanks a lot for your reply @oyooyo The app won't work because when you open the app, before you can control the device you must login to a website and the website it's down so you can't do the login and can't control the device... :-(

So you think it's almost impossibile to create a library for the sherlock smart lock? There are many people in this situation.. :-(

If you see the file that i have atteched in this ticket are similiar to Key-BLE app? I hope that this two lock share same or really similiar protocol to work so i hope we can just change the UUID and works?

Best Regards Stefano

oyooyo commented 2 years ago

The app won't work because when you open the app, before you can control the device you must login to a website and the website it's down so you can't do the login and can't control the device... :-(

Ah, I see. Well, that really sucks. Why do users need to do this, do you know if there is any reason why the user has to do so?

So you think it's almost impossibile to create a library for the sherlock smart lock? There are many people in this situation.. :-(

Ultimately I cannot really tell of course because I do not know the Sherlock lock. But I assume it would be rather hard and a lot of work, and here's why: Many or even most gadgets communicating via Bluetooth LE are using very simple protocols that can be implemented in a few lines of code, but they also have absolutely no encryption or security, anyone nearby can sniff all communication, could connect to them and control them. But that would be irresponsible in case of a smart lock of course, so smart locks communicating via Bluetooth LE need to secure the Bluetooth communication against common attacks like replay/MITM attacks etc. They ultimately need to implement their own security layer as part of the protocol, which of course makes their protocol a lot more complex and harder to reverse-engineer and re-implement. I assume this is true for the Sherlock as well. In case of the Key-BLE, I was at least having a working smartphone app which helped a lot.

If you see the file that i have atteched in this ticket are similiar to Key-BLE app? I hope that this two lock share same or really similiar protocol to work so i hope we can just change the UUID and works?

I only had a quick look at the code, but it seems they are using a different protocol. I'd be extremely surprised if that works.

You know, IF this stupid "user has to log in to some website before he can use the device" requirement is not really necessary, the easiest way to make the Sherlock usable again might be by patching the smartphone app to simply skip this step.

wes1993 commented 2 years ago

Thanks again for your reply :) Unfortunately I don’t know whit this fucking Chinese using stupid cloud of the app works by Bluetooth!!

i don’t know if it’s possibile to patch the app, I don’t know Java unfortunately :(

usually when app works I just connect to the account and the app restore my lock from cloud (that now is down forever… ) so I think we should also pass the UUID of the lock to the app or something else I think

thanks a lot Stefano

oyooyo commented 2 years ago

Thanks again for your reply :) Unfortunately I don’t know whit this fucking Chinese using stupid cloud of the app works by Bluetooth!!

i don’t know if it’s possibile to patch the app, I don’t know Java unfortunately :(

It should definitely be possible. There's a popular tool called apktool for doing things like this. But in this case one needs to go one step further and does not deal with high-level Java source code as you were posting, one has to deal with low-level disassembled Java bytecode, called "smali" (see here for an example of what that looks like). That is a little harder than Java and was completely new to me as well, which was yet another reason why it took so long to reverse-engineer the protocol.

usually when app works I just connect to the account and the app restore my lock from cloud (that now is down forever… ) so I think we should also pass the UUID of the lock to the app or something else I think

I do not know what UUID you are talking about exactly, but I think you currently have a slightly false impression what these UUIDs are for. In Bluetooth LE, every "service" and every "characteristic" needs to have a UUID, but they are not unique to one specific smart lock (like a MAC address, some unique serial number, a device-specific key or something like that), all devices of the same model are using the same UUIDs.

I want to be honest with yo: I think you best chance right now is to maybe find someone who has some experience with reverse-engineering/patching Android APKs, and who also own a Sherlock and thus also has a strong incentive to spend the work required to get it working again. Someone who does not own a Sherlock will most probably not want to do that work, especially if he doesn't own a Sherlock to test on.

wes1993 commented 2 years ago

Ok thanks a lot @oyooyo I will try to find some forum for this problem in the meantime I want to buy Eqiva Smart lock, so I can remove this shit and use the Eqiva instead. Do you have some review a sour Eqiva and your library? It’s stable? Thanks a lot Stefano

oyooyo commented 1 year ago

Do you have some review a sour Eqiva and your library? It’s stable?

Sorry, I don't really understand the question.

wes1993 commented 1 year ago

What is your feedback about the Eqiva smart lock and your library? Works well? It’s stable? It’s a good idea to buy the Eqiva?

oyooyo commented 1 year ago

If a smart lock with Bluetooth is what you are looking for, then I can definitely recommend the Eqiva. It works well and the smartphone app is ok as well (and will continue to work even if the company should die, which is unlikely ;-) ).

keyble is not 100% stable however. There are probably bugs in the keyble library as well, but I personally suspect that most issues stem from the "noble" library that keyble is using for Bluetooth communication, so I cannot do much about it. So it might be a good idea to instead look into the ESP32 port that you are already aware of, as it does not have that problem.

wes1993 commented 1 year ago

Thanks a lot for your reply :) Sure u will use the ESP32 porting. P.S. I have bought the Eqiva :)

wes1993 commented 1 year ago

There is just one problem there isn’t the emergency mode like the Sherlock, see this video at minute 9.32:

https:// www.youtube.com/watch?v=GrEbjreGs3I

Do you know if we can retrofit something?

oyooyo commented 1 year ago

There is just one problem there isn’t the emergency mode like the Sherlock, see this video at minute 9.32:

I watched about a minute of the video startng at 9:32, but I must admit that I did not really understand what this "emergency mode" is about.

wes1993 commented 1 year ago

It’s the possibility to insert and open the door if another key is inserted, my lock have this option but when I insert one key the other key is pulled out a little to open the door. But I have disassembled the smart lock and I have seen a spring so probably the eqiva also have this option!! :)

oyooyo commented 1 year ago

I'm still not 100% sure if I really understand it: Does this "emergency mode" mean that you can still open the lock from the outside using a normal key, if, for example, the smart lock on the inside does not work/respond?

wes1993 commented 1 year ago

Yes exactly I can open the door if there is a key inside

oyooyo commented 1 year ago

Okay, that explains why I didn't understand that "emergency mode"-feature when I watched the video: Because the lock cylinders that are common over here always works like this, the door can be opened by key from the outside even if there is a key on the inside.

So when I watched the video etc. I didn't see the feature, because I considered that to be normal behaviour.