diff --git a/CHANGELOG.md b/CHANGELOG.md
index aa97fac..89f0bc4 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -5,6 +5,12 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
# Suomeksi
+## [2.6.0] - 23.10.2023
+- Lisätty uusi ominaisuus: päivän keskiarvon käyttö hintarajana
+ - Jos syöttää mihin tahansa seuraavista kentistä arvon `avg`, käytetään päivän keskiarvoa kiinteän arvon sijaan
+ - **käsiohjaus**: hintaraja
+ - **jakson halvimmat tunnit**: aina päällä -raja, maksimihinta
+
## [2.5.1] - 21.10.2023 (2)
- Bugikorjaus: Jos asetti pakko-ohjauksen x tunniksi painikkeella, se kyllä toimi, mutta tuli virheilmoitus
@@ -57,6 +63,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Versio 2 julkaistu (tehty täysin uusiksi)
# In English
+## [2.6.0] - 23.10.2023
+- Added new feature: using day average price instead of static price limit (by setting value to `avg`)
## [2.5.1] - 21.10.2023 (2)
- Bugfix: Setting override hour using button caused an error (however it worked)
diff --git a/README.md b/README.md
index 3a238f4..0f38530 100644
--- a/README.md
+++ b/README.md
@@ -7,7 +7,9 @@
Shelly-laitteisiin selaimella ohjattava pörssisähkösovellus, joka venyttää laitteen skriptien rajoja. Pyörittää käyttöliittymää omalla web-serverillä ja tallentaa asetuksensa Shellyn muistiin.
-Jos haluat ohjata relekytkintä sähkön hinnan mukaan, ilman ulkopuolisia palveluita, niin tämä voi olla hyödyllinen. Käyttää suoraan Viron kantaverkkoyhtiön [elering.ee](https://dashboard.elering.ee/api) -rajapintaa, eli välissä ei ole kolmannen osapuolen palveluita. Skripti ei vaadi rekisteröitymistä mihinkään vaan se toimii "suoraan paketista".
+Jos haluat ohjata Shellyn relekytkintä sähkön hinnan mukaan, ilman johonkin palveluun rekisteröitymistä, niin tämä voi olla hyödyllinen.
+
+Käyttää suoraan Viron kantaverkkoyhtiön [elering.ee](https://dashboard.elering.ee/api) -rajapintaa, eli välissä ei ole muita palveluita. Skripti ei vaadi rekisteröitymistä mihinkään vaan se toimii "suoraan paketista".
![porssisahko](https://github.com/jisotalo/shelly-porssisahko/assets/13457157/751cbd0c-1b7a-4086-9e32-b04b888c5425)
@@ -15,7 +17,7 @@ Jos haluat ohjata relekytkintä sähkön hinnan mukaan, ilman ulkopuolisia palve
## Ominaisuudet
* Oma web-serveri Shellyn sisällä ja siinä pyörivä käyttöliittymä
* Valvonta ja konfigurointi selaimen avulla
-* Ei liityntöjä 3. osapuolen palveluihin
+* Ei tarvitse rekisteröityä mihinkään
* Kolme ohjaustapaa:
* **käsiohjaus** - yksinkertaisesti ohjaus päälle/pois
* **hintaraja** - jos hinta on alle rajan, laitetaan ohjaus päälle
@@ -29,6 +31,7 @@ Jos haluat ohjata relekytkintä sähkön hinnan mukaan, ilman ulkopuolisia palve
* Shelly Plus 1
* Shelly Pro 1
* Shelly Pro 2
+ * Shelly Plus Plug S
* *Laita viestiä jos sinulla on kokemusta muista laitteista!*
## Sisällysluettelo
@@ -41,12 +44,12 @@ Jos haluat ohjata relekytkintä sähkön hinnan mukaan, ilman ulkopuolisia palve
+ [Ohjaustapa: Hintaraja](#ohjaustapa-hintaraja)
+ [Ohjaustapa: Jakson halvimmat tunnit](#ohjaustapa-jakson-halvimmat-tunnit)
+ [Toiminnot](#toiminnot)
+- [Kysymyksiä ja vastauksia](#kysymyksiä-ja-vastauksia)
- [Teknistä tietoa ja kehitysympäristö](#teknistä-tietoa-ja-kehitysympäristö)
+ [Lyhyesti](#lyhyesti)
+ [Tiedostot ja kansiot](#tiedostot-ja-kansiot)
+ [Muistin käyttö](#muistin-käyttö)
+ [Kehitysympäristö](#kehitysympäristö)
-- [FAQ](#faq)
- [In English](#in-english)
- [License](#license)
@@ -147,7 +150,7 @@ Hintarajaohjauksella lähtö asetetaan päälle jos sähkön hinta on alle mää
| Asetus | Selite | Esim. (kuva yllä)
| --- | --- | ---
-| Hintaraja | Hinta, jossa ja jonka alla lähtö asetetaan päälle. [c/kWh] | `4.25`
+| Hintaraja | Hinta, jossa ja jonka alla lähtö asetetaan päälle. [c/kWh]
Voit syöttää tähän myös arvon `avg`, jolloin käytetään päivän hinnan keskiarvoa. | `4.25`
### Ohjaustapa: Jakson halvimmat tunnit
@@ -163,8 +166,8 @@ Versiosta 2.4.0 lähtien voidaan myös määrittää, että päälläolotuntien
| Ajanjakso | Minkä mittaisiin jaksoihin vuorokausi jaetaan. Jokaiselta jaksolta haetaan sitten halvimmat tunnit. [h] | `6`
| Tuntimäärä | Kuinka monta halvinta tuntia lähtö ohjataan päälle ajanjakson aikana.
Eli jos ajanjakso on 6h ja tuntimäärä 2, kello 00:00-06:00 lähtö ohjataan päälle kahtena halvimpana tuntina. Kuten myös kello 06:00-12:00 ja niin edelleen. | `2`
| Peräkkäiset | Jos käytössä, valitaan jakson tunnit siten että ne ovat peräkkäin.
Näin yksittäisiä halvimpia tunteja ei välttämättä hyödynnetä, mutta halvin mahdollinen yhtenäinen jakso otetaan käyttöön. Katso esimerkki alta. | `ei`
-| Aina päällä -raja | Jos sähkö on tätä halvempaa (tai juuri tämän hintaista) niin lähtö on aina päällä. [c/kWh] | `-0.5`
-| Maksimihinta | Jos sähkön hinta on tätä korkeampi, lähtöä ei aseteta päälle vaikka tunti olisikin halvimpia tunteja. [c/kWh]
Tämän kanssa pitää olla tarkkana, jos tulee kalliita päiviä. | `30`
+| Aina päällä -raja | Jos sähkö on tätä halvempaa (tai juuri tämän hintaista) niin lähtö on aina päällä. [c/kWh]
Voit syöttää tähän myös arvon `avg`, jolloin käytetään päivän hinnan keskiarvoa. | `-0.5`
+| Maksimihinta | Jos sähkön hinta on tätä korkeampi, lähtöä ei aseteta päälle vaikka tunti olisikin halvimpia tunteja. [c/kWh]
Voit syöttää tähän myös arvon `avg`, jolloin käytetään päivän hinnan keskiarvoa.
*Tämän kanssa pitää olla tarkkana, jos tulee kalliita päiviä.* | `30`
Alla esimerkki miten ohjaukset menenivät 12.10.2023 hinnoilla ja yllä olevilla asetuksilla (6h, 2 halvinta tuntia, aina päällä -raja -0.5 c/kWh). Huomaa jaksojen korostus taustavärillä.
@@ -195,6 +198,23 @@ Valitaan kolme perättäistä tuntia. Valitaan kello 17-19 koska niiden hinnan k
* **Shelly**
* Avaa uudessa välilehdessä Shellyn oman hallintasivun
+## Kysymyksiä ja vastauksia
+### Miksi välillä tulee HTTP error 503?
+
+Tällä hetkellä jos skripti hakee hintoja tai suorittaa ohjauslogiikkaa, vastataan kaikkiin HTTP-pyyntöihin 503 (Service Unavailable). Käyttöliittymä osaa hallita tämän.
+
+Jos hintojen hakeminen ei onnistu, voi tämä virhe tulla käyttöliittymää avatessa (hintojen haun aikakatkaisu on 5s --> pahimmillaan virhe voi tulla 5 sekunnin ajan). Yritä avata sivu uudelleen.
+
+Voi olla että muutan tätä myöhemmin, vaatii vielä testejä. Syy on jälleen muistin säästäminen.
+
+### Miten ohjaan ainoastaan yön halvimmilla tunneilla?
+
+Aseta ohjaustavaksi `jakson halvimmat tunnit` ja päivän siirtohinnaksi `999` c/kWh. Näin kaikki päivätunnit ovat kalliita ja halvimmat tunnit valitaan sen johdosta yöajalta.
+
+### Miten saan lähdön päälle aina jos sähkön hinta on keskiarvon alapuolella?
+
+Versiosta 2.6.0 lähtien tämä onnistuu valitsemalla ohjaustavaksi `hintaraja` ja asettamalla hintarajaksi arvon `avg`.
+
## Teknistä tietoa ja kehitysympäristö
### Lyhyesti
@@ -226,7 +246,7 @@ Valitaan kolme perättäistä tuntia. Valitaan kello 17-19 koska niiden hinnan k
### Muistin käyttö
-Versio 2.5.0 vie enimmillään 24276 tavua muistia (Shellyn maksimi 25200). Eli pieni skripti saattaa mahtua rinnalle pyörimään.
+Versio 2.6.0 vie enimmillään 24440 tavua muistia (Shellyn maksimi 25200). Eli pieni skripti saattaa mahtua rinnalle pyörimään.
### Kehitysympäristö
@@ -254,26 +274,13 @@ Käyttää Node.js -ympäristöä.
* käyttöliittymän kehitystä varten
* käynnistää paikallisen web-serverin ja tarjoaa `src/statics/` -kansion tiedostot portista 3000
-## FAQ
-**Miksi välillä tulee HTTP error 503?**
-
-Tällä hetkellä jos skripti hakee hintoja tai suorittaa ohjauslogiikkaa, vastataan kaikkiin HTTP-pyyntöihin 503 (Service Unavailable). Käyttöliittymä osaa hallita tämän.
-
-Jos hintojen hakeminen ei onnistu, voi tämä virhe tulla käyttöliittymää avatessa (hintojen haun aikakatkaisu on 5s --> pahimmillaan virhe voi tulla 5 sekunnin ajan). Yritä avata sivu uudelleen.
-
-Voi olla että muutan tätä myöhemmin, vaatii vielä testejä. Syy on jälleen muistin säästäminen.
-
-**Voinko ohjata ainoastaan yön halvimmilla tunneilla?**
-
-Aseta ohjaustavaksi `jakson halvimmat tunnit` ja päivän siirtohinnaksi 999 c/kWh. Näin kaikki päivätunnit ovat kalliita ja halvimmat tunnit valitaan sen johdosta yöajalta.
-
## In English
-This is a script to control relay by Nordpool electric spot prices for Shelly products (especially Shelly Plus 1PM) with web-based user interface.
+This is a script to control relay by Nordpool electric spot prices for Shelly products with web-based user interface.
At the moment it's available only in Finnish and the spot price is queried for Finland.
-There will soon be an English version (with country selection) available.
+There will be an English version (maybe with country selection) available later when I have an insipiration to work on it.
## License
diff --git a/dist/shelly-porssisahko.js b/dist/shelly-porssisahko.js
index 3f6e4d0..3fbd50d 100644
--- a/dist/shelly-porssisahko.js
+++ b/dist/shelly-porssisahko.js
@@ -1 +1 @@
-let C_HIST=24,C_ERRC=3,C_ERRD=120,C_DEF={mode:0,m0:{cmd:0},m1:{lim:0},m2:{per:24,cnt:0,lim:-999,sq:0,m:999},vat:24,day:0,night:0,bk:0,err:0,out:0,fh:0,inv:0},c={s:{v:"2.5.1",st:0,cmd:0,chkTs:0,errCnt:0,errTs:0,upTs:0,timeOK:0,configOK:0,fCmdTs:0,p:{ts:0,now:0,low:0,high:0,avg:0}},p:[],h:[],c:C_DEF},l=!1,i=!1;function o(t,s){s-=t;return 0<=s&&s<3600}function a(t){return Math.floor((t?t.getTime():Date.now())/1e3)}function n(t,s,e){let n=t.toString();for(;n.length=C_ERRC&&a(t)-c.s.errTs=C_ERRC&&(c.s.errCnt=0);return s}()){let s=new Date;try{let t=s.getFullYear()+"-"+n(s.getMonth()+1,2,"0")+"-"+n(f(s),2,"0")+"T00:00:00%2b03:00";var e=t.replace("T00:00:00","T23:59:59");let l={url:"https://dashboard.elering.ee/api/nps/price/csv?fields=fi&start="+t+"&end="+e,timeout:5,ssl_ca:"*"};s=null,t=null,Shelly.call("HTTP.GET",l,function(s,t,e){l=null;try{if(0!==t||null==s||200!==s.code||!s.body_b64)throw new Error("conn.err ("+e+") "+JSON.stringify(s));{s.headers=null,e=s.message=null,c.p=[],c.s.p.high=-999,c.s.p.low=999,s.body_b64=atob(s.body_b64),s.body_b64=s.body_b64.substring(s.body_b64.indexOf("\n")+1);let t=0;for(;0<=t;){s.body_b64=s.body_b64.substring(t);var n=[t=0,0];if(0===(t=s.body_b64.indexOf('"',t)+1))break;n[0]=Number(s.body_b64.substring(t,s.body_b64.indexOf('"',t))),t=s.body_b64.indexOf('"',t)+2,t=s.body_b64.indexOf(';"',t)+2,n[1]=Number(s.body_b64.substring(t,s.body_b64.indexOf('"',t)).replace(",",".")),n[1]=n[1]/10*(100+(0c.s.p.high&&(c.s.p.high=n[1]),n[1]c.c.m2.m&&(i=!1,c.s.st=11)):c.s.timeOK?(c.s.st=7,t=1<=C_HIST;)c.h.splice(0,1);c.h.push([a(),i?1:0]),n&&n(!0)}else n&&n(!1)},e)}catch(t){b(t),l=!1}}let A=0,u=0,h=0;function y(){var s=a();for(let t=0;t=C_ERRC&&c(t)-a.s.errTs=C_ERRC&&(a.s.errCnt=0);return e}()){let e=new Date;try{let t=e.getFullYear()+"-"+n(e.getMonth()+1,2,"0")+"-"+n(f(e),2,"0")+"T00:00:00%2b03:00";var s=t.replace("T00:00:00","T23:59:59");let l={url:"https://dashboard.elering.ee/api/nps/price/csv?fields=fi&start="+t+"&end="+s,timeout:5,ssl_ca:"*"};e=null,t=null,Shelly.call("HTTP.GET",l,function(e,t,s){l=null;try{if(0!==t||null==e||200!==e.code||!e.body_b64)throw new Error("conn.err ("+s+") "+JSON.stringify(e));{e.headers=null,s=e.message=null,a.p=[],a.s.p.high=-999,a.s.p.low=999,e.body_b64=atob(e.body_b64),e.body_b64=e.body_b64.substring(e.body_b64.indexOf("\n")+1);let t=0;for(;0<=t;){e.body_b64=e.body_b64.substring(t);var n=[t=0,0];if(0===(t=e.body_b64.indexOf('"',t)+1))break;n[0]=Number(e.body_b64.substring(t,e.body_b64.indexOf('"',t))),t=e.body_b64.indexOf('"',t)+2,t=e.body_b64.indexOf(';"',t)+2,n[1]=Number(e.body_b64.substring(t,e.body_b64.indexOf('"',t)).replace(",",".")),n[1]=n[1]/10*(100+(0a.s.p.high&&(a.s.p.high=n[1]),n[1]("avg"==a.c.m2.m?a.s.p.avg:a.c.m2.m)&&(i=!1,a.s.st=11)):a.s.timeOK?(a.s.st=7,t=1<=C_HIST;)a.h.splice(0,1);a.h.push([c(),i?1:0]),n&&n(!0)}else n&&n(!1)},s)}catch(t){m(t),l=!1}}let g=0,h=0,p=0;function v(){var e=c();for(let t=0;t 0 && getDate(new Date(_.s.p.ts * 1000)) === getDate(now))) {
//We have time and we have price data for today
@@ -594,7 +594,7 @@ function logic() {
} else if (_.c.mode === 1) {
//Price limit
- cmd = _.s.p.now <= _.c.m1.lim;
+ cmd = _.s.p.now <= (_.c.m1.lim == "avg" ? _.s.p.avg : _.c.m1.lim);
//log("moodi on hintaraja (" + _.c.m1.priceLimit + "), ohjaus: " + (cmd ? "PÄÄLLE" : "POIS"), me);
_.s.st = cmd ? 2 : 3;
@@ -604,13 +604,13 @@ function logic() {
_.s.st = cmd ? 5 : 4;
//always on price limit
- if (!cmd && _.s.p.now <= _.c.m2.lim) {
+ if (!cmd && _.s.p.now <= (_.c.m2.lim == "avg" ? _.s.p.avg : _.c.m2.lim)) {
cmd = true;
_.s.st = 6;
}
//maximum price
- if (cmd && _.s.p.now > _.c.m2.m) {
+ if (cmd && _.s.p.now > (_.c.m2.m == "avg" ? _.s.p.avg : _.c.m2.m)) {
cmd = false;
_.s.st = 11;
}
diff --git a/src/statics/tab-config.js b/src/statics/tab-config.js
index 99a03d2..afe8ced 100644
--- a/src/statics/tab-config.js
+++ b/src/statics/tab-config.js
@@ -59,6 +59,7 @@
try {
let c = state.c
let n = (v) => Number(v);
+ let avgn = (e) => qs(e).value == "avg" ? "avg" : n(qs(e).value);
c.mode = n(qs("#mode").value);
c.out = n(qs("#out").value);
@@ -80,12 +81,12 @@
c.err = qs("#err").checked ? 1 : 0;
c.m0.cmd = qs("#m0-cmd").checked ? 1 : 0;
- c.m1.lim = n(qs("#m1-lim").value);
+ c.m1.lim = avgn("#m1-lim");
c.m2.per = n(qs("#m2-per").value);
c.m2.cnt = Math.min(c.m2.per, n(qs("#m2-cnt").value));
c.m2.sq = qs("#m2-sq").checked ? 1 : 0;
- c.m2.lim = n(qs("#m2-lim").value);
- c.m2.m = n(qs("#m2-m").value);
+ c.m2.lim = avgn("#m2-lim");
+ c.m2.m = avgn("#m2-m");
DBG(me(), "Settings to save:", c);
diff --git a/src/statics/tab-status.js b/src/statics/tab-status.js
index 8aacaf5..6fcee9b 100644
--- a/src/statics/tab-status.js
+++ b/src/statics/tab-status.js
@@ -103,9 +103,9 @@
let date = new Date(row[0] * 1000);
let cmd =
(c.mode === 0 && c.m0.cmd)
- || (c.mode === 1 && row[1] <= c.m1.lim)
- || (c.mode === 2 && cheapest.includes(i) && row[1] <= c.m2.m)
- || (c.mode === 2 && row[1] <= c.m2.lim)
+ || (c.mode === 1 && row[1] <= (c.m1.lim == "avg" ? s.p.avg : c.m1.lim))
+ || (c.mode === 2 && cheapest.includes(i) && row[1] <= (c.m2.m == "avg" ? s.p.avg : c.m2.m))
+ || (c.mode === 2 && row[1] <= (c.m2.lim == "avg" ? s.p.avg : c.m2.lim))
|| (c.fh & (1 << i)) == (1 << i);
//Invert