Is there any way to connect Firebase to Hassbian

Why do you need a module? I am confused on what EXACTLY you are looking for here. You want to connect something like this you are going to have to write some code.

There is nothing directly in the UI.

hi @nehulagr, I was wondering about exactly the same thing. I don’t feel comfortable opening a door in the router so I’d rather keep the states in sync with firebase/firestore.

I’m completely new to HA so I would not have a clue where to start. Did you manage to understand how to do it ?

cheer

1 Like

I am trying to create NodeJS script to execute in the background. So with PM2 (run nodejs script in the background). I got it ready with maximum logic, there is only one problem I am facing, once that is done I will share with you.

Interesting approach. I was thinking something more similar to the google pub sub component . If that component supported “sub” then a couple of cloud functions would do the trick…

Yes that should also work. But I find NodeJS more easy to work with. I have having some trouble using it on both the sides. I have the script ready, but not 100% working perfect. Also it will more dependent from JSON structure you will create. If you can share the JSON structure then I will share the script related to it.

What about something like this ?

"""Sync with firestore"""
import logging
import os
from typing import Any, Dict

from homeassistant.const import (EVENT_STATE_CHANGED, STATE_UNAVAILABLE, STATE_UNKNOWN)
from homeassistant.core import Event, HomeAssistant

_LOGGER = logging.getLogger(__name__)

REQUIREMENTS = ['firebase-admin']

DOMAIN = 'google_firebase'

def setup(hass: HomeAssistant, yaml_config: Dict[str, Any]):
    import firebase_admin
    from firebase_admin import credentials
    from firebase_admin import firestore

    certificate = os.path.join(hass.config.config_dir, 'firestore.json')
    cred = credentials.Certificate(certificate)

    firebase_admin.initialize_app(cred)

    db = firestore.client()
    col_ref = db.collection(u'states')

    def update_firestore(event: Event):
        new_state = event.data.get('new_state')
        old_state = event.data.get('old_state')

        if (new_state is None
                or new_state.state in (STATE_UNKNOWN, '', STATE_UNAVAILABLE)
                or ( not new_state.entity_id.startswith('light.')
                     and not new_state.entity_id.startswith('switch.'))):
            return

        col_ref.document(new_state.entity_id).set({u'state': new_state.state})
        # col_ref.document(new_state.entity_id).set(new_state.as_dict())

        _LOGGER.debug('added to firestore id %s, from %s to %s',
            new_state.entity_id,
            old_state.state if old_state is not None else None,
            new_state.state)

    def on_snapshot(col_snapshot, changes, read_time):
        for change in changes:
            id = change.document.id
            state = change.document.to_dict().get('state')
            if state in ['on', 'off']:
                method_string = 'turn_' + state
                _LOGGER.debug('Calling homeassistant.%s %s', method_string, id)
                hass.services.call('homeassistant', method_string, { 'entity_id': id })

    query_watch = col_ref.on_snapshot(on_snapshot)
    hass.bus.listen(EVENT_STATE_CHANGED, update_firestore)

    return True

Hi Everyone,

Big thread coming, i’m new to HomeAssistant. And i also want all my devices offline, with some private online access. Or at lease having the control of the data. As HA say “Open source home automation that puts local control and privacy first” :grinning: !

I did take a look around and see other app, but none support Firebase. And also I don’t want to open any port, public IP etc…

So I make a quick POC syncing HomeAssistant database and Firebase.
Using @payano repo https://github.com/payano/homeassist-ng (A native android app).

The result is:

  • Sync all Entity with Firebase OK!
  • Using node-red with the firebase-contrib-plugin, turn on/off light OK!

Now the issue (or next step) is, I don’t want to configure node-red for every Entity. Maybe there is a way to pass data. But I think it’s better having HA handle firebase and consume the state light " on data change.

So, can someone help me on server side doing the following:

I’ll make the client side :

  • Add a toggle button “Go Online” (Need to discuss with @payano )
  • Switch app locale database to the firebase one if online.
  • Stop locale connexion while online, probably change the data source.
  • Make firebase config dynamic, actually firebase need a google-service.json at compile.
    Meaning anybody that want to used their own Firebase, will need to compile the app :frowning: .
  • I should be able to use cloud messenger for notification.
  • If I can’t removed google-servives.json, I’ll have to make a little bash script for installation if people are interested.

So at the end, would be nice if someone could handle the server side (@seba, @nehulagr, @anybody :grinning: ).

How does it sound, do you think I can go with that ?

Hello @Fraid, interesting approach! If the community wants it, I think it should be implemented.

I am doing refactoring in HomeAssist-ng, with one class HomeAssistant (HA) with a ConnectionHandler, which will be able to connnect the HA instance over different connection methods.

HomeAssistant have a data member: ConnectionHandler. ConnectionHandler have a list of EndPoints to use for connecting to HA.

[HomeAssistant] (Singleton) (Handles the configuration layout and states of all the items configured in HA)

  • [ConnectionHandler] (Handles the connection to HomeAssistant, have one or more EndPoints to connnect to the HA instance)
    • [HaWebSocketEndPoint] (Connects to HA over the WebSocketAPI) # currently working on this
    • [NabuCasaEndPoint] (Connects to HA over NabuCasa) # this is something that would be nice to have.
    • [FirebaseEndpoint] (Connects to HA over Firebase) # this is new

[GUI] Will request the HomeAssistant singleton for information and publishes it in the GUI for the user.

I’m thinking of having multiple connection endpoints configurable for the user in the settings view in the HomeAssist-ng application, the user can choose to have one or more endpoints configured, the user must atleast have the WebSocketAPI configured. When the user is connected to the LAN where the HA instance resides, the user will then be connected to HA over WebSocketAPI, if the network is changed and the user can no longer connect over WebSocketAPI, then the app will try the other endpoints. If it succeeds to connect to the instance, it will use that endpoint until the network connection is changed, then the HomeAssist-ng app will evaluate if it should try the WebSocketAPI.

I’m working on enabling support for LoveLace for HomeAssist-ng over WebSocketAPI, I will also remove the REST API implementation in the application, because the WebSocketAPI supports the publisher/subscriber design pattern which the REST API is missing, it only supports polling. If it is needed in the future, I will create a new endpoint and let it coexist with the WebSocket API so both can be connected to the HA instance simultaneously.

If you want a FirebaseEndPoint, there shouldn’t be any problem from the HomeAssist-ng app, we only need to agree on the data layout and the information that it contains. I would suggest that you also store the LoveLace layout in Firebase, as well as the states. But we can discuss this later on. If the FirebaseEndPoint sends a data structure with states and GUI layout, the application can publish it for the user.

Hi @payano,

Thank for the the interest! Sound good, do you already have like an interface, I can implement the FirebaseEndPoint?

[FirebaseEndPoint] I think we should stick with the same payload as HA, for easy migration, or a new connexion type. Which is what HA-ng does from what I see.
The only part left i think is dynamic configuration for Firebase, I’ll try to take a look at it this week.

[GUI] Lovelace, sure we can put everything in FireBase. But I don’t know much about it, for now in HA I only added my devices. No personalization yet ^^. Currently I’m learning node-red with online tutorial. Because look easier for me. And by the way I discover from HA-ng, i can sent the full payload to node red to make any action.

Hello @Fraid,

The implementation is far from done, but i published the code that i’m working on now on Github (https://github.com/payano/homeassist-ng-refactoring/).
If you want to try it, clone the repository and open the project in Intellij idea. Change url and password token in HAWebSocketEndPoint. The ConnectionHandler is setting up the connection, authenticating, requesting the states and subscribes to events. The interface “HAConnectionEndPoint” have most of the methods needed, if you do progress, please send Pull Requests so i can merge it with the master branch.

Cheers.

1 Like

Hi @payano,

Just to make sure does the following explain your goal?

HA-NG-EndPoint

Once we are connected to FB, any change will be automatically sync on the device, that mean FBConnexionEndpoint will handle only:

public void setup();
public boolean isOnline();
public void connect();
public void disconnect(); 
public void send(Payload data);

On the other side we need something like:

HAEventHandler
public void onLayoutDataChange(Entity data);
public void onDataChange(Entity data);

So are we on the same boat, did I miss something ?

Hello @Fraid,

The graphical illustration is a good representation of how the application should interact with other parties, such as a HA Local instance and CloudFirebase, you are spot on!

Regarding the interface, i’m open for suggestions, I have only focused on the retrieving part, for example, getting the states and the gui from HAWebSocket, but as you said, we need a way to also send data from the application to the endpoint, a send(Payload data) is good!

The way I thought would be a nice design is to let the ConnectionHandler be a subscriber to the Endpoints, and when the endpoints have new information they can publish it to the interested parts (most often ConnectionHandler). The ConnectionHandler is sleeping most of the time and when it gets a callback from an endpoint they intterupt the thread.sleep() call. The ConnectionHandler then checks for incoming messages and acts upon it.

Do you think these methods also should be available on the Endpoint interface?:

Cheers :slight_smile:

Hi @payano

This part look “weird” to me, because HAFirebase is automatically sync. When something change you will be notified by onDataChange callback. That look like two task waiting for the same thing.

If you let me this week, I’ll make a bigger picture of what I think of ConnexionHandler.

I started to play with Lovelace, when you say save the layout, is it the yaml file?

Cheers :grinning:

Hi @Fraid,
Your are right, it is unnecessary to have two tasks/threads waiting for this task. I really like having the ConnectionHandler on its own thread and skip the thread inside the EndPoints.

To set/get LoveLace configuration look at this link: https://github.com/payano/homeassist-ng/issues/13

I have created some sketches on how i would like to design the application:
My handwriting can be tricky to read sometimes :stuck_out_tongue:

The first one is how threads communicate:

Here is a class diagram:

Here is a use-case diagram:

Looking forward to see some of your pictures. :slight_smile:

1 Like

Awesome! We are definitively on the same boat, but not on the same floor :smiley: !

Correct me, if I’m wrong, but I think you’re seeing Firebase as a connexion like system.
However it’s more like a smart Database, the only thing we need to handle is data change on both side server/devices.

If you did know Android, before Glide/picasso library, there was many thing to handle before showing an image from url.
Now you mostly have to do:

Glide.load(«some uri » ).into(imageView)

So same thing for FB

Firebase.listenTo(« /user/home/door1/status »).onChange(«make layout red »)

From documentation :
The Firebase Realtime Database lets you build rich, collaborative applications by allowing secure access to the database directly from client-side code. Data is persisted locally, and even while offline, realtime events continue to fire, giving the end user a responsive experience. When the device regains connection, the Realtime Database synchronizes the local data changes with the remote updates that occurred while the client was offline, merging any conflicts automatically.
Source: Firebase Realtime Database

Knowing that, I’ll suggest something like:

public interface HAConnectionEndPoint {
public void setup();
public boolean isOnline();
public void connect();
public void disconnect();
public void authenticate();
- public void getStates();
- public void getGUILayout();

+ public void waitOnDataChange(HAEvent callBack);
OR (prefer the following)
+ public void waitOnStatesChange(HAEvent callBack); 
+ public void waitGUILayoutChange(HAEvent callBack);

public void registerSubscription();
public void unregisterSubscription();
+public void sendData(HAObject data,HAEvent callback); 
-public boolean testConfig(String url, String username, String password);
+ //Used sendData method ?

}

When data has been changed we can call:

HAEvent.onDataChange(HAObject);

[Lovelace] Didn’t really catch it for lovelace but on the server side ( HAFirebase.py i guess) you can send what ever you want. If you have node red installed on HA, i can make a mockup.

And no! I don’t work for Firebase neither have any action of then :D!

Hello @Fraid,

I don’t really get you here. I think that the app only should be connected to one EndPoint at a given time, when the EndPoint changes from WebSocketAPI to Firebase, the app should request all the states within the database and update the HomeAssistant class accordingly. If we have multiple endpoints connected at the same time and the states differs from WebsocketAPI and Firebase, the complexity of the app increases.

I didn’t know that. I had one Java and one Android course at university. To be honest, I’m bad at doing GUI, I am more of a backend developer writing stuff in C++ (that’s what I do as a living), but Java is a really neat language too!

I think for retrieving data, we should use some callback methods, the FirebaseEndPoint should be a publisher that the ConnectionHandler is subscribing for, and ConnectionHandler is a publisher that the HomeAssistant is a subscriber for. In this case the HomeAssistant class is not aware of which endpoint that is connected to, all it knows is that the ConnectionHandler is connected to one endpoint and everything is encapsulated. :wink:

Could you explain what we should have these methods for?

Should you call this method and the Endpoints should block the calling thread and wait for new data to be retrieved? Please explain :wink:

Haha! Good, but Google do some good stuff for developers!

Lovelace data can be retrieved from the WebSocketAPIEndPoint.

That’s good news that we are in the same boat!! :slight_smile:

Cheers :wink:

Hi @payano,

I pushed the changed I made for the POC. Can you take a look at https://github.com/Fraid/homeassist-ng.

You’ll see how i turn on my kittle using node-red with :

FirebaseDBManager.callService

I only send from HA-NG to node red, didn’t update the UI, but this can be done by calling following when we setup Firebase once:

FirebaseDBManager.waitOnStatesChange()

If you want to test it, let me know I’ll make a bigger tutorial but basically :
Add your google-services.json at the level of app/build.gradle, and install app.
Create a node red flow with firebase listening to homeassistant/request and forward everything to ha-service like :

And sure it’s one connexion at the time, we sync only if Firebase mode.
WebSocketAPIEndPoint…will see at time :smile:.

The change I made on my repo should answer all your question. If not please let me know.
If I got time also i’ll update the UI as well, so we will have a full picture how I send/receive data through firebase.

Cheers :wink:

Hello @Fraid.
That’s good news and nice that you have a working POC.
Yes it would be really nice if you could share a tutorial on how to set up Firebase. :wink:

Regarding the data types available in Firebase, i noticed that you wrote a comment saying that Firebase does not support BigDecimal, is suppose BigDecimal is another name for double? Is it necessary to have 64 bits of float precision?

How would we know when we shouldn’t use Firebase mode? I suppose that Firebase will be accessible all the time :slight_smile:

Great work!

By the way, I want to decouple JSON from the internals of the code, and only use it when communicating to some of the endpoint nodes. I have created a JSONParser on my Github repo which takes care of all the strings and converts them to the right datatype. UUID, Date, Double, Float, Long and Int.

It would be neat if you could send a PR so i can merge it with master and publish it on Google Play. :slight_smile:

Hi @payano,

So database setup

  1. Log in to https://console.firebase.google.com
  2. Create a new project or use an existing one
  3. Click on « Database » tab, and scroll down to « Realtime Database »
  4. Create a test mode database, because auth doesn’t work with node red a the time.
  1. Go back to Project overview (Top left), create a new android app
  2. Follow the instruction, at the end you’ll get the google-services.json

I just made the tutorial, if you have any issue please let me know, we may need this tutorial after :smiley:!

At the time, it was just a test, so didn’t spend time on it.
But from what I remember, I need to make a converter using String.
I need to verify that, but yes I think some sensor may need that for accuracy, I that may cause issue if we skip that part.

First let’s define our word with HA-S for home-assistant instance (the one install on raspberry or muc…etc) and HA-A for Android app.

So, firebase is enable in Firebase.yaml on HA-S. That part should be created and i’m not into python, but @seba made a sample should be easier.

Then, HA-A will fetch and save the setting and active firebase mode if all the following are true:

  • Device is not in local mode
  • Device is online
  • Firebase is connected to HA-S

Your repo help me a lot! :wink:

Their is some issue we need to fix before or think about if before (soon :smiley: !).

Using node red and firebase:

  • The authentification process in node red process isn’t done. So your firebase db should be in read/write for everyone. Not really an issue if you’re don’t share your db url (https://DB_NAME.firebaseio.com)
  • If you just want to make action we need to update the UI.
  • Same for data, user will need to specify what to sync within node red

Direct connexion with a firebase.py and firebase.yaml on HA-S:

  • firebase.py need to be done.
  • HA-A need mainly to handle firebase callback at least for an alpha version.

So node red will easily work but user will need to create the flow (like this node red flow), at lease just to send the data to HA-S from HA-A that could be an alpha option to publish.
That part I can handle it, but do you think people will be interested ?

The best I think is having a direct connexion with HA-S and Firebase.
Need more work, but it’s better for end user. This option will not required any action except setting up the firebase or import a google-services.json file .

JSONParser don’t really understand that part, but i know that jackson library does that, you can customize the deserialize/serialize.

Hello @Fraid,

I did follow your guide to setup Firebase, but I got confused on how to configure Node Red, I have never used it before, so I got stuck there :confused:

Okay, perhaps we should break the problem down into smaller parts and create tasks for them. I’m not sure how much time it takes to make the implementation in the current codebase, but I want to change the connection handling so we can have multiple endpoints. Today the app uses REST API as primary connection method and have the possibility to add websocket api for callbacks.

What do you mean by that?

How should we tackle the problem with connecting to multiple endpoints, are you thinking of replacing the websocketapi with firebase even when you are on the local area connection and can do a direct connection to the home assistant server?

I tried the Jackson library, but I did my own and can customize it as I choose to. :blush:

I think it would be wise to create issues/tasks for the work that has to be done so we can do them one by one.

Cheers! :blush: