Create Flutter Backend

Hello it’s me again,

I think Nymea is the backend I will use for my project since it got everything I need. Since I’m in a hate relationship with QT, I will use flutter for my Client.
I will make the pure backend open source here: GitHub - KiHu91/nymea-flutter
Currently, it can connect to Nymea and do the Hello stuff. It also opens a stream on the WebSocket and can Post JSON requests.
It doesn’t work with SSL or token currently.
I’m still having a hard time really understanding how the backend works.
My questions:

  1. I’m having problems identifying things and what they can do. Is there something like a list that I can use the “thingClassId” to check what the thing can do? Or do I always have to check with “Integrations.GetActionTypes”? With “Integrations.GetThingClasses” I get this HUGE answer with all kinds of stuff. But what if there is no interface?
  2. The same for stateTypeId. Is there a list where I can check what kind of type is behind which Id so I can display it the right way?
  3. To store the information in which room the thing is I should use a “Tag” right? Or is there a way to add new entries for a thing?

Hi,

Gernerally ThingClasses are the definitions of how things look like, what states/events/actions they have. Think of it as a template. From this template, things are created. For performance reasons things won’t carry all the information again about state names, default values and whatnot. They only hold the actual state values etc. Whenever you work with a thing, you want to keep its thingclass at hand to look up all those details.

What nymea:app does is to call indeed GetThingClasses once and store the entire reply in a cache. You can use the cache hashes in the JSONRPC.Hello reply to know whether is has changed on the core and needs to be updated or whether the thing class cache is still valid. GetThingClasses will contain all the (thing) info you’ll ever need, no need to call GetStateType and similar unless you only need a minimal interaction with just one or two particular states. That’s mostly meant for smaller scripts that won’t have the capability to cache the entire thing class definitions.

GetThings is called every time on the connection establishment. Then, it stores a pointer to the thingClass in every thing and has some convenience methods to do stuff like “thing.stateByName()” and “thing.stateById()” which will then just walk through thing,thingClass.stateTypes and return the appropriate one.

Once you have ThingClasses and Things loaded, subscribe for notifications (JSONRPC.SetNotificationStatus) for the Integrations namespace which would then update your client every time something changes.

To sum it up:

  • Call GetThingClasses when you connect to a host for the first time or the cache hash changed.
  • Call GetThings once on every connection establishment
  • Watch thing changes by subscribing to notifications (no need to call GetThings any more until the connection drops)

For the groups/rooms:
nymea:app uses tags for groups, yes. You can either re-use those tags to be in sync with nymea:app or create your own ones. Use “nymea:app” as appId for the tags if you want to re-use them or your own app id if you want a separate room/group system.

Since version 0.27 nymea also supports the AppData namespace which allows to store arbitrary data on the core (i.e. the new Dashboard is stored there). You can also store such stuff there…

@mzanetti maybe this “intro” should go to the docs? :slight_smile:

Yea that “into” would help a lot :smiley:
Also, can you maybe put the documents into separate sites? The HUGE pages are such a pain to use :expressionless:

A short update on my side:
I was able to do everything as you said, I load the HUGE file into a variable at the start and parse it. I can get all the things and get the Interfaces with the ThingClassesId.
Now I need to implement the Interfaces and it looks like they are not in any kind of order? At first, I hoped the last extend is always at the top but that’s not the case.
So for my understanding if I want to get the last extend I go through the interfaces and check what the list contains with:
e.g.: if(power) => if(light) => if(dimmablelight)
Then I know it is a dimmable light and can build an interface for that. Is this how it’s supposed to be used or is there something I don’t see?

It really depends on what your app should look like and how it should behave…

In nymea:app for example, all the things having the “light” interface are grouped into one group. And then, when opening an individual light control view, it just checks whether it can do “dimmablelight” or “colorlight” or just the plain on/off “light”.

if instead you don’t want any groups, just having all things in a single big list, then you’d probably want something like:

if (thingClass.interfaces.contains("colorlight") {
  openColorLightPage();
} else if (thingClass.interfaces.contains("dimmablelight)" {
  openDimmableLightsPage();
} else if (thingClass.interfaces.contains("light") {
  openOnOffLightsPage();
} else if ...

sorting it by the priority you want to show them. Note that a single thing might implement multiple interfaces, for example a garage door might implement the garagedoor and the light interface, given those garage engines often have a light on them.

Generally, the more important interface comes first in the thingclass. I.e. that garagedoor thing would have the interfaces ["garagedoor", "light"] in that order.

Yea I have a Map now to get the right extends. And take the first entry as the main Interface. The rest can later be used inside the main interface like batterie and connection.

I am able now to control my devices. So that part is working for the Interfaces I have implemented

Now I am at the point with rooms and I want a floorplan so every Thing needs an X and Y coordinate. The rooms can be done with Tags but x/y would be really inefficient since I need 2 new Tags per thing.

But you said something with AppData where I can store my data in the core. Can you give me more information about that? I don’t find anything online.

And is there a way to add fake data? I obviously don’t have all things Nymea can controle in my home :smiley:

Use JSONRPC.Introspect

For the fake data, install nymea-plugin-simulation