mirror of https://github.com/lumapu/ahoy.git
lumapu
2 years ago
42 changed files with 1937 additions and 1595 deletions
After Width: | Height: | Size: 650 KiB |
After Width: | Height: | Size: 66 KiB |
@ -0,0 +1,47 @@ |
|||||
|
# Prometheus Endpoint |
||||
|
Metrics available for AhoyDTU device, inverters and channels. |
||||
|
|
||||
|
Prometheus metrics provided at `/metrics`. |
||||
|
|
||||
|
## Labels |
||||
|
| Label name | Description | |
||||
|
|:-----------|:--------------------------------------| |
||||
|
| version | current installed version of AhoyDTU | |
||||
|
| image | currently not used | |
||||
|
| devicename | Device name from setup | |
||||
|
| name | Inverter name from setup | |
||||
|
| serial | Serial number of inverter | |
||||
|
| enabled | Communication enable for inverter | |
||||
|
| inverter | Inverter name from setup | |
||||
|
| channel | Channel name from setup | |
||||
|
|
||||
|
|
||||
|
## Exported Metrics |
||||
|
| Metric name | Type | Description | Labels | |
||||
|
|----------------------------------------|---------|--------------------------------------------------------|--------------| |
||||
|
| `ahoy_solar_info` | Gauge | Information about the AhoyDTU device | version, image, devicename | |
||||
|
| `ahoy_solar_inverter_info` | Gauge | Information about the configured inverter(s) | name, serial, enabled | |
||||
|
| `ahoy_solar_U_AC_volt` | Gauge | AC voltage of inverter [V] | inverter | |
||||
|
| `ahoy_solar_I_AC_ampere` | Gauge | AC current of inverter [A] | inverter | |
||||
|
| `ahoy_solar_P_AC_watt` | Gauge | AC power of inverter [W] | inverter | |
||||
|
| `ahoy_solar_Q_AC_var` | Gauge | AC reactive power[var] | inverter | |
||||
|
| `ahoy_solar_F_AC_hertz` | Gauge | AC frequency [Hz] | inverter | |
||||
|
| `ahoy_solar_PF_AC` | Gauge | AC Power factor | inverter | |
||||
|
| `ahoy_solar_Temp_celsius` | Gauge | Temperature of inverter | inverter | |
||||
|
| `ahoy_solar_ALARM_MES_ID` | Gauge | Last alarm message id of inverter | inverter | |
||||
|
| `ahoy_solar_YieldDay_wattHours` | Counter | Energy converted to AC per day [Wh] | inverter | |
||||
|
| `ahoy_solar_YieldTotal_kilowattHours` | Counter | Energy converted to AC since reset [kWh] | inverter | |
||||
|
| `ahoy_solar_P_DC_watt` | Gauge | DC power of inverter [W] | inverter | |
||||
|
| `ahoy_solar_Efficiency_ratio` | Gauge | ration AC Power over DC Power [%] | inverter | |
||||
|
| `ahoy_solar_U_DC_volt` | Gauge | DC voltage of channel [V] | inverter, channel | |
||||
|
| `ahoy_solar_I_DC_ampere` | Gauge | DC current of channel [A] | inverter, channel | |
||||
|
| `ahoy_solar_P_DC_watt` | Gauge | DC power of channel [P] | inverter, channel | |
||||
|
| `ahoy_solar_YieldDay_wattHours` | Counter | Energy converted to AC per day [Wh] | inverter, channel | |
||||
|
| `ahoy_solar_YieldTotal_kilowattHours` | Counter | Energy converted to AC since reset [kWh] | inverter, channel | |
||||
|
| `ahoy_solar_Irradiation_ratio` | Gauge | ratio DC Power over set maximum power per channel [%] | inverter, channel | |
||||
|
| `ahoy_solar_radio_rx_success` | Gauge | NRF24 statistic | | |
||||
|
| `ahoy_solar_radio_rx_fail` | Gauge | NRF24 statistic | | |
||||
|
| `ahoy_solar_radio_rx_fail_answer` | Gauge | NRF24 statistic | | |
||||
|
| `ahoy_solar_radio_frame_cnt` | Gauge | NRF24 statistic | | |
||||
|
| `ahoy_solar_radio_tx_cnt` | Gauge | NRF24 statistic | | |
||||
|
|
@ -1,36 +1,84 @@ |
|||||
# Changelog v0.5.66 |
# Changelog |
||||
|
|
||||
**Note:** Version `0.5.42` to `0.5.65` were development versions. Last release version was `0.5.41` |
(starting from release version `0.5.66`) |
||||
Detailed change log (development changes): https://github.com/lumapu/ahoy/blob/945a671d27d10d0f7c175ebbf2fbb2806f9cd79a/src/CHANGES.md |
|
||||
|
## 0.5.78 |
||||
|
* further improvements regarding wifi #611, fix connection if only one AP with same SSID is there |
||||
* updated REST API and MQTT (both of them use the same functionality) |
* fix endless loop in `zerovalues` #564 |
||||
* improved stability |
* fix auto discover again #565 |
||||
* Regular expressions for input fields which are used for MQTT to be compliant to MQTT |
* added total values to autodiscover #630 |
||||
* WiFi optimization (AP Mode and STA in parallel, reconnect if local STA is unavailable) |
* improved zero at midnight #625 |
||||
* improved display of `/system` |
|
||||
* fix Update button protection (prevent double click #527) |
## 0.5.77 |
||||
* optimized scheduler #515 |
* fix wrong filename for automatically created manifest (online installer) #620 |
||||
* fix of duplicates in API `/api/record/live` (#526) |
* added rotate display feature #619 |
||||
* added update information to `index.html` (check for update with github.com) |
* improved Prometheus endpoint #615, thx to @fsck-block |
||||
* fix web logout (auto logout) |
* improved wifi to connect always to strongest RSSI, thx to @beegee3 #611 |
||||
* switched MQTT library |
|
||||
* removed MQTT `available_text` (can be deducted from `available`) |
## 0.5.76 |
||||
* enhanced MQTT documentation in `User_Manual.md` |
* reduce MQTT retry interval from maximum speed to one second |
||||
* changed MQTT topic `status` to nummeric value, check documentation in `User_Manual.md` |
* fixed homeassistant autodiscovery #565 |
||||
* added immediate (each minute) report of inverter status MQTT #522 |
* implemented `getNTPTime` improvements #609 partially #611 |
||||
* increased MQTT user, pwd and topic length to 64 characters + `\0`. (The string end `\0` reduces the available size by one) #516 |
* added alarm messages to MQTT #177, #600, #608 |
||||
* added disable night communication flag to MQTT #505 |
|
||||
* added MQTT <TOPIC>/status to show status over all inverters |
## 0.5.75 |
||||
* added MQTT RX counter to index.html |
* fix wakeup issue, once wifi was lost during night the communication didn't start in the morning |
||||
* added protection mask to select which pages should be protected |
* reenabled FlashStringHelper because of lacking RAM |
||||
* added monochrome display that show values also if nothing changed and in offline mode #498 |
* complete rewrite of monochrome display class, thx to @dAjaY85 -> displays are now configurable in setup |
||||
* added icons to index.html, added WiFi-strength symbol on each page |
* fix power limit not possible #607 |
||||
* refactored communication offset (adjustable in minutes now) |
|
||||
* factory reset formats entire little fs |
## 0.5.74 |
||||
* renamed sunrise / sunset on index.html to start / stop communication |
* improved payload handling (retransmit all fragments on CRC error) |
||||
* fixed static IP save |
* improved `isAvailable`, checkes all record structs, inverter becomes available more early because version is check first |
||||
* fix NTP with static IP |
* fix tickers were not set if NTP is not available |
||||
* all values are displayed on /live even if they are 0 |
* disabled annoying `FlashStringHelper` it gives randomly Expeptions during development, feels more stable since then |
||||
* added NRF24 info to Systeminfo |
* moved erase button to the bottom in settings, not nice but more functional |
||||
* reordered enqueue commands after boot up to prevent same payload length for successive commands |
* split `tx_count` to `tx_cnt` and `retransmits` in `system.html` |
||||
|
* fix mqtt retransmit IP address #602 |
||||
|
* added debug infos for `scheduler` (web -> `/debug` as trigger prints list of tickers to serial console) |
||||
|
|
||||
|
## 0.5.73 |
||||
|
* improved payload handling (request / retransmit) #464 |
||||
|
* included alarm ID parse to serial console (in development) |
||||
|
|
||||
|
## 0.5.72 |
||||
|
* repaired system, scheduler was not called any more #596 |
||||
|
|
||||
|
## 0.5.71 |
||||
|
* improved wifi handling and tickers, many thanks to @beegee3 #571 |
||||
|
* fixed YieldTotal correction calculation #589 |
||||
|
* fixed serial output of power limit acknowledge #569 |
||||
|
* reviewed `sendDiscoveryConfig` #565 |
||||
|
* merged PR `Monodisplay`, many thanks to @dAjaY85 #566, Note: (settings are introduced but not able to be modified, will be included in next version) |
||||
|
|
||||
|
## 0.5.70 |
||||
|
* corrected MQTT `comm_disabled` #529 |
||||
|
* fix Prometheus and JSON endpoints (`config_override.h`) #561 |
||||
|
* publish MQTT with fixed interval even if inverter is not available #542 |
||||
|
* added JSON settings upload. NOTE: settings JSON download changed, so only settings should be uploaded starting from version `0.5.70` #551 |
||||
|
* MQTT topic and inverter name have more allowed characters: `[A-Za-z0-9./#$%&=+_-]+`, thx: @Mo Demman |
||||
|
* improved potential issue with `checkTicker`, thx @cbscpe |
||||
|
* MQTT option for reset values on midnight / not avail / communication stop #539 |
||||
|
* small fix in `tickIVCommunication` #534 |
||||
|
* add `YieldTotal` correction, eg. to have the option to zero at year start #512 |
||||
|
|
||||
|
## 0.5.69 |
||||
|
* merged SH1106 1.3" Display, thx @dAjaY85 |
||||
|
* added SH1106 to automatic build |
||||
|
* added IP address to MQTT (version, device and IP are retained and only transmitted once after boot) #556 |
||||
|
* added `set_power_limit` acknowledge MQTT publish #553 |
||||
|
* changed: version, device name are only published via MQTT once after boot |
||||
|
* added `Login` to menu if admin password is set #554 |
||||
|
* added `development` to second changelog link in `index.html` #543 |
||||
|
* added interval for MQTT (as option). With this settings MQTT live data is published in a fixed timing (only if inverter is available) #542, #523 |
||||
|
* added MQTT `comm_disabled` #529 |
||||
|
* changed name of binaries, moved GIT-Sha to the front #538 |
||||
|
|
||||
|
## 0.5.68 |
||||
|
* repaired receive payload |
||||
|
* Powerlimit is transfered immediately to inverter |
||||
|
|
||||
|
## 0.5.67 |
||||
|
* changed calculation of start / stop communication to 1 min after last comm. stop #515 |
||||
|
* moved payload send to `payload.h`, function `ivSend` #515 |
||||
|
* payload: if last frame is missing, request all frames again |
||||
|
@ -1,161 +0,0 @@ |
|||||
/*
|
|
||||
CircularBuffer - An Arduino circular buffering library for arbitrary types. |
|
||||
|
|
||||
Created by Ivo Pullens, Emmission, 2014 -- www.emmission.nl |
|
||||
|
|
||||
This library is free software; you can redistribute it and/or |
|
||||
modify it under the terms of the GNU Lesser General Public |
|
||||
License as published by the Free Software Foundation; either |
|
||||
version 2.1 of the License, or (at your option) any later version. |
|
||||
|
|
||||
This library is distributed in the hope that it will be useful, |
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
|
||||
Lesser General Public License for more details. |
|
||||
|
|
||||
You should have received a copy of the GNU Lesser General Public |
|
||||
License along with this library; if not, write to the Free Software |
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA |
|
||||
*/ |
|
||||
|
|
||||
#ifndef CircularBuffer_h |
|
||||
#define CircularBuffer_h |
|
||||
|
|
||||
#if defined(ESP8266) || defined(ESP32) |
|
||||
#define DISABLE_IRQ noInterrupts() |
|
||||
#define RESTORE_IRQ interrupts() |
|
||||
#else |
|
||||
#define DISABLE_IRQ \ |
|
||||
uint8_t sreg = SREG; \ |
|
||||
cli(); |
|
||||
|
|
||||
#define RESTORE_IRQ \ |
|
||||
SREG = sreg; |
|
||||
#endif |
|
||||
|
|
||||
template <class BUFFERTYPE, uint8_t BUFFERSIZE> |
|
||||
class CircularBuffer { |
|
||||
|
|
||||
typedef BUFFERTYPE BufferType; |
|
||||
BufferType Buffer[BUFFERSIZE]; |
|
||||
|
|
||||
public: |
|
||||
CircularBuffer() : m_buff(Buffer) { |
|
||||
m_size = BUFFERSIZE; |
|
||||
clear(); |
|
||||
} |
|
||||
|
|
||||
/** Clear all entries in the circular buffer. */ |
|
||||
void clear(void) |
|
||||
{ |
|
||||
m_front = 0; |
|
||||
m_fill = 0; |
|
||||
} |
|
||||
|
|
||||
/** Test if the circular buffer is empty */ |
|
||||
inline bool empty(void) const |
|
||||
{ |
|
||||
return !m_fill; |
|
||||
} |
|
||||
|
|
||||
/** Return the number of records stored in the buffer */ |
|
||||
inline uint8_t available(void) const |
|
||||
{ |
|
||||
return m_fill; |
|
||||
} |
|
||||
|
|
||||
/** Test if the circular buffer is full */ |
|
||||
inline bool full(void) const |
|
||||
{ |
|
||||
return m_fill == m_size; |
|
||||
} |
|
||||
|
|
||||
inline uint8_t getFill(void) const { |
|
||||
return m_fill; |
|
||||
} |
|
||||
|
|
||||
/** Aquire record on front of the buffer, for writing.
|
|
||||
* After filling the record, it has to be pushed to actually |
|
||||
* add it to the buffer. |
|
||||
* @return Pointer to record, or NULL when buffer is full. |
|
||||
*/ |
|
||||
BUFFERTYPE* getFront(void) const |
|
||||
{ |
|
||||
DISABLE_IRQ; |
|
||||
BUFFERTYPE* f = NULL; |
|
||||
if (!full()) |
|
||||
f = get(m_front); |
|
||||
RESTORE_IRQ; |
|
||||
return f; |
|
||||
} |
|
||||
|
|
||||
/** Push record to front of the buffer
|
|
||||
* @param record Record to push. If record was aquired previously (using getFront) its |
|
||||
* data will not be copied as it is already present in the buffer. |
|
||||
* @return True, when record was pushed successfully. |
|
||||
*/ |
|
||||
bool pushFront(BUFFERTYPE* record) |
|
||||
{ |
|
||||
bool ok = false; |
|
||||
DISABLE_IRQ; |
|
||||
if (!full()) |
|
||||
{ |
|
||||
BUFFERTYPE* f = get(m_front); |
|
||||
if (f != record) |
|
||||
*f = *record; |
|
||||
m_front = (m_front+1) % m_size; |
|
||||
m_fill++; |
|
||||
ok = true; |
|
||||
} |
|
||||
RESTORE_IRQ; |
|
||||
return ok; |
|
||||
} |
|
||||
|
|
||||
/** Aquire record on back of the buffer, for reading.
|
|
||||
* After reading the record, it has to be pop'ed to actually |
|
||||
* remove it from the buffer. |
|
||||
* @return Pointer to record, or NULL when buffer is empty. |
|
||||
*/ |
|
||||
BUFFERTYPE* getBack(void) const |
|
||||
{ |
|
||||
BUFFERTYPE* b = NULL; |
|
||||
DISABLE_IRQ; |
|
||||
if (!empty()) |
|
||||
b = get(back()); |
|
||||
RESTORE_IRQ; |
|
||||
return b; |
|
||||
} |
|
||||
|
|
||||
/** Remove record from back of the buffer.
|
|
||||
* @return True, when record was pop'ed successfully. |
|
||||
*/ |
|
||||
bool popBack(void) |
|
||||
{ |
|
||||
bool ok = false; |
|
||||
DISABLE_IRQ; |
|
||||
if (!empty()) |
|
||||
{ |
|
||||
m_fill--; |
|
||||
ok = true; |
|
||||
} |
|
||||
RESTORE_IRQ; |
|
||||
return ok; |
|
||||
} |
|
||||
|
|
||||
protected: |
|
||||
inline BUFFERTYPE * get(const uint8_t idx) const |
|
||||
{ |
|
||||
return &(m_buff[idx]); |
|
||||
} |
|
||||
inline uint8_t back(void) const |
|
||||
{ |
|
||||
return (m_front - m_fill + m_size) % m_size; |
|
||||
} |
|
||||
|
|
||||
uint8_t m_size; // Total number of records that can be stored in the buffer.
|
|
||||
BUFFERTYPE* const m_buff; |
|
||||
volatile uint8_t m_front; // Index of front element (not pushed yet).
|
|
||||
volatile uint8_t m_fill; // Amount of records currently pushed.
|
|
||||
}; |
|
||||
|
|
||||
#endif // CircularBuffer_h
|
|
@ -1,27 +0,0 @@ |
|||||
//-----------------------------------------------------------------------------
|
|
||||
// 2022 Ahoy, https://ahoydtu.de
|
|
||||
// Creative Commons - http://creativecommons.org/licenses/by-nc-sa/3.0/de/
|
|
||||
//-----------------------------------------------------------------------------
|
|
||||
|
|
||||
#ifndef __AHOY_TIMER_H__ |
|
||||
#define __AHOY_TIMER_H__ |
|
||||
|
|
||||
#include <Arduino.h> |
|
||||
|
|
||||
namespace ah { |
|
||||
inline bool checkTicker(uint32_t *ticker, uint32_t interval) { |
|
||||
uint32_t mil = millis(); |
|
||||
if(mil >= *ticker) { |
|
||||
*ticker = mil + interval; |
|
||||
return true; |
|
||||
} |
|
||||
else if(mil < (*ticker - interval)) { |
|
||||
*ticker = mil + interval; |
|
||||
return true; |
|
||||
} |
|
||||
|
|
||||
return false; |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
#endif /*__AHOY_TIMER_H__*/ |
|
@ -1,33 +0,0 @@ |
|||||
//-----------------------------------------------------------------------------
|
|
||||
// 2022 Ahoy, https://ahoydtu.de
|
|
||||
// Lukas Pusch, lukas@lpusch.de
|
|
||||
// Creative Commons - http://creativecommons.org/licenses/by-nc-sa/3.0/de/
|
|
||||
//-----------------------------------------------------------------------------
|
|
||||
|
|
||||
#ifndef __HANDLER_H__ |
|
||||
#define __HANDLER_H__ |
|
||||
|
|
||||
#include <memory> |
|
||||
#include <functional> |
|
||||
#include <list> |
|
||||
|
|
||||
template<class TYPE> |
|
||||
class Handler { |
|
||||
public: |
|
||||
Handler() {} |
|
||||
|
|
||||
void addListener(TYPE f) { |
|
||||
mList.push_back(f); |
|
||||
} |
|
||||
|
|
||||
/*virtual void notify(void) {
|
|
||||
for(typename std::list<TYPE>::iterator it = mList.begin(); it != mList.end(); ++it) { |
|
||||
(*it)(); |
|
||||
} |
|
||||
}*/ |
|
||||
|
|
||||
protected: |
|
||||
std::list<TYPE> mList; |
|
||||
}; |
|
||||
|
|
||||
#endif /*__HANDLER_H__*/ |
|
@ -1,110 +0,0 @@ |
|||||
//-----------------------------------------------------------------------------
|
|
||||
// 2022 Ahoy, https://ahoydtu.de
|
|
||||
// Lukas Pusch, lukas@lpusch.de
|
|
||||
// Creative Commons - http://creativecommons.org/licenses/by-nc-sa/3.0/de/
|
|
||||
//-----------------------------------------------------------------------------
|
|
||||
#ifndef __LIST_H__ |
|
||||
#define __LIST_H__ |
|
||||
|
|
||||
template<class T, class... Args> |
|
||||
struct node_s { |
|
||||
typedef T dT; |
|
||||
node_s *pre; |
|
||||
node_s *nxt; |
|
||||
uint8_t id; |
|
||||
dT d; |
|
||||
node_s() : pre(NULL), nxt(NULL), d() {} |
|
||||
node_s(Args... args) : id(0), pre(NULL), nxt(NULL), d(args...) {} |
|
||||
}; |
|
||||
|
|
||||
template<int MAX_NUM, class T, class... Args> |
|
||||
class llist { |
|
||||
typedef node_s<T, Args...> elmType; |
|
||||
typedef T dataType; |
|
||||
public: |
|
||||
llist() : root(mPool) { |
|
||||
root = NULL; |
|
||||
elmType *p = mPool; |
|
||||
for(uint32_t i = 0; i < MAX_NUM; i++) { |
|
||||
p->id = i; |
|
||||
p++; |
|
||||
} |
|
||||
mFill = mMax = 0; |
|
||||
} |
|
||||
|
|
||||
elmType *add(Args... args) { |
|
||||
elmType *p = root, *t; |
|
||||
if(NULL == (t = getFreeNode())) |
|
||||
return NULL; |
|
||||
if(++mFill > mMax) |
|
||||
mMax = mFill; |
|
||||
|
|
||||
if(NULL == root) { |
|
||||
p = root = t; |
|
||||
p->pre = p; |
|
||||
p->nxt = p; |
|
||||
} |
|
||||
else { |
|
||||
p = root->pre; |
|
||||
t->pre = p; |
|
||||
p->nxt->pre = t; |
|
||||
t->nxt = p->nxt; |
|
||||
p->nxt = t; |
|
||||
} |
|
||||
t->d = dataType(args...); |
|
||||
return p; |
|
||||
} |
|
||||
|
|
||||
elmType *getFront() { |
|
||||
return root; |
|
||||
} |
|
||||
|
|
||||
elmType *get(elmType *p) { |
|
||||
p = p->nxt; |
|
||||
return (p == root) ? NULL : p; |
|
||||
} |
|
||||
|
|
||||
elmType *rem(elmType *p) { |
|
||||
if(NULL == p) |
|
||||
return NULL; |
|
||||
elmType *t = p->nxt; |
|
||||
p->nxt->pre = p->pre; |
|
||||
p->pre->nxt = p->nxt; |
|
||||
if((root == p) && (p->nxt == p)) |
|
||||
root = NULL; |
|
||||
else |
|
||||
root = p->nxt; |
|
||||
p->nxt = NULL; |
|
||||
p->pre = NULL; |
|
||||
p = NULL; |
|
||||
mFill--; |
|
||||
return (NULL == root) ? NULL : ((t == root) ? NULL : t); |
|
||||
} |
|
||||
|
|
||||
uint16_t getFill(void) { |
|
||||
return mFill; |
|
||||
} |
|
||||
|
|
||||
uint16_t getMaxFill(void) { |
|
||||
return mMax; |
|
||||
} |
|
||||
|
|
||||
protected: |
|
||||
elmType *root; |
|
||||
|
|
||||
private: |
|
||||
elmType *getFreeNode(void) { |
|
||||
elmType *n = mPool; |
|
||||
for(uint32_t i = 0; i < MAX_NUM; i++) { |
|
||||
if(NULL == n->nxt) |
|
||||
return n; |
|
||||
n++; |
|
||||
} |
|
||||
return NULL; |
|
||||
} |
|
||||
|
|
||||
elmType mPool[MAX_NUM]; |
|
||||
uint16_t mFill, mMax; |
|
||||
}; |
|
||||
|
|
||||
#endif /*__LIST_H__*/ |
|
Loading…
Reference in new issue