Nymea/Maveo integration

Is there someone who is willing write a integration for the Nymea platform, which is used on the Maveo garagedooropeners. This looks an separate platform running an ARM-processor with an open platofrm developped by Nymea,

Some info
Nymea: https://nymea.io/
Nymea dev: https://docs.nymea.io/
Nymea github: https://github.com/nymea
Maveo box: https://www.smartwithmaveo.com/en/product-overview/

I already installed the Nymea app on my phone and was able to connect tot the Maveo box (and controll my garagedoor)
I also installed the Nymea-cli component and was also able to connect tot the Maveo box and completely controll the garagedoor (including status)

I hope someone likes to put his of her teeth into this platform. I am not a developer, but of-cource willing to beta test, of give acces to the system.

Thanks!!

Cheers,
Kees

If it has a nymea-cli command, then you should be able to integrate with it using the various command line tools (command line sensor / switch / scripts / etc) in Home Assistant.

I don’t have a device like that uses Nymea, so writing a component will be difficult. I would imagine no other developers do either, or there would likely already be a component for this.

Thanks for your reply. I’ll look in to it. I also opened a topic on the Nymea forum:

So both using the JSONRPC api and directly (bash)scripting is possible.

Cheers,
Kees

The JSONRPC API should make development pretty easy for anyone who has a device like this. It’s awesome of them to include something like that. Most device manufacturers don’t, or if they do, they don’t document it.

FWIW, nymea is free open source software, you can install it on any Linux machine (packages provided for Ubuntu, Debian and Raspbian). There’s also a ready-to-flash raspberry pi image available.

maveo is a branded nymea installation and has the identical software in it (well, a different set of plugins is installed on maveo boxes).

I’d not recommend to use nymea-cli for an integration with home-assistant. Instead, the JSONRPC api is the way to go.

Ah, one more difference between maveo boxes and the plain nymea image: maveo supports push-button authentication for authorizing a client on the JSONRPC api while the default setup on the raspberry pi uses username/password authentication instead. However, push button auth on the raspberry pi can be simulated too by using the command line based push button handler from the nymea-tests which allows to simulate a push button using the keyboard.

So everything needed to integrate maveo should be available for everyone.

Let me know if you need more help.

1 Like

Hi, did anyone work out any integration for the maveo smart garage?

Would be great to have an integration for maveo.
If someone can start with a JSONRPC connection I can for sure support with the development. Some years ago I was JAva developer (now more on the infrastructure side), but I have no experiance with WebSockets and JSONRPC.
So, if sombody can help with the first steps and can develop the other stuff…

An simple example, how to connect via JSONRPI from Home Assistant would be enough.

I found a way to include it in to HA: https://community.home-assistant.io/t/maveo-garage-door-integration/278761

That is nice, but this does not give the status of the door (open/closed)…

Yes, that is missing and according to the vendor it is currently not possible.
I asked them if they can add it in a future release/update, but did not get a response until now.

I worked on a very quick n dirty script to make it work with the MQTT Cover integration. It connects to the websocket port of maveo and runs commands over it. Docs on Maveo API is here but my god it’s awful.

This will most likely NOT work on your setup since the IDs could be very different, but I wanted to share it as a starting point in case anyone wants to build something useful. You also need a token which you can get from nymea-cli (note: my default port was 2223)

What SHOULD happen is that one must call Integrations.GetThings and find the garage door IDs from there, then retrieving stateTypeId and actionTypeId, but I am beyond lazy.

This covers all the requirements, including notifications of open/close/opening/closing, etc since it’s using JSONRPC websockets.

Once again, I whipped this up in like an hour, so the code is miserable and I really didn’t have time to clean it up, but I hope it helps anyone out there!

configuration.yaml

cover:
  - platform: mqtt
    name: "Garage Door"
    command_topic: "home-assistant/garage/set"
    state_topic: "home-assistant/garage/state"
    retain: true
    device_class: "garage"

NodeJS code that needs to run in background

var WebSocketClient = require('websocket').client;
var mqtt = require('mqtt')

var client = new WebSocketClient();

let maveoIP = "<MAVEO IP>";  //maveo box IP
let mqttIP  = "<MQTT IP>";   //MQTT IP

let token = "<TOKEN>";   //get this from nymea-cli
let garageID = "<DEVICE ID>";      //get this deviceId from Devices.GetConfiguredDevices (see below)
let garageClassID = "{ca6baab8-3708-4478-8ca2-7d4d6d542937}"; //get this deviceClassId from Devices.GetConfiguredDevices.  Not used now but you'll need it for GetActionTypes and GetStateTypes if you have to get their IDs

client.on('connectFailed', function(error) {
    console.log('Connect Error: ' + error.toString());
});

//putting those here for MQTT
let open = {
    id: 6,
    method: "Actions.ExecuteAction",
    params: {
        actionTypeId: "{5a1a68cb-a5ef-4bc9-8672-bc067b6c4d48}",  //NOTE: this could be different on your setup.  You can get it from Devices.GetActionTypes (pass in param deviceClassId)
        deviceId: garageID
    },
    token: token,
}

let close = {
    id: 7,
    method: "Actions.ExecuteAction",
    token: token,
    params: {
        actionTypeId: "{6a32c34f-763d-4065-acfc-2b88bfd9eb34}",  //NOTE: this could be different on your setup.  You can get it from Devices.GetActionTypes (pass in param deviceClassId)
        deviceId: garageID
    }
}

let stop = {
    id: 8,
    method: "Actions.ExecuteAction",
    token: token,
    params: {
        actionTypeId: "{fcb767de-e8d7-43da-ab21-17afea7eba24}",  //NOTE: this could be different on your setup.  You can get it from Devices.GetActionTypes (pass in param deviceClassId)
        deviceId: garageID
    }
}

//need this here for MQTT part to access send()
let send = undefined;


client.on('connect', function(connection) {
    send = (obj) => {
        if (connection.connected) {
            console.log("=>", obj);
            connection.sendUTF(JSON.stringify(obj));
        }
        else {
            console.log("Not connected");
        }
    }

    let getDoorState = () => {
        send({
            "id": 1,  //I've reserved 1 for door state so I can handle it in the websocket response.
            "method": "Devices.GetStateValue",
            token: token,
            params: {
                deviceId: garageID,
                stateTypeId: "{6f113f20-11ed-4f69-bda5-449363ab71d0}"  //NOTE: this could be different on your setup.  You can get it from Devices.GetStateTypes (pass in param deviceClassId)
            }
        })
    }

    let getMethod = (method, params) => {
        send({
            "id": 2,
            "method": method,
            token: token,
            params
        })
    }

    console.log('WebSocket Client Connected');
    connection.on('error', function(error) {
        console.log("Connection Error: " + error.toString());
    });
    connection.on('close', function() {
        console.log('Connection Closed');
    });
    connection.on('message', function(message) {
        if (message.type === 'utf8') {
            let obj = JSON.parse(message.utf8Data);

            if (obj.id == 0) {
                getDoorState();
                // getStates();
            }
            else if (obj.id == 1) {
                //report door state
                report(obj.params.value);
            }
            else if (obj.notification) {
                //NOTE:  stateTypeId might be different on your setup.
                if (obj.notification == "Devices.StateChanged" && obj.params.stateTypeId == "{6f113f20-11ed-4f69-bda5-449363ab71d0}") {
                    //report door state
                    report(obj.params.value);
                }
            }
            else {
                //just print it out
                console.dir(obj, {depth: null});
            }
        }
    });
    

    let hello = {
        "id": 0,
        "method": "JSONRPC.Hello",
        "params": {
            "locale": "en_US"
        }
    }

    send(hello);


    //enable notifications of open/opening/etc on this websocket.
    getMethod("JSONRPC.SetNotificationStatus", {enabled: true});

    //start here to get your device IDs
    // getMethod("Devices.GetConfiguredDevices");




});

client.connect(`ws://${maveoIP}:4445/`);

//MQTT part

var c  = mqtt.connect(`mqtt://${mqttIP}`)
 
c.on('connect', function () {
    //listen to commands from Home Assistant
  c.subscribe('home-assistant/garage/set', function (err) {
    if (err) {
        console(err);
    }
  })
})
 
c.on('message', function (topic, message) {
  //make sure the send function is available
  if (!send) return;

  // message is Buffer
  let msg = message.toString();

  console.log(msg)
  switch (msg) {
    case "OPEN":
        send(open);
        break;

    case "CLOSE":
        send(close);
        break;

    case "STOP":
        send(stop);
        break;
    
    default:
        break;
  };
  
})

//report garage state to Home Assistant
function report(state) {
    console.log(state);

    //there is no 'intermediate' state in HA
    if (state == "intermediate") {
        state = "open";
    }

    c.publish('home-assistant/garage/state', state);
}

Hey,

I find the above idea incredibly useful but struggled so far to install node.js on my instance. Is there any way to also build this in node-RED? I try to start this, but so far failed to even send simple commands - getting all of the IDs (by the way the same as in the post above :wink: ) worked.

Thank you for your help!

Kristian

Hi @Keeze and @KrisMH,
I found a way to control my garage door with the help of Node-RED, and also to get the current status reported back.

I posted my solution in @tomu 's original post. Maybe that’s useful for you too.