M-TEC Portal Datenabruf per HTTPMOD Code-Beispiel

Begonnen von minierm, 16 September 2023, 16:04:17

Vorheriges Thema - Nächstes Thema

minierm

    Hallo,
    nachdem diese Woche nach nur 4 Monaten die PV Anlage endlich vom Elektriker angeschlossen wurde kann ich jetzt Erfolg vermelden: Ich habe das M-TEC Portal per HTTPMOD an FHEM angebunden!

    Vorgehensweise:
    • Logindaten ermitteln
    • URL für Anlage ermitteln

    Per Developertools des Browsers muss man die Daten ermitteln, d.h. im Browser F12 drücken oder Strg-Umschalt+I oder:
    • Firefox: Weitere Werkzeuge/Werkzeuge für Webentwickler aktivieren
    • Edge: Weitere Tools/Entwicklungstools

    1. Logindaten ermitteln

    2. URL für Anlage ermitteln
    • Netzwerklog löschen
    • Anlage auswählen
    • URL mit "getSingleStationDataV2" kopieren
    • und bei DEF eintragen

    Hier der entsprechende Code:

define MTEC HTTPMOD https://energybutler.mtec-portal.com/api/sys/curve/station/getSingleStationDataV2?<yourdata> 60
attr MTEC enableCookies 1
attr MTEC event-on-change-reading .*
attr MTEC extractAllJSON 1
attr MTEC group PV
attr MTEC reAuthJSON code
attr MTEC reAuthRegex 3010022
attr MTEC requestHeader1 Accept: */*
attr MTEC requestHeader2 Authorization: $sid
attr MTEC requestHeader3 Cookie: token=$sid
attr MTEC room Strom
attr MTEC showError 1
attr MTEC sid01Data {\
"email": "<yourEMail>",\
"password": "<yourPWHash>",\
"salt": "<yoursalt>",\
"channel": "1"\
}
attr MTEC sid01IdJSON data_token
attr MTEC sid01URL https://energybutler.mtec-portal.com/api/sys/login/manager
attr MTEC sidHeader1 Content-Type: application/json
attr MTEC stateFormat PV data_dataNodeMap_inputNode_originData kW (H data_accumulatedData_todayEnergy data_accumulatedData_todayEnergyUnit / M data_accumulatedData_monthEneregy data_accumulatedData_monthEneregyUnit / J data_accumulatedData_yearEnergy data_accumulatedData_yearEnergyUnit) <br> \
Netz data_dataNodeMap_meterNode_currentData data_dataNodeMap_meterNode_currentDataUnit / Verbr. data_dataNodeMap_loadNode_currentData data_dataNodeMap_loadNode_currentDataUnit / Bat data_dataNodeMap_batteryNode_originData kW (data_dataNodeMap_batteryNode_otherData%) /
</code>

Kurze Erklärung:
Es wird bei der HTTP Response geschaut, ob in den JSON Daten ein code mit dem Wert "3010022" vorkommt. Wenn ja wird eine Authentifizierung erwartet. Die erfolgt über den Login-Manager, der einem in der JSON-Antwort ein Token übermittelt. Dieses Token muß dann bei jedem Request mitgeschickt werden.
Ich weiß nicht, ob das "salt" für jeden anders ist, theoretisch sollte es für alle gleich sein. Fängt bei mir mit 5c an und hört mit f4 auf.

Readings
READINGS:
#     2023-09-16 15:26:39   code            1000000
#     2023-09-16 13:36:52   data           
#     2023-09-16 15:26:39   data_accumulatedData_monthEneregy 96.1
#     2023-09-16 15:26:39   data_accumulatedData_monthEneregyUnit kWh
#     2023-09-16 15:26:39   data_accumulatedData_todayEnergy 49
#     2023-09-16 15:26:39   data_accumulatedData_todayEnergyUnit kWh
#     2023-09-16 15:26:39   data_accumulatedData_totalEnergy 96.1
#     2023-09-16 15:26:39   data_accumulatedData_totalEnergyUnit kWh
#     2023-09-16 15:26:39   data_accumulatedData_yearEnergy 96.1
#     2023-09-16 15:26:39   data_accumulatedData_yearEnergyUnit kWh
#     2023-09-16 15:26:39   data_allIsWattsonicBattery 0
#     2023-09-16 15:26:39   data_dataNodeMap_batteryNode_currentData 0
#     2023-09-16 15:26:39   data_dataNodeMap_batteryNode_currentDataUnit W
#     2023-09-16 15:26:39   data_dataNodeMap_batteryNode_currentDayCurve
#     2023-09-16 15:26:39   data_dataNodeMap_batteryNode_curveKey battery
#     2023-09-16 15:26:39   data_dataNodeMap_batteryNode_flowDirection 3
#     2023-09-16 15:26:39   data_dataNodeMap_batteryNode_meterWorking 1
#     2023-09-16 15:26:39   data_dataNodeMap_batteryNode_nodeName Battery Power
#     2023-09-16 15:26:39   data_dataNodeMap_batteryNode_originData 0
#     2023-09-16 15:26:39   data_dataNodeMap_batteryNode_otherData 100
#     2023-09-16 15:26:39   data_dataNodeMap_batteryNode_working 1
#     2023-09-16 15:26:39   data_dataNodeMap_inputNode_currentData 7.11
#     2023-09-16 15:26:39   data_dataNodeMap_inputNode_currentDataUnit kW
#     2023-09-16 15:26:39   data_dataNodeMap_inputNode_currentDayCurve
#     2023-09-16 15:26:39   data_dataNodeMap_inputNode_curveKey power
#     2023-09-16 15:26:39   data_dataNodeMap_inputNode_flowDirection 1
#     2023-09-16 15:26:39   data_dataNodeMap_inputNode_meterWorking 1
#     2023-09-16 15:26:39   data_dataNodeMap_inputNode_nodeName PV Power
#     2023-09-16 15:26:39   data_dataNodeMap_inputNode_originData 7.107
#     2023-09-16 15:26:39   data_dataNodeMap_inputNode_otherData
#     2023-09-16 15:26:39   data_dataNodeMap_inputNode_working 1
#     2023-09-16 15:26:39   data_dataNodeMap_loadNode_currentData 347
#     2023-09-16 15:26:39   data_dataNodeMap_loadNode_currentDataUnit W
#     2023-09-16 15:26:39   data_dataNodeMap_loadNode_currentDayCurve
#     2023-09-16 15:26:39   data_dataNodeMap_loadNode_curveKey loadPower
#     2023-09-16 15:26:39   data_dataNodeMap_loadNode_flowDirection 2
#     2023-09-16 15:26:39   data_dataNodeMap_loadNode_meterWorking 1
#     2023-09-16 15:26:39   data_dataNodeMap_loadNode_nodeName Load power
#     2023-09-16 15:26:39   data_dataNodeMap_loadNode_originData 0.347
#     2023-09-16 15:26:39   data_dataNodeMap_loadNode_otherData
#     2023-09-16 15:26:39   data_dataNodeMap_loadNode_working 1
#     2023-09-16 15:26:39   data_dataNodeMap_meterNode_currentData 6.76
#     2023-09-16 15:26:39   data_dataNodeMap_meterNode_currentDataUnit kW
#     2023-09-16 15:26:39   data_dataNodeMap_meterNode_currentDayCurve
#     2023-09-16 15:26:39   data_dataNodeMap_meterNode_curveKey pMeter
#     2023-09-16 15:26:39   data_dataNodeMap_meterNode_flowDirection 2
#     2023-09-16 15:26:39   data_dataNodeMap_meterNode_meterWorking 1
#     2023-09-16 15:26:39   data_dataNodeMap_meterNode_nodeName Grid power
#     2023-09-16 15:26:39   data_dataNodeMap_meterNode_originData 6.76
#     2023-09-16 15:26:39   data_dataNodeMap_meterNode_otherData
#     2023-09-16 15:26:39   data_dataNodeMap_meterNode_working 1
#     2023-09-16 15:26:39   data_lackMaster 0
#     2023-09-16 15:26:39   data_stationRunStatus 1
#     2023-09-16 15:26:39   data_stationRunType 0
#     2023-09-16 15:26:39   msg             成功
#     2023-09-16 15:26:39   time            2023-09-16 21:26:39
(Die msg bedeutet "Erfolg")
Meine Batterie ist voll geladen und die Sonne scheint, sonst wären wohl bei data_dataNodeMap_batteryNode_currentData  / data_dataNodeMap_batteryNode_originData die aktuellen Daten sichtbar.
Und ja, der Tippfehler bei "monthEneregy" ist echt :-)

minierm

#1
Ergänzung:
Mir ist beim Gesamtverbrauch jetzt die Einheit umgesprungen, ich habe die MWh geknackt :-)
Um jetzt wieder genaue Werte in kWh zu haben hilft dies:
attr MTEC userReadings data_dataNodeMap_loadNode_originData_addedBKW:data_dataNodeMap_loadNode_originData.* {ReadingsNum($NAME, "data_dataNodeMap_loadNode_originData", 0) *1000 + ReadingsNum("MQTT2_Growatt", "Power", 0)},\
data_accumulatedData_totalEnergykWh:data_accumulatedData_totalEnergy.* {ReadingsNum($NAME, "data_accumulatedData_totalEnergy", 0) *1000},\
data_accumulatedData_totalEnergy_fromtoday:data_accumulatedData_todayEnergy.* monotonic {my $val = ReadingsNum($NAME, "data_accumulatedData_todayEnergy", 0);; if (ReadingsVal($NAME, "data_accumulatedData_todayEnergyUnit", "?") eq "Wh") {$val / 1000} else {$val}}
Alternativ auch kürzeres IF:
data_accumulatedData_totalEnergy_fromtoday:data_accumulatedData_todayEnergy.* monotonic {
my $val = ReadingsNum ($name, "data_accumulatedData_todayEnergy", 0);
$val    = ReadingsVal ($name, "data_accumulatedData_todayEnergyUnit", "") eq "Wh" ? $val / 1000 : $val;
}
data_dataNodeMap_loadNode_originData_addedBKW: Daten von zweiter PV (BKW) zum Verbrauch addieren
data_accumulatedData_totalEnergykWh: Stumpfe Umrechnung von MWh in kWh, auf 10 kWh genau
data_accumulatedData_totalEnergy_fromtoday: Gesamtertrag mittels Tagesertrag präziser ermitteln (0,1 kWh/100 Wh) bzw. bei Werten kleiner 1 kWh auch Wh

Es gibt aber eine weitere Abfrage, mit der man den Gesamtertrag in kWh erhält, siehe nächstes Posting.

minierm

#2
Mit dieser Definition erhält man die Gesamtdaten des MTEC-Systems (Tab "Lebenszeit"):
(600 ist das Intervall in Sekunden, bitte ggf, anpassen)
Bei "Bat_Cycles" im StateFormat ist "11.5" die nominelle Speicherkapazität.
define MTEC_Station HTTPMOD https://energybutler.mtec-portal.com/api/sys/curve/station/queryStationBarChart 600
attr MTEC_Station enableCookies 1
attr MTEC_Station event-on-change-reading (?!.*(LAST_ERROR|code|msg|time)).*
attr MTEC_Station extractAllJSON 1
attr MTEC_Station group PV
attr MTEC_Station noShutdown 0
attr MTEC_Station reAuthAlways 0
attr MTEC_Station reAuthJSON code
attr MTEC_Station reAuthRegex 3010022
attr MTEC_Station requestData {\
"stationId":"<Your_StationID>",\
"stationType":0,\
"date":"",\
"durationType":4,\
"timeZoneOffset":120,\
"type":"init"\
}
attr MTEC_Station requestHeader1 Accept: application/json, text/javascript, */*;; q=0.01
attr MTEC_Station requestHeader2 Authorization: $sid
attr MTEC_Station requestHeader3 Cookie: token=$sid
attr MTEC_Station requestHeader4 Content-Type: application/json;; charset=UTF-8
attr MTEC_Station room Strom
attr MTEC_Station showBody 0
attr MTEC_Station showError 1
attr MTEC_Station sid01Data {\
"email": "<Your_EMail>",\
"password": "<Your_Hashed_PW>",\
"salt": "<Your_Salt>",\
"channel": "1"\
}
attr MTEC_Station sid01IdJSON data_token
attr MTEC_Station sid01URL https://energybutler.mtec-portal.com/api/sys/login/manager
attr MTEC_Station sidHeader1 Content-Type: application/json
attr MTEC_Station stateFormat <b>PV</b> data_curve_01_etotal data_config_01_unit / <b>Self</b> data_eRatioGraph_eUseSelf kWh (PVSelf%)<br>\
<b>Bat</b> data_curve_01_ebatteryCharge data_config_03_unit / data_curve_01_ebatteryDischarge data_config_04_unit (Bat_Cycles/Bat_Loss%)<br>\
<b>Export</b> data_curve_01_eselltotal data_config_05_unit / <b>Import</b> data_curve_01_ebuytotal data_config_06_unit
attr MTEC_Station userReadings PVSelf {sprintf("%0.2f", ReadingsNum($NAME, "data_eRatioGraph_eUseSelf", 0) / ReadingsNum($NAME, "data_curve_01_etotal", 0) * 100)},\
Bat_Cycles {sprintf("%0.1f", ReadingsNum($NAME, "data_curve_01_ebatteryCharge", 0) / 11.5)},\
Bat_Loss {sprintf("%0.2f", 100 - ReadingsNum($NAME, "data_curve_01_ebatteryDischarge", 0) / ReadingsNum($NAME, "data_curve_01_ebatteryCharge", 0) * 100)}

Readings:
#       code       reading
#       data       reading
#       data_config_01_key reading
#       data_config_01_name reading
#       data_config_01_unit reading
#       data_config_02_key reading
#       data_config_02_name reading
#       data_config_02_unit reading
#       data_config_03_key reading
#       data_config_03_name reading
#       data_config_03_unit reading
#       data_config_04_key reading
#       data_config_04_name reading
#       data_config_04_unit reading
#       data_config_05_key reading
#       data_config_05_name reading
#       data_config_05_unit reading
#       data_config_06_key reading
#       data_config_06_name reading
#       data_config_06_unit reading
#       data_curve_01_date reading
#       data_curve_01_eTotal reading
#       data_curve_01_ebatteryCharge reading
#       data_curve_01_ebatteryDischarge reading
#       data_curve_01_ebuytotal reading
#       data_curve_01_eselltotal reading
#       data_curve_01_etotal reading
#       data_curve_01_eusetotal reading
#       data_curve_01_income reading
#       data_curve_01_rmkElec reading
#       data_dataNodeMap_batteryNode_currentData reading
#       data_dataNodeMap_batteryNode_currentDataUnit reading
#       data_dataNodeMap_batteryNode_currentDayCurve reading
#       data_dataNodeMap_batteryNode_curveKey reading
#       data_dataNodeMap_batteryNode_flowDirection reading
#       data_dataNodeMap_batteryNode_meterWorking reading
#       data_dataNodeMap_batteryNode_nodeName reading
#       data_dataNodeMap_batteryNode_originData reading
#       data_dataNodeMap_batteryNode_otherData reading
#       data_dataNodeMap_batteryNode_working reading
#       data_dataNodeMap_inputNode_currentData reading
#       data_dataNodeMap_inputNode_currentDataUnit reading
#       data_dataNodeMap_inputNode_currentDayCurve reading
#       data_dataNodeMap_inputNode_curveKey reading
#       data_dataNodeMap_inputNode_flowDirection reading
#       data_dataNodeMap_inputNode_meterWorking reading
#       data_dataNodeMap_inputNode_nodeName reading
#       data_dataNodeMap_inputNode_originData reading
#       data_dataNodeMap_inputNode_otherData reading
#       data_dataNodeMap_inputNode_working reading
#       data_dataNodeMap_loadNode_currentData reading
#       data_dataNodeMap_loadNode_currentDataUnit reading
#       data_dataNodeMap_loadNode_currentDayCurve reading
#       data_dataNodeMap_loadNode_curveKey reading
#       data_dataNodeMap_loadNode_flowDirection reading
#       data_dataNodeMap_loadNode_meterWorking reading
#       data_dataNodeMap_loadNode_nodeName reading
#       data_dataNodeMap_loadNode_originData reading
#       data_dataNodeMap_loadNode_otherData reading
#       data_dataNodeMap_loadNode_working reading
#       data_dataNodeMap_meterNode_currentData reading
#       data_dataNodeMap_meterNode_currentDataUnit reading
#       data_dataNodeMap_meterNode_currentDayCurve reading
#       data_dataNodeMap_meterNode_curveKey reading
#       data_dataNodeMap_meterNode_flowDirection reading
#       data_dataNodeMap_meterNode_meterWorking reading
#       data_dataNodeMap_meterNode_nodeName reading
#       data_dataNodeMap_meterNode_originData reading
#       data_dataNodeMap_meterNode_otherData reading
#       data_dataNodeMap_meterNode_working reading
#       data_eRatioGraph_eDayTotal reading
#       data_eRatioGraph_eMeterTotalBuy reading
#       data_eRatioGraph_eMeterTotalSell reading
#       data_eRatioGraph_eUse reading
#       data_eRatioGraph_eUseSelf reading
#       data_eRatioGraph_edayTotal reading
#       data_eRatioGraph_emeterTotalBuy reading
#       data_eRatioGraph_emeterTotalSell reading
#       data_eRatioGraph_euse reading
#       data_eRatioGraph_euseSelf reading
#       data_eratioGraph_eDayTotal reading
#       data_eratioGraph_eMeterTotalBuy reading
#       data_eratioGraph_eMeterTotalSell reading
#       data_eratioGraph_eUse reading
#       data_eratioGraph_eUseSelf reading
#       data_eratioGraph_edayTotal reading
#       data_eratioGraph_emeterTotalBuy reading
#       data_eratioGraph_emeterTotalSell reading
#       data_eratioGraph_euse reading
#       data_eratioGraph_euseSelf reading
#       data_lackMaster reading
#       data_stationRunStatus reading
#       data_stationRunType reading
#       msg        reading
#       time       reading

Für andere Zeiträume muss man "date" und "durationType" anpassen:
Für Jahr:
date: "2023"
durationType:3
Für Monat:
date: "2023-10"
durationType:2
Für Tageswerte muss man auf "queryStationCurve" ausweichen.

minierm

Hier jetzt die Definition für Tageswerte.
Wer auch die Minutenwerte haben will löscht das Attribut "extractAllJSONFilter".
"300" ist das Intervall von 5 Minuten. Es kommen jede Menge (5-)Minuten-Daten mit...

define MTEC_Daily HTTPMOD https://energybutler.mtec-portal.com/api/sys/curve/station/queryStationCurve 300
attr MTEC_Daily enableCookies 1
attr MTEC_Daily event-on-change-reading (?!.*(LAST_ERROR|code|msg|time)).*
attr MTEC_Daily extractAllJSON 1
attr MTEC_Daily extractAllJSONFilter .*eRatioGraph.*
attr MTEC_Daily group PV
attr MTEC_Daily reAuthJSON code
attr MTEC_Daily reAuthRegex 3010022
attr MTEC_Daily replacement01Mode expression
attr MTEC_Daily replacement01Regex %%datetoday%%
attr MTEC_Daily replacement01Value {strftime('%F', localtime())}
attr MTEC_Daily requestData {\
"stationId":"<Your_StationID>",\
"stationType":0,\
"date":"%%datetoday%%",\
"durationType":1,\
"timeZoneOffset":120,\
"type":"init"\
}
attr MTEC_Daily requestHeader1 Accept: application/json, text/javascript, */*;; q=0.01
attr MTEC_Daily requestHeader2 Authorization: $sid
attr MTEC_Daily requestHeader3 Cookie: token=$sid
attr MTEC_Daily requestHeader4 Content-Type: application/json;; charset=UTF-8
attr MTEC_Daily room Strom
attr MTEC_Daily showBody 0
attr MTEC_Daily showError 1
attr MTEC_Daily sid01Data {\
"email": "<Your_EMail>,\
"password": "<Your_PW_Hash>",\
"salt": "<Your_Salt>",\
"channel": "1"\
}
attr MTEC_Daily sid01IdJSON data_token
attr MTEC_Daily sid01URL https://energybutler.mtec-portal.com/api/sys/login/manager
attr MTEC_Daily sidHeader1 Content-Type: application/json
attr MTEC_Daily stateFormat PV data_eRatioGraph_edayTotal kWh / Self data_eRatioGraph_euseSelf kWh <br>\
Export data_eRatioGraph_emeterTotalSell kWh / Import data_eRatioGraph_emeterTotalBuy kWh

Readings:
data_eRatioGraph_eDayTotal
data_eRatioGraph_eMeterTotalBuy
data_eRatioGraph_eMeterTotalSell
data_eRatioGraph_eUse
data_eRatioGraph_eUseSelf
data_eRatioGraph_edayTotal
data_eRatioGraph_emeterTotalBuy
data_eRatioGraph_emeterTotalSell
data_eRatioGraph_euse
data_eRatioGraph_euseSelf

Minutendaten:
READINGS:
#     2023-10-13 16:59:56   code            1000000
#     2023-10-13 16:59:56   data_config_01_key power
#     2023-10-13 16:59:56   data_config_01_name PV Power
#     2023-10-13 16:59:56   data_config_01_unit kW
#     2023-10-13 16:59:56   data_config_02_key loadPower
#     2023-10-13 16:59:56   data_config_02_name Load power
#     2023-10-13 16:59:56   data_config_02_unit kW
#     2023-10-13 16:59:56   data_config_03_key battery
#     2023-10-13 16:59:56   data_config_03_name Battery Power
#     2023-10-13 16:59:56   data_config_03_unit kW
#     2023-10-13 16:59:56   data_config_04_key pMeter
#     2023-10-13 16:59:56   data_config_04_name Grid power
#     2023-10-13 16:59:56   data_config_04_unit kW
#     2023-10-13 16:59:56   data_config_05_key SOC
#     2023-10-13 16:59:56   data_config_05_name SOC
#     2023-10-13 16:59:56   data_config_05_unit %

#     2023-10-13 16:59:56   data_curve_126_SOC 77.26
#     2023-10-13 16:59:56   data_curve_126_SOC_<Seriennummer> 77.26
#     2023-10-13 16:59:56   data_curve_126_battery -5.36
#     2023-10-13 16:59:56   data_curve_126_dateStamp 1697185500000
#     2023-10-13 16:59:56   data_curve_126_loadPower 0.33
#     2023-10-13 16:59:56   data_curve_126_pMeter -0.01
#     2023-10-13 16:59:56   data_curve_126_power 5.68
#     2023-10-13 16:59:56   data_curve_126_thirdPower 0

minierm

Zitat von: minierm am 16 September 2023, 16:04:17
    Hallo,
    nachdem diese Woche nach nur 4 Monaten die PV Anlage endlich vom Elektriker angeschlossen wurde kann ich jetzt Erfolg vermelden: Ich habe das M-TEC Portal per HTTPMOD an FHEM angebunden!

    Vorgehensweise:
    • Logindaten ermitteln
    • URL für Anlage ermitteln

    Per Developertools des Browsers muss man die Daten ermitteln, d.h. im Browser F12 drücken oder Strg-Umschalt+I oder:
    • Firefox: Weitere Werkzeuge/Werkzeuge für Webentwickler aktivieren
    • Edge: Weitere Tools/Entwicklungstools

    1. Logindaten ermitteln

    2. URL für Anlage ermitteln
    • Netzwerklog löschen
    • Anlage auswählen
    • URL mit "getSingleStationDataV2" kopieren
    • und bei DEF eintragen

    Hier der entsprechende Code:

define MTEC HTTPMOD https://energybutler.mtec-portal.com/api/sys/curve/station/getSingleStationDataV2?<yourdata> 60
attr MTEC enableCookies 1
attr MTEC event-on-change-reading .*
attr MTEC extractAllJSON 1
attr MTEC group PV
attr MTEC reAuthJSON code
attr MTEC reAuthRegex 3010022
attr MTEC requestHeader1 Accept: */*
attr MTEC requestHeader2 Authorization: $sid
attr MTEC requestHeader3 Cookie: token=$sid
attr MTEC room Strom
attr MTEC showError 1
attr MTEC sid01Data {\
"email": "<yourEMail>",\
"password": "<yourPWHash>",\
"salt": "<yoursalt>",\
"channel": "1"\
}
attr MTEC sid01IdJSON data_token
attr MTEC sid01URL https://energybutler.mtec-portal.com/api/sys/login/manager
attr MTEC sidHeader1 Content-Type: application/json
attr MTEC stateFormat PV data_dataNodeMap_inputNode_originData kW (H data_accumulatedData_todayEnergy data_accumulatedData_todayEnergyUnit / M data_accumulatedData_monthEneregy data_accumulatedData_monthEneregyUnit / J data_accumulatedData_yearEnergy data_accumulatedData_yearEnergyUnit) <br> \
Netz data_dataNodeMap_meterNode_currentData data_dataNodeMap_meterNode_currentDataUnit / Verbr. data_dataNodeMap_loadNode_currentData data_dataNodeMap_loadNode_currentDataUnit / Bat data_dataNodeMap_batteryNode_originData kW (data_dataNodeMap_batteryNode_otherData%) /
</code>

Kurze Erklärung:
Es wird bei der HTTP Response geschaut, ob in den JSON Daten ein code mit dem Wert "3010022" vorkommt. Wenn ja wird eine Authentifizierung erwartet. Die erfolgt über den Login-Manager, der einem in der JSON-Antwort ein Token übermittelt. Dieses Token muß dann bei jedem Request mitgeschickt werden.
Ich weiß nicht, ob das "salt" für jeden anders ist, theoretisch sollte es für alle gleich sein. Fängt bei mir mit 5c an und hört mit f4 auf.

Readings
READINGS:
#     2023-09-16 15:26:39   code            1000000
#     2023-09-16 13:36:52   data           
#     2023-09-16 15:26:39   data_accumulatedData_monthEneregy 96.1
#     2023-09-16 15:26:39   data_accumulatedData_monthEneregyUnit kWh
#     2023-09-16 15:26:39   data_accumulatedData_todayEnergy 49
#     2023-09-16 15:26:39   data_accumulatedData_todayEnergyUnit kWh
#     2023-09-16 15:26:39   data_accumulatedData_totalEnergy 96.1
#     2023-09-16 15:26:39   data_accumulatedData_totalEnergyUnit kWh
#     2023-09-16 15:26:39   data_accumulatedData_yearEnergy 96.1
#     2023-09-16 15:26:39   data_accumulatedData_yearEnergyUnit kWh
#     2023-09-16 15:26:39   data_allIsWattsonicBattery 0
#     2023-09-16 15:26:39   data_dataNodeMap_batteryNode_currentData 0
#     2023-09-16 15:26:39   data_dataNodeMap_batteryNode_currentDataUnit W
#     2023-09-16 15:26:39   data_dataNodeMap_batteryNode_currentDayCurve
#     2023-09-16 15:26:39   data_dataNodeMap_batteryNode_curveKey battery
#     2023-09-16 15:26:39   data_dataNodeMap_batteryNode_flowDirection 3
#     2023-09-16 15:26:39   data_dataNodeMap_batteryNode_meterWorking 1
#     2023-09-16 15:26:39   data_dataNodeMap_batteryNode_nodeName Battery Power
#     2023-09-16 15:26:39   data_dataNodeMap_batteryNode_originData 0
#     2023-09-16 15:26:39   data_dataNodeMap_batteryNode_otherData 100
#     2023-09-16 15:26:39   data_dataNodeMap_batteryNode_working 1
#     2023-09-16 15:26:39   data_dataNodeMap_inputNode_currentData 7.11
#     2023-09-16 15:26:39   data_dataNodeMap_inputNode_currentDataUnit kW
#     2023-09-16 15:26:39   data_dataNodeMap_inputNode_currentDayCurve
#     2023-09-16 15:26:39   data_dataNodeMap_inputNode_curveKey power
#     2023-09-16 15:26:39   data_dataNodeMap_inputNode_flowDirection 1
#     2023-09-16 15:26:39   data_dataNodeMap_inputNode_meterWorking 1
#     2023-09-16 15:26:39   data_dataNodeMap_inputNode_nodeName PV Power
#     2023-09-16 15:26:39   data_dataNodeMap_inputNode_originData 7.107
#     2023-09-16 15:26:39   data_dataNodeMap_inputNode_otherData
#     2023-09-16 15:26:39   data_dataNodeMap_inputNode_working 1
#     2023-09-16 15:26:39   data_dataNodeMap_loadNode_currentData 347
#     2023-09-16 15:26:39   data_dataNodeMap_loadNode_currentDataUnit W
#     2023-09-16 15:26:39   data_dataNodeMap_loadNode_currentDayCurve
#     2023-09-16 15:26:39   data_dataNodeMap_loadNode_curveKey loadPower
#     2023-09-16 15:26:39   data_dataNodeMap_loadNode_flowDirection 2
#     2023-09-16 15:26:39   data_dataNodeMap_loadNode_meterWorking 1
#     2023-09-16 15:26:39   data_dataNodeMap_loadNode_nodeName Load power
#     2023-09-16 15:26:39   data_dataNodeMap_loadNode_originData 0.347
#     2023-09-16 15:26:39   data_dataNodeMap_loadNode_otherData
#     2023-09-16 15:26:39   data_dataNodeMap_loadNode_working 1
#     2023-09-16 15:26:39   data_dataNodeMap_meterNode_currentData 6.76
#     2023-09-16 15:26:39   data_dataNodeMap_meterNode_currentDataUnit kW
#     2023-09-16 15:26:39   data_dataNodeMap_meterNode_currentDayCurve
#     2023-09-16 15:26:39   data_dataNodeMap_meterNode_curveKey pMeter
#     2023-09-16 15:26:39   data_dataNodeMap_meterNode_flowDirection 2
#     2023-09-16 15:26:39   data_dataNodeMap_meterNode_meterWorking 1
#     2023-09-16 15:26:39   data_dataNodeMap_meterNode_nodeName Grid power
#     2023-09-16 15:26:39   data_dataNodeMap_meterNode_originData 6.76
#     2023-09-16 15:26:39   data_dataNodeMap_meterNode_otherData
#     2023-09-16 15:26:39   data_dataNodeMap_meterNode_working 1
#     2023-09-16 15:26:39   data_lackMaster 0
#     2023-09-16 15:26:39   data_stationRunStatus 1
#     2023-09-16 15:26:39   data_stationRunType 0
#     2023-09-16 15:26:39   msg             成功
#     2023-09-16 15:26:39   time            2023-09-16 21:26:39
(Die msg bedeutet "Erfolg")
Meine Batterie ist voll geladen und die Sonne scheint, sonst wären wohl bei data_dataNodeMap_batteryNode_currentData  / data_dataNodeMap_batteryNode_originData die aktuellen Daten sichtbar.
Und ja, der Tippfehler bei "monthEneregy" ist echt :-)

Ich habe das Stateformat geändert, Einheiten angepasst und Daten ergänzt:
PV data_dataNodeMap_inputNode_originData kW (H data_accumulatedData_todayEnergy data_accumulatedData_todayEnergyUnit / M data_accumulatedData_monthEneregy data_accumulatedData_monthEneregyUnit / J data_accumulatedData_yearEnergy data_accumulatedData_yearEnergyUnit) <br> \
Netz data_dataNodeMap_meterNode_currentData data_dataNodeMap_meterNode_currentDataUnit / Verbr. data_dataNodeMap_loadNode_currentData data_dataNodeMap_loadNode_currentDataUnit / Bat data_dataNodeMap_batteryNode_originData kW (data_dataNodeMap_batteryNode_otherData%)

minierm

#5
Eins führt zum Anderen...Mir fehlten die Betriebsstunden (data_data_TimeTotal in Stunden).
Hier jetzt die Gerätedaten. Seeehr viele Parameter, sicherlich interessant für technisch Versierte. Die Programmierer sollten echt mal zur Fortbildung: Tippfehler, keine konsistente Namenskonvention (z.B. CamelCase), Konfiguration und Daten in einer API...Dazu kommen noch wechselnde Einheiten, aber immerhin wird die Einheit separat bereitgestellt.

defmod MTEC_Device_All HTTPMOD https://energybutler.mtec-portal.com/api/sys/device/getDeviceDataV3?id=1702319578461818881 600
attr MTEC_Device_All enableCookies 1
attr MTEC_Device_All event-on-change-reading (?!.*(LAST_ERROR|code|msg|time)).*
attr MTEC_Device_All extractAllJSON 1
attr MTEC_Device_All group PV
attr MTEC_Device_All icon measure_photovoltaic_inst
attr MTEC_Device_All reAuthJSON code
attr MTEC_Device_All reAuthRegex 3010022
attr MTEC_Device_All requestHeader1 Accept: */*
attr MTEC_Device_All requestHeader2 Authorization: $sid
attr MTEC_Device_All requestHeader3 Cookie: token=$sid
attr MTEC_Device_All room PV
attr MTEC_Device_All showBody 0
attr MTEC_Device_All showError 1
attr MTEC_Device_All sid01Data {\
"email": "<yourEMail>",\
"password": "<yourPWHash>",\
"salt": "<yoursalt>",\
"channel": "1"\
}
attr MTEC_Device_All sid01IdJSON data_token
attr MTEC_Device_All sid01URL https://energybutler.mtec-portal.com/api/sys/login/manager
attr MTEC_Device_All sidHeader1 Content-Type: application/json

Da mir das zu viel Daten sind habe ich diese noch auf zwei Objekte für "Config" und "Data" aufgeteilt und nur interessante Daten extrahiert.
  • data_config_01_label Inverter basic parameters
  • data_config_02_label Battery Parameters
  • data_config_03_label Inverter AC parameters
  • data_config_04_label PV Side

Für Config:
attr MTEC_Device_Config extractAllJSONFilter (code|data_config_(01_(data_(01|07|11|12|13|14|15)))|(02_(data_(01|04|07|08|09)))|(04_(data_))).*
attr MTEC_Device_Config stateFormat <B>PV</B>data_config_01_data_01_value\
data_config_01_data_07_value\
data_config_01_data_11_value\
<B>Bat</B> data_config_02_data_01_value\
data_config_02_data_08_value

Für Data:
attr MTEC_Device_Data extractAllJSONFilter (code|data_data_(ACChargerAlarm|BMS|CreationDate|E|Fault|MeterStatus|SO|Temperature|TimeTotal|UpdateDate|createTime|firmware|internalfirmwareversion|modulefirmwareversion|softwareversion)).*
attr MTEC_Device_Data stateFormat <b>BatCycles</b> Bat_Cycles <b>BatLoss</b> Bat_Loss%\
<b>BMS</b> <b>E</b> data_data_BMS_Error_Code <b>W</b> data_data_BMS_Warn_Code <b>SOH</b> data_data_SOH%<br>\
<b>Total:</b> TimeTotal_Days Tage (data_data_TimeTotal h) <b>Self</b> PVSelf_Ratio%<br>\
<b>firmwareType:</b> data_data_firmwareType\
<b>firmwareversion:</b> data_data_firmwareversion\
<b>internalfirmwareversion:</b> data_data_internalfirmwareversion\
<b>modulefirmwareversion:</b> data_data_modulefirmwareversion\
<b>softwareversion:</b> data_data_softwareversion
attr MTEC_Device_Data userReadings TimeTotal_Days {sprintf("%0.1f", ReadingsNum($NAME, "data_data_TimeTotal", 0) / 24)},\
EtotalPv_Self {sprintf("%0.2f", ReadingsNum($NAME, "data_data_EtotalPv", 0) - ReadingsNum($NAME, "data_data_EsellTotal", 0))},\
PVSelf_Ratio {sprintf("%0.2f", ReadingsNum($NAME, "EtotalPv_Self", 0) / ReadingsNum($NAME, "data_data_EtotalPv", 0) * 100)},\
Bat_Cycles {sprintf("%0.1f", ReadingsNum($NAME, "data_data_ETotalbatteryCharge", 0) / ReadingsNum($NAME, "data_data_BatCapacity", 0))},
Bat_Loss {sprintf("%0.2f", (ReadingsNum($NAME, "data_data_ETotalbatteryCharge", 0) - ReadingsNum($NAME, "data_data_ETotalbatteryDischarge", 0)) / ReadingsNum($NAME, "data_data_ETotalbatteryCharge", 0) * 100)}

minierm

Wer es gerne etwas geheimer möchte verwendet "set storeKeyValue" mit z.B. "password passwordhash"
(replacement05Mode nur für MTEC_Daily)
attr MTEC_Daily replacement01Mode key
attr MTEC_Daily replacement01Regex %%password%%
attr MTEC_Daily replacement01Value password
attr MTEC_Daily replacement02Mode key
attr MTEC_Daily replacement02Regex %%salt%%
attr MTEC_Daily replacement02Value salt
attr MTEC_Daily replacement03Mode key
attr MTEC_Daily replacement03Regex %%stationId%%
attr MTEC_Daily replacement03Value stationId
attr MTEC_Daily replacement04Mode key
attr MTEC_Daily replacement04Regex %%email%%
attr MTEC_Daily replacement04Value email
attr MTEC_Daily replacement05Mode expression
attr MTEC_Daily replacement05Regex %%datetoday%%
attr MTEC_Daily replacement05Value {strftime('%F', localtime())}
attr MTEC_Daily requestData {\
"stationId":"%%stationId%%",\
"stationType":0,\
"date":"%%datetoday%%",\
"durationType":1,\
"timeZoneOffset":120,\
"type":"init"\
}
attr MTEC_Daily sid01Data {\
"email": "%%email%%",\
"password": "%%password%%",\
"salt": "%%salt%%",\
"channel": "1"\
}

minierm

#7
Zitat von: minierm am 13 Oktober 2023, 16:45:33Mit dieser Definition erhält man die Gesamtdaten des MTEC-Systems (Tab "Lebenszeit"):
(600 ist das Intervall in Sekunden, bitte ggf, anpassen)
define MTEC_Station HTTPMOD https://energybutler.mtec-portal.com/api/sys/curve/station/queryStationBarChart 600
attr MTEC_Station enableCookies 1
attr MTEC_Station event-on-change-reading (?!.*(LAST_ERROR|code|msg|time)).*
attr MTEC_Station extractAllJSON 1
attr MTEC_Station group PV
attr MTEC_Station noShutdown 0
attr MTEC_Station reAuthAlways 0
attr MTEC_Station reAuthJSON code
attr MTEC_Station reAuthRegex 3010022
attr MTEC_Station requestData {\
"stationId":"<Your_StationID>",\
"stationType":0,\
"date":"",\
"durationType":4,\
"timeZoneOffset":120,\
"type":"init"\
}
attr MTEC_Station requestHeader1 Accept: application/json, text/javascript, */*;; q=0.01
attr MTEC_Station requestHeader2 Authorization: $sid
attr MTEC_Station requestHeader3 Cookie: token=$sid
attr MTEC_Station requestHeader4 Content-Type: application/json;; charset=UTF-8
attr MTEC_Station room Strom
attr MTEC_Station showBody 0
attr MTEC_Station showError 1
attr MTEC_Station sid01Data {\
"email": "<Your_EMail>",\
"password": "<Your_Hashed_PW>",\
"salt": "<Your_Salt>",\
"channel": "1"\
}
attr MTEC_Station sid01IdJSON data_token
attr MTEC_Station sid01URL https://energybutler.mtec-portal.com/api/sys/login/manager
attr MTEC_Station sidHeader1 Content-Type: application/json
attr MTEC_Station stateFormat <b>PV</b> data_curve_01_etotal data_config_01_unit / <b>Self</b> data_eRatioGraph_eUseSelf kWh (PVSelf%)<br>\
<b>Bat</b> data_curve_01_ebatteryCharge data_config_03_unit / data_curve_01_ebatteryDischarge data_config_04_unit (Bat_Cycles/Bat_Loss%)<br>\
<b>Export</b> data_curve_01_eselltotal data_config_05_unit / <b>Import</b> data_curve_01_ebuytotal data_config_06_unit
attr MTEC_Station userReadings PVSelf {sprintf("%0.2f", ReadingsNum($NAME, "data_eRatioGraph_eUseSelf", 0) / ReadingsNum($NAME, "data_curve_01_etotal", 0) * 100)},\
Bat_Cycles {sprintf("%0.1f", ReadingsNum($NAME, "data_curve_01_ebatteryCharge", 0) / 11.5)},\
Bat_Loss {sprintf("%0.2f", 100 - ReadingsNum($NAME, "data_curve_01_ebatteryDischarge", 0) / ReadingsNum($NAME, "data_curve_01_ebatteryCharge", 0) * 100)}

Readings:
#       code       reading
#       data       reading
#       data_config_01_key reading
#       data_config_01_name reading
#       data_config_01_unit reading
#       data_config_02_key reading
#       data_config_02_name reading
#       data_config_02_unit reading
#       data_config_03_key reading
#       data_config_03_name reading
#       data_config_03_unit reading
#       data_config_04_key reading
#       data_config_04_name reading
#       data_config_04_unit reading
#       data_config_05_key reading
#       data_config_05_name reading
#       data_config_05_unit reading
#       data_config_06_key reading
#       data_config_06_name reading
#       data_config_06_unit reading
#       data_curve_01_date reading
#       data_curve_01_eTotal reading
#       data_curve_01_ebatteryCharge reading
#       data_curve_01_ebatteryDischarge reading
#       data_curve_01_ebuytotal reading
#       data_curve_01_eselltotal reading
#       data_curve_01_etotal reading
#       data_curve_01_eusetotal reading
#       data_curve_01_income reading
#       data_curve_01_rmkElec reading
#       data_dataNodeMap_batteryNode_currentData reading
#       data_dataNodeMap_batteryNode_currentDataUnit reading
#       data_dataNodeMap_batteryNode_currentDayCurve reading
#       data_dataNodeMap_batteryNode_curveKey reading
#       data_dataNodeMap_batteryNode_flowDirection reading
#       data_dataNodeMap_batteryNode_meterWorking reading
#       data_dataNodeMap_batteryNode_nodeName reading
#       data_dataNodeMap_batteryNode_originData reading
#       data_dataNodeMap_batteryNode_otherData reading
#       data_dataNodeMap_batteryNode_working reading
#       data_dataNodeMap_inputNode_currentData reading
#       data_dataNodeMap_inputNode_currentDataUnit reading
#       data_dataNodeMap_inputNode_currentDayCurve reading
#       data_dataNodeMap_inputNode_curveKey reading
#       data_dataNodeMap_inputNode_flowDirection reading
#       data_dataNodeMap_inputNode_meterWorking reading
#       data_dataNodeMap_inputNode_nodeName reading
#       data_dataNodeMap_inputNode_originData reading
#       data_dataNodeMap_inputNode_otherData reading
#       data_dataNodeMap_inputNode_working reading
#       data_dataNodeMap_loadNode_currentData reading
#       data_dataNodeMap_loadNode_currentDataUnit reading
#       data_dataNodeMap_loadNode_currentDayCurve reading
#       data_dataNodeMap_loadNode_curveKey reading
#       data_dataNodeMap_loadNode_flowDirection reading
#       data_dataNodeMap_loadNode_meterWorking reading
#       data_dataNodeMap_loadNode_nodeName reading
#       data_dataNodeMap_loadNode_originData reading
#       data_dataNodeMap_loadNode_otherData reading
#       data_dataNodeMap_loadNode_working reading
#       data_dataNodeMap_meterNode_currentData reading
#       data_dataNodeMap_meterNode_currentDataUnit reading
#       data_dataNodeMap_meterNode_currentDayCurve reading
#       data_dataNodeMap_meterNode_curveKey reading
#       data_dataNodeMap_meterNode_flowDirection reading
#       data_dataNodeMap_meterNode_meterWorking reading
#       data_dataNodeMap_meterNode_nodeName reading
#       data_dataNodeMap_meterNode_originData reading
#       data_dataNodeMap_meterNode_otherData reading
#       data_dataNodeMap_meterNode_working reading
#       data_eRatioGraph_eDayTotal reading
#       data_eRatioGraph_eMeterTotalBuy reading
#       data_eRatioGraph_eMeterTotalSell reading
#       data_eRatioGraph_eUse reading
#       data_eRatioGraph_eUseSelf reading
#       data_eRatioGraph_edayTotal reading
#       data_eRatioGraph_emeterTotalBuy reading
#       data_eRatioGraph_emeterTotalSell reading
#       data_eRatioGraph_euse reading
#       data_eRatioGraph_euseSelf reading
#       data_eratioGraph_eDayTotal reading
#       data_eratioGraph_eMeterTotalBuy reading
#       data_eratioGraph_eMeterTotalSell reading
#       data_eratioGraph_eUse reading
#       data_eratioGraph_eUseSelf reading
#       data_eratioGraph_edayTotal reading
#       data_eratioGraph_emeterTotalBuy reading
#       data_eratioGraph_emeterTotalSell reading
#       data_eratioGraph_euse reading
#       data_eratioGraph_euseSelf reading
#       data_lackMaster reading
#       data_stationRunStatus reading
#       data_stationRunType reading
#       msg        reading
#       time       reading

Für andere Zeiträume muss man "date" und "durationType" anpassen:
Für Jahr:
date: "2023"
durationType:3
Für Monat:
date: "2023-10"
durationType:2
Für Tageswerte muss man auf "queryStationCurve" ausweichen.

Update des Stateformat für MTEC_Station, bei "Bat_Cycles" ist "11.5" die nominelle Speicherkapazität:
attr MTEC_Station stateFormat <b>PV</b> data_curve_01_etotal data_config_01_unit / <b>Self</b> data_eRatioGraph_eUseSelf kWh (PVSelf%)<br>\
<b>Bat</b> data_curve_01_ebatteryCharge data_config_03_unit / data_curve_01_ebatteryDischarge data_config_04_unit (Bat_Cycles/Bat_Loss%)<br>\
<b>Export</b> data_curve_01_eselltotal data_config_05_unit / <b>Import</b> data_curve_01_ebuytotal data_config_06_unit
attr MTEC_Station userReadings PVSelf {sprintf("%0.2f", ReadingsNum($NAME, "data_eRatioGraph_eUseSelf", 0) / ReadingsNum($NAME, "data_curve_01_etotal", 0) * 100)},\
Bat_Cycles {sprintf("%0.1f", ReadingsNum($NAME, "data_curve_01_ebatteryCharge", 0) / 11.5)},\
Bat_Loss {sprintf("%0.2f", 100 - ReadingsNum($NAME, "data_curve_01_ebatteryDischarge", 0) / ReadingsNum($NAME, "data_curve_01_ebatteryCharge", 0) * 100)}

minierm

Vorsicht:
Bei einigen Werten gibt es zwischendurch einen Einbruch:
Statt MTEC_Station data_curve_01_eTotal muss ich MTEC_Station data_eRatioGraph_eDayTotal nehmen obwohl es kein Tageswert ist.
Ähnlich beim Verbrauch, MTEC_Station data_eRatioGraph_eUse statt MTEC_Station data_curve_01_eusetotal.
Du darfst diesen Dateianhang nicht ansehen.