freakent / dbus-mqtt-devices

A driver for Victron VenusOS GX devices to support use of dbus-mqtt/flashmq-mqtt
MIT License
111 stars 24 forks source link

pvinverter not in dashboard #22

Closed stromibaer closed 1 year ago

stromibaer commented 1 year ago

Hi, have installed dbus-mqtt-devices latest version on Cerbo v2.91. Pvinverters will be registered and are listed as devices in VRM with deviceInstance number. I can also publish values to them and values are showed in Cerbo remote control.

image

But the pvinverters are not showed on the VRM Portal Dashbord neither on Cerbo display.

image

In the configuration of the pvinverters i have no "Setup" entry:

image

image

PV Inverter 31 is a ET112 which is metering whole energy of the inverters, but i want to display each pvinverter standalone in the VRM Portal and Cerbo.

All pvinverters are default on AC-IN1, but i have all on AC-OUT,how can i change this? Because Setup entrypoint is not available.

Thanks, Peter

freakent commented 1 year ago

Can you share your code that you used to register your device on MQTT to dbus?

stromibaer commented 1 year ago

on startup:

// Loop all inverters and register @Victron Venus OS for (uint8_t i = 0; i < Hoymiles.getNumInverters(); i++) { auto inv = Hoymiles.getInverterByPos(i);

    char buffer[sizeof(uint64_t) * 8 + 1];
    snprintf(buffer, sizeof(buffer), "%0x%08x",
        ((uint32_t)((inv->serial() >> 32) & 0xFFFFFFFF)),
        ((uint32_t)(inv->serial() & 0xFFFFFFFF)));
    String subtopic = String(buffer);

    // Register @Victon Venus
    String hoyserial = String(subtopic);
    mqttClient->subscribe(String("device/" + hoyserial + "/DBus").c_str(),0);

    DynamicJsonDocument serviceDoc(256);
    serviceDoc[hoyserial] = F("pvinverter");
    JsonObject serviceObj = serviceDoc.as<JsonObject>();

    DynamicJsonDocument rootDoc(1024);
    rootDoc[F("clientId")] = hoyserial;
    rootDoc[F("connected")] = 1;
    rootDoc[F("version")] = inv->DevInfo()->getHwVersion();
    rootDoc[F("services")] = serviceObj;
    JsonObject rootObj = rootDoc.as<JsonObject>();

    char data[1024];
    serializeJson(rootObj, data);

    String topic = ("device/" + hoyserial + "/Status");
    mqttClient->publish(topic.c_str(), 0, 1, data);
}

On MqTT Message receive:

    // Victron message only on startup after subscribe
    // device/116181045449/DBus = JSON 
    char* rest = &token_topic[strlen("device")];
    serial_str = strtok_r(rest, "/", &rest);

    if (serial_str == NULL) {
        return;
    }

    serial = strtoull(serial_str, 0, 16);

    auto inv = Hoymiles.getInverterBySerial(serial);

    if (inv == nullptr) {
        Serial.print(F("Can not register inverter: "));
        Serial.println(serial);
        return;
    }

    char* strlimit = new char[len + 1];
    memcpy(strlimit, payload, len);
    strlimit[len] = '\0';

    DynamicJsonDocument docDbus(512);
    deserializeJson(docDbus, strlimit);
    VictronPortalId = docDbus["portalId"];

    DynamicJsonDocument docInstance(256);
    docInstance = docDbus["deviceInstance"];
    String deviceInstance = docInstance[serial_str];

    String inverter = serial_str;
    VictronDeviceInstance.insert({inverter, deviceInstance});

    if (VictronDeviceInstance.find(inverter)!=VictronDeviceInstance.end()) {
        String valfound = VictronDeviceInstance[inverter];
        Serial.print(F(" to Venus OS with portalId: "));
        Serial.print(VictronPortalId);
        Serial.print(F(" and deviceInstance: "));
        Serial.println(valfound);
    }
    return;

And publishing values with:

// topic = "W/{}/pvinverter/{}/{}".format(portalId, deviceId, key) # UPDATE THIS
// print("{} = {}".format(topic, data.get(key) ) )
// client.publish(topic, json.dumps({ "value": data.get(key) }) )
if (channel == 0) {

    String fieldvalue = String(inv->Statistics()->getChannelFieldValue(channel, fieldId));
    String fieldname = (inv->Statistics()->getChannelFieldName(channel, fieldId));
    String topic = "W/" + MqttSettings.getVictronPortalId() + "/pvinverter";
    String topic_Victron_sum;
    String topic_Victron_phase;

    char serial[sizeof(uint64_t) * 8 + 1];
    snprintf(serial, sizeof(serial), "%0x%08x",
    ((uint32_t)((inv->serial() >> 32) & 0xFFFFFFFF)),
    ((uint32_t)(inv->serial() & 0xFFFFFFFF)));
    String invSerial = String(serial);

    String deviceInstance = MqttSettings.getVictronDeviceInstance(serial);

    int response = false;
    if ( fieldname == "Voltage" ) { response = true; }
    if ( fieldname == "Power") { response = true; }
    if ( fieldname == "Current" ) { response = true; }
    if ( fieldname == "YieldTotal") { response = true; }

    if ( response ) {   
        // fieldname[0] = std::toupper(fieldname[0]);
        if ( fieldname == "YieldTotal" ) { 
            topic_Victron_sum += topic + "/" + deviceInstance + "/Ac/Energy/Forward";
            topic_Victron_phase += topic + "/" + deviceInstance + "/Ac/L1/Energy/Forward";
        } else {
            topic_Victron_sum += topic + "/" + deviceInstance + "/Ac/" + fieldname;
            topic_Victron_phase += topic + "/" + deviceInstance + "/Ac/L1/" + fieldname;
        }    

        DynamicJsonDocument valueDoc(256);
        valueDoc["value"] = fieldvalue;
        JsonObject valueObj = valueDoc.as<JsonObject>();

        String data;
        serializeJson(valueObj, data);

        Serial.print(F("MqTT publish value: "));
        Serial.print(data);
        Serial.print(F(" to Venus OS with topic: "));
        Serial.println(topic_Victron_sum);

        MqttSettings.publishVictron(topic_Victron_sum, data);
        MqttSettings.publishVictron(topic_Victron_phase, data);

    }

--> I have extended the code from OpenDTU to send the special messages for Victron part With MqTT Explorer everything looks fine:

image

stromibaer commented 1 year ago

I think registration is just be done fine:

@40000000634d804e3a5cdd54 INFO:device: Registering device: 116181045449, services: {'116181045449': 'pvinverter'} @40000000634d804e3a72268c INFO:device:Registering Service pvinverter for client 116181045449 @40000000634d804e3a880c04 INFO:device_service_config:About to open config file @40000000634d804f268f3934 INFO:device_service:Registering service pvinverter for client 116181045449 at path com.victronenergy.pvinverter.mqtt_116181045449_116181045449 @40000000634d804f2a3997dc INFO:settingsdevice:Setting /Settings/Devices/mqtt_116181045449_116181045449/ClassAndVrmInstance does not exist yet or must be adjusted @40000000634d804f2e937834 INFO:vedbus:registered ourselves on D-Bus as com.victronenergy.pvinverter.mqtt_116181045449_116181045449 @40000000634d804f2f91259c INFO:device_service:Registered Service com.victronenergy.pvinverter.mqtt_116181045449_116181045449 under DeviceInstance 12 @40000000634d804f2fd268a4 INFO:device_manager:publish {'portalId': '48e7da889711', 'deviceInstance': {'116181045449': '12'}} to device/116181045449/DBus, status is 0

freakent commented 1 year ago

It's hard to say for sure, but it looks like you are using the driver correctly. The driver doesn't have any special handling for pvinverters so maybe the problem is outside the driver. I know there are others using the driver for pvinverters (I'm not) maybe they can offer more advice.

freakent commented 1 year ago

@hoffy Any ideas?

Hofyyy commented 1 year ago

Hi, yes it is running on my side without any problems.

Hofyyy commented 1 year ago

0F6ABFE2-FF18-4EA5-ADCF-05D0BCC5FA33 3CEC106D-31C0-42AF-84CF-4034CFAC7103

stromibaer commented 1 year ago

Which release do you have on Cerbo? And can you post me your services.yml file?

I have edited the services.yml file to:

Position: description: "0=AC input 1; 1=AC output; 2=AC input 2" persist: true default: 1 min: 0 max: 2 StatusCode: # not used by ESS demo mode pvinverter description: "0=Startup 0; 1=Startup 1; 2=Startup 2; 3=Startup 3; 4=Startup 4; 5=Startup 5; 6=Startup 6; 7=Running; 8=Standby; 9=Boot loading; 10=Error" default: 7 min: 0 max: 10 AllowedRoles: default: '["grid", "pvinverter", "genset", "acload"]' Role: description: "grid, pvinverter, genset, acload" persist: true default: 1 min: 0 max: 3

and get now a "Setup" entrypoint:

image

With following entries:

image

When i change the postion to AC OUT nothing happens. In the portal stands:

image

I downgraded the Cerbo version to 2.90 - After downgrade i have values in the overview, after redo the setup, because of yaml,etc. there are no values in the overview of the cerbo:

image

stromibaer commented 1 year ago

After doing some testing i following out

After switch on MqTT sender and registering again the pvinverters

In which logfiles can find some more infos about the Cerbo system and what is going wrong?

stromibaer commented 1 year ago

Einen Unterschied hab ich mittlerweile entdeckt --> die Formatierung der "Allowed Roles" ist bei allen MqTT PV Invertern anders als bei einem Gridzähler oder einem Zähler der die Rolle pvinverter inne hat:

image

image

image

image

Während am MqTT Explorer alle Werte zyklisch verschwinden und wieder erscheinen, bleiben diese hier permanent stehen:

image

Und lassen sich mit:

image

image

auch nicht überschreiben. Die Position lässt sich überschreiben.

Was steht da bei euch drin an "Allowed Role"?

stromibaer commented 1 year ago

@stundenblume i have seen from the victron community, that you has worked on same topic and had also some issues. Do you have now a working environment and can share it?

Hofyyy commented 1 year ago

Sieht bei mir komplett anders aus. Ich gehe mit dem MQTT Browser direkt auf meinen Victron Device V2.90. Ich hab deine Allowed Werte garnicht.

image image
stromibaer commented 1 year ago

Lange Rede nun gefunden: String fieldvalue = String(inv->Statistics()->getChannelFieldValue(channel, fieldId)); Die Wertausgabe muss ein Float sein, dann läuft alles.

freakent commented 1 year ago

Thanks for closing, but could you please post a short summary so that any else who comes here with the same problem can benefit? Regards, Martin

stromibaer commented 1 year ago

Now in english, sorry:

Long problem, short solution: String fieldvalue = String(inv->Statistics()->getChannelFieldValue(channel, fieldId)); The value must be an "float" not a "string", then everything works fine. With "String" the Victron get the value "1.92" and not 1.92

freakent commented 1 year ago

So just to be clear, is this a change you made to your client side code? Is this the data you are sending to the Victron MQTT topics for pvinverter?

stromibaer commented 1 year ago

Yes, client side. I have adapted den Open-DTU with some additions to publish the values from Hoymiles inverters directly to Venus OS.

stundenblume commented 1 year ago

@stundenblume i have seen from the victron community, that you has worked on same topic and had also some issues. Do you have now a working environment and can share it?

sorry, was on vacation.

Open-DTU seems to be a very nice project! That would be a reason to by Hoymiles inverters instead of the APSystems.