Skip to content

Commit

Permalink
Remote JSY + Charts Improvements
Browse files Browse the repository at this point in the history
(cherry picked from commit 961cfb4313416ea795c877a6475bc071f5b924fa)
  • Loading branch information
mathieucarbou committed Jun 24, 2024
1 parent a4113ae commit e9a8a37
Show file tree
Hide file tree
Showing 15 changed files with 147 additions and 69 deletions.
8 changes: 1 addition & 7 deletions include/YaSolR.h
Original file line number Diff line number Diff line change
Expand Up @@ -80,11 +80,6 @@ extern Mycila::RouterRelay routerRelay2;
extern Mycila::TrafficLight lights;
extern Mycila::ZCD zcd;

extern Mycila::CircularBuffer<uint32_t, YASOLR_GRAPH_POINTS> timeHistory;
extern Mycila::CircularBuffer<int, YASOLR_GRAPH_POINTS> gridPowerHistory;
extern Mycila::CircularBuffer<int, YASOLR_GRAPH_POINTS> routedPowerHistory;
extern Mycila::CircularBuffer<int, YASOLR_GRAPH_POINTS> routerTHDiHistory;

extern Mycila::TaskManager ioTaskManager;
extern Mycila::Task haDiscoveryTask;
extern Mycila::Task mqttPublishTask;
Expand All @@ -96,8 +91,7 @@ extern Mycila::Task jsyTask;

extern Mycila::TaskManager coreTaskManager;
extern Mycila::Task carouselTask;
extern Mycila::Task dashboardCards;
extern Mycila::Task dashboardCharts;
extern Mycila::Task dashboardTask;
extern Mycila::Task displayTask;
extern Mycila::Task ds18Task;
extern Mycila::Task lightsTask;
Expand Down
5 changes: 3 additions & 2 deletions include/YaSolRDefines.h
Original file line number Diff line number Diff line change
Expand Up @@ -54,11 +54,11 @@
#define YASOLR_RELAY_TYPE_NO "NO"
#define YASOLR_SERIAL_BAUDRATE 115200
#define YASOLR_WEEK_DAYS "sun,mon,tue,wed,thu,fri,sat"
#define YASOLR_GRAPH_POINTS 90
#define YASOLR_GRAPH_POINTS 120

// UDP communication

#define YASOLR_UDP_PORT 54321
#define YASOLR_UDP_PORT 53964
#define YASOLR_UDP_MSG_TYPE_JSY_DATA 0x01

// password configuration keys
Expand Down Expand Up @@ -132,6 +132,7 @@
#define KEY_RELAY1_TYPE "relay1_type"
#define KEY_RELAY2_LOAD "relay2_load"
#define KEY_RELAY2_TYPE "relay2_type"
#define KEY_UDP_PORT "udp_port"
#define KEY_WIFI_PASSWORD "wifi_pwd"
#define KEY_WIFI_SSID "wifi_ssid"

Expand Down
61 changes: 42 additions & 19 deletions remote/JSYRemoteUDP/JSYRemoteUDP.ino
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
#ifndef HTTPCLIENT_NOSECURE
#define HTTPCLIENT_NOSECURE 1
#endif

#ifndef ARDUINO_LOOP_STACK_SIZE
#define ARDUINO_LOOP_STACK_SIZE 4096
#endif
Expand Down Expand Up @@ -65,8 +69,9 @@
#define TAG "YaSolR"
#define YASOLR_APP_NAME "JSY Remote UDP"
#define YASOLR_ADMIN_USERNAME "admin"
#define YASOLR_UDP_PORT 54321
#define YASOLR_UDP_PORT 53964
#define YASOLR_UDP_MSG_TYPE_JSY_DATA 0x01
#define YASOLR_GRAPH_POINTS 120

#include <Arduino.h>
#include <ESPmDNS.h>
Expand All @@ -93,6 +98,19 @@ Mycila::TaskManager coreTaskManager("core");
Mycila::TaskManager ioTaskManager("io");
Mycila::TaskManager jsyTaskManager("jsy");

Statistic networkHostname = Statistic(&dashboard, "Network Hostname");
Statistic networkInterface = Statistic(&dashboard, "Network Interface");
Statistic networkAPIP = Statistic(&dashboard, "Network Access Point IP Address");
Statistic networkAPMAC = Statistic(&dashboard, "Network Access Point MAC Address");
Statistic networkEthIP = Statistic(&dashboard, "Network Ethernet IP Address");
Statistic networkEthMAC = Statistic(&dashboard, "Network Ethernet MAC Address");
Statistic networkWiFiIP = Statistic(&dashboard, "Network WiFi IP Address");
Statistic networkWiFiMAC = Statistic(&dashboard, "Network WiFi MAC Address");
Statistic networkWiFiSSID = Statistic(&dashboard, "Network WiFi SSID");
Statistic networkWiFiRSSI = Statistic(&dashboard, "Network WiFi RSSI");
Statistic networkWiFiSignal = Statistic(&dashboard, "Network WiFi Signal");
Statistic uptime = Statistic(&dashboard, "Uptime");

Card voltage = Card(&dashboard, GENERIC_CARD, "Voltage", "V");
Card activePower = Card(&dashboard, GENERIC_CARD, "Active Power", "W");
Card apparentPower = Card(&dashboard, GENERIC_CARD, "Apparent Power", "VA");
Expand All @@ -107,18 +125,9 @@ Card restart = Card(&dashboard, BUTTON_CARD, "Restart");
Card energyReset = Card(&dashboard, BUTTON_CARD, "Reset JSY");
Card reset = Card(&dashboard, BUTTON_CARD, "Reset Device");

Statistic networkHostname = Statistic(&dashboard, "Network Hostname");
Statistic networkInterface = Statistic(&dashboard, "Network Interface");
Statistic networkAPIP = Statistic(&dashboard, "Network Access Point IP Address");
Statistic networkAPMAC = Statistic(&dashboard, "Network Access Point MAC Address");
Statistic networkEthIP = Statistic(&dashboard, "Network Ethernet IP Address");
Statistic networkEthMAC = Statistic(&dashboard, "Network Ethernet MAC Address");
Statistic networkWiFiIP = Statistic(&dashboard, "Network WiFi IP Address");
Statistic networkWiFiMAC = Statistic(&dashboard, "Network WiFi MAC Address");
Statistic networkWiFiSSID = Statistic(&dashboard, "Network WiFi SSID");
Statistic networkWiFiRSSI = Statistic(&dashboard, "Network WiFi RSSI");
Statistic networkWiFiSignal = Statistic(&dashboard, "Network WiFi Signal");
Statistic uptime = Statistic(&dashboard, "Uptime");
int historyX[YASOLR_GRAPH_POINTS] = {0};
int gridPowerHistoryY[YASOLR_GRAPH_POINTS] = {0};
Chart gridPowerHistory = Chart(&dashboard, BAR_CHART, "Gris Power (Watts)");

String hostname;
String ssid;
Expand Down Expand Up @@ -169,7 +178,7 @@ Mycila::Task restartTask("Restart", Mycila::TaskType::ONCE, [](void* params) {
Mycila::System.restart(500);
});

Mycila::Task dashboardCards("Dashboard", [](void* params) {
Mycila::Task dashboardTask("Dashboard", [](void* params) {
ESPConnectMode mode = ESPConnect.getMode();

networkAPIP.set(ESPConnect.getIPAddress(ESPConnectMode::AP).toString().c_str());
Expand All @@ -190,6 +199,20 @@ Mycila::Task dashboardCards("Dashboard", [](void* params) {
powerFactor.update(jsy.getPowerFactor2());
voltage.update(jsy.getVoltage2());

// shift array
for (size_t i = 0; i < YASOLR_GRAPH_POINTS - 1; i++) {
historyX[i] = historyX[i + 1];
gridPowerHistoryY[i] = gridPowerHistoryY[i + 1];
}

// set new value
historyX[YASOLR_GRAPH_POINTS - 1] = millis() / 1000;
gridPowerHistoryY[YASOLR_GRAPH_POINTS - 1] = round(jsy.getPower2());

// update charts
gridPowerHistory.updateX(historyX, YASOLR_GRAPH_POINTS);
gridPowerHistory.updateY(gridPowerHistoryY, YASOLR_GRAPH_POINTS);

dashboard.sendUpdates();
});

Expand Down Expand Up @@ -242,9 +265,9 @@ void setup() {
Mycila::System.begin();

// tasks
dashboardCards.setEnabledWhen([]() { return ESPConnect.isConnected() && dashboard.hasClient() && !dashboard.isAsyncAccessInProgress(); });
dashboardCards.setInterval(751 * Mycila::TaskDuration::MILLISECONDS);
dashboardCards.setManager(coreTaskManager);
dashboardTask.setEnabledWhen([]() { return ESPConnect.isConnected() && dashboard.hasClient() && !dashboard.isAsyncAccessInProgress(); });
dashboardTask.setInterval(1000 * Mycila::TaskDuration::MILLISECONDS);
dashboardTask.setManager(coreTaskManager);
jsyTask.setEnabledWhen([]() { return jsy.isEnabled(); });
jsyTask.setManager(jsyTaskManager);
Mycila::TaskManager::configureWDT();
Expand All @@ -259,7 +282,7 @@ void setup() {
senderTask.setManager(ioTaskManager);

// profiling
dashboardCards.enableProfiling(10, Mycila::TaskTimeUnit::MILLISECONDS);
dashboardTask.enableProfiling(10, Mycila::TaskTimeUnit::MILLISECONDS);
jsyTask.enableProfiling(10, Mycila::TaskTimeUnit::MILLISECONDS);
otaTask.setCallback(LOG_EXEC_TIME);
profilerTask.enableProfiling(10, Mycila::TaskTimeUnit::MILLISECONDS);
Expand Down Expand Up @@ -317,7 +340,7 @@ void setup() {
});
dashboard.setAuthentication(YASOLR_ADMIN_USERNAME, YASOLR_ADMIN_PASSWORD);
dashboard.refreshLayout();
dashboardCards.forceRun();
dashboardTask.forceRun();

// jsy
jsy.begin(YASOLR_JSY_SERIAL, YASOLR_JSY_RX, YASOLR_JSY_TX);
Expand Down
66 changes: 64 additions & 2 deletions remote/JSYRemoteUDP/README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,66 @@
# Remote JSY with UDP

The ESP32 will communicate with the router through UDP protocol to send the JSY data.
Both ESP32 needs to be connected to the same WiFi network and multicast UDP packets must be allowed.
The `Remote JSY with UDP` firmware will communicate with YaSolR through UDP protocol to send the JSY data each 500 ms.
Both devices needs to be connected to the same WiFi network and UDP packets must be allowed.

![](https://github.com/mathieucarbou/YaSolR-OSS/assets/61346/b375bfda-6bc1-4576-afeb-26594b5c8649)
![](https://github.com/mathieucarbou/YaSolR-OSS/assets/61346/b1e893d1-a272-4006-9df6-ebbe091a0ce1)

## Installation with Arduino IDE

_I am not familiar with Arduino IDE because this is not a correct IDE for development._
_Please help contribute to this README if the explanation needs to be improved._

1. You need to install these Arduino dependencies from the library manager or by downloading them:

```c++
#include <ArduinoJson.h> // https://github.com/bblanchon/ArduinoJson
#include <AsyncTCP.h> // https://github.com/mathieucarbou/AsyncTCP
#include <ESPAsyncWebServer.h> // https://github.com/mathieucarbou/ESPAsyncWebServer
#include <ESPDash.h> // https://github.com/mathieucarbou/ayushsharma82-ESP-DASH#dev
#include <ElegantOTA.h> // https://github.com/mathieucarbou/ayushsharma82-ElegantOTA#dev
#include <MycilaESPConnect.h> // https://github.com/mathieucarbou/MycilaESPConnect
#include <MycilaJSY.h> // https://github.com/mathieucarbou/MycilaJSY
#include <MycilaLogger.h> // https://github.com/mathieucarbou/MycilaLogger
#include <MycilaSystem.h> // https://github.com/mathieucarbou/MycilaSystem
#include <MycilaTaskManager.h> // https://github.com/mathieucarbou/MycilaTaskMonitor
#include <MycilaTaskMonitor.h> // https://github.com/mathieucarbou/MycilaTaskMonitor
#include <WebSerialLite.h> // https://github.com/mathieucarbou/WebSerialLite
```

The program also uses these Arduino libraries:

```
DNSServer
ESP32 Async UDP
ESPmDNS
FS
Networking
LittleFS
WiFi
Ticker
Update
```

2. Compile and deploy to your board.

## Installation with PlatformIO

This is as simple as running:

```bash
pio run -t upload -e <your-board>
```

## Usage

Quick start is similar to YaSolR.
The device will open an access point, you need to connect to it and choose the WiFI to join.

Once the device has joined the WiFi and is connected to a JSY, you will see the JSY data on the web interface.

- To look at the logs, go to: `http://<device-ip>/console`

- To update the firmware, go to: `http://<device-ip>/update`

- To add a password, change the line `#define YASOLR_ADMIN_PASSWORD ""`
3 changes: 3 additions & 0 deletions remote/JSYRemoteUDP/platformio.ini
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,9 @@ build_flags =
-D CONFIG_ASYNC_TCP_STACK_SIZE=4096
-D DASH_JSON_SIZE=4096
-D ELEGANTOTA_USE_ASYNC_WEBSERVER=1
; Flag to disable secure clients
; https://github.com/espressif/arduino-esp32/pull/9893
-D HTTPCLIENT_NOSECURE
-D MYCILA_JSON_SUPPORT
-D MYCILA_LOGGER_SUPPORT
-D WS_MAX_QUEUED_MESSAGES=64
Expand Down
7 changes: 4 additions & 3 deletions remote/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@ You can install a JSY with an ESP32 on the electric panel and it will send its J

## Remote JSY with ESP-Now

The ESP32 will communicate with the router through the ESP-Now protocol.
The `Remote JSY with ESP-Now` firmware will communicate with YaSolR through the ESP-Now protocol.

ESP-Now is a low level protocol which is not using your WiFi (but has the same frequency and channel).
This protocol allows ESP32 devices to talk to each other without the need of a WiFi network.
It is fast and support long range communication.
Expand All @@ -14,7 +15,7 @@ This option is suitable if you cannot connect the ESP32 to your home WiFi networ

## Remote JSY with UDP

The ESP32 will communicate with the router through UDP protocol to send the JSY data.
Both ESP32 needs to be connected to the same WiFi network and multicast UDP packets must be allowed.
The `Remote JSY with UDP` firmware will communicate with YaSolR through UDP protocol to send the JSY data each 500 ms.
Both devices needs to be connected to the same WiFi network and UDP packets must be allowed.

=> [JSYRemoteUDP](JSYRemoteUDP)
29 changes: 20 additions & 9 deletions src/Website.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -646,16 +646,27 @@ void YaSolR::WebsiteClass::updateCards() {
}

void YaSolR::WebsiteClass::updateCharts() {
// graphs
int now = static_cast<int>(millis() / 1000);
for (size_t i = 0; i < YASOLR_GRAPH_POINTS; i++) {
_historyX[i] = static_cast<int>((timeHistory[i] / 1000)) - now;
// read last metrics
Mycila::GridMetrics gridMetrics;
grid.getMetrics(gridMetrics);
Mycila::RouterMetrics routerMetrics;
router.getMetrics(routerMetrics);

// shift array
for (size_t i = 0; i < YASOLR_GRAPH_POINTS - 1; i++) {
_historyX[i] = _historyX[i + 1];
_gridPowerHistoryY[i] = _gridPowerHistoryY[i + 1];
_routedPowerHistoryY[i] = _routedPowerHistoryY[i + 1];
_routerTHDiHistoryY[i] = _routerTHDiHistoryY[i + 1];
}

gridPowerHistory.copy(_gridPowerHistoryY);
routedPowerHistory.copy(_routedPowerHistoryY);
routerTHDiHistory.copy(_routerTHDiHistoryY);
// set new value
_historyX[YASOLR_GRAPH_POINTS - 1] = millis() / 1000;
_gridPowerHistoryY[YASOLR_GRAPH_POINTS - 1] = round(gridMetrics.power);
_routedPowerHistoryY[YASOLR_GRAPH_POINTS - 1] = round(routerMetrics.power);
_routerTHDiHistoryY[YASOLR_GRAPH_POINTS - 1] = round(routerMetrics.thdi * 100);

// update charts
_gridPowerHistory.updateX(_historyX, YASOLR_GRAPH_POINTS);
_gridPowerHistory.updateY(_gridPowerHistoryY, YASOLR_GRAPH_POINTS);
_routedPowerHistory.updateX(_historyX, YASOLR_GRAPH_POINTS);
Expand Down Expand Up @@ -757,7 +768,7 @@ void YaSolR::WebsiteClass::_outputBypassSwitch(Card& card, Mycila::RouterOutput&
}
card.update(output.isBypassOn());
dashboard.refreshCard(&card);
dashboardCards.requestEarlyRun();
dashboardTask.requestEarlyRun();
});
}

Expand All @@ -768,7 +779,7 @@ void YaSolR::WebsiteClass::_outputDimmerSlider(Card& card, Mycila::RouterOutput&
}
card.update(output.getDimmerDuty());
dashboard.refreshCard(&card);
dashboardCards.requestEarlyRun();
dashboardTask.requestEarlyRun();
});
}

Expand Down
1 change: 1 addition & 0 deletions src/init/Boot.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,7 @@ Mycila::Task bootTask("Boot", [](void* params) {
config.configure(KEY_RELAY1_TYPE, YASOLR_RELAY_TYPE_NO);
config.configure(KEY_RELAY2_LOAD, "0");
config.configure(KEY_RELAY2_TYPE, YASOLR_RELAY_TYPE_NO);
config.configure(KEY_UDP_PORT, String(YASOLR_UDP_PORT));
config.configure(KEY_WIFI_PASSWORD);
config.configure(KEY_WIFI_SSID);

Expand Down
6 changes: 2 additions & 4 deletions src/init/Config.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,8 @@ Mycila::Task initConfigTask("Init Config", [](void* params) {
// Tasks configuration
carouselTask.setEnabledWhen([]() { return display.isEnabled(); });
carouselTask.setIntervalSupplier([]() { return config.get(KEY_DISPLAY_SPEED).toInt() * Mycila::TaskDuration::SECONDS; });
dashboardCards.setEnabledWhen([]() { return ESPConnect.isConnected() && dashboard.hasClient() && !dashboard.isAsyncAccessInProgress() && !routingTask.isRunning(); });
dashboardCards.setInterval(751 * Mycila::TaskDuration::MILLISECONDS);
dashboardCharts.setEnabledWhen([]() { return ESPConnect.isConnected() && dashboard.hasClient() && !dashboard.isAsyncAccessInProgress() && !routingTask.isRunning(); });
dashboardCharts.setInterval(1000 * Mycila::TaskDuration::MILLISECONDS);
dashboardTask.setEnabledWhen([]() { return ESPConnect.isConnected() && dashboard.hasClient() && !dashboard.isAsyncAccessInProgress() && !routingTask.isRunning(); });
dashboardTask.setInterval(1000 * Mycila::TaskDuration::MILLISECONDS);
displayTask.setEnabledWhen([]() { return display.isEnabled(); });
displayTask.setInterval(293 * Mycila::TaskDuration::MILLISECONDS);
ds18Task.setEnabledWhen([]() { return ds18Sys.isEnabled() || ds18O1.isEnabled() || ds18O2.isEnabled(); });
Expand Down
3 changes: 1 addition & 2 deletions src/init/Core.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,7 @@ Mycila::Task initCoreTask("Init Core", [](void* params) {

// coreTaskManager
carouselTask.setManager(coreTaskManager);
dashboardCards.setManager(coreTaskManager);
dashboardCharts.setManager(coreTaskManager);
dashboardTask.setManager(coreTaskManager);
displayTask.setManager(coreTaskManager);
ds18Task.setManager(coreTaskManager);
lightsTask.setManager(coreTaskManager);
Expand Down
6 changes: 2 additions & 4 deletions src/init/Debug.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,7 @@ Mycila::Task initLoggingTask("Init Logging", [](void* params) {

if (debug) {
// Enable profiling for some FOREVER tasks
dashboardCards.enableProfiling(10, Mycila::TaskTimeUnit::MILLISECONDS);
dashboardCharts.enableProfiling(10, Mycila::TaskTimeUnit::MILLISECONDS);
dashboardTask.enableProfiling(10, Mycila::TaskTimeUnit::MILLISECONDS);
ds18Task.enableProfiling(10, Mycila::TaskTimeUnit::MILLISECONDS);
displayTask.enableProfiling(10, Mycila::TaskTimeUnit::MILLISECONDS);
jsyTask.enableProfiling(10, Mycila::TaskTimeUnit::MILLISECONDS);
Expand All @@ -34,8 +33,7 @@ Mycila::Task initLoggingTask("Init Logging", [](void* params) {
routerTask.enableProfiling(10, Mycila::TaskTimeUnit::MILLISECONDS);
routingTask.enableProfiling(10, Mycila::TaskTimeUnit::MILLISECONDS);
} else {
dashboardCards.disableProfiling();
dashboardCharts.disableProfiling();
dashboardTask.disableProfiling();
ds18Task.disableProfiling();
displayTask.disableProfiling();
jsyTask.disableProfiling();
Expand Down
5 changes: 0 additions & 5 deletions src/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -40,11 +40,6 @@ Mycila::RouterOutput output2("output2", dimmerO2, bypassRelayO2, ds18O2, grid, p
Mycila::RouterRelay routerRelay1(relay1);
Mycila::RouterRelay routerRelay2(relay2);

Mycila::CircularBuffer<uint32_t, YASOLR_GRAPH_POINTS> timeHistory;
Mycila::CircularBuffer<int, YASOLR_GRAPH_POINTS> gridPowerHistory;
Mycila::CircularBuffer<int, YASOLR_GRAPH_POINTS> routedPowerHistory;
Mycila::CircularBuffer<int, YASOLR_GRAPH_POINTS> routerTHDiHistory;

AsyncWebServer webServer(80);
AsyncUDP udp;
ESPDash dashboard = ESPDash(&webServer, "/dashboard", false);
Expand Down
6 changes: 1 addition & 5 deletions src/tasks/Dashboard.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,8 @@
#include <YaSolR.h>
#include <YaSolRWebsite.h>

Mycila::Task dashboardCards("Dashboard", [](void* params) {
Mycila::Task dashboardTask("Dashboard", [](void* params) {
YaSolR::Website.updateCards();
dashboard.sendUpdates();
});

Mycila::Task dashboardCharts("Dashboard Charts", [](void* params) {
YaSolR::Website.updateCharts();
dashboard.sendUpdates();
});
Loading

0 comments on commit e9a8a37

Please sign in to comment.