mirror of https://github.com/lumapu/ahoy.git
				
				
			
				 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