nhorvath / python-thermoworks-smoke

Pull data for your thermoworks smoke thermometer
GNU General Public License v3.0
9 stars 8 forks source link

Support for Thermoworks Signals? #2

Open Ramias1 opened 4 years ago

Ramias1 commented 4 years ago

Great job. Can I ask if you'd consider adding support for Thermoworks Signals and Billows? It is the same app and may be just a different db table (though I don't know the name nor how to find out). Biggest difference is Signals uses 4 probes, and has the fan, so output may be different.

nhorvath commented 4 years ago

I had to reverse engineer this one. Without one to play with and see where the data goes it's not really possible.

On Wed, Apr 15, 2020 at 2:27 PM Ramias1 notifications@github.com wrote:

Great job. Can I ask if you'd consider adding support for Thermoworks Signals and Billows? It is the same app and may be just a different db table (though I don't know the name nor how to find out). Biggest difference is Signals uses 4 probes, and has the fan, so output may be different.

— You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHub https://github.com/nhorvath/python-thermoworks-smoke/issues/2, or unsubscribe https://github.com/notifications/unsubscribe-auth/AABIJXD4L3AYWLQ4ND3FHW3RMX4CXANCNFSM4MIZT3XQ .

Ramias1 commented 4 years ago

Understand. How did you reverse engineer it? Jail-broken client device and crack the https?

nhorvath commented 4 years ago

I decompiled the APK and saw what firebase calls they were making. Once you connect to their firebase it's pretty open (within your account). I poked around there with a firebase client until i found what i wanted.

You can skip the first step and use the credentials/instructions from this project to connect.

ironicbadger commented 4 years ago

Thank you for the work so far, it's gotten me a decent head start instead of starting from scratch. What I haven't yet quite been able to figure out is how to browse around the DB as you suggest above. I want to do this because the smokeTemp child is empty and signalsTemp gives me permission denied like this:

list = db.child("signalTemp")\
         .child(serial)\
         .get(token=user["idToken"])

signalsTemp was a complete guess instead of smokeTemp but I haven't been able to figure out how to list the db.children quite yet. I'm new to firebase.

I was able to correctly obtain the serial of the signal device with

results = db.child("users")\
            .child(user["localId"])\
            .child("devices")\
            .child("signals")\
            .get(token=user["idToken"])

Any help would be gratefully received. Looking forward to getting this working with HA.

nhorvath commented 4 years ago

I wrote this little html/javascript page when i was reversing it. Just save this as firebase.html and enter your email, password, and serial. Then open it in chrome and in the console you can just type "smoke" for example and get back the object that is there. Be careful going too high up the tree. I'm pretty sure I crashed their firebase instance once. I think I got the starting points by decompiling the app. Is signals in the same app?


<script>
    // Initialize Firebase
    var config = {
        apiKey: "AIzaSyCfCUKlG5-VPsqta-9M92XBSFLHYsbSqLk",
        authDomain: "smoke-cloud.firebaseapp.com",
        databaseURL: "https://smoke-cloud.firebaseio.com",
        projectId: "smoke-cloud",
        storageBucket: "smoke-cloud.appspot.com",
        messagingSenderId: "74663406178",
    };
    firebase.initializeApp(config);
    var email = ''; // required
    var password = ''; // required
    var serial = ''; // required
    var userId = ''; // ignore
    var data = null;
    var devices = null;
    var smoke = null;
    var smokeTemp = null;

    var auth = firebase.auth().signInWithEmailAndPassword(email, password).catch(function(error) {
        // Handle Errors here.
        console.warn(error);
    }).then(function() {
        userId = firebase.auth().currentUser.uid;

        firebase.database().ref('/users/' + userId+ '/devices/smoke/').once('value').then(function(snapshot) {
            devices = snapshot.val();
        });
        firebase.database().ref('/users/' + userId+ '/storage/data/').once('value').then(function(snapshot) {
            data = snapshot.val();
        });
        firebase.database().ref('smokeTemp/' + serial + '/').once('value').then(function(snapshot) {
            smokeTemp = snapshot.val();
        });
        firebase.database().ref('smoke/' + serial + '/').once('value').then(function(snapshot) {
            smoke = snapshot.val();
        });
    });
</script>```
ironicbadger commented 4 years ago

Signals uses 'ThermoWorks BBQ'.

Going to give the script above a try now. Thanks!

ironicbadger commented 4 years ago

Unfortunately I am getting an error with firebase.database. Looking through the API spec what you have looks like it should word. But here is the error I see.

image

It pertains to these lines of code

firebase.database().ref('/users/' + userId+ '/devices/smoke/').once('value').then(function(snapshot) {
            devices = snapshot.val();
        });
firebase.database().ref('/users/' + userId+ '/storage/data/').once('value').then(function(snapshot) {
            data = snapshot.val();
        });
firebase.database().ref('smokeTemp/' + serial + '/').once('value').then(function(snapshot) {
            smokeTemp = snapshot.val();
        });
firebase.database().ref('smoke/' + serial + '/').once('value').then(function(snapshot) {
            smoke = snapshot.val();
        });
nhorvath commented 4 years ago

Strange because I tested it immediately before I posted it. The only thing I did was delete my credentials.

On Fri, May 8, 2020, 5:17 PM Alex Kretzschmar notifications@github.com wrote:

Unfortunately I am getting an error with firebase.database. Looking through the API spec what you have looks like it should word. But here is the error I see.

[image: image] https://user-images.githubusercontent.com/2773080/81450105-bac2e480-914f-11ea-8441-64e37c6afa49.png

It pertains to these lines of code

  firebase.database().ref('/users/' + userId+ '/devices/smoke/').once('value').then(function(snapshot) {
      devices = snapshot.val();
  });
  firebase.database().ref('/users/' + userId+ '/storage/data/').once('value').then(function(snapshot) {
      data = snapshot.val();
  });
  firebase.database().ref('smokeTemp/' + serial + '/').once('value').then(function(snapshot) {
      smokeTemp = snapshot.val();
  });
  firebase.database().ref('smoke/' + serial + '/').once('value').then(function(snapshot) {
      smoke = snapshot.val();
  });

— You are receiving this because you commented. Reply to this email directly, view it on GitHub https://github.com/nhorvath/python-thermoworks-smoke/issues/2#issuecomment-626024638, or unsubscribe https://github.com/notifications/unsubscribe-auth/AABIJXGGONN7DVBH32EZEBLRQRZHLANCNFSM4MIZT3XQ .

ironicbadger commented 4 years ago

If you are open to this I'd be interested in spending a few mins on a call with you to go through the basics. It might be a simple thing to get this working in lieu of you having a device of your own. Appreciate that's beyond the call of duty though, I'm on the HA discord if you want to talk further.

Thanks.

ironicbadger commented 4 years ago

I decompiled the APK and found where the graphs are stored under storage/..... but there is no nice and tidy UpdateFirebase.java equivalent for Signals like there appears to be for the smoke gateway.

Having spent most of the weekend on this I'm close to admitting defeat! Thanks for your help with the script, I had to import some libraries above it and then it worked.

nhorvath commented 4 years ago

I'm sorry I didn't have time this weekend to help you. It's possible they aren't using firebase to store the temps for the signal, but it would seem to me they would do it the same way as smoke. If I recall correctly the graphs and instant temperatures were in different places.

agentdr8 commented 3 years ago

Not sure if there's still interest in supporting Signals, but I was able to figure out how the latest (v1.12.2) app is retrieving data. The data itself for Signals is still kept within Firebase, but retrieval is happening by way of gRPC calls (via the grpc-java-okhttp library) to https://firestore.googleapis.com/v1/. The parent resource name is projects/thermoworks-cloud-production/databases/(default)/documents/. Here's a list of collectionIds/child endpoints that I've found so far:

You still need the Firebase API key from the strings.xml, and also need to set/send the Authorization: Bearer header that Firebase authentication returns for your username/password combo.

For testing, you can use this curl command:

curl 'https://firestore.googleapis.com/v1/projects/thermoworks-cloud-production/databases/(default)/documents/devices/<Signal_MAC_here>/channels/1?key=<FIREBASE_API_KEY_HERE>' --header 'Authorization: Bearer <FIREBASE_AUTH_TOKEN_HERE>' --header 'Accept: application/json' --compressed

In addition, settings updates and graphs are done via Cloud Functions, using the following URL: https://us-central1-thermoworks-cloud-production.cloudfunctions.net/

The endpoints that I found so far are:

Ramias1 commented 3 years ago

@agentdr8 how do I get the Firebase bearer token? Is there a simple way to do that with curl?

agentdr8 commented 3 years ago

The Bearer token is what is provided after you've authenticated to Firebase (as the 'idToken' of the firebase.auth object). I've only used pyrebase to obtain an authenticated session with Firebase, but there might be a way to do that via curl too that I'm unaware of.

EDIT: Yes, you can get your Bearer token via curl. See example:

curl 'https://identitytoolkit.googleapis.com/v1/accounts:signInWithPassword?key=[FIREBASE_API_KEY] \ -H 'Content-Type: application/json' \ --data-binary '{"email":"signal_user_email_address","password":"password_for_signal_user","returnSecureToken":true}'

Ramias1 commented 3 years ago

Nice. thanks.

I got a response with a localID, IDtoken and a refreshToken.

Tried them with this curl with MAC address with no :

curl 'https://firestore.googleapis.com/v1/projects/thermoworks-cloud-production/databases/(default)/documents/devices/MAC/channels/1?key=AIzaSyCfCUKlG5-VPsqta-9M92XBSFLHYsbSqLk' --header 'Authorization: Bearer ' --header 'Accept: application/json' --compressed

with the longer ID token I get:

"code": 403, "message": "Missing or insufficient permissions.", "status": "PERMISSION_DENIED"

with the others, I got UNATHENTICATED.

Any pointers are appreciated

agentdr8 commented 3 years ago

Make sure your quoting is correct. You'll usually get 403s if it isn't sending the proper Bearer header.

Also, the MAC address should be in the colon-hex notation.

Another thing to check is the Firebase API key. The one posted above is from the older app, before they integrated the Signals support. The API key I extracted from the most recent version is AIzaSyC1DR1AhkeTV99x2nWk0OoTUC40Se4Di9I

intoran commented 3 years ago

Any progress on this? Would love to get this integrated into HA.

nhorvath commented 3 years ago

Sorry I haven't had time to work on this at all.

taw123 commented 6 months ago

Just a bump before I consider looking at what needs to be done here myself....