Börsihinna jälgimise automaatika

küttesüsteemid, millega ja kuidas kütta
ping
Ehituspenskar
Ehituspenskar
Postitusi: 4450
Liitunud: 28 Jaan 2016, 10:35
On tänanud: 86 korda
On tänatud: 223 korda

Re: Börsihinna jälgimise automaatika

Lugemata postitus Postitas ping »

kunn24 kirjutas: 09 Veebr 2023, 18:14 Tulemus:
tarbimine.JPG
Pilt
Scripti tuli veel siluda, timerile kirjutasin 3660 s (61*60), sest muidu iga tunni lõpus klõpsutas asjatult releed, läbustas lülitamiste logi ja saatis mulle põhjuseta teavituse, et küte on väljas ja uuesti sees.
Nagu ka sellelt pildilt on näha, et väiksema päevatarbimise juures tekitab olulise kokkuhoiu, juba kui kasutada kasvõi lihtsat aegreleed või aegreleena programmeeritavat termostaati.
:hello:
Kõik ohutustehnika reeglid on kirjutatud kellegi verega!!!
kunn24
Ehituspenskar
Ehituspenskar
Postitusi: 2048
Liitunud: 11 Veebr 2018, 14:45
On tänanud: 32 korda
On tänatud: 68 korda

Re: Börsihinna jälgimise automaatika

Lugemata postitus Postitas kunn24 »

Ei saanud aru, Shelly jubin on juba piisavalt odav ja lihtsalt paigaldatav, et milleks muu keberniit? Ainuke seletus, kui netile ligipääs puudub.
Kuid kõige lihtsam viis kokku hoida on mõttetud tarbijad välja lülitada. Ega see pesuruumi põranda kütminegi väga vajalik pole, rohkem mugavusteema. Saab ka selle ruumi ukse kinni panna ja jahedamana hoida.

Kuid kui Bh-s vastavad hinnalohud sees on, võib ju need ära kasutada. Ainult aegreleega ei tee seda kuidagi, kui just käsitsi pidevalt ei taha sisselülitamist juhtida.
Bh3.JPG
Ma tellisin mõned jubinad juurde, plaanis on need pista ventagregaadi, teise korruse pesuruumi põrandakütte ja võimalik, et ka käterätikuivatite ette. Lisaks ka võimalik, et pistan ka ÕSP ette, mis mul majas on. Pean hakkama oma kunagisi sõnu sööma, et nutividinad on saatanast. ;). Sest kui Bh selliste lohkude ajal ÕSP käima lasta, siis on see energia päris tasuta käes. Ok, võrgutasu lisandub, sellega peab hakkama arvestama. Lisaks peab arvestama, et mõnikord soodasaid Bh lohkusid üldse ei tule, kuid Shelly haldusprogrammis on hea valik, moodustada gruppe, siis saab 1 nupuvajutusega kogu krempli välja lülitada.
Mäluvärkendsueks, UT hind on praegu 18,49 koos KM-ga ja Elektrikella Bh graafik ka koos KM-ga.

GetBalticu gaasihinnad on ka huvitaval kursil https://www.getbaltic.com/en/
vtl
Ehitusveteran
Ehitusveteran
Postitusi: 1732
Liitunud: 25 Juul 2006, 19:13
On tänanud: 8 korda
On tänatud: 109 korda

Re: Börsihinna jälgimise automaatika

Lugemata postitus Postitas vtl »

kunn24 kirjutas: 12 Veebr 2023, 13:34...Sest kui Bh selliste lohkude ajal ÕSP käima lasta, siis on see energia päris tasuta käes. Ok, võrgutasu lisandub, sellega peab hakkama arvestama. Lisaks peab arvestama, et mõnikord soodasaid Bh lohkusid üldse ei tule
[...]
Mäluvärkendsueks, UT hind on praegu 18,49 koos KM-ga
Tuletan meelde, et mitte kuigi palju aega tagasi nägi igapäevaselt ka sellist graafikut (allpool). Kui ka tunniajane "lohk" tekkis, kus hind oli 70 sendi asemel tund aega 35 senti, siis sellega ei kütnud soojaks ei boilerit ega tuba.
borsihind.jpeg
kunn24
Ehituspenskar
Ehituspenskar
Postitusi: 2048
Liitunud: 11 Veebr 2018, 14:45
On tänanud: 32 korda
On tänatud: 68 korda

Re: Börsihinna jälgimise automaatika

Lugemata postitus Postitas kunn24 »

Nii, ja mida me selle mäluvärskendusega HETKEL peale hakkame? Mul on kollektiivne OFF nupp ka olemas. Kirjutasin ju: Kuid kui Bh-s vastavad hinnalohud sees on, võib ju need ära kasutada.
Aga.. sa ära siis neid kasuta, vaba valik ju. Kipub sinna kanti, kui eile poes saia polnud ja täna on, siis ära ikka poodi mine, sest mine tea, äkki homme jälle ei ole. ;)
Sa IT inimesena võiksid pigem mõelda positiivselt ja vaadata, kas on midagi paremat nendest vidinatest, mis sama ilusti või paremini selliseid ülesandeid lahendaks.
vtl
Ehitusveteran
Ehitusveteran
Postitusi: 1732
Liitunud: 25 Juul 2006, 19:13
On tänanud: 8 korda
On tänatud: 109 korda

Re: Börsihinna jälgimise automaatika

Lugemata postitus Postitas vtl »

kunn24 kirjutas: 12 Veebr 2023, 18:11 Nii, ja mida me selle mäluvärskendusega HETKEL peale hakkame?
[…]
Sa IT inimesena võiksid pigem mõelda positiivselt ja vaadata, kas on midagi paremat nendest vidinatest, mis sama ilusti või paremini selliseid ülesandeid lahendaks.
Ma olin pikka aega ka bõrsiusku, aga detsembris võtsin siiski pikaajalise kahetariifse fixpaketi (mis tuli odavam kui UT) ja selletõttu ei ole vajadus enam lohkusid jahtida. Kui need odavtunnid oleksid iga öö garanteeritud, siis seel saaks targa ajatamise ja salvestamisega hakkama, aga enne ei usu, kui aastakene on börsihind enam-vähem stabiilne püsinud (st. keskmine alla 10…15 sendi)

Mis on parem? Sõltub ülejäänud infrast ju. Mul on enam-vähem kõikehõlmav ja pilvest sõltumatu koduautomaatika juba palju aastaid olemas olnud, sellele oli vaja ainult ühte väikest skripti, mis Nordpoolis hinda lugemas käib ja loogikat, mis otsustab, millal tarbida.
kunn24
Ehituspenskar
Ehituspenskar
Postitusi: 2048
Liitunud: 11 Veebr 2018, 14:45
On tänanud: 32 korda
On tänatud: 68 korda

Re: Börsihinna jälgimise automaatika

Lugemata postitus Postitas kunn24 »

Ei ole mingit usku, lihtne konstateering. Kui see muutub, muutub ka pakett.
vtl
Ehitusveteran
Ehitusveteran
Postitusi: 1732
Liitunud: 25 Juul 2006, 19:13
On tänanud: 8 korda
On tänatud: 109 korda

Re: Börsihinna jälgimise automaatika

Lugemata postitus Postitas vtl »

kunn24 kirjutas: 12 Veebr 2023, 20:21 Ei ole mingit usku, lihtne konstateering. Kui see muutub, muutub ka pakett.
Kõik on õige. Lihtsalt sellega kaasnevad mõned nüansid:
* Börsihinnal tuleb siis ikkagi automaatikast sõltumata pidevalt silma peal hoida. See on stress ja tüli;
* Paketti saab muuta kord kuus ja 1. kuupäeva seisuga (vähemalt minu energiamüüja juures);
* Kui keskmine börsihind hakkab tõusma, siis tõusevad kohe ka fixpaketi hinnad. (*

*) Ei taha kedagi reklaamida, aga täna on A-tähega algava energiamüüja juures pikaajaline pakett 15 / 12 s/kWh (päev / öö). Keskmine 13.5 s. Need on käibega hinnad. Jah, ei ole kriisieelne 5 senti, aga samas kannatab sellega veel elada. Jah, katkestamistasu on ka, aga mitte nii röövellik, nagu E-tähega algavas ettevõttes. Kui elektrihind läheb niipalju odavamaks, et kuu kokkuhoid ületaks pikas perspektiivis 20€, siis kannatab ka väljumistasu maksta.


fixhind.png
kunn24
Ehituspenskar
Ehituspenskar
Postitusi: 2048
Liitunud: 11 Veebr 2018, 14:45
On tänanud: 32 korda
On tänatud: 68 korda

Re: Börsihinna jälgimise automaatika

Lugemata postitus Postitas kunn24 »

Siis on ju kõik ok, kui A-tähega müüja on leidnud, et elektrifutuurid on 12/10 s ja ta saab need sulle edasi müüa 15/12-ga. Järelikult kannatab ka ise börsipaketti pidada seda enam, kui lihtne automaatika peale lasta sellistele tarbijatele, mis on suutelised salvestama vms taolised.
Kui tähele panid, siis selle paketi hinna ta pakkus välja alles 02.02. Ega seal ka lollid pole ja võrreldes meie mõne hetkelise börsihinnavaatlemisega on neil selleks terve kamp "sägasid", kes analüüsivad kõik läbi enne, kui õnged välja viskavad.
Kuid 15/12 hind on ka täiesti ok, see on hea info, et sellisega on nüüd välja tuldud. Alles EE pakkus 15,49 s pluss kuutasu 1,99 s 84-ks kuuks. Tendents suure tõenäosusega võib olla allapoole. Vaata ka gaasibörsil GetBaltic toimuvat.
Viimati muutis kunn24, 12 Veebr 2023, 21:39, muudetud 1 kord kokku.
vtl
Ehitusveteran
Ehitusveteran
Postitusi: 1732
Liitunud: 25 Juul 2006, 19:13
On tänanud: 8 korda
On tänatud: 109 korda

Re: Börsihinna jälgimise automaatika

Lugemata postitus Postitas vtl »

kunn24 kirjutas: 12 Veebr 2023, 21:20 Siis on ju kõik ok, kui A-tähega müüja on leidnud, et elektrifutuurid on 12/10 s ja ta saab need sulle edasi müüa 15/12-ga. Järelikult kannatab ka ise börsipaketti pidada seda enam, kui lihtne automaatika peale lasta sellistele tarbijatele, mis on suutelised salvestama vms taolised.
Kui tähele panid, siis selle paketi hinna ta pakkus välja alles 02.02. Ega seal ka lollid pole ja võrreldes meie mõne hetkelise börsihinnavaatlemisega on neil selleks terve kamp "sägasid", kes analüüsivad kõik läbi enne, kui õnged välja viskavad.
Kuid 15/12 hind on ka täiesti ok, see on hea info, et sellisega on nüüd välja tuldud.
Mulle on praegusel ajal mulje jäänud (niivähe, kui ma elektri hinnamajandusest üldse tean), et futuuride hind ei pruugi olla otseses korrelatsioonis börsihinnaga, vaid sisaldab mõõdukas koguses müüja riski kui ette ostetud laskmata karude nahkasid. Ehk mingis koguses saab ka ette osta nt. alla börsihinna.
Jah, see pakett tuli välja alles veebr. alguses ja mulle tundub, et vastusena E-tähega Ettevõte pikaajalisele mürkrohelisele paketile 15.5 s/kWh. Ehk praegu võideldakse pikaajaliselt seotud klientide pärast.
vtl
Ehitusveteran
Ehitusveteran
Postitusi: 1732
Liitunud: 25 Juul 2006, 19:13
On tänanud: 8 korda
On tänatud: 109 korda

Re: Börsihinna jälgimise automaatika

Lugemata postitus Postitas vtl »

kunn24 kirjutas: 12 Veebr 2023, 21:20...Kui tähele panid, siis selle paketi hinna ta pakkus välja alles 02.02. Ega seal ka lollid pole ja võrreldes meie mõne hetkelise börsihinnavaatlemisega on neil selleks terve kamp "sägasid", kes analüüsivad kõik läbi enne, kui õnged välja viskavad...
Ma enne kirjutasin, et mina sõlmisin lepingu detsembri alguses, kui hind oli 17.5/13.5 s/kWh käibega, keskmine 15.5 s ehk 2 senti kallim praegusest. Loetud päevad peale seda tõstis A-tähega ettevõte oma fixhinda veel mõned sendid üles (vt. hinna-ajaloo graafikut paar posti ülalpool). Detsembri keskmine börsihind oli siis 32 s / 21 s päev/öö.

Ehk detsembri keskel korraks üles tõstetud fixhinna küür näitab tegelikult seda, et sealsed hiromandid ka ei teadnud täpselt, mis veebruaris juhtuma hakkab.
kunn24
Ehituspenskar
Ehituspenskar
Postitusi: 2048
Liitunud: 11 Veebr 2018, 14:45
On tänanud: 32 korda
On tänatud: 68 korda

Re: Börsihinna jälgimise automaatika

Lugemata postitus Postitas kunn24 »

Tegelt praegu leidsin scriptis puuduse, tal peaks saama määrata hinnapiiri, üle mille ei lülita. Piir võiks olla näiteks 60 €/MWh ja olema koodist muudetav stiilis: let PriceLimit = 60

Teed ära? Siis saaks tõepoolest rakendada mõtet, et pole vaja neid börsihindu vahtida, vaid panna kriteerium paika ja unustada.

Praegu on mul töös selline asi:

Kood: Vali kõik

 // This script is calculating next day heating time based on weather forecast, 
// and turn on your heating system for cheapest hours based on electricity market price.

// It's scheduled to run daily after 23:00 to set heating timeslots for next day.
// by Leivo Sepp, 14.01.2023
// Energy Market price is downloaded from Elering API https://dashboard.elering.ee/assets/api-doc.html#/nps-controller/getPriceUsingGET. 
// Weather forecast is based on free Open-Meteo API https://open-meteo.com/en/docs

// Set the country Estonia-ee, Finland-fi, Lthuania-lt, Latvia-lv
// No other countries support exist trough Elering API. 
let country = "ee";

// Parameter heatingCurve is used to set proper heating curve for your house. This is very personal and also crucial component.
// You can start with the default number 5, and take a look how this works for you.
// If you feel cold, then increase this number. If you feel too warm, then decrease this number.
// You can see the dependency of temperature and and this parameter from this visualization: "link will be here..."
// Heating hours are calculated by this quadratic equation: (startingTemp-avgTemp)^2 + (heatingCurve / powerFactor) * (startingTemp-avgTemp)
let heatingCurve = 1;

// Parameter startingTemp is used as starting point for heating curve.
// For example if startingTemp = 10, then the heating is not turned on for any temperature warmer than 10 degrees.
let startingTemp = 18;

// powerFactor is used to set quadratic equation parabola curve flat or steep. Change it with your own responsibility.
let powerFactor = 0.2;

// This parameter used to set a number of heating hours in a day in case the weather forecast fails. Number 1-24. 
// If Shelly was able to get the forecast, then this number is owerwritten by the heating curve calculation.
// For example if this number is set to 5 then Shelly will be turned on for 5 most cheapest hours during a day. 
// If the cheapest hours are 02:00, 04:00, 07:00, 15:00 and 16:00, then the Shelly is turned on 02-03, 04-05, 07-08 and 15-17 (two hours in a row).
let heatingTime = 5;

// If getting electricity prices from Elering fails, then use this number as a time to start Shelly. 2 means 02:00. 
// For example if there is no internet connection at all, and heatingTime=5, default_start_time=1 then the Shelly is turned on from 01:00 to 06:00
let default_start_time = 1;

// Keep this is_reverse value "false", I think 99% of the situations are required so.
// Rarely some heating systems requires reversed relay. Put this "true" if you are sure that your appliance requires so.
// For example my personal ground source heat pump requires reversed management. If Shelly relay is activated (ON), then the pump is turned off.
let is_reverse = false;

// This is timezone for EE, LT, LV and FI.
// Do not change this because it won't work currently for other timezones.
let timezone = 2;

// some global variables
let openMeteoUrl = "https://api.open-meteo.com/v1/forecast?daily=temperature_2m_max,temperature_2m_min&timezone=auto";
let eleringUrl = "https://dashboard.elering.ee/api/nps/price";
let data_indx;
let sorted = [];
let weatherDate;
let dateStart;
let dateEnd;
let lat = JSON.stringify(Shelly.getComponentConfig("sys").location.lat);
let lon = JSON.stringify(Shelly.getComponentConfig("sys").location.lon);
let shellyUnixtime = Shelly.getComponentStatus("sys").unixtime;

// Crontab for running this script. 
// This script is run at random moment during the first 15 minutes after 23:00
// Random timing is used so that all clients wouldn't be polling the server exactly at same time
let minrand = JSON.stringify(Math.floor(Math.random() * 15));
let secrand = JSON.stringify(Math.floor(Math.random() * 59));
let script_schedule = secrand + " " + minrand + " " + "23 * * SUN,MON,TUE,WED,THU,FRI,SAT";

// Number for this script. If this doesn't work (as in earlier versions), get it from this url (use your own ip) http://192.168.33.1/rpc/Script.List
// You can check the schedules here (use your own ip) http://192.168.33.1/rpc/Schedule.List
let script_number = Shelly.getCurrentScriptId();

// Let's start with Shelly GetStatus to get location, date and time
function getShellyStatus() {
    let addDays = -1; //yesterday, used in case the scipt started before 3PM and we don't have tomorrow prices
    let shellyHour = JSON.parse(unixTimeToHumanReadable(shellyUnixtime, timezone, addDays).slice(11, 13));
    // Only after 3PM this script can calculate schedule for tomorrow as the energy prices are not available before 3PM
    if (shellyHour >= 15) {
        addDays = 0
    }
    let shellyTime = unixTimeToHumanReadable(shellyUnixtime, timezone, addDays);
    let shellyTimePlus1 = unixTimeToHumanReadable(shellyUnixtime, timezone, addDays + 1);

    // Let's prepare proper date-time formats for Elering query
    dateStart = shellyTime.slice(0, 10) + "T22:00Z";
    dateEnd = shellyTimePlus1.slice(0, 10) + "T21:00Z";
    // Let's make proper date format of getting wether forecast
    weatherDate = shellyTimePlus1.slice(0, 10);

    // Let's call Open-Meteo weather forecast API to get tomorrow min and max temperatures
    print("Starting to fetch weather data for ", weatherDate, " from Open-Meteo.com for your location:", lat, lon, ".")
    Shelly.call("HTTP.GET", { url: openMeteoUrl + "&latitude=" + lat + "&longitude=" + lon + "&start_date=" + weatherDate + "&end_date=" + weatherDate }, function (response) {
        if (response === null || JSON.parse(response.body)["error"]) {
            print("Getting temperature failed. Using default heatingTime parameter and will turn on heating fot ", heatingTime, " hours.");
        }
        else {
            let json = JSON.parse(response.body);
            // This is very simple way for temperature forecast, just averaging tomorrow min and max temperatures :) 
            let avgTempForecast = (json["daily"]["temperature_2m_max"][0] + json["daily"]["temperature_2m_min"][0]) / 2;
            // the next line is basically the "smart quadratic equation" which calculates the hetaing hours based on the temperature
            heatingTime = ((startingTemp - avgTempForecast) * (startingTemp - avgTempForecast) + (heatingCurve / powerFactor) * (startingTemp - avgTempForecast)) / 100;
            heatingTime = Math.ceil(heatingTime);
            if (heatingTime > 24) { heatingTime = 24; }
            print("Temperture forecast tomorrow", weatherDate, " is ", avgTempForecast, " heating is turned on for ", heatingTime, " hours.");
        }
        find_cheapest();
    }
    );
}

// This is the main function to proceed with the price sorting etc.
function find_cheapest() {
    // Let's get the electricity market price from Elering
    print("Starting to fetch market prices from Elering from ", dateStart, " to ", dateEnd, ".");
    Shelly.call("HTTP.GET", { url: eleringUrl + "?start=" + dateStart + "&end=" + dateEnd }, function (result) {
        if (result === null) {
            // If there is no result, then use the default_start_time and heatingTime
            print("Fetching market prices failed. Adding one big timeslot.");
            setTimer(is_reverse, heatingTime);
            addSchedules(sorted, default_start_time, default_start_time + 1);
        }
        else {
            // Let's hope we got good JSON result and we can proceed normally
            // Example of good json
            // let json = "{success: true,data: {ee: [{timestamp: 1673301600,price: 80.5900},"+
            // "{timestamp: 1673305200,price: 76.0500},{timestamp: 1673308800,price: 79.9500}]}}";   
            print("We got market prices, going to sort them from cheapest to most expensive ...");
            let json = JSON.parse(result.body);
            let pricesArray = json["data"][country];

            // Sort prices from smallest to largest
            sorted = sort(pricesArray, "price");

            print("Cheapest daily price:", sorted[0].price, " ", unixTimeToHumanReadable(sorted[0].timestamp, 2, 0));
            print("Most expensive daily price", sorted[sorted.length - 1].price, " ", unixTimeToHumanReadable(sorted[sorted.length - 1].timestamp, 2, 0));

            // The fact is that Shelly RPC calls are limited to 5, one is used already for HTTP.GET and we have only 4 left.
            // These 4 RPC calls are used here. 
            if (heatingTime - 4 < 1) { data_indx = heatingTime; }
            else { data_indx = 4; }
            print("Starting to add hours 0-3");
            addSchedules(sorted, 0, data_indx);

            // This is the hack with the timers to add more RPC calls. We simply add a 4 second delay between the timer actions :) 
            // Timers are called four times and each timer has four RPC calls to set up alltogether maximum 20 schedules.
            // The Timers in Shelly script are limited also to 5, as one is used to stop the script itself we can call maximum 4 timers.
            // For some reason I couldn't make this code smarter as calling timers seems not working from for-loop which would be the normal solution.
            if (heatingTime - 4 > 0) {
                Timer.set(5 * 1000, false, function () {
                    print("Starting to add hours 4-8");
                    if (heatingTime - 9 < 1) { data_indx = heatingTime; }
                    else { data_indx = 9; }
                    addSchedules(sorted, 4, data_indx);
                });
            }
            if (heatingTime - 9 > 0) {
                Timer.set(10 * 1000, false, function () {
                    print("Starting to add hours 9-13");
                    if (heatingTime - 14 < 1) { data_indx = heatingTime; }
                    else { data_indx = 14; }
                    addSchedules(sorted, 9, data_indx);
                });
            }
            if (heatingTime - 14 > 0) {
                Timer.set(15 * 1000, false, function () {
                    print("Starting to add hours 14-19");
                    if (heatingTime - 19 < 1) { data_indx = heatingTime; }
                    else { data_indx = 19; }
                    addSchedules(sorted, 14, data_indx);
                });
            }
            if (heatingTime - 19 > 0) {
                Timer.set(20 * 1000, false, function () {
                    print("Starting to add hours 19-23");
                    if (heatingTime - 24 < 1) { data_indx = heatingTime; }
                    else { data_indx = 24; }
                    addSchedules(sorted, 19, data_indx);
                });
            }
        }
    });
}

// Add schedulers, switching them on or off is depends on the "is_reverse" parameter
function addSchedules(sorted_prices, start_indx, data_indx) {
    for (let i = start_indx; i < data_indx; i++) {
        let hour, price;
        if (sorted_prices.length > 0) {
            hour = unixTimeToHumanReadable(sorted_prices[i].timestamp, 2, 0).slice(11, 13);
            price = sorted_prices[i].price;
        }
        else {
            hour = JSON.stringify(start_indx);
            price = "no price.";
        }
        print("Scheduled start at: ", hour, " price: ", price);
        // Remove leading zeros from hour
        if (hour.slice(0, 1) === "0") { hour = hour.slice(1, 2); }
        // Set the start time crontab
        let timer_start = "0 0 " + hour + " * * SUN,MON,TUE,WED,THU,FRI,SAT";
        // Creating one hour schedulers 
        Shelly.call("Schedule.Create", {
            "id": 0, "enable": true, "timespec": timer_start,
            "calls": [{
                "method": "Switch.Set",
                "params": {
                    id: 0,
                    "on": !is_reverse
                }
            }]
        }
        )
    }
}

// Shelly doesn't support any date-time management.
// With this very basic math we can convert unix time to Human readable format
function unixTimeToHumanReadable(seconds, timezone, addDay) {
    //add timezone
    seconds += 60 * 60 * timezone;
    //add days
    seconds += 60 * 60 * 24 * addDay;
    // Save the time in Human readable format
    let ans = "";
    // Number of days in month in normal year
    let daysOfMonth = [31, 28, 31, 30, 31, 30,
        31, 31, 30, 31, 30, 31];
    let currYear, daysTillNow, extraTime,
        extraDays, index, date, month, hours,
        minutes, secondss, flag = 0;
    // Calculate total days unix time T
    daysTillNow = Math.floor(seconds / (24 * 60 * 60));
    extraTime = seconds % (24 * 60 * 60);
    currYear = 1970;
    // Calculating current year
    while (true) {
        if (currYear % 400 === 0
            || (currYear % 4 === 0 && currYear % 100 !== 0)) {
            if (daysTillNow < 366) {
                break;
            }
            daysTillNow -= 366;
        }
        else {
            if (daysTillNow < 365) {
                break;
            }
            daysTillNow -= 365;
        }
        currYear += 1;
    }
    // Updating extradays because it will give days till previous day and we have include current day
    extraDays = daysTillNow + 1;
    if (currYear % 400 === 0 ||
        (currYear % 4 === 0 &&
            currYear % 100 !== 0))
        flag = 1;
    // Calculating MONTH and DATE
    month = 0; index = 0;
    if (flag === 1) {
        while (true) {
            if (index === 1) {
                if (extraDays - 29 < 0)
                    break;

                month += 1;
                extraDays -= 29;
            }
            else {
                if (extraDays - daysOfMonth[index] <= 0) {
                    break;
                }
                month += 1;
                extraDays -= daysOfMonth[index];
            }
            index += 1;
        }
    }
    else {
        while (true) {
            if (extraDays - daysOfMonth[index] <= 0) {
                break;
            }
            month += 1;
            extraDays -= daysOfMonth[index];
            index += 1;
        }
    }
    // Current Month
    if (extraDays > 0) {
        month += 1;
        date = extraDays;
    }
    else {
        if (month === 2 && flag === 1) {
            date = 29;
        }
        else {
            date = daysOfMonth[month - 1];
        }
    }
    // Calculating HH:MM:SS
    hours = Math.floor(extraTime / 3600);
    minutes = Math.floor((extraTime % 3600) / 60);
    secondss = Math.floor((extraTime % 3600) % 60);
    //add leading 0 to month, date, hour, minute, and seconds
    let monthStr, dateStr, hoursStr, minutesStr, secondsStr;
    if (month < 10) { monthStr = "0" + JSON.stringify(month); } else { monthStr = JSON.stringify(month); }
    if (date < 10) { dateStr = "0" + JSON.stringify(date); } else { dateStr = JSON.stringify(date); }
    if (hours < 10) { hoursStr = "0" + JSON.stringify(hours); } else { hoursStr = JSON.stringify(hours); }
    if (minutes < 10) { minutesStr = "0" + JSON.stringify(minutes); } else { minutesStr = JSON.stringify(minutes); }
    if (secondss < 10) { secondsStr = "0" + JSON.stringify(secondss); } else { secondsStr = JSON.stringify(secondss); }

    ans += JSON.stringify(currYear);
    ans += "-";
    ans += monthStr;
    ans += "-";
    ans += dateStr;
    ans += " ";
    ans += hoursStr;
    ans += ":";
    ans += minutesStr;
    ans += ":";
    ans += secondsStr;
    // Return the time
    return ans;
}

// Shelly doesnt support Javascript sort function so this basic math algorithm will do the sorting job
function sort(array, sortby) {
    // Sorting array from smallest to larger
    let i, j, k, min, max, min_indx, max_indx, tmp;
    j = array.length - 1;
    for (i = 0; i < j; i++) {
        min = max = array[i][sortby];
        min_indx = max_indx = i;
        for (k = i; k <= j; k++) {
            if (array[k][sortby] > max) {
                max = array[k][sortby];
                max_indx = k;
            }
            else if (array[k][sortby] < min) {
                min = array[k][sortby];
                min_indx = k;
            }
        }
        tmp = array[i];
        array.splice(i, 1, array[min_indx]);
        array.splice(min_indx, 1, tmp);

        if (array[min_indx][sortby] === max) {
            tmp = array[j];
            array.splice(j, 1, array[min_indx]);
            array.splice(min_indx, 1, tmp);
        }
        else {
            tmp = array[j];
            array.splice(j, 1, array[max_indx]);
            array.splice(max_indx, 1, tmp);
        }
        j--;
    }
    return array;
    // Huhh, array is finally sorted
}

// Delete all the schedulers before adding new ones
function deleteSchedulers() {
    print("Deleting all existing schedules ...");
    Shelly.call("Schedule.DeleteAll");
}

// Set automatic one hour countdown timer to flip the Shelly status
// Auto_on or auto_off is depends on the "is_reverse" parameter
// Delay_hour is the time period in hour. Shelly will translate this to seconds.
function setTimer(is_reverse, delay_hour) {
    let is_on;
    if (is_reverse) { is_on = "on" }
    else { is_on = "off" }
    print("Setting ", delay_hour, " hour auto_", is_on, "_delay.");
    Shelly.call("Switch.SetConfig", {
        "id": 0,
        config: {
            "name": "Switch0",
            "auto_on": is_reverse,
            "auto_on_delay": delay_hour * 61 * 60,
            "auto_off": !is_reverse,
            "auto_off_delay": delay_hour * 61 * 60
        }
    }
    )
}

function scheduleScript() {
    print("Creating schedule for this script with the following CRON", script_schedule);
    Shelly.call("Schedule.create", {
        "id": 3, "enable": true, "timespec": script_schedule,
        "calls": [{
            "method": "Script.start",
            "params": {
                "id": script_number
            }
        }]
    })
}

function stopScript() {
    // Stop this script in 1.5 minute from now
    Timer.set(100 * 1000, false, function () {
        print("Stopping the script ...");
        Shelly.call("Script.stop", { "id": script_number });
    });
}

deleteSchedulers();
getShellyStatus();
setTimer(is_reverse, 1);
scheduleScript();
stopScript();
Coolhouse
Ehitusveteran
Ehitusveteran
Postitusi: 1001
Liitunud: 12 Sept 2008, 14:19
On tänanud: 1 kord
On tänatud: 26 korda

Re: Börsihinna jälgimise automaatika

Lugemata postitus Postitas Coolhouse »

Ilmateate rida on supper!

You can see the dependency of temperature and and this parameter from this visualization: "link will be here..."
See rida on küsitava väärtusega, vähemalt soojuspumba jaoks.
Piltlikult öeldes ei koosne arvutisüsteem mitte ühest suurest arvutist vaid võib koosneda ka paljudest väikestest ehk soojuspumba või ruumiautomaatika protsessor teeb ikka oma igapäevast tööd edasi.
Küttegraafikut ei pea see programm paika panema. Küttegraafik pannakse paika vaid korra, nt soojuspumba menüüs, tõsi kogemuslikult. Nt kui soojuspump on 3 tundi seisnud ja varasem küttegraafik annab ülesandeks veetemp 38C siis käivitudes soojuspumba protsessor vaatab ise kui kiiresti ta selle eesmärgini jõuab.
( see link oleks juba töötavat(olemasolevat) automaatikat dubleeriv ja kui igaüks hakkaks ise otsustama kus kohast erinevatel seadmetel infot sisendisse hankida siis .....)
Kui küttegraafikut ei ole st puudub juba olemasolev riistvara siis äkki on targem sisestada programmi arvude jada +20C =25C ,+7C =28C , +2C = 33 C ,-10C = 38C -25C= 42C , midagi sellist ja igamees saab valida sobiva veetemperatuuri. ( toatemperatuuri anduri, andurite, inerts on suurem ning seda tihti ei kasutata).

2 väljundit, küte ja tarbevesi. Kuna kütmisel on inerts suur siis mõne tunnise katkestuse jaoks sobib on/off väljundsignaal küll.
Kuid ka kõrge hinna puhul võiks tarbevee kütmine mingil temp siiski alata.

Ehk programmi eesmärk 1) optimaalne maja kütmine, 2) optimaalne tarbevee soojendamine.
Programmi eesmärk ei ole kõrge elekrienergia hinna puhul kütte väljalülitamine jne jne.
Õhk-vesi soojuspumbad, külmseadmed .
Müük, hooldus. info@coolhouse.ee
vtl
Ehitusveteran
Ehitusveteran
Postitusi: 1732
Liitunud: 25 Juul 2006, 19:13
On tänanud: 8 korda
On tänatud: 109 korda

Re: Börsihinna jälgimise automaatika

Lugemata postitus Postitas vtl »

kunn24 kirjutas: 12 Veebr 2023, 22:29 Tegelt praegu leidsin scriptis puuduse, tal peaks saama määrata hinnapiiri, üle mille ei lülita. Piir võiks olla näiteks 60 €/MWh ja olema koodist muudetav stiilis: let PriceLimit = 60

Teed ära? Siis saaks tõepoolest rakendada mõtet, et pole vaja neid börsihindu vahtida, vaid panna kriteerium paika ja unustada.
Coolhouse kirjutas: 13 Veebr 2023, 08:21Ehk programmi eesmärk 1) optimaalne maja kütmine, 2) optimaalne tarbevee soojendamine.
Programmi eesmärk ei ole kõrge elekrienergia hinna puhul kütte väljalülitamine jne jne.
Hinnapiiri järgi välja lülitada saab mugavusfunktsioone, a'la vannitoa põrandaküte. Põhikütte väljalülitamisega võib saada külma maja ja kui olukord pikemalt kestab (ja ise oled ära), siis ka näiteks külmunud veetorud.
Kui hakkad sooja tarbeveega koonerdama, siis sekkub ühel hetkel naine ja/või teismeline tütar ja teeb omad korrektiivid.
ping
Ehituspenskar
Ehituspenskar
Postitusi: 4450
Liitunud: 28 Jaan 2016, 10:35
On tänanud: 86 korda
On tänatud: 223 korda

Re: Börsihinna jälgimise automaatika

Lugemata postitus Postitas ping »

vtl kirjutas: 13 Veebr 2023, 12:34 Hinnapiiri järgi välja lülitada saab mugavusfunktsioone, a'la vannitoa põrandaküte. Põhikütte väljalülitamisega võib saada külma maja ja kui olukord pikemalt kestab (ja ise oled ära), siis ka näiteks külmunud veetorud.
Kui hakkad sooja tarbeveega koonerdama, siis sekkub ühel hetkel naine ja/või teismeline tütar ja teeb omad korrektiivid.
Sellest ongi tavaliselt alul "noortel kasutajatel" raske arusaada, et nii mugavusküttest (märgruumi põrandaküte, EL boiler, jne.) ja toas kasutatavate majapidamisriistade (valgustus, pliit, triikraud, tolmuimeja, külmik, arvuti, telekas, jne) poolt eralduv soojus on hoonesse eraldunud soojusenergia, mis on võrdne otseelektriküttega.

Kui kõik need asjad näiteks nädalaks välja lülitada, siis puudujääva energia peab kompenseerima hoone põhikütteseade.

Kui massiivsete soojust salvestavate seintega hoone vajab stabiilse sisetemperatuuri säilitamiseks näiteks iga päev 30kWh soojusenergiat ja kui ühel päeval saab hoone elektrisäästmiseks 20kWh soojusenergiat, siis järgmisel päeval on vaja eelmise päeva puudujäägi kompenseerimiseks, sama sisekliima säilitamiseks vaja hoonesse 40kWh soojusenergiat.

Kui juba kahel järjestikuse päeval tekkib massiivsel salvestusel puudujääk 2x10kWh, siis kolmandal päeval on vaja juba 50kWh soojusenergiat hoonesse ja siinkohal võib olla piiravaks teguriks kütteseadme piisav võimsus ja peakaitsme suurus nende mõnede odavate tundide jooksul.

Ehk utreeritult, siis kui (pesuruumi) põrandakütte lülitame ühel päeval, mõneks tunniks välja sellel päeval 5kWh säästmiseks, siis järgmisel päeval on sama mugavuse saavutamiseks, selle põranda ülessoojendamiseks vaja ca 10kWh soojusenergiat rohkem kui eelmisel päeval.

0C juures või väikse inertsiga karkasshoonel, kus soojusenergia tarve soojusinertsi ületamiseks ei ole suur, on soojusenergia tarbe tõus, sisetemperatuuri taastamiseks, väiksem.
:hello:
Kõik ohutustehnika reeglid on kirjutatud kellegi verega!!!
kunn24
Ehituspenskar
Ehituspenskar
Postitusi: 2048
Liitunud: 11 Veebr 2018, 14:45
On tänanud: 32 korda
On tänatud: 68 korda

Re: Börsihinna jälgimise automaatika

Lugemata postitus Postitas kunn24 »

vtl kirjutas: 13 Veebr 2023, 12:34 Hinnapiiri järgi välja lülitada saab mugavusfunktsioone, a'la vannitoa põrandaküte.
Sellest ju jutt käibki.
Aga olgu.
ping
Ehituspenskar
Ehituspenskar
Postitusi: 4450
Liitunud: 28 Jaan 2016, 10:35
On tänanud: 86 korda
On tänatud: 223 korda

Re: Börsihinna jälgimise automaatika

Lugemata postitus Postitas ping »

Kas koduse energiasalvestuse hinnastamise plaan on susisemas?
Elering tahab küsida tarbimiskoha tasu ja võimsustasu, et paremini arvestada akudega ning muutustega elektrivõrgus.

https://www.err.ee/1608884057/elering-t ... rgutasusid
:hello:
Kõik ohutustehnika reeglid on kirjutatud kellegi verega!!!
ping
Ehituspenskar
Ehituspenskar
Postitusi: 4450
Liitunud: 28 Jaan 2016, 10:35
On tänanud: 86 korda
On tänatud: 223 korda

Re: Börsihinna jälgimise automaatika

Lugemata postitus Postitas ping »

kunn24 kirjutas: 13 Veebr 2023, 14:26
vtl kirjutas: 13 Veebr 2023, 12:34 Hinnapiiri järgi välja lülitada saab mugavusfunktsioone, a'la vannitoa põrandaküte.
Sellest ju jutt käibki.
Aga olgu.
Minut varem just kirjutasin selle mõjust hoone energiabilansile.
:hello:
Kõik ohutustehnika reeglid on kirjutatud kellegi verega!!!
kunn24
Ehituspenskar
Ehituspenskar
Postitusi: 2048
Liitunud: 11 Veebr 2018, 14:45
On tänanud: 32 korda
On tänatud: 68 korda

Re: Börsihinna jälgimise automaatika

Lugemata postitus Postitas kunn24 »

Sai piirhind ka lisatud. Antud variandis on let max_price = 50 .

Kood: Vali kõik

// This script is calculating next day heating time based on weather forecast, 
// and turn on your heating system for cheapest hours based on electricity market price.

// It's scheduled to run daily after 23:00 to set heating timeslots for next day.
// by Leivo Sepp, 14.01.2023
// Energy Market price is downloaded from Elering API https://dashboard.elering.ee/assets/api-doc.html#/nps-controller/getPriceUsingGET. 
// Weather forecast is based on free Open-Meteo API https://open-meteo.com/en/docs

// Set the country Estonia-ee, Finland-fi, Lthuania-lt, Latvia-lv
// No other countries support exist trough Elering API. 
let country = "ee";

// Parameter heatingCurve is used to set proper heating curve for your house. This is very personal and also crucial component.
// You can start with the default number 5, and take a look how this works for you.
// If you feel cold, then increase this number. If you feel too warm, then decrease this number.
// You can see the dependency of temperature and and this parameter from this visualization: "link will be here..."
// Heating hours are calculated by this quadratic equation: (startingTemp-avgTemp)^2 + (heatingCurve / powerFactor) * (startingTemp-avgTemp)
let heatingCurve = 3;

// Parameter startingTemp is used as starting point for heating curve.
// For example if startingTemp = 10, then the heating is not turned on for any temperature warmer than 10 degrees.
let startingTemp = 18;

// powerFactor is used to set quadratic equation parabola curve flat or steep. Change it with your own responsibility.
let powerFactor = 0.2;

// This parameter used to set a number of heating hours in a day in case the weather forecast fails. Number 1-24. 
// If Shelly was able to get the forecast, then this number is owerwritten by the heating curve calculation.
// For example if this number is set to 5 then Shelly will be turned on for 5 most cheapest hours during a day. 
// If the cheapest hours are 02:00, 04:00, 07:00, 15:00 and 16:00, then the Shelly is turned on 02-03, 04-05, 07-08 and 15-17 (two hours in a row).
let heatingTime = 5;

// If getting electricity prices from Elering fails, then use this number as a time to start Shelly. 2 means 02:00. 
// For example if there is no internet connection at all, and heatingTime=5, default_start_time=1 then the Shelly is turned on from 01:00 to 06:00
let default_start_time = 1;

// Keep this is_reverse value "false", I think 99% of the situations are required so.
// Rarely some heating systems requires reversed relay. Put this "true" if you are sure that your appliance requires so.
// For example my personal ground source heat pump requires reversed management. If Shelly relay is activated (ON), then the pump is turned off.
let is_reverse = false;

// This is timezone for EE, LT, LV and FI.
// Do not change this because it won't work currently for other timezones.
let timezone = 2;

// Maximum price above which the work programme will not be drawn up.
let max_price = 50; 

// some global variables
let openMeteoUrl = "https://api.open-meteo.com/v1/forecast?daily=temperature_2m_max,temperature_2m_min&timezone=auto";
let eleringUrl = "https://dashboard.elering.ee/api/nps/price";
let data_indx;
let sorted = [];
let weatherDate;
let dateStart;
let dateEnd;
let lat = JSON.stringify(Shelly.getComponentConfig("sys").location.lat);
let lon = JSON.stringify(Shelly.getComponentConfig("sys").location.lon);
let shellyUnixtime = Shelly.getComponentStatus("sys").unixtime;

// Crontab for running this script. 
// This script is run at random moment during the first 15 minutes after 23:00
// Random timing is used so that all clients wouldn't be polling the server exactly at same time
let minrand = JSON.stringify(Math.floor(Math.random() * 15));
let secrand = JSON.stringify(Math.floor(Math.random() * 59));
let script_schedule = secrand + " " + minrand + " " + "23 * * SUN,MON,TUE,WED,THU,FRI,SAT";

// Number for this script. If this doesn't work (as in earlier versions), get it from this url (use your own ip) http://192.168.33.1/rpc/Script.List
// You can check the schedules here (use your own ip) http://192.168.33.1/rpc/Schedule.List
let script_number = Shelly.getCurrentScriptId();

// Let's start with Shelly GetStatus to get location, date and time
function getShellyStatus() {
    let addDays = -1; //yesterday, used in case the scipt started before 3PM and we don't have tomorrow prices
    let shellyHour = JSON.parse(unixTimeToHumanReadable(shellyUnixtime, timezone, addDays).slice(11, 13));
    // Only after 3PM this script can calculate schedule for tomorrow as the energy prices are not available before 3PM
    if (shellyHour >= 15) {
        addDays = 0
    }
    let shellyTime = unixTimeToHumanReadable(shellyUnixtime, timezone, addDays);
    let shellyTimePlus1 = unixTimeToHumanReadable(shellyUnixtime, timezone, addDays + 1);

    // Let's prepare proper date-time formats for Elering query
    dateStart = shellyTime.slice(0, 10) + "T22:00Z";
    dateEnd = shellyTimePlus1.slice(0, 10) + "T21:00Z";
    // Let's make proper date format of getting wether forecast
    weatherDate = shellyTimePlus1.slice(0, 10);

    // Let's call Open-Meteo weather forecast API to get tomorrow min and max temperatures
    print("Starting to fetch weather data for ", weatherDate, " from Open-Meteo.com for your location:", lat, lon, ".")
    Shelly.call("HTTP.GET", { url: openMeteoUrl + "&latitude=" + lat + "&longitude=" + lon + "&start_date=" + weatherDate + "&end_date=" + weatherDate }, function (response) {
        if (response === null || JSON.parse(response.body)["error"]) {
            print("Getting temperature failed. Using default heatingTime parameter and will turn on heating fot ", heatingTime, " hours.");
        }
        else {
            let json = JSON.parse(response.body);
            // This is very simple way for temperature forecast, just averaging tomorrow min and max temperatures :) 
            let avgTempForecast = (json["daily"]["temperature_2m_max"][0] + json["daily"]["temperature_2m_min"][0]) / 2;
            // the next line is basically the "smart quadratic equation" which calculates the hetaing hours based on the temperature
            heatingTime = ((startingTemp - avgTempForecast) * (startingTemp - avgTempForecast) + (heatingCurve / powerFactor) * (startingTemp - avgTempForecast)) / 100;
            heatingTime = Math.ceil(heatingTime);
            if (heatingTime > 24) { heatingTime = 24; }
            print("Temperture forecast tomorrow", weatherDate, " is ", avgTempForecast, " heating is turned on for ", heatingTime, " hours.");
        }
        find_cheapest();
    }
    );
}

// This is the main function to proceed with the price sorting etc.
function find_cheapest() {
    // Let's get the electricity market price from Elering
    print("Starting to fetch market prices from Elering from ", dateStart, " to ", dateEnd, ".");
    Shelly.call("HTTP.GET", { url: eleringUrl + "?start=" + dateStart + "&end=" + dateEnd }, function (result) {
        if (result === null) {
            // If there is no result, then use the default_start_time and heatingTime
            print("Fetching market prices failed. Adding one big timeslot.");
            setTimer(is_reverse, heatingTime);
            addSchedules(sorted, default_start_time, default_start_time + 1);
        }
        else {
            // Let's hope we got good JSON result and we can proceed normally
            // Example of good json
            // let json = "{success: true,data: {ee: [{timestamp: 1673301600,price: 80.5900},"+
            // "{timestamp: 1673305200,price: 76.0500},{timestamp: 1673308800,price: 79.9500}]}}";   
            print("We got market prices, going to sort them from cheapest to most expensive ...");
            let json = JSON.parse(result.body);
            let pricesArray = json["data"][country];

            // Sort prices from smallest to largest
            sorted = sort(pricesArray, "price");

            print("Cheapest daily price:", sorted[0].price, " ", unixTimeToHumanReadable(sorted[0].timestamp, 2, 0));
            print("Most expensive daily price", sorted[sorted.length - 1].price, " ", unixTimeToHumanReadable(sorted[sorted.length - 1].timestamp, 2, 0));

            // The fact is that Shelly RPC calls are limited to 5, one is used already for HTTP.GET and we have only 4 left.
            // These 4 RPC calls are used here. 
            if (heatingTime - 4 < 1) { data_indx = heatingTime; }
            else { data_indx = 4; }
            print("Starting to add hours 0-3");
            addSchedules(sorted, 0, data_indx);

            // This is the hack with the timers to add more RPC calls. We simply add a 4 second delay between the timer actions :) 
            // Timers are called four times and each timer has four RPC calls to set up alltogether maximum 20 schedules.
            // The Timers in Shelly script are limited also to 5, as one is used to stop the script itself we can call maximum 4 timers.
            // For some reason I couldn't make this code smarter as calling timers seems not working from for-loop which would be the normal solution.
            if (heatingTime - 4 > 0) {
                Timer.set(5 * 1000, false, function () {
                    print("Starting to add hours 4-8");
                    if (heatingTime - 9 < 1) { data_indx = heatingTime; }
                    else { data_indx = 9; }
                    addSchedules(sorted, 4, data_indx);
                });
            }
            if (heatingTime - 9 > 0) {
                Timer.set(10 * 1000, false, function () {
                    print("Starting to add hours 9-13");
                    if (heatingTime - 14 < 1) { data_indx = heatingTime; }
                    else { data_indx = 14; }
                    addSchedules(sorted, 9, data_indx);
                });
            }
            if (heatingTime - 14 > 0) {
                Timer.set(15 * 1000, false, function () {
                    print("Starting to add hours 14-19");
                    if (heatingTime - 19 < 1) { data_indx = heatingTime; }
                    else { data_indx = 19; }
                    addSchedules(sorted, 14, data_indx);
                });
            }
            if (heatingTime - 19 > 0) {
                Timer.set(20 * 1000, false, function () {
                    print("Starting to add hours 19-23");
                    if (heatingTime - 24 < 1) { data_indx = heatingTime; }
                    else { data_indx = 24; }
                    addSchedules(sorted, 19, data_indx);
                });
            }
        }
    });
}

// Add schedulers, switching them on or off is depends on the "is_reverse" parameter
function addSchedules(sorted_prices, start_indx, data_indx) {
    for (let i = start_indx; i < data_indx; i++) {
        let hour, price;
        if (sorted_prices.length > 0) {
            hour = unixTimeToHumanReadable(sorted_prices[i].timestamp, 2, 0).slice(11, 13);
            price = sorted_prices[i].price;
        }
        else {
            hour = JSON.stringify(start_indx);
            price = "no price.";
        }

  if (price < max_price) {
 
        print("Scheduled start at: ", hour, " price: ", price);
        // Remove leading zeros from hour
        if (hour.slice(0, 1) === "0") { hour = hour.slice(1, 2); }
        // Set the start time crontab
        let timer_start = "0 0 " + hour + " * * SUN,MON,TUE,WED,THU,FRI,SAT";
        // Creating one hour schedulers 
        Shelly.call("Schedule.Create", {
            "id": 0, "enable": true, "timespec": timer_start,
            "calls": [{
                "method": "Switch.Set",
                "params": {
                    id: 0,
                    "on": !is_reverse
                }
            }]
        }
        )
   }
    }
}

// Shelly doesn't support any date-time management.
// With this very basic math we can convert unix time to Human readable format
function unixTimeToHumanReadable(seconds, timezone, addDay) {
    //add timezone
    seconds += 60 * 60 * timezone;
    //add days
    seconds += 60 * 60 * 24 * addDay;
    // Save the time in Human readable format
    let ans = "";
    // Number of days in month in normal year
    let daysOfMonth = [31, 28, 31, 30, 31, 30,
        31, 31, 30, 31, 30, 31];
    let currYear, daysTillNow, extraTime,
        extraDays, index, date, month, hours,
        minutes, secondss, flag = 0;
    // Calculate total days unix time T
    daysTillNow = Math.floor(seconds / (24 * 60 * 60));
    extraTime = seconds % (24 * 60 * 60);
    currYear = 1970;
    // Calculating current year
    while (true) {
        if (currYear % 400 === 0
            || (currYear % 4 === 0 && currYear % 100 !== 0)) {
            if (daysTillNow < 366) {
                break;
            }
            daysTillNow -= 366;
        }
        else {
            if (daysTillNow < 365) {
                break;
            }
            daysTillNow -= 365;
        }
        currYear += 1;
    }
    // Updating extradays because it will give days till previous day and we have include current day
    extraDays = daysTillNow + 1;
    if (currYear % 400 === 0 ||
        (currYear % 4 === 0 &&
            currYear % 100 !== 0))
        flag = 1;
    // Calculating MONTH and DATE
    month = 0; index = 0;
    if (flag === 1) {
        while (true) {
            if (index === 1) {
                if (extraDays - 29 < 0)
                    break;

                month += 1;
                extraDays -= 29;
            }
            else {
                if (extraDays - daysOfMonth[index] <= 0) {
                    break;
                }
                month += 1;
                extraDays -= daysOfMonth[index];
            }
            index += 1;
        }
    }
    else {
        while (true) {
            if (extraDays - daysOfMonth[index] <= 0) {
                break;
            }
            month += 1;
            extraDays -= daysOfMonth[index];
            index += 1;
        }
    }
    // Current Month
    if (extraDays > 0) {
        month += 1;
        date = extraDays;
    }
    else {
        if (month === 2 && flag === 1) {
            date = 29;
        }
        else {
            date = daysOfMonth[month - 1];
        }
    }
    // Calculating HH:MM:SS
    hours = Math.floor(extraTime / 3600);
    minutes = Math.floor((extraTime % 3600) / 60);
    secondss = Math.floor((extraTime % 3600) % 60);
    //add leading 0 to month, date, hour, minute, and seconds
    let monthStr, dateStr, hoursStr, minutesStr, secondsStr;
    if (month < 10) { monthStr = "0" + JSON.stringify(month); } else { monthStr = JSON.stringify(month); }
    if (date < 10) { dateStr = "0" + JSON.stringify(date); } else { dateStr = JSON.stringify(date); }
    if (hours < 10) { hoursStr = "0" + JSON.stringify(hours); } else { hoursStr = JSON.stringify(hours); }
    if (minutes < 10) { minutesStr = "0" + JSON.stringify(minutes); } else { minutesStr = JSON.stringify(minutes); }
    if (secondss < 10) { secondsStr = "0" + JSON.stringify(secondss); } else { secondsStr = JSON.stringify(secondss); }

    ans += JSON.stringify(currYear);
    ans += "-";
    ans += monthStr;
    ans += "-";
    ans += dateStr;
    ans += " ";
    ans += hoursStr;
    ans += ":";
    ans += minutesStr;
    ans += ":";
    ans += secondsStr;
    // Return the time
    return ans;
}

// Shelly doesnt support Javascript sort function so this basic math algorithm will do the sorting job
function sort(array, sortby) {
    // Sorting array from smallest to larger
    let i, j, k, min, max, min_indx, max_indx, tmp;
    j = array.length - 1;
    for (i = 0; i < j; i++) {
        min = max = array[i][sortby];
        min_indx = max_indx = i;
        for (k = i; k <= j; k++) {
            if (array[k][sortby] > max) {
                max = array[k][sortby];
                max_indx = k;
            }
            else if (array[k][sortby] < min) {
                min = array[k][sortby];
                min_indx = k;
            }
        }
        tmp = array[i];
        array.splice(i, 1, array[min_indx]);
        array.splice(min_indx, 1, tmp);

        if (array[min_indx][sortby] === max) {
            tmp = array[j];
            array.splice(j, 1, array[min_indx]);
            array.splice(min_indx, 1, tmp);
        }
        else {
            tmp = array[j];
            array.splice(j, 1, array[max_indx]);
            array.splice(max_indx, 1, tmp);
        }
        j--;
    }
    return array;
    // Huhh, array is finally sorted
}

// Delete all the schedulers before adding new ones
function deleteSchedulers() {
    print("Deleting all existing schedules ...");
    Shelly.call("Schedule.DeleteAll");
}

// Set automatic one hour countdown timer to flip the Shelly status
// Auto_on or auto_off is depends on the "is_reverse" parameter
// Delay_hour is the time period in hour. Shelly will translate this to seconds.
function setTimer(is_reverse, delay_hour) {
    let is_on;
    if (is_reverse) { is_on = "on" }
    else { is_on = "off" }
    print("Setting ", delay_hour, " hour auto_", is_on, "_delay.");
    Shelly.call("Switch.SetConfig", {
        "id": 0,
        config: {
            "name": "Switch0",
            "auto_on": is_reverse,
            "auto_on_delay": delay_hour * 61 * 60,
            "auto_off": !is_reverse,
            "auto_off_delay": delay_hour * 61 * 60
        }
    }
    )
}

function scheduleScript() {
    print("Creating schedule for this script with the following CRON", script_schedule);
    Shelly.call("Schedule.create", {
        "id": 3, "enable": true, "timespec": script_schedule,
        "calls": [{
            "method": "Script.start",
            "params": {
                "id": script_number
            }
        }]
    })
}

function stopScript() {
    // Stop this script in 1.5 minute from now
    Timer.set(100 * 1000, false, function () {
        print("Stopping the script ...");
        Shelly.call("Script.stop", { "id": script_number });
    });
}

deleteSchedulers();
getShellyStatus();
setTimer(is_reverse, 1);
scheduleScript();
stopScript();
Kasutaja avatar
nexus4
Korralik postitaja
Korralik postitaja
Postitusi: 132
Liitunud: 06 Jaan 2023, 11:23
On tänanud: 3 korda
On tänatud: 9 korda

Re: Börsihinna jälgimise automaatika

Lugemata postitus Postitas nexus4 »

linni kirjutas: 22 Jaan 2023, 09:20
nexus4 kirjutas: 19 Jaan 2023, 21:41
Kas on algusest peale jälgimise peal olnud? Kui mitte, siis ole kena, jaga energy log andmeid mõlema perioodi kohta. Minu kogemusel cop kukkus liiga palju jälgimisega vs. Stabiilne tööreziim.
Mu aparaat energialogi ei võimalda ja eraldi mõõtjat ka vahel ei ole. COP mind niiväga ei huvitagi.
Mul oli kunagi IVT maapump, mis pekki läks. Kogu maja tarbimine oli stabiilselt 50% päeval ja 50% öösel.

Peale Nibe soetamist ja võrku ühendamist on tarbimine olnud 70% öösel ja 30% päeval.
No kui eesmärgiks rahaline kokkuhoid siis huvitab ka COP, sest jälgimisega saavutatud odavam hind peab katma ka langenud COP mõju. Kui COP jälgimis vs stabiilses režiimis teadmata, ei ole sääst garanteeritud ning võid ka rahaliselt rohkem kulutada.
:read:
Urmas
autodidakt
Postitusi: 10852
Liitunud: 17 Apr 2009, 23:51
On tänanud: 309 korda
On tänatud: 383 korda

Re: Börsihinna jälgimise automaatika

Lugemata postitus Postitas Urmas »

nexus4 kirjutas: 24 Veebr 2023, 16:47 No kui eesmärgiks rahaline kokkuhoid siis huvitab ka COP, sest jälgimisega saavutatud odavam hind peab katma ka langenud COP mõju. Kui COP jälgimis vs stabiilses režiimis teadmata, ei ole sääst garanteeritud ning võid ka rahaliselt rohkem kulutada.
Seda isegi mõtlesin, et kas börsihinna jälgimise automatika suudab tagada ka stabiilse toatemperatuuri? :scratch: Või istun -25* välistemperatturiga max börsihindadega senikaua külmas kuni börsihind on vastuvõetav ette antud programmile. :scratch: Kas börsihinna jägimise automaatika arvestab köetava pinna soojainertsi jnejne küsimusi. Läheb vist nanotehnoloogiasse ära? Kas päikese väljailmumine pilves ilmaga ja selle reageeriva automaatika, laseb rulood alla, soetushind on korrelatsioonis kasutusmugavavusega? Minu jaoks on see sama mõtetu/jabur nagu kodus diivanil vedeledes telefoniäpist kardinate ettetõmbamine. ;)
Kalvis
Ehituspenskar
Ehituspenskar
Postitusi: 10642
Liitunud: 03 Veebr 2008, 14:02
On tänanud: 2 korda
On tänatud: 288 korda

Re: Börsihinna jälgimise automaatika

Lugemata postitus Postitas Kalvis »

Sul on õigus - kõige lihtsam valem jätab külma. Natuke keerulisem arvestab välistemperatuuri alusel (jah seda sisendit on vaja) 1ja otsib vastavalt sellele minimaalsete nõutavate tundide alusel min. tunnid välja, et oleks tagatud +21 C toas.
kunn24
Ehituspenskar
Ehituspenskar
Postitusi: 2048
Liitunud: 11 Veebr 2018, 14:45
On tänanud: 32 korda
On tänatud: 68 korda

Re: Börsihinna jälgimise automaatika

Lugemata postitus Postitas kunn24 »

Kui elekter pole põhiküte, vaid temas on vahel Jumala armuannist pea-aegu tasuta lohud, siis neid mitte ära kasutada oleks patt. Seda enam, et vastvad seadmed on paari võileiva, hamburgeri või viskipudeli hinnaga (kellele "mis" on argument). Kui võrdluseks mul on gaasi kW hind praegu ca 0,09, siis näiteks seadistades automaatika kuni samasugust el hinda kasutama on mõistlik. Ilma automaatikata allolevast läbust mõistlikku el hinda pidevalt välja otsida on lootusetu üritus. Enam ei ole nii, et ainult öine hind on ok- eriti nädalavahetustel või pühadel.
Ainuke, mis võib olla nende vidinatega tüütu, et nende võrkusidumisel peab olema veidi tuttav võrgu kujundamisega, et ei tekiks võrgus sellist läbu, millest keegi enam aru ei saa, igal vidinal on ca 1 kuni 1,5 W omatarve ja nende WIFI tundlikkus on kehv. Kui näiteks viia läpakas sinna kohta, kus näitab WIFI signaalitugevuseks ca -65 dB, siis seda vidinat sinna kohta toppida enam ei saa. Kuid vidinatel on WIFI repiiter (menüüs: WIFI Extender) ehk kui 1. saab sättida norm signaalitugevusega kohta, siis sellega saab teha oma WIFI subneti sisevõrgu sees. Seadmed ei saa siis enam eraldi IP-d, vaid seotakse põhiseadmega läbi vastavate portide.
Teine var, minna võtta odavmüügist mõni norm ruuter ja konfida ta tööle switch-/AP-na või repiiterina, saab oma koduvõrgu WIFI-t ka paremaks. Näiteks Elisa jagab praegu 25 €-ga väga korralikku HUAWEI WS5200.
El hetkehind.JPG
xxx111
Ehituspenskar
Ehituspenskar
Postitusi: 5331
Liitunud: 17 Veebr 2020, 21:47
On tänanud: 4 korda
On tänatud: 134 korda

Re: Börsihinna jälgimise automaatika

Lugemata postitus Postitas xxx111 »

Kui elekter pole põhiküte...
Ma lisaksin, kui el kütet üldse pole siis mis määral "kokkuhoidu" jälgimise automaatika (arvestades ka kasutusmugavust) üldse annab?
kunn24
Ehituspenskar
Ehituspenskar
Postitusi: 2048
Liitunud: 11 Veebr 2018, 14:45
On tänanud: 32 korda
On tänatud: 68 korda

Re: Börsihinna jälgimise automaatika

Lugemata postitus Postitas kunn24 »

Ei anna, selles sul õigus. Pigem siis võiks viitsida mõne liigselt põleva lambi kustutada või lülitada oma majal mingi ülinapakas fasaadivalgustus (otsene valgussaaste) välja.
Automatiseerida on mõttekas, kui see annab mingitlaadi säästu, loob juurde märgatavat mugavust, on tõesti vajalik. Ja selle juures tuleb kindlasti püstitada küsimus: mis saab hiljem, kes haldab jne?
Vahel võib muidugi vaimne keberniit ka asja soodustada või tahtmine olla naabrist parem, tekitades näiteks eespool mainitud fassadi-pedemajaka, mida panna päikseloojangul põlema ja tõusul kustu. Ka seda saab automatiseerida, :).
bladerunner
Uus kasutaja
Uus kasutaja
Postitusi: 34
Liitunud: 15 Aug 2022, 23:11
On tänatud: 1 kord

Re: Börsihinna jälgimise automaatika

Lugemata postitus Postitas bladerunner »

Hämaraanduriga välisvalgustus a' 50W keskmiselt 8h päevas teeb universaalalektriga aastakuluks ~1€/kuus.
Vasta