Skip to content

Instantly share code, notes, and snippets.

@dnoegel
Created August 26, 2023 14:22
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save dnoegel/c6cb7f176d25199c0575dce97ee87253 to your computer and use it in GitHub Desktop.
Save dnoegel/c6cb7f176d25199c0575dce97ee87253 to your computer and use it in GitHub Desktop.
Typescript Modbus Iobroker
var dec, number, bitPosition, einspeisung, timeout2, timeout;
// Beschreibe diese Funktion …
async function extractRunningStates(dec) {
function decToBit(dec, bitPosition) {
return (dec & (1 << bitPosition)) === 0 ? false : true;
}
// Creates a state if it does not exist yet
function createStateIfNotExists(state, name)
{
// createState(state, 0, true, {name: name, type: "number", role: 'value'}, function () {});
if ( !existsState(state )) {
createState(state, 0, false, {name: name, type: "number", role: 'value'}, function () {});
}
}
// Create states
createStateIfNotExists("0_userdata.0.PV.PvToLoad", "Power from PV to load");
createStateIfNotExists("0_userdata.0.PV.PvToBat", "Power from PV to bat");
createStateIfNotExists("0_userdata.0.PV.PvToGrid", "Power from PV to grid");
createStateIfNotExists("0_userdata.0.PV.BatToLoad", "Power from Bat to load");
createStateIfNotExists("0_userdata.0.PV.BatToGrid", "Power from Bat to grid");
createStateIfNotExists("0_userdata.0.PV.GridToLoad", "Power from grid to load");
createStateIfNotExists("0_userdata.0.PV.GridToBat", "Power from Gridto battery");
createStateIfNotExists("0_userdata.0.PV.SignedBat", "Battery but with minus sign for charging");
// Decode running state flags
$powerGeneratedFromPV = decToBit(dec, 0);
$batteryCharging = decToBit(dec, 1);
$batteryDischarging = decToBit(dec, 2);
$loadActive = decToBit(dec, 3);
$powerFeedIntoGrid = decToBit(dec, 4);
$powerImportFromGrid = decToBit(dec, 5);
$powerGeneratedFromLoad = decToBit(dec, 7);
// Save running state more speaking fields
setState("0_userdata.0.PV.PowerGeneratedFromPV", $powerGeneratedFromPV, true);
setState("0_userdata.0.PV.BatteryCharging", $batteryCharging, true);
setState("0_userdata.0.PV.BatteryDischarging", $batteryDischarging, true);
setState("0_userdata.0.PV.LoadActive", $loadActive, true);
setState("0_userdata.0.PV.PowerFeedIntoGrid", $powerFeedIntoGrid, true);
setState("0_userdata.0.PV.PowerImportFromGrid", $powerImportFromGrid, true);
setState("0_userdata.0.PV.PowerGeneratedFromLoad", $powerGeneratedFromLoad, true);
// Read current power levels of bat, pv, load and grid
$load = getState("modbus.0.inputRegisters.13007_Load_power_").val;
$grid = getState("modbus.0.inputRegisters.13009_Export_power").val;
$pv = getState("modbus.0.inputRegisters.5016_Total_DC_Power").val;
//$pv = getState("modbus.0.inputRegisters.13033_Total_active_power").val; // This register gives more plausible values regarding pvToGrid and the actual grid values. But was wrong by a few 100 watts in the mornung
$battery = getState("modbus.0.inputRegisters.13021_Battery_power_").val;
// Write signed bat
setState("0_userdata.0.PV.SignedBat", $batteryCharging ? $battery * -1 : $battery, true);
// Calculate PV
$pvToBat = 0;
$pvToLoad = 0;
$pvToGrid = 0;
$loadRemaining = $load;
if ($powerGeneratedFromPV) {
$remaining = $pv;
if ($remaining > $loadRemaining) {
$pvToLoad = $loadRemaining;
$remaining -= $load;
$loadRemaining = 0;
} else {
$pvToLoad = $remaining;
$loadRemaining = $load - $remaining;
$remaining = 0;
}
if ($batteryCharging) {
if ($remaining > $battery) {
$pvToBat = $battery;
$remaining -= $battery;
} else {
$pvToBat = $remaining;
$remaining = 0;
}
}
if ($grid > 0) {
$pvToGrid = Math.min($grid, $remaining);
}
}
setState("0_userdata.0.PV.PvToLoad", $pvToLoad);
setState("0_userdata.0.PV.PvToBat", $pvToBat);
setState("0_userdata.0.PV.PvToGrid", $pvToGrid);
// Calculate Bat
$batToLoad = 0;
$batToGrid = 0;
if ($batteryDischarging) {
$remaining = $battery;
if ($remaining > $loadRemaining) {
$batToLoad = $loadRemaining;
$remaining -= $loadRemaining;
$loadRemaining = 0;
} else {
$batToLoad = $remaining;
$loadRemaining -= $remaining;
$remaining = 0;
}
if ($powerFeedIntoGrid) {
$batToGrid = Math.min($grid, $remaining);
}
}
setState("0_userdata.0.PV.BatToLoad", $batToLoad);
setState("0_userdata.0.PV.BatToGrid", $batToGrid);
// Calculate grid
$gridToBat = 0;
$gridToLoad = 0;
if ($grid < 0) {
$remaining = Math.abs($grid);
if ($remaining > $loadRemaining) {
$gridToLoad = $loadRemaining;
$remaining -= $loadRemaining;
$loadRemaining = 0;
} else {
$gridToLoad = $remaining;
$loadRemaining -= $remaining;
$remaining = 0;
}
if ($batteryCharging) {
$gridToBat = Math.min($battery, $remaining);;
}
}
setState("0_userdata.0.PV.GridToLoad", $gridToLoad);
setState("0_userdata.0.PV.GridToBat", $gridToBat);
}
// Beschreibe diese Funktion …
async function getBit(number, bitPosition) {
return (number & (1 << bitPosition)) === 0 ? 0 : 1;
}
// Beschreibe diese Funktion …
async function debug_output(dec) {
// create some debug messages so we can check state changes in the log after the fact
console.log(('Power generation' + String(await getBit(dec, 0))));
console.log(('Battery charging' + String(await getBit(dec, 1))));
console.log(('Battery discharging' + String(await getBit(dec, 2))));
console.log(('Positive load' + String(await getBit(dec, 3))));
console.log(('Power feed into the grid' + String(await getBit(dec, 4))));
console.log(('Power from the grid' + String(await getBit(dec, 5))));
console.log(('Power from load' + String(await getBit(dec, 7))));
}
// MPPT Leistung ausmultiplizieren
on({id: [].concat(['modbus.0.inputRegisters.5010_MPPT_1_Voltage']).concat(['modbus.0.inputRegisters.5012_MPPT_2_Voltage']), change: "ne"}, async function (obj) {
setState("0_userdata.0.PV.MPPT1"/*MPPT1*/, (Math.round(parseFloat(getState("modbus.0.inputRegisters.5010_MPPT_1_Voltage").val) * getState("modbus.0.inputRegisters.5011_MPPT_1_Current").val)), true);
setState("0_userdata.0.PV.MPPT2"/*MPPT2*/, (Math.round(parseFloat(getState("modbus.0.inputRegisters.5012_MPPT_2_Voltage").val) * getState("modbus.0.inputRegisters.5013_MPPT_2_Current").val)), true);
});
// Bei Änderung von Status oder Wirkleistung
// Running state + Leistungen extrahieren
on({id: [].concat(['modbus.0.inputRegisters.13000_Running_State']).concat(['modbus.0.inputRegisters.13007_Load_power_']), change: "ne"}, async function (obj) {
await wait(50);
await extractRunningStates(getState("modbus.0.inputRegisters.13000_Running_State").val);
setState("0_userdata.0.PV.EnergyConsumptionToday"/*EnergyConsumptionToday*/, Math.round(([getState("modbus.0.inputRegisters.13016_Daily_direct__Energy_Consumption").val, getState("modbus.0.inputRegisters.13035_Daily_Import_Energy").val, getState("modbus.0.inputRegisters.13025_Daily_battery_discharge_Energy").val].reduce(function(x, y) {return x + y;}))*10)/10, true);
});
// Alle 10 Minuten: Running States ausgeben
schedule("*/10 * * * *", async function () {
});
await debug_output(getState("modbus.0.inputRegisters.13000_Running_State").val);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment