-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathplugenergymeter_js
More file actions
188 lines (140 loc) · 4.82 KB
/
Copy pathplugenergymeter_js
File metadata and controls
188 lines (140 loc) · 4.82 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
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
/**
* @summary Shelly Plug energy meter. Color of the plug's light shows how much unused solar energy is available
* @author Mika Aronen <github.com/Mika9000>
*
* Inspired by Shelly Plug S Spot Price Illuminator <https://github.com/shellykauppa/plug-s-spot-illuminator>
*
**/
const CONFIG = {
energymeterAPI: 'http://192.168.2.121/meter/', //CTek Nanogrid Air
baseConsumption: 0, //Set suitable value here if energy reading is not a net yield
readinterval: 60, //seconds
blinkinterval: 2,
brightlight: 100, //normal brightness
dimlight: 50, //dimmed phase when blinking
colorlist: [
{ power: -3500, color: [0,100,12], blink: true }, //Bluish green
{ power: -1500, color: [12,100,0], blink: false }, //Green
{ power: -100, color: [100,69,0], blink: false }, //Greenish yellow
{ power: 500, color: [100,31,0], blink: false }, //Orange
{ power: 1500, color: [100,12,0], blink: false }, //Reddish orange
{ power: 3500, color: [100,0,0], blink: false }, //Red
{ power: 9999, color: [100,0,6], blink: true }, //Bright red
{ power: 10001, color: [31,31,31], blink: false } //White, error/wait
]
};
const VERSION = {
number: '1.1',
date: '250626',
};
const READINGWAIT = 10000;
var previousresult = -1;
var queryRunning = false;
var measuretime;
var timecounter = 0;
var led = {
bright: false,
blinking: false,
color: [0,0,0],
unset: false
}
function ShellyResponse(response, error_code, error_message) {
queryRunning=false;
if (error_code !== 0) console.log('Internal API invalid response: ' + JSON.stringify(error_code) + ' ' + error_message);
}
//Set plug mode to "switch" and turn switch on
function Startup() {
let uiConfig = Shelly.getComponentConfig("plugs_ui");
if ( uiConfig.leds.mode !== "switch" ) {
uiConfig.leds.mode = "switch";
queryRunning=true;
Shelly.call(
"PLUGS_UI.SetConfig",
{ config: uiConfig },
ShellyResponse
);
}
Shelly.call(
"switch.set",
{ id: 0, on: true },
ShellyResponse
);
}
//Let there be light!
function LightLed() {
if (queryRunning) return; //Previous call must finish first
queryRunning = true;
led.bright = !led.bright; //Blinker
let color = {
rgb: led.color,
brightness: (led.bright || led.unset) ? CONFIG.brightlight : CONFIG.dimlight
};
let config = Shelly.getComponentConfig("plugs_ui");
config.leds.colors["switch:0"].on = color;
led.unset = false;
Shelly.call(
"HTTP.Request",
{ method: "GET", url: "http://localhost/rpc/PLUGS_UI.SetConfig?config=" + JSON.stringify(config), timeout: 30, ssl_ca: "*" },
ShellyResponse
);
}
//Set color that matches power reading
function SetColor(power) {
let found = false;
CONFIG.colorlist.forEach( function(row, index) {
if (!found && power < row.power) {
found = true;
let logstr = "Reading: " + JSON.stringify(power) + ", index: " + JSON.stringify(index);
if (index != previousresult) {
previousresult = index;
led.color = row.color;
led.blinking = row.blink;
led.unset = true; //Tell brain the color changed
} else {
logstr += ", no change";
}
console.log(logstr);
}
});
}
//Callback function for external api call
function QueryResponse(res, error_code, error_msg) {
let reading = READINGWAIT;
queryRunning = false;
if (error_code !== 0) {
console.log("External API invalid response: " + JSON.stringify(error_code) + " " + error_msg);
} else {
if (res.code === 200) {
let st = JSON.parse(res.body);
//Power reading. Result is watts, negative sign when production exceeds consumption
//CTek Nanogrid Air
reading = parseInt((st.activePowerIn - st.activePowerOut)*1000); //Nanogrid, calculate net consumption and convert kW to W
//For solar panel reading following code may be adapted. Note negative sign and baseConsumption that is added to the value
//reading = -1 * parseInt(st.power.production) + CONFIG.baseConsumption;
}
}
SetColor(reading);
}
//Get power reading
function TakeReading() {
if (queryRunning) return; //Previous call must finish first
queryRunning = true;
timecounter = 0;
Shelly.call("HTTP.GET", { url: CONFIG.energymeterAPI, timeout:30, ssl_ca:"*" }, QueryResponse);
}
//Take reading, or blink or turn on led (called by timer)
function PlugBrains() {
timecounter++;
if (timecounter >= measuretime) {
TakeReading();
} else if (led.blinking || led.unset) {
LightLed();
}
}
//"Main"
console.log('Energyplug v' + VERSION.number + ' ' + VERSION.date);
Startup();
SetColor(READINGWAIT);
measuretime = parseInt(CONFIG.readinterval / CONFIG.blinkinterval);
timecounter = measuretime-5; //Wait 5 seconds before taking first power reading
Timer.set( CONFIG.blinkinterval * 1000, true, PlugBrains );