Gábor Tályai Posted July 17 Share Posted July 17 Maybe you want to integrate your Fronius inverter to your Shelly Cloud, here is the script, but before you have to make 5 virtual buttons: 1. Battery charge level: (type: Text, view: Progress bar) Virtual ID: 201 2. Power: (type Number , View: Label) Virtual ID: 202 3. Grid: (type Number , View: Label) Virtual ID: 203 4. Consumption: (type Number , View: Label) Virtual ID: 204 If your Virtual buttons have otther ID-s, then change the script, and change your Fronius local IP address. I hope it helps 🙂 // Fronius inverter IP address and API endpoint let inverter_ip = "10.10.40.14"; // Replace with the Fronius inverter IP address let api_endpoint = "/solar_api/v1/GetPowerFlowRealtimeData.fcgi"; // Fronius API endpoint // Virtual buttons IDs let battery_id = 201; let power_id = 202; let grid_id = 203; let consumption_id = 204; // New ID for consumption // Function to fetch data from Fronius inverter function fetchInverterData() { print("Starting fetchInverterData function"); // URL for the inverter API request let url = "http://" + inverter_ip + api_endpoint; Shelly.call("HTTP.GET", { url: url }, function (result, error_code, error_message) { if (error_code !== 0) { print("Error fetching inverter data: " + error_message); print("Error code: " + error_code); } else { print("HTTP GET request successful. Parsing result..."); try { let inverterData = JSON.parse(result.body); print("Received data: " + JSON.stringify(inverterData, null, 2)); // Specific data extraction and conversion to kW with 3 decimal places let power = (inverterData.Body.Data.Site.P_PV / 1000).toFixed(3); let grid = (inverterData.Body.Data.Site.P_Grid / 1000).toFixed(3); let battery_charge = Math.round(inverterData.Body.Data.Inverters["1"].SOC); // Battery state of charge (SOC) let consumption = (inverterData.Body.Data.Site.P_Load / 1000).toFixed(3); // Current consumption in kWh // Print extracted data print("Power: " + power + " kW"); print("Grid: " + grid + " kW"); print("Battery Charge: " + battery_charge + " %"); print("Consumption: " + consumption + " kWh"); // Update virtual components updateVirtualComponent(battery_id, battery_charge); updateVirtualComponent(power_id, power); updateVirtualComponent(grid_id, grid); updateVirtualComponent(consumption_id, consumption); } catch (e) { print("Error parsing inverter data: " + e.message); print("Received data: " + result.body); // Print the actual data received for debugging } } }); } // Function to update virtual components function updateVirtualComponent(component_id, value) { Shelly.call( "Number.Set", { "id": component_id, "value": value }, function(result, error_code, error_message) { if (error_code !== 0) { print("An error occurred when updating the virtual component: " + error_message); } else { print("Virtual component successfully updated. ID: " + component_id + ", Value: " + value); } } ); } // Fetch inverter data every 5 minutes Timer.set(300000, true, function () { print("Timer triggered. Fetching inverter data..."); fetchInverterData(); }); // Initial fetch to verify script is working print("Initial fetch to verify script is working..."); fetchInverterData(); 2 Quote Translate Revert translation? English (American) Finnish French German Italian Portuguese (European) Spanish Link to comment Share on other sites More sharing options...
Alexanderr Adam Posted July 18 Share Posted July 18 Cool, just tried and it worked. Thanks a lot for publishing Do you have an idea how to get the status if the Fronius Inverter is running in Backup Power mode ? Quote Translate Revert translation? English (American) Finnish French German Italian Portuguese (European) Spanish Link to comment Share on other sites More sharing options...
Gábor Tályai Posted July 18 Author Share Posted July 18 Unfortunately, I am not using the Fronius inverter in backup mode, so I don't know why it's not working. Is there any error message or indication of a problem? Quote Translate Revert translation? English (American) Finnish French German Italian Portuguese (European) Spanish Link to comment Share on other sites More sharing options...
Alexanderr Adam Posted July 20 Share Posted July 20 Backup power mode is working. I am having the heat pump and wallbox connected to the backup power and want to control both devices in case of a power outage. So, switch off heat pump when on backup power to save battery life. Quote Translate Revert translation? English (American) Finnish French German Italian Portuguese (European) Spanish Link to comment Share on other sites More sharing options...
Gábor Tályai Posted July 20 Author Share Posted July 20 (edited) On 18.7.2024 at 08:45, Alexanderr Adam said: Do you have an idea how to get the status if the Fronius Inverter is running in Backup Power mode ? So you don't get the status if the inverter is in Backup Power mode? Or I misunderstood something? Edited July 20 by Gábor Tályai Quote Translate Revert translation? English (American) Finnish French German Italian Portuguese (European) Spanish Link to comment Share on other sites More sharing options...
Gábor Tályai Posted July 20 Author Share Posted July 20 (edited) Ooh 🙂 You want to get the Power Mode status? To see in what Power Mode is in the inverter. Please run this script, when the inverter is in normal mode, and when in backup mode, and we will see, if the code is working correctly. I checked it in my Fronius Gen24, and it gives back me: Inverter mode: bidirectional (grid or backup) but I cannot set my device to Backup Power mode to test it. Anyway, here is the code - don't forget to change the IP address of the inverter. // Fronius inverter IP address and API endpoint let inverter_ip = "10.10.40.14"; // Replace with the Fronius inverter IP address let api_endpoint = "/solar_api/v1/GetPowerFlowRealtimeData.fcgi"; // Fronius API endpoint // Function to fetch data from Fronius inverter function fetchInverterMode() { print("Starting fetchInverterMode function"); // URL for the inverter API request let url = "http://" + inverter_ip + api_endpoint; Shelly.call("HTTP.GET", { url: url }, function (result, error_code, error_message) { if (error_code !== 0) { print("Error fetching inverter data: " + error_message); print("Error code: " + error_code); } else { print("HTTP GET request successful. Parsing result..."); try { let inverterData = JSON.parse(result.body); // Check the mode of the inverter let mode = inverterData.Body.Data.Site.Mode; // Assuming the mode is available in this field if (mode === "bidirectional") { print("Inverter mode: bidirectional (grid or backup)"); } else if (mode === "grid") { print("Inverter mode: grid"); } else if (mode === "backup") { print("Inverter mode: backup"); } else { print("Inverter mode: " + mode); } } catch (e) { print("Error parsing inverter data: " + e.message); print("Received data: " + result.body); // Print the actual data received for debugging } } }); } // Fetch inverter mode every 5 minutes Timer.set(300000, true, function () { print("Timer triggered. Fetching inverter mode..."); fetchInverterMode(); }); // Initial fetch to verify script is working print("Initial fetch to verify script is working..."); fetchInverterMode(); Edited July 20 by Gábor Tályai spelling Quote Translate Revert translation? English (American) Finnish French German Italian Portuguese (European) Spanish Link to comment Share on other sites More sharing options...
Alexanderr Adam Posted July 20 Share Posted July 20 Cool, thanks. I modified the script a bit to update an virtual component. My programming skills are very rusty. I was wondering that boolean virtual component got another 200 id and the value is not getting updated.... // Fronius inverter IP address and API endpoint let inverter_ip = "192.168.178.10"; // Replace with the Fronius inverter IP address let api_endpoint = "/solar_api/v1/GetPowerFlowRealtimeData.fcgi"; // Fronius API endpoint let powermode_id = 200; // Function to fetch data from Fronius inverter function fetchInverterMode() { print("Starting fetchInverterMode function"); // URL for the inverter API request let url = "http://" + inverter_ip + api_endpoint; Shelly.call("HTTP.GET", { url: url }, function (result, error_code, error_message) { if (error_code !== 0) { print("Error fetching inverter data: " + error_message); print("Error code: " + error_code); } else { print("HTTP GET request successful. Parsing result..."); try { let inverterData = JSON.parse(result.body); // Check the mode of the inverter let mode = inverterData.Body.Data.Site.Mode; // Assuming the mode is available in this field if (mode === "bidirectional") { print("Inverter mode: bidirectional (grid or backup)"); } else if (mode === "grid") { print("Inverter mode: grid"); updateVirtualComponent(powermode_id, false); } else if (mode === "backup") { print("Inverter mode: backup"); updateVirtualComponent(powermode_id, true); } else { print("Inverter mode: " + mode); } } catch (e) { print("Error parsing inverter data: " + e.message); print("Received data: " + result.body); // Print the actual data received for debugging } } }); } // Fetch inverter mode every 5 seconds Timer.set(5000, true, function () { print("Timer triggered. Fetching inverter mode..."); fetchInverterMode(); }); // Initial fetch to verify script is working print("Initial fetch to verify script is working..."); fetchInverterMode(); Quote Translate Revert translation? English (American) Finnish French German Italian Portuguese (European) Spanish Link to comment Share on other sites More sharing options...
Alexanderr Adam Posted July 20 Share Posted July 20 Modified it to include updatevirtualcomponent, but still not working ... . 😞 // Fronius inverter IP address and API endpoint let inverter_ip = "192.168.178.10"; // Replace with the Fronius inverter IP address let api_endpoint = "/solar_api/v1/GetPowerFlowRealtimeData.fcgi"; // Fronius API endpoint let powermode_id = 200; // Function to fetch data from Fronius inverter function fetchInverterMode() { print("Starting fetchInverterMode function"); // URL for the inverter API request let url = "http://" + inverter_ip + api_endpoint; Shelly.call("HTTP.GET", { url: url }, function (result, error_code, error_message) { if (error_code !== 0) { print("Error fetching inverter data: " + error_message); print("Error code: " + error_code); } else { print("HTTP GET request successful. Parsing result..."); try { let inverterData = JSON.parse(result.body); // Check the mode of the inverter let mode = inverterData.Body.Data.Site.Mode; // Assuming the mode is available in this field if (mode === "bidirectional") { print("Inverter mode: bidirectional (grid or backup)"); } else if (mode === "grid") { print("Inverter mode: grid"); updateVirtualComponentBoolean(powermode_id, true); } else if (mode === "backup") { print("Inverter mode: backup"); updateVirtualComponentBoolean(powermode_id, false); } else { print("Inverter mode: " + mode); } } catch (e) { print("Error parsing inverter data: " + e.message); print("Received data: " + result.body); // Print the actual data received for debugging } } }); } // Function to update virtual components function updateVirtualComponentBoolean(component_id, value) { Shelly.call( "Boolean.Set", { "id": component_id, "value": value }, function(result, error_code, error_message) { if (error_code !== 0) { print("An error occurred when updating the virtual component: " + error_message); } else { print("Virtual component successfully updated. ID: " + component_id + ", Value: " + value); } } ); } // Fetch inverter mode every 5 seconds Timer.set(5000, true, function () { print("Timer triggered. Fetching inverter mode..."); fetchInverterMode(); }); // Initial fetch to verify script is working print("Initial fetch to verify script is working..."); fetchInverterMode(); Quote Translate Revert translation? English (American) Finnish French German Italian Portuguese (European) Spanish Link to comment Share on other sites More sharing options...
Gábor Tályai Posted July 20 Author Share Posted July 20 Please tell me exactly, what is not working? I do not understood what is the problem. Quote Translate Revert translation? English (American) Finnish French German Italian Portuguese (European) Spanish Link to comment Share on other sites More sharing options...
Alexanderr Adam Posted July 20 Share Posted July 20 Tried to set a boolean virtual compontent with thes status OnBackupPower=True Quote Translate Revert translation? English (American) Finnish French German Italian Portuguese (European) Spanish Link to comment Share on other sites More sharing options...
Alexanderr Adam Posted July 20 Share Posted July 20 Hi Gabor, just tested the switch to Backup Power, but the status keeps as "bidirectional. Quote Translate Revert translation? English (American) Finnish French German Italian Portuguese (European) Spanish Link to comment Share on other sites More sharing options...
Alexanderr Adam Posted July 20 Share Posted July 20 Gabor, maybe this value ? Can you help me with the coding ? Quote Translate Revert translation? English (American) Finnish French German Italian Portuguese (European) Spanish Link to comment Share on other sites More sharing options...
Alexanderr Adam Posted July 20 Share Posted July 20 tested it, it is the BackupMode flagging power backup. Quote Translate Revert translation? English (American) Finnish French German Italian Portuguese (European) Spanish Link to comment Share on other sites More sharing options...
Alexanderr Adam Posted July 20 Share Posted July 20 But I still need to get a Virtual Boolean component updated. Can you please share some working sample code ? Thanks Quote Translate Revert translation? English (American) Finnish French German Italian Portuguese (European) Spanish Link to comment Share on other sites More sharing options...
Gábor Tályai Posted July 21 Author Share Posted July 21 (edited) The BackupMode is in the same api endpoint, so you can add your code to the defined places: //Virtual components let backupmode_id = 205; // Specific data extraction... let backupMode = inverterData.Body.Data.Site.BackupMode; // Print extracted data to check it in the console print("Backupmode: " + backupMode); // Update virtual components updateVirtualComponent(backupmode_id, backupMode); For me is not working now, but it should. Check it in the console to see if it is true or false, to see if the code is working. To update the virtual button: maybe there is some problem with the new firmware, because every time I make a new virtual component, then it gets ID:200. Please check it in your side too. Edited July 21 by Gábor Tályai spelling Quote Translate Revert translation? English (American) Finnish French German Italian Portuguese (European) Spanish Link to comment Share on other sites More sharing options...
Gábor Tályai Posted July 21 Author Share Posted July 21 Here is the reworked code: - Make the virtual components ID and type as in the code, or change the code - Boolean type's view must be LABEL! - Number type's unit: kWh (to see the "kWh" in the Shelly app) - Change your inverter IP address - Separated functions, you can delete if something is not useful for you You will get: - Fronius Backup mode (true/false) - Grid power - Load power - PV power - Battery SOC - Energy from/to battery // Fronius inverter IP address and API endpoint let inverter_ip = "10.10.40.14"; // Replace with the Fronius inverter IP address let api_endpoint = "/solar_api/v1/GetPowerFlowRealtimeData.fcgi"; // Fronius API endpoint // Virtual component IDs let battery_mode_id = 200; // Boolean let grid_id = 200; // Number let load_id = 201; // Number let pv_id = 202; // Number let soc_id = 203; // Number let battery_id = 204; // Number // Function to create the URL for the API request function createURL() { return "http://" + inverter_ip + api_endpoint; } // Function to handle the HTTP GET call function httpGetCall(url, callback) { Shelly.call("HTTP.GET", { url: url }, function (result, error_code, error_message) { if (error_code !== 0) { print("Error: " + error_message); } else { try { let data = JSON.parse(result.body); callback(data); } catch (e) { print("Error parsing data: " + e.message); } } }); } // Function to fetch Battery Mode function fetchBatteryMode(callback) { let url = createURL(); httpGetCall(url, function (data) { let battery_mode = data.Body.Data.Site.BackupMode; updateBooleanComponent(battery_mode_id, battery_mode); print("Battery Mode: " + battery_mode); if (callback) callback(); }); } // Function to fetch Grid data function fetchGrid(callback) { let url = createURL(); httpGetCall(url, function (data) { let grid = (data.Body.Data.Site.P_Grid / 1000).toFixed(2); updateNumberComponent(grid_id, grid); print("Grid: " + grid + " kW"); if (callback) callback(); }); } // Function to fetch Load data function fetchLoad(callback) { let url = createURL(); httpGetCall(url, function (data) { let load = (data.Body.Data.Site.P_Load / 1000).toFixed(2); updateNumberComponent(load_id, load); print("Load: " + load + " kW"); if (callback) callback(); }); } // Function to fetch PV data function fetchPV(callback) { let url = createURL(); httpGetCall(url, function (data) { let pv = (data.Body.Data.Site.P_PV / 1000).toFixed(2); updateNumberComponent(pv_id, pv); print("PV: " + pv + " kW"); if (callback) callback(); }); } // Function to fetch SOC data function fetchSOC(callback) { let url = createURL(); httpGetCall(url, function (data) { let soc = Math.round(data.Body.Data.Inverters["1"].SOC); updateNumberComponent(soc_id, soc); print("SOC: " + soc + " %"); if (callback) callback(); }); } // Function to fetch Battery data function fetchBattery(callback) { let url = createURL(); httpGetCall(url, function (data) { let battery = (data.Body.Data.Site.P_Akku / 1000).toFixed(2); updateNumberComponent(battery_id, battery); print("Battery: " + battery + " kW"); if (callback) callback(); }); } // Function to update Shelly boolean virtual component function updateBooleanComponent(component_id, value) { Shelly.call( "Boolean.Set", { "id": component_id, "value": value }, function(result, error_code, error_message) { if (error_code !== 0) { print("Error updating boolean component: " + error_message); } else { print("Boolean component updated. ID: " + component_id + ", Value: " + value); } } ); } // Function to update Shelly number virtual component function updateNumberComponent(component_id, value) { print("Updating component ID: " + component_id + " with value: " + value); Shelly.call( "Number.Set", { "id": component_id, "value": value }, function(result, error_code, error_message) { if (error_code !== 0) { print("Error updating number component: " + error_message); } else { print("Number component updated. ID: " + component_id + ", Value: " + value); } } ); } // Sequentially execute all fetch functions function fetchAllDataSequentially() { fetchBatteryMode(function () { fetchGrid(function () { fetchLoad(function () { fetchPV(function () { fetchSOC(function () { fetchBattery(); }); }); }); }); }); } // Fetch all data every 5 minutes Timer.set(300000, true, function () { fetchAllDataSequentially(); }); // Initial fetch to verify script is working fetchAllDataSequentially(); Quote Translate Revert translation? English (American) Finnish French German Italian Portuguese (European) Spanish Link to comment Share on other sites More sharing options...
Gábor Tályai Posted July 21 Author Share Posted July 21 Here is some cool, linkable icon for the Fronius virtual components: https://img.icons8.com/?size=100&id=0lTulS5AIq64&format=png&color=000000 https://img.icons8.com/?size=100&id=E0UwFzCYyf39&format=png&color=000000 https://img.icons8.com/?size=100&id=51369&format=png&color=000000 https://img.icons8.com/?size=100&id=1ltUbDhgx4RV&format=png&color=000000 https://img.icons8.com/?size=100&id=dwzqRjO6XcTN&format=png&color=000000 https://img.icons8.com/?size=100&id=ehpwHqwrNT4b&format=png&color=000000 And the result: 1 1 Quote Translate Revert translation? English (American) Finnish French German Italian Portuguese (European) Spanish Link to comment Share on other sites More sharing options...
Alexanderr Adam Posted July 21 Share Posted July 21 Cool, you are a genious. Will try later this evening. Quote Translate Revert translation? English (American) Finnish French German Italian Portuguese (European) Spanish Link to comment Share on other sites More sharing options...
Alexanderr Adam Posted July 21 Share Posted July 21 Cool, the script is working. Many thanks for your supprt. How do you get the virtual components into the app ? Is there a beta for the app ? Quote Translate Revert translation? English (American) Finnish French German Italian Portuguese (European) Spanish Link to comment Share on other sites More sharing options...
Alexanderr Adam Posted July 21 Share Posted July 21 Wondering why you are doing now individual http requests for each of the 6 value. I am looking for a more frequent update, like every 5 seconds. Isn't that a bit inefficient to query the data 6 times ? Quote Translate Revert translation? English (American) Finnish French German Italian Portuguese (European) Spanish Link to comment Share on other sites More sharing options...
Gábor Tályai Posted July 21 Author Share Posted July 21 6 minutes ago, Alexanderr Adam said: Wondering why you are doing now individual http requests for each of the 6 value. I am looking for a more frequent update, like every 5 seconds. Isn't that a bit inefficient to query the data 6 times ? I created separate functions so that if someone doesn't have a battery, they can easily delete the ones they don't need. Efficiency: does it work? 🙂 Then it’s efficient 🙂 You can safely put them into one function; based on the first code and this, it will be easy to do, at least you'll practice programming 🙂 Quote Translate Revert translation? English (American) Finnish French German Italian Portuguese (European) Spanish Link to comment Share on other sites More sharing options...
Gábor Tályai Posted July 21 Author Share Posted July 21 16 minutes ago, Alexanderr Adam said: Cool, the script is working. Many thanks for your supprt. How do you get the virtual components into the app ? Is there a beta for the app ? Thanks! Virtual components in the app: - you can create a Virtual Component group in the local web interface, and add the virtual components. You can sort the components, as you wish. - simply turn on the button on the cloud app/virtual components tab (group/components). -- but you must toggle this every time, so I recommend to make a virtual group Quote Translate Revert translation? English (American) Finnish French German Italian Portuguese (European) Spanish Link to comment Share on other sites More sharing options...
Alexanderr Adam Posted July 21 Share Posted July 21 Cool, got it Quote Translate Revert translation? English (American) Finnish French German Italian Portuguese (European) Spanish Link to comment Share on other sites More sharing options...
Alexanderr Adam Posted July 21 Share Posted July 21 Really cool stuff, advertized this thread in the German Photovoltaik Forum. https://www.photovoltaikforum.com/thread/232217-shelly-script-um-fronius-daten-per-solarapi-auszulesen-virtuelle-komponenten-zu/ Quote Translate Revert translation? English (American) Finnish French German Italian Portuguese (European) Spanish Link to comment Share on other sites More sharing options...
AlexAn Posted July 21 Share Posted July 21 (edited) Mein Fronius Symo braucht Zeile 60 mit / -1000 let load = (data.Body.Data.Site.P_Load / -1000).toFixed(2); Cooles Script 👍 Edited July 21 by AlexAn Quote Translate Revert translation? English (American) Finnish French German Italian Portuguese (European) Spanish Link to comment Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.