-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathscript
More file actions
123 lines (108 loc) · 3.92 KB
/
Copy pathscript
File metadata and controls
123 lines (108 loc) · 3.92 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
/*
Created by Heikki Visnapuu, 2026
Licensed under the MIT License
https://github.com/hv-tec/Shelly_PV_off
This Shelly script retrieves 15 min energy market prices from Elering and
activates shelly NO relay to cut off solar panels production.
Events are logged to Supabase. Telegram notifications are handled by
a Supabase Edge Function that batches events from all plants per user.
Taastuvenergia toetusega tootjad: jätke tasakaalustus ja marginaal 0-ks.
Börsilepinguga tootjad: seadistage tasakaalustus ja marginaal vastavalt lepingule.
*/
let CFG = {
relay_id: 0,
threshold_eur_kwh: 0,
check_interval: 120,
api_timeout: 15,
tasakaalustus_eur_kwh: 0,
marginaal_eur_kwh: 0,
plant_id: "assaku", // ← unikaalne id SB jaoks
plant_name: "Assaku Solar", // ← inimloetav nimi teavitustes
supabase_url: "YOUR_SUPABASE_URL",
supabase_key: "YOUR_SUPABASE_KEY"
};
let state = { relay_on: false, last_price: null };
function nowISO() {
return new Date(Shelly.getComponentStatus("sys").unixtime * 1000).toISOString();
}
function logEvent(np_price, eff_price, relay_on) {
Shelly.call("HTTP.POST", {
url: CFG.supabase_url + "/rest/v1/cutoff_events",
headers: {
"apikey": CFG.supabase_key,
"Authorization": "Bearer " + CFG.supabase_key,
"Content-Type": "application/json"
},
body: JSON.stringify({
plant_id: CFG.plant_id,
plant_name: CFG.plant_name,
timestamp: nowISO(),
np_price: np_price,
eff_price: eff_price,
relay_on: relay_on
}),
ssl_ca: "*",
timeout: CFG.api_timeout
}, function(res, err) {
if (err) { print("Supabase log error:", err); return; }
print("Event logged. relay_on:", relay_on);
});
}
function setRelay(on, np_price, eff_price) {
if (state.relay_on === on) return;
Shelly.call("Switch.Set", { id: CFG.relay_id, on: on }, function(r, e) {
if (e) { print("Relay error:", e); return; }
state.relay_on = on;
if (on) {
print(">>> RELAY ON - PV Off (" + eff_price + " EUR/kWh)");
} else {
print("<<< RELAY OFF - PV On (" + eff_price + " EUR/kWh)");
}
logEvent(np_price, eff_price, on);
});
}
function checkPrice() {
let unixtime = Shelly.getComponentStatus("sys").unixtime;
let periodStart = Math.floor(unixtime / 900) * 900;
let periodEnd = periodStart + 900;
function toISO(s) {
return new Date(s * 1000).toISOString().split(".")[0] + "Z";
}
let url = "https://dashboard.elering.ee/api/nps/price"
+ "?fields=ee"
+ "&start=" + toISO(periodStart)
+ "&end=" + toISO(periodEnd);
Shelly.call("HTTP.GET", { url: url, ssl_ca: "*", timeout: CFG.api_timeout }, function(res, err) {
if (err || !res || res.code !== 200) {
print("Elering API error:", err || (res ? res.code : "no response"));
return;
}
try {
let data = JSON.parse(res.body);
if (!data.success || !data.data || !data.data.ee || !data.data.ee.length) {
print("Empty response from Elering API");
return;
}
// Elering returns EUR/MWh -> convert to EUR/kWh
let np_price = Math.round(data.data.ee[0].price / 10) / 100;
let eff_price = Math.round((np_price - CFG.tasakaalustus_eur_kwh - CFG.marginaal_eur_kwh) * 10000) / 10000;
state.last_price = eff_price;
print("NP:", np_price, "EUR/kWh | Efektiivne:", eff_price, "EUR/kWh");
if (eff_price < CFG.threshold_eur_kwh) {
setRelay(true, np_price, eff_price);
} else {
setRelay(false, np_price, eff_price);
}
} catch(e) {
print("JSON parse error:", e);
}
});
}
checkPrice();
Timer.set(CFG.check_interval * 1000, true, checkPrice);
print("Script started. Plant:", CFG.plant_name, "| Threshold:", CFG.threshold_eur_kwh, "EUR/kWh");
Shelly.addStatusHandler(function(e) {
if (e.component === "switch:0" && e.delta && e.delta.output !== undefined) {
print("Manual relay switch:", e.delta.output ? "ON" : "OFF");
}
});